Re: [RFC] Allow disabling wakeup for serial ports, including during off mode.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 28, 2009 at 4:03 AM, Premi, Sanjeev <premi@xxxxxx> wrote:>> -----Original Message----->> From: linux-omap-owner@xxxxxxxxxxxxxxx>> [mailto:linux-omap-owner@xxxxxxxxxxxxxxx] On Behalf Of Russ Dill>> Sent: Tuesday, April 28, 2009 12:58 AM>> To: linux-omap@xxxxxxxxxxxxxxx>> Cc: Russ Dill>> Subject: [RFC] Allow disabling wakeup for serial ports,>> including during off mode.>>>> This patch causes the OMAP uarts to honor the sysfs>> power/wakeup file for>> IOPADs. Before the OMAP was always woken up from off mode on>> a rs232 signal>> change.>>>> This patch also creates a different platform device for each serial>> port so that the wakeup properties can be control per port.>>>> The patch is not in a complete state, but for my testing it>> was necessary>> to disable rs232 wakeup as allowing the signals to float in>> off mode by>> powering off the level converters was causing a wakeup event.>> --->>  arch/arm/mach-omap2/serial.c |  165>> ++++++++++++++++++++++++++++++++---------->>  1 files changed, 126 insertions(+), 39 deletions(-)>>>> diff --git a/arch/arm/mach-omap2/serial.c>> b/arch/arm/mach-omap2/serial.c>> index 0762165..95b047a 100644>> --- a/arch/arm/mach-omap2/serial.c>> +++ b/arch/arm/mach-omap2/serial.c>> @@ -49,6 +49,7 @@ struct omap_uart_state {>>>>       struct plat_serial8250_port *p;>>       struct list_head node;>> +     struct platform_device pdev;>>>>  #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)>>       int context_valid;>> @@ -63,10 +64,9 @@ struct omap_uart_state {>>  #endif>>  };>>>> -static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];>>  static LIST_HEAD(uart_list);>>>> -static struct plat_serial8250_port serial_platform_data[] = {>> +static struct plat_serial8250_port serial_platform_data0[] = {>> [sp] Is it necessary to split the array?
Not really, it should be a separate patch. It allows the wakeup andtimeout options to be set per port.
>>       {>>               .membase        = IO_ADDRESS(OMAP_UART1_BASE),>>               .mapbase        = OMAP_UART1_BASE,>> @@ -76,6 +76,12 @@ static struct plat_serial8250_port>> serial_platform_data[] = {>>               .regshift       = 2,>>               .uartclk        = OMAP24XX_BASE_BAUD * 16,>>       }, {>> +             .flags          = 0>> +     }>> +};>> +>> +static struct plat_serial8250_port serial_platform_data1[] = {>> +     {>>               .membase        = IO_ADDRESS(OMAP_UART2_BASE),>>               .mapbase        = OMAP_UART2_BASE,>>               .irq            = 73,>> @@ -84,6 +90,12 @@ static struct plat_serial8250_port>> serial_platform_data[] = {>>               .regshift       = 2,>>               .uartclk        = OMAP24XX_BASE_BAUD * 16,>>       }, {>> +             .flags          = 0>> +     }>> +};>> +>> +static struct plat_serial8250_port serial_platform_data2[] = {>> +     {>>               .membase        = IO_ADDRESS(OMAP_UART3_BASE),>>               .mapbase        = OMAP_UART3_BASE,>>               .irq            = 74,>> @@ -197,6 +209,40 @@ static inline void>> omap_uart_save_context(struct omap_uart_state *uart) {}>>  static inline void omap_uart_restore_context(struct>> omap_uart_state *uart) {}>>  #endif /* CONFIG_ARCH_OMAP3 */>>>> +static void omap_uart_enable_wakeup(struct omap_uart_state *uart)>> +{>> +     /* Set wake-enable bit */>> +     if (uart->wk_en && uart->wk_mask) {>> +             u32 v = __raw_readl(uart->wk_en);>> +             v |= uart->wk_mask;>> +             __raw_writel(v, uart->wk_en);>> +     }>> +>> +     /* Ensure IOPAD wake-enables are set */>> +     if (cpu_is_omap34xx() && uart->padconf) {>> +             u16 v = omap_ctrl_readw(uart->padconf);>> +             v |= OMAP3_PADCONF_WAKEUPENABLE0;>> +             omap_ctrl_writew(v, uart->padconf);>> +     }>> +}>> +>> +static void omap_uart_disable_wakeup(struct omap_uart_state *uart)>> +{>> +     /* Clear wake-enable bit */>> +     if (uart->wk_en && uart->wk_mask) {>> +             u32 v = __raw_readl(uart->wk_en);>> +             v &= ~uart->wk_mask;>> +             __raw_writel(v, uart->wk_en);>> +     }>> +>> +     /* Ensure IOPAD wake-enables are cleared */>> +     if (cpu_is_omap34xx() && uart->padconf) {>> +             u16 v = omap_ctrl_readw(uart->padconf);>> +             v &= ~OMAP3_PADCONF_WAKEUPENABLE0;>> +             omap_ctrl_writew(v, uart->padconf);>> +     }>> +}>> +>>  static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,>>                                         int enable)>>  {>> @@ -220,6 +266,11 @@ static inline void>> omap_uart_restore(struct omap_uart_state *uart)>>>>  static inline void omap_uart_disable_clocks(struct>> omap_uart_state *uart)>>  {>> +     if (device_may_wakeup(&uart->pdev.dev))>> +             omap_uart_enable_wakeup(uart);>> +     else>> +             omap_uart_disable_wakeup(uart);>> +>>       if (!uart->clocked)>>               return;>>>> @@ -290,6 +341,7 @@ void omap_uart_resume_idle(int num)>>                       if (__raw_readl(uart->wk_st) & uart->wk_mask)>>                               omap_uart_block_sleep(uart);>>>> +                     omap_uart_enable_wakeup(uart);>>                       return;>>               }>>       }>> @@ -300,6 +352,7 @@ void omap_uart_prepare_suspend(void)>>       struct omap_uart_state *uart;>>>>       list_for_each_entry(uart, &uart_list, node) {>> +             omap_uart_enable_wakeup(uart);>>               omap_uart_allow_sleep(uart);>>       }>>  }>> @@ -343,16 +396,13 @@ static irqreturn_t>> omap_uart_interrupt(int irq, void *dev_id)>>       return IRQ_NONE;>>  }>>>> -static u32 sleep_timeout = DEFAULT_TIMEOUT;>> ->>  static void omap_uart_idle_init(struct omap_uart_state *uart)>>  {>> -     u32 v;>>       struct plat_serial8250_port *p = uart->p;>>       int ret;>>>>       uart->can_sleep = 0;>> -     uart->timeout = sleep_timeout;>> +     uart->timeout = DEFAULT_TIMEOUT;>> [sp] Why do we need a constant here?>
where else should the value get initialized?
>>       setup_timer(&uart->timer, omap_uart_idle_timer,>>                   (unsigned long) uart);>>       mod_timer(&uart->timer, jiffies + uart->timeout);>> @@ -410,22 +460,6 @@ static void omap_uart_idle_init(struct>> omap_uart_state *uart)>>               uart->padconf = 0;>>       }>>>> -     /* Set wake-enable bit */>> -     if (uart->wk_en && uart->wk_mask) {>> -             v = __raw_readl(uart->wk_en);>> -             v |= uart->wk_mask;>> -             __raw_writel(v, uart->wk_en);>> -     }>> ->> -     /* Ensure IOPAD wake-enables are set */>> -     if (cpu_is_omap34xx() && uart->padconf) {>> -             u16 v;>> ->> -             v = omap_ctrl_readw(uart->padconf);>> -             v |= OMAP3_PADCONF_WAKEUPENABLE0;>> -             omap_ctrl_writew(v, uart->padconf);>> -     }>> ->>       p->flags |= UPF_SHARE_IRQ;>>       ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,>>                         "serial idle", (void *)uart);>> @@ -450,23 +484,30 @@ static ssize_t>> sleep_timeout_show(struct kobject *kobj,>>                                 struct kobj_attribute *attr,>>                                 char *buf)>>  {>> -     return sprintf(buf, "%u\n", sleep_timeout / HZ);>> +     struct device *dev = container_of(kobj, struct device, kobj);>> +     struct platform_device *pdev = container_of(dev,>> +                                     struct platform_device, dev);>> +     struct omap_uart_state *uart = container_of(pdev,>> +                                     struct omap_uart_state, pdev);>> +     return sprintf(buf, "%u\n", uart->timeout / HZ);>>  }>>>>  static ssize_t sleep_timeout_store(struct kobject *kobj,>>                                  struct kobj_attribute *attr,>>                                  const char *buf, size_t n)>>  {>> -     struct omap_uart_state *uart;>> +     struct device *dev = container_of(kobj, struct device, kobj);>> +     struct platform_device *pdev = container_of(dev,>> +                                     struct platform_device, dev);>> +     struct omap_uart_state *uart = container_of(pdev,>> +                                     struct omap_uart_state, pdev);>>       unsigned int value;>>>>       if (sscanf(buf, "%u", &value) != 1) {>>               printk(KERN_ERR "sleep_timeout_store: Invalid value\n");>>               return -EINVAL;>>       }>> -     sleep_timeout = value * HZ;>> -     list_for_each_entry(uart, &uart_list, node)>> -             uart->timeout = sleep_timeout;>> +     uart->timeout = value * HZ;>>       return n;>>  }>>>> @@ -477,6 +518,34 @@ static struct kobj_attribute sleep_timeout_attr =>>  static inline void omap_uart_idle_init(struct>> omap_uart_state *uart) {}>>  #endif /* CONFIG_PM */>>>> +static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {>> +     {>> +             .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,>> +                     },>> +             },>> +     },>> +};>> +>>  void __init omap_serial_init(void)>>  {>>       int i;>> @@ -495,8 +564,8 @@ void __init omap_serial_init(void)>>               return;>>>>       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {>> -             struct plat_serial8250_port *p =>> serial_platform_data + i;>>               struct omap_uart_state *uart = &omap_uart[i];>> +             struct plat_serial8250_port *p =>> uart->pdev.dev.platform_data;>>>>               if (!(info->enabled_uarts & (1 << i))) {>>                       p->membase = NULL;>> @@ -532,25 +601,43 @@ void __init omap_serial_init(void)>>       }>>  }>>>> -static struct platform_device serial_device = {>> -     .name                   = "serial8250",>> -     .id                     = PLAT8250_DEV_PLATFORM,>> -     .dev                    = {>> -             .platform_data  = serial_platform_data,>> -     },>> -};>> ->>  static int __init omap_init(void)>>  {>>       int ret;>> +     int i;>>>> -     ret = platform_device_register(&serial_device);>> +     for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {>> +             ret = platform_device_register(&omap_uart[i].pdev);>> +             if (ret < 0)>> +                     goto device_err;>> +             if ((cpu_is_omap34xx() && omap_uart[i].padconf) ||>> +                 (omap_uart[i].wk_en && omap_uart[i].wk_mask)) {>> +                     printk(KERN_ERR "%s: Setting>> init_wakeup\n", __func__);>> +>> device_init_wakeup(&omap_uart[i].pdev.dev, true);>> +             }>> +     }>>>>  #ifdef CONFIG_PM>> -     if (!ret)>> -             ret = sysfs_create_file(&serial_device.dev.kobj,>> +     for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {>> +             ret = sysfs_create_file(&omap_uart[i].pdev.dev.kobj,>>                                       &sleep_timeout_attr.attr);>> +             if (ret < 0)>> +                     goto sysfs_err;>> +     }>> +#endif>> +     return ret;>> +>> +#ifdef CONFIG_PM>> +sysfs_err:>> +     for (i--; i >= 0; i--)>> +             sysfs_remove_file(&omap_uart[i].pdev.dev.kobj,>> +                             &sleep_timeout_attr.attr);>> +     i = ARRAY_SIZE(omap_uart);>>  #endif>> +>> +device_err:>> +     for (i--; i >= 0; i--)>> +             platform_device_unregister(&omap_uart[i].pdev);>>       return ret;>>  }>>  arch_initcall(omap_init);>> -->> 1.6.0.4>>>> -->> To unsubscribe from this list: send the line "unsubscribe>> linux-omap" in>> the body of a message to majordomo@xxxxxxxxxxxxxxx>> More majordomo info at  http://vger.kernel.org/majordomo-info.html>>>>��.n��������+%������w��{.n�����{�������ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux