* Re: [PATCH 3/3] OMAP: UART: convert to use omap_device layer
@ 2009-12-11 13:23 Govindraj.R
2009-12-11 16:58 ` Kevin Hilman
0 siblings, 1 reply; 3+ messages in thread
From: Govindraj.R @ 2009-12-11 13:23 UTC (permalink / raw)
To: Kevin Hilman; +Cc: linux-omap
Kevin,
I have following changes on top of this patch,
1.) Updated omap_uart_port_info as per your comments.
2.) Added Errata 2.15 for DMA mode.
3.) Fix compilation error if omap-serial is enabled with 8250.
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c067416..cbe1f76 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -249,10 +249,18 @@ static inline void omap_uart_smart_idle_enable(struct omap_uart_state *p,
sysc = omap_hwmod_read_sysc(p->oh);
sysc &= ~SYSC_SIDLEMODE_MASK;
- if (enable)
- sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT;
- else
+ 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);
}
@@ -540,14 +548,17 @@ void __init omap_serial_early_init(void)
void __init omap_serial_init(void)
{
struct omap_uart_state *uart;
+ char *name;
list_for_each_entry(uart, &uart_list, node) {
struct omap_hwmod *oh = uart->oh;
struct omap_device *od;
void *pdata = NULL;
u32 pdata_size = 0;
+
+ uart->dma_enabled = 0;
#ifdef CONFIG_SERIAL_8250_CONSOLE
- char *name = "serial8250";
+ name = "serial8250";
struct plat_serial8250_port ports[2] = {
{},
{.flags = 0},
@@ -578,14 +589,20 @@ void __init omap_serial_init(void)
pdata_size = 2 * sizeof(struct plat_serial8250_port);
#endif
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
- struct uart_port_info p;
- char *name = "omap-hsuart";
+ struct omap_uart_port_info omap_up;
+ name = "omap-hsuart";
+
+ omap_up.dma_enabled = 0;
+ uart->dma_enabled = omap_up.dma_enabled;
- p.dma_enabled = 0;
- p.uartclk = OMAP24XX_BASE_BAUD * 16;
+ 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;
- pdata = &p;
- pdata_size = sizeof(struct uart_port_info);
+ pdata = &omap_up;
+ pdata_size = sizeof(struct omap_uart_port_info);
#endif
if (WARN_ON(!oh))
Do you want me to re-post this patch integrating the above changes?
If changes are fine with you.
--
Regards,
Govindraj.R
On Wed, Nov 25, 2009 at 1:26 AM, Kevin Hilman <khilman@deeprootsystems.com> wrote:
> 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
>
> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
> ---
> arch/arm/mach-omap2/serial.c | 338 +++++++++++++++++++-----------------------
> 1 files changed, 154 insertions(+), 184 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
> index 3595ffa..c067416 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -24,20 +24,33 @@
> #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_WER 0x17 /* Wake-up enable register */
>
> #define DEFAULT_TIMEOUT (5 * HZ)
>
> +#define MAX_UART_HWMOD_NAME_LEN 16
> +
> struct omap_uart_state {
> int num;
> int can_sleep;
> @@ -61,7 +74,8 @@ struct omap_uart_state {
> 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;
> @@ -78,102 +92,13 @@ struct omap_uart_state {
>
> static LIST_HEAD(uart_list);
>
> -#ifdef CONFIG_SERIAL_8250
> -#include <linux/serial_8250.h>
> -
> -static struct plat_serial8250_port serial_platform_data0[] = {
> - {
> - .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[] = {
> +static struct omap_device_pm_latency omap_uart_latency[] = {
> {
> - .mapbase = OMAP_UART3_BASE,
> - .irq = 74,
> - .flags = UPF_BOOT_AUTOCONF,
> - .iotype = UPIO_MEM,
> - .regshift = 2,
> - .uartclk = OMAP24XX_BASE_BAUD * 16,
> - }, {
> - .flags = 0
> - }
> -};
> -
> -#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 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,
> - },
> - },
> + .deactivate_func = omap_device_idle_hwmods,
> + .activate_func = omap_device_enable_hwmods,
> + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> },
> -#endif
> };
> -#endif
>
> static inline unsigned int serial_read_reg(struct omap_uart_state *up,
> int offset)
> @@ -200,7 +125,6 @@ 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)
> @@ -267,8 +191,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);
> }
> @@ -282,8 +205,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)
> @@ -320,18 +242,18 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
> }
> }
>
> -static void omap_uart_smart_idle_enable(struct omap_uart_state *p,
> - int enable)
> +static inline void omap_uart_smart_idle_enable(struct omap_uart_state *p,
> + int enable)
> {
> - u16 sysc;
> + u32 sysc;
>
> - sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
> + sysc = omap_hwmod_read_sysc(p->oh);
> + sysc &= ~SYSC_SIDLEMODE_MASK;
> if (enable)
> - sysc |= 0x2 << 3;
> + sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT;
> else
> - sysc |= 0x1 << 3;
> -
> - serial_write_reg(p, UART_OMAP_SYSC, sysc);
> + sysc |= 0x1 << SYSC_SIDLEMODE_SHIFT;
> + omap_hwmod_write_sysc(sysc, p->oh);
> }
>
> static void omap_uart_block_sleep(struct omap_uart_state *uart)
> @@ -348,7 +270,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);
> @@ -443,6 +365,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;
> @@ -516,8 +439,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
> }
>
> uart->irqflags |= IRQF_SHARED;
> - ret = request_irq(uart->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);
> WARN_ON(ret);
> }
>
> @@ -528,8 +451,11 @@ void omap_uart_enable_irqs(int enable)
>
> list_for_each_entry(uart, &uart_list, node) {
> if (enable)
> - ret = request_irq(uart->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->irq, (void *)uart);
> }
> @@ -539,10 +465,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);
> }
> @@ -551,10 +476,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) {
> @@ -582,87 +506,133 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
>
> 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.
> - */
> + int i = 0;
>
> - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
> - struct omap_uart_state *uart = &omap_uart[i];
> + do {
> + char oh_name[MAX_UART_HWMOD_NAME_LEN];
> + struct omap_hwmod *oh;
> + struct omap_uart_state *uart;
>
> - uart->num = i;
> -
> - /*
> - * Module 4KB + L4 interconnect 4KB
> - * Static mapping, never released
> - */
> - uart->membase = ioremap(uart->mapbase, SZ_8K);
> - if (!uart->membase) {
> - printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
> - continue;
> - }
> -
> - 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;
> - }
> -
> - 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;
> - }
> + snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
> + "uart%d_hwmod", i + 1);
> + oh = omap_hwmod_lookup(oh_name);
> + if (!oh)
> + break;
>
> - /* FIXME: Remove this once the clkdev is ready */
> - if (!cpu_is_omap44xx()) {
> - if (!uart->ick || !uart->fck)
> - continue;
> - }
> + uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
> + if (WARN_ON(!uart))
> + return;
>
> + uart->oh = oh;
> + uart->num = i++;
> list_add_tail(&uart->node, &uart_list);
>
> - if (cpu_is_omap44xx())
> - uart->irq += 32;
> -
> - omap_uart_enable_clocks(uart);
> - }
> + /* 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);
> }
>
> void __init omap_serial_init(void)
> {
> - int i;
> -
> - 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;
> -#ifdef CONFIG_SERIAL_8250
> - struct plat_serial8250_port *p = dev->platform_data;
> + struct omap_uart_state *uart;
> +
> + list_for_each_entry(uart, &uart_list, node) {
> + struct omap_hwmod *oh = uart->oh;
> + struct omap_device *od;
> + void *pdata = NULL;
> + u32 pdata_size = 0;
> +#ifdef CONFIG_SERIAL_8250_CONSOLE
> + char *name = "serial8250";
> + struct plat_serial8250_port ports[2] = {
> + {},
> + {.flags = 0},
> + };
> + struct plat_serial8250_port *p = &ports[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;
> +
> + pdata = &ports[0];
> + pdata_size = 2 * sizeof(struct plat_serial8250_port);
> #endif
> +#ifdef CONFIG_SERIAL_OMAP_CONSOLE
> + struct uart_port_info p;
> + char *name = "omap-hsuart";
>
> - omap_uart_reset(uart);
> - omap_uart_idle_init(uart);
> + p.dma_enabled = 0;
> + p.uartclk = OMAP24XX_BASE_BAUD * 16;
>
> -#ifdef CONFIG_SERIAL_8250
> - p->membase = uart->membase;
> - p->mapbase = uart->mapbase;
> - p->irq = uart->irq;
> - p->irqflags = uart->irqflags;
> - p->private_data = uart;
> + pdata = &p;
> + pdata_size = sizeof(struct uart_port_info);
> #endif
> - if (WARN_ON(platform_device_register(pdev)))
> +
> + if (WARN_ON(!oh))
> continue;
> +
> + 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(dev, true);
> - DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
> + device_init_wakeup(&od->pdev.dev, true);
> + DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
> }
> }
> }
> --
> 1.6.5.1
>
> --
> 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 related [flat|nested] 3+ messages in thread* Re: [PATCH 3/3] OMAP: UART: convert to use omap_device layer
2009-12-11 13:23 [PATCH 3/3] OMAP: UART: convert to use omap_device layer Govindraj.R
@ 2009-12-11 16:58 ` Kevin Hilman
0 siblings, 0 replies; 3+ messages in thread
From: Kevin Hilman @ 2009-12-11 16:58 UTC (permalink / raw)
To: Govindraj.R; +Cc: linux-omap
"Govindraj.R" <govindraj.raja@ti.com> writes:
> Kevin,
>
> I have following changes on top of this patch,
> 1.) Updated omap_uart_port_info as per your comments.
> 2.) Added Errata 2.15 for DMA mode.
> 3.) Fix compilation error if omap-serial is enabled with 8250.
Thanks! looks great.
[...]
>
> Do you want me to re-post this patch integrating the above changes?
> If changes are fine with you.
>
I need to update my omap_device series on top of latest l-o
and Paul's updates so I will incorporate your changes into the next
version.
Kevin
>
> On Wed, Nov 25, 2009 at 1:26 AM, Kevin Hilman <khilman@deeprootsystems.com> wrote:
>> 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
>>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>> ---
>> arch/arm/mach-omap2/serial.c | 338 +++++++++++++++++++-----------------------
>> 1 files changed, 154 insertions(+), 184 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
>> index 3595ffa..c067416 100644
>> --- a/arch/arm/mach-omap2/serial.c
>> +++ b/arch/arm/mach-omap2/serial.c
>> @@ -24,20 +24,33 @@
>> #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_WER 0x17 /* Wake-up enable register */
>>
>> #define DEFAULT_TIMEOUT (5 * HZ)
>>
>> +#define MAX_UART_HWMOD_NAME_LEN 16
>> +
>> struct omap_uart_state {
>> int num;
>> int can_sleep;
>> @@ -61,7 +74,8 @@ struct omap_uart_state {
>> 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;
>> @@ -78,102 +92,13 @@ struct omap_uart_state {
>>
>> static LIST_HEAD(uart_list);
>>
>> -#ifdef CONFIG_SERIAL_8250
>> -#include <linux/serial_8250.h>
>> -
>> -static struct plat_serial8250_port serial_platform_data0[] = {
>> - {
>> - .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[] = {
>> +static struct omap_device_pm_latency omap_uart_latency[] = {
>> {
>> - .mapbase = OMAP_UART3_BASE,
>> - .irq = 74,
>> - .flags = UPF_BOOT_AUTOCONF,
>> - .iotype = UPIO_MEM,
>> - .regshift = 2,
>> - .uartclk = OMAP24XX_BASE_BAUD * 16,
>> - }, {
>> - .flags = 0
>> - }
>> -};
>> -
>> -#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 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,
>> - },
>> - },
>> + .deactivate_func = omap_device_idle_hwmods,
>> + .activate_func = omap_device_enable_hwmods,
>> + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
>> },
>> -#endif
>> };
>> -#endif
>>
>> static inline unsigned int serial_read_reg(struct omap_uart_state *up,
>> int offset)
>> @@ -200,7 +125,6 @@ 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)
>> @@ -267,8 +191,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);
>> }
>> @@ -282,8 +205,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)
>> @@ -320,18 +242,18 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
>> }
>> }
>>
>> -static void omap_uart_smart_idle_enable(struct omap_uart_state *p,
>> - int enable)
>> +static inline void omap_uart_smart_idle_enable(struct omap_uart_state *p,
>> + int enable)
>> {
>> - u16 sysc;
>> + u32 sysc;
>>
>> - sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
>> + sysc = omap_hwmod_read_sysc(p->oh);
>> + sysc &= ~SYSC_SIDLEMODE_MASK;
>> if (enable)
>> - sysc |= 0x2 << 3;
>> + sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT;
>> else
>> - sysc |= 0x1 << 3;
>> -
>> - serial_write_reg(p, UART_OMAP_SYSC, sysc);
>> + sysc |= 0x1 << SYSC_SIDLEMODE_SHIFT;
>> + omap_hwmod_write_sysc(sysc, p->oh);
>> }
>>
>> static void omap_uart_block_sleep(struct omap_uart_state *uart)
>> @@ -348,7 +270,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);
>> @@ -443,6 +365,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;
>> @@ -516,8 +439,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
>> }
>>
>> uart->irqflags |= IRQF_SHARED;
>> - ret = request_irq(uart->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);
>> WARN_ON(ret);
>> }
>>
>> @@ -528,8 +451,11 @@ void omap_uart_enable_irqs(int enable)
>>
>> list_for_each_entry(uart, &uart_list, node) {
>> if (enable)
>> - ret = request_irq(uart->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->irq, (void *)uart);
>> }
>> @@ -539,10 +465,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);
>> }
>> @@ -551,10 +476,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) {
>> @@ -582,87 +506,133 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
>>
>> 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.
>> - */
>> + int i = 0;
>>
>> - for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
>> - struct omap_uart_state *uart = &omap_uart[i];
>> + do {
>> + char oh_name[MAX_UART_HWMOD_NAME_LEN];
>> + struct omap_hwmod *oh;
>> + struct omap_uart_state *uart;
>>
>> - uart->num = i;
>> -
>> - /*
>> - * Module 4KB + L4 interconnect 4KB
>> - * Static mapping, never released
>> - */
>> - uart->membase = ioremap(uart->mapbase, SZ_8K);
>> - if (!uart->membase) {
>> - printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
>> - continue;
>> - }
>> -
>> - 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;
>> - }
>> -
>> - 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;
>> - }
>> + snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
>> + "uart%d_hwmod", i + 1);
>> + oh = omap_hwmod_lookup(oh_name);
>> + if (!oh)
>> + break;
>>
>> - /* FIXME: Remove this once the clkdev is ready */
>> - if (!cpu_is_omap44xx()) {
>> - if (!uart->ick || !uart->fck)
>> - continue;
>> - }
>> + uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
>> + if (WARN_ON(!uart))
>> + return;
>>
>> + uart->oh = oh;
>> + uart->num = i++;
>> list_add_tail(&uart->node, &uart_list);
>>
>> - if (cpu_is_omap44xx())
>> - uart->irq += 32;
>> -
>> - omap_uart_enable_clocks(uart);
>> - }
>> + /* 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);
>> }
>>
>> void __init omap_serial_init(void)
>> {
>> - int i;
>> -
>> - 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;
>> -#ifdef CONFIG_SERIAL_8250
>> - struct plat_serial8250_port *p = dev->platform_data;
>> + struct omap_uart_state *uart;
>> +
>> + list_for_each_entry(uart, &uart_list, node) {
>> + struct omap_hwmod *oh = uart->oh;
>> + struct omap_device *od;
>> + void *pdata = NULL;
>> + u32 pdata_size = 0;
>> +#ifdef CONFIG_SERIAL_8250_CONSOLE
>> + char *name = "serial8250";
>> + struct plat_serial8250_port ports[2] = {
>> + {},
>> + {.flags = 0},
>> + };
>> + struct plat_serial8250_port *p = &ports[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;
>> +
>> + pdata = &ports[0];
>> + pdata_size = 2 * sizeof(struct plat_serial8250_port);
>> #endif
>> +#ifdef CONFIG_SERIAL_OMAP_CONSOLE
>> + struct uart_port_info p;
>> + char *name = "omap-hsuart";
>>
>> - omap_uart_reset(uart);
>> - omap_uart_idle_init(uart);
>> + p.dma_enabled = 0;
>> + p.uartclk = OMAP24XX_BASE_BAUD * 16;
>>
>> -#ifdef CONFIG_SERIAL_8250
>> - p->membase = uart->membase;
>> - p->mapbase = uart->mapbase;
>> - p->irq = uart->irq;
>> - p->irqflags = uart->irqflags;
>> - p->private_data = uart;
>> + pdata = &p;
>> + pdata_size = sizeof(struct uart_port_info);
>> #endif
>> - if (WARN_ON(platform_device_register(pdev)))
>> +
>> + if (WARN_ON(!oh))
>> continue;
>> +
>> + 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(dev, true);
>> - DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
>> + device_init_wakeup(&od->pdev.dev, true);
>> + DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
>> }
>> }
>> }
>> --
>> 1.6.5.1
>>
>> --
>> 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] 3+ messages in thread
* [PATCH 0/3] UART conversion to omap_device layer
@ 2009-11-24 19:56 Kevin Hilman
2009-11-24 19:56 ` [PATCH 1/3] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman
0 siblings, 1 reply; 3+ messages in thread
From: Kevin Hilman @ 2009-11-24 19:56 UTC (permalink / raw)
To: linux-omap
This series converts the UART core and PM code to use the omap_device
layer based on the omap_hwmod layer.
This depends on the various omap_hwmod and omap_device updates from
Paul as well as omap_hwmod and omap_device patches I've sent to the
list. The 'pm-wip/omap_device' branch in my linux-omap-pm git tree
has a collection of all these hwmod/omap_device changes. This UART
series applies on top of the pm-wip/omap_device branch.
This series is also available in my git tree as branch 'pm-wip/uart'
Tested on 3430SDP only using 8250 driver and latest version of
omap-serial driver from Govindraj.
Govindraj R (1):
OMAP: UART: remove 8520 assumptions from UART core
Kevin Hilman (2):
OMAP3: add omap_hwmods for UART1,2,3
OMAP: UART: convert to use omap_device layer
arch/arm/mach-omap2/omap_hwmod_34xx.h | 188 +++++++++++++++
arch/arm/mach-omap2/serial.c | 418 ++++++++++++++++-----------------
2 files changed, 389 insertions(+), 217 deletions(-)
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/3] OMAP3: add omap_hwmods for UART1,2,3
2009-11-24 19:56 [PATCH 0/3] UART conversion to " Kevin Hilman
@ 2009-11-24 19:56 ` Kevin Hilman
2009-11-24 19:56 ` [PATCH 2/3] OMAP: UART: remove 8520 assumptions from UART core Kevin Hilman
0 siblings, 1 reply; 3+ messages in thread
From: Kevin Hilman @ 2009-11-24 19:56 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.5.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/3] OMAP: UART: remove 8520 assumptions from UART core
2009-11-24 19:56 ` [PATCH 1/3] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman
@ 2009-11-24 19:56 ` Kevin Hilman
2009-11-24 19:56 ` [PATCH 3/3] OMAP: UART: convert to use omap_device layer Kevin Hilman
0 siblings, 1 reply; 3+ messages in thread
From: Kevin Hilman @ 2009-11-24 19:56 UTC (permalink / raw)
To: linux-omap; +Cc: Govindraj R
From: Govindraj R <govindraj.raja@ti.com>
In preparation for a new omap-serial driver, remove 8250 assumptions
and dependencies from the serial core.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/serial.c | 202 ++++++++++++++++++++++-------------------
1 files changed, 108 insertions(+), 94 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 2e17b57..3595ffa 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,15 +19,16 @@
*/
#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>
#include <plat/common.h>
#include <plat/board.h>
#include <plat/clock.h>
#include <plat/control.h>
+#include <plat/dma.h>
#include "prm.h"
#include "pm.h"
@@ -47,12 +48,18 @@ 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;
@@ -71,6 +78,9 @@ struct omap_uart_state {
static LIST_HEAD(uart_list);
+#ifdef CONFIG_SERIAL_8250
+#include <linux/serial_8250.h>
+
static struct plat_serial8250_port serial_platform_data0[] = {
{
.mapbase = OMAP_UART1_BASE,
@@ -124,18 +134,59 @@ static struct plat_serial8250_port serial_platform_data3[] = {
}
};
#endif
-static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+
+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
+};
+#endif
+
+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);
}
/*
@@ -143,10 +194,9 @@ 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);
@@ -158,20 +208,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;
}
@@ -179,7 +228,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;
@@ -189,25 +237,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) {}
@@ -272,10 +320,9 @@ 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 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;
@@ -407,7 +454,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;
@@ -469,8 +515,8 @@ 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,
+ uart->irqflags |= IRQF_SHARED;
+ ret = request_irq(uart->irq, omap_uart_interrupt, IRQF_SHARED,
"serial idle", (void *)uart);
WARN_ON(ret);
}
@@ -482,10 +528,10 @@ 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,
+ ret = request_irq(uart->irq, omap_uart_interrupt,
IRQF_SHARED, "serial idle", (void *)uart);
else
- free_irq(uart->p->irq, (void *)uart);
+ free_irq(uart->irq, (void *)uart);
}
}
@@ -533,44 +579,6 @@ 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
-};
void __init omap_serial_early_init(void)
{
@@ -585,16 +593,15 @@ void __init omap_serial_early_init(void)
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;
+
+ uart->num = i;
/*
* Module 4KB + L4 interconnect 4KB
* Static mapping, never released
*/
- p->membase = ioremap(p->mapbase, SZ_8K);
- if (!p->membase) {
+ uart->membase = ioremap(uart->mapbase, SZ_8K);
+ if (!uart->membase) {
printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
continue;
}
@@ -619,13 +626,10 @@ void __init omap_serial_early_init(void)
continue;
}
- uart->num = i;
- p->private_data = uart;
- uart->p = p;
list_add_tail(&uart->node, &uart_list);
if (cpu_is_omap44xx())
- p->irq += 32;
+ uart->irq += 32;
omap_uart_enable_clocks(uart);
}
@@ -639,10 +643,20 @@ void __init omap_serial_init(void)
struct omap_uart_state *uart = &omap_uart[i];
struct platform_device *pdev = &uart->pdev;
struct device *dev = &pdev->dev;
+#ifdef CONFIG_SERIAL_8250
+ struct plat_serial8250_port *p = dev->platform_data;
+#endif
omap_uart_reset(uart);
omap_uart_idle_init(uart);
+#ifdef CONFIG_SERIAL_8250
+ p->membase = uart->membase;
+ p->mapbase = uart->mapbase;
+ p->irq = uart->irq;
+ p->irqflags = uart->irqflags;
+ p->private_data = uart;
+#endif
if (WARN_ON(platform_device_register(pdev)))
continue;
if ((cpu_is_omap34xx() && uart->padconf) ||
--
1.6.5.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 3/3] OMAP: UART: convert to use omap_device layer
2009-11-24 19:56 ` [PATCH 2/3] OMAP: UART: remove 8520 assumptions from UART core Kevin Hilman
@ 2009-11-24 19:56 ` Kevin Hilman
0 siblings, 0 replies; 3+ messages in thread
From: Kevin Hilman @ 2009-11-24 19:56 UTC (permalink / raw)
To: linux-omap
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
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/serial.c | 338 +++++++++++++++++++-----------------------
1 files changed, 154 insertions(+), 184 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 3595ffa..c067416 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -24,20 +24,33 @@
#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_WER 0x17 /* Wake-up enable register */
#define DEFAULT_TIMEOUT (5 * HZ)
+#define MAX_UART_HWMOD_NAME_LEN 16
+
struct omap_uart_state {
int num;
int can_sleep;
@@ -61,7 +74,8 @@ struct omap_uart_state {
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;
@@ -78,102 +92,13 @@ struct omap_uart_state {
static LIST_HEAD(uart_list);
-#ifdef CONFIG_SERIAL_8250
-#include <linux/serial_8250.h>
-
-static struct plat_serial8250_port serial_platform_data0[] = {
- {
- .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[] = {
+static struct omap_device_pm_latency omap_uart_latency[] = {
{
- .mapbase = OMAP_UART3_BASE,
- .irq = 74,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = OMAP24XX_BASE_BAUD * 16,
- }, {
- .flags = 0
- }
-};
-
-#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 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,
- },
- },
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
-#endif
};
-#endif
static inline unsigned int serial_read_reg(struct omap_uart_state *up,
int offset)
@@ -200,7 +125,6 @@ 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)
@@ -267,8 +191,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);
}
@@ -282,8 +205,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)
@@ -320,18 +242,18 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
}
}
-static void omap_uart_smart_idle_enable(struct omap_uart_state *p,
- int enable)
+static inline void omap_uart_smart_idle_enable(struct omap_uart_state *p,
+ int enable)
{
- u16 sysc;
+ u32 sysc;
- sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
+ sysc = omap_hwmod_read_sysc(p->oh);
+ sysc &= ~SYSC_SIDLEMODE_MASK;
if (enable)
- sysc |= 0x2 << 3;
+ sysc |= 0x2 << SYSC_SIDLEMODE_SHIFT;
else
- sysc |= 0x1 << 3;
-
- serial_write_reg(p, UART_OMAP_SYSC, sysc);
+ sysc |= 0x1 << SYSC_SIDLEMODE_SHIFT;
+ omap_hwmod_write_sysc(sysc, p->oh);
}
static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -348,7 +270,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);
@@ -443,6 +365,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;
@@ -516,8 +439,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
}
uart->irqflags |= IRQF_SHARED;
- ret = request_irq(uart->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);
WARN_ON(ret);
}
@@ -528,8 +451,11 @@ void omap_uart_enable_irqs(int enable)
list_for_each_entry(uart, &uart_list, node) {
if (enable)
- ret = request_irq(uart->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->irq, (void *)uart);
}
@@ -539,10 +465,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);
}
@@ -551,10 +476,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) {
@@ -582,87 +506,133 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
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.
- */
+ int i = 0;
- for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
- struct omap_uart_state *uart = &omap_uart[i];
+ do {
+ char oh_name[MAX_UART_HWMOD_NAME_LEN];
+ struct omap_hwmod *oh;
+ struct omap_uart_state *uart;
- uart->num = i;
-
- /*
- * Module 4KB + L4 interconnect 4KB
- * Static mapping, never released
- */
- uart->membase = ioremap(uart->mapbase, SZ_8K);
- if (!uart->membase) {
- printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
- continue;
- }
-
- 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;
- }
-
- 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;
- }
+ snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
+ "uart%d_hwmod", i + 1);
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh)
+ break;
- /* FIXME: Remove this once the clkdev is ready */
- if (!cpu_is_omap44xx()) {
- if (!uart->ick || !uart->fck)
- continue;
- }
+ uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
+ if (WARN_ON(!uart))
+ return;
+ uart->oh = oh;
+ uart->num = i++;
list_add_tail(&uart->node, &uart_list);
- if (cpu_is_omap44xx())
- uart->irq += 32;
-
- omap_uart_enable_clocks(uart);
- }
+ /* 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);
}
void __init omap_serial_init(void)
{
- int i;
-
- 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;
-#ifdef CONFIG_SERIAL_8250
- struct plat_serial8250_port *p = dev->platform_data;
+ struct omap_uart_state *uart;
+
+ list_for_each_entry(uart, &uart_list, node) {
+ struct omap_hwmod *oh = uart->oh;
+ struct omap_device *od;
+ void *pdata = NULL;
+ u32 pdata_size = 0;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char *name = "serial8250";
+ struct plat_serial8250_port ports[2] = {
+ {},
+ {.flags = 0},
+ };
+ struct plat_serial8250_port *p = &ports[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;
+
+ pdata = &ports[0];
+ pdata_size = 2 * sizeof(struct plat_serial8250_port);
#endif
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+ struct uart_port_info p;
+ char *name = "omap-hsuart";
- omap_uart_reset(uart);
- omap_uart_idle_init(uart);
+ p.dma_enabled = 0;
+ p.uartclk = OMAP24XX_BASE_BAUD * 16;
-#ifdef CONFIG_SERIAL_8250
- p->membase = uart->membase;
- p->mapbase = uart->mapbase;
- p->irq = uart->irq;
- p->irqflags = uart->irqflags;
- p->private_data = uart;
+ pdata = &p;
+ pdata_size = sizeof(struct uart_port_info);
#endif
- if (WARN_ON(platform_device_register(pdev)))
+
+ if (WARN_ON(!oh))
continue;
+
+ 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(dev, true);
- DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
+ device_init_wakeup(&od->pdev.dev, true);
+ DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
}
}
}
--
1.6.5.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-12-11 16:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-11 13:23 [PATCH 3/3] OMAP: UART: convert to use omap_device layer Govindraj.R
2009-12-11 16:58 ` Kevin Hilman
-- strict thread matches above, loose matches on Subject: below --
2009-11-24 19:56 [PATCH 0/3] UART conversion to " Kevin Hilman
2009-11-24 19:56 ` [PATCH 1/3] OMAP3: add omap_hwmods for UART1,2,3 Kevin Hilman
2009-11-24 19:56 ` [PATCH 2/3] OMAP: UART: remove 8520 assumptions from UART core Kevin Hilman
2009-11-24 19:56 ` [PATCH 3/3] OMAP: UART: convert to use omap_device layer Kevin Hilman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.