/* * arch/arm/mach-omap2/serial.c * * OMAP2 serial support. * * Copyright (C) 2005 Nokia Corporation * Author: Paul Mundt * * 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 #include #include #include #include #include #include #include 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 = (char *)IO_ADDRESS(OMAP_UART1_BASE), .mapbase = (unsigned long)OMAP_UART1_BASE, .irq = 72, .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = OMAP16XX_BASE_BAUD * 16, }, { .membase = (char *)IO_ADDRESS(OMAP_UART2_BASE), .mapbase = (unsigned long)OMAP_UART2_BASE, .irq = 73, .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = OMAP16XX_BASE_BAUD * 16, }, { .membase = (char *)IO_ADDRESS(OMAP_UART3_BASE), .mapbase = (unsigned long)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, (unsigned long)(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, 0x01); } 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);