[PATCH] [RFC][ARM] pxa: rework pxa3xx-ulpi driver calls for ohci-pxa27x
Igor Grinberg
grinberg at compulab.co.il
Tue Sep 7 10:14:09 EDT 2010
This patch reworks Marek's quick fix for pxa3xx-u2d crash when ULPI not
used by:
1) Introducing the struct u2d_hc_ops for start/stop the U2DC Host mode.
2) Enabling the Host functionality only when ULPI is used.
Signed-off-by: Igor Grinberg <grinberg at compulab.co.il>
---
arch/arm/mach-pxa/cm-x300.c | 1 +
arch/arm/mach-pxa/include/mach/ohci.h | 2 +
arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h | 12 +++--
arch/arm/mach-pxa/pxa3xx-ulpi.c | 66 +++++++++++++++++++--------
drivers/usb/host/ohci-pxa27x.c | 8 ++--
5 files changed, 62 insertions(+), 27 deletions(-)
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 8e0b562..952b475 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -566,6 +566,7 @@ static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
static void __init cm_x300_init_ohci(void)
{
+ cm_x300_ohci_platform_data.u2d_hc_ops = pxa3xx_get_u2d_hc_ops();
pxa_set_ohci_info(&cm_x300_ohci_platform_data);
}
#else
diff --git a/arch/arm/mach-pxa/include/mach/ohci.h b/arch/arm/mach-pxa/include/mach/ohci.h
index 95b6e2a..0924e26 100644
--- a/arch/arm/mach-pxa/include/mach/ohci.h
+++ b/arch/arm/mach-pxa/include/mach/ohci.h
@@ -29,6 +29,8 @@ struct pxaohci_platform_data {
#define PMM_PERPORT_MODE 3
int power_budget;
+
+ struct pxa3xx_u2d_hc_ops *u2d_hc_ops;
};
extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
index 9d82cb6..6f37f43 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
@@ -25,10 +25,14 @@ struct pxa3xx_u2d_platform_data {
};
-/* Start PXA3xx U2D host */
-int pxa3xx_u2d_start_hc(struct usb_bus *host);
-/* Stop PXA3xx U2D host */
-void pxa3xx_u2d_stop_hc(struct usb_bus *host);
+struct pxa3xx_u2d_hc_ops {
+ /* Start PXA3xx U2D host */
+ int (*start_hc)(struct usb_bus *host);
+ /* Stop PXA3xx U2D host */
+ void (*stop_hc)(struct usb_bus *host);
+};
+
+struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void);
extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index ce7168b..7e76cbe 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -234,27 +234,18 @@ static void pxa310_otg_exit(void)
{
kfree(u2d->otg);
}
-#else
-static inline void pxa310_u2d_setup_otg_hc(void) {}
-static inline int pxa310_start_otg_hc(struct usb_bus *host)
-{
- return 0;
-}
-static inline void pxa310_stop_otg_hc(void) {}
-static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
-{
- return 0;
-}
-static inline void pxa310_otg_exit(void) {}
-#endif /* CONFIG_PXA310_ULPI */
-int pxa3xx_u2d_start_hc(struct usb_bus *host)
+static int pxa3xx_u2d_start_hc(struct usb_bus *host)
{
int err = 0;
- /* In case the PXA3xx ULPI isn't used, do nothing. */
- if (!u2d)
+ if (!u2d) {
+ pr_err("%s: Error: u2d struct is not initialized! "
+ "ULPI enabed, but pxa3xx-u2d device not registered?",
+ __func__);
+
return 0;
+ }
clk_enable(u2d->clk);
@@ -266,11 +257,15 @@ int pxa3xx_u2d_start_hc(struct usb_bus *host)
return err;
}
-void pxa3xx_u2d_stop_hc(struct usb_bus *host)
+static void pxa3xx_u2d_stop_hc(struct usb_bus *host)
{
- /* In case the PXA3xx ULPI isn't used, do nothing. */
- if (!u2d)
+ if (!u2d) {
+ pr_err("%s: Error: u2d struct is not initialized! "
+ "ULPI enabed, but pxa3xx-u2d device not registered?",
+ __func__);
+
return;
+ }
if (cpu_is_pxa310())
pxa310_stop_otg_hc();
@@ -278,6 +273,39 @@ void pxa3xx_u2d_stop_hc(struct usb_bus *host)
clk_disable(u2d->clk);
}
+static struct pxa3xx_u2d_hc_ops u2d_hc_ops = {
+ .start_hc = pxa3xx_u2d_start_hc,
+ .stop_hc = pxa3xx_u2d_stop_hc,
+};
+
+struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void)
+{
+ return &u2d_hc_ops;
+}
+#else
+static inline void pxa310_u2d_setup_otg_hc(void) {}
+static inline int pxa310_start_otg_hc(struct usb_bus *host)
+{
+ return 0;
+}
+static inline void pxa310_stop_otg_hc(void) {}
+static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+ return 0;
+}
+static inline void pxa310_otg_exit(void) {}
+static inline int pxa3xx_u2d_start_hc(struct usb_bus *host)
+{
+ return 0;
+}
+static inline void pxa3xx_u2d_stop_hc(struct usb_bus *host) {}
+
+struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void)
+{
+ return NULL;
+}
+#endif /* CONFIG_PXA310_ULPI */
+
static int pxa3xx_u2d_probe(struct platform_device *pdev)
{
struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index afef7b0..61ff775 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -236,8 +236,8 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
if (retval < 0)
return retval;
- if (cpu_is_pxa3xx())
- pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
+ if (cpu_is_pxa3xx() && inf->u2d_hc_ops)
+ inf->u2d_hc_ops->start_hc(&ohci_to_hcd(&ohci->ohci)->self);
uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
__raw_writel(uhchr, ohci->mmio_base + UHCHR);
@@ -255,8 +255,8 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
inf = dev->platform_data;
- if (cpu_is_pxa3xx())
- pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
+ if (cpu_is_pxa3xx() && inf->u2d_hc_ops)
+ inf->u2d_hc_ops->stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
if (inf->exit)
inf->exit(dev);
--
1.7.1
More information about the linux-arm-kernel
mailing list