blob: 77feaab78059540fa418c1782ff23c41cf899da7 [file] [log] [blame]
Tony Lindgren1dbae812005-11-10 14:26:51 +00001/*
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02002 * arch/arm/mach-omap2/serial.c
Tony Lindgren1dbae812005-11-10 14:26:51 +00003 *
4 * OMAP2 serial support.
5 *
Jouni Hogander6e811762008-10-06 15:49:15 +03006 * Copyright (C) 2005-2008 Nokia Corporation
Tony Lindgren1dbae812005-11-10 14:26:51 +00007 * Author: Paul Mundt <paul.mundt@nokia.com>
8 *
Kevin Hilman4af40162009-02-04 10:51:40 -08009 * Major rework for PM support by Kevin Hilman
10 *
Tony Lindgren1dbae812005-11-10 14:26:51 +000011 * Based off of arch/arm/mach-omap/omap1/serial.c
12 *
Santosh Shilimkar44169072009-05-28 14:16:04 -070013 * Copyright (C) 2009 Texas Instruments
14 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com
15 *
Tony Lindgren1dbae812005-11-10 14:26:51 +000016 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file "COPYING" in the main directory of this archive
18 * for more details.
19 */
20#include <linux/kernel.h>
21#include <linux/init.h>
Russell Kingf8ce2542006-01-07 16:15:52 +000022#include <linux/clk.h>
Russell Kingfced80c2008-09-06 12:10:45 +010023#include <linux/io.h>
Santosh Shilimkare03d37d2010-02-18 08:59:06 +000024#include <linux/delay.h>
Kevin Hilman6f251e92010-09-27 20:19:38 +053025#include <linux/platform_device.h>
26#include <linux/slab.h>
Kevin Hilman3244fcd2010-09-27 20:19:53 +053027#include <linux/pm_runtime.h>
Paul Walmsley0d8e2d02010-11-24 16:49:05 -070028#include <linux/console.h>
Kevin Hilman6f251e92010-09-27 20:19:38 +053029
Kevin Hilman6f251e92010-09-27 20:19:38 +053030#include <plat/omap-serial.h>
Tony Lindgren4e653312011-11-10 22:45:17 +010031#include "common.h"
Tony Lindgrence491cf2009-10-20 09:40:47 -070032#include <plat/board.h>
Kevin Hilman6f251e92010-09-27 20:19:38 +053033#include <plat/dma.h>
34#include <plat/omap_hwmod.h>
35#include <plat/omap_device.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000036
Paul Walmsley59fb6592010-12-21 15:30:55 -070037#include "prm2xxx_3xxx.h"
Kevin Hilman4af40162009-02-04 10:51:40 -080038#include "pm.h"
Paul Walmsley59fb6592010-12-21 15:30:55 -070039#include "cm2xxx_3xxx.h"
Kevin Hilman4af40162009-02-04 10:51:40 -080040#include "prm-regbits-34xx.h"
Paul Walmsley4814ced2010-10-08 11:40:20 -060041#include "control.h"
Tony Lindgren40e44392010-12-22 18:42:35 -080042#include "mux.h"
Kevin Hilman4af40162009-02-04 10:51:40 -080043
44#define UART_OMAP_WER 0x17 /* Wake-up enable register */
45
Deepak K00034502010-08-02 13:18:12 +030046#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
Nishanth Menon5a927b32010-08-02 13:18:12 +030047
Tony Lindgren301fe8e2010-02-01 12:34:31 -080048/*
49 * NOTE: By default the serial timeout is disabled as it causes lost characters
50 * over the serial ports. This means that the UART clocks will stay on until
51 * disabled via sysfs. This also causes that any deeper omap sleep states are
52 * blocked.
53 */
54#define DEFAULT_TIMEOUT 0
Kevin Hilman4af40162009-02-04 10:51:40 -080055
Kevin Hilman6f251e92010-09-27 20:19:38 +053056#define MAX_UART_HWMOD_NAME_LEN 16
57
Kevin Hilman4af40162009-02-04 10:51:40 -080058struct omap_uart_state {
59 int num;
60 int can_sleep;
Kevin Hilman4af40162009-02-04 10:51:40 -080061
62 void __iomem *wk_st;
63 void __iomem *wk_en;
64 u32 wk_mask;
Kevin Hilman6f251e92010-09-27 20:19:38 +053065 u32 dma_enabled;
Kevin Hilman4af40162009-02-04 10:51:40 -080066
Kevin Hilman4af40162009-02-04 10:51:40 -080067 int clocked;
68
Kevin Hilman6f251e92010-09-27 20:19:38 +053069 int regshift;
Kevin Hilman6f251e92010-09-27 20:19:38 +053070 void __iomem *membase;
71 resource_size_t mapbase;
72
Kevin Hilman4af40162009-02-04 10:51:40 -080073 struct list_head node;
Kevin Hilman6f251e92010-09-27 20:19:38 +053074 struct omap_hwmod *oh;
75 struct platform_device *pdev;
Kevin Hilman4af40162009-02-04 10:51:40 -080076
Nishanth Menon5a927b32010-08-02 13:18:12 +030077 u32 errata;
Kevin Hilman4af40162009-02-04 10:51:40 -080078#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
79 int context_valid;
80
81 /* Registers to be saved/restored for OFF-mode */
82 u16 dll;
83 u16 dlh;
84 u16 ier;
85 u16 sysc;
86 u16 scr;
87 u16 wer;
Govindraj R5ade4ff2010-08-02 13:18:11 +030088 u16 mcr;
Kevin Hilman4af40162009-02-04 10:51:40 -080089#endif
90};
91
Kevin Hilman4af40162009-02-04 10:51:40 -080092static LIST_HEAD(uart_list);
Kevin Hilman6f251e92010-09-27 20:19:38 +053093static u8 num_uarts;
Tony Lindgren1dbae812005-11-10 14:26:51 +000094
Alexander Shishkin92303722010-01-08 10:29:06 -080095static inline unsigned int __serial_read_reg(struct uart_port *up,
Kevin Hilman6f251e92010-09-27 20:19:38 +053096 int offset)
Alexander Shishkin92303722010-01-08 10:29:06 -080097{
98 offset <<= up->regshift;
99 return (unsigned int)__raw_readb(up->membase + offset);
100}
101
Kevin Hilman6f251e92010-09-27 20:19:38 +0530102static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
Tony Lindgren1dbae812005-11-10 14:26:51 +0000103 int offset)
104{
Kevin Hilman6f251e92010-09-27 20:19:38 +0530105 offset <<= uart->regshift;
106 return (unsigned int)__raw_readb(uart->membase + offset);
Tony Lindgren1dbae812005-11-10 14:26:51 +0000107}
108
Santosh Shilimkare03d37d2010-02-18 08:59:06 +0000109static inline void __serial_write_reg(struct uart_port *up, int offset,
110 int value)
111{
112 offset <<= up->regshift;
113 __raw_writeb(value, up->membase + offset);
114}
115
Kevin Hilman6f251e92010-09-27 20:19:38 +0530116static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
Tony Lindgren1dbae812005-11-10 14:26:51 +0000117 int value)
118{
Kevin Hilman6f251e92010-09-27 20:19:38 +0530119 offset <<= uart->regshift;
120 __raw_writeb(value, uart->membase + offset);
Tony Lindgren1dbae812005-11-10 14:26:51 +0000121}
122
123/*
124 * Internal UARTs need to be initialized for the 8250 autoconfig to work
125 * properly. Note that the TX watermark initialization may not be needed
126 * once the 8250.c watermark handling code is merged.
127 */
Kevin Hilman6f251e92010-09-27 20:19:38 +0530128
Kevin Hilman4af40162009-02-04 10:51:40 -0800129static inline void __init omap_uart_reset(struct omap_uart_state *uart)
Tony Lindgren1dbae812005-11-10 14:26:51 +0000130{
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800131 serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530132 serial_write_reg(uart, UART_OMAP_SCR, 0x08);
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800133 serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
Tony Lindgren1dbae812005-11-10 14:26:51 +0000134}
135
Kevin Hilman4af40162009-02-04 10:51:40 -0800136#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
137
Deepak K00034502010-08-02 13:18:12 +0300138/*
139 * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
140 * The access to uart register after MDR1 Access
141 * causes UART to corrupt data.
142 *
143 * Need a delay =
144 * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
145 * give 10 times as much
146 */
147static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
148 u8 fcr_val)
149{
Deepak K00034502010-08-02 13:18:12 +0300150 u8 timeout = 255;
151
Kevin Hilman6f251e92010-09-27 20:19:38 +0530152 serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
Deepak K00034502010-08-02 13:18:12 +0300153 udelay(2);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530154 serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
Deepak K00034502010-08-02 13:18:12 +0300155 UART_FCR_CLEAR_RCVR);
156 /*
157 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
158 * TX_FIFO_E bit is 1.
159 */
Kevin Hilman6f251e92010-09-27 20:19:38 +0530160 while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
Deepak K00034502010-08-02 13:18:12 +0300161 (UART_LSR_THRE | UART_LSR_DR))) {
162 timeout--;
163 if (!timeout) {
164 /* Should *never* happen. we warn and carry on */
Kevin Hilman6f251e92010-09-27 20:19:38 +0530165 dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
166 serial_read_reg(uart, UART_LSR));
Deepak K00034502010-08-02 13:18:12 +0300167 break;
168 }
169 udelay(1);
170 }
171}
172
Kevin Hilman4af40162009-02-04 10:51:40 -0800173static void omap_uart_save_context(struct omap_uart_state *uart)
Jouni Hogander6e811762008-10-06 15:49:15 +0300174{
Kevin Hilman4af40162009-02-04 10:51:40 -0800175 u16 lcr = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800176
177 if (!enable_off_mode)
178 return;
179
Kevin Hilman6f251e92010-09-27 20:19:38 +0530180 lcr = serial_read_reg(uart, UART_LCR);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800181 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530182 uart->dll = serial_read_reg(uart, UART_DLL);
183 uart->dlh = serial_read_reg(uart, UART_DLM);
184 serial_write_reg(uart, UART_LCR, lcr);
185 uart->ier = serial_read_reg(uart, UART_IER);
186 uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
187 uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
188 uart->wer = serial_read_reg(uart, UART_OMAP_WER);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800189 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530190 uart->mcr = serial_read_reg(uart, UART_MCR);
191 serial_write_reg(uart, UART_LCR, lcr);
Kevin Hilman4af40162009-02-04 10:51:40 -0800192
193 uart->context_valid = 1;
194}
195
196static void omap_uart_restore_context(struct omap_uart_state *uart)
197{
198 u16 efr = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800199
200 if (!enable_off_mode)
201 return;
202
203 if (!uart->context_valid)
204 return;
205
206 uart->context_valid = 0;
207
Deepak K00034502010-08-02 13:18:12 +0300208 if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800209 omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
Deepak K00034502010-08-02 13:18:12 +0300210 else
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800211 serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
212
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800213 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530214 efr = serial_read_reg(uart, UART_EFR);
215 serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
216 serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
217 serial_write_reg(uart, UART_IER, 0x0);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800218 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530219 serial_write_reg(uart, UART_DLL, uart->dll);
220 serial_write_reg(uart, UART_DLM, uart->dlh);
221 serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
222 serial_write_reg(uart, UART_IER, uart->ier);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800223 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530224 serial_write_reg(uart, UART_MCR, uart->mcr);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800225 serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530226 serial_write_reg(uart, UART_EFR, efr);
227 serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
228 serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
229 serial_write_reg(uart, UART_OMAP_WER, uart->wer);
230 serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800231
Deepak K00034502010-08-02 13:18:12 +0300232 if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800233 omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
Deepak K00034502010-08-02 13:18:12 +0300234 else
Kevin Hilman6f251e92010-09-27 20:19:38 +0530235 /* UART 16x mode */
Andrei Emeltchenko498cb952010-11-30 14:11:49 -0800236 serial_write_reg(uart, UART_OMAP_MDR1,
237 UART_OMAP_MDR1_16X_MODE);
Kevin Hilman4af40162009-02-04 10:51:40 -0800238}
239#else
240static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
241static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
242#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
243
244static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
245{
246 if (uart->clocked)
247 return;
248
Kevin Hilman6f251e92010-09-27 20:19:38 +0530249 omap_device_enable(uart->pdev);
Kevin Hilman4af40162009-02-04 10:51:40 -0800250 uart->clocked = 1;
251 omap_uart_restore_context(uart);
252}
253
254#ifdef CONFIG_PM
255
256static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
257{
258 if (!uart->clocked)
259 return;
260
261 omap_uart_save_context(uart);
262 uart->clocked = 0;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530263 omap_device_idle(uart->pdev);
Kevin Hilman4af40162009-02-04 10:51:40 -0800264}
265
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700266static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
267{
268 /* Set wake-enable bit */
269 if (uart->wk_en && uart->wk_mask) {
270 u32 v = __raw_readl(uart->wk_en);
271 v |= uart->wk_mask;
272 __raw_writel(v, uart->wk_en);
273 }
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700274}
275
276static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
277{
278 /* Clear wake-enable bit */
279 if (uart->wk_en && uart->wk_mask) {
280 u32 v = __raw_readl(uart->wk_en);
281 v &= ~uart->wk_mask;
282 __raw_writel(v, uart->wk_en);
283 }
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700284}
285
Kevin Hilman4af40162009-02-04 10:51:40 -0800286static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
Kevin Hilman6f251e92010-09-27 20:19:38 +0530287 int enable)
Kevin Hilman4af40162009-02-04 10:51:40 -0800288{
Kevin Hilman6f251e92010-09-27 20:19:38 +0530289 u8 idlemode;
Kevin Hilman4af40162009-02-04 10:51:40 -0800290
Kevin Hilman6f251e92010-09-27 20:19:38 +0530291 if (enable) {
292 /**
293 * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
294 * in Smartidle Mode When Configured for DMA Operations.
295 */
296 if (uart->dma_enabled)
297 idlemode = HWMOD_IDLEMODE_FORCE;
298 else
299 idlemode = HWMOD_IDLEMODE_SMART;
300 } else {
301 idlemode = HWMOD_IDLEMODE_NO;
302 }
Kevin Hilman4af40162009-02-04 10:51:40 -0800303
Kevin Hilman6f251e92010-09-27 20:19:38 +0530304 omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
Kevin Hilman4af40162009-02-04 10:51:40 -0800305}
306
307static void omap_uart_block_sleep(struct omap_uart_state *uart)
308{
309 omap_uart_enable_clocks(uart);
310
311 omap_uart_smart_idle_enable(uart, 0);
312 uart->can_sleep = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800313}
314
Kevin Hilman4af40162009-02-04 10:51:40 -0800315int omap_uart_can_sleep(void)
316{
317 struct omap_uart_state *uart;
318 int can_sleep = 1;
319
320 list_for_each_entry(uart, &uart_list, node) {
321 if (!uart->clocked)
322 continue;
323
324 if (!uart->can_sleep) {
325 can_sleep = 0;
326 continue;
327 }
328
329 /* This UART can now safely sleep. */
330 omap_uart_allow_sleep(uart);
331 }
332
333 return can_sleep;
334}
335
Kevin Hilman4af40162009-02-04 10:51:40 -0800336static void omap_uart_idle_init(struct omap_uart_state *uart)
337{
Kevin Hilman4af40162009-02-04 10:51:40 -0800338 int ret;
339
340 uart->can_sleep = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800341 omap_uart_smart_idle_enable(uart, 0);
342
Hemant Pedanekara9203602011-12-13 10:46:44 -0800343 if (cpu_is_omap34xx() && !(cpu_is_ti81xx() || cpu_is_am33xx())) {
Govindraj.R52663ae2010-09-27 20:20:41 +0530344 u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
Kevin Hilman4af40162009-02-04 10:51:40 -0800345 u32 wk_mask = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800346
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700347 /* XXX These PRM accesses do not belong here */
Kevin Hilman4af40162009-02-04 10:51:40 -0800348 uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
349 uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
350 switch (uart->num) {
351 case 0:
352 wk_mask = OMAP3430_ST_UART1_MASK;
Kevin Hilman4af40162009-02-04 10:51:40 -0800353 break;
354 case 1:
355 wk_mask = OMAP3430_ST_UART2_MASK;
Kevin Hilman4af40162009-02-04 10:51:40 -0800356 break;
357 case 2:
358 wk_mask = OMAP3430_ST_UART3_MASK;
Kevin Hilman4af40162009-02-04 10:51:40 -0800359 break;
Govindraj.R52663ae2010-09-27 20:20:41 +0530360 case 3:
361 wk_mask = OMAP3630_ST_UART4_MASK;
Govindraj.R52663ae2010-09-27 20:20:41 +0530362 break;
Kevin Hilman4af40162009-02-04 10:51:40 -0800363 }
364 uart->wk_mask = wk_mask;
Kevin Hilman4af40162009-02-04 10:51:40 -0800365 } else if (cpu_is_omap24xx()) {
366 u32 wk_mask = 0;
Kevin Hilmancb74f022010-10-20 23:19:03 +0000367 u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
Kevin Hilman4af40162009-02-04 10:51:40 -0800368
Kevin Hilman4af40162009-02-04 10:51:40 -0800369 switch (uart->num) {
370 case 0:
371 wk_mask = OMAP24XX_ST_UART1_MASK;
372 break;
373 case 1:
374 wk_mask = OMAP24XX_ST_UART2_MASK;
375 break;
376 case 2:
Kevin Hilmancb74f022010-10-20 23:19:03 +0000377 wk_en = OMAP24XX_PM_WKEN2;
378 wk_st = OMAP24XX_PM_WKST2;
Kevin Hilman4af40162009-02-04 10:51:40 -0800379 wk_mask = OMAP24XX_ST_UART3_MASK;
380 break;
381 }
382 uart->wk_mask = wk_mask;
Kevin Hilmancb74f022010-10-20 23:19:03 +0000383 if (cpu_is_omap2430()) {
384 uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
385 uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
386 } else if (cpu_is_omap2420()) {
387 uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
388 uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
389 }
Kevin Hilman4af40162009-02-04 10:51:40 -0800390 } else {
Nishanth Menonc54bae12010-08-02 13:18:11 +0300391 uart->wk_en = NULL;
392 uart->wk_st = NULL;
Kevin Hilman4af40162009-02-04 10:51:40 -0800393 uart->wk_mask = 0;
Kevin Hilman4af40162009-02-04 10:51:40 -0800394 }
Kevin Hilman4af40162009-02-04 10:51:40 -0800395}
396
397#else
Santosh Shilimkara1b04cc2010-10-11 11:05:18 +0000398static void omap_uart_block_sleep(struct omap_uart_state *uart)
399{
400 /* Needed to enable UART clocks when built without CONFIG_PM */
401 omap_uart_enable_clocks(uart);
402}
Kevin Hilman4af40162009-02-04 10:51:40 -0800403#endif /* CONFIG_PM */
404
Govindraj.R7496ba32011-11-07 18:55:05 +0530405#ifdef CONFIG_OMAP_MUX
406static struct omap_device_pad default_uart1_pads[] __initdata = {
407 {
408 .name = "uart1_cts.uart1_cts",
409 .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
410 },
411 {
412 .name = "uart1_rts.uart1_rts",
413 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
414 },
415 {
416 .name = "uart1_tx.uart1_tx",
417 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
418 },
419 {
420 .name = "uart1_rx.uart1_rx",
421 .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
422 .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
423 .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
424 },
425};
426
427static struct omap_device_pad default_uart2_pads[] __initdata = {
428 {
429 .name = "uart2_cts.uart2_cts",
430 .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
431 },
432 {
433 .name = "uart2_rts.uart2_rts",
434 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
435 },
436 {
437 .name = "uart2_tx.uart2_tx",
438 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
439 },
440 {
441 .name = "uart2_rx.uart2_rx",
442 .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
443 .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
444 .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
445 },
446};
447
448static struct omap_device_pad default_uart3_pads[] __initdata = {
449 {
450 .name = "uart3_cts_rctx.uart3_cts_rctx",
451 .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
452 },
453 {
454 .name = "uart3_rts_sd.uart3_rts_sd",
455 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
456 },
457 {
458 .name = "uart3_tx_irtx.uart3_tx_irtx",
459 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
460 },
461 {
462 .name = "uart3_rx_irrx.uart3_rx_irrx",
463 .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
464 .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
465 .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
466 },
467};
468
469static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {
470 {
471 .name = "gpmc_wait2.uart4_tx",
472 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
473 },
474 {
475 .name = "gpmc_wait3.uart4_rx",
476 .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
477 .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
478 .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
479 },
480};
481
482static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {
483 {
484 .name = "uart4_tx.uart4_tx",
485 .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
486 },
487 {
488 .name = "uart4_rx.uart4_rx",
489 .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
490 .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
491 .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
492 },
493};
494
495static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
496{
497 switch (bdata->id) {
498 case 0:
499 bdata->pads = default_uart1_pads;
500 bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads);
501 break;
502 case 1:
503 bdata->pads = default_uart2_pads;
504 bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads);
505 break;
506 case 2:
507 bdata->pads = default_uart3_pads;
508 bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads);
509 break;
510 case 3:
511 if (cpu_is_omap44xx()) {
512 bdata->pads = default_omap4_uart4_pads;
513 bdata->pads_cnt =
514 ARRAY_SIZE(default_omap4_uart4_pads);
515 } else if (cpu_is_omap3630()) {
516 bdata->pads = default_omap36xx_uart4_pads;
517 bdata->pads_cnt =
518 ARRAY_SIZE(default_omap36xx_uart4_pads);
519 }
520 break;
521 default:
522 break;
523 }
524}
525#else
526static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {}
527#endif
528
Tony Lindgren3e16f922011-02-14 15:40:20 -0800529static int __init omap_serial_early_init(void)
Tony Lindgren1dbae812005-11-10 14:26:51 +0000530{
Kevin Hilman6f251e92010-09-27 20:19:38 +0530531 int i = 0;
Tony Lindgren1dbae812005-11-10 14:26:51 +0000532
Kevin Hilman6f251e92010-09-27 20:19:38 +0530533 do {
534 char oh_name[MAX_UART_HWMOD_NAME_LEN];
535 struct omap_hwmod *oh;
536 struct omap_uart_state *uart;
Thomas Weber21b90342010-02-25 09:40:19 +0000537
Kevin Hilman6f251e92010-09-27 20:19:38 +0530538 snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
539 "uart%d", i + 1);
540 oh = omap_hwmod_lookup(oh_name);
541 if (!oh)
542 break;
Tony Lindgren1dbae812005-11-10 14:26:51 +0000543
Kevin Hilman6f251e92010-09-27 20:19:38 +0530544 uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
545 if (WARN_ON(!uart))
Tony Lindgren3e16f922011-02-14 15:40:20 -0800546 return -ENODEV;
Tony Lindgren1dbae812005-11-10 14:26:51 +0000547
Kevin Hilman6f251e92010-09-27 20:19:38 +0530548 uart->oh = oh;
549 uart->num = i++;
550 list_add_tail(&uart->node, &uart_list);
551 num_uarts++;
552
Tony Lindgren84f90c92009-10-16 09:53:00 -0700553 /*
Paul Walmsley550c8092011-02-28 11:58:14 -0700554 * NOTE: omap_hwmod_setup*() has not yet been called,
Kevin Hilman6f251e92010-09-27 20:19:38 +0530555 * so no hwmod functions will work yet.
Tony Lindgren84f90c92009-10-16 09:53:00 -0700556 */
Tony Lindgren84f90c92009-10-16 09:53:00 -0700557
Kevin Hilman6f251e92010-09-27 20:19:38 +0530558 /*
559 * During UART early init, device need to be probed
560 * to determine SoC specific init before omap_device
561 * is ready. Therefore, don't allow idle here
562 */
563 uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
564 } while (1);
Tony Lindgren3e16f922011-02-14 15:40:20 -0800565
566 return 0;
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300567}
Tony Lindgren3e16f922011-02-14 15:40:20 -0800568core_initcall(omap_serial_early_init);
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300569
Mika Westerbergf62349e2009-12-11 16:16:35 -0800570/**
571 * omap_serial_init_port() - initialize single serial port
Tony Lindgren40e44392010-12-22 18:42:35 -0800572 * @bdata: port specific board data pointer
Mika Westerbergf62349e2009-12-11 16:16:35 -0800573 *
Tony Lindgren40e44392010-12-22 18:42:35 -0800574 * This function initialies serial driver for given port only.
Mika Westerbergf62349e2009-12-11 16:16:35 -0800575 * Platforms can call this function instead of omap_serial_init()
576 * if they don't plan to use all available UARTs as serial ports.
577 *
578 * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
579 * use only one of the two.
580 */
Tony Lindgren40e44392010-12-22 18:42:35 -0800581void __init omap_serial_init_port(struct omap_board_data *bdata)
Mika Westerbergf62349e2009-12-11 16:16:35 -0800582{
583 struct omap_uart_state *uart;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530584 struct omap_hwmod *oh;
Kevin Hilman3528c582011-07-21 13:48:45 -0700585 struct platform_device *pdev;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530586 void *pdata = NULL;
587 u32 pdata_size = 0;
588 char *name;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530589 struct omap_uart_port_info omap_up;
Mika Westerbergf62349e2009-12-11 16:16:35 -0800590
Tony Lindgren40e44392010-12-22 18:42:35 -0800591 if (WARN_ON(!bdata))
Sergio Aguirree88d5562010-02-27 14:13:43 -0600592 return;
Tony Lindgren40e44392010-12-22 18:42:35 -0800593 if (WARN_ON(bdata->id < 0))
594 return;
595 if (WARN_ON(bdata->id >= num_uarts))
Mika Westerbergf62349e2009-12-11 16:16:35 -0800596 return;
597
Kevin Hilman6f251e92010-09-27 20:19:38 +0530598 list_for_each_entry(uart, &uart_list, node)
Tony Lindgren40e44392010-12-22 18:42:35 -0800599 if (bdata->id == uart->num)
Kevin Hilman6f251e92010-09-27 20:19:38 +0530600 break;
601
602 oh = uart->oh;
603 uart->dma_enabled = 0;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530604 name = DRIVER_NAME;
605
606 omap_up.dma_enabled = uart->dma_enabled;
607 omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
608 omap_up.mapbase = oh->slaves[0]->addr->pa_start;
609 omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
Govindraj.R273558b2011-09-13 14:01:01 +0530610 omap_up.flags = UPF_BOOT_AUTOCONF;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530611
612 pdata = &omap_up;
613 pdata_size = sizeof(struct omap_uart_port_info);
Kevin Hilman6f251e92010-09-27 20:19:38 +0530614
615 if (WARN_ON(!oh))
616 return;
617
Kevin Hilman3528c582011-07-21 13:48:45 -0700618 pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
Benoit Coussonf718e2c2011-08-10 15:30:09 +0200619 NULL, 0, false);
Kevin Hilman3528c582011-07-21 13:48:45 -0700620 WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
Kevin Hilman6f251e92010-09-27 20:19:38 +0530621 name, oh->name);
622
Kevin Hilman9f8b6942011-08-01 09:33:13 -0700623 omap_device_disable_idle_on_suspend(pdev);
Tony Lindgren40e44392010-12-22 18:42:35 -0800624 oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
625
Kevin Hilman6f251e92010-09-27 20:19:38 +0530626 uart->regshift = 2;
627 uart->mapbase = oh->slaves[0]->addr->pa_start;
628 uart->membase = omap_hwmod_get_mpu_rt_va(oh);
Kevin Hilman3528c582011-07-21 13:48:45 -0700629 uart->pdev = pdev;
Kevin Hilman6f251e92010-09-27 20:19:38 +0530630
631 oh->dev_attr = uart;
632
Torben Hohnac751ef2011-01-25 15:07:35 -0800633 console_lock(); /* in case the earlycon is on the UART */
Paul Walmsley0d8e2d02010-11-24 16:49:05 -0700634
Kevin Hilman6f251e92010-09-27 20:19:38 +0530635 /*
636 * Because of early UART probing, UART did not get idled
637 * on init. Now that omap_device is ready, ensure full idle
638 * before doing omap_device_enable().
639 */
640 omap_hwmod_idle(uart->oh);
641
642 omap_device_enable(uart->pdev);
643 omap_uart_idle_init(uart);
644 omap_uart_reset(uart);
645 omap_hwmod_enable_wakeup(uart->oh);
646 omap_device_idle(uart->pdev);
647
Kevin Hilman6f251e92010-09-27 20:19:38 +0530648 omap_uart_block_sleep(uart);
Torben Hohnac751ef2011-01-25 15:07:35 -0800649 console_unlock();
Paul Walmsley0d8e2d02010-11-24 16:49:05 -0700650
Govindraj.R7496ba32011-11-07 18:55:05 +0530651 if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
652 (pdata->wk_en && pdata->wk_mask))
Kevin Hilman3528c582011-07-21 13:48:45 -0700653 device_init_wakeup(&pdev->dev, true);
Deepak K00034502010-08-02 13:18:12 +0300654
655 /* Enable the MDR1 errata for OMAP3 */
Hemant Pedanekara9203602011-12-13 10:46:44 -0800656 if (cpu_is_omap34xx() && !(cpu_is_ti81xx() || cpu_is_am33xx()))
Deepak K00034502010-08-02 13:18:12 +0300657 uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
Mika Westerbergf62349e2009-12-11 16:16:35 -0800658}
659
660/**
Uwe Kleine-Königb5950762010-11-01 15:38:34 -0400661 * omap_serial_init() - initialize all supported serial ports
Mika Westerbergf62349e2009-12-11 16:16:35 -0800662 *
663 * Initializes all available UARTs as serial ports. Platforms
664 * can call this function when they want to have default behaviour
665 * for serial ports (e.g initialize them all as serial ports).
666 */
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300667void __init omap_serial_init(void)
668{
Kevin Hilman6f251e92010-09-27 20:19:38 +0530669 struct omap_uart_state *uart;
Tony Lindgren40e44392010-12-22 18:42:35 -0800670 struct omap_board_data bdata;
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300671
Tony Lindgren40e44392010-12-22 18:42:35 -0800672 list_for_each_entry(uart, &uart_list, node) {
673 bdata.id = uart->num;
674 bdata.flags = 0;
675 bdata.pads = NULL;
676 bdata.pads_cnt = 0;
Govindraj.R7496ba32011-11-07 18:55:05 +0530677
678 if (cpu_is_omap44xx() || cpu_is_omap34xx())
679 omap_serial_fill_default_pads(&bdata);
680
Tony Lindgren40e44392010-12-22 18:42:35 -0800681 omap_serial_init_port(&bdata);
682
683 }
Tony Lindgren1dbae812005-11-10 14:26:51 +0000684}