diff options
22 files changed, 2707 insertions, 296 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1c4b2377862b..91dd215d05f0 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -11,9 +11,8 @@ config ARCH_OMAP2PLUS_TYPICAL | |||
11 | select PM_RUNTIME | 11 | select PM_RUNTIME |
12 | select VFP | 12 | select VFP |
13 | select NEON if ARCH_OMAP3 || ARCH_OMAP4 | 13 | select NEON if ARCH_OMAP3 || ARCH_OMAP4 |
14 | select SERIAL_8250 | 14 | select SERIAL_OMAP |
15 | select SERIAL_CORE_CONSOLE | 15 | select SERIAL_OMAP_CONSOLE |
16 | select SERIAL_8250_CONSOLE | ||
17 | select I2C | 16 | select I2C |
18 | select I2C_OMAP | 17 | select I2C_OMAP |
19 | select MFD | 18 | select MFD |
@@ -222,12 +221,18 @@ config MACH_OMAP_ZOOM2 | |||
222 | depends on ARCH_OMAP3 | 221 | depends on ARCH_OMAP3 |
223 | default y | 222 | default y |
224 | select OMAP_PACKAGE_CBB | 223 | select OMAP_PACKAGE_CBB |
224 | select SERIAL_8250 | ||
225 | select SERIAL_CORE_CONSOLE | ||
226 | select SERIAL_8250_CONSOLE | ||
225 | 227 | ||
226 | config MACH_OMAP_ZOOM3 | 228 | config MACH_OMAP_ZOOM3 |
227 | bool "OMAP3630 Zoom3 board" | 229 | bool "OMAP3630 Zoom3 board" |
228 | depends on ARCH_OMAP3 | 230 | depends on ARCH_OMAP3 |
229 | default y | 231 | default y |
230 | select OMAP_PACKAGE_CBP | 232 | select OMAP_PACKAGE_CBP |
233 | select SERIAL_8250 | ||
234 | select SERIAL_CORE_CONSOLE | ||
235 | select SERIAL_8250_CONSOLE | ||
231 | 236 | ||
232 | config MACH_CM_T35 | 237 | config MACH_CM_T35 |
233 | bool "CompuLab CM-T35 module" | 238 | bool "CompuLab CM-T35 module" |
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index b359c3f7bb39..d5104519ab03 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c | |||
@@ -208,7 +208,6 @@ static struct flash_partitions sdp_flash_partitions[] = { | |||
208 | static void __init omap_sdp_init(void) | 208 | static void __init omap_sdp_init(void) |
209 | { | 209 | { |
210 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBP); | 210 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBP); |
211 | omap_serial_init(); | ||
212 | zoom_peripherals_init(); | 211 | zoom_peripherals_init(); |
213 | board_smc91x_init(); | 212 | board_smc91x_init(); |
214 | board_flash_init(sdp_flash_partitions, chip_sel_sdp); | 213 | board_flash_init(sdp_flash_partitions, chip_sel_sdp); |
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index e5eac46bbac9..35066b355bd5 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c | |||
@@ -283,4 +283,5 @@ void __init zoom_peripherals_init(void) | |||
283 | omap_i2c_init(); | 283 | omap_i2c_init(); |
284 | usb_musb_init(&musb_board_data); | 284 | usb_musb_init(&musb_board_data); |
285 | enable_board_wakeup_source(); | 285 | enable_board_wakeup_source(); |
286 | omap_serial_init(); | ||
286 | } | 287 | } |
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index c73906d17458..ba01ec0cae45 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c | |||
@@ -2465,6 +2465,16 @@ static struct clk uart3_fck = { | |||
2465 | .recalc = &followparent_recalc, | 2465 | .recalc = &followparent_recalc, |
2466 | }; | 2466 | }; |
2467 | 2467 | ||
2468 | static struct clk uart4_fck = { | ||
2469 | .name = "uart4_fck", | ||
2470 | .ops = &clkops_omap2_dflt_wait, | ||
2471 | .parent = &per_48m_fck, | ||
2472 | .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), | ||
2473 | .enable_bit = OMAP3630_EN_UART4_SHIFT, | ||
2474 | .clkdm_name = "per_clkdm", | ||
2475 | .recalc = &followparent_recalc, | ||
2476 | }; | ||
2477 | |||
2468 | static struct clk gpt2_fck = { | 2478 | static struct clk gpt2_fck = { |
2469 | .name = "gpt2_fck", | 2479 | .name = "gpt2_fck", |
2470 | .ops = &clkops_omap2_dflt_wait, | 2480 | .ops = &clkops_omap2_dflt_wait, |
@@ -2715,6 +2725,16 @@ static struct clk uart3_ick = { | |||
2715 | .recalc = &followparent_recalc, | 2725 | .recalc = &followparent_recalc, |
2716 | }; | 2726 | }; |
2717 | 2727 | ||
2728 | static struct clk uart4_ick = { | ||
2729 | .name = "uart4_ick", | ||
2730 | .ops = &clkops_omap2_dflt_wait, | ||
2731 | .parent = &per_l4_ick, | ||
2732 | .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), | ||
2733 | .enable_bit = OMAP3630_EN_UART4_SHIFT, | ||
2734 | .clkdm_name = "per_clkdm", | ||
2735 | .recalc = &followparent_recalc, | ||
2736 | }; | ||
2737 | |||
2718 | static struct clk gpt9_ick = { | 2738 | static struct clk gpt9_ick = { |
2719 | .name = "gpt9_ick", | 2739 | .name = "gpt9_ick", |
2720 | .ops = &clkops_omap2_dflt_wait, | 2740 | .ops = &clkops_omap2_dflt_wait, |
@@ -3349,6 +3369,7 @@ static struct omap_clk omap3xxx_clks[] = { | |||
3349 | CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX), | 3369 | CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX), |
3350 | CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX), | 3370 | CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX), |
3351 | CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX), | 3371 | CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX), |
3372 | CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX), | ||
3352 | CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX), | 3373 | CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX), |
3353 | CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX), | 3374 | CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX), |
3354 | CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX), | 3375 | CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX), |
@@ -3372,6 +3393,7 @@ static struct omap_clk omap3xxx_clks[] = { | |||
3372 | CLK(NULL, "gpio2_ick", &gpio2_ick, CK_3XXX), | 3393 | CLK(NULL, "gpio2_ick", &gpio2_ick, CK_3XXX), |
3373 | CLK(NULL, "wdt3_ick", &wdt3_ick, CK_3XXX), | 3394 | CLK(NULL, "wdt3_ick", &wdt3_ick, CK_3XXX), |
3374 | CLK(NULL, "uart3_ick", &uart3_ick, CK_3XXX), | 3395 | CLK(NULL, "uart3_ick", &uart3_ick, CK_3XXX), |
3396 | CLK(NULL, "uart4_ick", &uart4_ick, CK_36XX), | ||
3375 | CLK(NULL, "gpt9_ick", &gpt9_ick, CK_3XXX), | 3397 | CLK(NULL, "gpt9_ick", &gpt9_ick, CK_3XXX), |
3376 | CLK(NULL, "gpt8_ick", &gpt8_ick, CK_3XXX), | 3398 | CLK(NULL, "gpt8_ick", &gpt8_ick, CK_3XXX), |
3377 | CLK(NULL, "gpt7_ick", &gpt7_ick, CK_3XXX), | 3399 | CLK(NULL, "gpt7_ick", &gpt7_ick, CK_3XXX), |
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index fe82b79d5f3b..4f959a7d881c 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h | |||
@@ -649,6 +649,8 @@ | |||
649 | #define OMAP3430_ST_MCBSP2_MASK (1 << 0) | 649 | #define OMAP3430_ST_MCBSP2_MASK (1 << 0) |
650 | 650 | ||
651 | /* CM_AUTOIDLE_PER */ | 651 | /* CM_AUTOIDLE_PER */ |
652 | #define OMAP3630_AUTO_UART4_MASK (1 << 18) | ||
653 | #define OMAP3630_AUTO_UART4_SHIFT 18 | ||
652 | #define OMAP3430_AUTO_GPIO6_MASK (1 << 17) | 654 | #define OMAP3430_AUTO_GPIO6_MASK (1 << 17) |
653 | #define OMAP3430_AUTO_GPIO6_SHIFT 17 | 655 | #define OMAP3430_AUTO_GPIO6_SHIFT 17 |
654 | #define OMAP3430_AUTO_GPIO5_MASK (1 << 16) | 656 | #define OMAP3430_AUTO_GPIO5_MASK (1 << 16) |
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 66678d98ad96..adf6e3632a2b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <mach/irqs.h> | 15 | #include <mach/irqs.h> |
16 | #include <plat/cpu.h> | 16 | #include <plat/cpu.h> |
17 | #include <plat/dma.h> | 17 | #include <plat/dma.h> |
18 | #include <plat/serial.h> | ||
18 | 19 | ||
19 | #include "omap_hwmod_common_data.h" | 20 | #include "omap_hwmod_common_data.h" |
20 | 21 | ||
@@ -73,6 +74,9 @@ static struct omap_hwmod omap2420_l3_main_hwmod = { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static struct omap_hwmod omap2420_l4_wkup_hwmod; | 76 | static struct omap_hwmod omap2420_l4_wkup_hwmod; |
77 | static struct omap_hwmod omap2420_uart1_hwmod; | ||
78 | static struct omap_hwmod omap2420_uart2_hwmod; | ||
79 | static struct omap_hwmod omap2420_uart3_hwmod; | ||
76 | 80 | ||
77 | /* L4_CORE -> L4_WKUP interface */ | 81 | /* L4_CORE -> L4_WKUP interface */ |
78 | static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = { | 82 | static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = { |
@@ -81,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = { | |||
81 | .user = OCP_USER_MPU | OCP_USER_SDMA, | 85 | .user = OCP_USER_MPU | OCP_USER_SDMA, |
82 | }; | 86 | }; |
83 | 87 | ||
88 | /* L4 CORE -> UART1 interface */ | ||
89 | static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = { | ||
90 | { | ||
91 | .pa_start = OMAP2_UART1_BASE, | ||
92 | .pa_end = OMAP2_UART1_BASE + SZ_8K - 1, | ||
93 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = { | ||
98 | .master = &omap2420_l4_core_hwmod, | ||
99 | .slave = &omap2420_uart1_hwmod, | ||
100 | .clk = "uart1_ick", | ||
101 | .addr = omap2420_uart1_addr_space, | ||
102 | .addr_cnt = ARRAY_SIZE(omap2420_uart1_addr_space), | ||
103 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
104 | }; | ||
105 | |||
106 | /* L4 CORE -> UART2 interface */ | ||
107 | static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = { | ||
108 | { | ||
109 | .pa_start = OMAP2_UART2_BASE, | ||
110 | .pa_end = OMAP2_UART2_BASE + SZ_1K - 1, | ||
111 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
112 | }, | ||
113 | }; | ||
114 | |||
115 | static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = { | ||
116 | .master = &omap2420_l4_core_hwmod, | ||
117 | .slave = &omap2420_uart2_hwmod, | ||
118 | .clk = "uart2_ick", | ||
119 | .addr = omap2420_uart2_addr_space, | ||
120 | .addr_cnt = ARRAY_SIZE(omap2420_uart2_addr_space), | ||
121 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
122 | }; | ||
123 | |||
124 | /* L4 PER -> UART3 interface */ | ||
125 | static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = { | ||
126 | { | ||
127 | .pa_start = OMAP2_UART3_BASE, | ||
128 | .pa_end = OMAP2_UART3_BASE + SZ_1K - 1, | ||
129 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = { | ||
134 | .master = &omap2420_l4_core_hwmod, | ||
135 | .slave = &omap2420_uart3_hwmod, | ||
136 | .clk = "uart3_ick", | ||
137 | .addr = omap2420_uart3_addr_space, | ||
138 | .addr_cnt = ARRAY_SIZE(omap2420_uart3_addr_space), | ||
139 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
140 | }; | ||
141 | |||
84 | /* Slave interfaces on the L4_CORE interconnect */ | 142 | /* Slave interfaces on the L4_CORE interconnect */ |
85 | static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = { | 143 | static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = { |
86 | &omap2420_l3_main__l4_core, | 144 | &omap2420_l3_main__l4_core, |
@@ -89,6 +147,9 @@ static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = { | |||
89 | /* Master interfaces on the L4_CORE interconnect */ | 147 | /* Master interfaces on the L4_CORE interconnect */ |
90 | static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = { | 148 | static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = { |
91 | &omap2420_l4_core__l4_wkup, | 149 | &omap2420_l4_core__l4_wkup, |
150 | &omap2_l4_core__uart1, | ||
151 | &omap2_l4_core__uart2, | ||
152 | &omap2_l4_core__uart3, | ||
92 | }; | 153 | }; |
93 | 154 | ||
94 | /* L4 CORE */ | 155 | /* L4 CORE */ |
@@ -228,6 +289,135 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = { | |||
228 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), | 289 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), |
229 | }; | 290 | }; |
230 | 291 | ||
292 | /* UART */ | ||
293 | |||
294 | static struct omap_hwmod_class_sysconfig uart_sysc = { | ||
295 | .rev_offs = 0x50, | ||
296 | .sysc_offs = 0x54, | ||
297 | .syss_offs = 0x58, | ||
298 | .sysc_flags = (SYSC_HAS_SIDLEMODE | | ||
299 | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | | ||
300 | SYSC_HAS_AUTOIDLE), | ||
301 | .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
302 | .sysc_fields = &omap_hwmod_sysc_type1, | ||
303 | }; | ||
304 | |||
305 | static struct omap_hwmod_class uart_class = { | ||
306 | .name = "uart", | ||
307 | .sysc = &uart_sysc, | ||
308 | }; | ||
309 | |||
310 | /* UART1 */ | ||
311 | |||
312 | static struct omap_hwmod_irq_info uart1_mpu_irqs[] = { | ||
313 | { .irq = INT_24XX_UART1_IRQ, }, | ||
314 | }; | ||
315 | |||
316 | static struct omap_hwmod_dma_info uart1_sdma_reqs[] = { | ||
317 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, }, | ||
318 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, }, | ||
319 | }; | ||
320 | |||
321 | static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = { | ||
322 | &omap2_l4_core__uart1, | ||
323 | }; | ||
324 | |||
325 | static struct omap_hwmod omap2420_uart1_hwmod = { | ||
326 | .name = "uart1", | ||
327 | .mpu_irqs = uart1_mpu_irqs, | ||
328 | .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs), | ||
329 | .sdma_reqs = uart1_sdma_reqs, | ||
330 | .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs), | ||
331 | .main_clk = "uart1_fck", | ||
332 | .prcm = { | ||
333 | .omap2 = { | ||
334 | .module_offs = CORE_MOD, | ||
335 | .prcm_reg_id = 1, | ||
336 | .module_bit = OMAP24XX_EN_UART1_SHIFT, | ||
337 | .idlest_reg_id = 1, | ||
338 | .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT, | ||
339 | }, | ||
340 | }, | ||
341 | .slaves = omap2420_uart1_slaves, | ||
342 | .slaves_cnt = ARRAY_SIZE(omap2420_uart1_slaves), | ||
343 | .class = &uart_class, | ||
344 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), | ||
345 | }; | ||
346 | |||
347 | /* UART2 */ | ||
348 | |||
349 | static struct omap_hwmod_irq_info uart2_mpu_irqs[] = { | ||
350 | { .irq = INT_24XX_UART2_IRQ, }, | ||
351 | }; | ||
352 | |||
353 | static struct omap_hwmod_dma_info uart2_sdma_reqs[] = { | ||
354 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, }, | ||
355 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, }, | ||
356 | }; | ||
357 | |||
358 | static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = { | ||
359 | &omap2_l4_core__uart2, | ||
360 | }; | ||
361 | |||
362 | static struct omap_hwmod omap2420_uart2_hwmod = { | ||
363 | .name = "uart2", | ||
364 | .mpu_irqs = uart2_mpu_irqs, | ||
365 | .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs), | ||
366 | .sdma_reqs = uart2_sdma_reqs, | ||
367 | .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs), | ||
368 | .main_clk = "uart2_fck", | ||
369 | .prcm = { | ||
370 | .omap2 = { | ||
371 | .module_offs = CORE_MOD, | ||
372 | .prcm_reg_id = 1, | ||
373 | .module_bit = OMAP24XX_EN_UART2_SHIFT, | ||
374 | .idlest_reg_id = 1, | ||
375 | .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT, | ||
376 | }, | ||
377 | }, | ||
378 | .slaves = omap2420_uart2_slaves, | ||
379 | .slaves_cnt = ARRAY_SIZE(omap2420_uart2_slaves), | ||
380 | .class = &uart_class, | ||
381 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), | ||
382 | }; | ||
383 | |||
384 | /* UART3 */ | ||
385 | |||
386 | static struct omap_hwmod_irq_info uart3_mpu_irqs[] = { | ||
387 | { .irq = INT_24XX_UART3_IRQ, }, | ||
388 | }; | ||
389 | |||
390 | static struct omap_hwmod_dma_info uart3_sdma_reqs[] = { | ||
391 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, }, | ||
392 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, }, | ||
393 | }; | ||
394 | |||
395 | static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = { | ||
396 | &omap2_l4_core__uart3, | ||
397 | }; | ||
398 | |||
399 | static struct omap_hwmod omap2420_uart3_hwmod = { | ||
400 | .name = "uart3", | ||
401 | .mpu_irqs = uart3_mpu_irqs, | ||
402 | .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs), | ||
403 | .sdma_reqs = uart3_sdma_reqs, | ||
404 | .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs), | ||
405 | .main_clk = "uart3_fck", | ||
406 | .prcm = { | ||
407 | .omap2 = { | ||
408 | .module_offs = CORE_MOD, | ||
409 | .prcm_reg_id = 2, | ||
410 | .module_bit = OMAP24XX_EN_UART3_SHIFT, | ||
411 | .idlest_reg_id = 2, | ||
412 | .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT, | ||
413 | }, | ||
414 | }, | ||
415 | .slaves = omap2420_uart3_slaves, | ||
416 | .slaves_cnt = ARRAY_SIZE(omap2420_uart3_slaves), | ||
417 | .class = &uart_class, | ||
418 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), | ||
419 | }; | ||
420 | |||
231 | static __initdata struct omap_hwmod *omap2420_hwmods[] = { | 421 | static __initdata struct omap_hwmod *omap2420_hwmods[] = { |
232 | &omap2420_l3_main_hwmod, | 422 | &omap2420_l3_main_hwmod, |
233 | &omap2420_l4_core_hwmod, | 423 | &omap2420_l4_core_hwmod, |
@@ -235,6 +425,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = { | |||
235 | &omap2420_mpu_hwmod, | 425 | &omap2420_mpu_hwmod, |
236 | &omap2420_iva_hwmod, | 426 | &omap2420_iva_hwmod, |
237 | &omap2420_wd_timer2_hwmod, | 427 | &omap2420_wd_timer2_hwmod, |
428 | &omap2420_uart1_hwmod, | ||
429 | &omap2420_uart2_hwmod, | ||
430 | &omap2420_uart3_hwmod, | ||
238 | NULL, | 431 | NULL, |
239 | }; | 432 | }; |
240 | 433 | ||
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 7ec927aa23de..12d939e456cf 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <mach/irqs.h> | 15 | #include <mach/irqs.h> |
16 | #include <plat/cpu.h> | 16 | #include <plat/cpu.h> |
17 | #include <plat/dma.h> | 17 | #include <plat/dma.h> |
18 | #include <plat/serial.h> | ||
18 | 19 | ||
19 | #include "omap_hwmod_common_data.h" | 20 | #include "omap_hwmod_common_data.h" |
20 | 21 | ||
@@ -73,6 +74,9 @@ static struct omap_hwmod omap2430_l3_main_hwmod = { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static struct omap_hwmod omap2430_l4_wkup_hwmod; | 76 | static struct omap_hwmod omap2430_l4_wkup_hwmod; |
77 | static struct omap_hwmod omap2430_uart1_hwmod; | ||
78 | static struct omap_hwmod omap2430_uart2_hwmod; | ||
79 | static struct omap_hwmod omap2430_uart3_hwmod; | ||
76 | 80 | ||
77 | /* L4_CORE -> L4_WKUP interface */ | 81 | /* L4_CORE -> L4_WKUP interface */ |
78 | static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = { | 82 | static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = { |
@@ -81,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = { | |||
81 | .user = OCP_USER_MPU | OCP_USER_SDMA, | 85 | .user = OCP_USER_MPU | OCP_USER_SDMA, |
82 | }; | 86 | }; |
83 | 87 | ||
88 | /* L4 CORE -> UART1 interface */ | ||
89 | static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = { | ||
90 | { | ||
91 | .pa_start = OMAP2_UART1_BASE, | ||
92 | .pa_end = OMAP2_UART1_BASE + SZ_8K - 1, | ||
93 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = { | ||
98 | .master = &omap2430_l4_core_hwmod, | ||
99 | .slave = &omap2430_uart1_hwmod, | ||
100 | .clk = "uart1_ick", | ||
101 | .addr = omap2430_uart1_addr_space, | ||
102 | .addr_cnt = ARRAY_SIZE(omap2430_uart1_addr_space), | ||
103 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
104 | }; | ||
105 | |||
106 | /* L4 CORE -> UART2 interface */ | ||
107 | static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = { | ||
108 | { | ||
109 | .pa_start = OMAP2_UART2_BASE, | ||
110 | .pa_end = OMAP2_UART2_BASE + SZ_1K - 1, | ||
111 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
112 | }, | ||
113 | }; | ||
114 | |||
115 | static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = { | ||
116 | .master = &omap2430_l4_core_hwmod, | ||
117 | .slave = &omap2430_uart2_hwmod, | ||
118 | .clk = "uart2_ick", | ||
119 | .addr = omap2430_uart2_addr_space, | ||
120 | .addr_cnt = ARRAY_SIZE(omap2430_uart2_addr_space), | ||
121 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
122 | }; | ||
123 | |||
124 | /* L4 PER -> UART3 interface */ | ||
125 | static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = { | ||
126 | { | ||
127 | .pa_start = OMAP2_UART3_BASE, | ||
128 | .pa_end = OMAP2_UART3_BASE + SZ_1K - 1, | ||
129 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = { | ||
134 | .master = &omap2430_l4_core_hwmod, | ||
135 | .slave = &omap2430_uart3_hwmod, | ||
136 | .clk = "uart3_ick", | ||
137 | .addr = omap2430_uart3_addr_space, | ||
138 | .addr_cnt = ARRAY_SIZE(omap2430_uart3_addr_space), | ||
139 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
140 | }; | ||
141 | |||
84 | /* Slave interfaces on the L4_CORE interconnect */ | 142 | /* Slave interfaces on the L4_CORE interconnect */ |
85 | static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = { | 143 | static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = { |
86 | &omap2430_l3_main__l4_core, | 144 | &omap2430_l3_main__l4_core, |
@@ -106,6 +164,9 @@ static struct omap_hwmod omap2430_l4_core_hwmod = { | |||
106 | /* Slave interfaces on the L4_WKUP interconnect */ | 164 | /* Slave interfaces on the L4_WKUP interconnect */ |
107 | static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = { | 165 | static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = { |
108 | &omap2430_l4_core__l4_wkup, | 166 | &omap2430_l4_core__l4_wkup, |
167 | &omap2_l4_core__uart1, | ||
168 | &omap2_l4_core__uart2, | ||
169 | &omap2_l4_core__uart3, | ||
109 | }; | 170 | }; |
110 | 171 | ||
111 | /* Master interfaces on the L4_WKUP interconnect */ | 172 | /* Master interfaces on the L4_WKUP interconnect */ |
@@ -228,6 +289,135 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = { | |||
228 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), | 289 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), |
229 | }; | 290 | }; |
230 | 291 | ||
292 | /* UART */ | ||
293 | |||
294 | static struct omap_hwmod_class_sysconfig uart_sysc = { | ||
295 | .rev_offs = 0x50, | ||
296 | .sysc_offs = 0x54, | ||
297 | .syss_offs = 0x58, | ||
298 | .sysc_flags = (SYSC_HAS_SIDLEMODE | | ||
299 | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | | ||
300 | SYSC_HAS_AUTOIDLE), | ||
301 | .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
302 | .sysc_fields = &omap_hwmod_sysc_type1, | ||
303 | }; | ||
304 | |||
305 | static struct omap_hwmod_class uart_class = { | ||
306 | .name = "uart", | ||
307 | .sysc = &uart_sysc, | ||
308 | }; | ||
309 | |||
310 | /* UART1 */ | ||
311 | |||
312 | static struct omap_hwmod_irq_info uart1_mpu_irqs[] = { | ||
313 | { .irq = INT_24XX_UART1_IRQ, }, | ||
314 | }; | ||
315 | |||
316 | static struct omap_hwmod_dma_info uart1_sdma_reqs[] = { | ||
317 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, }, | ||
318 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, }, | ||
319 | }; | ||
320 | |||
321 | static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = { | ||
322 | &omap2_l4_core__uart1, | ||
323 | }; | ||
324 | |||
325 | static struct omap_hwmod omap2430_uart1_hwmod = { | ||
326 | .name = "uart1", | ||
327 | .mpu_irqs = uart1_mpu_irqs, | ||
328 | .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs), | ||
329 | .sdma_reqs = uart1_sdma_reqs, | ||
330 | .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs), | ||
331 | .main_clk = "uart1_fck", | ||
332 | .prcm = { | ||
333 | .omap2 = { | ||
334 | .module_offs = CORE_MOD, | ||
335 | .prcm_reg_id = 1, | ||
336 | .module_bit = OMAP24XX_EN_UART1_SHIFT, | ||
337 | .idlest_reg_id = 1, | ||
338 | .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT, | ||
339 | }, | ||
340 | }, | ||
341 | .slaves = omap2430_uart1_slaves, | ||
342 | .slaves_cnt = ARRAY_SIZE(omap2430_uart1_slaves), | ||
343 | .class = &uart_class, | ||
344 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), | ||
345 | }; | ||
346 | |||
347 | /* UART2 */ | ||
348 | |||
349 | static struct omap_hwmod_irq_info uart2_mpu_irqs[] = { | ||
350 | { .irq = INT_24XX_UART2_IRQ, }, | ||
351 | }; | ||
352 | |||
353 | static struct omap_hwmod_dma_info uart2_sdma_reqs[] = { | ||
354 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, }, | ||
355 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, }, | ||
356 | }; | ||
357 | |||
358 | static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = { | ||
359 | &omap2_l4_core__uart2, | ||
360 | }; | ||
361 | |||
362 | static struct omap_hwmod omap2430_uart2_hwmod = { | ||
363 | .name = "uart2", | ||
364 | .mpu_irqs = uart2_mpu_irqs, | ||
365 | .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs), | ||
366 | .sdma_reqs = uart2_sdma_reqs, | ||
367 | .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs), | ||
368 | .main_clk = "uart2_fck", | ||
369 | .prcm = { | ||
370 | .omap2 = { | ||
371 | .module_offs = CORE_MOD, | ||
372 | .prcm_reg_id = 1, | ||
373 | .module_bit = OMAP24XX_EN_UART2_SHIFT, | ||
374 | .idlest_reg_id = 1, | ||
375 | .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT, | ||
376 | }, | ||
377 | }, | ||
378 | .slaves = omap2430_uart2_slaves, | ||
379 | .slaves_cnt = ARRAY_SIZE(omap2430_uart2_slaves), | ||
380 | .class = &uart_class, | ||
381 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), | ||
382 | }; | ||
383 | |||
384 | /* UART3 */ | ||
385 | |||
386 | static struct omap_hwmod_irq_info uart3_mpu_irqs[] = { | ||
387 | { .irq = INT_24XX_UART3_IRQ, }, | ||
388 | }; | ||
389 | |||
390 | static struct omap_hwmod_dma_info uart3_sdma_reqs[] = { | ||
391 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, }, | ||
392 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, }, | ||
393 | }; | ||
394 | |||
395 | static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = { | ||
396 | &omap2_l4_core__uart3, | ||
397 | }; | ||
398 | |||
399 | static struct omap_hwmod omap2430_uart3_hwmod = { | ||
400 | .name = "uart3", | ||
401 | .mpu_irqs = uart3_mpu_irqs, | ||
402 | .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs), | ||
403 | .sdma_reqs = uart3_sdma_reqs, | ||
404 | .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs), | ||
405 | .main_clk = "uart3_fck", | ||
406 | .prcm = { | ||
407 | .omap2 = { | ||
408 | .module_offs = CORE_MOD, | ||
409 | .prcm_reg_id = 2, | ||
410 | .module_bit = OMAP24XX_EN_UART3_SHIFT, | ||
411 | .idlest_reg_id = 2, | ||
412 | .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT, | ||
413 | }, | ||
414 | }, | ||
415 | .slaves = omap2430_uart3_slaves, | ||
416 | .slaves_cnt = ARRAY_SIZE(omap2430_uart3_slaves), | ||
417 | .class = &uart_class, | ||
418 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), | ||
419 | }; | ||
420 | |||
231 | static __initdata struct omap_hwmod *omap2430_hwmods[] = { | 421 | static __initdata struct omap_hwmod *omap2430_hwmods[] = { |
232 | &omap2430_l3_main_hwmod, | 422 | &omap2430_l3_main_hwmod, |
233 | &omap2430_l4_core_hwmod, | 423 | &omap2430_l4_core_hwmod, |
@@ -235,6 +425,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = { | |||
235 | &omap2430_mpu_hwmod, | 425 | &omap2430_mpu_hwmod, |
236 | &omap2430_iva_hwmod, | 426 | &omap2430_iva_hwmod, |
237 | &omap2430_wd_timer2_hwmod, | 427 | &omap2430_wd_timer2_hwmod, |
428 | &omap2430_uart1_hwmod, | ||
429 | &omap2430_uart2_hwmod, | ||
430 | &omap2430_uart3_hwmod, | ||
238 | NULL, | 431 | NULL, |
239 | }; | 432 | }; |
240 | 433 | ||
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 5bfe9c933144..cb97ecf0a3f6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <mach/irqs.h> | 17 | #include <mach/irqs.h> |
18 | #include <plat/cpu.h> | 18 | #include <plat/cpu.h> |
19 | #include <plat/dma.h> | 19 | #include <plat/dma.h> |
20 | #include <plat/serial.h> | ||
20 | 21 | ||
21 | #include "omap_hwmod_common_data.h" | 22 | #include "omap_hwmod_common_data.h" |
22 | 23 | ||
@@ -84,6 +85,10 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = { | |||
84 | }; | 85 | }; |
85 | 86 | ||
86 | static struct omap_hwmod omap3xxx_l4_wkup_hwmod; | 87 | static struct omap_hwmod omap3xxx_l4_wkup_hwmod; |
88 | static struct omap_hwmod omap3xxx_uart1_hwmod; | ||
89 | static struct omap_hwmod omap3xxx_uart2_hwmod; | ||
90 | static struct omap_hwmod omap3xxx_uart3_hwmod; | ||
91 | static struct omap_hwmod omap3xxx_uart4_hwmod; | ||
87 | 92 | ||
88 | /* L4_CORE -> L4_WKUP interface */ | 93 | /* L4_CORE -> L4_WKUP interface */ |
89 | static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { | 94 | static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { |
@@ -92,6 +97,78 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { | |||
92 | .user = OCP_USER_MPU | OCP_USER_SDMA, | 97 | .user = OCP_USER_MPU | OCP_USER_SDMA, |
93 | }; | 98 | }; |
94 | 99 | ||
100 | /* L4 CORE -> UART1 interface */ | ||
101 | static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = { | ||
102 | { | ||
103 | .pa_start = OMAP3_UART1_BASE, | ||
104 | .pa_end = OMAP3_UART1_BASE + SZ_8K - 1, | ||
105 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = { | ||
110 | .master = &omap3xxx_l4_core_hwmod, | ||
111 | .slave = &omap3xxx_uart1_hwmod, | ||
112 | .clk = "uart1_ick", | ||
113 | .addr = omap3xxx_uart1_addr_space, | ||
114 | .addr_cnt = ARRAY_SIZE(omap3xxx_uart1_addr_space), | ||
115 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
116 | }; | ||
117 | |||
118 | /* L4 CORE -> UART2 interface */ | ||
119 | static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = { | ||
120 | { | ||
121 | .pa_start = OMAP3_UART2_BASE, | ||
122 | .pa_end = OMAP3_UART2_BASE + SZ_1K - 1, | ||
123 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = { | ||
128 | .master = &omap3xxx_l4_core_hwmod, | ||
129 | .slave = &omap3xxx_uart2_hwmod, | ||
130 | .clk = "uart2_ick", | ||
131 | .addr = omap3xxx_uart2_addr_space, | ||
132 | .addr_cnt = ARRAY_SIZE(omap3xxx_uart2_addr_space), | ||
133 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
134 | }; | ||
135 | |||
136 | /* L4 PER -> UART3 interface */ | ||
137 | static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = { | ||
138 | { | ||
139 | .pa_start = OMAP3_UART3_BASE, | ||
140 | .pa_end = OMAP3_UART3_BASE + SZ_1K - 1, | ||
141 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
142 | }, | ||
143 | }; | ||
144 | |||
145 | static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = { | ||
146 | .master = &omap3xxx_l4_per_hwmod, | ||
147 | .slave = &omap3xxx_uart3_hwmod, | ||
148 | .clk = "uart3_ick", | ||
149 | .addr = omap3xxx_uart3_addr_space, | ||
150 | .addr_cnt = ARRAY_SIZE(omap3xxx_uart3_addr_space), | ||
151 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
152 | }; | ||
153 | |||
154 | /* L4 PER -> UART4 interface */ | ||
155 | static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = { | ||
156 | { | ||
157 | .pa_start = OMAP3_UART4_BASE, | ||
158 | .pa_end = OMAP3_UART4_BASE + SZ_1K - 1, | ||
159 | .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = { | ||
164 | .master = &omap3xxx_l4_per_hwmod, | ||
165 | .slave = &omap3xxx_uart4_hwmod, | ||
166 | .clk = "uart4_ick", | ||
167 | .addr = omap3xxx_uart4_addr_space, | ||
168 | .addr_cnt = ARRAY_SIZE(omap3xxx_uart4_addr_space), | ||
169 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
170 | }; | ||
171 | |||
95 | /* Slave interfaces on the L4_CORE interconnect */ | 172 | /* Slave interfaces on the L4_CORE interconnect */ |
96 | static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { | 173 | static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { |
97 | &omap3xxx_l3_main__l4_core, | 174 | &omap3xxx_l3_main__l4_core, |
@@ -100,6 +177,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { | |||
100 | /* Master interfaces on the L4_CORE interconnect */ | 177 | /* Master interfaces on the L4_CORE interconnect */ |
101 | static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = { | 178 | static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = { |
102 | &omap3xxx_l4_core__l4_wkup, | 179 | &omap3xxx_l4_core__l4_wkup, |
180 | &omap3_l4_core__uart1, | ||
181 | &omap3_l4_core__uart2, | ||
103 | }; | 182 | }; |
104 | 183 | ||
105 | /* L4 CORE */ | 184 | /* L4 CORE */ |
@@ -121,6 +200,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = { | |||
121 | 200 | ||
122 | /* Master interfaces on the L4_PER interconnect */ | 201 | /* Master interfaces on the L4_PER interconnect */ |
123 | static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = { | 202 | static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = { |
203 | &omap3_l4_per__uart3, | ||
204 | &omap3_l4_per__uart4, | ||
124 | }; | 205 | }; |
125 | 206 | ||
126 | /* L4 PER */ | 207 | /* L4 PER */ |
@@ -262,6 +343,172 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = { | |||
262 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | 343 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), |
263 | }; | 344 | }; |
264 | 345 | ||
346 | /* UART common */ | ||
347 | |||
348 | static struct omap_hwmod_class_sysconfig uart_sysc = { | ||
349 | .rev_offs = 0x50, | ||
350 | .sysc_offs = 0x54, | ||
351 | .syss_offs = 0x58, | ||
352 | .sysc_flags = (SYSC_HAS_SIDLEMODE | | ||
353 | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | | ||
354 | SYSC_HAS_AUTOIDLE), | ||
355 | .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
356 | .sysc_fields = &omap_hwmod_sysc_type1, | ||
357 | }; | ||
358 | |||
359 | static struct omap_hwmod_class uart_class = { | ||
360 | .name = "uart", | ||
361 | .sysc = &uart_sysc, | ||
362 | }; | ||
363 | |||
364 | /* UART1 */ | ||
365 | |||
366 | static struct omap_hwmod_irq_info uart1_mpu_irqs[] = { | ||
367 | { .irq = INT_24XX_UART1_IRQ, }, | ||
368 | }; | ||
369 | |||
370 | static struct omap_hwmod_dma_info uart1_sdma_reqs[] = { | ||
371 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, }, | ||
372 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, }, | ||
373 | }; | ||
374 | |||
375 | static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = { | ||
376 | &omap3_l4_core__uart1, | ||
377 | }; | ||
378 | |||
379 | static struct omap_hwmod omap3xxx_uart1_hwmod = { | ||
380 | .name = "uart1", | ||
381 | .mpu_irqs = uart1_mpu_irqs, | ||
382 | .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs), | ||
383 | .sdma_reqs = uart1_sdma_reqs, | ||
384 | .sdma_reqs_cnt = ARRAY_SIZE(uart1_sdma_reqs), | ||
385 | .main_clk = "uart1_fck", | ||
386 | .prcm = { | ||
387 | .omap2 = { | ||
388 | .module_offs = CORE_MOD, | ||
389 | .prcm_reg_id = 1, | ||
390 | .module_bit = OMAP3430_EN_UART1_SHIFT, | ||
391 | .idlest_reg_id = 1, | ||
392 | .idlest_idle_bit = OMAP3430_EN_UART1_SHIFT, | ||
393 | }, | ||
394 | }, | ||
395 | .slaves = omap3xxx_uart1_slaves, | ||
396 | .slaves_cnt = ARRAY_SIZE(omap3xxx_uart1_slaves), | ||
397 | .class = &uart_class, | ||
398 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
399 | }; | ||
400 | |||
401 | /* UART2 */ | ||
402 | |||
403 | static struct omap_hwmod_irq_info uart2_mpu_irqs[] = { | ||
404 | { .irq = INT_24XX_UART2_IRQ, }, | ||
405 | }; | ||
406 | |||
407 | static struct omap_hwmod_dma_info uart2_sdma_reqs[] = { | ||
408 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, }, | ||
409 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, }, | ||
410 | }; | ||
411 | |||
412 | static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = { | ||
413 | &omap3_l4_core__uart2, | ||
414 | }; | ||
415 | |||
416 | static struct omap_hwmod omap3xxx_uart2_hwmod = { | ||
417 | .name = "uart2", | ||
418 | .mpu_irqs = uart2_mpu_irqs, | ||
419 | .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs), | ||
420 | .sdma_reqs = uart2_sdma_reqs, | ||
421 | .sdma_reqs_cnt = ARRAY_SIZE(uart2_sdma_reqs), | ||
422 | .main_clk = "uart2_fck", | ||
423 | .prcm = { | ||
424 | .omap2 = { | ||
425 | .module_offs = CORE_MOD, | ||
426 | .prcm_reg_id = 1, | ||
427 | .module_bit = OMAP3430_EN_UART2_SHIFT, | ||
428 | .idlest_reg_id = 1, | ||
429 | .idlest_idle_bit = OMAP3430_EN_UART2_SHIFT, | ||
430 | }, | ||
431 | }, | ||
432 | .slaves = omap3xxx_uart2_slaves, | ||
433 | .slaves_cnt = ARRAY_SIZE(omap3xxx_uart2_slaves), | ||
434 | .class = &uart_class, | ||
435 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
436 | }; | ||
437 | |||
438 | /* UART3 */ | ||
439 | |||
440 | static struct omap_hwmod_irq_info uart3_mpu_irqs[] = { | ||
441 | { .irq = INT_24XX_UART3_IRQ, }, | ||
442 | }; | ||
443 | |||
444 | static struct omap_hwmod_dma_info uart3_sdma_reqs[] = { | ||
445 | { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, }, | ||
446 | { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, }, | ||
447 | }; | ||
448 | |||
449 | static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = { | ||
450 | &omap3_l4_per__uart3, | ||
451 | }; | ||
452 | |||
453 | static struct omap_hwmod omap3xxx_uart3_hwmod = { | ||
454 | .name = "uart3", | ||
455 | .mpu_irqs = uart3_mpu_irqs, | ||
456 | .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs), | ||
457 | .sdma_reqs = uart3_sdma_reqs, | ||
458 | .sdma_reqs_cnt = ARRAY_SIZE(uart3_sdma_reqs), | ||
459 | .main_clk = "uart3_fck", | ||
460 | .prcm = { | ||
461 | .omap2 = { | ||
462 | .module_offs = OMAP3430_PER_MOD, | ||
463 | .prcm_reg_id = 1, | ||
464 | .module_bit = OMAP3430_EN_UART3_SHIFT, | ||
465 | .idlest_reg_id = 1, | ||
466 | .idlest_idle_bit = OMAP3430_EN_UART3_SHIFT, | ||
467 | }, | ||
468 | }, | ||
469 | .slaves = omap3xxx_uart3_slaves, | ||
470 | .slaves_cnt = ARRAY_SIZE(omap3xxx_uart3_slaves), | ||
471 | .class = &uart_class, | ||
472 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
473 | }; | ||
474 | |||
475 | /* UART4 */ | ||
476 | |||
477 | static struct omap_hwmod_irq_info uart4_mpu_irqs[] = { | ||
478 | { .irq = INT_36XX_UART4_IRQ, }, | ||
479 | }; | ||
480 | |||
481 | static struct omap_hwmod_dma_info uart4_sdma_reqs[] = { | ||
482 | { .name = "rx", .dma_req = OMAP36XX_DMA_UART4_RX, }, | ||
483 | { .name = "tx", .dma_req = OMAP36XX_DMA_UART4_TX, }, | ||
484 | }; | ||
485 | |||
486 | static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = { | ||
487 | &omap3_l4_per__uart4, | ||
488 | }; | ||
489 | |||
490 | static struct omap_hwmod omap3xxx_uart4_hwmod = { | ||
491 | .name = "uart4", | ||
492 | .mpu_irqs = uart4_mpu_irqs, | ||
493 | .mpu_irqs_cnt = ARRAY_SIZE(uart4_mpu_irqs), | ||
494 | .sdma_reqs = uart4_sdma_reqs, | ||
495 | .sdma_reqs_cnt = ARRAY_SIZE(uart4_sdma_reqs), | ||
496 | .main_clk = "uart4_fck", | ||
497 | .prcm = { | ||
498 | .omap2 = { | ||
499 | .module_offs = OMAP3430_PER_MOD, | ||
500 | .prcm_reg_id = 1, | ||
501 | .module_bit = OMAP3630_EN_UART4_SHIFT, | ||
502 | .idlest_reg_id = 1, | ||
503 | .idlest_idle_bit = OMAP3630_EN_UART4_SHIFT, | ||
504 | }, | ||
505 | }, | ||
506 | .slaves = omap3xxx_uart4_slaves, | ||
507 | .slaves_cnt = ARRAY_SIZE(omap3xxx_uart4_slaves), | ||
508 | .class = &uart_class, | ||
509 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), | ||
510 | }; | ||
511 | |||
265 | static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { | 512 | static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { |
266 | &omap3xxx_l3_main_hwmod, | 513 | &omap3xxx_l3_main_hwmod, |
267 | &omap3xxx_l4_core_hwmod, | 514 | &omap3xxx_l4_core_hwmod, |
@@ -270,6 +517,10 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { | |||
270 | &omap3xxx_mpu_hwmod, | 517 | &omap3xxx_mpu_hwmod, |
271 | &omap3xxx_iva_hwmod, | 518 | &omap3xxx_iva_hwmod, |
272 | &omap3xxx_wd_timer2_hwmod, | 519 | &omap3xxx_wd_timer2_hwmod, |
520 | &omap3xxx_uart1_hwmod, | ||
521 | &omap3xxx_uart2_hwmod, | ||
522 | &omap3xxx_uart3_hwmod, | ||
523 | &omap3xxx_uart4_hwmod, | ||
273 | NULL, | 524 | NULL, |
274 | }; | 525 | }; |
275 | 526 | ||
@@ -277,5 +528,3 @@ int __init omap3xxx_hwmod_init(void) | |||
277 | { | 528 | { |
278 | return omap_hwmod_init(omap3xxx_hwmods); | 529 | return omap_hwmod_init(omap3xxx_hwmods); |
279 | } | 530 | } |
280 | |||
281 | |||
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 9523b4c9537f..7274db4de487 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | |||
@@ -468,6 +468,21 @@ static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = { | |||
468 | .sysc_fields = &omap_hwmod_sysc_type1, | 468 | .sysc_fields = &omap_hwmod_sysc_type1, |
469 | }; | 469 | }; |
470 | 470 | ||
471 | /* | ||
472 | * 'uart' class | ||
473 | * universal asynchronous receiver/transmitter (uart) | ||
474 | */ | ||
475 | |||
476 | static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = { | ||
477 | .rev_offs = 0x0050, | ||
478 | .sysc_offs = 0x0054, | ||
479 | .syss_offs = 0x0058, | ||
480 | .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | | ||
481 | SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), | ||
482 | .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
483 | .sysc_fields = &omap_hwmod_sysc_type1, | ||
484 | }; | ||
485 | |||
471 | static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = { | 486 | static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = { |
472 | .name = "wd_timer", | 487 | .name = "wd_timer", |
473 | .sysc = &omap44xx_wd_timer_sysc, | 488 | .sysc = &omap44xx_wd_timer_sysc, |
@@ -487,6 +502,82 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = { | |||
487 | }, | 502 | }, |
488 | }; | 503 | }; |
489 | 504 | ||
505 | static struct omap_hwmod_class omap44xx_uart_hwmod_class = { | ||
506 | .name = "uart", | ||
507 | .sysc = &omap44xx_uart_sysc, | ||
508 | }; | ||
509 | |||
510 | /* uart1 */ | ||
511 | static struct omap_hwmod omap44xx_uart1_hwmod; | ||
512 | static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = { | ||
513 | { .irq = 72 + OMAP44XX_IRQ_GIC_START }, | ||
514 | }; | ||
515 | |||
516 | static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = { | ||
517 | { .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START }, | ||
518 | { .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START }, | ||
519 | }; | ||
520 | |||
521 | static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = { | ||
522 | { | ||
523 | .pa_start = 0x4806a000, | ||
524 | .pa_end = 0x4806a0ff, | ||
525 | .flags = ADDR_TYPE_RT | ||
526 | }, | ||
527 | }; | ||
528 | |||
529 | /* l4_per -> uart1 */ | ||
530 | static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = { | ||
531 | .master = &omap44xx_l4_per_hwmod, | ||
532 | .slave = &omap44xx_uart1_hwmod, | ||
533 | .clk = "l4_div_ck", | ||
534 | .addr = omap44xx_uart1_addrs, | ||
535 | .addr_cnt = ARRAY_SIZE(omap44xx_uart1_addrs), | ||
536 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
537 | }; | ||
538 | |||
539 | /* uart1 slave ports */ | ||
540 | static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = { | ||
541 | &omap44xx_l4_per__uart1, | ||
542 | }; | ||
543 | |||
544 | static struct omap_hwmod omap44xx_uart1_hwmod = { | ||
545 | .name = "uart1", | ||
546 | .class = &omap44xx_uart_hwmod_class, | ||
547 | .mpu_irqs = omap44xx_uart1_irqs, | ||
548 | .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart1_irqs), | ||
549 | .sdma_reqs = omap44xx_uart1_sdma_reqs, | ||
550 | .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart1_sdma_reqs), | ||
551 | .main_clk = "uart1_fck", | ||
552 | .prcm = { | ||
553 | .omap4 = { | ||
554 | .clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL, | ||
555 | }, | ||
556 | }, | ||
557 | .slaves = omap44xx_uart1_slaves, | ||
558 | .slaves_cnt = ARRAY_SIZE(omap44xx_uart1_slaves), | ||
559 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
560 | }; | ||
561 | |||
562 | /* uart2 */ | ||
563 | static struct omap_hwmod omap44xx_uart2_hwmod; | ||
564 | static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = { | ||
565 | { .irq = 73 + OMAP44XX_IRQ_GIC_START }, | ||
566 | }; | ||
567 | |||
568 | static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = { | ||
569 | { .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START }, | ||
570 | { .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START }, | ||
571 | }; | ||
572 | |||
573 | static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = { | ||
574 | { | ||
575 | .pa_start = 0x4806c000, | ||
576 | .pa_end = 0x4806c0ff, | ||
577 | .flags = ADDR_TYPE_RT | ||
578 | }, | ||
579 | }; | ||
580 | |||
490 | /* l4_wkup -> wd_timer2 */ | 581 | /* l4_wkup -> wd_timer2 */ |
491 | static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = { | 582 | static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = { |
492 | .master = &omap44xx_l4_wkup_hwmod, | 583 | .master = &omap44xx_l4_wkup_hwmod, |
@@ -532,6 +623,58 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = { | |||
532 | }, | 623 | }, |
533 | }; | 624 | }; |
534 | 625 | ||
626 | /* l4_per -> uart2 */ | ||
627 | static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = { | ||
628 | .master = &omap44xx_l4_per_hwmod, | ||
629 | .slave = &omap44xx_uart2_hwmod, | ||
630 | .clk = "l4_div_ck", | ||
631 | .addr = omap44xx_uart2_addrs, | ||
632 | .addr_cnt = ARRAY_SIZE(omap44xx_uart2_addrs), | ||
633 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
634 | }; | ||
635 | |||
636 | /* uart2 slave ports */ | ||
637 | static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = { | ||
638 | &omap44xx_l4_per__uart2, | ||
639 | }; | ||
640 | |||
641 | static struct omap_hwmod omap44xx_uart2_hwmod = { | ||
642 | .name = "uart2", | ||
643 | .class = &omap44xx_uart_hwmod_class, | ||
644 | .mpu_irqs = omap44xx_uart2_irqs, | ||
645 | .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart2_irqs), | ||
646 | .sdma_reqs = omap44xx_uart2_sdma_reqs, | ||
647 | .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart2_sdma_reqs), | ||
648 | .main_clk = "uart2_fck", | ||
649 | .prcm = { | ||
650 | .omap4 = { | ||
651 | .clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL, | ||
652 | }, | ||
653 | }, | ||
654 | .slaves = omap44xx_uart2_slaves, | ||
655 | .slaves_cnt = ARRAY_SIZE(omap44xx_uart2_slaves), | ||
656 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
657 | }; | ||
658 | |||
659 | /* uart3 */ | ||
660 | static struct omap_hwmod omap44xx_uart3_hwmod; | ||
661 | static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = { | ||
662 | { .irq = 74 + OMAP44XX_IRQ_GIC_START }, | ||
663 | }; | ||
664 | |||
665 | static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = { | ||
666 | { .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START }, | ||
667 | { .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START }, | ||
668 | }; | ||
669 | |||
670 | static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = { | ||
671 | { | ||
672 | .pa_start = 0x48020000, | ||
673 | .pa_end = 0x480200ff, | ||
674 | .flags = ADDR_TYPE_RT | ||
675 | }, | ||
676 | }; | ||
677 | |||
535 | /* l4_abe -> wd_timer3 */ | 678 | /* l4_abe -> wd_timer3 */ |
536 | static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = { | 679 | static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = { |
537 | .master = &omap44xx_l4_abe_hwmod, | 680 | .master = &omap44xx_l4_abe_hwmod, |
@@ -551,6 +694,59 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = { | |||
551 | }, | 694 | }, |
552 | }; | 695 | }; |
553 | 696 | ||
697 | /* l4_per -> uart3 */ | ||
698 | static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = { | ||
699 | .master = &omap44xx_l4_per_hwmod, | ||
700 | .slave = &omap44xx_uart3_hwmod, | ||
701 | .clk = "l4_div_ck", | ||
702 | .addr = omap44xx_uart3_addrs, | ||
703 | .addr_cnt = ARRAY_SIZE(omap44xx_uart3_addrs), | ||
704 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
705 | }; | ||
706 | |||
707 | /* uart3 slave ports */ | ||
708 | static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = { | ||
709 | &omap44xx_l4_per__uart3, | ||
710 | }; | ||
711 | |||
712 | static struct omap_hwmod omap44xx_uart3_hwmod = { | ||
713 | .name = "uart3", | ||
714 | .class = &omap44xx_uart_hwmod_class, | ||
715 | .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), | ||
716 | .mpu_irqs = omap44xx_uart3_irqs, | ||
717 | .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart3_irqs), | ||
718 | .sdma_reqs = omap44xx_uart3_sdma_reqs, | ||
719 | .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart3_sdma_reqs), | ||
720 | .main_clk = "uart3_fck", | ||
721 | .prcm = { | ||
722 | .omap4 = { | ||
723 | .clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL, | ||
724 | }, | ||
725 | }, | ||
726 | .slaves = omap44xx_uart3_slaves, | ||
727 | .slaves_cnt = ARRAY_SIZE(omap44xx_uart3_slaves), | ||
728 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
729 | }; | ||
730 | |||
731 | /* uart4 */ | ||
732 | static struct omap_hwmod omap44xx_uart4_hwmod; | ||
733 | static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = { | ||
734 | { .irq = 70 + OMAP44XX_IRQ_GIC_START }, | ||
735 | }; | ||
736 | |||
737 | static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = { | ||
738 | { .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START }, | ||
739 | { .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START }, | ||
740 | }; | ||
741 | |||
742 | static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = { | ||
743 | { | ||
744 | .pa_start = 0x4806e000, | ||
745 | .pa_end = 0x4806e0ff, | ||
746 | .flags = ADDR_TYPE_RT | ||
747 | }, | ||
748 | }; | ||
749 | |||
554 | static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = { | 750 | static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = { |
555 | .master = &omap44xx_l4_abe_hwmod, | 751 | .master = &omap44xx_l4_abe_hwmod, |
556 | .slave = &omap44xx_wd_timer3_hwmod, | 752 | .slave = &omap44xx_wd_timer3_hwmod, |
@@ -582,6 +778,39 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { | |||
582 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | 778 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), |
583 | }; | 779 | }; |
584 | 780 | ||
781 | /* l4_per -> uart4 */ | ||
782 | static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = { | ||
783 | .master = &omap44xx_l4_per_hwmod, | ||
784 | .slave = &omap44xx_uart4_hwmod, | ||
785 | .clk = "l4_div_ck", | ||
786 | .addr = omap44xx_uart4_addrs, | ||
787 | .addr_cnt = ARRAY_SIZE(omap44xx_uart4_addrs), | ||
788 | .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
789 | }; | ||
790 | |||
791 | /* uart4 slave ports */ | ||
792 | static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = { | ||
793 | &omap44xx_l4_per__uart4, | ||
794 | }; | ||
795 | |||
796 | static struct omap_hwmod omap44xx_uart4_hwmod = { | ||
797 | .name = "uart4", | ||
798 | .class = &omap44xx_uart_hwmod_class, | ||
799 | .mpu_irqs = omap44xx_uart4_irqs, | ||
800 | .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart4_irqs), | ||
801 | .sdma_reqs = omap44xx_uart4_sdma_reqs, | ||
802 | .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_uart4_sdma_reqs), | ||
803 | .main_clk = "uart4_fck", | ||
804 | .prcm = { | ||
805 | .omap4 = { | ||
806 | .clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL, | ||
807 | }, | ||
808 | }, | ||
809 | .slaves = omap44xx_uart4_slaves, | ||
810 | .slaves_cnt = ARRAY_SIZE(omap44xx_uart4_slaves), | ||
811 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
812 | }; | ||
813 | |||
585 | static __initdata struct omap_hwmod *omap44xx_hwmods[] = { | 814 | static __initdata struct omap_hwmod *omap44xx_hwmods[] = { |
586 | /* dmm class */ | 815 | /* dmm class */ |
587 | &omap44xx_dmm_hwmod, | 816 | &omap44xx_dmm_hwmod, |
@@ -605,6 +834,12 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { | |||
605 | /* wd_timer class */ | 834 | /* wd_timer class */ |
606 | &omap44xx_wd_timer2_hwmod, | 835 | &omap44xx_wd_timer2_hwmod, |
607 | &omap44xx_wd_timer3_hwmod, | 836 | &omap44xx_wd_timer3_hwmod, |
837 | |||
838 | /* uart class */ | ||
839 | &omap44xx_uart1_hwmod, | ||
840 | &omap44xx_uart2_hwmod, | ||
841 | &omap44xx_uart3_hwmod, | ||
842 | &omap44xx_uart4_hwmod, | ||
608 | NULL, | 843 | NULL, |
609 | }; | 844 | }; |
610 | 845 | ||
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index d2b940c7215d..60baffa27cb3 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -388,6 +388,7 @@ void omap_sram_idle(void) | |||
388 | /* PER */ | 388 | /* PER */ |
389 | if (per_next_state < PWRDM_POWER_ON) { | 389 | if (per_next_state < PWRDM_POWER_ON) { |
390 | omap_uart_prepare_idle(2); | 390 | omap_uart_prepare_idle(2); |
391 | omap_uart_prepare_idle(3); | ||
391 | omap2_gpio_prepare_for_idle(per_next_state); | 392 | omap2_gpio_prepare_for_idle(per_next_state); |
392 | if (per_next_state == PWRDM_POWER_OFF) | 393 | if (per_next_state == PWRDM_POWER_OFF) |
393 | omap3_per_save_context(); | 394 | omap3_per_save_context(); |
@@ -459,6 +460,7 @@ void omap_sram_idle(void) | |||
459 | if (per_prev_state == PWRDM_POWER_OFF) | 460 | if (per_prev_state == PWRDM_POWER_OFF) |
460 | omap3_per_restore_context(); | 461 | omap3_per_restore_context(); |
461 | omap_uart_resume_idle(2); | 462 | omap_uart_resume_idle(2); |
463 | omap_uart_resume_idle(3); | ||
462 | } | 464 | } |
463 | 465 | ||
464 | /* Disable IO-PAD and IO-CHAIN wakeup */ | 466 | /* Disable IO-PAD and IO-CHAIN wakeup */ |
@@ -676,6 +678,14 @@ static void __init omap3_d2d_idle(void) | |||
676 | 678 | ||
677 | static void __init prcm_setup_regs(void) | 679 | static void __init prcm_setup_regs(void) |
678 | { | 680 | { |
681 | u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ? | ||
682 | OMAP3630_AUTO_UART4_MASK : 0; | ||
683 | u32 omap3630_en_uart4_mask = cpu_is_omap3630() ? | ||
684 | OMAP3630_EN_UART4_MASK : 0; | ||
685 | u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ? | ||
686 | OMAP3630_GRPSEL_UART4_MASK : 0; | ||
687 | |||
688 | |||
679 | /* XXX Reset all wkdeps. This should be done when initializing | 689 | /* XXX Reset all wkdeps. This should be done when initializing |
680 | * powerdomains */ | 690 | * powerdomains */ |
681 | prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); | 691 | prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); |
@@ -762,6 +772,7 @@ static void __init prcm_setup_regs(void) | |||
762 | CM_AUTOIDLE); | 772 | CM_AUTOIDLE); |
763 | 773 | ||
764 | cm_write_mod_reg( | 774 | cm_write_mod_reg( |
775 | omap3630_auto_uart4_mask | | ||
765 | OMAP3430_AUTO_GPIO6_MASK | | 776 | OMAP3430_AUTO_GPIO6_MASK | |
766 | OMAP3430_AUTO_GPIO5_MASK | | 777 | OMAP3430_AUTO_GPIO5_MASK | |
767 | OMAP3430_AUTO_GPIO4_MASK | | 778 | OMAP3430_AUTO_GPIO4_MASK | |
@@ -838,14 +849,16 @@ static void __init prcm_setup_regs(void) | |||
838 | OMAP3430_DSS_MOD, PM_WKEN); | 849 | OMAP3430_DSS_MOD, PM_WKEN); |
839 | 850 | ||
840 | /* Enable wakeups in PER */ | 851 | /* Enable wakeups in PER */ |
841 | prm_write_mod_reg(OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK | | 852 | prm_write_mod_reg(omap3630_en_uart4_mask | |
853 | OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK | | ||
842 | OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK | | 854 | OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK | |
843 | OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK | | 855 | OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK | |
844 | OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK | | 856 | OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK | |
845 | OMAP3430_EN_MCBSP4_MASK, | 857 | OMAP3430_EN_MCBSP4_MASK, |
846 | OMAP3430_PER_MOD, PM_WKEN); | 858 | OMAP3430_PER_MOD, PM_WKEN); |
847 | /* and allow them to wake up MPU */ | 859 | /* and allow them to wake up MPU */ |
848 | prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2_MASK | | 860 | prm_write_mod_reg(omap3630_grpsel_uart4_mask | |
861 | OMAP3430_GRPSEL_GPIO2_MASK | | ||
849 | OMAP3430_GRPSEL_GPIO3_MASK | | 862 | OMAP3430_GRPSEL_GPIO3_MASK | |
850 | OMAP3430_GRPSEL_GPIO4_MASK | | 863 | OMAP3430_GRPSEL_GPIO4_MASK | |
851 | OMAP3430_GRPSEL_GPIO5_MASK | | 864 | OMAP3430_GRPSEL_GPIO5_MASK | |
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 995b7edbf18d..298a22a754e2 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h | |||
@@ -382,6 +382,9 @@ | |||
382 | #define OMAP3430_EN_MPU_SHIFT 1 | 382 | #define OMAP3430_EN_MPU_SHIFT 1 |
383 | 383 | ||
384 | /* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */ | 384 | /* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */ |
385 | |||
386 | #define OMAP3630_EN_UART4_MASK (1 << 18) | ||
387 | #define OMAP3630_EN_UART4_SHIFT 18 | ||
385 | #define OMAP3430_EN_GPIO6_MASK (1 << 17) | 388 | #define OMAP3430_EN_GPIO6_MASK (1 << 17) |
386 | #define OMAP3430_EN_GPIO6_SHIFT 17 | 389 | #define OMAP3430_EN_GPIO6_SHIFT 17 |
387 | #define OMAP3430_EN_GPIO5_MASK (1 << 16) | 390 | #define OMAP3430_EN_GPIO5_MASK (1 << 16) |
@@ -422,6 +425,8 @@ | |||
422 | #define OMAP3430_EN_MCBSP2_SHIFT 0 | 425 | #define OMAP3430_EN_MCBSP2_SHIFT 0 |
423 | 426 | ||
424 | /* CM_IDLEST_PER, PM_WKST_PER shared bits */ | 427 | /* CM_IDLEST_PER, PM_WKST_PER shared bits */ |
428 | #define OMAP3630_ST_UART4_SHIFT 18 | ||
429 | #define OMAP3630_ST_UART4_MASK (1 << 18) | ||
425 | #define OMAP3430_ST_GPIO6_SHIFT 17 | 430 | #define OMAP3430_ST_GPIO6_SHIFT 17 |
426 | #define OMAP3430_ST_GPIO6_MASK (1 << 17) | 431 | #define OMAP3430_ST_GPIO6_MASK (1 << 17) |
427 | #define OMAP3430_ST_GPIO5_SHIFT 16 | 432 | #define OMAP3430_ST_GPIO5_SHIFT 16 |
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index 7fd6023edf96..9e63cb743a97 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h | |||
@@ -122,6 +122,7 @@ | |||
122 | #define OMAP3430_MEMRETSTATE_MASK (1 << 8) | 122 | #define OMAP3430_MEMRETSTATE_MASK (1 << 8) |
123 | 123 | ||
124 | /* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */ | 124 | /* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */ |
125 | #define OMAP3630_GRPSEL_UART4_MASK (1 << 18) | ||
125 | #define OMAP3430_GRPSEL_GPIO6_MASK (1 << 17) | 126 | #define OMAP3430_GRPSEL_GPIO6_MASK (1 << 17) |
126 | #define OMAP3430_GRPSEL_GPIO5_MASK (1 << 16) | 127 | #define OMAP3430_GRPSEL_GPIO5_MASK (1 << 16) |
127 | #define OMAP3430_GRPSEL_GPIO4_MASK (1 << 15) | 128 | #define OMAP3430_GRPSEL_GPIO4_MASK (1 << 15) |
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 566e991ede81..0bcc9df0c034 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
@@ -19,19 +19,30 @@ | |||
19 | */ | 19 | */ |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/serial_8250.h> | ||
23 | #include <linux/serial_reg.h> | 22 | #include <linux/serial_reg.h> |
24 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
25 | #include <linux/io.h> | 24 | #include <linux/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/serial_8250.h> | ||
29 | #include <linux/pm_runtime.h> | ||
30 | |||
31 | #ifdef CONFIG_SERIAL_OMAP | ||
32 | #include <plat/omap-serial.h> | ||
33 | #endif | ||
27 | 34 | ||
28 | #include <plat/common.h> | 35 | #include <plat/common.h> |
29 | #include <plat/board.h> | 36 | #include <plat/board.h> |
30 | #include <plat/clock.h> | 37 | #include <plat/clock.h> |
31 | #include <plat/control.h> | 38 | #include <plat/control.h> |
39 | #include <plat/dma.h> | ||
40 | #include <plat/omap_hwmod.h> | ||
41 | #include <plat/omap_device.h> | ||
32 | 42 | ||
33 | #include "prm.h" | 43 | #include "prm.h" |
34 | #include "pm.h" | 44 | #include "pm.h" |
45 | #include "cm.h" | ||
35 | #include "prm-regbits-34xx.h" | 46 | #include "prm-regbits-34xx.h" |
36 | 47 | ||
37 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 | 48 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 |
@@ -48,6 +59,8 @@ | |||
48 | */ | 59 | */ |
49 | #define DEFAULT_TIMEOUT 0 | 60 | #define DEFAULT_TIMEOUT 0 |
50 | 61 | ||
62 | #define MAX_UART_HWMOD_NAME_LEN 16 | ||
63 | |||
51 | struct omap_uart_state { | 64 | struct omap_uart_state { |
52 | int num; | 65 | int num; |
53 | int can_sleep; | 66 | int can_sleep; |
@@ -58,14 +71,21 @@ struct omap_uart_state { | |||
58 | void __iomem *wk_en; | 71 | void __iomem *wk_en; |
59 | u32 wk_mask; | 72 | u32 wk_mask; |
60 | u32 padconf; | 73 | u32 padconf; |
74 | u32 dma_enabled; | ||
61 | 75 | ||
62 | struct clk *ick; | 76 | struct clk *ick; |
63 | struct clk *fck; | 77 | struct clk *fck; |
64 | int clocked; | 78 | int clocked; |
65 | 79 | ||
66 | struct plat_serial8250_port *p; | 80 | int irq; |
81 | int regshift; | ||
82 | int irqflags; | ||
83 | void __iomem *membase; | ||
84 | resource_size_t mapbase; | ||
85 | |||
67 | struct list_head node; | 86 | struct list_head node; |
68 | struct platform_device pdev; | 87 | struct omap_hwmod *oh; |
88 | struct platform_device *pdev; | ||
69 | 89 | ||
70 | u32 errata; | 90 | u32 errata; |
71 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) | 91 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) |
@@ -83,75 +103,47 @@ struct omap_uart_state { | |||
83 | }; | 103 | }; |
84 | 104 | ||
85 | static LIST_HEAD(uart_list); | 105 | static LIST_HEAD(uart_list); |
106 | static u8 num_uarts; | ||
86 | 107 | ||
87 | static struct plat_serial8250_port serial_platform_data0[] = { | 108 | /* |
88 | { | 109 | * Since these idle/enable hooks are used in the idle path itself |
89 | .irq = 72, | 110 | * which has interrupts disabled, use the non-locking versions of |
90 | .flags = UPF_BOOT_AUTOCONF, | 111 | * the hwmod enable/disable functions. |
91 | .iotype = UPIO_MEM, | 112 | */ |
92 | .regshift = 2, | 113 | static int uart_idle_hwmod(struct omap_device *od) |
93 | .uartclk = OMAP24XX_BASE_BAUD * 16, | 114 | { |
94 | }, { | 115 | _omap_hwmod_idle(od->hwmods[0]); |
95 | .flags = 0 | ||
96 | } | ||
97 | }; | ||
98 | 116 | ||
99 | static struct plat_serial8250_port serial_platform_data1[] = { | 117 | return 0; |
100 | { | 118 | } |
101 | .irq = 73, | ||
102 | .flags = UPF_BOOT_AUTOCONF, | ||
103 | .iotype = UPIO_MEM, | ||
104 | .regshift = 2, | ||
105 | .uartclk = OMAP24XX_BASE_BAUD * 16, | ||
106 | }, { | ||
107 | .flags = 0 | ||
108 | } | ||
109 | }; | ||
110 | 119 | ||
111 | static struct plat_serial8250_port serial_platform_data2[] = { | 120 | static int uart_enable_hwmod(struct omap_device *od) |
112 | { | 121 | { |
113 | .irq = 74, | 122 | _omap_hwmod_enable(od->hwmods[0]); |
114 | .flags = UPF_BOOT_AUTOCONF, | 123 | |
115 | .iotype = UPIO_MEM, | 124 | return 0; |
116 | .regshift = 2, | 125 | } |
117 | .uartclk = OMAP24XX_BASE_BAUD * 16, | ||
118 | }, { | ||
119 | .flags = 0 | ||
120 | } | ||
121 | }; | ||
122 | 126 | ||
123 | static struct plat_serial8250_port serial_platform_data3[] = { | 127 | static struct omap_device_pm_latency omap_uart_latency[] = { |
124 | { | 128 | { |
125 | .irq = 70, | 129 | .deactivate_func = uart_idle_hwmod, |
126 | .flags = UPF_BOOT_AUTOCONF, | 130 | .activate_func = uart_enable_hwmod, |
127 | .iotype = UPIO_MEM, | 131 | .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, |
128 | .regshift = 2, | 132 | }, |
129 | .uartclk = OMAP24XX_BASE_BAUD * 16, | ||
130 | }, { | ||
131 | .flags = 0 | ||
132 | } | ||
133 | }; | 133 | }; |
134 | 134 | ||
135 | void __init omap2_set_globals_uart(struct omap_globals *omap2_globals) | ||
136 | { | ||
137 | serial_platform_data0[0].mapbase = omap2_globals->uart1_phys; | ||
138 | serial_platform_data1[0].mapbase = omap2_globals->uart2_phys; | ||
139 | serial_platform_data2[0].mapbase = omap2_globals->uart3_phys; | ||
140 | serial_platform_data3[0].mapbase = omap2_globals->uart4_phys; | ||
141 | } | ||
142 | |||
143 | static inline unsigned int __serial_read_reg(struct uart_port *up, | 135 | static inline unsigned int __serial_read_reg(struct uart_port *up, |
144 | int offset) | 136 | int offset) |
145 | { | 137 | { |
146 | offset <<= up->regshift; | 138 | offset <<= up->regshift; |
147 | return (unsigned int)__raw_readb(up->membase + offset); | 139 | return (unsigned int)__raw_readb(up->membase + offset); |
148 | } | 140 | } |
149 | 141 | ||
150 | static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, | 142 | static inline unsigned int serial_read_reg(struct omap_uart_state *uart, |
151 | int offset) | 143 | int offset) |
152 | { | 144 | { |
153 | offset <<= up->regshift; | 145 | offset <<= uart->regshift; |
154 | return (unsigned int)__raw_readb(up->membase + offset); | 146 | return (unsigned int)__raw_readb(uart->membase + offset); |
155 | } | 147 | } |
156 | 148 | ||
157 | static inline void __serial_write_reg(struct uart_port *up, int offset, | 149 | static inline void __serial_write_reg(struct uart_port *up, int offset, |
@@ -161,11 +153,11 @@ static inline void __serial_write_reg(struct uart_port *up, int offset, | |||
161 | __raw_writeb(value, up->membase + offset); | 153 | __raw_writeb(value, up->membase + offset); |
162 | } | 154 | } |
163 | 155 | ||
164 | static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, | 156 | static inline void serial_write_reg(struct omap_uart_state *uart, int offset, |
165 | int value) | 157 | int value) |
166 | { | 158 | { |
167 | offset <<= p->regshift; | 159 | offset <<= uart->regshift; |
168 | __raw_writeb(value, p->membase + offset); | 160 | __raw_writeb(value, uart->membase + offset); |
169 | } | 161 | } |
170 | 162 | ||
171 | /* | 163 | /* |
@@ -173,14 +165,12 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, | |||
173 | * properly. Note that the TX watermark initialization may not be needed | 165 | * properly. Note that the TX watermark initialization may not be needed |
174 | * once the 8250.c watermark handling code is merged. | 166 | * once the 8250.c watermark handling code is merged. |
175 | */ | 167 | */ |
168 | |||
176 | static inline void __init omap_uart_reset(struct omap_uart_state *uart) | 169 | static inline void __init omap_uart_reset(struct omap_uart_state *uart) |
177 | { | 170 | { |
178 | struct plat_serial8250_port *p = uart->p; | 171 | serial_write_reg(uart, UART_OMAP_MDR1, 0x07); |
179 | 172 | serial_write_reg(uart, UART_OMAP_SCR, 0x08); | |
180 | serial_write_reg(p, UART_OMAP_MDR1, 0x07); | 173 | serial_write_reg(uart, UART_OMAP_MDR1, 0x00); |
181 | serial_write_reg(p, UART_OMAP_SCR, 0x08); | ||
182 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); | ||
183 | serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); | ||
184 | } | 174 | } |
185 | 175 | ||
186 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) | 176 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) |
@@ -197,24 +187,23 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart) | |||
197 | static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val, | 187 | static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val, |
198 | u8 fcr_val) | 188 | u8 fcr_val) |
199 | { | 189 | { |
200 | struct plat_serial8250_port *p = uart->p; | ||
201 | u8 timeout = 255; | 190 | u8 timeout = 255; |
202 | 191 | ||
203 | serial_write_reg(p, UART_OMAP_MDR1, mdr1_val); | 192 | serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val); |
204 | udelay(2); | 193 | udelay(2); |
205 | serial_write_reg(p, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT | | 194 | serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT | |
206 | UART_FCR_CLEAR_RCVR); | 195 | UART_FCR_CLEAR_RCVR); |
207 | /* | 196 | /* |
208 | * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and | 197 | * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and |
209 | * TX_FIFO_E bit is 1. | 198 | * TX_FIFO_E bit is 1. |
210 | */ | 199 | */ |
211 | while (UART_LSR_THRE != (serial_read_reg(p, UART_LSR) & | 200 | while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) & |
212 | (UART_LSR_THRE | UART_LSR_DR))) { | 201 | (UART_LSR_THRE | UART_LSR_DR))) { |
213 | timeout--; | 202 | timeout--; |
214 | if (!timeout) { | 203 | if (!timeout) { |
215 | /* Should *never* happen. we warn and carry on */ | 204 | /* Should *never* happen. we warn and carry on */ |
216 | dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n", | 205 | dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n", |
217 | serial_read_reg(p, UART_LSR)); | 206 | serial_read_reg(uart, UART_LSR)); |
218 | break; | 207 | break; |
219 | } | 208 | } |
220 | udelay(1); | 209 | udelay(1); |
@@ -224,23 +213,22 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val, | |||
224 | static void omap_uart_save_context(struct omap_uart_state *uart) | 213 | static void omap_uart_save_context(struct omap_uart_state *uart) |
225 | { | 214 | { |
226 | u16 lcr = 0; | 215 | u16 lcr = 0; |
227 | struct plat_serial8250_port *p = uart->p; | ||
228 | 216 | ||
229 | if (!enable_off_mode) | 217 | if (!enable_off_mode) |
230 | return; | 218 | return; |
231 | 219 | ||
232 | lcr = serial_read_reg(p, UART_LCR); | 220 | lcr = serial_read_reg(uart, UART_LCR); |
233 | serial_write_reg(p, UART_LCR, 0xBF); | 221 | serial_write_reg(uart, UART_LCR, 0xBF); |
234 | uart->dll = serial_read_reg(p, UART_DLL); | 222 | uart->dll = serial_read_reg(uart, UART_DLL); |
235 | uart->dlh = serial_read_reg(p, UART_DLM); | 223 | uart->dlh = serial_read_reg(uart, UART_DLM); |
236 | serial_write_reg(p, UART_LCR, lcr); | 224 | serial_write_reg(uart, UART_LCR, lcr); |
237 | uart->ier = serial_read_reg(p, UART_IER); | 225 | uart->ier = serial_read_reg(uart, UART_IER); |
238 | uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); | 226 | uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); |
239 | uart->scr = serial_read_reg(p, UART_OMAP_SCR); | 227 | uart->scr = serial_read_reg(uart, UART_OMAP_SCR); |
240 | uart->wer = serial_read_reg(p, UART_OMAP_WER); | 228 | uart->wer = serial_read_reg(uart, UART_OMAP_WER); |
241 | serial_write_reg(p, UART_LCR, 0x80); | 229 | serial_write_reg(uart, UART_LCR, 0x80); |
242 | uart->mcr = serial_read_reg(p, UART_MCR); | 230 | uart->mcr = serial_read_reg(uart, UART_MCR); |
243 | serial_write_reg(p, UART_LCR, lcr); | 231 | serial_write_reg(uart, UART_LCR, lcr); |
244 | 232 | ||
245 | uart->context_valid = 1; | 233 | uart->context_valid = 1; |
246 | } | 234 | } |
@@ -248,7 +236,6 @@ static void omap_uart_save_context(struct omap_uart_state *uart) | |||
248 | static void omap_uart_restore_context(struct omap_uart_state *uart) | 236 | static void omap_uart_restore_context(struct omap_uart_state *uart) |
249 | { | 237 | { |
250 | u16 efr = 0; | 238 | u16 efr = 0; |
251 | struct plat_serial8250_port *p = uart->p; | ||
252 | 239 | ||
253 | if (!enable_off_mode) | 240 | if (!enable_off_mode) |
254 | return; | 241 | return; |
@@ -261,29 +248,30 @@ static void omap_uart_restore_context(struct omap_uart_state *uart) | |||
261 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) | 248 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) |
262 | omap_uart_mdr1_errataset(uart, 0x07, 0xA0); | 249 | omap_uart_mdr1_errataset(uart, 0x07, 0xA0); |
263 | else | 250 | else |
264 | serial_write_reg(p, UART_OMAP_MDR1, 0x7); | 251 | serial_write_reg(uart, UART_OMAP_MDR1, 0x7); |
265 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | 252 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ |
266 | efr = serial_read_reg(p, UART_EFR); | 253 | efr = serial_read_reg(uart, UART_EFR); |
267 | serial_write_reg(p, UART_EFR, UART_EFR_ECB); | 254 | serial_write_reg(uart, UART_EFR, UART_EFR_ECB); |
268 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ | 255 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ |
269 | serial_write_reg(p, UART_IER, 0x0); | 256 | serial_write_reg(uart, UART_IER, 0x0); |
270 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | 257 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ |
271 | serial_write_reg(p, UART_DLL, uart->dll); | 258 | serial_write_reg(uart, UART_DLL, uart->dll); |
272 | serial_write_reg(p, UART_DLM, uart->dlh); | 259 | serial_write_reg(uart, UART_DLM, uart->dlh); |
273 | serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ | 260 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ |
274 | serial_write_reg(p, UART_IER, uart->ier); | 261 | serial_write_reg(uart, UART_IER, uart->ier); |
275 | serial_write_reg(p, UART_LCR, 0x80); | 262 | serial_write_reg(uart, UART_LCR, 0x80); |
276 | serial_write_reg(p, UART_MCR, uart->mcr); | 263 | serial_write_reg(uart, UART_MCR, uart->mcr); |
277 | serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ | 264 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ |
278 | serial_write_reg(p, UART_EFR, efr); | 265 | serial_write_reg(uart, UART_EFR, efr); |
279 | serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); | 266 | serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); |
280 | serial_write_reg(p, UART_OMAP_SCR, uart->scr); | 267 | serial_write_reg(uart, UART_OMAP_SCR, uart->scr); |
281 | serial_write_reg(p, UART_OMAP_WER, uart->wer); | 268 | serial_write_reg(uart, UART_OMAP_WER, uart->wer); |
282 | serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); | 269 | serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); |
283 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) | 270 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) |
284 | omap_uart_mdr1_errataset(uart, 0x00, 0xA1); | 271 | omap_uart_mdr1_errataset(uart, 0x00, 0xA1); |
285 | else | 272 | else |
286 | serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ | 273 | /* UART 16x mode */ |
274 | serial_write_reg(uart, UART_OMAP_MDR1, 0x00); | ||
287 | } | 275 | } |
288 | #else | 276 | #else |
289 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} | 277 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} |
@@ -295,8 +283,7 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) | |||
295 | if (uart->clocked) | 283 | if (uart->clocked) |
296 | return; | 284 | return; |
297 | 285 | ||
298 | clk_enable(uart->ick); | 286 | omap_device_enable(uart->pdev); |
299 | clk_enable(uart->fck); | ||
300 | uart->clocked = 1; | 287 | uart->clocked = 1; |
301 | omap_uart_restore_context(uart); | 288 | omap_uart_restore_context(uart); |
302 | } | 289 | } |
@@ -310,8 +297,7 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) | |||
310 | 297 | ||
311 | omap_uart_save_context(uart); | 298 | omap_uart_save_context(uart); |
312 | uart->clocked = 0; | 299 | uart->clocked = 0; |
313 | clk_disable(uart->ick); | 300 | omap_device_idle(uart->pdev); |
314 | clk_disable(uart->fck); | ||
315 | } | 301 | } |
316 | 302 | ||
317 | static void omap_uart_enable_wakeup(struct omap_uart_state *uart) | 303 | static void omap_uart_enable_wakeup(struct omap_uart_state *uart) |
@@ -349,18 +335,24 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart) | |||
349 | } | 335 | } |
350 | 336 | ||
351 | static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, | 337 | static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, |
352 | int enable) | 338 | int enable) |
353 | { | 339 | { |
354 | struct plat_serial8250_port *p = uart->p; | 340 | u8 idlemode; |
355 | u16 sysc; | ||
356 | 341 | ||
357 | sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7; | 342 | if (enable) { |
358 | if (enable) | 343 | /** |
359 | sysc |= 0x2 << 3; | 344 | * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests |
360 | else | 345 | * in Smartidle Mode When Configured for DMA Operations. |
361 | sysc |= 0x1 << 3; | 346 | */ |
347 | if (uart->dma_enabled) | ||
348 | idlemode = HWMOD_IDLEMODE_FORCE; | ||
349 | else | ||
350 | idlemode = HWMOD_IDLEMODE_SMART; | ||
351 | } else { | ||
352 | idlemode = HWMOD_IDLEMODE_NO; | ||
353 | } | ||
362 | 354 | ||
363 | serial_write_reg(p, UART_OMAP_SYSC, sysc); | 355 | omap_hwmod_set_slave_idlemode(uart->oh, idlemode); |
364 | } | 356 | } |
365 | 357 | ||
366 | static void omap_uart_block_sleep(struct omap_uart_state *uart) | 358 | static void omap_uart_block_sleep(struct omap_uart_state *uart) |
@@ -377,7 +369,7 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart) | |||
377 | 369 | ||
378 | static void omap_uart_allow_sleep(struct omap_uart_state *uart) | 370 | static void omap_uart_allow_sleep(struct omap_uart_state *uart) |
379 | { | 371 | { |
380 | if (device_may_wakeup(&uart->pdev.dev)) | 372 | if (device_may_wakeup(&uart->pdev->dev)) |
381 | omap_uart_enable_wakeup(uart); | 373 | omap_uart_enable_wakeup(uart); |
382 | else | 374 | else |
383 | omap_uart_disable_wakeup(uart); | 375 | omap_uart_disable_wakeup(uart); |
@@ -472,6 +464,7 @@ int omap_uart_can_sleep(void) | |||
472 | * UART will not idle or sleep for its timeout period. | 464 | * UART will not idle or sleep for its timeout period. |
473 | * | 465 | * |
474 | **/ | 466 | **/ |
467 | /* static int first_interrupt; */ | ||
475 | static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) | 468 | static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) |
476 | { | 469 | { |
477 | struct omap_uart_state *uart = dev_id; | 470 | struct omap_uart_state *uart = dev_id; |
@@ -483,7 +476,6 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) | |||
483 | 476 | ||
484 | static void omap_uart_idle_init(struct omap_uart_state *uart) | 477 | static void omap_uart_idle_init(struct omap_uart_state *uart) |
485 | { | 478 | { |
486 | struct plat_serial8250_port *p = uart->p; | ||
487 | int ret; | 479 | int ret; |
488 | 480 | ||
489 | uart->can_sleep = 0; | 481 | uart->can_sleep = 0; |
@@ -495,7 +487,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
495 | omap_uart_smart_idle_enable(uart, 0); | 487 | omap_uart_smart_idle_enable(uart, 0); |
496 | 488 | ||
497 | if (cpu_is_omap34xx()) { | 489 | if (cpu_is_omap34xx()) { |
498 | u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD; | 490 | u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD; |
499 | u32 wk_mask = 0; | 491 | u32 wk_mask = 0; |
500 | u32 padconf = 0; | 492 | u32 padconf = 0; |
501 | 493 | ||
@@ -514,6 +506,10 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
514 | wk_mask = OMAP3430_ST_UART3_MASK; | 506 | wk_mask = OMAP3430_ST_UART3_MASK; |
515 | padconf = 0x19e; | 507 | padconf = 0x19e; |
516 | break; | 508 | break; |
509 | case 3: | ||
510 | wk_mask = OMAP3630_ST_UART4_MASK; | ||
511 | padconf = 0x0d2; | ||
512 | break; | ||
517 | } | 513 | } |
518 | uart->wk_mask = wk_mask; | 514 | uart->wk_mask = wk_mask; |
519 | uart->padconf = padconf; | 515 | uart->padconf = padconf; |
@@ -546,9 +542,9 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
546 | uart->padconf = 0; | 542 | uart->padconf = 0; |
547 | } | 543 | } |
548 | 544 | ||
549 | p->irqflags |= IRQF_SHARED; | 545 | uart->irqflags |= IRQF_SHARED; |
550 | ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, | 546 | ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt, |
551 | "serial idle", (void *)uart); | 547 | IRQF_SHARED, "serial idle", (void *)uart); |
552 | WARN_ON(ret); | 548 | WARN_ON(ret); |
553 | } | 549 | } |
554 | 550 | ||
@@ -558,11 +554,17 @@ void omap_uart_enable_irqs(int enable) | |||
558 | struct omap_uart_state *uart; | 554 | struct omap_uart_state *uart; |
559 | 555 | ||
560 | list_for_each_entry(uart, &uart_list, node) { | 556 | list_for_each_entry(uart, &uart_list, node) { |
561 | if (enable) | 557 | if (enable) { |
562 | ret = request_irq(uart->p->irq, omap_uart_interrupt, | 558 | pm_runtime_put_sync(&uart->pdev->dev); |
563 | IRQF_SHARED, "serial idle", (void *)uart); | 559 | ret = request_threaded_irq(uart->irq, NULL, |
564 | else | 560 | omap_uart_interrupt, |
565 | free_irq(uart->p->irq, (void *)uart); | 561 | IRQF_SHARED, |
562 | "serial idle", | ||
563 | (void *)uart); | ||
564 | } else { | ||
565 | pm_runtime_get_noresume(&uart->pdev->dev); | ||
566 | free_irq(uart->irq, (void *)uart); | ||
567 | } | ||
566 | } | 568 | } |
567 | } | 569 | } |
568 | 570 | ||
@@ -570,10 +572,9 @@ static ssize_t sleep_timeout_show(struct device *dev, | |||
570 | struct device_attribute *attr, | 572 | struct device_attribute *attr, |
571 | char *buf) | 573 | char *buf) |
572 | { | 574 | { |
573 | struct platform_device *pdev = container_of(dev, | 575 | struct platform_device *pdev = to_platform_device(dev); |
574 | struct platform_device, dev); | 576 | struct omap_device *odev = to_omap_device(pdev); |
575 | struct omap_uart_state *uart = container_of(pdev, | 577 | struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; |
576 | struct omap_uart_state, pdev); | ||
577 | 578 | ||
578 | return sprintf(buf, "%u\n", uart->timeout / HZ); | 579 | return sprintf(buf, "%u\n", uart->timeout / HZ); |
579 | } | 580 | } |
@@ -582,10 +583,9 @@ static ssize_t sleep_timeout_store(struct device *dev, | |||
582 | struct device_attribute *attr, | 583 | struct device_attribute *attr, |
583 | const char *buf, size_t n) | 584 | const char *buf, size_t n) |
584 | { | 585 | { |
585 | struct platform_device *pdev = container_of(dev, | 586 | struct platform_device *pdev = to_platform_device(dev); |
586 | struct platform_device, dev); | 587 | struct omap_device *odev = to_omap_device(pdev); |
587 | struct omap_uart_state *uart = container_of(pdev, | 588 | struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; |
588 | struct omap_uart_state, pdev); | ||
589 | unsigned int value; | 589 | unsigned int value; |
590 | 590 | ||
591 | if (sscanf(buf, "%u", &value) != 1) { | 591 | if (sscanf(buf, "%u", &value) != 1) { |
@@ -608,48 +608,11 @@ static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, | |||
608 | #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) | 608 | #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) |
609 | #else | 609 | #else |
610 | static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} | 610 | static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} |
611 | static void omap_uart_block_sleep(struct omap_uart_state *uart) {} | ||
611 | #define DEV_CREATE_FILE(dev, attr) | 612 | #define DEV_CREATE_FILE(dev, attr) |
612 | #endif /* CONFIG_PM */ | 613 | #endif /* CONFIG_PM */ |
613 | 614 | ||
614 | static struct omap_uart_state omap_uart[] = { | 615 | #ifndef CONFIG_SERIAL_OMAP |
615 | { | ||
616 | .pdev = { | ||
617 | .name = "serial8250", | ||
618 | .id = PLAT8250_DEV_PLATFORM, | ||
619 | .dev = { | ||
620 | .platform_data = serial_platform_data0, | ||
621 | }, | ||
622 | }, | ||
623 | }, { | ||
624 | .pdev = { | ||
625 | .name = "serial8250", | ||
626 | .id = PLAT8250_DEV_PLATFORM1, | ||
627 | .dev = { | ||
628 | .platform_data = serial_platform_data1, | ||
629 | }, | ||
630 | }, | ||
631 | }, { | ||
632 | .pdev = { | ||
633 | .name = "serial8250", | ||
634 | .id = PLAT8250_DEV_PLATFORM2, | ||
635 | .dev = { | ||
636 | .platform_data = serial_platform_data2, | ||
637 | }, | ||
638 | }, | ||
639 | }, | ||
640 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) | ||
641 | { | ||
642 | .pdev = { | ||
643 | .name = "serial8250", | ||
644 | .id = 3, | ||
645 | .dev = { | ||
646 | .platform_data = serial_platform_data3, | ||
647 | }, | ||
648 | }, | ||
649 | }, | ||
650 | #endif | ||
651 | }; | ||
652 | |||
653 | /* | 616 | /* |
654 | * Override the default 8250 read handler: mem_serial_in() | 617 | * Override the default 8250 read handler: mem_serial_in() |
655 | * Empty RX fifo read causes an abort on omap3630 and omap4 | 618 | * Empty RX fifo read causes an abort on omap3630 and omap4 |
@@ -682,71 +645,44 @@ static void serial_out_override(struct uart_port *up, int offset, int value) | |||
682 | } | 645 | } |
683 | __serial_write_reg(up, offset, value); | 646 | __serial_write_reg(up, offset, value); |
684 | } | 647 | } |
648 | #endif | ||
649 | |||
685 | void __init omap_serial_early_init(void) | 650 | void __init omap_serial_early_init(void) |
686 | { | 651 | { |
687 | int i, nr_ports; | 652 | int i = 0; |
688 | char name[16]; | ||
689 | 653 | ||
690 | if (!(cpu_is_omap3630() || cpu_is_omap4430())) | 654 | do { |
691 | nr_ports = 3; | 655 | char oh_name[MAX_UART_HWMOD_NAME_LEN]; |
692 | else | 656 | struct omap_hwmod *oh; |
693 | nr_ports = ARRAY_SIZE(omap_uart); | 657 | struct omap_uart_state *uart; |
694 | 658 | ||
695 | /* | 659 | snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, |
696 | * Make sure the serial ports are muxed on at this point. | 660 | "uart%d", i + 1); |
697 | * You have to mux them off in device drivers later on | 661 | oh = omap_hwmod_lookup(oh_name); |
698 | * if not needed. | 662 | if (!oh) |
699 | */ | 663 | break; |
700 | 664 | ||
701 | for (i = 0; i < nr_ports; i++) { | 665 | uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL); |
702 | struct omap_uart_state *uart = &omap_uart[i]; | 666 | if (WARN_ON(!uart)) |
703 | struct platform_device *pdev = &uart->pdev; | 667 | return; |
704 | struct device *dev = &pdev->dev; | 668 | |
705 | struct plat_serial8250_port *p = dev->platform_data; | 669 | uart->oh = oh; |
670 | uart->num = i++; | ||
671 | list_add_tail(&uart->node, &uart_list); | ||
672 | num_uarts++; | ||
706 | 673 | ||
707 | /* Don't map zero-based physical address */ | ||
708 | if (p->mapbase == 0) { | ||
709 | dev_warn(dev, "no physical address for uart#%d," | ||
710 | " so skipping early_init...\n", i); | ||
711 | continue; | ||
712 | } | ||
713 | /* | 674 | /* |
714 | * Module 4KB + L4 interconnect 4KB | 675 | * NOTE: omap_hwmod_init() has not yet been called, |
715 | * Static mapping, never released | 676 | * so no hwmod functions will work yet. |
716 | */ | 677 | */ |
717 | p->membase = ioremap(p->mapbase, SZ_8K); | ||
718 | if (!p->membase) { | ||
719 | dev_err(dev, "ioremap failed for uart%i\n", i + 1); | ||
720 | continue; | ||
721 | } | ||
722 | |||
723 | sprintf(name, "uart%d_ick", i + 1); | ||
724 | uart->ick = clk_get(NULL, name); | ||
725 | if (IS_ERR(uart->ick)) { | ||
726 | dev_err(dev, "Could not get uart%d_ick\n", i + 1); | ||
727 | uart->ick = NULL; | ||
728 | } | ||
729 | |||
730 | sprintf(name, "uart%d_fck", i+1); | ||
731 | uart->fck = clk_get(NULL, name); | ||
732 | if (IS_ERR(uart->fck)) { | ||
733 | dev_err(dev, "Could not get uart%d_fck\n", i + 1); | ||
734 | uart->fck = NULL; | ||
735 | } | ||
736 | |||
737 | /* FIXME: Remove this once the clkdev is ready */ | ||
738 | if (!cpu_is_omap44xx()) { | ||
739 | if (!uart->ick || !uart->fck) | ||
740 | continue; | ||
741 | } | ||
742 | |||
743 | uart->num = i; | ||
744 | p->private_data = uart; | ||
745 | uart->p = p; | ||
746 | 678 | ||
747 | if (cpu_is_omap44xx()) | 679 | /* |
748 | p->irq += 32; | 680 | * During UART early init, device need to be probed |
749 | } | 681 | * to determine SoC specific init before omap_device |
682 | * is ready. Therefore, don't allow idle here | ||
683 | */ | ||
684 | uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; | ||
685 | } while (1); | ||
750 | } | 686 | } |
751 | 687 | ||
752 | /** | 688 | /** |
@@ -763,53 +699,135 @@ void __init omap_serial_early_init(void) | |||
763 | void __init omap_serial_init_port(int port) | 699 | void __init omap_serial_init_port(int port) |
764 | { | 700 | { |
765 | struct omap_uart_state *uart; | 701 | struct omap_uart_state *uart; |
766 | struct platform_device *pdev; | 702 | struct omap_hwmod *oh; |
767 | struct device *dev; | 703 | struct omap_device *od; |
768 | 704 | void *pdata = NULL; | |
769 | BUG_ON(port < 0); | 705 | u32 pdata_size = 0; |
770 | BUG_ON(port >= ARRAY_SIZE(omap_uart)); | 706 | char *name; |
771 | 707 | #ifndef CONFIG_SERIAL_OMAP | |
772 | uart = &omap_uart[port]; | 708 | struct plat_serial8250_port ports[2] = { |
773 | pdev = &uart->pdev; | 709 | {}, |
774 | dev = &pdev->dev; | 710 | {.flags = 0}, |
711 | }; | ||
712 | struct plat_serial8250_port *p = &ports[0]; | ||
713 | #else | ||
714 | struct omap_uart_port_info omap_up; | ||
715 | #endif | ||
775 | 716 | ||
776 | /* Don't proceed if there's no clocks available */ | 717 | if (WARN_ON(port < 0)) |
777 | if (unlikely(!uart->ick || !uart->fck)) { | 718 | return; |
778 | WARN(1, "%s: can't init uart%d, no clocks available\n", | 719 | if (WARN_ON(port >= num_uarts)) |
779 | kobject_name(&dev->kobj), port); | ||
780 | return; | 720 | return; |
781 | } | ||
782 | |||
783 | omap_uart_enable_clocks(uart); | ||
784 | |||
785 | omap_uart_reset(uart); | ||
786 | omap_uart_idle_init(uart); | ||
787 | 721 | ||
788 | list_add_tail(&uart->node, &uart_list); | 722 | list_for_each_entry(uart, &uart_list, node) |
723 | if (port == uart->num) | ||
724 | break; | ||
789 | 725 | ||
790 | if (WARN_ON(platform_device_register(pdev))) | 726 | oh = uart->oh; |
791 | return; | 727 | uart->dma_enabled = 0; |
728 | #ifndef CONFIG_SERIAL_OMAP | ||
729 | name = "serial8250"; | ||
792 | 730 | ||
793 | if ((cpu_is_omap34xx() && uart->padconf) || | 731 | /* |
794 | (uart->wk_en && uart->wk_mask)) { | 732 | * !! 8250 driver does not use standard IORESOURCE* It |
795 | device_init_wakeup(dev, true); | 733 | * has it's own custom pdata that can be taken from |
796 | DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); | 734 | * the hwmod resource data. But, this needs to be |
797 | } | 735 | * done after the build. |
736 | * | ||
737 | * ?? does it have to be done before the register ?? | ||
738 | * YES, because platform_device_data_add() copies | ||
739 | * pdata, it does not use a pointer. | ||
740 | */ | ||
741 | p->flags = UPF_BOOT_AUTOCONF; | ||
742 | p->iotype = UPIO_MEM; | ||
743 | p->regshift = 2; | ||
744 | p->uartclk = OMAP24XX_BASE_BAUD * 16; | ||
745 | p->irq = oh->mpu_irqs[0].irq; | ||
746 | p->mapbase = oh->slaves[0]->addr->pa_start; | ||
747 | p->membase = omap_hwmod_get_mpu_rt_va(oh); | ||
748 | p->irqflags = IRQF_SHARED; | ||
749 | p->private_data = uart; | ||
798 | 750 | ||
799 | /* | 751 | /* |
800 | * omap44xx: Never read empty UART fifo | 752 | * omap44xx: Never read empty UART fifo |
801 | * omap3xxx: Never read empty UART fifo on UARTs | 753 | * omap3xxx: Never read empty UART fifo on UARTs |
802 | * with IP rev >=0x52 | 754 | * with IP rev >=0x52 |
803 | */ | 755 | */ |
756 | uart->regshift = p->regshift; | ||
757 | uart->membase = p->membase; | ||
804 | if (cpu_is_omap44xx()) | 758 | if (cpu_is_omap44xx()) |
805 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; | 759 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; |
806 | else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) | 760 | else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF) |
807 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) | 761 | >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) |
808 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; | 762 | uart->errata |= UART_ERRATA_FIFO_FULL_ABORT; |
809 | 763 | ||
810 | if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) { | 764 | if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) { |
811 | uart->p->serial_in = serial_in_override; | 765 | p->serial_in = serial_in_override; |
812 | uart->p->serial_out = serial_out_override; | 766 | p->serial_out = serial_out_override; |
767 | } | ||
768 | |||
769 | pdata = &ports[0]; | ||
770 | pdata_size = 2 * sizeof(struct plat_serial8250_port); | ||
771 | #else | ||
772 | |||
773 | name = DRIVER_NAME; | ||
774 | |||
775 | omap_up.dma_enabled = uart->dma_enabled; | ||
776 | omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; | ||
777 | omap_up.mapbase = oh->slaves[0]->addr->pa_start; | ||
778 | omap_up.membase = omap_hwmod_get_mpu_rt_va(oh); | ||
779 | omap_up.irqflags = IRQF_SHARED; | ||
780 | omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; | ||
781 | |||
782 | pdata = &omap_up; | ||
783 | pdata_size = sizeof(struct omap_uart_port_info); | ||
784 | #endif | ||
785 | |||
786 | if (WARN_ON(!oh)) | ||
787 | return; | ||
788 | |||
789 | od = omap_device_build(name, uart->num, oh, pdata, pdata_size, | ||
790 | omap_uart_latency, | ||
791 | ARRAY_SIZE(omap_uart_latency), false); | ||
792 | WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", | ||
793 | name, oh->name); | ||
794 | |||
795 | uart->irq = oh->mpu_irqs[0].irq; | ||
796 | uart->regshift = 2; | ||
797 | uart->mapbase = oh->slaves[0]->addr->pa_start; | ||
798 | uart->membase = omap_hwmod_get_mpu_rt_va(oh); | ||
799 | uart->pdev = &od->pdev; | ||
800 | |||
801 | oh->dev_attr = uart; | ||
802 | |||
803 | /* | ||
804 | * Because of early UART probing, UART did not get idled | ||
805 | * on init. Now that omap_device is ready, ensure full idle | ||
806 | * before doing omap_device_enable(). | ||
807 | */ | ||
808 | omap_hwmod_idle(uart->oh); | ||
809 | |||
810 | omap_device_enable(uart->pdev); | ||
811 | omap_uart_idle_init(uart); | ||
812 | omap_uart_reset(uart); | ||
813 | omap_hwmod_enable_wakeup(uart->oh); | ||
814 | omap_device_idle(uart->pdev); | ||
815 | |||
816 | /* | ||
817 | * Need to block sleep long enough for interrupt driven | ||
818 | * driver to start. Console driver is in polling mode | ||
819 | * so device needs to be kept enabled while polling driver | ||
820 | * is in use. | ||
821 | */ | ||
822 | if (uart->timeout) | ||
823 | uart->timeout = (30 * HZ); | ||
824 | omap_uart_block_sleep(uart); | ||
825 | uart->timeout = DEFAULT_TIMEOUT; | ||
826 | |||
827 | if ((cpu_is_omap34xx() && uart->padconf) || | ||
828 | (uart->wk_en && uart->wk_mask)) { | ||
829 | device_init_wakeup(&od->pdev.dev, true); | ||
830 | DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout); | ||
813 | } | 831 | } |
814 | 832 | ||
815 | /* Enable the MDR1 errata for OMAP3 */ | 833 | /* Enable the MDR1 errata for OMAP3 */ |
@@ -826,13 +844,8 @@ void __init omap_serial_init_port(int port) | |||
826 | */ | 844 | */ |
827 | void __init omap_serial_init(void) | 845 | void __init omap_serial_init(void) |
828 | { | 846 | { |
829 | int i, nr_ports; | 847 | struct omap_uart_state *uart; |
830 | |||
831 | if (!(cpu_is_omap3630() || cpu_is_omap4430())) | ||
832 | nr_ports = 3; | ||
833 | else | ||
834 | nr_ports = ARRAY_SIZE(omap_uart); | ||
835 | 848 | ||
836 | for (i = 0; i < nr_ports; i++) | 849 | list_for_each_entry(uart, &uart_list, node) |
837 | omap_serial_init_port(i); | 850 | omap_serial_init_port(uart->num); |
838 | } | 851 | } |
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 7d668b3b5363..947de3fb93f3 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -257,7 +257,6 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals) | |||
257 | omap2_set_globals_sdrc(omap2_globals); | 257 | omap2_set_globals_sdrc(omap2_globals); |
258 | omap2_set_globals_control(omap2_globals); | 258 | omap2_set_globals_control(omap2_globals); |
259 | omap2_set_globals_prcm(omap2_globals); | 259 | omap2_set_globals_prcm(omap2_globals); |
260 | omap2_set_globals_uart(omap2_globals); | ||
261 | } | 260 | } |
262 | 261 | ||
263 | #endif | 262 | #endif |
@@ -272,9 +271,6 @@ static struct omap_globals omap242x_globals = { | |||
272 | .ctrl = OMAP2420_CTRL_BASE, | 271 | .ctrl = OMAP2420_CTRL_BASE, |
273 | .prm = OMAP2420_PRM_BASE, | 272 | .prm = OMAP2420_PRM_BASE, |
274 | .cm = OMAP2420_CM_BASE, | 273 | .cm = OMAP2420_CM_BASE, |
275 | .uart1_phys = OMAP2_UART1_BASE, | ||
276 | .uart2_phys = OMAP2_UART2_BASE, | ||
277 | .uart3_phys = OMAP2_UART3_BASE, | ||
278 | }; | 274 | }; |
279 | 275 | ||
280 | void __init omap2_set_globals_242x(void) | 276 | void __init omap2_set_globals_242x(void) |
@@ -293,9 +289,6 @@ static struct omap_globals omap243x_globals = { | |||
293 | .ctrl = OMAP243X_CTRL_BASE, | 289 | .ctrl = OMAP243X_CTRL_BASE, |
294 | .prm = OMAP2430_PRM_BASE, | 290 | .prm = OMAP2430_PRM_BASE, |
295 | .cm = OMAP2430_CM_BASE, | 291 | .cm = OMAP2430_CM_BASE, |
296 | .uart1_phys = OMAP2_UART1_BASE, | ||
297 | .uart2_phys = OMAP2_UART2_BASE, | ||
298 | .uart3_phys = OMAP2_UART3_BASE, | ||
299 | }; | 292 | }; |
300 | 293 | ||
301 | void __init omap2_set_globals_243x(void) | 294 | void __init omap2_set_globals_243x(void) |
@@ -314,10 +307,6 @@ static struct omap_globals omap3_globals = { | |||
314 | .ctrl = OMAP343X_CTRL_BASE, | 307 | .ctrl = OMAP343X_CTRL_BASE, |
315 | .prm = OMAP3430_PRM_BASE, | 308 | .prm = OMAP3430_PRM_BASE, |
316 | .cm = OMAP3430_CM_BASE, | 309 | .cm = OMAP3430_CM_BASE, |
317 | .uart1_phys = OMAP3_UART1_BASE, | ||
318 | .uart2_phys = OMAP3_UART2_BASE, | ||
319 | .uart3_phys = OMAP3_UART3_BASE, | ||
320 | .uart4_phys = OMAP3_UART4_BASE, /* Only on 3630 */ | ||
321 | }; | 310 | }; |
322 | 311 | ||
323 | void __init omap2_set_globals_3xxx(void) | 312 | void __init omap2_set_globals_3xxx(void) |
@@ -341,10 +330,6 @@ static struct omap_globals omap4_globals = { | |||
341 | .prm = OMAP4430_PRM_BASE, | 330 | .prm = OMAP4430_PRM_BASE, |
342 | .cm = OMAP4430_CM_BASE, | 331 | .cm = OMAP4430_CM_BASE, |
343 | .cm2 = OMAP4430_CM2_BASE, | 332 | .cm2 = OMAP4430_CM2_BASE, |
344 | .uart1_phys = OMAP4_UART1_BASE, | ||
345 | .uart2_phys = OMAP4_UART2_BASE, | ||
346 | .uart3_phys = OMAP4_UART3_BASE, | ||
347 | .uart4_phys = OMAP4_UART4_BASE, | ||
348 | }; | 333 | }; |
349 | 334 | ||
350 | void __init omap2_set_globals_443x(void) | 335 | void __init omap2_set_globals_443x(void) |
@@ -352,7 +337,6 @@ void __init omap2_set_globals_443x(void) | |||
352 | omap2_set_globals_tap(&omap4_globals); | 337 | omap2_set_globals_tap(&omap4_globals); |
353 | omap2_set_globals_control(&omap4_globals); | 338 | omap2_set_globals_control(&omap4_globals); |
354 | omap2_set_globals_prcm(&omap4_globals); | 339 | omap2_set_globals_prcm(&omap4_globals); |
355 | omap2_set_globals_uart(&omap4_globals); | ||
356 | } | 340 | } |
357 | #endif | 341 | #endif |
358 | 342 | ||
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 2d8f98d7ae50..a9d69a09920d 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h | |||
@@ -67,7 +67,6 @@ void omap2_set_globals_tap(struct omap_globals *); | |||
67 | void omap2_set_globals_sdrc(struct omap_globals *); | 67 | void omap2_set_globals_sdrc(struct omap_globals *); |
68 | void omap2_set_globals_control(struct omap_globals *); | 68 | void omap2_set_globals_control(struct omap_globals *); |
69 | void omap2_set_globals_prcm(struct omap_globals *); | 69 | void omap2_set_globals_prcm(struct omap_globals *); |
70 | void omap2_set_globals_uart(struct omap_globals *); | ||
71 | 70 | ||
72 | void omap3_map_io(void); | 71 | void omap3_map_io(void); |
73 | 72 | ||
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index af3a03941add..098f154f5d41 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h | |||
@@ -319,6 +319,8 @@ | |||
319 | #define OMAP34XX_DMA_USIM_TX 79 /* S_DMA_78 */ | 319 | #define OMAP34XX_DMA_USIM_TX 79 /* S_DMA_78 */ |
320 | #define OMAP34XX_DMA_USIM_RX 80 /* S_DMA_79 */ | 320 | #define OMAP34XX_DMA_USIM_RX 80 /* S_DMA_79 */ |
321 | 321 | ||
322 | #define OMAP36XX_DMA_UART4_TX 81 /* S_DMA_80 */ | ||
323 | #define OMAP36XX_DMA_UART4_RX 82 /* S_DMA_81 */ | ||
322 | /*----------------------------------------------------------------------------*/ | 324 | /*----------------------------------------------------------------------------*/ |
323 | 325 | ||
324 | #define OMAP1_DMA_TOUT_IRQ (1 << 0) | 326 | #define OMAP1_DMA_TOUT_IRQ (1 << 0) |
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index c01d9f08a198..65e20a686713 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h | |||
@@ -345,6 +345,8 @@ | |||
345 | #define INT_34XX_MMC3_IRQ 94 | 345 | #define INT_34XX_MMC3_IRQ 94 |
346 | #define INT_34XX_GPT12_IRQ 95 | 346 | #define INT_34XX_GPT12_IRQ 95 |
347 | 347 | ||
348 | #define INT_36XX_UART4_IRQ 80 | ||
349 | |||
348 | #define INT_35XX_HECC0_IRQ 24 | 350 | #define INT_35XX_HECC0_IRQ 24 |
349 | #define INT_35XX_HECC1_IRQ 28 | 351 | #define INT_35XX_HECC1_IRQ 28 |
350 | #define INT_35XX_EMAC_C0_RXTHRESH_IRQ 67 | 352 | #define INT_35XX_EMAC_C0_RXTHRESH_IRQ 67 |
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h new file mode 100644 index 000000000000..0d6f076cf748 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/omap-serial.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Driver for OMAP-UART controller. | ||
3 | * Based on drivers/serial/8250.c | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Govindraj R <govindraj.raja@ti.com> | ||
9 | * Thara Gopinath <thara@ti.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #ifndef __OMAP_SERIAL_H__ | ||
18 | #define __OMAP_SERIAL_H__ | ||
19 | |||
20 | #include <linux/serial_core.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <plat/control.h> | ||
24 | #include <plat/mux.h> | ||
25 | |||
26 | #define DRIVER_NAME "omap-hsuart" | ||
27 | |||
28 | /* | ||
29 | * Use tty device name as ttyO, [O -> OMAP] | ||
30 | * in bootargs we specify as console=ttyO0 if uart1 | ||
31 | * is used as console uart. | ||
32 | */ | ||
33 | #define OMAP_SERIAL_NAME "ttyO" | ||
34 | |||
35 | #define OMAP_MDR1_DISABLE 0x07 | ||
36 | #define OMAP_MDR1_MODE13X 0x03 | ||
37 | #define OMAP_MDR1_MODE16X 0x00 | ||
38 | #define OMAP_MODE13X_SPEED 230400 | ||
39 | |||
40 | /* | ||
41 | * LCR = 0XBF: Switch to Configuration Mode B. | ||
42 | * In configuration mode b allow access | ||
43 | * to EFR,DLL,DLH. | ||
44 | * Reference OMAP TRM Chapter 17 | ||
45 | * Section: 1.4.3 Mode Selection | ||
46 | */ | ||
47 | #define OMAP_UART_LCR_CONF_MDB 0XBF | ||
48 | |||
49 | /* WER = 0x7F | ||
50 | * Enable module level wakeup in WER reg | ||
51 | */ | ||
52 | #define OMAP_UART_WER_MOD_WKUP 0X7F | ||
53 | |||
54 | /* Enable XON/XOFF flow control on output */ | ||
55 | #define OMAP_UART_SW_TX 0x04 | ||
56 | |||
57 | /* Enable XON/XOFF flow control on input */ | ||
58 | #define OMAP_UART_SW_RX 0x04 | ||
59 | |||
60 | #define OMAP_UART_SYSC_RESET 0X07 | ||
61 | #define OMAP_UART_TCR_TRIG 0X0F | ||
62 | #define OMAP_UART_SW_CLR 0XF0 | ||
63 | #define OMAP_UART_FIFO_CLR 0X06 | ||
64 | |||
65 | #define OMAP_UART_DMA_CH_FREE -1 | ||
66 | |||
67 | #define RX_TIMEOUT (3 * HZ) | ||
68 | #define OMAP_MAX_HSUART_PORTS 4 | ||
69 | |||
70 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | ||
71 | |||
72 | struct omap_uart_port_info { | ||
73 | bool dma_enabled; /* To specify DMA Mode */ | ||
74 | unsigned int uartclk; /* UART clock rate */ | ||
75 | void __iomem *membase; /* ioremap cookie or NULL */ | ||
76 | resource_size_t mapbase; /* resource base */ | ||
77 | unsigned long irqflags; /* request_irq flags */ | ||
78 | upf_t flags; /* UPF_* flags */ | ||
79 | }; | ||
80 | |||
81 | struct uart_omap_dma { | ||
82 | u8 uart_dma_tx; | ||
83 | u8 uart_dma_rx; | ||
84 | int rx_dma_channel; | ||
85 | int tx_dma_channel; | ||
86 | dma_addr_t rx_buf_dma_phys; | ||
87 | dma_addr_t tx_buf_dma_phys; | ||
88 | unsigned int uart_base; | ||
89 | /* | ||
90 | * Buffer for rx dma.It is not required for tx because the buffer | ||
91 | * comes from port structure. | ||
92 | */ | ||
93 | unsigned char *rx_buf; | ||
94 | unsigned int prev_rx_dma_pos; | ||
95 | int tx_buf_size; | ||
96 | int tx_dma_used; | ||
97 | int rx_dma_used; | ||
98 | spinlock_t tx_lock; | ||
99 | spinlock_t rx_lock; | ||
100 | /* timer to poll activity on rx dma */ | ||
101 | struct timer_list rx_timer; | ||
102 | int rx_buf_size; | ||
103 | int rx_timeout; | ||
104 | }; | ||
105 | |||
106 | struct uart_omap_port { | ||
107 | struct uart_port port; | ||
108 | struct uart_omap_dma uart_dma; | ||
109 | struct platform_device *pdev; | ||
110 | |||
111 | unsigned char ier; | ||
112 | unsigned char lcr; | ||
113 | unsigned char mcr; | ||
114 | unsigned char fcr; | ||
115 | unsigned char efr; | ||
116 | |||
117 | int use_dma; | ||
118 | /* | ||
119 | * Some bits in registers are cleared on a read, so they must | ||
120 | * be saved whenever the register is read but the bits will not | ||
121 | * be immediately processed. | ||
122 | */ | ||
123 | unsigned int lsr_break_flag; | ||
124 | unsigned char msr_saved_flags; | ||
125 | char name[20]; | ||
126 | unsigned long port_activity; | ||
127 | }; | ||
128 | |||
129 | #endif /* __OMAP_SERIAL_H__ */ | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 12900f7083b0..8d8b975ce784 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -1416,6 +1416,33 @@ config SERIAL_OF_PLATFORM | |||
1416 | Currently, only 8250 compatible ports are supported, but | 1416 | Currently, only 8250 compatible ports are supported, but |
1417 | others can easily be added. | 1417 | others can easily be added. |
1418 | 1418 | ||
1419 | config SERIAL_OMAP | ||
1420 | tristate "OMAP serial port support" | ||
1421 | depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4 | ||
1422 | select SERIAL_CORE | ||
1423 | help | ||
1424 | If you have a machine based on an Texas Instruments OMAP CPU you | ||
1425 | can enable its onboard serial ports by enabling this option. | ||
1426 | |||
1427 | By enabling this option you take advantage of dma feature available | ||
1428 | with the omap-serial driver. DMA support can be enabled from platform | ||
1429 | data. | ||
1430 | |||
1431 | config SERIAL_OMAP_CONSOLE | ||
1432 | bool "Console on OMAP serial port" | ||
1433 | depends on SERIAL_OMAP | ||
1434 | select SERIAL_CORE_CONSOLE | ||
1435 | help | ||
1436 | Select this option if you would like to use omap serial port as | ||
1437 | console. | ||
1438 | |||
1439 | Even if you say Y here, the currently visible virtual console | ||
1440 | (/dev/tty0) will still be used as the system console by default, but | ||
1441 | you can alter that using a kernel command line option such as | ||
1442 | "console=ttyOx". (Try "man bootparam" or see the documentation of | ||
1443 | your boot loader about how to pass options to the kernel at | ||
1444 | boot time.) | ||
1445 | |||
1419 | config SERIAL_OF_PLATFORM_NWPSERIAL | 1446 | config SERIAL_OF_PLATFORM_NWPSERIAL |
1420 | tristate "NWP serial port driver" | 1447 | tristate "NWP serial port driver" |
1421 | depends on PPC_OF && PPC_DCR | 1448 | depends on PPC_OF && PPC_DCR |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 1ca4fd599ffe..c5705765454f 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -88,3 +88,4 @@ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o | |||
88 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | 88 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o |
89 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o | 89 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o |
90 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o | 90 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o |
91 | obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o | ||
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c new file mode 100644 index 000000000000..2ee1d3282a8c --- /dev/null +++ b/drivers/serial/omap-serial.c | |||
@@ -0,0 +1,1333 @@ | |||
1 | /* | ||
2 | * Driver for OMAP-UART controller. | ||
3 | * Based on drivers/serial/8250.c | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Govindraj R <govindraj.raja@ti.com> | ||
9 | * Thara Gopinath <thara@ti.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * Note: This driver is made seperate from 8250 driver as we cannot | ||
17 | * over load 8250 driver with omap platform specific configuration for | ||
18 | * features like DMA, it makes easier to implement features like DMA and | ||
19 | * hardware flow control and software flow control configuration with | ||
20 | * this driver as required for the omap-platform. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/serial_reg.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/tty_flip.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/serial_core.h> | ||
35 | #include <linux/irq.h> | ||
36 | |||
37 | #include <plat/dma.h> | ||
38 | #include <plat/dmtimer.h> | ||
39 | #include <plat/omap-serial.h> | ||
40 | |||
41 | static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; | ||
42 | |||
43 | /* Forward declaration of functions */ | ||
44 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); | ||
45 | static void serial_omap_rx_timeout(unsigned long uart_no); | ||
46 | static int serial_omap_start_rxdma(struct uart_omap_port *up); | ||
47 | |||
48 | static inline unsigned int serial_in(struct uart_omap_port *up, int offset) | ||
49 | { | ||
50 | offset <<= up->port.regshift; | ||
51 | return readw(up->port.membase + offset); | ||
52 | } | ||
53 | |||
54 | static inline void serial_out(struct uart_omap_port *up, int offset, int value) | ||
55 | { | ||
56 | offset <<= up->port.regshift; | ||
57 | writew(value, up->port.membase + offset); | ||
58 | } | ||
59 | |||
60 | static inline void serial_omap_clear_fifos(struct uart_omap_port *up) | ||
61 | { | ||
62 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); | ||
63 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
64 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | ||
65 | serial_out(up, UART_FCR, 0); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * serial_omap_get_divisor - calculate divisor value | ||
70 | * @port: uart port info | ||
71 | * @baud: baudrate for which divisor needs to be calculated. | ||
72 | * | ||
73 | * We have written our own function to get the divisor so as to support | ||
74 | * 13x mode. 3Mbps Baudrate as an different divisor. | ||
75 | * Reference OMAP TRM Chapter 17: | ||
76 | * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates | ||
77 | * referring to oversampling - divisor value | ||
78 | * baudrate 460,800 to 3,686,400 all have divisor 13 | ||
79 | * except 3,000,000 which has divisor value 16 | ||
80 | */ | ||
81 | static unsigned int | ||
82 | serial_omap_get_divisor(struct uart_port *port, unsigned int baud) | ||
83 | { | ||
84 | unsigned int divisor; | ||
85 | |||
86 | if (baud > OMAP_MODE13X_SPEED && baud != 3000000) | ||
87 | divisor = 13; | ||
88 | else | ||
89 | divisor = 16; | ||
90 | return port->uartclk/(baud * divisor); | ||
91 | } | ||
92 | |||
93 | static void serial_omap_stop_rxdma(struct uart_omap_port *up) | ||
94 | { | ||
95 | if (up->uart_dma.rx_dma_used) { | ||
96 | del_timer(&up->uart_dma.rx_timer); | ||
97 | omap_stop_dma(up->uart_dma.rx_dma_channel); | ||
98 | omap_free_dma(up->uart_dma.rx_dma_channel); | ||
99 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | ||
100 | up->uart_dma.rx_dma_used = false; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static void serial_omap_enable_ms(struct uart_port *port) | ||
105 | { | ||
106 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
107 | |||
108 | dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id); | ||
109 | up->ier |= UART_IER_MSI; | ||
110 | serial_out(up, UART_IER, up->ier); | ||
111 | } | ||
112 | |||
113 | static void serial_omap_stop_tx(struct uart_port *port) | ||
114 | { | ||
115 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
116 | |||
117 | if (up->use_dma && | ||
118 | up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { | ||
119 | /* | ||
120 | * Check if dma is still active. If yes do nothing, | ||
121 | * return. Else stop dma | ||
122 | */ | ||
123 | if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel)) | ||
124 | return; | ||
125 | omap_stop_dma(up->uart_dma.tx_dma_channel); | ||
126 | omap_free_dma(up->uart_dma.tx_dma_channel); | ||
127 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; | ||
128 | } | ||
129 | |||
130 | if (up->ier & UART_IER_THRI) { | ||
131 | up->ier &= ~UART_IER_THRI; | ||
132 | serial_out(up, UART_IER, up->ier); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static void serial_omap_stop_rx(struct uart_port *port) | ||
137 | { | ||
138 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
139 | |||
140 | if (up->use_dma) | ||
141 | serial_omap_stop_rxdma(up); | ||
142 | up->ier &= ~UART_IER_RLSI; | ||
143 | up->port.read_status_mask &= ~UART_LSR_DR; | ||
144 | serial_out(up, UART_IER, up->ier); | ||
145 | } | ||
146 | |||
147 | static inline void receive_chars(struct uart_omap_port *up, int *status) | ||
148 | { | ||
149 | struct tty_struct *tty = up->port.state->port.tty; | ||
150 | unsigned int flag; | ||
151 | unsigned char ch, lsr = *status; | ||
152 | int max_count = 256; | ||
153 | |||
154 | do { | ||
155 | if (likely(lsr & UART_LSR_DR)) | ||
156 | ch = serial_in(up, UART_RX); | ||
157 | flag = TTY_NORMAL; | ||
158 | up->port.icount.rx++; | ||
159 | |||
160 | if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { | ||
161 | /* | ||
162 | * For statistics only | ||
163 | */ | ||
164 | if (lsr & UART_LSR_BI) { | ||
165 | lsr &= ~(UART_LSR_FE | UART_LSR_PE); | ||
166 | up->port.icount.brk++; | ||
167 | /* | ||
168 | * We do the SysRQ and SAK checking | ||
169 | * here because otherwise the break | ||
170 | * may get masked by ignore_status_mask | ||
171 | * or read_status_mask. | ||
172 | */ | ||
173 | if (uart_handle_break(&up->port)) | ||
174 | goto ignore_char; | ||
175 | } else if (lsr & UART_LSR_PE) { | ||
176 | up->port.icount.parity++; | ||
177 | } else if (lsr & UART_LSR_FE) { | ||
178 | up->port.icount.frame++; | ||
179 | } | ||
180 | |||
181 | if (lsr & UART_LSR_OE) | ||
182 | up->port.icount.overrun++; | ||
183 | |||
184 | /* | ||
185 | * Mask off conditions which should be ignored. | ||
186 | */ | ||
187 | lsr &= up->port.read_status_mask; | ||
188 | |||
189 | #ifdef CONFIG_SERIAL_OMAP_CONSOLE | ||
190 | if (up->port.line == up->port.cons->index) { | ||
191 | /* Recover the break flag from console xmit */ | ||
192 | lsr |= up->lsr_break_flag; | ||
193 | up->lsr_break_flag = 0; | ||
194 | } | ||
195 | #endif | ||
196 | if (lsr & UART_LSR_BI) | ||
197 | flag = TTY_BREAK; | ||
198 | else if (lsr & UART_LSR_PE) | ||
199 | flag = TTY_PARITY; | ||
200 | else if (lsr & UART_LSR_FE) | ||
201 | flag = TTY_FRAME; | ||
202 | } | ||
203 | |||
204 | if (uart_handle_sysrq_char(&up->port, ch)) | ||
205 | goto ignore_char; | ||
206 | uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); | ||
207 | ignore_char: | ||
208 | lsr = serial_in(up, UART_LSR); | ||
209 | } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); | ||
210 | spin_unlock(&up->port.lock); | ||
211 | tty_flip_buffer_push(tty); | ||
212 | spin_lock(&up->port.lock); | ||
213 | } | ||
214 | |||
215 | static void transmit_chars(struct uart_omap_port *up) | ||
216 | { | ||
217 | struct circ_buf *xmit = &up->port.state->xmit; | ||
218 | int count; | ||
219 | |||
220 | if (up->port.x_char) { | ||
221 | serial_out(up, UART_TX, up->port.x_char); | ||
222 | up->port.icount.tx++; | ||
223 | up->port.x_char = 0; | ||
224 | return; | ||
225 | } | ||
226 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | ||
227 | serial_omap_stop_tx(&up->port); | ||
228 | return; | ||
229 | } | ||
230 | count = up->port.fifosize / 4; | ||
231 | do { | ||
232 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | ||
233 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
234 | up->port.icount.tx++; | ||
235 | if (uart_circ_empty(xmit)) | ||
236 | break; | ||
237 | } while (--count > 0); | ||
238 | |||
239 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
240 | uart_write_wakeup(&up->port); | ||
241 | |||
242 | if (uart_circ_empty(xmit)) | ||
243 | serial_omap_stop_tx(&up->port); | ||
244 | } | ||
245 | |||
246 | static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) | ||
247 | { | ||
248 | if (!(up->ier & UART_IER_THRI)) { | ||
249 | up->ier |= UART_IER_THRI; | ||
250 | serial_out(up, UART_IER, up->ier); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static void serial_omap_start_tx(struct uart_port *port) | ||
255 | { | ||
256 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
257 | struct circ_buf *xmit; | ||
258 | unsigned int start; | ||
259 | int ret = 0; | ||
260 | |||
261 | if (!up->use_dma) { | ||
262 | serial_omap_enable_ier_thri(up); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | if (up->uart_dma.tx_dma_used) | ||
267 | return; | ||
268 | |||
269 | xmit = &up->port.state->xmit; | ||
270 | |||
271 | if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { | ||
272 | ret = omap_request_dma(up->uart_dma.uart_dma_tx, | ||
273 | "UART Tx DMA", | ||
274 | (void *)uart_tx_dma_callback, up, | ||
275 | &(up->uart_dma.tx_dma_channel)); | ||
276 | |||
277 | if (ret < 0) { | ||
278 | serial_omap_enable_ier_thri(up); | ||
279 | return; | ||
280 | } | ||
281 | } | ||
282 | spin_lock(&(up->uart_dma.tx_lock)); | ||
283 | up->uart_dma.tx_dma_used = true; | ||
284 | spin_unlock(&(up->uart_dma.tx_lock)); | ||
285 | |||
286 | start = up->uart_dma.tx_buf_dma_phys + | ||
287 | (xmit->tail & (UART_XMIT_SIZE - 1)); | ||
288 | |||
289 | up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); | ||
290 | /* | ||
291 | * It is a circular buffer. See if the buffer has wounded back. | ||
292 | * If yes it will have to be transferred in two separate dma | ||
293 | * transfers | ||
294 | */ | ||
295 | if (start + up->uart_dma.tx_buf_size >= | ||
296 | up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) | ||
297 | up->uart_dma.tx_buf_size = | ||
298 | (up->uart_dma.tx_buf_dma_phys + | ||
299 | UART_XMIT_SIZE) - start; | ||
300 | |||
301 | omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, | ||
302 | OMAP_DMA_AMODE_CONSTANT, | ||
303 | up->uart_dma.uart_base, 0, 0); | ||
304 | omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, | ||
305 | OMAP_DMA_AMODE_POST_INC, start, 0, 0); | ||
306 | omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, | ||
307 | OMAP_DMA_DATA_TYPE_S8, | ||
308 | up->uart_dma.tx_buf_size, 1, | ||
309 | OMAP_DMA_SYNC_ELEMENT, | ||
310 | up->uart_dma.uart_dma_tx, 0); | ||
311 | /* FIXME: Cache maintenance needed here? */ | ||
312 | omap_start_dma(up->uart_dma.tx_dma_channel); | ||
313 | } | ||
314 | |||
315 | static unsigned int check_modem_status(struct uart_omap_port *up) | ||
316 | { | ||
317 | unsigned int status; | ||
318 | |||
319 | status = serial_in(up, UART_MSR); | ||
320 | status |= up->msr_saved_flags; | ||
321 | up->msr_saved_flags = 0; | ||
322 | if ((status & UART_MSR_ANY_DELTA) == 0) | ||
323 | return status; | ||
324 | |||
325 | if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && | ||
326 | up->port.state != NULL) { | ||
327 | if (status & UART_MSR_TERI) | ||
328 | up->port.icount.rng++; | ||
329 | if (status & UART_MSR_DDSR) | ||
330 | up->port.icount.dsr++; | ||
331 | if (status & UART_MSR_DDCD) | ||
332 | uart_handle_dcd_change | ||
333 | (&up->port, status & UART_MSR_DCD); | ||
334 | if (status & UART_MSR_DCTS) | ||
335 | uart_handle_cts_change | ||
336 | (&up->port, status & UART_MSR_CTS); | ||
337 | wake_up_interruptible(&up->port.state->port.delta_msr_wait); | ||
338 | } | ||
339 | |||
340 | return status; | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * serial_omap_irq() - This handles the interrupt from one port | ||
345 | * @irq: uart port irq number | ||
346 | * @dev_id: uart port info | ||
347 | */ | ||
348 | static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) | ||
349 | { | ||
350 | struct uart_omap_port *up = dev_id; | ||
351 | unsigned int iir, lsr; | ||
352 | unsigned long flags; | ||
353 | |||
354 | iir = serial_in(up, UART_IIR); | ||
355 | if (iir & UART_IIR_NO_INT) | ||
356 | return IRQ_NONE; | ||
357 | |||
358 | spin_lock_irqsave(&up->port.lock, flags); | ||
359 | lsr = serial_in(up, UART_LSR); | ||
360 | if (iir & UART_IIR_RLSI) { | ||
361 | if (!up->use_dma) { | ||
362 | if (lsr & UART_LSR_DR) | ||
363 | receive_chars(up, &lsr); | ||
364 | } else { | ||
365 | up->ier &= ~(UART_IER_RDI | UART_IER_RLSI); | ||
366 | serial_out(up, UART_IER, up->ier); | ||
367 | if ((serial_omap_start_rxdma(up) != 0) && | ||
368 | (lsr & UART_LSR_DR)) | ||
369 | receive_chars(up, &lsr); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | check_modem_status(up); | ||
374 | if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI)) | ||
375 | transmit_chars(up); | ||
376 | |||
377 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
378 | up->port_activity = jiffies; | ||
379 | return IRQ_HANDLED; | ||
380 | } | ||
381 | |||
382 | static unsigned int serial_omap_tx_empty(struct uart_port *port) | ||
383 | { | ||
384 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
385 | unsigned long flags = 0; | ||
386 | unsigned int ret = 0; | ||
387 | |||
388 | dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id); | ||
389 | spin_lock_irqsave(&up->port.lock, flags); | ||
390 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | ||
391 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static unsigned int serial_omap_get_mctrl(struct uart_port *port) | ||
397 | { | ||
398 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
399 | unsigned char status; | ||
400 | unsigned int ret = 0; | ||
401 | |||
402 | status = check_modem_status(up); | ||
403 | dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id); | ||
404 | |||
405 | if (status & UART_MSR_DCD) | ||
406 | ret |= TIOCM_CAR; | ||
407 | if (status & UART_MSR_RI) | ||
408 | ret |= TIOCM_RNG; | ||
409 | if (status & UART_MSR_DSR) | ||
410 | ret |= TIOCM_DSR; | ||
411 | if (status & UART_MSR_CTS) | ||
412 | ret |= TIOCM_CTS; | ||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
417 | { | ||
418 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
419 | unsigned char mcr = 0; | ||
420 | |||
421 | dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id); | ||
422 | if (mctrl & TIOCM_RTS) | ||
423 | mcr |= UART_MCR_RTS; | ||
424 | if (mctrl & TIOCM_DTR) | ||
425 | mcr |= UART_MCR_DTR; | ||
426 | if (mctrl & TIOCM_OUT1) | ||
427 | mcr |= UART_MCR_OUT1; | ||
428 | if (mctrl & TIOCM_OUT2) | ||
429 | mcr |= UART_MCR_OUT2; | ||
430 | if (mctrl & TIOCM_LOOP) | ||
431 | mcr |= UART_MCR_LOOP; | ||
432 | |||
433 | mcr |= up->mcr; | ||
434 | serial_out(up, UART_MCR, mcr); | ||
435 | } | ||
436 | |||
437 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) | ||
438 | { | ||
439 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
440 | unsigned long flags = 0; | ||
441 | |||
442 | dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id); | ||
443 | spin_lock_irqsave(&up->port.lock, flags); | ||
444 | if (break_state == -1) | ||
445 | up->lcr |= UART_LCR_SBC; | ||
446 | else | ||
447 | up->lcr &= ~UART_LCR_SBC; | ||
448 | serial_out(up, UART_LCR, up->lcr); | ||
449 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
450 | } | ||
451 | |||
452 | static int serial_omap_startup(struct uart_port *port) | ||
453 | { | ||
454 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
455 | unsigned long flags = 0; | ||
456 | int retval; | ||
457 | |||
458 | /* | ||
459 | * Allocate the IRQ | ||
460 | */ | ||
461 | retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags, | ||
462 | up->name, up); | ||
463 | if (retval) | ||
464 | return retval; | ||
465 | |||
466 | dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id); | ||
467 | |||
468 | /* | ||
469 | * Clear the FIFO buffers and disable them. | ||
470 | * (they will be reenabled in set_termios()) | ||
471 | */ | ||
472 | serial_omap_clear_fifos(up); | ||
473 | /* For Hardware flow control */ | ||
474 | serial_out(up, UART_MCR, UART_MCR_RTS); | ||
475 | |||
476 | /* | ||
477 | * Clear the interrupt registers. | ||
478 | */ | ||
479 | (void) serial_in(up, UART_LSR); | ||
480 | if (serial_in(up, UART_LSR) & UART_LSR_DR) | ||
481 | (void) serial_in(up, UART_RX); | ||
482 | (void) serial_in(up, UART_IIR); | ||
483 | (void) serial_in(up, UART_MSR); | ||
484 | |||
485 | /* | ||
486 | * Now, initialize the UART | ||
487 | */ | ||
488 | serial_out(up, UART_LCR, UART_LCR_WLEN8); | ||
489 | spin_lock_irqsave(&up->port.lock, flags); | ||
490 | /* | ||
491 | * Most PC uarts need OUT2 raised to enable interrupts. | ||
492 | */ | ||
493 | up->port.mctrl |= TIOCM_OUT2; | ||
494 | serial_omap_set_mctrl(&up->port, up->port.mctrl); | ||
495 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
496 | |||
497 | up->msr_saved_flags = 0; | ||
498 | if (up->use_dma) { | ||
499 | free_page((unsigned long)up->port.state->xmit.buf); | ||
500 | up->port.state->xmit.buf = dma_alloc_coherent(NULL, | ||
501 | UART_XMIT_SIZE, | ||
502 | (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys), | ||
503 | 0); | ||
504 | init_timer(&(up->uart_dma.rx_timer)); | ||
505 | up->uart_dma.rx_timer.function = serial_omap_rx_timeout; | ||
506 | up->uart_dma.rx_timer.data = up->pdev->id; | ||
507 | /* Currently the buffer size is 4KB. Can increase it */ | ||
508 | up->uart_dma.rx_buf = dma_alloc_coherent(NULL, | ||
509 | up->uart_dma.rx_buf_size, | ||
510 | (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0); | ||
511 | } | ||
512 | /* | ||
513 | * Finally, enable interrupts. Note: Modem status interrupts | ||
514 | * are set via set_termios(), which will be occurring imminently | ||
515 | * anyway, so we don't enable them here. | ||
516 | */ | ||
517 | up->ier = UART_IER_RLSI | UART_IER_RDI; | ||
518 | serial_out(up, UART_IER, up->ier); | ||
519 | |||
520 | up->port_activity = jiffies; | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static void serial_omap_shutdown(struct uart_port *port) | ||
525 | { | ||
526 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
527 | unsigned long flags = 0; | ||
528 | |||
529 | dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id); | ||
530 | /* | ||
531 | * Disable interrupts from this port | ||
532 | */ | ||
533 | up->ier = 0; | ||
534 | serial_out(up, UART_IER, 0); | ||
535 | |||
536 | spin_lock_irqsave(&up->port.lock, flags); | ||
537 | up->port.mctrl &= ~TIOCM_OUT2; | ||
538 | serial_omap_set_mctrl(&up->port, up->port.mctrl); | ||
539 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
540 | |||
541 | /* | ||
542 | * Disable break condition and FIFOs | ||
543 | */ | ||
544 | serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); | ||
545 | serial_omap_clear_fifos(up); | ||
546 | |||
547 | /* | ||
548 | * Read data port to reset things, and then free the irq | ||
549 | */ | ||
550 | if (serial_in(up, UART_LSR) & UART_LSR_DR) | ||
551 | (void) serial_in(up, UART_RX); | ||
552 | if (up->use_dma) { | ||
553 | dma_free_coherent(up->port.dev, | ||
554 | UART_XMIT_SIZE, up->port.state->xmit.buf, | ||
555 | up->uart_dma.tx_buf_dma_phys); | ||
556 | up->port.state->xmit.buf = NULL; | ||
557 | serial_omap_stop_rx(port); | ||
558 | dma_free_coherent(up->port.dev, | ||
559 | up->uart_dma.rx_buf_size, up->uart_dma.rx_buf, | ||
560 | up->uart_dma.rx_buf_dma_phys); | ||
561 | up->uart_dma.rx_buf = NULL; | ||
562 | } | ||
563 | free_irq(up->port.irq, up); | ||
564 | } | ||
565 | |||
566 | static inline void | ||
567 | serial_omap_configure_xonxoff | ||
568 | (struct uart_omap_port *up, struct ktermios *termios) | ||
569 | { | ||
570 | unsigned char efr = 0; | ||
571 | |||
572 | up->lcr = serial_in(up, UART_LCR); | ||
573 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
574 | up->efr = serial_in(up, UART_EFR); | ||
575 | serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB); | ||
576 | |||
577 | serial_out(up, UART_XON1, termios->c_cc[VSTART]); | ||
578 | serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); | ||
579 | |||
580 | /* clear SW control mode bits */ | ||
581 | efr = up->efr; | ||
582 | efr &= OMAP_UART_SW_CLR; | ||
583 | |||
584 | /* | ||
585 | * IXON Flag: | ||
586 | * Enable XON/XOFF flow control on output. | ||
587 | * Transmit XON1, XOFF1 | ||
588 | */ | ||
589 | if (termios->c_iflag & IXON) | ||
590 | efr |= OMAP_UART_SW_TX; | ||
591 | |||
592 | /* | ||
593 | * IXOFF Flag: | ||
594 | * Enable XON/XOFF flow control on input. | ||
595 | * Receiver compares XON1, XOFF1. | ||
596 | */ | ||
597 | if (termios->c_iflag & IXOFF) | ||
598 | efr |= OMAP_UART_SW_RX; | ||
599 | |||
600 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
601 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
602 | |||
603 | up->mcr = serial_in(up, UART_MCR); | ||
604 | |||
605 | /* | ||
606 | * IXANY Flag: | ||
607 | * Enable any character to restart output. | ||
608 | * Operation resumes after receiving any | ||
609 | * character after recognition of the XOFF character | ||
610 | */ | ||
611 | if (termios->c_iflag & IXANY) | ||
612 | up->mcr |= UART_MCR_XONANY; | ||
613 | |||
614 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | ||
615 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
616 | serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); | ||
617 | /* Enable special char function UARTi.EFR_REG[5] and | ||
618 | * load the new software flow control mode IXON or IXOFF | ||
619 | * and restore the UARTi.EFR_REG[4] ENHANCED_EN value. | ||
620 | */ | ||
621 | serial_out(up, UART_EFR, efr | UART_EFR_SCD); | ||
622 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
623 | |||
624 | serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR); | ||
625 | serial_out(up, UART_LCR, up->lcr); | ||
626 | } | ||
627 | |||
628 | static void | ||
629 | serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | ||
630 | struct ktermios *old) | ||
631 | { | ||
632 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
633 | unsigned char cval = 0; | ||
634 | unsigned char efr = 0; | ||
635 | unsigned long flags = 0; | ||
636 | unsigned int baud, quot; | ||
637 | |||
638 | switch (termios->c_cflag & CSIZE) { | ||
639 | case CS5: | ||
640 | cval = UART_LCR_WLEN5; | ||
641 | break; | ||
642 | case CS6: | ||
643 | cval = UART_LCR_WLEN6; | ||
644 | break; | ||
645 | case CS7: | ||
646 | cval = UART_LCR_WLEN7; | ||
647 | break; | ||
648 | default: | ||
649 | case CS8: | ||
650 | cval = UART_LCR_WLEN8; | ||
651 | break; | ||
652 | } | ||
653 | |||
654 | if (termios->c_cflag & CSTOPB) | ||
655 | cval |= UART_LCR_STOP; | ||
656 | if (termios->c_cflag & PARENB) | ||
657 | cval |= UART_LCR_PARITY; | ||
658 | if (!(termios->c_cflag & PARODD)) | ||
659 | cval |= UART_LCR_EPAR; | ||
660 | |||
661 | /* | ||
662 | * Ask the core to calculate the divisor for us. | ||
663 | */ | ||
664 | |||
665 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); | ||
666 | quot = serial_omap_get_divisor(port, baud); | ||
667 | |||
668 | up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | | ||
669 | UART_FCR_ENABLE_FIFO; | ||
670 | if (up->use_dma) | ||
671 | up->fcr |= UART_FCR_DMA_SELECT; | ||
672 | |||
673 | /* | ||
674 | * Ok, we're now changing the port state. Do it with | ||
675 | * interrupts disabled. | ||
676 | */ | ||
677 | spin_lock_irqsave(&up->port.lock, flags); | ||
678 | |||
679 | /* | ||
680 | * Update the per-port timeout. | ||
681 | */ | ||
682 | uart_update_timeout(port, termios->c_cflag, baud); | ||
683 | |||
684 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
685 | if (termios->c_iflag & INPCK) | ||
686 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
687 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
688 | up->port.read_status_mask |= UART_LSR_BI; | ||
689 | |||
690 | /* | ||
691 | * Characters to ignore | ||
692 | */ | ||
693 | up->port.ignore_status_mask = 0; | ||
694 | if (termios->c_iflag & IGNPAR) | ||
695 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
696 | if (termios->c_iflag & IGNBRK) { | ||
697 | up->port.ignore_status_mask |= UART_LSR_BI; | ||
698 | /* | ||
699 | * If we're ignoring parity and break indicators, | ||
700 | * ignore overruns too (for real raw support). | ||
701 | */ | ||
702 | if (termios->c_iflag & IGNPAR) | ||
703 | up->port.ignore_status_mask |= UART_LSR_OE; | ||
704 | } | ||
705 | |||
706 | /* | ||
707 | * ignore all characters if CREAD is not set | ||
708 | */ | ||
709 | if ((termios->c_cflag & CREAD) == 0) | ||
710 | up->port.ignore_status_mask |= UART_LSR_DR; | ||
711 | |||
712 | /* | ||
713 | * Modem status interrupts | ||
714 | */ | ||
715 | up->ier &= ~UART_IER_MSI; | ||
716 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | ||
717 | up->ier |= UART_IER_MSI; | ||
718 | serial_out(up, UART_IER, up->ier); | ||
719 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | ||
720 | |||
721 | /* FIFOs and DMA Settings */ | ||
722 | |||
723 | /* FCR can be changed only when the | ||
724 | * baud clock is not running | ||
725 | * DLL_REG and DLH_REG set to 0. | ||
726 | */ | ||
727 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
728 | serial_out(up, UART_DLL, 0); | ||
729 | serial_out(up, UART_DLM, 0); | ||
730 | serial_out(up, UART_LCR, 0); | ||
731 | |||
732 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
733 | |||
734 | up->efr = serial_in(up, UART_EFR); | ||
735 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
736 | |||
737 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
738 | up->mcr = serial_in(up, UART_MCR); | ||
739 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | ||
740 | /* FIFO ENABLE, DMA MODE */ | ||
741 | serial_out(up, UART_FCR, up->fcr); | ||
742 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
743 | |||
744 | if (up->use_dma) { | ||
745 | serial_out(up, UART_TI752_TLR, 0); | ||
746 | serial_out(up, UART_OMAP_SCR, | ||
747 | (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8)); | ||
748 | } | ||
749 | |||
750 | serial_out(up, UART_EFR, up->efr); | ||
751 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
752 | serial_out(up, UART_MCR, up->mcr); | ||
753 | |||
754 | /* Protocol, Baud Rate, and Interrupt Settings */ | ||
755 | |||
756 | serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE); | ||
757 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
758 | |||
759 | up->efr = serial_in(up, UART_EFR); | ||
760 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
761 | |||
762 | serial_out(up, UART_LCR, 0); | ||
763 | serial_out(up, UART_IER, 0); | ||
764 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
765 | |||
766 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | ||
767 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | ||
768 | |||
769 | serial_out(up, UART_LCR, 0); | ||
770 | serial_out(up, UART_IER, up->ier); | ||
771 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
772 | |||
773 | serial_out(up, UART_EFR, up->efr); | ||
774 | serial_out(up, UART_LCR, cval); | ||
775 | |||
776 | if (baud > 230400 && baud != 3000000) | ||
777 | serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X); | ||
778 | else | ||
779 | serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X); | ||
780 | |||
781 | /* Hardware Flow Control Configuration */ | ||
782 | |||
783 | if (termios->c_cflag & CRTSCTS) { | ||
784 | efr |= (UART_EFR_CTS | UART_EFR_RTS); | ||
785 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
786 | |||
787 | up->mcr = serial_in(up, UART_MCR); | ||
788 | serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); | ||
789 | |||
790 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
791 | up->efr = serial_in(up, UART_EFR); | ||
792 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | ||
793 | |||
794 | serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); | ||
795 | serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */ | ||
796 | serial_out(up, UART_LCR, UART_LCR_DLAB); | ||
797 | serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS); | ||
798 | serial_out(up, UART_LCR, cval); | ||
799 | } | ||
800 | |||
801 | serial_omap_set_mctrl(&up->port, up->port.mctrl); | ||
802 | /* Software Flow Control Configuration */ | ||
803 | if (termios->c_iflag & (IXON | IXOFF)) | ||
804 | serial_omap_configure_xonxoff(up, termios); | ||
805 | |||
806 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
807 | dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); | ||
808 | } | ||
809 | |||
810 | static void | ||
811 | serial_omap_pm(struct uart_port *port, unsigned int state, | ||
812 | unsigned int oldstate) | ||
813 | { | ||
814 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
815 | unsigned char efr; | ||
816 | |||
817 | dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id); | ||
818 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
819 | efr = serial_in(up, UART_EFR); | ||
820 | serial_out(up, UART_EFR, efr | UART_EFR_ECB); | ||
821 | serial_out(up, UART_LCR, 0); | ||
822 | |||
823 | serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); | ||
824 | serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); | ||
825 | serial_out(up, UART_EFR, efr); | ||
826 | serial_out(up, UART_LCR, 0); | ||
827 | /* Enable module level wake up */ | ||
828 | serial_out(up, UART_OMAP_WER, | ||
829 | (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0); | ||
830 | } | ||
831 | |||
832 | static void serial_omap_release_port(struct uart_port *port) | ||
833 | { | ||
834 | dev_dbg(port->dev, "serial_omap_release_port+\n"); | ||
835 | } | ||
836 | |||
837 | static int serial_omap_request_port(struct uart_port *port) | ||
838 | { | ||
839 | dev_dbg(port->dev, "serial_omap_request_port+\n"); | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static void serial_omap_config_port(struct uart_port *port, int flags) | ||
844 | { | ||
845 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
846 | |||
847 | dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", | ||
848 | up->pdev->id); | ||
849 | up->port.type = PORT_OMAP; | ||
850 | } | ||
851 | |||
852 | static int | ||
853 | serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
854 | { | ||
855 | /* we don't want the core code to modify any port params */ | ||
856 | dev_dbg(port->dev, "serial_omap_verify_port+\n"); | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | |||
860 | static const char * | ||
861 | serial_omap_type(struct uart_port *port) | ||
862 | { | ||
863 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
864 | |||
865 | dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id); | ||
866 | return up->name; | ||
867 | } | ||
868 | |||
869 | #ifdef CONFIG_SERIAL_OMAP_CONSOLE | ||
870 | |||
871 | static struct uart_omap_port *serial_omap_console_ports[4]; | ||
872 | |||
873 | static struct uart_driver serial_omap_reg; | ||
874 | |||
875 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | ||
876 | |||
877 | static inline void wait_for_xmitr(struct uart_omap_port *up) | ||
878 | { | ||
879 | unsigned int status, tmout = 10000; | ||
880 | |||
881 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
882 | do { | ||
883 | status = serial_in(up, UART_LSR); | ||
884 | |||
885 | if (status & UART_LSR_BI) | ||
886 | up->lsr_break_flag = UART_LSR_BI; | ||
887 | |||
888 | if (--tmout == 0) | ||
889 | break; | ||
890 | udelay(1); | ||
891 | } while ((status & BOTH_EMPTY) != BOTH_EMPTY); | ||
892 | |||
893 | /* Wait up to 1s for flow control if necessary */ | ||
894 | if (up->port.flags & UPF_CONS_FLOW) { | ||
895 | tmout = 1000000; | ||
896 | for (tmout = 1000000; tmout; tmout--) { | ||
897 | unsigned int msr = serial_in(up, UART_MSR); | ||
898 | |||
899 | up->msr_saved_flags |= msr & MSR_SAVE_FLAGS; | ||
900 | if (msr & UART_MSR_CTS) | ||
901 | break; | ||
902 | |||
903 | udelay(1); | ||
904 | } | ||
905 | } | ||
906 | } | ||
907 | |||
908 | static void serial_omap_console_putchar(struct uart_port *port, int ch) | ||
909 | { | ||
910 | struct uart_omap_port *up = (struct uart_omap_port *)port; | ||
911 | |||
912 | wait_for_xmitr(up); | ||
913 | serial_out(up, UART_TX, ch); | ||
914 | } | ||
915 | |||
916 | static void | ||
917 | serial_omap_console_write(struct console *co, const char *s, | ||
918 | unsigned int count) | ||
919 | { | ||
920 | struct uart_omap_port *up = serial_omap_console_ports[co->index]; | ||
921 | unsigned long flags; | ||
922 | unsigned int ier; | ||
923 | int locked = 1; | ||
924 | |||
925 | local_irq_save(flags); | ||
926 | if (up->port.sysrq) | ||
927 | locked = 0; | ||
928 | else if (oops_in_progress) | ||
929 | locked = spin_trylock(&up->port.lock); | ||
930 | else | ||
931 | spin_lock(&up->port.lock); | ||
932 | |||
933 | /* | ||
934 | * First save the IER then disable the interrupts | ||
935 | */ | ||
936 | ier = serial_in(up, UART_IER); | ||
937 | serial_out(up, UART_IER, 0); | ||
938 | |||
939 | uart_console_write(&up->port, s, count, serial_omap_console_putchar); | ||
940 | |||
941 | /* | ||
942 | * Finally, wait for transmitter to become empty | ||
943 | * and restore the IER | ||
944 | */ | ||
945 | wait_for_xmitr(up); | ||
946 | serial_out(up, UART_IER, ier); | ||
947 | /* | ||
948 | * The receive handling will happen properly because the | ||
949 | * receive ready bit will still be set; it is not cleared | ||
950 | * on read. However, modem control will not, we must | ||
951 | * call it if we have saved something in the saved flags | ||
952 | * while processing with interrupts off. | ||
953 | */ | ||
954 | if (up->msr_saved_flags) | ||
955 | check_modem_status(up); | ||
956 | |||
957 | if (locked) | ||
958 | spin_unlock(&up->port.lock); | ||
959 | local_irq_restore(flags); | ||
960 | } | ||
961 | |||
962 | static int __init | ||
963 | serial_omap_console_setup(struct console *co, char *options) | ||
964 | { | ||
965 | struct uart_omap_port *up; | ||
966 | int baud = 115200; | ||
967 | int bits = 8; | ||
968 | int parity = 'n'; | ||
969 | int flow = 'n'; | ||
970 | |||
971 | if (serial_omap_console_ports[co->index] == NULL) | ||
972 | return -ENODEV; | ||
973 | up = serial_omap_console_ports[co->index]; | ||
974 | |||
975 | if (options) | ||
976 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
977 | |||
978 | return uart_set_options(&up->port, co, baud, parity, bits, flow); | ||
979 | } | ||
980 | |||
981 | static struct console serial_omap_console = { | ||
982 | .name = OMAP_SERIAL_NAME, | ||
983 | .write = serial_omap_console_write, | ||
984 | .device = uart_console_device, | ||
985 | .setup = serial_omap_console_setup, | ||
986 | .flags = CON_PRINTBUFFER, | ||
987 | .index = -1, | ||
988 | .data = &serial_omap_reg, | ||
989 | }; | ||
990 | |||
991 | static void serial_omap_add_console_port(struct uart_omap_port *up) | ||
992 | { | ||
993 | serial_omap_console_ports[up->pdev->id] = up; | ||
994 | } | ||
995 | |||
996 | #define OMAP_CONSOLE (&serial_omap_console) | ||
997 | |||
998 | #else | ||
999 | |||
1000 | #define OMAP_CONSOLE NULL | ||
1001 | |||
1002 | static inline void serial_omap_add_console_port(struct uart_omap_port *up) | ||
1003 | {} | ||
1004 | |||
1005 | #endif | ||
1006 | |||
1007 | static struct uart_ops serial_omap_pops = { | ||
1008 | .tx_empty = serial_omap_tx_empty, | ||
1009 | .set_mctrl = serial_omap_set_mctrl, | ||
1010 | .get_mctrl = serial_omap_get_mctrl, | ||
1011 | .stop_tx = serial_omap_stop_tx, | ||
1012 | .start_tx = serial_omap_start_tx, | ||
1013 | .stop_rx = serial_omap_stop_rx, | ||
1014 | .enable_ms = serial_omap_enable_ms, | ||
1015 | .break_ctl = serial_omap_break_ctl, | ||
1016 | .startup = serial_omap_startup, | ||
1017 | .shutdown = serial_omap_shutdown, | ||
1018 | .set_termios = serial_omap_set_termios, | ||
1019 | .pm = serial_omap_pm, | ||
1020 | .type = serial_omap_type, | ||
1021 | .release_port = serial_omap_release_port, | ||
1022 | .request_port = serial_omap_request_port, | ||
1023 | .config_port = serial_omap_config_port, | ||
1024 | .verify_port = serial_omap_verify_port, | ||
1025 | }; | ||
1026 | |||
1027 | static struct uart_driver serial_omap_reg = { | ||
1028 | .owner = THIS_MODULE, | ||
1029 | .driver_name = "OMAP-SERIAL", | ||
1030 | .dev_name = OMAP_SERIAL_NAME, | ||
1031 | .nr = OMAP_MAX_HSUART_PORTS, | ||
1032 | .cons = OMAP_CONSOLE, | ||
1033 | }; | ||
1034 | |||
1035 | static int | ||
1036 | serial_omap_suspend(struct platform_device *pdev, pm_message_t state) | ||
1037 | { | ||
1038 | struct uart_omap_port *up = platform_get_drvdata(pdev); | ||
1039 | |||
1040 | if (up) | ||
1041 | uart_suspend_port(&serial_omap_reg, &up->port); | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static int serial_omap_resume(struct platform_device *dev) | ||
1046 | { | ||
1047 | struct uart_omap_port *up = platform_get_drvdata(dev); | ||
1048 | |||
1049 | if (up) | ||
1050 | uart_resume_port(&serial_omap_reg, &up->port); | ||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | static void serial_omap_rx_timeout(unsigned long uart_no) | ||
1055 | { | ||
1056 | struct uart_omap_port *up = ui[uart_no]; | ||
1057 | unsigned int curr_dma_pos, curr_transmitted_size; | ||
1058 | unsigned int ret = 0; | ||
1059 | |||
1060 | curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel); | ||
1061 | if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) || | ||
1062 | (curr_dma_pos == 0)) { | ||
1063 | if (jiffies_to_msecs(jiffies - up->port_activity) < | ||
1064 | RX_TIMEOUT) { | ||
1065 | mod_timer(&up->uart_dma.rx_timer, jiffies + | ||
1066 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | ||
1067 | } else { | ||
1068 | serial_omap_stop_rxdma(up); | ||
1069 | up->ier |= (UART_IER_RDI | UART_IER_RLSI); | ||
1070 | serial_out(up, UART_IER, up->ier); | ||
1071 | } | ||
1072 | return; | ||
1073 | } | ||
1074 | |||
1075 | curr_transmitted_size = curr_dma_pos - | ||
1076 | up->uart_dma.prev_rx_dma_pos; | ||
1077 | up->port.icount.rx += curr_transmitted_size; | ||
1078 | tty_insert_flip_string(up->port.state->port.tty, | ||
1079 | up->uart_dma.rx_buf + | ||
1080 | (up->uart_dma.prev_rx_dma_pos - | ||
1081 | up->uart_dma.rx_buf_dma_phys), | ||
1082 | curr_transmitted_size); | ||
1083 | tty_flip_buffer_push(up->port.state->port.tty); | ||
1084 | up->uart_dma.prev_rx_dma_pos = curr_dma_pos; | ||
1085 | if (up->uart_dma.rx_buf_size + | ||
1086 | up->uart_dma.rx_buf_dma_phys == curr_dma_pos) { | ||
1087 | ret = serial_omap_start_rxdma(up); | ||
1088 | if (ret < 0) { | ||
1089 | serial_omap_stop_rxdma(up); | ||
1090 | up->ier |= (UART_IER_RDI | UART_IER_RLSI); | ||
1091 | serial_out(up, UART_IER, up->ier); | ||
1092 | } | ||
1093 | } else { | ||
1094 | mod_timer(&up->uart_dma.rx_timer, jiffies + | ||
1095 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | ||
1096 | } | ||
1097 | up->port_activity = jiffies; | ||
1098 | } | ||
1099 | |||
1100 | static void uart_rx_dma_callback(int lch, u16 ch_status, void *data) | ||
1101 | { | ||
1102 | return; | ||
1103 | } | ||
1104 | |||
1105 | static int serial_omap_start_rxdma(struct uart_omap_port *up) | ||
1106 | { | ||
1107 | int ret = 0; | ||
1108 | |||
1109 | if (up->uart_dma.rx_dma_channel == -1) { | ||
1110 | ret = omap_request_dma(up->uart_dma.uart_dma_rx, | ||
1111 | "UART Rx DMA", | ||
1112 | (void *)uart_rx_dma_callback, up, | ||
1113 | &(up->uart_dma.rx_dma_channel)); | ||
1114 | if (ret < 0) | ||
1115 | return ret; | ||
1116 | |||
1117 | omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, | ||
1118 | OMAP_DMA_AMODE_CONSTANT, | ||
1119 | up->uart_dma.uart_base, 0, 0); | ||
1120 | omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, | ||
1121 | OMAP_DMA_AMODE_POST_INC, | ||
1122 | up->uart_dma.rx_buf_dma_phys, 0, 0); | ||
1123 | omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, | ||
1124 | OMAP_DMA_DATA_TYPE_S8, | ||
1125 | up->uart_dma.rx_buf_size, 1, | ||
1126 | OMAP_DMA_SYNC_ELEMENT, | ||
1127 | up->uart_dma.uart_dma_rx, 0); | ||
1128 | } | ||
1129 | up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; | ||
1130 | /* FIXME: Cache maintenance needed here? */ | ||
1131 | omap_start_dma(up->uart_dma.rx_dma_channel); | ||
1132 | mod_timer(&up->uart_dma.rx_timer, jiffies + | ||
1133 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | ||
1134 | up->uart_dma.rx_dma_used = true; | ||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | static void serial_omap_continue_tx(struct uart_omap_port *up) | ||
1139 | { | ||
1140 | struct circ_buf *xmit = &up->port.state->xmit; | ||
1141 | unsigned int start = up->uart_dma.tx_buf_dma_phys | ||
1142 | + (xmit->tail & (UART_XMIT_SIZE - 1)); | ||
1143 | |||
1144 | if (uart_circ_empty(xmit)) | ||
1145 | return; | ||
1146 | |||
1147 | up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); | ||
1148 | /* | ||
1149 | * It is a circular buffer. See if the buffer has wounded back. | ||
1150 | * If yes it will have to be transferred in two separate dma | ||
1151 | * transfers | ||
1152 | */ | ||
1153 | if (start + up->uart_dma.tx_buf_size >= | ||
1154 | up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) | ||
1155 | up->uart_dma.tx_buf_size = | ||
1156 | (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; | ||
1157 | omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, | ||
1158 | OMAP_DMA_AMODE_CONSTANT, | ||
1159 | up->uart_dma.uart_base, 0, 0); | ||
1160 | omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, | ||
1161 | OMAP_DMA_AMODE_POST_INC, start, 0, 0); | ||
1162 | omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, | ||
1163 | OMAP_DMA_DATA_TYPE_S8, | ||
1164 | up->uart_dma.tx_buf_size, 1, | ||
1165 | OMAP_DMA_SYNC_ELEMENT, | ||
1166 | up->uart_dma.uart_dma_tx, 0); | ||
1167 | /* FIXME: Cache maintenance needed here? */ | ||
1168 | omap_start_dma(up->uart_dma.tx_dma_channel); | ||
1169 | } | ||
1170 | |||
1171 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data) | ||
1172 | { | ||
1173 | struct uart_omap_port *up = (struct uart_omap_port *)data; | ||
1174 | struct circ_buf *xmit = &up->port.state->xmit; | ||
1175 | |||
1176 | xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \ | ||
1177 | (UART_XMIT_SIZE - 1); | ||
1178 | up->port.icount.tx += up->uart_dma.tx_buf_size; | ||
1179 | |||
1180 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
1181 | uart_write_wakeup(&up->port); | ||
1182 | |||
1183 | if (uart_circ_empty(xmit)) { | ||
1184 | spin_lock(&(up->uart_dma.tx_lock)); | ||
1185 | serial_omap_stop_tx(&up->port); | ||
1186 | up->uart_dma.tx_dma_used = false; | ||
1187 | spin_unlock(&(up->uart_dma.tx_lock)); | ||
1188 | } else { | ||
1189 | omap_stop_dma(up->uart_dma.tx_dma_channel); | ||
1190 | serial_omap_continue_tx(up); | ||
1191 | } | ||
1192 | up->port_activity = jiffies; | ||
1193 | return; | ||
1194 | } | ||
1195 | |||
1196 | static int serial_omap_probe(struct platform_device *pdev) | ||
1197 | { | ||
1198 | struct uart_omap_port *up; | ||
1199 | struct resource *mem, *irq, *dma_tx, *dma_rx; | ||
1200 | struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; | ||
1201 | int ret = -ENOSPC; | ||
1202 | |||
1203 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1204 | if (!mem) { | ||
1205 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
1206 | return -ENODEV; | ||
1207 | } | ||
1208 | |||
1209 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1210 | if (!irq) { | ||
1211 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
1212 | return -ENODEV; | ||
1213 | } | ||
1214 | |||
1215 | if (!request_mem_region(mem->start, (mem->end - mem->start) + 1, | ||
1216 | pdev->dev.driver->name)) { | ||
1217 | dev_err(&pdev->dev, "memory region already claimed\n"); | ||
1218 | return -EBUSY; | ||
1219 | } | ||
1220 | |||
1221 | dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); | ||
1222 | if (!dma_rx) { | ||
1223 | ret = -EINVAL; | ||
1224 | goto err; | ||
1225 | } | ||
1226 | |||
1227 | dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); | ||
1228 | if (!dma_tx) { | ||
1229 | ret = -EINVAL; | ||
1230 | goto err; | ||
1231 | } | ||
1232 | |||
1233 | up = kzalloc(sizeof(*up), GFP_KERNEL); | ||
1234 | if (up == NULL) { | ||
1235 | ret = -ENOMEM; | ||
1236 | goto do_release_region; | ||
1237 | } | ||
1238 | sprintf(up->name, "OMAP UART%d", pdev->id); | ||
1239 | up->pdev = pdev; | ||
1240 | up->port.dev = &pdev->dev; | ||
1241 | up->port.type = PORT_OMAP; | ||
1242 | up->port.iotype = UPIO_MEM; | ||
1243 | up->port.irq = irq->start; | ||
1244 | |||
1245 | up->port.regshift = 2; | ||
1246 | up->port.fifosize = 64; | ||
1247 | up->port.ops = &serial_omap_pops; | ||
1248 | up->port.line = pdev->id; | ||
1249 | |||
1250 | up->port.membase = omap_up_info->membase; | ||
1251 | up->port.mapbase = omap_up_info->mapbase; | ||
1252 | up->port.flags = omap_up_info->flags; | ||
1253 | up->port.irqflags = omap_up_info->irqflags; | ||
1254 | up->port.uartclk = omap_up_info->uartclk; | ||
1255 | up->uart_dma.uart_base = mem->start; | ||
1256 | |||
1257 | if (omap_up_info->dma_enabled) { | ||
1258 | up->uart_dma.uart_dma_tx = dma_tx->start; | ||
1259 | up->uart_dma.uart_dma_rx = dma_rx->start; | ||
1260 | up->use_dma = 1; | ||
1261 | up->uart_dma.rx_buf_size = 4096; | ||
1262 | up->uart_dma.rx_timeout = 2; | ||
1263 | spin_lock_init(&(up->uart_dma.tx_lock)); | ||
1264 | spin_lock_init(&(up->uart_dma.rx_lock)); | ||
1265 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; | ||
1266 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | ||
1267 | } | ||
1268 | |||
1269 | ui[pdev->id] = up; | ||
1270 | serial_omap_add_console_port(up); | ||
1271 | |||
1272 | ret = uart_add_one_port(&serial_omap_reg, &up->port); | ||
1273 | if (ret != 0) | ||
1274 | goto do_release_region; | ||
1275 | |||
1276 | platform_set_drvdata(pdev, up); | ||
1277 | return 0; | ||
1278 | err: | ||
1279 | dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n", | ||
1280 | pdev->id, __func__, ret); | ||
1281 | do_release_region: | ||
1282 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1286 | static int serial_omap_remove(struct platform_device *dev) | ||
1287 | { | ||
1288 | struct uart_omap_port *up = platform_get_drvdata(dev); | ||
1289 | |||
1290 | platform_set_drvdata(dev, NULL); | ||
1291 | if (up) { | ||
1292 | uart_remove_one_port(&serial_omap_reg, &up->port); | ||
1293 | kfree(up); | ||
1294 | } | ||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | static struct platform_driver serial_omap_driver = { | ||
1299 | .probe = serial_omap_probe, | ||
1300 | .remove = serial_omap_remove, | ||
1301 | |||
1302 | .suspend = serial_omap_suspend, | ||
1303 | .resume = serial_omap_resume, | ||
1304 | .driver = { | ||
1305 | .name = DRIVER_NAME, | ||
1306 | }, | ||
1307 | }; | ||
1308 | |||
1309 | static int __init serial_omap_init(void) | ||
1310 | { | ||
1311 | int ret; | ||
1312 | |||
1313 | ret = uart_register_driver(&serial_omap_reg); | ||
1314 | if (ret != 0) | ||
1315 | return ret; | ||
1316 | ret = platform_driver_register(&serial_omap_driver); | ||
1317 | if (ret != 0) | ||
1318 | uart_unregister_driver(&serial_omap_reg); | ||
1319 | return ret; | ||
1320 | } | ||
1321 | |||
1322 | static void __exit serial_omap_exit(void) | ||
1323 | { | ||
1324 | platform_driver_unregister(&serial_omap_driver); | ||
1325 | uart_unregister_driver(&serial_omap_reg); | ||
1326 | } | ||
1327 | |||
1328 | module_init(serial_omap_init); | ||
1329 | module_exit(serial_omap_exit); | ||
1330 | |||
1331 | MODULE_DESCRIPTION("OMAP High Speed UART driver"); | ||
1332 | MODULE_LICENSE("GPL"); | ||
1333 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 563e23400913..295e89817de8 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -196,6 +196,9 @@ | |||
196 | /* High Speed UART for Medfield */ | 196 | /* High Speed UART for Medfield */ |
197 | #define PORT_MFD 95 | 197 | #define PORT_MFD 95 |
198 | 198 | ||
199 | /* TI OMAP-UART */ | ||
200 | #define PORT_OMAP 96 | ||
201 | |||
199 | #ifdef __KERNEL__ | 202 | #ifdef __KERNEL__ |
200 | 203 | ||
201 | #include <linux/compiler.h> | 204 | #include <linux/compiler.h> |