* [PATCH v3 1/4] USB: OHCI: Export the OHCI hub control and status_data functions
2014-04-16 13:16 [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Laurent Pinchart
@ 2014-04-16 13:16 ` Laurent Pinchart
2014-04-16 13:16 ` [PATCH v3 2/4] USB: EHCI: Export the ehci_hub_control function Laurent Pinchart
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2014-04-16 13:16 UTC (permalink / raw)
To: linux-arm-kernel
Platform drivers sometimes need to perform specific handling of hub
control requests and status data. Make this possible by exporting the
ohci_hub_control() and ohci_hub_status_data() functions which can then
be called from custom hub operations in the default case.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/usb/host/ohci-at91.c | 11 ++---------
drivers/usb/host/ohci-hub.c | 8 ++++----
drivers/usb/host/ohci-s3c2410.c | 13 +++----------
drivers/usb/host/ohci.h | 3 +++
4 files changed, 12 insertions(+), 23 deletions(-)
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 091ae49..e49eb4f 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -46,9 +46,6 @@ static const char hcd_name[] = "ohci-atmel";
static struct hc_driver __read_mostly ohci_at91_hc_driver;
static int clocked;
-static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
- u16 wValue, u16 wIndex, char *buf, u16 wLength);
-static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
extern int usb_disabled(void);
@@ -262,7 +259,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
- int length = orig_ohci_hub_status_data(hcd, buf);
+ int length = ohci_hub_status_data(hcd, buf);
int port;
at91_for_each_port(port) {
@@ -340,8 +337,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
}
- ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex + 1,
- buf, wLength);
+ ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
if (ret)
goto out;
@@ -690,9 +686,6 @@ static int __init ohci_at91_init(void)
* too easy.
*/
- orig_ohci_hub_control = ohci_at91_hc_driver.hub_control;
- orig_ohci_hub_status_data = ohci_at91_hc_driver.hub_status_data;
-
ohci_at91_hc_driver.hub_status_data = ohci_at91_hub_status_data;
ohci_at91_hc_driver.hub_control = ohci_at91_hub_control;
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index c81c872..3d53208 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -438,8 +438,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
/* build "status change" packet (one or two bytes) from HC registers */
-static int
-ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+int ohci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
@@ -504,6 +503,7 @@ done:
return changed ? length : 0;
}
+EXPORT_SYMBOL_GPL(ohci_hub_status_data);
/*-------------------------------------------------------------------------*/
@@ -646,7 +646,7 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
return 0;
}
-static int ohci_hub_control (
+int ohci_hub_control(
struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
@@ -772,4 +772,4 @@ error:
}
return retval;
}
-
+EXPORT_SYMBOL_GPL(ohci_hub_control);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index ff7c8f1..3d753a9 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -45,10 +45,6 @@ static struct clk *usb_clk;
/* forward definitions */
-static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
- u16 wValue, u16 wIndex, char *buf, u16 wLength);
-static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
-
static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
/* conversion functions */
@@ -110,7 +106,7 @@ ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf)
int orig;
int portno;
- orig = orig_ohci_hub_status_data(hcd, buf);
+ orig = ohci_hub_status_data(hcd, buf);
if (info == NULL)
return orig;
@@ -181,7 +177,7 @@ static int ohci_s3c2410_hub_control(
* process the request straight away and exit */
if (info == NULL) {
- ret = orig_ohci_hub_control(hcd, typeReq, wValue,
+ ret = ohci_hub_control(hcd, typeReq, wValue,
wIndex, buf, wLength);
goto out;
}
@@ -231,7 +227,7 @@ static int ohci_s3c2410_hub_control(
break;
}
- ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+ ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
if (ret)
goto out;
@@ -489,9 +485,6 @@ static int __init ohci_s3c2410_init(void)
* override these functions by making it too easy.
*/
- orig_ohci_hub_control = ohci_s3c2410_hc_driver.hub_control;
- orig_ohci_hub_status_data = ohci_s3c2410_hc_driver.hub_status_data;
-
ohci_s3c2410_hc_driver.hub_status_data = ohci_s3c2410_hub_status_data;
ohci_s3c2410_hc_driver.hub_control = ohci_s3c2410_hub_control;
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 9250cad..a116583 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -727,3 +727,6 @@ extern int ohci_setup(struct usb_hcd *hcd);
extern int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup);
extern int ohci_resume(struct usb_hcd *hcd, bool hibernated);
#endif
+extern int ohci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength);
+extern int ohci_hub_status_data(struct usb_hcd *hcd, char *buf);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 2/4] USB: EHCI: Export the ehci_hub_control function
2014-04-16 13:16 [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Laurent Pinchart
2014-04-16 13:16 ` [PATCH v3 1/4] USB: OHCI: Export the OHCI hub control and status_data functions Laurent Pinchart
@ 2014-04-16 13:16 ` Laurent Pinchart
2014-04-16 13:16 ` [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators Laurent Pinchart
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2014-04-16 13:16 UTC (permalink / raw)
To: linux-arm-kernel
Platform drivers sometimes need to perform specific handling of hub
control requests. Make this possible by exporting the ehci_hub_control()
function which can then be called from a custom hub control handler in
the default case.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/usb/host/ehci-hub.c | 12 ++----------
drivers/usb/host/ehci-tegra.c | 8 +-------
drivers/usb/host/ehci.h | 3 +++
3 files changed, 6 insertions(+), 17 deletions(-)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 7ae0c4d..cc305c7 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -33,15 +33,6 @@
#ifdef CONFIG_PM
-static int ehci_hub_control(
- struct usb_hcd *hcd,
- u16 typeReq,
- u16 wValue,
- u16 wIndex,
- char *buf,
- u16 wLength
-);
-
static int persist_enabled_on_companion(struct usb_device *udev, void *unused)
{
return !udev->maxchild && udev->persist_enabled &&
@@ -865,7 +856,7 @@ cleanup:
#endif /* CONFIG_USB_HCD_TEST_MODE */
/*-------------------------------------------------------------------------*/
-static int ehci_hub_control (
+int ehci_hub_control(
struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
@@ -1285,6 +1276,7 @@ error_exit:
spin_unlock_irqrestore (&ehci->lock, flags);
return retval;
}
+EXPORT_SYMBOL_GPL(ehci_hub_control);
static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
{
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index af28b74..f64653f 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -55,10 +55,6 @@ struct tegra_ehci_soc_config {
bool has_hostpc;
};
-static int (*orig_hub_control)(struct usb_hcd *hcd,
- u16 typeReq, u16 wValue, u16 wIndex,
- char *buf, u16 wLength);
-
struct tegra_ehci_hcd {
struct tegra_usb_phy *phy;
struct clk *clk;
@@ -240,7 +236,7 @@ static int tegra_ehci_hub_control(
spin_unlock_irqrestore(&ehci->lock, flags);
/* Handle the hub control events here */
- return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+ return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
done:
spin_unlock_irqrestore(&ehci->lock, flags);
@@ -535,8 +531,6 @@ static int __init ehci_tegra_init(void)
* too easy.
*/
- orig_hub_control = tegra_ehci_hc_driver.hub_control;
-
tegra_ehci_hc_driver.map_urb_for_dma = tegra_ehci_map_urb_for_dma;
tegra_ehci_hc_driver.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma;
tegra_ehci_hc_driver.hub_control = tegra_ehci_hub_control;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 9dfc6c1..eee228a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -872,4 +872,7 @@ extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
extern int ehci_resume(struct usb_hcd *hcd, bool hibernated);
#endif /* CONFIG_PM */
+extern int ehci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength);
+
#endif /* __LINUX_EHCI_HCD_H */
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators
2014-04-16 13:16 [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Laurent Pinchart
2014-04-16 13:16 ` [PATCH v3 1/4] USB: OHCI: Export the OHCI hub control and status_data functions Laurent Pinchart
2014-04-16 13:16 ` [PATCH v3 2/4] USB: EHCI: Export the ehci_hub_control function Laurent Pinchart
@ 2014-04-16 13:16 ` Laurent Pinchart
2014-04-16 15:07 ` Alan Stern
2014-04-16 13:16 ` [PATCH v3 4/4] ARM: pxa: zeus: Replace OHCI init/exit functions with a regulator Laurent Pinchart
2014-04-16 15:01 ` [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Alan Stern
4 siblings, 1 reply; 8+ messages in thread
From: Laurent Pinchart @ 2014-04-16 13:16 UTC (permalink / raw)
To: linux-arm-kernel
Override the hub control operation to enable and disable external
regulators for the ports vbus power supply in response to clear/set
USB_PORT_FEAT_POWER requests.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/usb/host/ohci-pxa27x.c | 67 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index d21d5fe..0c31265 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -30,6 +30,7 @@
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/usb-pxa3xx-ulpi.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/signal.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -120,6 +121,8 @@ static struct hc_driver __read_mostly ohci_pxa27x_hc_driver;
struct pxa27x_ohci {
struct clk *clk;
void __iomem *mmio_base;
+ struct regulator *vbus[3];
+ bool vbus_enabled[3];
};
#define to_pxa27x_ohci(hcd) (struct pxa27x_ohci *)(hcd_to_ohci(hcd)->priv)
@@ -166,6 +169,52 @@ static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode)
return 0;
}
+static int pxa27x_ohci_set_vbus_power(struct pxa27x_ohci *pxa_ohci,
+ unsigned int port, bool enable)
+{
+ struct regulator *vbus = pxa_ohci->vbus[port];
+ int ret = 0;
+
+ if (IS_ERR_OR_NULL(vbus))
+ return 0;
+
+ if (enable && !pxa_ohci->vbus_enabled[port])
+ ret = regulator_enable(vbus);
+ else if (!enable && pxa_ohci->vbus_enabled[port])
+ ret = regulator_disable(vbus);
+
+ if (ret < 0)
+ return ret;
+
+ pxa_ohci->vbus_enabled[port] = enable;
+
+ return 0;
+}
+
+static int pxa27x_ohci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+{
+ struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
+ int ret;
+
+ switch (typeReq) {
+ case SetPortFeature:
+ case ClearPortFeature:
+ if (!wIndex || wIndex > 3)
+ return -EPIPE;
+
+ if (wValue != USB_PORT_FEAT_POWER)
+ break;
+
+ ret = pxa27x_ohci_set_vbus_power(pxa_ohci, wIndex - 1,
+ typeReq == SetPortFeature);
+ if (ret)
+ return ret;
+ break;
+ }
+
+ return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+}
/*-------------------------------------------------------------------------*/
static inline void pxa27x_setup_hc(struct pxa27x_ohci *pxa_ohci,
@@ -372,6 +421,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
struct ohci_hcd *ohci;
struct resource *r;
struct clk *usb_clk;
+ unsigned int i;
retval = ohci_pxa_of_init(pdev);
if (retval)
@@ -417,6 +467,16 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
pxa_ohci->clk = usb_clk;
pxa_ohci->mmio_base = (void __iomem *)hcd->regs;
+ for (i = 0; i < 3; ++i) {
+ char name[6];
+
+ if (!(inf->flags & (ENABLE_PORT1 << i)))
+ continue;
+
+ sprintf(name, "vbus%u", i + 1);
+ pxa_ohci->vbus[i] = devm_regulator_get(&pdev->dev, name);
+ }
+
retval = pxa27x_start_hc(pxa_ohci, &pdev->dev);
if (retval < 0) {
pr_debug("pxa27x_start_hc failed");
@@ -462,6 +522,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
+ unsigned int i;
+
+ for (i = 0; i < 3; ++i)
+ pxa27x_ohci_set_vbus_power(pxa_ohci, i, false);
usb_remove_hcd(hcd);
pxa27x_stop_hc(pxa_ohci, &pdev->dev);
@@ -563,7 +627,10 @@ static int __init ohci_pxa27x_init(void)
return -ENODEV;
pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
ohci_init_driver(&ohci_pxa27x_hc_driver, &pxa27x_overrides);
+ ohci_pxa27x_hc_driver.hub_control = pxa27x_ohci_hub_control;
+
return platform_driver_register(&ohci_hcd_pxa27x_driver);
}
module_init(ohci_pxa27x_init);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators
2014-04-16 13:16 ` [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators Laurent Pinchart
@ 2014-04-16 15:07 ` Alan Stern
2014-04-16 15:40 ` Laurent Pinchart
0 siblings, 1 reply; 8+ messages in thread
From: Alan Stern @ 2014-04-16 15:07 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 16 Apr 2014, Laurent Pinchart wrote:
> Override the hub control operation to enable and disable external
> regulators for the ports vbus power supply in response to clear/set
> USB_PORT_FEAT_POWER requests.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> @@ -417,6 +467,16 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
> pxa_ohci->clk = usb_clk;
> pxa_ohci->mmio_base = (void __iomem *)hcd->regs;
>
> + for (i = 0; i < 3; ++i) {
> + char name[6];
> +
> + if (!(inf->flags & (ENABLE_PORT1 << i)))
> + continue;
> +
> + sprintf(name, "vbus%u", i + 1);
> + pxa_ohci->vbus[i] = devm_regulator_get(&pdev->dev, name);
> + }
> +
> retval = pxa27x_start_hc(pxa_ohci, &pdev->dev);
> if (retval < 0) {
> pr_debug("pxa27x_start_hc failed");
> @@ -462,6 +522,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
> void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
> {
> struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
> + unsigned int i;
> +
> + for (i = 0; i < 3; ++i)
> + pxa27x_ohci_set_vbus_power(pxa_ohci, i, false);
>
> usb_remove_hcd(hcd);
> pxa27x_stop_hc(pxa_ohci, &pdev->dev);
You probably should leave the port power enabled until after
usb_remove_hcd() returns. Apart from that,
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Alan Stern
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators
2014-04-16 15:07 ` Alan Stern
@ 2014-04-16 15:40 ` Laurent Pinchart
0 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2014-04-16 15:40 UTC (permalink / raw)
To: linux-arm-kernel
Hi Alan,
On Wednesday 16 April 2014 11:07:34 Alan Stern wrote:
> On Wed, 16 Apr 2014, Laurent Pinchart wrote:
> > Override the hub control operation to enable and disable external
> > regulators for the ports vbus power supply in response to clear/set
> > USB_PORT_FEAT_POWER requests.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > @@ -417,6 +467,16 @@ int usb_hcd_pxa27x_probe (const struct hc_driver
> > *driver, struct platform_device>
> > pxa_ohci->clk = usb_clk;
> > pxa_ohci->mmio_base = (void __iomem *)hcd->regs;
> >
> > + for (i = 0; i < 3; ++i) {
> > + char name[6];
> > +
> > + if (!(inf->flags & (ENABLE_PORT1 << i)))
> > + continue;
> > +
> > + sprintf(name, "vbus%u", i + 1);
> > + pxa_ohci->vbus[i] = devm_regulator_get(&pdev->dev, name);
> > + }
> > +
> >
> > retval = pxa27x_start_hc(pxa_ohci, &pdev->dev);
> > if (retval < 0) {
> >
> > pr_debug("pxa27x_start_hc failed");
> >
> > @@ -462,6 +522,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver
> > *driver, struct platform_device>
> > void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device
> > *pdev) {
> >
> > struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
> >
> > + unsigned int i;
> > +
> > + for (i = 0; i < 3; ++i)
> > + pxa27x_ohci_set_vbus_power(pxa_ohci, i, false);
> >
> > usb_remove_hcd(hcd);
> > pxa27x_stop_hc(pxa_ohci, &pdev->dev);
>
> You probably should leave the port power enabled until after
> usb_remove_hcd() returns. Apart from that,
>
> Acked-by: Alan Stern <stern@rowland.harvard.edu>
Good point, I'll fix that and submit v4. Thank you.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 4/4] ARM: pxa: zeus: Replace OHCI init/exit functions with a regulator
2014-04-16 13:16 [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Laurent Pinchart
` (2 preceding siblings ...)
2014-04-16 13:16 ` [PATCH v3 3/4] USB: ohci-pxa27x: Add support for external vbus regulators Laurent Pinchart
@ 2014-04-16 13:16 ` Laurent Pinchart
2014-04-16 15:01 ` [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Alan Stern
4 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2014-04-16 13:16 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/mach-pxa/zeus.c | 89 ++++++++++++++++++++++++++----------------------
1 file changed, 48 insertions(+), 41 deletions(-)
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index b19d1c3..205f9bf 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -413,7 +413,7 @@ static struct fixed_voltage_config can_regulator_pdata = {
static struct platform_device can_regulator_device = {
.name = "reg-fixed-volage",
- .id = -1,
+ .id = 0,
.dev = {
.platform_data = &can_regulator_pdata,
},
@@ -510,18 +510,6 @@ struct platform_device zeus_max6369_device = {
.num_resources = 1,
};
-static struct platform_device *zeus_devices[] __initdata = {
- &zeus_serial_device,
- &zeus_mtd_devices[0],
- &zeus_dm9k0_device,
- &zeus_dm9k1_device,
- &zeus_sram_device,
- &zeus_leds_device,
- &zeus_pcmcia_device,
- &zeus_max6369_device,
- &can_regulator_device,
-};
-
/* AC'97 */
static pxa2xx_audio_ops_t zeus_ac97_info = {
.reset_gpio = 95,
@@ -532,44 +520,50 @@ static pxa2xx_audio_ops_t zeus_ac97_info = {
* USB host
*/
-static int zeus_ohci_init(struct device *dev)
-{
- int err;
-
- /* Switch on port 2. */
- if ((err = gpio_request(ZEUS_USB2_PWREN_GPIO, "USB2_PWREN"))) {
- dev_err(dev, "Can't request USB2_PWREN\n");
- return err;
- }
-
- if ((err = gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 1))) {
- gpio_free(ZEUS_USB2_PWREN_GPIO);
- dev_err(dev, "Can't enable USB2_PWREN\n");
- return err;
- }
+static struct regulator_consumer_supply zeus_ohci_regulator_supplies[] = {
+ REGULATOR_SUPPLY("vbus2", "pxa27x-ohci"),
+};
- /* Port 2 is shared between host and client interface. */
- UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
+static struct regulator_init_data zeus_ohci_regulator_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(zeus_ohci_regulator_supplies),
+ .consumer_supplies = zeus_ohci_regulator_supplies,
+};
- return 0;
-}
+static struct fixed_voltage_config zeus_ohci_regulator_config = {
+ .supply_name = "vbus2",
+ .microvolts = 5000000, /* 5.0V */
+ .gpio = ZEUS_USB2_PWREN_GPIO,
+ .enable_high = 1,
+ .startup_delay = 0,
+ .init_data = &zeus_ohci_regulator_data,
+};
-static void zeus_ohci_exit(struct device *dev)
-{
- /* Power-off port 2 */
- gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 0);
- gpio_free(ZEUS_USB2_PWREN_GPIO);
-}
+static struct platform_device zeus_ohci_regulator_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &zeus_ohci_regulator_config,
+ },
+};
static struct pxaohci_platform_data zeus_ohci_platform_data = {
.port_mode = PMM_NPS_MODE,
/* Clear Power Control Polarity Low and set Power Sense
* Polarity Low. Supply power to USB ports. */
.flags = ENABLE_PORT_ALL | POWER_SENSE_LOW,
- .init = zeus_ohci_init,
- .exit = zeus_ohci_exit,
};
+static void zeus_register_ohci(void)
+{
+ /* Port 2 is shared between host and client interface. */
+ UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
+
+ pxa_set_ohci_info(&zeus_ohci_platform_data);
+}
+
/*
* Flat Panel
*/
@@ -677,6 +671,19 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
.udc_command = zeus_udc_command,
};
+static struct platform_device *zeus_devices[] __initdata = {
+ &zeus_serial_device,
+ &zeus_mtd_devices[0],
+ &zeus_dm9k0_device,
+ &zeus_dm9k1_device,
+ &zeus_sram_device,
+ &zeus_leds_device,
+ &zeus_pcmcia_device,
+ &zeus_max6369_device,
+ &can_regulator_device,
+ &zeus_ohci_regulator_device,
+};
+
#ifdef CONFIG_PM
static void zeus_power_off(void)
{
@@ -847,7 +854,7 @@ static void __init zeus_init(void)
platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));
- pxa_set_ohci_info(&zeus_ohci_platform_data);
+ zeus_register_ohci();
if (zeus_setup_fb_gpios())
pr_err("Failed to setup fb gpios\n");
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations
2014-04-16 13:16 [PATCH v3 0/4] Allow OHCI/EHCI drivers to override more hub operations Laurent Pinchart
` (3 preceding siblings ...)
2014-04-16 13:16 ` [PATCH v3 4/4] ARM: pxa: zeus: Replace OHCI init/exit functions with a regulator Laurent Pinchart
@ 2014-04-16 15:01 ` Alan Stern
4 siblings, 0 replies; 8+ messages in thread
From: Alan Stern @ 2014-04-16 15:01 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 16 Apr 2014, Laurent Pinchart wrote:
> Hello,
>
> The PXA27x OHCI implementation doesn't perform automatic control of port power
> supplies for all ports. While the PPS and LSDA bits of the HcRhPortStatus
> register are implemented, only a subset of ports have an external power enable
> pin controlled by the port status register. Other ports need their power supply
> to be controlled manually.
>
> In order to do so I've implemented manual regulator control in the ohci-pxa27x
> driver. This requires overriding the default behaviour of the CLEAR_FEATURE
> and SET_FEATURE requests for USB_PORT_FEAT_POWER with a custom hub control
> operation. In turn this requires calling the currently static ohci_hub_control
> function from the ohci-pxa27x driver.
>
> The ohci-at91 and ohci-s3c2410 drivers already implement a similar feature,
> and access the ohci_hub_control and ohci_hub_status_data functions by saving
> the struct hc_driver hub_control and hub_status_data values to a variables
> right after calling ohci_init_driver. This vtable-like implementation can be
> optimized by exporting the ohci_hub_control and ohci_hub_status_data functions
> and calling them directly. As the ohci-pxa27x driver needs to override hub
> control operations as well I've decided to export the functions.
>
> For the sake of completeness I've also exported the ehci_hub_control function
> and modified the ehci-tegra driver to call it directly.
>
> As a side note regarding the ohci-at91 driver, the "atmel,vbus-gpio" DT
> property should really have referenced a regulator instead of a GPIO. Fixing
> this in a backward-compatible way would be messy :-(
>
> Please note that I haven't been able to test the third and fourth patches due
> to lack of hardware. I've however tested a similar implementation for OHCI on
> an out of tree PXA270 board.
>
> Changes compared to v2:
>
> - Export ohci_hub_status_data()
> - Call ohci_hub_status_data() directly from ohci-at91 and ohci-s3c2410
>
> Changes compared to v1:
>
> - Export ehci_hub_control()
> - Call ehci_hub_control() directly from ehci-tegra
> - Call ohci_hub_control() directly from ohci-at91
For patches 1 and 2:
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Comments on patch 3 sent separately.
Alan Stern
^ permalink raw reply [flat|nested] 8+ messages in thread