![Russell King](/assets/img/avatar_default.png)
OMAP1_IO_ADDRESS(), OMAP2_IO_ADDRESS() and IO_ADDRESS() returns cookies for use with __raw_{read|write}* for accessing registers. Therefore, these macros should return (void __iomem *) cookies, not integer values. Doing this improves typechecking, and means we can find those places where, eg, DMA controllers are incorrectly given virtual addresses to DMA to, or physical addresses are thrown through a virtual to physical address translation. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
181 lines
4.1 KiB
C
181 lines
4.1 KiB
C
/*
|
|
* arch/arm/mach-omap2/serial.c
|
|
*
|
|
* OMAP2 serial support.
|
|
*
|
|
* Copyright (C) 2005 Nokia Corporation
|
|
* Author: Paul Mundt <paul.mundt@nokia.com>
|
|
*
|
|
* Based off of arch/arm/mach-omap/omap1/serial.c
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/serial_8250.h>
|
|
#include <linux/serial_reg.h>
|
|
#include <linux/clk.h>
|
|
|
|
#include <asm/io.h>
|
|
|
|
#include <mach/common.h>
|
|
#include <mach/board.h>
|
|
|
|
static struct clk * uart1_ick = NULL;
|
|
static struct clk * uart1_fck = NULL;
|
|
static struct clk * uart2_ick = NULL;
|
|
static struct clk * uart2_fck = NULL;
|
|
static struct clk * uart3_ick = NULL;
|
|
static struct clk * uart3_fck = NULL;
|
|
|
|
static struct plat_serial8250_port serial_platform_data[] = {
|
|
{
|
|
.membase = IO_ADDRESS(OMAP_UART1_BASE),
|
|
.mapbase = OMAP_UART1_BASE,
|
|
.irq = 72,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
}, {
|
|
.membase = IO_ADDRESS(OMAP_UART2_BASE),
|
|
.mapbase = OMAP_UART2_BASE,
|
|
.irq = 73,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
}, {
|
|
.membase = IO_ADDRESS(OMAP_UART3_BASE),
|
|
.mapbase = OMAP_UART3_BASE,
|
|
.irq = 74,
|
|
.flags = UPF_BOOT_AUTOCONF,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 2,
|
|
.uartclk = OMAP16XX_BASE_BAUD * 16,
|
|
}, {
|
|
.flags = 0
|
|
}
|
|
};
|
|
|
|
static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
|
|
int offset)
|
|
{
|
|
offset <<= up->regshift;
|
|
return (unsigned int)__raw_readb(up->membase + offset);
|
|
}
|
|
|
|
static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
|
|
int value)
|
|
{
|
|
offset <<= p->regshift;
|
|
__raw_writeb(value, p->membase + offset);
|
|
}
|
|
|
|
/*
|
|
* Internal UARTs need to be initialized for the 8250 autoconfig to work
|
|
* properly. Note that the TX watermark initialization may not be needed
|
|
* once the 8250.c watermark handling code is merged.
|
|
*/
|
|
static inline void __init omap_serial_reset(struct plat_serial8250_port *p)
|
|
{
|
|
serial_write_reg(p, UART_OMAP_MDR1, 0x07);
|
|
serial_write_reg(p, UART_OMAP_SCR, 0x08);
|
|
serial_write_reg(p, UART_OMAP_MDR1, 0x00);
|
|
serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
|
|
}
|
|
|
|
void __init omap_serial_init()
|
|
{
|
|
int i;
|
|
const struct omap_uart_config *info;
|
|
|
|
/*
|
|
* Make sure the serial ports are muxed on at this point.
|
|
* You have to mux them off in device drivers later on
|
|
* if not needed.
|
|
*/
|
|
|
|
info = omap_get_config(OMAP_TAG_UART,
|
|
struct omap_uart_config);
|
|
|
|
if (info == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
|
|
struct plat_serial8250_port *p = serial_platform_data + i;
|
|
|
|
if (!(info->enabled_uarts & (1 << i))) {
|
|
p->membase = 0;
|
|
p->mapbase = 0;
|
|
continue;
|
|
}
|
|
|
|
switch (i) {
|
|
case 0:
|
|
uart1_ick = clk_get(NULL, "uart1_ick");
|
|
if (IS_ERR(uart1_ick))
|
|
printk("Could not get uart1_ick\n");
|
|
else {
|
|
clk_enable(uart1_ick);
|
|
}
|
|
|
|
uart1_fck = clk_get(NULL, "uart1_fck");
|
|
if (IS_ERR(uart1_fck))
|
|
printk("Could not get uart1_fck\n");
|
|
else {
|
|
clk_enable(uart1_fck);
|
|
}
|
|
break;
|
|
case 1:
|
|
uart2_ick = clk_get(NULL, "uart2_ick");
|
|
if (IS_ERR(uart2_ick))
|
|
printk("Could not get uart2_ick\n");
|
|
else {
|
|
clk_enable(uart2_ick);
|
|
}
|
|
|
|
uart2_fck = clk_get(NULL, "uart2_fck");
|
|
if (IS_ERR(uart2_fck))
|
|
printk("Could not get uart2_fck\n");
|
|
else {
|
|
clk_enable(uart2_fck);
|
|
}
|
|
break;
|
|
case 2:
|
|
uart3_ick = clk_get(NULL, "uart3_ick");
|
|
if (IS_ERR(uart3_ick))
|
|
printk("Could not get uart3_ick\n");
|
|
else {
|
|
clk_enable(uart3_ick);
|
|
}
|
|
|
|
uart3_fck = clk_get(NULL, "uart3_fck");
|
|
if (IS_ERR(uart3_fck))
|
|
printk("Could not get uart3_fck\n");
|
|
else {
|
|
clk_enable(uart3_fck);
|
|
}
|
|
break;
|
|
}
|
|
|
|
omap_serial_reset(p);
|
|
}
|
|
}
|
|
|
|
static struct platform_device serial_device = {
|
|
.name = "serial8250",
|
|
.id = PLAT8250_DEV_PLATFORM,
|
|
.dev = {
|
|
.platform_data = serial_platform_data,
|
|
},
|
|
};
|
|
|
|
static int __init omap_init(void)
|
|
{
|
|
return platform_device_register(&serial_device);
|
|
}
|
|
arch_initcall(omap_init);
|