diff options
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 947 |
1 files changed, 285 insertions, 662 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 1ac361b..76b9cfb 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -19,26 +19,20 @@ */ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/serial_reg.h> #include <linux/clk.h> #include <linux/io.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/serial_8250.h> #include <linux/pm_runtime.h> -#include <linux/console.h> -#ifdef CONFIG_SERIAL_OMAP #include <plat/omap-serial.h> -#endif - #include <plat/common.h> #include <plat/board.h> #include <plat/clock.h> #include <plat/dma.h> -#include <plat/omap_hwmod.h> #include <plat/omap_device.h> +#include <plat/omap-pm.h> #include "prm2xxx_3xxx.h" #include "pm.h" @@ -47,65 +41,19 @@ #include "control.h" #include "mux.h" -#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 -#define UART_OMAP_WER 0x17 /* Wake-up enable register */ - -#define UART_ERRATA_FIFO_FULL_ABORT (0x1 << 0) -#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1) - -/* - * NOTE: By default the serial timeout is disabled as it causes lost characters - * over the serial ports. This means that the UART clocks will stay on until - * disabled via sysfs. This also causes that any deeper omap sleep states are - * blocked. - */ -#define DEFAULT_TIMEOUT 0 - #define MAX_UART_HWMOD_NAME_LEN 16 -struct omap_uart_state { - int num; - int can_sleep; - struct timer_list timer; - u32 timeout; - - void __iomem *wk_st; - void __iomem *wk_en; - u32 wk_mask; - u32 padconf; - u32 dma_enabled; - - struct clk *ick; - struct clk *fck; - int clocked; - - int irq; - int regshift; - int irqflags; - void __iomem *membase; - resource_size_t mapbase; - - struct list_head node; - struct omap_hwmod *oh; - struct platform_device *pdev; - - u32 errata; -#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) - int context_valid; - - /* Registers to be saved/restored for OFF-mode */ - u16 dll; - u16 dlh; - u16 ier; - u16 sysc; - u16 scr; - u16 wer; - u16 mcr; -#endif -}; +static int omap_uart_con_id __initdata = -1; -static LIST_HEAD(uart_list); -static u8 num_uarts; +static struct omap_uart_port_info omap_serial_default_info[] = { + { + .use_dma = 0, + .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE, + .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, + .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT, + .auto_sus_timeout = DEFAULT_AUTOSUSPEND_DELAY, + }, +}; static int uart_idle_hwmod(struct omap_device *od) { @@ -129,396 +77,203 @@ static struct omap_device_pm_latency omap_uart_latency[] = { }, }; -static inline unsigned int __serial_read_reg(struct uart_port *up, - int offset) -{ - offset <<= up->regshift; - return (unsigned int)__raw_readb(up->membase + offset); -} - -static inline unsigned int serial_read_reg(struct omap_uart_state *uart, - int offset) -{ - offset <<= uart->regshift; - return (unsigned int)__raw_readb(uart->membase + offset); -} - -static inline void __serial_write_reg(struct uart_port *up, int offset, - int value) -{ - offset <<= up->regshift; - __raw_writeb(value, up->membase + offset); -} - -static inline void serial_write_reg(struct omap_uart_state *uart, int offset, - int value) -{ - offset <<= uart->regshift; - __raw_writeb(value, uart->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_uart_reset(struct omap_uart_state *uart) -{ - serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); - serial_write_reg(uart, UART_OMAP_SCR, 0x08); - serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); -} - -#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) - -/* - * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6) - * The access to uart register after MDR1 Access - * causes UART to corrupt data. - * - * Need a delay = - * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) - * give 10 times as much - */ -static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val, - u8 fcr_val) -{ - u8 timeout = 255; - - serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val); - udelay(2); - serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT | - UART_FCR_CLEAR_RCVR); - /* - * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and - * TX_FIFO_E bit is 1. - */ - while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) & - (UART_LSR_THRE | UART_LSR_DR))) { - timeout--; - if (!timeout) { - /* Should *never* happen. we warn and carry on */ - dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n", - serial_read_reg(uart, UART_LSR)); - break; - } - udelay(1); - } -} - -static void omap_uart_save_context(struct omap_uart_state *uart) -{ - u16 lcr = 0; - - if (!enable_off_mode) - return; - - lcr = serial_read_reg(uart, UART_LCR); - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); - uart->dll = serial_read_reg(uart, UART_DLL); - uart->dlh = serial_read_reg(uart, UART_DLM); - serial_write_reg(uart, UART_LCR, lcr); - uart->ier = serial_read_reg(uart, UART_IER); - uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); - uart->scr = serial_read_reg(uart, UART_OMAP_SCR); - uart->wer = serial_read_reg(uart, UART_OMAP_WER); - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A); - uart->mcr = serial_read_reg(uart, UART_MCR); - serial_write_reg(uart, UART_LCR, lcr); - - uart->context_valid = 1; -} - -static void omap_uart_restore_context(struct omap_uart_state *uart) -{ - u16 efr = 0; +#ifdef CONFIG_OMAP_MUX +static struct omap_device_pad default_uart1_pads[] __initdata = { + { + .name = "uart1_cts.uart1_cts", + .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + }, + { + .name = "uart1_rts.uart1_rts", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart1_tx.uart1_tx", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart1_rx.uart1_rx", + .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + }, +}; - if (!enable_off_mode) - return; +static struct omap_device_pad default_uart2_pads[] __initdata = { + { + .name = "uart2_cts.uart2_cts", + .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + }, + { + .name = "uart2_rts.uart2_rts", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart2_tx.uart2_tx", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart2_rx.uart2_rx", + .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + }, +}; - if (!uart->context_valid) - return; +static struct omap_device_pad default_uart3_pads[] __initdata = { + { + .name = "uart3_cts_rctx.uart3_cts_rctx", + .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, + }, + { + .name = "uart3_rts_sd.uart3_rts_sd", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart3_tx_irtx.uart3_tx_irtx", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart3_rx_irrx.uart3_rx_irrx", + .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + }, +}; - uart->context_valid = 0; +static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = { + { + .name = "gpmc_wait2.uart4_tx", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "gpmc_wait3.uart4_rx", + .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2, + .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2, + }, +}; - if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) - omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0); - else - serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); - - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); - efr = serial_read_reg(uart, UART_EFR); - serial_write_reg(uart, UART_EFR, UART_EFR_ECB); - serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ - serial_write_reg(uart, UART_IER, 0x0); - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); - serial_write_reg(uart, UART_DLL, uart->dll); - serial_write_reg(uart, UART_DLM, uart->dlh); - serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ - serial_write_reg(uart, UART_IER, uart->ier); - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A); - serial_write_reg(uart, UART_MCR, uart->mcr); - serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); - serial_write_reg(uart, UART_EFR, efr); - serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); - serial_write_reg(uart, UART_OMAP_SCR, uart->scr); - serial_write_reg(uart, UART_OMAP_WER, uart->wer); - serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); - - if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) - omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1); - else - /* UART 16x mode */ - serial_write_reg(uart, UART_OMAP_MDR1, - UART_OMAP_MDR1_16X_MODE); -} +static struct omap_device_pad default_omap4_uart4_pads[] __initdata = { + { + .name = "uart4_tx.uart4_tx", + .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, + }, + { + .name = "uart4_rx.uart4_rx", + .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, + .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, + }, +}; #else -static inline void omap_uart_save_context(struct omap_uart_state *uart) {} -static inline void omap_uart_restore_context(struct omap_uart_state *uart) {} -#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */ - -static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) -{ - if (uart->clocked) - return; - - omap_device_enable(uart->pdev); - uart->clocked = 1; - omap_uart_restore_context(uart); -} - -#ifdef CONFIG_PM - -static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) -{ - if (!uart->clocked) - return; - - omap_uart_save_context(uart); - uart->clocked = 0; - omap_device_idle(uart->pdev); -} - -static void omap_uart_enable_wakeup(struct omap_uart_state *uart) -{ - /* Set wake-enable bit */ - if (uart->wk_en && uart->wk_mask) { - u32 v = __raw_readl(uart->wk_en); - v |= uart->wk_mask; - __raw_writel(v, uart->wk_en); - } - - /* Ensure IOPAD wake-enables are set */ - if (cpu_is_omap34xx() && uart->padconf) { - u16 v = omap_ctrl_readw(uart->padconf); - v |= OMAP3_PADCONF_WAKEUPENABLE0; - omap_ctrl_writew(v, uart->padconf); - } -} - -static void omap_uart_disable_wakeup(struct omap_uart_state *uart) -{ - /* Clear wake-enable bit */ - if (uart->wk_en && uart->wk_mask) { - u32 v = __raw_readl(uart->wk_en); - v &= ~uart->wk_mask; - __raw_writel(v, uart->wk_en); - } - - /* Ensure IOPAD wake-enables are cleared */ - if (cpu_is_omap34xx() && uart->padconf) { - u16 v = omap_ctrl_readw(uart->padconf); - v &= ~OMAP3_PADCONF_WAKEUPENABLE0; - omap_ctrl_writew(v, uart->padconf); - } -} - -static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, - int enable) -{ - u8 idlemode; - - if (enable) { - /** - * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests - * in Smartidle Mode When Configured for DMA Operations. - */ - if (uart->dma_enabled) - idlemode = HWMOD_IDLEMODE_FORCE; - else - idlemode = HWMOD_IDLEMODE_SMART; - } else { - idlemode = HWMOD_IDLEMODE_NO; - } - - omap_hwmod_set_slave_idlemode(uart->oh, idlemode); -} - -static void omap_uart_block_sleep(struct omap_uart_state *uart) -{ - omap_uart_enable_clocks(uart); - - omap_uart_smart_idle_enable(uart, 0); - uart->can_sleep = 0; - if (uart->timeout) - mod_timer(&uart->timer, jiffies + uart->timeout); - else - del_timer(&uart->timer); -} - -static void omap_uart_allow_sleep(struct omap_uart_state *uart) -{ - if (device_may_wakeup(&uart->pdev->dev)) - omap_uart_enable_wakeup(uart); - else - omap_uart_disable_wakeup(uart); - - if (!uart->clocked) - return; - - omap_uart_smart_idle_enable(uart, 1); - uart->can_sleep = 1; - del_timer(&uart->timer); -} - -static void omap_uart_idle_timer(unsigned long data) -{ - struct omap_uart_state *uart = (struct omap_uart_state *)data; - - omap_uart_allow_sleep(uart); -} - -void omap_uart_prepare_idle(int num) -{ - struct omap_uart_state *uart; - - list_for_each_entry(uart, &uart_list, node) { - if (num == uart->num && uart->can_sleep) { - omap_uart_disable_clocks(uart); - return; - } - } -} - -void omap_uart_resume_idle(int num) -{ - struct omap_uart_state *uart; - - list_for_each_entry(uart, &uart_list, node) { - if (num == uart->num && uart->can_sleep) { - omap_uart_enable_clocks(uart); - - /* Check for IO pad wakeup */ - if (cpu_is_omap34xx() && uart->padconf) { - u16 p = omap_ctrl_readw(uart->padconf); - - if (p & OMAP3_PADCONF_WAKEUPEVENT0) - omap_uart_block_sleep(uart); - } +static struct omap_device_pad default_uart1_pads[] __initdata = {}; +static struct omap_device_pad default_uart2_pads[] __initdata = {}; +static struct omap_device_pad default_uart3_pads[] __initdata = {}; +static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {}; +static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {}; +#endif - /* Check for normal UART wakeup */ - if (__raw_readl(uart->wk_st) & uart->wk_mask) - omap_uart_block_sleep(uart); - return; +static __init void omap_serial_fill_default_pads(struct omap_board_data *bdata) +{ + BUG_ON(!cpu_is_omap44xx() && !cpu_is_omap34xx()); + + switch (bdata->id) { + case 0: + bdata->pads = default_uart1_pads; + bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads); + break; + case 1: + bdata->pads = default_uart2_pads; + bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads); + break; + case 2: + bdata->pads = default_uart3_pads; + bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads); + break; + case 3: + if (cpu_is_omap44xx()) { + bdata->pads = default_omap4_uart4_pads; + bdata->pads_cnt = + ARRAY_SIZE(default_omap4_uart4_pads); + } else { + bdata->pads = default_omap36xx_uart4_pads; + bdata->pads_cnt = + ARRAY_SIZE(default_omap36xx_uart4_pads); } + break; + default: + break; } } -void omap_uart_prepare_suspend(void) -{ - struct omap_uart_state *uart; - - list_for_each_entry(uart, &uart_list, node) { - omap_uart_allow_sleep(uart); - } -} - -int omap_uart_can_sleep(void) +/* TBD: Will be removed once we have irq-chaing mechanism */ +static bool omap_uart_chk_wakeup(struct platform_device *pdev) { - struct omap_uart_state *uart; - int can_sleep = 1; - - list_for_each_entry(uart, &uart_list, node) { - if (!uart->clocked) - continue; - - if (!uart->can_sleep) { - can_sleep = 0; - continue; + struct omap_uart_port_info *up = pdev->dev.platform_data; + struct omap_device *od; + u32 wkst = 0; + bool ret = false; + + od = to_omap_device(pdev); + if (omap_hwmod_pad_get_wakeup_status(od->hwmods[0])) + ret = true; + + if (up->wk_st && up->wk_en && up->wk_mask) { + /* Check for normal UART wakeup (and clear it) */ + wkst = __raw_readl(up->wk_st) & up->wk_mask; + if (wkst) { + __raw_writel(wkst, up->wk_st); + ret = true; } - - /* This UART can now safely sleep. */ - omap_uart_allow_sleep(uart); } - return can_sleep; + return ret; } -/** - * omap_uart_interrupt() - * - * This handler is used only to detect that *any* UART interrupt has - * occurred. It does _nothing_ to handle the interrupt. Rather, - * any UART interrupt will trigger the inactivity timer so the - * UART will not idle or sleep for its timeout period. - * - **/ -/* static int first_interrupt; */ -static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) +static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable) { - struct omap_uart_state *uart = dev_id; - - omap_uart_block_sleep(uart); + struct omap_device *od; - return IRQ_NONE; + od = to_omap_device(pdev); + if (enable) + omap_hwmod_enable_wakeup(od->hwmods[0]); + else + omap_hwmod_disable_wakeup(od->hwmods[0]); } -static void omap_uart_idle_init(struct omap_uart_state *uart) +static void omap_uart_idle_init(struct omap_uart_port_info *uart, + unsigned short num) { - int ret; - - uart->can_sleep = 0; - uart->timeout = DEFAULT_TIMEOUT; - setup_timer(&uart->timer, omap_uart_idle_timer, - (unsigned long) uart); - if (uart->timeout) - mod_timer(&uart->timer, jiffies + uart->timeout); - omap_uart_smart_idle_enable(uart, 0); - - if (cpu_is_omap34xx() && !cpu_is_ti816x()) { - u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD; + if (cpu_is_omap44xx()) { + uart->wer |= OMAP4_UART_WER_MOD_WKUP; + } else if (cpu_is_omap34xx()) { + u32 mod = num > 1 ? OMAP3430_PER_MOD : CORE_MOD; u32 wk_mask = 0; - u32 padconf = 0; - /* XXX These PRM accesses do not belong here */ + uart->wer |= OMAP2_UART_WER_MOD_WKUP; uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); - switch (uart->num) { + switch (num) { case 0: wk_mask = OMAP3430_ST_UART1_MASK; - padconf = 0x182; break; case 1: wk_mask = OMAP3430_ST_UART2_MASK; - padconf = 0x17a; break; case 2: wk_mask = OMAP3430_ST_UART3_MASK; - padconf = 0x19e; break; case 3: wk_mask = OMAP3630_ST_UART4_MASK; - padconf = 0x0d2; break; } uart->wk_mask = wk_mask; - uart->padconf = padconf; } else if (cpu_is_omap24xx()) { u32 wk_mask = 0; u32 wk_en = PM_WKEN1, wk_st = PM_WKST1; - switch (uart->num) { + switch (num) { case 0: wk_mask = OMAP24XX_ST_UART1_MASK; break; @@ -543,162 +298,87 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) uart->wk_en = NULL; uart->wk_st = NULL; uart->wk_mask = 0; - uart->padconf = 0; - } - - uart->irqflags |= IRQF_SHARED; - ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt, - IRQF_SHARED, "serial idle", (void *)uart); - WARN_ON(ret); -} - -void omap_uart_enable_irqs(int enable) -{ - int ret; - struct omap_uart_state *uart; - - list_for_each_entry(uart, &uart_list, node) { - if (enable) { - pm_runtime_put_sync(&uart->pdev->dev); - ret = request_threaded_irq(uart->irq, NULL, - omap_uart_interrupt, - IRQF_SHARED, - "serial idle", - (void *)uart); - } else { - pm_runtime_get_noresume(&uart->pdev->dev); - free_irq(uart->irq, (void *)uart); - } } } -static ssize_t sleep_timeout_show(struct device *dev, - struct device_attribute *attr, - char *buf) +char *cmdline_find_option(char *str) { - struct platform_device *pdev = to_platform_device(dev); - struct omap_device *odev = to_omap_device(pdev); - struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; + extern char *saved_command_line; - return sprintf(buf, "%u\n", uart->timeout / HZ); + return strstr(saved_command_line, str); } -static ssize_t sleep_timeout_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t n) +struct omap_hwmod *omap_uart_hwmod_lookup(int num) { - struct platform_device *pdev = to_platform_device(dev); - struct omap_device *odev = to_omap_device(pdev); - struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; - unsigned int value; - - if (sscanf(buf, "%u", &value) != 1) { - dev_err(dev, "sleep_timeout_store: Invalid value\n"); - return -EINVAL; - } - - uart->timeout = value * HZ; - if (uart->timeout) - mod_timer(&uart->timer, jiffies + uart->timeout); - else - /* A zero value means disable timeout feature */ - omap_uart_block_sleep(uart); - - return n; -} + struct omap_hwmod *oh; + char oh_name[MAX_UART_HWMOD_NAME_LEN]; -static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, - sleep_timeout_store); -#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) -#else -static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} -static void omap_uart_block_sleep(struct omap_uart_state *uart) -{ - /* Needed to enable UART clocks when built without CONFIG_PM */ - omap_uart_enable_clocks(uart); + snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1); + oh = omap_hwmod_lookup(oh_name); + WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n", + oh_name); + return oh; } -#define DEV_CREATE_FILE(dev, attr) -#endif /* CONFIG_PM */ -#ifndef CONFIG_SERIAL_OMAP -/* - * Override the default 8250 read handler: mem_serial_in() - * Empty RX fifo read causes an abort on omap3630 and omap4 - * This function makes sure that an empty rx fifo is not read on these silicons - * (OMAP1/2/3430 are not affected) - */ -static unsigned int serial_in_override(struct uart_port *up, int offset) +void omap_rts_mux_write(u16 val, int num) { - if (UART_RX == offset) { - unsigned int lsr; - lsr = __serial_read_reg(up, UART_LSR); - if (!(lsr & UART_LSR_DR)) - return -EPERM; - } - - return __serial_read_reg(up, offset); -} + struct omap_hwmod *oh; + int i; -static void serial_out_override(struct uart_port *up, int offset, int value) -{ - unsigned int status, tmout = 10000; + oh = omap_uart_hwmod_lookup(num); + if (!oh) + return; - status = __serial_read_reg(up, UART_LSR); - while (!(status & UART_LSR_THRE)) { - /* Wait up to 10ms for the character(s) to be sent. */ - if (--tmout == 0) + for (i = 0; i < oh->mux->nr_pads ; i++) { + if (strstr(oh->mux->pads[i].name, "rts")) { + omap_mux_write(oh->mux->pads[i].partition, + val, + oh->mux->pads[i].mux[0].reg_offset); break; - udelay(1); - status = __serial_read_reg(up, UART_LSR); + } } - __serial_write_reg(up, offset, value); } -#endif static int __init omap_serial_early_init(void) { int i = 0; + char omap_tty_name[MAX_UART_HWMOD_NAME_LEN]; + struct omap_hwmod *oh; - do { - char oh_name[MAX_UART_HWMOD_NAME_LEN]; - struct omap_hwmod *oh; - struct omap_uart_state *uart; - - snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, - "uart%d", i + 1); - oh = omap_hwmod_lookup(oh_name); - if (!oh) - break; - - uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL); - if (WARN_ON(!uart)) - return -ENODEV; + for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) { + snprintf(omap_tty_name, MAX_UART_HWMOD_NAME_LEN, + "%s%d", OMAP_SERIAL_NAME, i); + if (cmdline_find_option(omap_tty_name)) { + omap_uart_con_id = i; + oh = omap_uart_hwmod_lookup(i); + oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; + return 0; + } + } + return 0; +} +core_initcall(omap_serial_early_init); - uart->oh = oh; - uart->num = i++; - list_add_tail(&uart->node, &uart_list); - num_uarts++; +void __init omap_serial_init_port_pads(int id, struct omap_device_pad *pads, + int size, struct omap_uart_port_info *info) +{ + struct omap_board_data bdata; - /* - * NOTE: omap_hwmod_setup*() has not yet been called, - * so no hwmod functions will work yet. - */ + bdata.id = id; + bdata.flags = 0; + bdata.pads = pads; + bdata.pads_cnt = size; - /* - * During UART early init, device need to be probed - * to determine SoC specific init before omap_device - * is ready. Therefore, don't allow idle here - */ - uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; - } while (1); + if (!bdata.pads) + omap_serial_fill_default_pads(&bdata); - return 0; + omap_serial_init_port(&bdata, info); } -core_initcall(omap_serial_early_init); /** * omap_serial_init_port() - initialize single serial port * @bdata: port specific board data pointer + * @info: platform specific data pointer * * This function initialies serial driver for given port only. * Platforms can call this function instead of omap_serial_init() @@ -707,171 +387,114 @@ core_initcall(omap_serial_early_init); * Don't mix calls to omap_serial_init_port() and omap_serial_init(), * use only one of the two. */ -void __init omap_serial_init_port(struct omap_board_data *bdata) +void __init omap_serial_init_port(struct omap_board_data *bdata, + struct omap_uart_port_info *info) { - struct omap_uart_state *uart; struct omap_hwmod *oh; struct omap_device *od; - void *pdata = NULL; - u32 pdata_size = 0; - char *name; -#ifndef CONFIG_SERIAL_OMAP - struct plat_serial8250_port ports[2] = { - {}, - {.flags = 0}, - }; - struct plat_serial8250_port *p = &ports[0]; -#else - struct omap_uart_port_info omap_up; -#endif + struct omap_uart_port_info *pdata; + char *name = DRIVER_NAME; if (WARN_ON(!bdata)) return; if (WARN_ON(bdata->id < 0)) return; - if (WARN_ON(bdata->id >= num_uarts)) + if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS)) return; - list_for_each_entry(uart, &uart_list, node) - if (bdata->id == uart->num) - break; - - oh = uart->oh; - uart->dma_enabled = 0; -#ifndef CONFIG_SERIAL_OMAP - name = "serial8250"; - - /* - * !! 8250 driver does not use standard IORESOURCE* It - * has it's own custom pdata that can be taken from - * the hwmod resource data. But, this needs to be - * done after the build. - * - * ?? does it have to be done before the register ?? - * YES, because platform_device_data_add() copies - * pdata, it does not use a pointer. - */ - p->flags = UPF_BOOT_AUTOCONF; - p->iotype = UPIO_MEM; - p->regshift = 2; - p->uartclk = OMAP24XX_BASE_BAUD * 16; - p->irq = oh->mpu_irqs[0].irq; - p->mapbase = oh->slaves[0]->addr->pa_start; - p->membase = omap_hwmod_get_mpu_rt_va(oh); - p->irqflags = IRQF_SHARED; - p->private_data = uart; - - /* - * omap44xx, ti816x: Never read empty UART fifo - * omap3xxx: Never read empty UART fifo on UARTs - * with IP rev >=0x52 - */ - uart->regshift = p->regshift; - uart->membase = p->membase; - if (cpu_is_omap44xx() || cpu_is_ti816x()) - uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; - else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF) - >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) - uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; - - if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) { - p->serial_in = serial_in_override; - p->serial_out = serial_out_override; - } - - pdata = &ports[0]; - pdata_size = 2 * sizeof(struct plat_serial8250_port); -#else + oh = omap_uart_hwmod_lookup(bdata->id); + if (!oh) + return; - name = DRIVER_NAME; + if (info == NULL) + info = omap_serial_default_info; - omap_up.dma_enabled = uart->dma_enabled; - omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; - omap_up.mapbase = oh->slaves[0]->addr->pa_start; - omap_up.membase = omap_hwmod_get_mpu_rt_va(oh); - omap_up.irqflags = IRQF_SHARED; - omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + pr_err("Memory allocation for UART pdata failed\n"); + return; + } - pdata = &omap_up; - pdata_size = sizeof(struct omap_uart_port_info); + if (cpu_is_omap34xx() || cpu_is_omap44xx()) + pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS; + + omap_uart_idle_init(pdata, bdata->id); + + pdata->uartclk = OMAP24XX_BASE_BAUD * 16; + pdata->flags = UPF_BOOT_AUTOCONF; + pdata->enable_wakeup = omap_uart_wakeup_enable; + pdata->use_dma = info->use_dma; + pdata->chk_wakeup = omap_uart_chk_wakeup; + pdata->dma_rx_buf_size = info->dma_rx_buf_size; + pdata->dma_rx_poll_rate = info->dma_rx_poll_rate; + pdata->dma_rx_timeout = info->dma_rx_timeout; + pdata->auto_sus_timeout = info->auto_sus_timeout; + pdata->wake_peer = info->wake_peer; + pdata->rts_mux_driver_control = info->rts_mux_driver_control; + if (bdata->id == omap_uart_con_id) { + pdata->console_uart = true; +#ifdef CONFIG_DEBUG_LL + pdata->auto_sus_timeout = -1; #endif + } - if (WARN_ON(!oh)) - return; + if (pdata->use_dma && + cpu_is_omap44xx() && omap_rev() > OMAP4430_REV_ES1_0) + pdata->errata |= OMAP4_UART_ERRATA_i659_TX_THR; - od = omap_device_build(name, uart->num, oh, pdata, pdata_size, - omap_uart_latency, - ARRAY_SIZE(omap_uart_latency), false); + od = omap_device_build(name, bdata->id, oh, pdata, + sizeof(*pdata), omap_uart_latency, + ARRAY_SIZE(omap_uart_latency), false); WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", name, oh->name); oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); - uart->irq = oh->mpu_irqs[0].irq; - uart->regshift = 2; - uart->mapbase = oh->slaves[0]->addr->pa_start; - uart->membase = omap_hwmod_get_mpu_rt_va(oh); - uart->pdev = &od->pdev; - - oh->dev_attr = uart; - - console_lock(); /* in case the earlycon is on the UART */ - - /* - * Because of early UART probing, UART did not get idled - * on init. Now that omap_device is ready, ensure full idle - * before doing omap_device_enable(). - */ - omap_hwmod_idle(uart->oh); - - omap_device_enable(uart->pdev); - omap_uart_idle_init(uart); - omap_uart_reset(uart); - omap_hwmod_enable_wakeup(uart->oh); - omap_device_idle(uart->pdev); - - /* - * Need to block sleep long enough for interrupt driven - * driver to start. Console driver is in polling mode - * so device needs to be kept enabled while polling driver - * is in use. - */ - if (uart->timeout) - uart->timeout = (30 * HZ); - omap_uart_block_sleep(uart); - uart->timeout = DEFAULT_TIMEOUT; - - console_unlock(); - - if ((cpu_is_omap34xx() && uart->padconf) || - (uart->wk_en && uart->wk_mask)) { + if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) || + (pdata->wk_en && pdata->wk_mask)) { device_init_wakeup(&od->pdev.dev, true); - DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout); } - /* Enable the MDR1 errata for OMAP3 */ - if (cpu_is_omap34xx() && !cpu_is_ti816x()) - uart->errata |= UART_ERRATA_i202_MDR1_ACCESS; + kfree(pdata); } /** - * omap_serial_init() - initialize all supported serial ports + * omap_serial_board_init() - initialize all supported serial ports + * @platform_data: platform specific data pointer * * Initializes all available UARTs as serial ports. Platforms * can call this function when they want to have default behaviour * for serial ports (e.g initialize them all as serial ports). */ -void __init omap_serial_init(void) +void __init omap_serial_board_init(struct omap_uart_port_info *platform_data) { - struct omap_uart_state *uart; struct omap_board_data bdata; + u8 i; - list_for_each_entry(uart, &uart_list, node) { - bdata.id = uart->num; + for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) { + bdata.id = i; bdata.flags = 0; bdata.pads = NULL; bdata.pads_cnt = 0; - omap_serial_init_port(&bdata); + if (cpu_is_omap44xx() || cpu_is_omap34xx()) + omap_serial_fill_default_pads(&bdata); + + if (platform_data == NULL) + omap_serial_init_port(&bdata, NULL); + else + omap_serial_init_port(&bdata, &platform_data[i]); } } + +/** + * omap_serial_init() - initialize all supported serial ports + * + * Initializes all available UARTs. + * Platforms can call this function when they want to have default behaviour + * for serial ports (e.g initialize them all as serial ports). + */ +void __init omap_serial_init(void) +{ + omap_serial_board_init(NULL); +} |