Merge branch 'omap3-upstream' into for-next
authorTony Lindgren <tony@atomide.com>
Thu, 28 May 2009 22:44:54 +0000 (15:44 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 28 May 2009 22:44:54 +0000 (15:44 -0700)
Conflicts:
arch/arm/mach-omap2/serial.c

1  2 
arch/arm/mach-omap2/serial.c

index a0a280377a8c58a3165ab56f27586aba6b2aeb75,3c2d325d3dcacd9d1694308134c6aa953482f45f..fddbc4e1b2310b5fa35f5bc2709b51f4b54cfbf8
@@@ -295,183 -98,17 +295,191 @@@ void omap_uart_resume_idle(int num
        }
  }
  
 +void omap_uart_prepare_suspend(void)
 +{
 +      struct omap_uart_state *uart;
 +
 +      list_for_each_entry(uart, &uart_list, node) {
 +              omap_uart_allow_sleep(uart);
 +      }
 +}
 +
 +int omap_uart_can_sleep(void)
 +{
 +      struct omap_uart_state *uart;
 +      int can_sleep = 1;
 +
 +      list_for_each_entry(uart, &uart_list, node) {
 +              if (!uart->clocked)
 +                      continue;
 +
 +              if (!uart->can_sleep) {
 +                      can_sleep = 0;
 +                      continue;
 +              }
 +
 +              /* This UART can now safely sleep. */
 +              omap_uart_allow_sleep(uart);
 +      }
 +
 +      return can_sleep;
 +}
 +
 +/**
 + * omap_uart_interrupt()
 + *
 + * This handler is used only to detect that *any* UART interrupt has
 + * occurred.  It does _nothing_ to handle the interrupt.  Rather,
 + * any UART interrupt will trigger the inactivity timer so the
 + * UART will not idle or sleep for its timeout period.
 + *
 + **/
 +static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 +{
 +      struct omap_uart_state *uart = dev_id;
 +
 +      omap_uart_block_sleep(uart);
 +
 +      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;
 +      setup_timer(&uart->timer, omap_uart_idle_timer,
 +                  (unsigned long) uart);
 +      mod_timer(&uart->timer, jiffies + uart->timeout);
 +      omap_uart_smart_idle_enable(uart, 0);
 +
 +      if (cpu_is_omap34xx()) {
 +              u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
 +              u32 wk_mask = 0;
 +              u32 padconf = 0;
 +
 +              uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 +              uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
 +              switch (uart->num) {
 +              case 0:
 +                      wk_mask = OMAP3430_ST_UART1_MASK;
 +                      padconf = 0x182;
 +                      break;
 +              case 1:
 +                      wk_mask = OMAP3430_ST_UART2_MASK;
 +                      padconf = 0x17a;
 +                      break;
 +              case 2:
 +                      wk_mask = OMAP3430_ST_UART3_MASK;
 +                      padconf = 0x19e;
 +                      break;
 +              }
 +              uart->wk_mask = wk_mask;
 +              uart->padconf = padconf;
 +      } else if (cpu_is_omap24xx()) {
 +              u32 wk_mask = 0;
 +
 +              if (cpu_is_omap2430()) {
 +                      uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
 +                      uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
 +              } else if (cpu_is_omap2420()) {
 +                      uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
 +                      uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
 +              }
 +              switch (uart->num) {
 +              case 0:
 +                      wk_mask = OMAP24XX_ST_UART1_MASK;
 +                      break;
 +              case 1:
 +                      wk_mask = OMAP24XX_ST_UART2_MASK;
 +                      break;
 +              case 2:
 +                      wk_mask = OMAP24XX_ST_UART3_MASK;
 +                      break;
 +              }
 +              uart->wk_mask = wk_mask;
 +      } else {
 +              uart->wk_en = 0;
 +              uart->wk_st = 0;
 +              uart->wk_mask = 0;
 +              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);
 +      WARN_ON(ret);
 +}
 +
 +static ssize_t sleep_timeout_show(struct kobject *kobj,
 +                                struct kobj_attribute *attr,
 +                                char *buf)
 +{
 +      return sprintf(buf, "%u\n", sleep_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;
 +      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;
 +              if (uart->timeout)
 +                      mod_timer(&uart->timer, jiffies + uart->timeout);
 +              else
 +                      /* A zero value means disable timeout feature */
 +                      omap_uart_block_sleep(uart);
 +      }
 +      return n;
 +}
 +
 +static struct kobj_attribute sleep_timeout_attr =
 +      __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
 +
 +#else
 +static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
 +#endif /* CONFIG_PM */
 +
+ static struct platform_device serial_device = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = serial_platform_data,
+       },
+ };
  void __init omap_serial_init(void)
  {
--      int i;
++      int i, err;
        const struct omap_uart_config *info;
        char name[16];
  
                }
  
                sprintf(name, "uart%d_ick", i+1);
 -              uart_ick[i] = clk_get(NULL, name);
 -              if (IS_ERR(uart_ick[i])) {
 +              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[i] = NULL;
 -              } else
 -                      clk_enable(uart_ick[i]);
 +                      uart->ick = NULL;
 +              }
  
                sprintf(name, "uart%d_fck", i+1);
 -              uart_fck[i] = clk_get(NULL, name);
 -              if (IS_ERR(uart_fck[i])) {
 +              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[i] = NULL;
 -              } else
 -                      clk_enable(uart_fck[i]);
 +                      uart->fck = NULL;
 +              }
 +
 +              if (!uart->ick || !uart->fck)
 +                      continue;
  
 -              omap_serial_reset(p);
 +              uart->num = i;
 +              p->private_data = uart;
 +              uart->p = p;
 +              list_add(&uart->node, &uart_list);
 +
 +              omap_uart_enable_clocks(uart);
 +              omap_uart_reset(uart);
 +              omap_uart_idle_init(uart);
        }
- }
- 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;
-       ret = platform_device_register(&serial_device);
 -      platform_device_register(&serial_device);
++      err = platform_device_register(&serial_device);
 +
 +#ifdef CONFIG_PM
-       if (!ret)
-               ret = sysfs_create_file(&serial_device.dev.kobj,
++      if (!err)
++              err = sysfs_create_file(&serial_device.dev.kobj,
 +                                      &sleep_timeout_attr.attr);
 +#endif
-       return ret;
++
  }
- arch_initcall(omap_init);
++