OMAP3: allow to disable UART4
[pandora-kernel.git] / arch / arm / mach-omap2 / serial.c
index 9992dbf..9ccb723 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/serial_8250.h>
 #include <linux/pm_runtime.h>
 #include <linux/console.h>
+#include <linux/module.h>
 
 #ifdef CONFIG_SERIAL_OMAP
 #include <plat/omap-serial.h>
@@ -59,7 +60,7 @@
  * disabled via sysfs. This also causes that any deeper omap sleep states are
  * blocked. 
  */
-#define DEFAULT_TIMEOUT 0
+#define DEFAULT_TIMEOUT (10 * HZ)
 
 #define MAX_UART_HWMOD_NAME_LEN                16
 
@@ -73,6 +74,7 @@ struct omap_uart_state {
        void __iomem *wk_en;
        u32 wk_mask;
        u32 padconf;
+       u32 padconf2;
        u32 dma_enabled;
 
        struct clk *ick;
@@ -288,10 +290,17 @@ static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
        }
 
        /* 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);
+       if (cpu_is_omap34xx()) {
+               if (uart->padconf) {
+                       u16 v = omap_ctrl_readw(uart->padconf);
+                       v |= OMAP3_PADCONF_WAKEUPENABLE0;
+                       omap_ctrl_writew(v, uart->padconf);
+               }
+               if (uart->padconf2) {
+                       u16 v = omap_ctrl_readw(uart->padconf2);
+                       v |= OMAP3_PADCONF_WAKEUPENABLE0;
+                       omap_ctrl_writew(v, uart->padconf2);
+               }
        }
 }
 
@@ -305,10 +314,17 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
        }
 
        /* 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);
+       if (cpu_is_omap34xx()) {
+               if (uart->padconf) {
+                       u16 v = omap_ctrl_readw(uart->padconf);
+                       v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
+                       omap_ctrl_writew(v, uart->padconf);
+               }
+               if (uart->padconf2) {
+                       u16 v = omap_ctrl_readw(uart->padconf2);
+                       v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
+                       omap_ctrl_writew(v, uart->padconf2);
+               }
        }
 }
 
@@ -360,6 +376,19 @@ static void omap_uart_allow_sleep(struct omap_uart_state *uart)
        del_timer(&uart->timer);
 }
 
+void omap_uart_block_sleep_id(int num)
+{
+       struct omap_uart_state *uart;
+
+       list_for_each_entry(uart, &uart_list, node) {
+               if (num == uart->num && uart->can_sleep) {
+                       omap_uart_block_sleep(uart);
+                       return;
+               }
+       }
+}
+EXPORT_SYMBOL(omap_uart_block_sleep_id);
+
 static void omap_uart_idle_timer(unsigned long data)
 {
        struct omap_uart_state *uart = (struct omap_uart_state *)data;
@@ -388,8 +417,12 @@ void omap_uart_resume_idle(int num)
                        omap_uart_enable_clocks(uart);
 
                        /* Check for IO pad wakeup */
-                       if (cpu_is_omap34xx() && uart->padconf) {
-                               u16 p = omap_ctrl_readw(uart->padconf);
+                       if (cpu_is_omap34xx()) {
+                               u16 p = 0;
+                               if (uart->padconf)
+                                       p |= omap_ctrl_readw(uart->padconf);
+                               if (uart->padconf2)
+                                       p |= omap_ctrl_readw(uart->padconf2);
 
                                if (p & OMAP3_PADCONF_WAKEUPEVENT0)
                                        omap_uart_block_sleep(uart);
@@ -468,6 +501,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
                u32 wk_mask = 0;
                u32 padconf = 0;
+               u32 padconf2 = 0;
 
                /* XXX These PRM accesses do not belong here */
                uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
@@ -476,6 +510,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                case 0:
                        wk_mask = OMAP3430_ST_UART1_MASK;
                        padconf = 0x182;
+                       padconf2 = 0x180;
                        break;
                case 1:
                        wk_mask = OMAP3430_ST_UART2_MASK;
@@ -492,6 +527,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                }
                uart->wk_mask = wk_mask;
                uart->padconf = padconf;
+               uart->padconf2 = padconf2;
        } else if (cpu_is_omap24xx()) {
                u32 wk_mask = 0;
                u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
@@ -522,6 +558,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                uart->wk_st = NULL;
                uart->wk_mask = 0;
                uart->padconf = 0;
+               uart->padconf2 = 0;
        }
 
        uart->irqflags |= IRQF_SHARED;
@@ -642,6 +679,13 @@ static int __init omap_serial_early_init(void)
                struct omap_hwmod *oh;
                struct omap_uart_state *uart;
 
+#ifdef CONFIG_OMAP3_DISABLE_UART4
+               if (i == 3) {
+                       i++;
+                       continue;
+               }
+#endif
+
                snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
                         "uart%d", i + 1);
                oh = omap_hwmod_lookup(oh_name);
@@ -821,7 +865,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
        console_unlock();
 
-       if ((cpu_is_omap34xx() && uart->padconf) ||
+       if ((cpu_is_omap34xx() && (uart->padconf || uart->padconf2)) ||
            (uart->wk_en && uart->wk_mask)) {
                device_init_wakeup(&pdev->dev, true);
                DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);