netns xfrm: fix "ip xfrm state|policy count" misreport
[safe/jmp/linux-2.6] / arch / arm / mach-pxa / mfp-pxa2xx.c
index 1f22987..cf6b720 100644 (file)
 #include <linux/init.h>
 #include <linux/sysdev.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/gpio.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa2xx.h>
 
 #include "generic.h"
 
-#define gpio_to_bank(gpio)     ((gpio) >> 5)
-
 #define PGSR(x)                __REG2(0x40F00020, (x) << 2)
 #define __GAFR(u, x)   __REG2((u) ? 0x40E00058 : 0x40E00054, (x) << 3)
 #define GAFR_L(x)      __GAFR(0, x)
@@ -38,6 +35,7 @@ struct gpio_desc {
        unsigned        valid           : 1;
        unsigned        can_wakeup      : 1;
        unsigned        keypad_gpio     : 1;
+       unsigned        dir_inverted    : 1;
        unsigned int    mask; /* bit mask in PWER or PKWR */
        unsigned int    mux_mask; /* bit mask of muxed gpio bits, 0 if no mux */
        unsigned long   config;
@@ -54,7 +52,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
        int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */
        int shft = (gpio & 0xf) << 1;
        int fn = MFP_AF(c);
-       int dir = c & MFP_DIR_OUT;
+       int is_out = (c & MFP_DIR_OUT) ? 1 : 0;
 
        if (fn > 3)
                return -EINVAL;
@@ -68,7 +66,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
        else
                GAFR_U(bank) = gafr;
 
-       if (dir == MFP_DIR_OUT)
+       if (is_out ^ gpio_desc[gpio].dir_inverted)
                GPDR(gpio) |= mask;
        else
                GPDR(gpio) &= ~mask;
@@ -77,11 +75,11 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
        switch (c & MFP_LPM_STATE_MASK) {
        case MFP_LPM_DRIVE_HIGH:
                PGSR(bank) |= mask;
-               dir = MFP_DIR_OUT;
+               is_out = 1;
                break;
        case MFP_LPM_DRIVE_LOW:
                PGSR(bank) &= ~mask;
-               dir = MFP_DIR_OUT;
+               is_out = 1;
                break;
        case MFP_LPM_DEFAULT:
                break;
@@ -92,7 +90,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
                break;
        }
 
-       if (dir == MFP_DIR_OUT)
+       if (is_out ^ gpio_desc[gpio].dir_inverted)
                gpdr_lpm[bank] |= mask;
        else
                gpdr_lpm[bank] &= ~mask;
@@ -106,7 +104,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
                return -EINVAL;
        }
 
-       if ((c & MFP_LPM_CAN_WAKEUP) && (dir == MFP_DIR_OUT)) {
+       if ((c & MFP_LPM_CAN_WAKEUP) && is_out) {
                pr_warning("%s: output GPIO%d unable to wakeup\n",
                                __func__, gpio);
                return -EINVAL;
@@ -221,6 +219,12 @@ static void __init pxa25x_mfp_init(void)
                gpio_desc[i].can_wakeup = 1;
                gpio_desc[i].mask = GPIO_bit(i);
        }
+
+       /* PXA26x has additional 4 GPIOs (86/87/88/89) which has the
+        * direction bit inverted in GPDR2. See PXA26x DM 4.1.1.
+        */
+       for (i = 86; i <= pxa_last_gpio; i++)
+               gpio_desc[i].dir_inverted = 1;
 }
 #else
 static inline void pxa25x_mfp_init(void) {}
@@ -318,6 +322,7 @@ static inline void pxa27x_mfp_init(void) {}
 #ifdef CONFIG_PM
 static unsigned long saved_gafr[2][4];
 static unsigned long saved_gpdr[4];
+static unsigned long saved_pgsr[4];
 
 static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
 {
@@ -328,6 +333,7 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
                saved_gafr[0][i] = GAFR_L(i);
                saved_gafr[1][i] = GAFR_U(i);
                saved_gpdr[i] = GPDR(i * 32);
+               saved_pgsr[i] = PGSR(i);
 
                GPDR(i * 32) = gpdr_lpm[i];
        }
@@ -342,6 +348,7 @@ static int pxa2xx_mfp_resume(struct sys_device *d)
                GAFR_L(i) = saved_gafr[0][i];
                GAFR_U(i) = saved_gafr[1][i];
                GPDR(i * 32) = saved_gpdr[i];
+               PGSR(i) = saved_pgsr[i];
        }
        PSSR = PSSR_RDH | PSSR_PH;
        return 0;
@@ -370,6 +377,9 @@ static int __init pxa2xx_mfp_init(void)
        if (cpu_is_pxa27x())
                pxa27x_mfp_init();
 
+       /* clear RDH bit to enable GPIO receivers after reset/sleep exit */
+       PSSR = PSSR_RDH;
+
        /* initialize gafr_run[], pgsr_lpm[] from existing values */
        for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++)
                gpdr_lpm[i] = GPDR(i * 32);