* [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod
@ 2010-01-12 23:58 Kevin Hilman
2010-01-12 23:58 ` [PATCH 1/2] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Kevin Hilman @ 2010-01-12 23:58 UTC (permalink / raw)
To: linux-omap
This series applies on curren PM branch plus my omap_device series
posted on 8 jan:
[PATCH 0/3] misc. omap_device/omap_hwmod updates
and is also available as branch 'pm-wip/uart' in my linux-omap-pm repo[1].
This series should allow further development and testing of the new
omap-serial driver from Govindraj.
[1] http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git
Kevin Hilman (2):
OMAP3: add omap_hwmods for UART1,2,3
OMAP: UART: omap_device converions, remove implicit 8520 assumptions
arch/arm/mach-omap2/omap_hwmod_34xx.h | 188 +++++++++++++
arch/arm/mach-omap2/serial.c | 474 +++++++++++++++++----------------
2 files changed, 430 insertions(+), 232 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/2] OMAP3: add omap_hwmods for UART1,2,3 2010-01-12 23:58 [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman @ 2010-01-12 23:58 ` Kevin Hilman 2010-01-12 23:58 ` [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions Kevin Hilman 2010-01-13 0:04 ` [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman 2 siblings, 0 replies; 6+ messages in thread From: Kevin Hilman @ 2010-01-12 23:58 UTC (permalink / raw) To: linux-omap This is temporary and will likely be replaced by autogenerated hwmods for OMAP3. --- arch/arm/mach-omap2/omap_hwmod_34xx.h | 188 +++++++++++++++++++++++++++++++++ 1 files changed, 188 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_34xx.h b/arch/arm/mach-omap2/omap_hwmod_34xx.h index b6076b9..8225bd3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_34xx.h +++ b/arch/arm/mach-omap2/omap_hwmod_34xx.h @@ -18,6 +18,7 @@ #include <mach/irqs.h> #include <plat/cpu.h> #include <plat/dma.h> +#include <plat/serial.h> #include "prm-regbits-34xx.h" @@ -48,6 +49,7 @@ static struct omap_hwmod_ocp_if omap34xx_mpu__l3 = { }; /* Slave interfaces on the L3 interconnect */ +/* KJH: OCP ifs which have L3 interconnect as the slave */ static struct omap_hwmod_ocp_if *omap34xx_l3_slaves[] = { &omap34xx_mpu__l3, }; @@ -69,6 +71,9 @@ static struct omap_hwmod omap34xx_l3_hwmod = { }; static struct omap_hwmod omap34xx_l4_wkup_hwmod; +static struct omap_hwmod omap34xx_uart1_hwmod; +static struct omap_hwmod omap34xx_uart2_hwmod; +static struct omap_hwmod omap34xx_uart3_hwmod; /* L4_CORE -> L4_WKUP interface */ static struct omap_hwmod_ocp_if omap34xx_l4_core__l4_wkup = { @@ -77,14 +82,75 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__l4_wkup = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* L4 CORE -> UART1 interface */ +static struct omap_hwmod_addr_space omap34xx_uart1_addr_space[] = { + { + .pa_start = OMAP_UART1_BASE, + .pa_end = OMAP_UART1_BASE + SZ_8K - 1, + .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, + }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = { + .master = &omap34xx_l4_core_hwmod, + .slave = &omap34xx_uart1_hwmod, + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart1_ick", + .addr = omap34xx_uart1_addr_space, + .addr_cnt = ARRAY_SIZE(omap34xx_uart1_addr_space), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* L4 CORE -> UART2 interface */ +static struct omap_hwmod_addr_space omap34xx_uart2_addr_space[] = { + { + .pa_start = OMAP_UART2_BASE, + .pa_end = OMAP_UART2_BASE + SZ_1K - 1, + .flags = ADDR_MAP_ON_INIT |ADDR_TYPE_RT, + }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = { + .master = &omap34xx_l4_core_hwmod, + .slave = &omap34xx_uart2_hwmod, + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart2_ick", + .addr = omap34xx_uart2_addr_space, + .addr_cnt = ARRAY_SIZE(omap34xx_uart2_addr_space), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* L4 PER -> UART3 interface */ +static struct omap_hwmod_addr_space omap34xx_uart3_addr_space[] = { + { + .pa_start = OMAP_UART3_BASE, + .pa_end = OMAP_UART3_BASE + SZ_1K - 1, + .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, + }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = { + .master = &omap34xx_l4_per_hwmod, + .slave = &omap34xx_uart3_hwmod, + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart3_ick", + .addr = omap34xx_uart3_addr_space, + .addr_cnt = ARRAY_SIZE(omap34xx_uart3_addr_space), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* Slave interfaces on the L4_CORE interconnect */ +/* KJH: OCP ifs where L4 CORE is the slave */ static struct omap_hwmod_ocp_if *omap34xx_l4_core_slaves[] = { &omap34xx_l3__l4_core, }; /* Master interfaces on the L4_CORE interconnect */ +/* KJH: OCP ifs where L4 CORE is the master */ static struct omap_hwmod_ocp_if *omap34xx_l4_core_masters[] = { &omap34xx_l4_core__l4_wkup, + &omap3_l4_core__uart1, + &omap3_l4_core__uart2, }; /* L4 CORE */ @@ -104,6 +170,7 @@ static struct omap_hwmod_ocp_if *omap34xx_l4_per_slaves[] = { /* Master interfaces on the L4_PER interconnect */ static struct omap_hwmod_ocp_if *omap34xx_l4_per_masters[] = { + &omap3_l4_per__uart3, }; /* L4 PER */ @@ -136,6 +203,7 @@ static struct omap_hwmod omap34xx_l4_wkup_hwmod = { }; /* Master interfaces on the MPU device */ +/* KJH: OCP ifs where MPU is the master */ static struct omap_hwmod_ocp_if *omap34xx_mpu_masters[] = { &omap34xx_mpu__l3, }; @@ -150,12 +218,132 @@ static struct omap_hwmod omap34xx_mpu_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +/* UART common */ + +static struct omap_hwmod_sysconfig uart_if_ctrl = { + .rev_offs = 0x50, + .sysc_offs = 0x54, + .syss_offs = 0x58, + .sysc_flags = (SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), +}; + +/* UART1 */ + +static struct omap_hwmod_irq_info uart1_mpu_irqs[] = { + { .irq = INT_24XX_UART1_IRQ, }, +}; + +static struct omap_hwmod_dma_info uart1_sdma_chs[] = { + { .name = "tx", .dma_ch = OMAP24XX_DMA_UART1_TX, }, + { .name = "rx", .dma_ch = OMAP24XX_DMA_UART1_RX, }, +}; + +static struct omap_hwmod_ocp_if *omap34xx_uart1_slaves[] = { + &omap3_l4_core__uart1, +}; + +static struct omap_hwmod omap34xx_uart1_hwmod = { + .name = "uart1_hwmod", + .mpu_irqs = uart1_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(uart1_mpu_irqs), + .sdma_chs = uart1_sdma_chs, + .sdma_chs_cnt = ARRAY_SIZE(uart1_sdma_chs), + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_UART1_SHIFT, + }, + }, + .slaves = omap34xx_uart1_slaves, + .slaves_cnt = ARRAY_SIZE(omap34xx_uart1_slaves), + .sysconfig = &uart_if_ctrl, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +/* UART2 */ + +static struct omap_hwmod_irq_info uart2_mpu_irqs[] = { + { .irq = INT_24XX_UART2_IRQ, }, +}; + +static struct omap_hwmod_dma_info uart2_sdma_chs[] = { + { .name = "tx", .dma_ch = OMAP24XX_DMA_UART2_TX, }, + { .name = "rx", .dma_ch = OMAP24XX_DMA_UART2_RX, }, +}; + +static struct omap_hwmod_ocp_if *omap34xx_uart2_slaves[] = { + &omap3_l4_core__uart2, +}; + +static struct omap_hwmod omap34xx_uart2_hwmod = { + .name = "uart2_hwmod", + .mpu_irqs = uart2_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(uart2_mpu_irqs), + .sdma_chs = uart2_sdma_chs, + .sdma_chs_cnt = ARRAY_SIZE(uart2_sdma_chs), + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart2_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_UART2_SHIFT, + }, + }, + .slaves = omap34xx_uart2_slaves, + .slaves_cnt = ARRAY_SIZE(omap34xx_uart2_slaves), + .sysconfig = &uart_if_ctrl, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +/* UART3 */ + +static struct omap_hwmod_irq_info uart3_mpu_irqs[] = { + { .irq = INT_24XX_UART3_IRQ, }, +}; + +static struct omap_hwmod_dma_info uart3_sdma_chs[] = { + { .name = "tx", .dma_ch = OMAP24XX_DMA_UART3_TX, }, + { .name = "rx", .dma_ch = OMAP24XX_DMA_UART3_RX, }, +}; + +static struct omap_hwmod_ocp_if *omap34xx_uart3_slaves[] = { + &omap3_l4_per__uart3, +}; + +static struct omap_hwmod omap34xx_uart3_hwmod = { + .name = "uart3_hwmod", + .mpu_irqs = uart3_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(uart3_mpu_irqs), + .sdma_chs = uart3_sdma_chs, + .sdma_chs_cnt = ARRAY_SIZE(uart3_sdma_chs), + .clkdev_dev_id = NULL, + .clkdev_con_id = "uart3_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_UART3_SHIFT, + }, + }, + .slaves = omap34xx_uart3_slaves, + .slaves_cnt = ARRAY_SIZE(omap34xx_uart3_slaves), + .sysconfig = &uart_if_ctrl, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + static __initdata struct omap_hwmod *omap34xx_hwmods[] = { &omap34xx_l3_hwmod, &omap34xx_l4_core_hwmod, &omap34xx_l4_per_hwmod, &omap34xx_l4_wkup_hwmod, &omap34xx_mpu_hwmod, + &omap34xx_uart1_hwmod, + &omap34xx_uart2_hwmod, + &omap34xx_uart3_hwmod, NULL, }; -- 1.6.6 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions 2010-01-12 23:58 [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman 2010-01-12 23:58 ` [PATCH 1/2] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman @ 2010-01-12 23:58 ` Kevin Hilman 2010-01-30 6:35 ` Nayak, Rajendra 2010-01-13 0:04 ` [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman 2 siblings, 1 reply; 6+ messages in thread From: Kevin Hilman @ 2010-01-12 23:58 UTC (permalink / raw) To: linux-omap; +Cc: Govindraj R Major rework of OMAP UART init for omap_device conversion as well as use with either 8250 driver or new omap-serial driver. Signifcant contributions and testing from Govindraj R <govindraj.raja@ti.com>. In preparation for a new omap-serial driver, remove 8250 assumptions and dependencies from the serial core. Convert UART core and PM support to use omap_device layer. Also add support for both console on 8250 or omap-serial driver. omap_device conversion: - Convert clock API calls to omap_device calls - Remove all static platform_data setup and configuration. This is all done by the omap_device build phase. Known issues: - broken on OMAP4 until OMAP4 UART hwmods are available Cc: Govindraj R <govindraj.raja@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> --- arch/arm/mach-omap2/serial.c | 474 +++++++++++++++++++++--------------------- 1 files changed, 242 insertions(+), 232 deletions(-) diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 8c964be..9060fb8 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -19,18 +19,30 @@ */ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/serial_8250.h> #include <linux/serial_reg.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_device.h> + +#ifdef CONFIG_SERIAL_8250_CONSOLE +#include <linux/serial_8250.h> +#endif + +#ifdef CONFIG_SERIAL_OMAP_CONSOLE +#include <plat/omap-serial.h> +#endif #include <plat/common.h> #include <plat/board.h> #include <plat/clock.h> #include <plat/control.h> +#include <plat/dma.h> +#include <plat/omap_hwmod.h> +#include <plat/omap_device.h> #include "prm.h" #include "pm.h" +#include "cm.h" #include "prm-regbits-34xx.h" #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 @@ -38,6 +50,8 @@ #define DEFAULT_TIMEOUT (5 * HZ) +#define MAX_UART_HWMOD_NAME_LEN 16 + struct omap_uart_state { int num; int can_sleep; @@ -48,14 +62,21 @@ struct omap_uart_state { void __iomem *wk_en; u32 wk_mask; u32 padconf; + u32 dma_enabled; struct clk *ick; struct clk *fck; int clocked; - struct plat_serial8250_port *p; + int irq; + int regshift; + int irqflags; + void __iomem *membase; + resource_size_t mapbase; + struct list_head node; - struct platform_device pdev; + struct omap_hwmod *oh; + struct platform_device *pdev; #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) int context_valid; @@ -71,60 +92,16 @@ struct omap_uart_state { }; static LIST_HEAD(uart_list); +static u8 num_uarts; -static struct plat_serial8250_port serial_platform_data0[] = { +static struct omap_device_pm_latency omap_uart_latency[] = { { - .mapbase = OMAP_UART1_BASE, - .irq = 72, - .flags = UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = OMAP24XX_BASE_BAUD * 16, - }, { - .flags = 0 - } -}; - -static struct plat_serial8250_port serial_platform_data1[] = { - { - .mapbase = OMAP_UART2_BASE, - .irq = 73, - .flags = UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = OMAP24XX_BASE_BAUD * 16, - }, { - .flags = 0 - } -}; - -static struct plat_serial8250_port serial_platform_data2[] = { - { - .mapbase = OMAP_UART3_BASE, - .irq = 74, - .flags = UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = OMAP24XX_BASE_BAUD * 16, - }, { - .flags = 0 - } + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, }; -#ifdef CONFIG_ARCH_OMAP4 -static struct plat_serial8250_port serial_platform_data3[] = { - { - .mapbase = OMAP_UART4_BASE, - .irq = 70, - .flags = UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = OMAP24XX_BASE_BAUD * 16, - }, { - .flags = 0 - } -}; -#endif static inline unsigned int __serial_read_reg(struct uart_port *up, int offset) { @@ -132,18 +109,18 @@ static inline unsigned int __serial_read_reg(struct uart_port *up, return (unsigned int)__raw_readb(up->membase + offset); } -static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, +static inline unsigned int serial_read_reg(struct omap_uart_state *up, int offset) { offset <<= up->regshift; return (unsigned int)__raw_readb(up->membase + offset); } -static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, +static inline void serial_write_reg(struct omap_uart_state *up, int offset, int value) { - offset <<= p->regshift; - __raw_writeb(value, p->membase + offset); + offset <<= up->regshift; + __raw_writeb(value, up->membase + offset); } /* @@ -151,14 +128,12 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, * properly. Note that the TX watermark initialization may not be needed * once the 8250.c watermark handling code is merged. */ -static inline void __init omap_uart_reset(struct omap_uart_state *uart) -{ - struct plat_serial8250_port *p = uart->p; +static inline void __init omap_uart_reset(struct omap_uart_state *p) +{ serial_write_reg(p, UART_OMAP_MDR1, 0x07); serial_write_reg(p, UART_OMAP_SCR, 0x08); serial_write_reg(p, UART_OMAP_MDR1, 0x00); - serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); } #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) @@ -166,20 +141,19 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart) static void omap_uart_save_context(struct omap_uart_state *uart) { u16 lcr = 0; - struct plat_serial8250_port *p = uart->p; if (!enable_off_mode) return; - lcr = serial_read_reg(p, UART_LCR); - serial_write_reg(p, UART_LCR, 0xBF); - uart->dll = serial_read_reg(p, UART_DLL); - uart->dlh = serial_read_reg(p, UART_DLM); - serial_write_reg(p, UART_LCR, lcr); - uart->ier = serial_read_reg(p, UART_IER); - uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); - uart->scr = serial_read_reg(p, UART_OMAP_SCR); - uart->wer = serial_read_reg(p, UART_OMAP_WER); + lcr = serial_read_reg(uart, UART_LCR); + serial_write_reg(uart, UART_LCR, 0xBF); + uart->dll = serial_read_reg(uart, UART_DLL); + uart->dlh = serial_read_reg(uart, UART_DLM); + serial_write_reg(uart, UART_LCR, lcr); + uart->ier = serial_read_reg(uart, UART_IER); + uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); + uart->scr = serial_read_reg(uart, UART_OMAP_SCR); + uart->wer = serial_read_reg(uart, UART_OMAP_WER); uart->context_valid = 1; } @@ -187,7 +161,6 @@ static void omap_uart_save_context(struct omap_uart_state *uart) static void omap_uart_restore_context(struct omap_uart_state *uart) { u16 efr = 0; - struct plat_serial8250_port *p = uart->p; if (!enable_off_mode) return; @@ -197,25 +170,25 @@ static void omap_uart_restore_context(struct omap_uart_state *uart) uart->context_valid = 0; - serial_write_reg(p, UART_OMAP_MDR1, 0x7); - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ - efr = serial_read_reg(p, UART_EFR); - serial_write_reg(p, UART_EFR, UART_EFR_ECB); - serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ - serial_write_reg(p, UART_IER, 0x0); - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ - serial_write_reg(p, UART_DLL, uart->dll); - serial_write_reg(p, UART_DLM, uart->dlh); - serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ - serial_write_reg(p, UART_IER, uart->ier); - serial_write_reg(p, UART_FCR, 0xA1); - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ - serial_write_reg(p, UART_EFR, efr); - serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); - serial_write_reg(p, UART_OMAP_SCR, uart->scr); - serial_write_reg(p, UART_OMAP_WER, uart->wer); - serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); - serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ + serial_write_reg(uart, UART_OMAP_MDR1, 0x7); + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ + efr = serial_read_reg(uart, UART_EFR); + serial_write_reg(uart, UART_EFR, UART_EFR_ECB); + serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ + serial_write_reg(uart, UART_IER, 0x0); + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ + serial_write_reg(uart, UART_DLL, uart->dll); + serial_write_reg(uart, UART_DLM, uart->dlh); + serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ + serial_write_reg(uart, UART_IER, uart->ier); + serial_write_reg(uart, UART_FCR, 0xA1); + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ + serial_write_reg(uart, UART_EFR, efr); + serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); + serial_write_reg(uart, UART_OMAP_SCR, uart->scr); + serial_write_reg(uart, UART_OMAP_WER, uart->wer); + serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); + serial_write_reg(uart, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ } #else static inline void omap_uart_save_context(struct omap_uart_state *uart) {} @@ -227,8 +200,7 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) if (uart->clocked) return; - clk_enable(uart->ick); - clk_enable(uart->fck); + omap_device_enable(uart->pdev); uart->clocked = 1; omap_uart_restore_context(uart); } @@ -242,8 +214,7 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) omap_uart_save_context(uart); uart->clocked = 0; - clk_disable(uart->ick); - clk_disable(uart->fck); + omap_device_idle(uart->pdev); } static void omap_uart_enable_wakeup(struct omap_uart_state *uart) @@ -280,19 +251,26 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart) } } -static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, - int enable) +static inline void omap_uart_smart_idle_enable(struct omap_uart_state *p, + int enable) { - struct plat_serial8250_port *p = uart->p; - u16 sysc; - - sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7; - if (enable) - sysc |= 0x2 << 3; - else - sysc |= 0x1 << 3; - - serial_write_reg(p, UART_OMAP_SYSC, sysc); + u32 sysc; + + sysc = omap_hwmod_read_sysc(p->oh); + sysc &= ~SYSC_SIDLEMODE_MASK; + if (enable) { + /** + * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests + * in Smartidle Mode When Configured for DMA Operations. + */ + if (p->dma_enabled) + sysc |= 0x0 << SYSC_SIDLEMODE_SHIFT; + else + sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT; + } else { + sysc |= 0x1 << SYSC_SIDLEMODE_SHIFT; + } + omap_hwmod_write_sysc(sysc, p->oh); } static void omap_uart_block_sleep(struct omap_uart_state *uart) @@ -309,7 +287,7 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart) static void omap_uart_allow_sleep(struct omap_uart_state *uart) { - if (device_may_wakeup(&uart->pdev.dev)) + if (device_may_wakeup(&uart->pdev->dev)) omap_uart_enable_wakeup(uart); else omap_uart_disable_wakeup(uart); @@ -404,6 +382,7 @@ int omap_uart_can_sleep(void) * UART will not idle or sleep for its timeout period. * **/ +/* static int first_interrupt; */ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) { struct omap_uart_state *uart = dev_id; @@ -415,7 +394,6 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) static void omap_uart_idle_init(struct omap_uart_state *uart) { - struct plat_serial8250_port *p = uart->p; int ret; uart->can_sleep = 0; @@ -477,9 +455,9 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) uart->padconf = 0; } - p->irqflags |= IRQF_SHARED; - ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, - "serial idle", (void *)uart); + uart->irqflags |= IRQF_SHARED; + ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt, + IRQF_SHARED, "serial idle", (void *)uart); WARN_ON(ret); } @@ -490,10 +468,13 @@ void omap_uart_enable_irqs(int enable) list_for_each_entry(uart, &uart_list, node) { if (enable) - ret = request_irq(uart->p->irq, omap_uart_interrupt, - IRQF_SHARED, "serial idle", (void *)uart); + ret = request_threaded_irq(uart->irq, NULL, + omap_uart_interrupt, + IRQF_SHARED, + "serial idle", + (void *)uart); else - free_irq(uart->p->irq, (void *)uart); + free_irq(uart->irq, (void *)uart); } } @@ -501,10 +482,9 @@ static ssize_t sleep_timeout_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct platform_device *pdev = container_of(dev, - struct platform_device, dev); - struct omap_uart_state *uart = container_of(pdev, - struct omap_uart_state, pdev); + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *odev = to_omap_device(pdev); + struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; return sprintf(buf, "%u\n", uart->timeout / HZ); } @@ -513,10 +493,9 @@ static ssize_t sleep_timeout_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { - struct platform_device *pdev = container_of(dev, - struct platform_device, dev); - struct omap_uart_state *uart = container_of(pdev, - struct omap_uart_state, pdev); + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *odev = to_omap_device(pdev); + struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; unsigned int value; if (sscanf(buf, "%u", &value) != 1) { @@ -541,45 +520,8 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} #define DEV_CREATE_FILE(dev, attr) #endif /* CONFIG_PM */ -static struct omap_uart_state omap_uart[] = { - { - .pdev = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = serial_platform_data0, - }, - }, - }, { - .pdev = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM1, - .dev = { - .platform_data = serial_platform_data1, - }, - }, - }, { - .pdev = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM2, - .dev = { - .platform_data = serial_platform_data2, - }, - }, - }, -#ifdef CONFIG_ARCH_OMAP4 - { - .pdev = { - .name = "serial8250", - .id = 3, - .dev = { - .platform_data = serial_platform_data3, - }, - }, - }, -#endif -}; +#ifdef CONFIG_SERIAL_8250_CONSOLE /* * Override the default 8250 read handler: mem_serial_in() * Empty RX fifo read causes an abort on omap3630 and omap4 @@ -597,61 +539,40 @@ static unsigned int serial_in_override(struct uart_port *up, int offset) return __serial_read_reg(up, offset); } +#endif void __init omap_serial_early_init(void) { - int i; - char name[16]; - - /* - * Make sure the serial ports are muxed on at this point. - * You have to mux them off in device drivers later on - * if not needed. - */ - - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) { - struct omap_uart_state *uart = &omap_uart[i]; - struct platform_device *pdev = &uart->pdev; - struct device *dev = &pdev->dev; - struct plat_serial8250_port *p = dev->platform_data; - - /* - * Module 4KB + L4 interconnect 4KB - * Static mapping, never released - */ - p->membase = ioremap(p->mapbase, SZ_8K); - if (!p->membase) { - printk(KERN_ERR "ioremap failed for uart%i\n", i + 1); - continue; - } + int i = 0; - sprintf(name, "uart%d_ick", i+1); - uart->ick = clk_get(NULL, name); - if (IS_ERR(uart->ick)) { - printk(KERN_ERR "Could not get uart%d_ick\n", i+1); - uart->ick = NULL; - } + do { + char oh_name[MAX_UART_HWMOD_NAME_LEN]; + struct omap_hwmod *oh; + struct omap_uart_state *uart; - sprintf(name, "uart%d_fck", i+1); - uart->fck = clk_get(NULL, name); - if (IS_ERR(uart->fck)) { - printk(KERN_ERR "Could not get uart%d_fck\n", i+1); - uart->fck = NULL; - } - - /* FIXME: Remove this once the clkdev is ready */ - if (!cpu_is_omap44xx()) { - if (!uart->ick || !uart->fck) - continue; - } + snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, + "uart%d_hwmod", i + 1); + oh = omap_hwmod_lookup(oh_name); + if (!oh) + break; - uart->num = i; - p->private_data = uart; - uart->p = p; + uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL); + if (WARN_ON(!uart)) + return; - if (cpu_is_omap44xx()) - p->irq += 32; - } + uart->oh = oh; + uart->num = i++; + list_add_tail(&uart->node, &uart_list); + num_uarts++; + + /* NOTE: omap_hwmod_init() has not yet been called, + * so no hwmod functions will work yet. */ +#ifdef CONFIG_DEBUG_LL + /* For DEBUG_LL, don't reset/idle the UARTs otherwise + * early UART access will fault. */ + uart->oh->flags |= HWMOD_INIT_NO_IDLE; +#endif + } while(1); } /** @@ -668,41 +589,130 @@ void __init omap_serial_early_init(void) void __init omap_serial_init_port(int port) { struct omap_uart_state *uart; - struct platform_device *pdev; - struct device *dev; + char *name; BUG_ON(port < 0); - BUG_ON(port >= ARRAY_SIZE(omap_uart)); + BUG_ON(port >= num_uarts); - uart = &omap_uart[port]; - pdev = &uart->pdev; - dev = &pdev->dev; + list_for_each_entry(uart, &uart_list, node) + if (port == uart->num) + break; - omap_uart_enable_clocks(uart); + { + struct omap_hwmod *oh = uart->oh; + struct omap_device *od; + void *pdata = NULL; + u32 pdata_size = 0; + +#ifdef CONFIG_SERIAL_8250_CONSOLE + struct plat_serial8250_port ports[2] = { + {}, + {.flags = 0}, + }; + struct plat_serial8250_port *p = &ports[0]; + + name = "serial8250"; + uart->dma_enabled = 0; + + /* + * !! 8250 driver does not use standard IORESOURCE* It + * has it's own custom pdata that can be taken from + * the hwmod resource data. But, this needs to be + * done after the build. + * + * ?? does it have to be done before the register ?? + * YES, because platform_device_data_add() copies + * pdata, it does not use a pointer. + */ + p->flags = UPF_BOOT_AUTOCONF; + p->iotype = UPIO_MEM; + p->regshift = 2; + p->uartclk = OMAP24XX_BASE_BAUD * 16; + p->irq = oh->mpu_irqs[0].irq; + p->mapbase = oh->slaves[0]->addr->pa_start; + p->membase = oh->_rt_va; + p->irqflags = IRQF_SHARED; + p->private_data = uart; - omap_uart_reset(uart); - omap_uart_idle_init(uart); + pdata = &ports[0]; + pdata_size = 2 * sizeof(struct plat_serial8250_port); +#endif +#ifdef CONFIG_SERIAL_OMAP_CONSOLE + struct omap_uart_port_info omap_up; - list_add_tail(&uart->node, &uart_list); + name = "omap-hsuart"; + uart->dma_enabled = 0; - if (WARN_ON(platform_device_register(pdev))) - return; + omap_up.dma_enabled = uart->dma_enabled; + omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; + omap_up.mapbase = oh->slaves[0]->addr->pa_start; + omap_up.membase = oh->_rt_va; + omap_up.irqflags = IRQF_SHARED; + omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; - if ((cpu_is_omap34xx() && uart->padconf) || - (uart->wk_en && uart->wk_mask)) { - device_init_wakeup(dev, true); - DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); - } + pdata = &omap_up; + pdata_size = sizeof(struct omap_uart_port_info); +#endif + if (WARN_ON(!oh)) + return; + + od = omap_device_build(name, uart->num, oh, pdata, pdata_size, + omap_uart_latency, + ARRAY_SIZE(omap_uart_latency)); + WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", + name, oh->name); + + uart->irq = oh->mpu_irqs[0].irq; + uart->regshift = 2; + uart->mapbase = oh->slaves[0]->addr->pa_start; + uart->membase = oh->_rt_va; + uart->pdev = &od->pdev; + + oh->dev_attr = uart; + +#ifdef CONFIG_DEBUG_LL + /* + * Because of earlyprintk output, UART did not get idled + * on init. Now that omap_device is ready, ensure full idle + * before doing omap_device_enable(). + */ + omap_hwmod_idle(uart->oh); +#endif + omap_device_enable(uart->pdev); + omap_uart_idle_init(uart); + omap_uart_reset(uart); + omap_hwmod_enable_wakeup(uart->oh); + omap_device_idle(uart->pdev); + + /* + * Need to block sleep long enough for interrupt driven + * driver to start. Console driver is in polling mode + * so device needs to be kept enabled while polling driver + * is in use. + */ + uart->timeout = (30 * HZ); + omap_uart_block_sleep(uart); + uart->timeout = DEFAULT_TIMEOUT; + + if ((cpu_is_omap34xx() && uart->padconf) || + (uart->wk_en && uart->wk_mask)) { + device_init_wakeup(&od->pdev.dev, true); + DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout); + } + +#ifdef CONFIG_SERIAL_8250_CONSOLE /* omap44xx: Never read empty UART fifo * omap3xxx: Never read empty UART fifo on UARTs * with IP rev >=0x52 */ if (cpu_is_omap44xx()) - uart->p->serial_in = serial_in_override; - else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF) + p->serial_in = serial_in_override; + else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF) >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) - uart->p->serial_in = serial_in_override; + p->serial_in = serial_in_override; +#endif + } } /** @@ -714,8 +724,8 @@ void __init omap_serial_init_port(int port) */ void __init omap_serial_init(void) { - int i; + struct omap_uart_state *uart; - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) - omap_serial_init_port(i); + list_for_each_entry(uart, &uart_list, node) + omap_serial_init_port(uart->num); } -- 1.6.6 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions 2010-01-12 23:58 ` [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions Kevin Hilman @ 2010-01-30 6:35 ` Nayak, Rajendra 2010-03-01 19:26 ` Kevin Hilman 0 siblings, 1 reply; 6+ messages in thread From: Nayak, Rajendra @ 2010-01-30 6:35 UTC (permalink / raw) To: Kevin Hilman, linux-omap@vger.kernel.org; +Cc: Raja, Govindraj Hi Kevin, > -----Original Message----- > From: linux-omap-owner@vger.kernel.org > [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of Kevin Hilman > Sent: Wednesday, January 13, 2010 5:29 AM > To: linux-omap@vger.kernel.org > Cc: Raja, Govindraj > Subject: [PATCH 2/2] OMAP: UART: omap_device converions, > remove implicit 8520 assumptions > > Major rework of OMAP UART init for omap_device conversion as well as > use with either 8250 driver or new omap-serial driver. > > Signifcant contributions and testing from Govindraj R > <govindraj.raja@ti.com>. > > In preparation for a new omap-serial driver, remove 8250 assumptions > and dependencies from the serial core. > > Convert UART core and PM support to use omap_device layer. Also add > support for both console on 8250 or omap-serial driver. > > omap_device conversion: > - Convert clock API calls to omap_device calls > - Remove all static platform_data setup and configuration. This is > all done by the omap_device build phase. > > Known issues: > - broken on OMAP4 until OMAP4 UART hwmods are available > > Cc: Govindraj R <govindraj.raja@ti.com> > Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> > --- > arch/arm/mach-omap2/serial.c | 474 > +++++++++++++++++++++--------------------- > 1 files changed, 242 insertions(+), 232 deletions(-) > > diff --git a/arch/arm/mach-omap2/serial.c > b/arch/arm/mach-omap2/serial.c > index 8c964be..9060fb8 100644 > --- a/arch/arm/mach-omap2/serial.c > +++ b/arch/arm/mach-omap2/serial.c > @@ -19,18 +19,30 @@ > */ > #include <linux/kernel.h> > #include <linux/init.h> > -#include <linux/serial_8250.h> > #include <linux/serial_reg.h> > #include <linux/clk.h> > #include <linux/io.h> > +#include <linux/platform_device.h> > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +#include <linux/serial_8250.h> > +#endif > + > +#ifdef CONFIG_SERIAL_OMAP_CONSOLE > +#include <plat/omap-serial.h> > +#endif > > #include <plat/common.h> > #include <plat/board.h> > #include <plat/clock.h> > #include <plat/control.h> > +#include <plat/dma.h> > +#include <plat/omap_hwmod.h> > +#include <plat/omap_device.h> > > #include "prm.h" > #include "pm.h" > +#include "cm.h" > #include "prm-regbits-34xx.h" > > #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 > @@ -38,6 +50,8 @@ > > #define DEFAULT_TIMEOUT (5 * HZ) > > +#define MAX_UART_HWMOD_NAME_LEN 16 > + > struct omap_uart_state { > int num; > int can_sleep; > @@ -48,14 +62,21 @@ struct omap_uart_state { > void __iomem *wk_en; > u32 wk_mask; > u32 padconf; > + u32 dma_enabled; > > struct clk *ick; > struct clk *fck; > int clocked; > > - struct plat_serial8250_port *p; > + int irq; > + int regshift; > + int irqflags; > + void __iomem *membase; > + resource_size_t mapbase; > + > struct list_head node; > - struct platform_device pdev; > + struct omap_hwmod *oh; > + struct platform_device *pdev; > > #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) > int context_valid; > @@ -71,60 +92,16 @@ struct omap_uart_state { > }; > > static LIST_HEAD(uart_list); > +static u8 num_uarts; > > -static struct plat_serial8250_port serial_platform_data0[] = { > +static struct omap_device_pm_latency omap_uart_latency[] = { > { > - .mapbase = OMAP_UART1_BASE, > - .irq = 72, > - .flags = UPF_BOOT_AUTOCONF, > - .iotype = UPIO_MEM, > - .regshift = 2, > - .uartclk = OMAP24XX_BASE_BAUD * 16, > - }, { > - .flags = 0 > - } > -}; > - > -static struct plat_serial8250_port serial_platform_data1[] = { > - { > - .mapbase = OMAP_UART2_BASE, > - .irq = 73, > - .flags = UPF_BOOT_AUTOCONF, > - .iotype = UPIO_MEM, > - .regshift = 2, > - .uartclk = OMAP24XX_BASE_BAUD * 16, > - }, { > - .flags = 0 > - } > -}; > - > -static struct plat_serial8250_port serial_platform_data2[] = { > - { > - .mapbase = OMAP_UART3_BASE, > - .irq = 74, > - .flags = UPF_BOOT_AUTOCONF, > - .iotype = UPIO_MEM, > - .regshift = 2, > - .uartclk = OMAP24XX_BASE_BAUD * 16, > - }, { > - .flags = 0 > - } > + .deactivate_func = omap_device_idle_hwmods, > + .activate_func = omap_device_enable_hwmods, > + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, > + }, > }; > > -#ifdef CONFIG_ARCH_OMAP4 > -static struct plat_serial8250_port serial_platform_data3[] = { > - { > - .mapbase = OMAP_UART4_BASE, > - .irq = 70, > - .flags = UPF_BOOT_AUTOCONF, > - .iotype = UPIO_MEM, > - .regshift = 2, > - .uartclk = OMAP24XX_BASE_BAUD * 16, > - }, { > - .flags = 0 > - } > -}; > -#endif > static inline unsigned int __serial_read_reg(struct uart_port *up, > int offset) > { > @@ -132,18 +109,18 @@ static inline unsigned int > __serial_read_reg(struct uart_port *up, > return (unsigned int)__raw_readb(up->membase + offset); > } > > -static inline unsigned int serial_read_reg(struct > plat_serial8250_port *up, > +static inline unsigned int serial_read_reg(struct > omap_uart_state *up, > int offset) > { > offset <<= up->regshift; > return (unsigned int)__raw_readb(up->membase + offset); > } > > -static inline void serial_write_reg(struct > plat_serial8250_port *p, int offset, > +static inline void serial_write_reg(struct omap_uart_state > *up, int offset, > int value) > { > - offset <<= p->regshift; > - __raw_writeb(value, p->membase + offset); > + offset <<= up->regshift; > + __raw_writeb(value, up->membase + offset); > } > > /* > @@ -151,14 +128,12 @@ static inline void > serial_write_reg(struct plat_serial8250_port *p, int offset, > * properly. Note that the TX watermark initialization may > not be needed > * once the 8250.c watermark handling code is merged. > */ > -static inline void __init omap_uart_reset(struct > omap_uart_state *uart) > -{ > - struct plat_serial8250_port *p = uart->p; > > +static inline void __init omap_uart_reset(struct omap_uart_state *p) > +{ > serial_write_reg(p, UART_OMAP_MDR1, 0x07); > serial_write_reg(p, UART_OMAP_SCR, 0x08); > serial_write_reg(p, UART_OMAP_MDR1, 0x00); > - serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << > 2) | (1 << 0)); > } > > #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) > @@ -166,20 +141,19 @@ static inline void __init > omap_uart_reset(struct omap_uart_state *uart) > static void omap_uart_save_context(struct omap_uart_state *uart) > { > u16 lcr = 0; > - struct plat_serial8250_port *p = uart->p; > > if (!enable_off_mode) > return; > > - lcr = serial_read_reg(p, UART_LCR); > - serial_write_reg(p, UART_LCR, 0xBF); > - uart->dll = serial_read_reg(p, UART_DLL); > - uart->dlh = serial_read_reg(p, UART_DLM); > - serial_write_reg(p, UART_LCR, lcr); > - uart->ier = serial_read_reg(p, UART_IER); > - uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); > - uart->scr = serial_read_reg(p, UART_OMAP_SCR); > - uart->wer = serial_read_reg(p, UART_OMAP_WER); > + lcr = serial_read_reg(uart, UART_LCR); > + serial_write_reg(uart, UART_LCR, 0xBF); > + uart->dll = serial_read_reg(uart, UART_DLL); > + uart->dlh = serial_read_reg(uart, UART_DLM); > + serial_write_reg(uart, UART_LCR, lcr); > + uart->ier = serial_read_reg(uart, UART_IER); > + uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); > + uart->scr = serial_read_reg(uart, UART_OMAP_SCR); > + uart->wer = serial_read_reg(uart, UART_OMAP_WER); > > uart->context_valid = 1; > } > @@ -187,7 +161,6 @@ static void omap_uart_save_context(struct > omap_uart_state *uart) > static void omap_uart_restore_context(struct omap_uart_state *uart) > { > u16 efr = 0; > - struct plat_serial8250_port *p = uart->p; > > if (!enable_off_mode) > return; > @@ -197,25 +170,25 @@ static void > omap_uart_restore_context(struct omap_uart_state *uart) > > uart->context_valid = 0; > > - serial_write_reg(p, UART_OMAP_MDR1, 0x7); > - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ > - efr = serial_read_reg(p, UART_EFR); > - serial_write_reg(p, UART_EFR, UART_EFR_ECB); > - serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ > - serial_write_reg(p, UART_IER, 0x0); > - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ > - serial_write_reg(p, UART_DLL, uart->dll); > - serial_write_reg(p, UART_DLM, uart->dlh); > - serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ > - serial_write_reg(p, UART_IER, uart->ier); > - serial_write_reg(p, UART_FCR, 0xA1); > - serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ > - serial_write_reg(p, UART_EFR, efr); > - serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); > - serial_write_reg(p, UART_OMAP_SCR, uart->scr); > - serial_write_reg(p, UART_OMAP_WER, uart->wer); > - serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); > - serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ > + serial_write_reg(uart, UART_OMAP_MDR1, 0x7); > + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ > + efr = serial_read_reg(uart, UART_EFR); > + serial_write_reg(uart, UART_EFR, UART_EFR_ECB); > + serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ > + serial_write_reg(uart, UART_IER, 0x0); > + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ > + serial_write_reg(uart, UART_DLL, uart->dll); > + serial_write_reg(uart, UART_DLM, uart->dlh); > + serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ > + serial_write_reg(uart, UART_IER, uart->ier); > + serial_write_reg(uart, UART_FCR, 0xA1); > + serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ > + serial_write_reg(uart, UART_EFR, efr); > + serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); > + serial_write_reg(uart, UART_OMAP_SCR, uart->scr); > + serial_write_reg(uart, UART_OMAP_WER, uart->wer); > + serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); > + serial_write_reg(uart, UART_OMAP_MDR1, 0x00); /* UART > 16x mode */ > } > #else > static inline void omap_uart_save_context(struct > omap_uart_state *uart) {} > @@ -227,8 +200,7 @@ static inline void > omap_uart_enable_clocks(struct omap_uart_state *uart) > if (uart->clocked) > return; > > - clk_enable(uart->ick); > - clk_enable(uart->fck); > + omap_device_enable(uart->pdev); > uart->clocked = 1; > omap_uart_restore_context(uart); > } > @@ -242,8 +214,7 @@ static inline void > omap_uart_disable_clocks(struct omap_uart_state *uart) > > omap_uart_save_context(uart); > uart->clocked = 0; > - clk_disable(uart->ick); > - clk_disable(uart->fck); > + omap_device_idle(uart->pdev); > } > > static void omap_uart_enable_wakeup(struct omap_uart_state *uart) > @@ -280,19 +251,26 @@ static void > omap_uart_disable_wakeup(struct omap_uart_state *uart) > } > } > > -static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, > - int enable) > +static inline void omap_uart_smart_idle_enable(struct > omap_uart_state *p, > + int enable) > { > - struct plat_serial8250_port *p = uart->p; > - u16 sysc; > - > - sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7; > - if (enable) > - sysc |= 0x2 << 3; > - else > - sysc |= 0x1 << 3; > - > - serial_write_reg(p, UART_OMAP_SYSC, sysc); > + u32 sysc; > + > + sysc = omap_hwmod_read_sysc(p->oh); > + sysc &= ~SYSC_SIDLEMODE_MASK; > + if (enable) { > + /** > + * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests > + * in Smartidle Mode When Configured for DMA Operations. > + */ > + if (p->dma_enabled) > + sysc |= 0x0 << SYSC_SIDLEMODE_SHIFT; > + else > + sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT; > + } else { > + sysc |= 0x1 << SYSC_SIDLEMODE_SHIFT; > + } > + omap_hwmod_write_sysc(sysc, p->oh); > } > > static void omap_uart_block_sleep(struct omap_uart_state *uart) > @@ -309,7 +287,7 @@ static void omap_uart_block_sleep(struct > omap_uart_state *uart) > > static void omap_uart_allow_sleep(struct omap_uart_state *uart) > { > - if (device_may_wakeup(&uart->pdev.dev)) > + if (device_may_wakeup(&uart->pdev->dev)) > omap_uart_enable_wakeup(uart); > else > omap_uart_disable_wakeup(uart); > @@ -404,6 +382,7 @@ int omap_uart_can_sleep(void) > * UART will not idle or sleep for its timeout period. > * > **/ > +/* static int first_interrupt; */ > static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) > { > struct omap_uart_state *uart = dev_id; > @@ -415,7 +394,6 @@ static irqreturn_t > omap_uart_interrupt(int irq, void *dev_id) > > static void omap_uart_idle_init(struct omap_uart_state *uart) > { > - struct plat_serial8250_port *p = uart->p; > int ret; > > uart->can_sleep = 0; > @@ -477,9 +455,9 @@ static void omap_uart_idle_init(struct > omap_uart_state *uart) > uart->padconf = 0; > } > > - p->irqflags |= IRQF_SHARED; > - ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, > - "serial idle", (void *)uart); > + uart->irqflags |= IRQF_SHARED; > + ret = request_threaded_irq(uart->irq, NULL, > omap_uart_interrupt, > + IRQF_SHARED, "serial idle", > (void *)uart); > WARN_ON(ret); > } > > @@ -490,10 +468,13 @@ void omap_uart_enable_irqs(int enable) > > list_for_each_entry(uart, &uart_list, node) { > if (enable) > - ret = request_irq(uart->p->irq, > omap_uart_interrupt, > - IRQF_SHARED, "serial idle", > (void *)uart); > + ret = request_threaded_irq(uart->irq, NULL, > + omap_uart_interrupt, > + IRQF_SHARED, > + "serial idle", > + (void *)uart); > else > - free_irq(uart->p->irq, (void *)uart); > + free_irq(uart->irq, (void *)uart); > } > } > > @@ -501,10 +482,9 @@ static ssize_t sleep_timeout_show(struct > device *dev, > struct device_attribute *attr, > char *buf) > { > - struct platform_device *pdev = container_of(dev, > - struct platform_device, dev); > - struct omap_uart_state *uart = container_of(pdev, > - struct omap_uart_state, pdev); > + struct platform_device *pdev = to_platform_device(dev); > + struct omap_device *odev = to_omap_device(pdev); > + struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; > > return sprintf(buf, "%u\n", uart->timeout / HZ); > } > @@ -513,10 +493,9 @@ static ssize_t > sleep_timeout_store(struct device *dev, > struct device_attribute *attr, > const char *buf, size_t n) > { > - struct platform_device *pdev = container_of(dev, > - struct platform_device, dev); > - struct omap_uart_state *uart = container_of(pdev, > - struct omap_uart_state, pdev); > + struct platform_device *pdev = to_platform_device(dev); > + struct omap_device *odev = to_omap_device(pdev); > + struct omap_uart_state *uart = odev->hwmods[0]->dev_attr; > unsigned int value; > > if (sscanf(buf, "%u", &value) != 1) { > @@ -541,45 +520,8 @@ static inline void > omap_uart_idle_init(struct omap_uart_state *uart) {} > #define DEV_CREATE_FILE(dev, attr) > #endif /* CONFIG_PM */ > > -static struct omap_uart_state omap_uart[] = { > - { > - .pdev = { > - .name = "serial8250", > - .id = PLAT8250_DEV_PLATFORM, > - .dev = { > - .platform_data = serial_platform_data0, > - }, > - }, > - }, { > - .pdev = { > - .name = "serial8250", > - .id = > PLAT8250_DEV_PLATFORM1, > - .dev = { > - .platform_data = serial_platform_data1, > - }, > - }, > - }, { > - .pdev = { > - .name = "serial8250", > - .id = > PLAT8250_DEV_PLATFORM2, > - .dev = { > - .platform_data = serial_platform_data2, > - }, > - }, > - }, > -#ifdef CONFIG_ARCH_OMAP4 > - { > - .pdev = { > - .name = "serial8250", > - .id = 3, > - .dev = { > - .platform_data = serial_platform_data3, > - }, > - }, > - }, > -#endif > -}; > > +#ifdef CONFIG_SERIAL_8250_CONSOLE > /* > * Override the default 8250 read handler: mem_serial_in() > * Empty RX fifo read causes an abort on omap3630 and omap4 > @@ -597,61 +539,40 @@ static unsigned int > serial_in_override(struct uart_port *up, int offset) > > return __serial_read_reg(up, offset); > } > +#endif > > void __init omap_serial_early_init(void) > { > - int i; > - char name[16]; > - > - /* > - * Make sure the serial ports are muxed on at this point. > - * You have to mux them off in device drivers later on > - * if not needed. > - */ > - > - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) { > - struct omap_uart_state *uart = &omap_uart[i]; > - struct platform_device *pdev = &uart->pdev; > - struct device *dev = &pdev->dev; > - struct plat_serial8250_port *p = dev->platform_data; > - > - /* > - * Module 4KB + L4 interconnect 4KB > - * Static mapping, never released > - */ > - p->membase = ioremap(p->mapbase, SZ_8K); > - if (!p->membase) { > - printk(KERN_ERR "ioremap failed for > uart%i\n", i + 1); > - continue; > - } > + int i = 0; > > - sprintf(name, "uart%d_ick", i+1); > - uart->ick = clk_get(NULL, name); > - if (IS_ERR(uart->ick)) { > - printk(KERN_ERR "Could not get > uart%d_ick\n", i+1); > - uart->ick = NULL; > - } > + do { > + char oh_name[MAX_UART_HWMOD_NAME_LEN]; > + struct omap_hwmod *oh; > + struct omap_uart_state *uart; > > - sprintf(name, "uart%d_fck", i+1); > - uart->fck = clk_get(NULL, name); > - if (IS_ERR(uart->fck)) { > - printk(KERN_ERR "Could not get > uart%d_fck\n", i+1); > - uart->fck = NULL; > - } > - > - /* FIXME: Remove this once the clkdev is ready */ > - if (!cpu_is_omap44xx()) { > - if (!uart->ick || !uart->fck) > - continue; > - } > + snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, > + "uart%d_hwmod", i + 1); > + oh = omap_hwmod_lookup(oh_name); > + if (!oh) > + break; > > - uart->num = i; > - p->private_data = uart; > - uart->p = p; > + uart = kzalloc(sizeof(struct omap_uart_state), > GFP_KERNEL); > + if (WARN_ON(!uart)) > + return; > > - if (cpu_is_omap44xx()) > - p->irq += 32; > - } > + uart->oh = oh; > + uart->num = i++; > + list_add_tail(&uart->node, &uart_list); > + num_uarts++; > + > + /* NOTE: omap_hwmod_init() has not yet been called, > + * so no hwmod functions will work yet. */ > +#ifdef CONFIG_DEBUG_LL > + /* For DEBUG_LL, don't reset/idle the UARTs otherwise > + * early UART access will fault. */ > + uart->oh->flags |= HWMOD_INIT_NO_IDLE; > +#endif > + } while(1); > } > > /** > @@ -668,41 +589,130 @@ void __init omap_serial_early_init(void) > void __init omap_serial_init_port(int port) > { > struct omap_uart_state *uart; > - struct platform_device *pdev; > - struct device *dev; > + char *name; > > BUG_ON(port < 0); > - BUG_ON(port >= ARRAY_SIZE(omap_uart)); > + BUG_ON(port >= num_uarts); > > - uart = &omap_uart[port]; > - pdev = &uart->pdev; > - dev = &pdev->dev; > + list_for_each_entry(uart, &uart_list, node) > + if (port == uart->num) > + break; > > - omap_uart_enable_clocks(uart); > + { > + struct omap_hwmod *oh = uart->oh; > + struct omap_device *od; > + void *pdata = NULL; > + u32 pdata_size = 0; > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > + struct plat_serial8250_port ports[2] = { > + {}, > + {.flags = 0}, > + }; > + struct plat_serial8250_port *p = &ports[0]; > + > + name = "serial8250"; > + uart->dma_enabled = 0; > + > + /* > + * !! 8250 driver does not use standard IORESOURCE* It > + * has it's own custom pdata that can be taken from > + * the hwmod resource data. But, this needs to be > + * done after the build. > + * > + * ?? does it have to be done before the register ?? > + * YES, because platform_device_data_add() copies > + * pdata, it does not use a pointer. > + */ > + p->flags = UPF_BOOT_AUTOCONF; > + p->iotype = UPIO_MEM; > + p->regshift = 2; > + p->uartclk = OMAP24XX_BASE_BAUD * 16; > + p->irq = oh->mpu_irqs[0].irq; > + p->mapbase = oh->slaves[0]->addr->pa_start; > + p->membase = oh->_rt_va; > + p->irqflags = IRQF_SHARED; > + p->private_data = uart; > > - omap_uart_reset(uart); > - omap_uart_idle_init(uart); > + pdata = &ports[0]; > + pdata_size = 2 * sizeof(struct plat_serial8250_port); > +#endif > +#ifdef CONFIG_SERIAL_OMAP_CONSOLE > + struct omap_uart_port_info omap_up; > > - list_add_tail(&uart->node, &uart_list); > + name = "omap-hsuart"; > + uart->dma_enabled = 0; > > - if (WARN_ON(platform_device_register(pdev))) > - return; > + omap_up.dma_enabled = uart->dma_enabled; > + omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; > + omap_up.mapbase = oh->slaves[0]->addr->pa_start; > + omap_up.membase = oh->_rt_va; > + omap_up.irqflags = IRQF_SHARED; > + omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; > > - if ((cpu_is_omap34xx() && uart->padconf) || > - (uart->wk_en && uart->wk_mask)) { > - device_init_wakeup(dev, true); > - DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); > - } > + pdata = &omap_up; > + pdata_size = sizeof(struct omap_uart_port_info); > +#endif > > + if (WARN_ON(!oh)) > + return; > + > + od = omap_device_build(name, uart->num, oh, > pdata, pdata_size, > + omap_uart_latency, > + ARRAY_SIZE(omap_uart_latency)); > + WARN(IS_ERR(od), "Could not build omap_device > for %s: %s.\n", > + name, oh->name); > + > + uart->irq = oh->mpu_irqs[0].irq; > + uart->regshift = 2; > + uart->mapbase = oh->slaves[0]->addr->pa_start; > + uart->membase = oh->_rt_va; > + uart->pdev = &od->pdev; > + > + oh->dev_attr = uart; > + > +#ifdef CONFIG_DEBUG_LL > + /* > + * Because of earlyprintk output, UART did not get idled > + * on init. Now that omap_device is ready, > ensure full idle > + * before doing omap_device_enable(). > + */ > + omap_hwmod_idle(uart->oh); > +#endif > + omap_device_enable(uart->pdev); > + omap_uart_idle_init(uart); > + omap_uart_reset(uart); > + omap_hwmod_enable_wakeup(uart->oh); > + omap_device_idle(uart->pdev); > + > + /* > + * Need to block sleep long enough for interrupt driven > + * driver to start. Console driver is in polling mode > + * so device needs to be kept enabled while > polling driver > + * is in use. > + */ > + uart->timeout = (30 * HZ); > + omap_uart_block_sleep(uart); > + uart->timeout = DEFAULT_TIMEOUT; > + > + if ((cpu_is_omap34xx() && uart->padconf) || > + (uart->wk_en && uart->wk_mask)) { > + device_init_wakeup(&od->pdev.dev, true); > + DEV_CREATE_FILE(&od->pdev.dev, > &dev_attr_sleep_timeout); > + } > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > /* omap44xx: Never read empty UART fifo > * omap3xxx: Never read empty UART fifo on UARTs > * with IP rev >=0x52 > */ > if (cpu_is_omap44xx()) > - uart->p->serial_in = serial_in_override; > - else if ((serial_read_reg(uart->p, > UART_OMAP_MVER) & 0xFF) > + p->serial_in = serial_in_override; > + else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF) > >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) > - uart->p->serial_in = serial_in_override; > + p->serial_in = serial_in_override; > +#endif I think this (overriding serial_in) needs to be done sometime before you do a omap_device_build() call. Else this has no affect. > + } > } > > /** > @@ -714,8 +724,8 @@ void __init omap_serial_init_port(int port) > */ > void __init omap_serial_init(void) > { > - int i; > + struct omap_uart_state *uart; > > - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) > - omap_serial_init_port(i); > + list_for_each_entry(uart, &uart_list, node) > + omap_serial_init_port(uart->num); > } > -- > 1.6.6 > > -- > To unsubscribe from this list: send the line "unsubscribe > linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions 2010-01-30 6:35 ` Nayak, Rajendra @ 2010-03-01 19:26 ` Kevin Hilman 0 siblings, 0 replies; 6+ messages in thread From: Kevin Hilman @ 2010-03-01 19:26 UTC (permalink / raw) To: Nayak, Rajendra; +Cc: linux-omap@vger.kernel.org, Raja, Govindraj "Nayak, Rajendra" <rnayak@ti.com> writes: [...] >> + /* >> + * Need to block sleep long enough for interrupt driven >> + * driver to start. Console driver is in polling mode >> + * so device needs to be kept enabled while >> polling driver >> + * is in use. >> + */ >> + uart->timeout = (30 * HZ); >> + omap_uart_block_sleep(uart); >> + uart->timeout = DEFAULT_TIMEOUT; >> + >> + if ((cpu_is_omap34xx() && uart->padconf) || >> + (uart->wk_en && uart->wk_mask)) { >> + device_init_wakeup(&od->pdev.dev, true); >> + DEV_CREATE_FILE(&od->pdev.dev, >> &dev_attr_sleep_timeout); >> + } >> + >> +#ifdef CONFIG_SERIAL_8250_CONSOLE >> /* omap44xx: Never read empty UART fifo >> * omap3xxx: Never read empty UART fifo on UARTs >> * with IP rev >=0x52 >> */ >> if (cpu_is_omap44xx()) >> - uart->p->serial_in = serial_in_override; >> - else if ((serial_read_reg(uart->p, >> UART_OMAP_MVER) & 0xFF) >> + p->serial_in = serial_in_override; >> + else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF) >> >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV) >> - uart->p->serial_in = serial_in_override; >> + p->serial_in = serial_in_override; >> +#endif > > I think this (overriding serial_in) needs to be done sometime before you do a > omap_device_build() call. Else this has no affect. > Thanks Rajendra, you're right, good catch. Will fix in next spin. Thanks , Kevin ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod 2010-01-12 23:58 [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman 2010-01-12 23:58 ` [PATCH 1/2] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman 2010-01-12 23:58 ` [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions Kevin Hilman @ 2010-01-13 0:04 ` Kevin Hilman 2 siblings, 0 replies; 6+ messages in thread From: Kevin Hilman @ 2010-01-13 0:04 UTC (permalink / raw) To: Govindraj R; +Cc: linux-omap Kevin Hilman <khilman@deeprootsystems.com> writes: > This series applies on curren PM branch plus my omap_device series > posted on 8 jan: > > [PATCH 0/3] misc. omap_device/omap_hwmod updates > > and is also available as branch 'pm-wip/uart' in my linux-omap-pm repo[1]. > > This series should allow further development and testing of the new > omap-serial driver from Govindraj. Govindraj, I forgot to mention that I tested this both with the 8250 driver and your V4 omap-serial driver. There still seem to be some strange hangs when using omap-serial driver compard to 8250, especially when booting a full userspace like Arago. I haven't debugged fully, but omap-serial needs some more testing with this. Kevin ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-03-01 19:26 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-01-12 23:58 [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman 2010-01-12 23:58 ` [PATCH 1/2] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman 2010-01-12 23:58 ` [PATCH 2/2] OMAP: UART: omap_device converions, remove implicit 8520 assumptions Kevin Hilman 2010-01-30 6:35 ` Nayak, Rajendra 2010-03-01 19:26 ` Kevin Hilman 2010-01-13 0:04 ` [PATCH 0/2] OMAP: UART conversion to omap_device/omap_hwmod Kevin Hilman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox