[PATCH 1/2] USB: EHCI: add portpower callback and override

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The current EHCI implementation is prepared to toggle the
PORT_POWER bit to enable or disable a USB-Port. In some
cases this port power can not be toggled by the PORT_POWER
bit but instead i.e. by an external GPIO.
This patch adds an callback to be triggered as well.
The host needs to assign a capable portpower callback.

Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx>
---
 drivers/usb/host/ehci-hcd.c |  2 ++
 drivers/usb/host/ehci-hub.c | 25 +++++++++++++++++++------
 drivers/usb/host/ehci.h     |  1 +
 include/linux/usb/hcd.h     |  1 +
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 488a308..063128c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1233,6 +1233,8 @@ void ehci_init_driver(struct hc_driver *drv,
 		drv->hcd_priv_size += over->extra_priv_size;
 		if (over->reset)
 			drv->reset = over->reset;
+		if (over->portpower)
+			drv->portpower = over->portpower;
 	}
 }
 EXPORT_SYMBOL_GPL(ehci_init_driver);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 6130b75..2bfe660 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -952,6 +952,11 @@ int ehci_hub_control(
 			clear_bit(wIndex, &ehci->port_c_suspend);
 			break;
 		case USB_PORT_FEAT_POWER:
+
+			/* disable port power by callback */
+			if (hcd->driver->portpower)
+				hcd->driver->portpower(hcd, 0);
+
 			if (HCS_PPC (ehci->hcs_params))
 				ehci_writel(ehci, temp & ~PORT_POWER,
 						status_reg);
@@ -1002,12 +1007,16 @@ int ehci_hub_control(
 			 * power switching; they're allowed to just limit the
 			 * current.  khubd will turn the power back on.
 			 */
-			if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle))
-					&& HCS_PPC(ehci->hcs_params)) {
-				ehci_writel(ehci,
-					temp & ~(PORT_RWC_BITS | PORT_POWER),
-					status_reg);
-				temp = ehci_readl(ehci, status_reg);
+			if ((temp & PORT_OC) || (ehci->need_oc_pp_cycle)) {
+				/* disable port power by callback */
+				if (hcd->driver->portpower)
+					hcd->driver->portpower(hcd, 0);
+
+				if (HCS_PPC(ehci->hcs_params)) {
+					temp &= ~(PORT_RWC_BITS | PORT_POWER);
+					ehci_writel(ehci, temp, status_reg);
+					temp = ehci_readl(ehci, status_reg);
+				}
 			}
 		}
 
@@ -1187,6 +1196,10 @@ int ehci_hub_control(
 			set_bit(wIndex, &ehci->suspended_ports);
 			break;
 		case USB_PORT_FEAT_POWER:
+			/* enable port power by callback */
+			if (hcd->driver->portpower)
+				hcd->driver->portpower(hcd, 1);
+
 			if (HCS_PPC (ehci->hcs_params))
 				ehci_writel(ehci, temp | PORT_POWER,
 						status_reg);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index eee228a..7f48048 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -859,6 +859,7 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 struct ehci_driver_overrides {
 	size_t		extra_priv_size;
 	int		(*reset)(struct usb_hcd *hcd);
+	int		(*portpower)(struct usb_hcd *hcd, int enable);
 };
 
 extern void	ehci_init_driver(struct hc_driver *drv,
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 485cd5e..3f60acb 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -241,6 +241,7 @@ struct hc_driver {
 	/* called to init HCD and root hub */
 	int	(*reset) (struct usb_hcd *hcd);
 	int	(*start) (struct usb_hcd *hcd);
+	int	(*portpower)(struct usb_hcd *hcd, int enable);
 
 	/* NOTE:  these suspend/resume calls relate to the HC as
 	 * a whole, not just the root hub; they're for PCI bus glue.
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux