[ARM] ohci-pxa27x: introduce flags to avoid direct access to OHCI registers
authorEric Miao <eric.miao@marvell.com>
Sat, 27 Sep 2008 07:49:57 +0000 (15:49 +0800)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 7 Oct 2008 18:12:57 +0000 (19:12 +0100)
Direct access to USB host controller registers is considered to be not
portable, and is usually a bad sign for poorly abstracted interface.
Introduce .flags and .power_on_delay to "struct pxaohci_platform_data"
so that most platforms don't bother to write their own .init/.exit()
sequences.

Signed-off-by: Eric Miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
12 files changed:
arch/arm/mach-pxa/cm-x270.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/include/mach/ohci.h
arch/arm/mach-pxa/include/mach/pxa-regs.h
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/trizeps4.c
drivers/usb/host/ohci-pxa27x.c

index 102a431..a82dad1 100644 (file)
@@ -257,18 +257,9 @@ static inline void cmx270_init_2700G(void) {}
 
 /* PXA27x OHCI controller setup */
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static int cmx270_ohci_init(struct device *dev)
-{
-       /* Set the Power Control Polarity Low */
-       UHCHR = (UHCHR | UHCHR_PCPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data cmx270_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = cmx270_ohci_init,
+       .flags          = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
 };
 
 static void __init cmx270_init_ohci(void)
index 7bc5679..deb46cd 100644 (file)
@@ -365,19 +365,11 @@ static inline void cm_x300_init_mmc(void) {}
 #endif
 
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static int cm_x300_ohci_init(struct device *dev)
-{
-       /* Set the Power Control Polarity Low */
-       UHCHR = (UHCHR | UHCHR_PCPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = cm_x300_ohci_init,
+       .flags          = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
 };
+
 static void __init cm_x300_init_ohci(void)
 {
        pxa_set_ohci_info(&cm_x300_ohci_platform_data);
index 7a0a681..f5ed803 100644 (file)
@@ -373,10 +373,6 @@ static inline void em_x270_init_nand(void) {}
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int em_x270_ohci_init(struct device *dev)
 {
-       /* Set the Power Control Polarity Low */
-       UHCHR = (UHCHR | UHCHR_PCPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
-
        /* enable port 2 transiever */
        UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
 
@@ -385,6 +381,7 @@ static int em_x270_ohci_init(struct device *dev)
 
 static struct pxaohci_platform_data em_x270_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
+       .flags          = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
        .init           = em_x270_ohci_init,
 };
 
index e848a47..95b6e2a 100644 (file)
@@ -7,6 +7,22 @@ struct pxaohci_platform_data {
        int (*init)(struct device *);
        void (*exit)(struct device *);
 
+       unsigned long flags;
+#define ENABLE_PORT1           (1 << 0)
+#define ENABLE_PORT2           (1 << 1)
+#define ENABLE_PORT3           (1 << 2)
+#define ENABLE_PORT_ALL                (ENABLE_PORT1 | ENABLE_PORT2 | ENABLE_PORT3)
+
+#define POWER_SENSE_LOW                (1 << 3)
+#define POWER_CONTROL_LOW      (1 << 4)
+#define NO_OC_PROTECTION       (1 << 5)
+#define OC_MODE_GLOBAL         (0 << 6)
+#define OC_MODE_PERPORT                (1 << 6)
+
+       int power_on_delay;     /* Power On to Power Good time - in ms
+                                * HCD must wait for this duration before
+                                * accessing a powered on port
+                                */
        int port_mode;
 #define PMM_NPS_MODE           1
 #define PMM_GLOBAL_MODE        2
index 98ded45..b34e8a7 100644 (file)
 
 #define UHCRHDA                __REG(0x4C000048) /* UHC Root Hub Descriptor A */
 #define UHCRHDA_NOCP   (1 << 12)       /* No over current protection */
+#define UHCRHDA_OCPM   (1 << 11)       /* Over Current Protection Mode */
+#define UHCRHDA_POTPGT(x) \
+                       (((x) & 0xff) << 24) /* Power On To Power Good Time */
 
 #define UHCRHDB                __REG(0x4C00004C) /* UHC Root Hub Descriptor B */
 #define UHCRHS         __REG(0x4C000050) /* UHC Root Hub Status */
index 7b158e5..92728a3 100644 (file)
@@ -448,19 +448,9 @@ static struct platform_device *platform_devices[] __initdata = {
        &lpd270_flash_device[1],
 };
 
-static int lpd270_ohci_init(struct device *dev)
-{
-       /* Set the Power Control Polarity Low and Power Sense
-          Polarity Low to active low. */
-       UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data lpd270_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = lpd270_ohci_init,
+       .flags          = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
 };
 
 static void __init lpd270_init(void)
index 8ebdac7..519138b 100644 (file)
@@ -669,18 +669,10 @@ static struct pxamci_platform_data magician_mci_info = {
  * USB OHCI
  */
 
-static int magician_ohci_init(struct device *dev)
-{
-       UHCHR = (UHCHR | UHCHR_SSEP2 | UHCHR_PCPL | UHCHR_CGR) &
-           ~(UHCHR_SSEP1 | UHCHR_SSEP3 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data magician_ohci_info = {
-       .port_mode    = PMM_PERPORT_MODE,
-       .init         = magician_ohci_init,
-       .power_budget = 0,
+       .port_mode      = PMM_PERPORT_MODE,
+       .flags          = ENABLE_PORT1 | ENABLE_PORT3 | POWER_CONTROL_LOW,
+       .power_budget   = 0,
 };
 
 
index d44af76..a02edfd 100644 (file)
@@ -508,19 +508,9 @@ static struct platform_device *platform_devices[] __initdata = {
        &mst_gpio_keys_device,
 };
 
-static int mainstone_ohci_init(struct device *dev)
-{
-       /* Set the Power Control Polarity Low and Power Sense
-          Polarity Low to active low. */
-       UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data mainstone_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = mainstone_ohci_init,
+       .flags          = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
 };
 
 #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
index 420c9b3..e9efb80 100644 (file)
@@ -328,36 +328,10 @@ static struct pxamci_platform_data pcm990_mci_platform_data = {
        .exit           = pcm990_mci_exit,
 };
 
-/*
- * init OHCI hardware to work with
- *
- * Note: Only USB port 1 (host only) is connected
- *
- * GPIO88 (USBHPWR#1): overcurrent in, overcurrent when low
- * GPIO89 (USBHPEN#1): power-on out, on when low
- */
-static int pcm990_ohci_init(struct device *dev)
-{
-       /*
-        * disable USB port 2 and 3
-        * power sense is active low
-        */
-       UHCHR = ((UHCHR) | UHCHR_PCPL | UHCHR_PSPL | UHCHR_SSEP2 |
-                               UHCHR_SSEP3) & ~(UHCHR_SSEP1 | UHCHR_SSE);
-       /*
-        * wait 10ms after Power on
-        * overcurrent per port
-        * power switch per port
-        */
-       UHCRHDA = (5<<24) | (1<<11) | (1<<8);   /* FIXME: Required? */
-
-       return 0;
-}
-
 static struct pxaohci_platform_data pcm990_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = pcm990_ohci_init,
-       .exit           = NULL,
+       .flags          = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
+       .power_on_delay = 10,
 };
 
 /*
index 245890d..7ef3461 100644 (file)
@@ -495,19 +495,13 @@ static int spitz_ohci_init(struct device *dev)
         */
        UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
 
-       gpio_direction_output(SPITZ_GPIO_USB_HOST, 1);
-
-       UHCHR = (UHCHR) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
-
-       UHCRHDA |= UHCRHDA_NOCP;
-
-       return 0;
+       return gpio_direction_output(SPITZ_GPIO_USB_HOST, 1);
 }
 
 static struct pxaohci_platform_data spitz_ohci_platform_data = {
        .port_mode      = PMM_NPS_MODE,
        .init           = spitz_ohci_init,
+       .flags          = ENABLE_PORT_ALL | NO_OC_PROTECTION,
        .power_budget   = 150,
 };
 
index 75ff8f4..a13dbf3 100644 (file)
@@ -425,19 +425,9 @@ static struct pxaficp_platform_data trizeps4_ficp_platform_data = {
 /****************************************************************************
  * OHCI USB port
  ****************************************************************************/
-static int trizeps4_ohci_init(struct device *dev)
-{
-       /* Set the Power Control Polarity Low and Power Sense
-          Polarity Low to active low. */
-       UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
-
-       return 0;
-}
-
 static struct pxaohci_platform_data trizeps4_ohci_platform_data = {
        .port_mode      = PMM_PERPORT_MODE,
-       .init           = trizeps4_ohci_init,
+       .flags          = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
 };
 
 static struct map_desc trizeps4_io_desc[] __initdata = {
index 7f0f35c..2a7d5e0 100644 (file)
@@ -76,6 +76,41 @@ extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
 
+static inline void pxa27x_setup_hc(struct pxaohci_platform_data *inf)
+{
+       uint32_t uhchr = UHCHR;
+       uint32_t uhcrhda = UHCRHDA;
+
+       if (inf->flags & ENABLE_PORT1)
+               uhchr &= ~UHCHR_SSEP1;
+
+       if (inf->flags & ENABLE_PORT2)
+               uhchr &= ~UHCHR_SSEP2;
+
+       if (inf->flags & ENABLE_PORT3)
+               uhchr &= ~UHCHR_SSEP3;
+
+       if (inf->flags & POWER_CONTROL_LOW)
+               uhchr |= UHCHR_PCPL;
+
+       if (inf->flags & POWER_SENSE_LOW)
+               uhchr |= UHCHR_PSPL;
+
+       if (inf->flags & NO_OC_PROTECTION)
+               uhcrhda |= UHCRHDA_NOCP;
+
+       if (inf->flags & OC_MODE_PERPORT)
+               uhcrhda |= UHCRHDA_OCPM;
+
+       if (inf->power_on_delay) {
+               uhcrhda &= ~UHCRHDA_POTPGT(0xff);
+               uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2);
+       }
+
+       UHCHR = uhchr;
+       UHCRHDA = uhcrhda;
+}
+
 static int pxa27x_start_hc(struct device *dev)
 {
        int retval = 0;
@@ -93,6 +128,8 @@ static int pxa27x_start_hc(struct device *dev)
        while (UHCHR & UHCHR_FSBIR)
                cpu_relax();
 
+       pxa27x_setup_hc(inf);
+
        if (inf->init)
                retval = inf->init(dev);