summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/usbtmc.c2
-rw-r--r--drivers/usb/core/hub.c42
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/port.c21
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/dwc2/gadget.c12
-rw-r--r--drivers/usb/dwc3/Kconfig7
-rw-r--r--drivers/usb/dwc3/host.c14
-rw-r--r--drivers/usb/gadget/mv_udc_core.c4
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-mem.c2
-rw-r--r--drivers/usb/host/ehci-msm.c2
-rw-r--r--drivers/usb/host/ehci-pci.c25
-rw-r--r--drivers/usb/host/ehci-spear.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c67
-rw-r--r--drivers/usb/host/fhci-dbg.c8
-rw-r--r--drivers/usb/host/fotg210-hcd.c48
-rw-r--r--drivers/usb/host/max3421-hcd.c48
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c48
-rw-r--r--drivers/usb/host/uhci-grlib.c31
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/uhci-platform.c22
-rw-r--r--drivers/usb/host/xhci-plat.c52
-rw-r--r--drivers/usb/host/xhci-rcar.c148
-rw-r--r--drivers/usb/host/xhci-rcar.h27
-rw-r--r--drivers/usb/host/xhci.c153
-rw-r--r--drivers/usb/misc/usb3503.c37
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c9
-rw-r--r--drivers/usb/serial/kl5kusb105.c30
-rw-r--r--drivers/usb/serial/mos7840.c5
35 files changed, 565 insertions, 327 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 103a6e9ee49d..ec978408a2ee 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -715,7 +715,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
u8 *buffer;
int rv;
int n;
- int actual;
+ int actual = 0;
int max_size;
dev = &data->intf->dev;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 21b99b4b4082..88f1db27e0af 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2587,13 +2587,20 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
/* Is a USB 3.0 port in the Inactive or Compliance Mode state?
* Port worm reset is required to recover
*/
-static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
+static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+ u16 portstatus)
{
- return hub_is_superspeed(hub->hdev) &&
- (((portstatus & USB_PORT_STAT_LINK_STATE) ==
- USB_SS_PORT_LS_SS_INACTIVE) ||
- ((portstatus & USB_PORT_STAT_LINK_STATE) ==
- USB_SS_PORT_LS_COMP_MOD)) ;
+ u16 link_state;
+
+ if (!hub_is_superspeed(hub->hdev))
+ return false;
+
+ if (test_bit(port1, hub->warm_reset_bits))
+ return true;
+
+ link_state = portstatus & USB_PORT_STAT_LINK_STATE;
+ return link_state == USB_SS_PORT_LS_SS_INACTIVE
+ || link_state == USB_SS_PORT_LS_COMP_MOD;
}
static int hub_port_wait_reset(struct usb_hub *hub, int port1,
@@ -2630,7 +2637,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
if ((portstatus & USB_PORT_STAT_RESET))
return -EBUSY;
- if (hub_port_warm_reset_required(hub, portstatus))
+ if (hub_port_warm_reset_required(hub, port1, portstatus))
return -ENOTCONN;
/* Device went away? */
@@ -2730,9 +2737,10 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
if (status < 0)
goto done;
- if (hub_port_warm_reset_required(hub, portstatus))
+ if (hub_port_warm_reset_required(hub, port1, portstatus))
warm = true;
}
+ clear_bit(port1, hub->warm_reset_bits);
/* Reset the port */
for (i = 0; i < PORT_RESET_TRIES; i++) {
@@ -2769,7 +2777,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
&portstatus, &portchange) < 0)
goto done;
- if (!hub_port_warm_reset_required(hub, portstatus))
+ if (!hub_port_warm_reset_required(hub, port1,
+ portstatus))
goto done;
/*
@@ -2856,8 +2865,13 @@ static int check_port_resume_type(struct usb_device *udev,
{
struct usb_port *port_dev = hub->ports[port1 - 1];
+ /* Is a warm reset needed to recover the connection? */
+ if (status == 0 && udev->reset_resume
+ && hub_port_warm_reset_required(hub, port1, portstatus)) {
+ /* pass */;
+ }
/* Is the device still present? */
- if (status || port_is_suspended(hub, portstatus) ||
+ else if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus) ||
!(portstatus & USB_PORT_STAT_CONNECTION)) {
if (status >= 0)
@@ -3860,7 +3874,8 @@ int usb_disable_lpm(struct usb_device *udev)
if (!udev || !udev->parent ||
udev->speed != USB_SPEED_SUPER ||
- !udev->lpm_capable)
+ !udev->lpm_capable ||
+ udev->state < USB_STATE_DEFAULT)
return 0;
hcd = bus_to_hcd(udev->bus);
@@ -3916,7 +3931,8 @@ void usb_enable_lpm(struct usb_device *udev)
if (!udev || !udev->parent ||
udev->speed != USB_SPEED_SUPER ||
- !udev->lpm_capable)
+ !udev->lpm_capable ||
+ udev->state < USB_STATE_DEFAULT)
return;
udev->lpm_disable_count--;
@@ -4870,7 +4886,7 @@ static void port_event(struct usb_hub *hub, int port1)
* Warm reset a USB3 protocol port if it's in
* SS.Inactive state.
*/
- if (hub_port_warm_reset_required(hub, portstatus)) {
+ if (hub_port_warm_reset_required(hub, port1, portstatus)) {
dev_dbg(&port_dev->dev, "do warm reset\n");
if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
|| udev->state == USB_STATE_NOTATTACHED) {
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 326308e53961..c77d8778af4b 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -52,6 +52,8 @@ struct usb_hub {
unsigned long power_bits[1]; /* ports that are powered */
unsigned long child_usage_bits[1]; /* ports powered on for
children */
+ unsigned long warm_reset_bits[1]; /* ports requesting warm
+ reset recovery */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index fe1b6d0967e3..cd3f9dc24a06 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -103,16 +103,19 @@ static int usb_port_runtime_resume(struct device *dev)
msleep(hub_power_on_good_delay(hub));
if (udev && !retval) {
/*
- * Attempt to wait for usb hub port to be reconnected in order
- * to make the resume procedure successful. The device may have
- * disconnected while the port was powered off, so ignore the
- * return status.
+ * Our preference is to simply wait for the port to reconnect,
+ * as that is the lowest latency method to restart the port.
+ * However, there are cases where toggling port power results in
+ * the host port and the device port getting out of sync causing
+ * a link training live lock. Upon timeout, flag the port as
+ * needing warm reset recovery (to be performed later by
+ * usb_port_resume() as requested via usb_wakeup_notification())
*/
- retval = hub_port_debounce_be_connected(hub, port1);
- if (retval < 0)
- dev_dbg(&port_dev->dev, "can't get reconnection after setting port power on, status %d\n",
- retval);
- retval = 0;
+ if (hub_port_debounce_be_connected(hub, port1) < 0) {
+ dev_dbg(&port_dev->dev, "reconnect timeout\n");
+ if (hub_is_superspeed(hdev))
+ set_bit(port1, hub->warm_reset_bits);
+ }
/* Force the child awake to revalidate after the power loss. */
if (!test_and_set_bit(port1, hub->child_usage_bits)) {
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 739ee8e8bdfd..2c9ba4077075 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -152,6 +152,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* USB3503 */
+ { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
{ } /* terminating entry must be last */
};
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index f3c56a2fed5b..0ba9c335b584 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1,6 +1,4 @@
/**
- * linux/drivers/usb/gadget/s3c-hsotg.c
- *
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
@@ -1022,7 +1020,8 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
*
* Set stall for ep0 as response for setup request.
*/
-static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
+static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg)
+{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
u32 reg;
u32 ctrl;
@@ -1994,7 +1993,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
s3c_hsotg_complete_request(hsotg, ep, req,
result);
}
- if(hsotg->dedicated_fifos)
+ if (hsotg->dedicated_fifos)
if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072)
s3c_hsotg_txfifo_flush(hsotg, ep->index);
}
@@ -3390,10 +3389,8 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
int i;
hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
- if (!hsotg) {
- dev_err(dev, "cannot get memory\n");
+ if (!hsotg)
return -ENOMEM;
- }
/*
* Attempt to find a generic PHY, then look for an old style
@@ -3512,7 +3509,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep),
GFP_KERNEL);
if (!eps) {
- dev_err(dev, "cannot get memory\n");
ret = -ENOMEM;
goto err_supplies;
}
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 261c3b428220..785510a0a0c3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -93,4 +93,11 @@ config USB_DWC3_VERBOSE
help
Say Y here to enable verbose debugging messages on DWC3 Driver.
+config DWC3_HOST_USB3_LPM_ENABLE
+ bool "Enable USB3 LPM Capability"
+ depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+ default n
+ help
+ Select this when you want to enable USB3 LPM with dwc3 xhci host.
+
endif
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 32db328cc769..dcb8ca084598 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,12 +16,14 @@
*/
#include <linux/platform_device.h>
+#include <linux/usb/xhci_pdriver.h>
#include "core.h"
int dwc3_host_init(struct dwc3 *dwc)
{
struct platform_device *xhci;
+ struct usb_xhci_pdata pdata;
int ret;
xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
@@ -46,6 +48,18 @@ int dwc3_host_init(struct dwc3 *dwc)
goto err1;
}
+ memset(&pdata, 0, sizeof(pdata));
+
+#ifdef CONFIG_DWC3_HOST_USB3_LPM_ENABLE
+ pdata.usb3_lpm_capable = 1;
+#endif
+
+ ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
+ if (ret) {
+ dev_err(dwc->dev, "couldn't add platform data to xHCI device\n");
+ goto err1;
+ }
+
ret = platform_device_add(xhci);
if (ret) {
dev_err(dwc->dev, "failed to register xHCI device\n");
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index fcff3a571b45..040fb169b162 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -332,7 +332,7 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req)
/* clear active and halt bit, in case set from a previous error */
dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);
- /* Ensure that updates to the QH will occure before priming. */
+ /* Ensure that updates to the QH will occur before priming. */
wmb();
/* Prime the Endpoint */
@@ -1656,7 +1656,7 @@ static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
dev_dbg(&udc->dev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
setup->bRequestType, setup->bRequest,
setup->wValue, setup->wIndex, setup->wLength);
- /* We process some stardard setup requests here */
+ /* We process some standard setup requests here */
if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
switch (setup->bRequest) {
case USB_REQ_GET_STATUS:
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 03314f861bee..82800a775501 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -37,6 +37,14 @@ config USB_XHCI_MVEBU
Say 'Y' to enable the support for the xHCI host controller
found in Marvell Armada 375/38x ARM SOCs.
+config USB_XHCI_RCAR
+ tristate "xHCI support for Renesas R-Car SoCs"
+ select USB_XHCI_PLATFORM
+ depends on ARCH_SHMOBILE || COMPILE_TEST
+ ---help---
+ Say 'Y' to enable the support for the xHCI host controller
+ found in Renesas R-Car ARM SoCs.
+
endif # USB_XHCI_HCD
config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index af89a903d97e..144c038ef70f 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -22,6 +22,9 @@ ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
ifneq ($(CONFIG_USB_XHCI_MVEBU), )
xhci-hcd-y += xhci-mvebu.o
endif
+ifneq ($(CONFIG_USB_XHCI_RCAR), )
+ xhci-hcd-y += xhci-rcar.o
+endif
endif
obj-$(CONFIG_USB_WHCI_HCD) += whci/
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d1c76216350f..cda0a2f5c467 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -88,7 +88,7 @@ static int exynos_ehci_get_phy(struct device *dev,
return -EINVAL;
}
- phy = devm_of_phy_get(dev, child, 0);
+ phy = devm_of_phy_get(dev, child, NULL);
of_node_put(child);
if (IS_ERR(phy)) {
ret = PTR_ERR(phy);
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index c0fb6a8ae6a3..b6205fac3567 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -209,7 +209,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
ehci->periodic = (__le32 *)
dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
ehci->periodic_size * sizeof(__le32),
- &ehci->periodic_dma, 0);
+ &ehci->periodic_dma, flags);
if (ehci->periodic == NULL) {
goto fail;
}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 982c09bebe0f..934b39d5e44a 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -190,7 +190,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
.resume = ehci_msm_pm_resume,
};
-static struct of_device_id msm_ehci_dt_match[] = {
+static const struct of_device_id msm_ehci_dt_match[] = {
{ .compatible = "qcom,ehci-host", },
{}
};
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 3e86bf4371b3..ca7b964124af 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -35,6 +35,21 @@ static const char hcd_name[] = "ehci-pci";
#define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70
/*-------------------------------------------------------------------------*/
+#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939
+static inline bool is_intel_quark_x1000(struct pci_dev *pdev)
+{
+ return pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC;
+}
+
+/*
+ * 0x84 is the offset of in/out threshold register,
+ * and it is the same offset as the register of 'hostpc'.
+ */
+#define intel_quark_x1000_insnreg01 hostpc
+
+/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */
+#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD 0x007f007f
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
@@ -50,6 +65,16 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
if (!retval)
ehci_dbg(ehci, "MWI active\n");
+ /* Reset the threshold limit */
+ if (is_intel_quark_x1000(pdev)) {
+ /*
+ * For the Intel QUARK X1000, raise the I/O threshold to the
+ * maximum usable value in order to improve performance.
+ */
+ ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD,
+ ehci->regs->intel_quark_x1000_insnreg01);
+ }
+
return 0;
}
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 1d59958ad0ce..1355ff0946b9 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -150,7 +150,7 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id spear_ehci_id_table[] = {
+static const struct of_device_id spear_ehci_id_table[] = {
{ .compatible = "st,spear600-ehci", },
{ },
};
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6fdcb8ad2296..7aafb05e7a40 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -46,6 +46,7 @@
#define DRV_NAME "tegra-ehci"
static struct hc_driver __read_mostly tegra_ehci_hc_driver;
+static bool usb1_reset_attempted;
struct tegra_ehci_soc_config {
bool has_hostpc;
@@ -60,6 +61,61 @@ struct tegra_ehci_hcd {
enum tegra_usb_phy_port_speed port_speed;
};
+/*
+ * The 1st USB controller contains some UTMI pad registers that are global for
+ * all the controllers on the chip. Those registers are also cleared when
+ * reset is asserted to the 1st controller. This means that the 1st controller
+ * can only be reset when no other controlled has finished probing. So we'll
+ * reset the 1st controller before doing any other setup on any of the
+ * controllers, and then never again.
+ *
+ * Since this is a PHY issue, the Tegra PHY driver should probably be doing
+ * the resetting of the USB controllers. But to keep compatibility with old
+ * device trees that don't have reset phandles in the PHYs, do it here.
+ * Those old DTs will be vulnerable to total USB breakage if the 1st EHCI
+ * device isn't the first one to finish probing, so warn them.
+ */
+static int tegra_reset_usb_controller(struct platform_device *pdev)
+{
+ struct device_node *phy_np;
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct tegra_ehci_hcd *tegra =
+ (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+ phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
+ if (!phy_np)
+ return -ENOENT;
+
+ if (!usb1_reset_attempted) {
+ struct reset_control *usb1_reset;
+
+ usb1_reset = of_reset_control_get(phy_np, "usb");
+ if (IS_ERR(usb1_reset)) {
+ dev_warn(&pdev->dev,
+ "can't get utmi-pads reset from the PHY\n");
+ dev_warn(&pdev->dev,
+ "continuing, but please update your DT\n");
+ } else {
+ reset_control_assert(usb1_reset);
+ udelay(1);
+ reset_control_deassert(usb1_reset);
+ }
+
+ reset_control_put(usb1_reset);
+ usb1_reset_attempted = true;
+ }
+
+ if (!of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) {
+ reset_control_assert(tegra->rst);
+ udelay(1);
+ reset_control_deassert(tegra->rst);
+ }
+
+ of_node_put(phy_np);
+
+ return 0;
+}
+
static int tegra_ehci_internal_port_reset(
struct ehci_hcd *ehci,
u32 __iomem *portsc_reg
@@ -326,7 +382,7 @@ static const struct tegra_ehci_soc_config tegra20_soc_config = {
.has_hostpc = false,
};
-static struct of_device_id tegra_ehci_of_match[] = {
+static const struct of_device_id tegra_ehci_of_match[] = {
{ .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config },
{ .compatible = "nvidia,tegra20-ehci", .data = &tegra20_soc_config },
{ },
@@ -389,9 +445,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (err)
goto cleanup_hcd_create;
- reset_control_assert(tegra->rst);
- udelay(1);
- reset_control_deassert(tegra->rst);
+ err = tegra_reset_usb_controller(pdev);
+ if (err)
+ goto cleanup_clk_en;
u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
if (IS_ERR(u_phy)) {
@@ -479,10 +535,11 @@ static int tegra_ehci_remove(struct platform_device *pdev)
usb_phy_shutdown(hcd->phy);
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
clk_disable_unprepare(tegra->clk);
+ usb_put_hcd(hcd);
+
return 0;
}
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c
index f238cb37305c..b58e7a60913a 100644
--- a/drivers/usb/host/fhci-dbg.c
+++ b/drivers/usb/host/fhci-dbg.c
@@ -129,11 +129,7 @@ void fhci_dfs_destroy(struct fhci_hcd *fhci)
if (!fhci->dfs_root)
return;
- if (fhci->dfs_irq_stat)
- debugfs_remove(fhci->dfs_irq_stat);
-
- if (fhci->dfs_regs)
- debugfs_remove(fhci->dfs_regs);
-
+ debugfs_remove(fhci->dfs_irq_stat);
+ debugfs_remove(fhci->dfs_regs);
debugfs_remove(fhci->dfs_root);
}
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 98a89d16cc3e..adcd2050dced 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -5838,41 +5838,17 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
goto fail_create_hcd;
}
+ hcd->has_tt = 1;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(dev));
- retval = -ENODEV;
- goto fail_request_resource;
+ hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hcd->regs)) {
+ retval = PTR_ERR(hcd->regs);
+ goto failed;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- hcd->has_tt = 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- fotg210_fotg210_hc_driver.description)) {
- dev_dbg(dev, "controller already in use\n");
- retval = -EBUSY;
- goto fail_request_resource;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!res) {
- dev_err(dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(dev));
- retval = -ENODEV;
- goto fail_request_resource;
- }
-
- hcd->regs = ioremap_nocache(res->start, resource_size(res));
- if (hcd->regs == NULL) {
- dev_dbg(dev, "error mapping memory\n");
- retval = -EFAULT;
- goto fail_ioremap;
- }
fotg210 = hcd_to_fotg210(hcd);
@@ -5880,24 +5856,20 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
retval = fotg210_setup(hcd);
if (retval)
- goto fail_add_hcd;
+ goto failed;
fotg210_init(fotg210);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval) {
dev_err(dev, "failed to add hcd with err %d\n", retval);
- goto fail_add_hcd;
+ goto failed;
}
device_wakeup_enable(hcd->self.controller);
return retval;
-fail_add_hcd:
- iounmap(hcd->regs);
-fail_ioremap:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+failed:
usb_put_hcd(hcd);
fail_create_hcd:
dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
@@ -5918,8 +5890,6 @@ static int fotg210_hcd_remove(struct platform_device *pdev)
return 0;
usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
return 0;
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
index 858efcfda50b..6234c75da33f 100644
--- a/drivers/usb/host/max3421-hcd.c
+++ b/drivers/usb/host/max3421-hcd.c
@@ -102,6 +102,15 @@ enum scheduling_pass {
SCHED_PASS_DONE
};
+/* Bit numbers for max3421_hcd->todo: */
+enum {
+ ENABLE_IRQ = 0,
+ RESET_HCD,
+ RESET_PORT,
+ CHECK_UNLINK,
+ IOPIN_UPDATE
+};
+
struct max3421_dma_buf {
u8 data[2];
};
@@ -146,11 +155,7 @@ struct max3421_hcd {
u8 hien;
u8 mode;
u8 iopins[2];
- unsigned int do_enable_irq:1;
- unsigned int do_reset_hcd:1;
- unsigned int do_reset_port:1;
- unsigned int do_check_unlink:1;
- unsigned int do_iopin_update:1;
+ unsigned long todo;
#ifdef DEBUG
unsigned long err_stat[16];
#endif
@@ -1165,10 +1170,8 @@ max3421_irq_handler(int irq, void *dev_id)
if (max3421_hcd->spi_thread &&
max3421_hcd->spi_thread->state != TASK_RUNNING)
wake_up_process(max3421_hcd->spi_thread);
- if (!max3421_hcd->do_enable_irq) {
- max3421_hcd->do_enable_irq = 1;
+ if (!test_and_set_bit(ENABLE_IRQ, &max3421_hcd->todo))
disable_irq_nosync(spi->irq);
- }
return IRQ_HANDLED;
}
@@ -1423,10 +1426,8 @@ max3421_spi_thread(void *dev_id)
spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
set_current_state(TASK_INTERRUPTIBLE);
- if (max3421_hcd->do_enable_irq) {
- max3421_hcd->do_enable_irq = 0;
+ if (test_and_clear_bit(ENABLE_IRQ, &max3421_hcd->todo))
enable_irq(spi->irq);
- }
schedule();
__set_current_state(TASK_RUNNING);
}
@@ -1440,23 +1441,18 @@ max3421_spi_thread(void *dev_id)
else if (!max3421_hcd->curr_urb)
i_worked |= max3421_select_and_start_urb(hcd);
- if (max3421_hcd->do_reset_hcd) {
+ if (test_and_clear_bit(RESET_HCD, &max3421_hcd->todo))
/* reset the HCD: */
- max3421_hcd->do_reset_hcd = 0;
i_worked |= max3421_reset_hcd(hcd);
- }
- if (max3421_hcd->do_reset_port) {
+ if (test_and_clear_bit(RESET_PORT, &max3421_hcd->todo)) {
/* perform a USB bus reset: */
- max3421_hcd->do_reset_port = 0;
spi_wr8(hcd, MAX3421_REG_HCTL,
BIT(MAX3421_HCTL_BUSRST_BIT));
i_worked = 1;
}
- if (max3421_hcd->do_check_unlink) {
- max3421_hcd->do_check_unlink = 0;
+ if (test_and_clear_bit(CHECK_UNLINK, &max3421_hcd->todo))
i_worked |= max3421_check_unlink(hcd);
- }
- if (max3421_hcd->do_iopin_update) {
+ if (test_and_clear_bit(IOPIN_UPDATE, &max3421_hcd->todo)) {
/*
* IOPINS1/IOPINS2 do not auto-increment, so we can't
* use spi_wr_buf().
@@ -1469,7 +1465,6 @@ max3421_spi_thread(void *dev_id)
spi_wr8(hcd, MAX3421_REG_IOPINS1 + i, val);
max3421_hcd->iopins[i] = val;
}
- max3421_hcd->do_iopin_update = 0;
i_worked = 1;
}
}
@@ -1485,7 +1480,8 @@ max3421_reset_port(struct usb_hcd *hcd)
max3421_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |
USB_PORT_STAT_LOW_SPEED);
- max3421_hcd->do_reset_port = 1;
+ max3421_hcd->port_status |= USB_PORT_STAT_RESET;
+ set_bit(RESET_PORT, &max3421_hcd->todo);
wake_up_process(max3421_hcd->spi_thread);
return 0;
}
@@ -1498,7 +1494,7 @@ max3421_reset(struct usb_hcd *hcd)
hcd->self.sg_tablesize = 0;
hcd->speed = HCD_USB2;
hcd->self.root_hub->speed = USB_SPEED_FULL;
- max3421_hcd->do_reset_hcd = 1;
+ set_bit(RESET_HCD, &max3421_hcd->todo);
wake_up_process(max3421_hcd->spi_thread);
return 0;
}
@@ -1551,7 +1547,7 @@ max3421_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
max3421_ep = urb->ep->hcpriv;
if (!max3421_ep) {
/* gets freed in max3421_endpoint_disable: */
- max3421_ep = kzalloc(sizeof(struct max3421_ep), mem_flags);
+ max3421_ep = kzalloc(sizeof(struct max3421_ep), GFP_ATOMIC);
if (!max3421_ep) {
retval = -ENOMEM;
goto out;
@@ -1590,7 +1586,7 @@ max3421_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
*/
retval = usb_hcd_check_unlink_urb(hcd, urb, status);
if (retval == 0) {
- max3421_hcd->do_check_unlink = 1;
+ set_bit(CHECK_UNLINK, &max3421_hcd->todo);
wake_up_process(max3421_hcd->spi_thread);
}
spin_unlock_irqrestore(&max3421_hcd->lock, flags);
@@ -1690,7 +1686,7 @@ max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value)
max3421_hcd->iopins[idx] |= mask;
else
max3421_hcd->iopins[idx] &= ~mask;
- max3421_hcd->do_iopin_update = 1;
+ set_bit(IOPIN_UPDATE, &max3421_hcd->todo);
wake_up_process(max3421_hcd->spi_thread);
}
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 060a6a414750..a72ab8fe8cd3 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -87,7 +87,7 @@ static int exynos_ohci_get_phy(struct device *dev,
return -EINVAL;
}
- phy = devm_of_phy_get(dev, child, 0);
+ phy = devm_of_phy_get(dev, child, NULL);
of_node_put(child);
if (IS_ERR(phy)) {
ret = PTR_ERR(phy);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index f98d03f3144c..6f8ec52c7e0c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -559,7 +559,7 @@ static int ohci_init (struct ohci_hcd *ohci)
return 0;
ohci->hcca = dma_alloc_coherent (hcd->self.controller,
- sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+ sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
if (!ohci->hcca)
return -ENOMEM;
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 8b29a0c04c23..8d5876692e7c 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -162,7 +162,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
}
#endif
-static struct of_device_id spear_ohci_id_table[] = {
+static const struct of_device_id spear_ohci_id_table[] = {
{ .compatible = "st,spear600-ohci", },
{ },
};
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index e07248b6ab67..da5fb0e3c363 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3826,49 +3826,36 @@ static int oxu_drv_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "IRQ resource %d\n", irq);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "no registers address! Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base)) {
+ ret = PTR_ERR(base);
+ goto error;
}
memstart = res->start;
memlen = resource_size(res);
- dev_dbg(&pdev->dev, "MEM resource %lx-%lx\n", memstart, memlen);
- if (!request_mem_region(memstart, memlen,
- oxu_hc_driver.description)) {
- dev_dbg(&pdev->dev, "memory area already in use\n");
- return -EBUSY;
- }
ret = irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);
if (ret) {
dev_err(&pdev->dev, "error setting irq type\n");
ret = -EFAULT;
- goto error_set_irq_type;
- }
-
- base = ioremap(memstart, memlen);
- if (!base) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- ret = -EFAULT;
- goto error_ioremap;
+ goto error;
}
/* Allocate a driver data struct to hold useful info for both
* SPH & OTG devices
*/
- info = kzalloc(sizeof(struct oxu_info), GFP_KERNEL);
+ info = devm_kzalloc(&pdev->dev, sizeof(struct oxu_info), GFP_KERNEL);
if (!info) {
dev_dbg(&pdev->dev, "error allocating memory\n");
ret = -EFAULT;
- goto error_alloc;
+ goto error;
}
platform_set_drvdata(pdev, info);
ret = oxu_init(pdev, memstart, memlen, base, irq);
if (ret < 0) {
dev_dbg(&pdev->dev, "cannot init USB devices\n");
- goto error_init;
+ goto error;
}
dev_info(&pdev->dev, "devices enabled and running\n");
@@ -3876,16 +3863,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
return 0;
-error_init:
- kfree(info);
-
-error_alloc:
- iounmap(base);
-
-error_set_irq_type:
-error_ioremap:
- release_mem_region(memstart, memlen);
-
+error:
dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
return ret;
}
@@ -3899,18 +3877,10 @@ static void oxu_remove(struct platform_device *pdev, struct usb_hcd *hcd)
static int oxu_drv_remove(struct platform_device *pdev)
{
struct oxu_info *info = platform_get_drvdata(pdev);
- unsigned long memstart = info->hcd[0]->rsrc_start,
- memlen = info->hcd[0]->rsrc_len;
- void *base = info->hcd[0]->regs;
oxu_remove(pdev, info->hcd[0]);
oxu_remove(pdev, info->hcd[1]);
- iounmap(base);
- release_mem_region(memstart, memlen);
-
- kfree(info);
-
return 0;
}
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index ab25dc397e8b..05f57ffdf9ab 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -17,6 +17,7 @@
* (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
*/
+#include <linux/device.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
@@ -113,24 +114,17 @@ static int uhci_hcd_grlib_probe(struct platform_device *op)
hcd->rsrc_start = res.start;
hcd->rsrc_len = resource_size(&res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
- rv = -EBUSY;
- goto err_rmr;
- }
-
irq = irq_of_parse_and_map(dn, 0);
if (irq == NO_IRQ) {
printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
rv = -EBUSY;
- goto err_irq;
+ goto err_usb;
}
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
- rv = -ENOMEM;
- goto err_ioremap;
+ hcd->regs = devm_ioremap_resource(&op->dev, &res);
+ if (IS_ERR(hcd->regs)) {
+ rv = PTR_ERR(hcd->regs);
+ goto err_irq;
}
uhci = hcd_to_uhci(hcd);
@@ -139,18 +133,14 @@ static int uhci_hcd_grlib_probe(struct platform_device *op)
rv = usb_add_hcd(hcd, irq, 0);
if (rv)
- goto err_uhci;
+ goto err_irq;
device_wakeup_enable(hcd->self.controller);
return 0;
-err_uhci:
- iounmap(hcd->regs);
-err_ioremap:
- irq_dispose_mapping(irq);
err_irq:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_rmr:
+ irq_dispose_mapping(irq);
+err_usb:
usb_put_hcd(hcd);
return rv;
@@ -164,10 +154,7 @@ static int uhci_hcd_grlib_remove(struct platform_device *op)
usb_remove_hcd(hcd);
- iounmap(hcd->regs);
irq_dispose_mapping(hcd->irq);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
usb_put_hcd(hcd);
return 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 27f35e8f161b..a7de8e8bb458 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -591,7 +591,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
- &uhci->frame_dma_handle, 0);
+ &uhci->frame_dma_handle, GFP_KERNEL);
if (!uhci->frame) {
dev_err(uhci_dev(uhci),
"unable to allocate consistent memory for frame list\n");
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 01833ab2b5c3..b987f1d10058 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -8,6 +8,7 @@
*/
#include <linux/of.h>
+#include <linux/device.h>
#include <linux/platform_device.h>
static int uhci_platform_init(struct usb_hcd *hcd)
@@ -88,33 +89,22 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_err("%s: request_mem_region failed\n", __func__);
- ret = -EBUSY;
+ hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hcd->regs)) {
+ ret = PTR_ERR(hcd->regs);
goto err_rmr;
}
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_err("%s: ioremap failed\n", __func__);
- ret = -ENOMEM;
- goto err_irq;
- }
uhci = hcd_to_uhci(hcd);
uhci->regs = hcd->regs;
ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
if (ret)
- goto err_uhci;
+ goto err_rmr;
device_wakeup_enable(hcd->self.controller);
return 0;
-err_uhci:
- iounmap(hcd->regs);
-err_irq:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_rmr:
usb_put_hcd(hcd);
@@ -126,8 +116,6 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
return 0;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 29d8adb5c8d1..1a0cf9f31e43 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -17,9 +17,11 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/usb/xhci_pdriver.h>
#include "xhci.h"
#include "xhci-mvebu.h"
+#include "xhci-rcar.h"
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
@@ -34,11 +36,27 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
/* called during probe() after chip reset completes */
static int xhci_plat_setup(struct usb_hcd *hcd)
{
+ struct device_node *of_node = hcd->self.controller->of_node;
+ int ret;
+
+ if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
+ of_device_is_compatible(of_node, "renesas,xhci-r8a7791")) {
+ ret = xhci_rcar_init_quirk(hcd);
+ if (ret)
+ return ret;
+ }
+
return xhci_gen_setup(hcd, xhci_plat_quirks);
}
static int xhci_plat_start(struct usb_hcd *hcd)
{
+ struct device_node *of_node = hcd->self.controller->of_node;
+
+ if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
+ of_device_is_compatible(of_node, "renesas,xhci-r8a7791"))
+ xhci_rcar_start(hcd);
+
return xhci_run(hcd);
}
@@ -90,10 +108,15 @@ static const struct hc_driver xhci_plat_xhci_driver = {
.hub_status_data = xhci_hub_status_data,
.bus_suspend = xhci_bus_suspend,
.bus_resume = xhci_bus_resume,
+
+ .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
+ .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
};
static int xhci_plat_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
+ struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev);
const struct hc_driver *driver;
struct xhci_hcd *xhci;
struct resource *res;
@@ -140,20 +163,12 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description)) {
- dev_dbg(&pdev->dev, "controller already in use\n");
- ret = -EBUSY;
+ hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hcd->regs)) {
+ ret = PTR_ERR(hcd->regs);
goto put_hcd;
}
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- ret = -EFAULT;
- goto release_mem_region;
- }
-
/*
* Not all platforms have a clk so it is not an error if the
* clock does not exists.
@@ -162,7 +177,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (!IS_ERR(clk)) {
ret = clk_prepare_enable(clk);
if (ret)
- goto unmap_registers;
+ goto put_hcd;
}
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -182,6 +197,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
goto dealloc_usb2_hcd;
}
+ if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
+ (pdata && pdata->usb3_lpm_capable))
+ xhci->quirks |= XHCI_LPM_SUPPORT;
/*
* Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
* is called by usb_add_hcd().
@@ -207,12 +225,6 @@ disable_clk:
if (!IS_ERR(clk))
clk_disable_unprepare(clk);
-unmap_registers:
- iounmap(hcd->regs);
-
-release_mem_region:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
put_hcd:
usb_put_hcd(hcd);
@@ -231,8 +243,6 @@ static int xhci_plat_remove(struct platform_device *dev)
usb_remove_hcd(hcd);
if (!IS_ERR(clk))
clk_disable_unprepare(clk);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
kfree(xhci);
@@ -270,6 +280,8 @@ static const struct of_device_id usb_xhci_of_match[] = {
{ .compatible = "xhci-platform" },
{ .compatible = "marvell,armada-375-xhci"},
{ .compatible = "marvell,armada-380-xhci"},
+ { .compatible = "renesas,xhci-r8a7790"},
+ { .compatible = "renesas,xhci-r8a7791"},
{ },
};
MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
new file mode 100644
index 000000000000..ff0d1b44ea58
--- /dev/null
+++ b/drivers/usb/host/xhci-rcar.c
@@ -0,0 +1,148 @@
+/*
+ * xHCI host controller driver for R-Car SoCs
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/phy.h>
+
+#include "xhci.h"
+#include "xhci-rcar.h"
+
+#define FIRMWARE_NAME "r8a779x_usb3_v1.dlmem"
+MODULE_FIRMWARE(FIRMWARE_NAME);
+
+/*** Register Offset ***/
+#define RCAR_USB3_INT_ENA 0x224 /* Interrupt Enable */
+#define RCAR_USB3_DL_CTRL 0x250 /* FW Download Control & Status */
+#define RCAR_USB3_FW_DATA0 0x258 /* FW Data0 */
+
+#define RCAR_USB3_LCLK 0xa44 /* LCLK Select */
+#define RCAR_USB3_CONF1 0xa48 /* USB3.0 Configuration1 */
+#define RCAR_USB3_CONF2 0xa5c /* USB3.0 Configuration2 */
+#define RCAR_USB3_CONF3 0xaa8 /* USB3.0 Configuration3 */
+#define RCAR_USB3_RX_POL 0xab0 /* USB3.0 RX Polarity */
+#define RCAR_USB3_TX_POL 0xab8 /* USB3.0 TX Polarity */
+
+/*** Register Settings ***/
+/* Interrupt Enable */
+#define RCAR_USB3_INT_XHC_ENA 0x00000001
+#define RCAR_USB3_INT_PME_ENA 0x00000002
+#define RCAR_USB3_INT_HSE_ENA 0x00000004
+#define RCAR_USB3_INT_ENA_VAL (RCAR_USB3_INT_XHC_ENA | \
+ RCAR_USB3_INT_PME_ENA | RCAR_USB3_INT_HSE_ENA)
+
+/* FW Download Control & Status */
+#define RCAR_USB3_DL_CTRL_ENABLE 0x00000001
+#define RCAR_USB3_DL_CTRL_FW_SUCCESS 0x00000010
+#define RCAR_USB3_DL_CTRL_FW_SET_DATA0 0x00000100
+
+/* LCLK Select */
+#define RCAR_USB3_LCLK_ENA_VAL 0x01030001
+
+/* USB3.0 Configuration */
+#define RCAR_USB3_CONF1_VAL 0x00030204
+#define RCAR_USB3_CONF2_VAL 0x00030300
+#define RCAR_USB3_CONF3_VAL 0x13802007
+
+/* USB3.0 Polarity */
+#define RCAR_USB3_RX_POL_VAL BIT(21)
+#define RCAR_USB3_TX_POL_VAL BIT(4)
+
+void xhci_rcar_start(struct usb_hcd *hcd)
+{
+ u32 temp;
+
+ if (hcd->regs != NULL) {
+ /* Interrupt Enable */
+ temp = readl(hcd->regs + RCAR_USB3_INT_ENA);
+ temp |= RCAR_USB3_INT_ENA_VAL;
+ writel(temp, hcd->regs + RCAR_USB3_INT_ENA);
+ /* LCLK Select */
+ writel(RCAR_USB3_LCLK_ENA_VAL, hcd->regs + RCAR_USB3_LCLK);
+ /* USB3.0 Configuration */
+ writel(RCAR_USB3_CONF1_VAL, hcd->regs + RCAR_USB3_CONF1);
+ writel(RCAR_USB3_CONF2_VAL, hcd->regs + RCAR_USB3_CONF2);
+ writel(RCAR_USB3_CONF3_VAL, hcd->regs + RCAR_USB3_CONF3);
+ /* USB3.0 Polarity */
+ writel(RCAR_USB3_RX_POL_VAL, hcd->regs + RCAR_USB3_RX_POL);
+ writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL);
+ }
+}
+
+static int xhci_rcar_download_firmware(struct device *dev, void __iomem *regs)
+{
+ const struct firmware *fw;
+ int retval, index, j, time;
+ int timeout = 10000;
+ u32 data, val, temp;
+
+ /* request R-Car USB3.0 firmware */
+ retval = request_firmware(&fw, FIRMWARE_NAME, dev);
+ if (retval)
+ return retval;
+
+ /* download R-Car USB3.0 firmware */
+ temp = readl(regs + RCAR_USB3_DL_CTRL);
+ temp |= RCAR_USB3_DL_CTRL_ENABLE;
+ writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+ for (index = 0; index < fw->size; index += 4) {
+ /* to avoid reading beyond the end of the buffer */
+ for (data = 0, j = 3; j >= 0; j--) {
+ if ((j + index) < fw->size)
+ data |= fw->data[index + j] << (8 * j);
+ }
+ writel(data, regs + RCAR_USB3_FW_DATA0);
+ temp = readl(regs + RCAR_USB3_DL_CTRL);
+ temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
+ writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+ for (time = 0; time < timeout; time++) {
+ val = readl(regs + RCAR_USB3_DL_CTRL);
+ if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)
+ break;
+ udelay(1);
+ }
+ if (time == timeout) {
+ retval = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ temp = readl(regs + RCAR_USB3_DL_CTRL);
+ temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
+ writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+ for (time = 0; time < timeout; time++) {
+ val = readl(regs + RCAR_USB3_DL_CTRL);
+ if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {
+ retval = 0;
+ break;
+ }
+ udelay(1);
+ }
+ if (time == timeout)
+ retval = -ETIMEDOUT;
+
+ release_firmware(fw);
+
+ return retval;
+}
+
+/* This function needs to initialize a "phy" of usb before */
+int xhci_rcar_init_quirk(struct usb_hcd *hcd)
+{
+ /* If hcd->regs is NULL, we don't just call the following function */
+ if (!hcd->regs)
+ return 0;
+
+ return xhci_rcar_download_firmware(hcd->self.controller, hcd->regs);
+}
diff --git a/drivers/usb/host/xhci-rcar.h b/drivers/usb/host/xhci-rcar.h
new file mode 100644
index 000000000000..58501256715d
--- /dev/null
+++ b/drivers/usb/host/xhci-rcar.h
@@ -0,0 +1,27 @@
+/*
+ * drivers/usb/host/xhci-rcar.h
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _XHCI_RCAR_H
+#define _XHCI_RCAR_H
+
+#if IS_ENABLED(CONFIG_USB_XHCI_RCAR)
+void xhci_rcar_start(struct usb_hcd *hcd);
+int xhci_rcar_init_quirk(struct usb_hcd *hcd);
+#else
+static inline void xhci_rcar_start(struct usb_hcd *hcd)
+{
+}
+
+static inline int xhci_rcar_init_quirk(struct usb_hcd *hcd)
+{
+ return 0;
+}
+#endif
+#endif /* _XHCI_RCAR_H */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 7436d5f5e67a..0342d9b63977 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1586,12 +1586,10 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx, *out_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
- struct xhci_slot_ctx *slot_ctx;
- unsigned int last_ctx;
unsigned int ep_index;
struct xhci_ep_ctx *ep_ctx;
u32 drop_flag;
- u32 new_add_flags, new_drop_flags, new_slot_info;
+ u32 new_add_flags, new_drop_flags;
int ret;
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
@@ -1638,24 +1636,13 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag);
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
- last_ctx = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags));
- slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
- /* Update the last valid endpoint context, if we deleted the last one */
- if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) >
- LAST_CTX(last_ctx)) {
- slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
- slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
- }
- new_slot_info = le32_to_cpu(slot_ctx->dev_info);
-
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
- xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
+ xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
udev->slot_id,
(unsigned int) new_drop_flags,
- (unsigned int) new_add_flags,
- (unsigned int) new_slot_info);
+ (unsigned int) new_add_flags);
return 0;
}
@@ -1678,11 +1665,9 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx, *out_ctx;
unsigned int ep_index;
- struct xhci_slot_ctx *slot_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
u32 added_ctxs;
- unsigned int last_ctx;
- u32 new_add_flags, new_drop_flags, new_slot_info;
+ u32 new_add_flags, new_drop_flags;
struct xhci_virt_device *virt_dev;
int ret = 0;
@@ -1697,7 +1682,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return -ENODEV;
added_ctxs = xhci_get_endpoint_flag(&ep->desc);
- last_ctx = xhci_last_valid_endpoint(added_ctxs);
if (added_ctxs == SLOT_FLAG || added_ctxs == EP0_FLAG) {
/* FIXME when we have to issue an evaluate endpoint command to
* deal with ep0 max packet size changing once we get the
@@ -1763,24 +1747,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
*/
new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
- slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
- /* Update the last valid endpoint context, if we just added one past */
- if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) <
- LAST_CTX(last_ctx)) {
- slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
- slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
- }
- new_slot_info = le32_to_cpu(slot_ctx->dev_info);
-
/* Store the usb_device pointer for later use */
ep->hcpriv = udev;
- xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
+ xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
udev->slot_id,
(unsigned int) new_drop_flags,
- (unsigned int) new_add_flags,
- (unsigned int) new_slot_info);
+ (unsigned int) new_add_flags);
return 0;
}
@@ -1830,15 +1804,15 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
ret = -ETIME;
break;
case COMP_ENOMEM:
- dev_warn(&udev->dev, "Not enough host controller resources "
- "for new device state.\n");
+ dev_warn(&udev->dev,
+ "Not enough host controller resources for new device state.\n");
ret = -ENOMEM;
/* FIXME: can we allocate more resources for the HC? */
break;
case COMP_BW_ERR:
case COMP_2ND_BW_ERR:
- dev_warn(&udev->dev, "Not enough bandwidth "
- "for new device state.\n");
+ dev_warn(&udev->dev,
+ "Not enough bandwidth for new device state.\n");
ret = -ENOSPC;
/* FIXME: can we go back to the old state? */
break;
@@ -1850,8 +1824,8 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
ret = -EINVAL;
break;
case COMP_DEV_ERR:
- dev_warn(&udev->dev, "ERROR: Incompatible device for endpoint "
- "configure command.\n");
+ dev_warn(&udev->dev,
+ "ERROR: Incompatible device for endpoint configure command.\n");
ret = -ENODEV;
break;
case COMP_SUCCESS:
@@ -1860,8 +1834,8 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
ret = 0;
break;
default:
- xhci_err(xhci, "ERROR: unexpected command completion "
- "code 0x%x.\n", *cmd_status);
+ xhci_err(xhci, "ERROR: unexpected command completion code 0x%x.\n",
+ *cmd_status);
ret = -EINVAL;
break;
}
@@ -1881,24 +1855,24 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
ret = -ETIME;
break;
case COMP_EINVAL:
- dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
- "context command.\n");
+ dev_warn(&udev->dev,
+ "WARN: xHCI driver setup invalid evaluate context command.\n");
ret = -EINVAL;
break;
case COMP_EBADSLT:
- dev_warn(&udev->dev, "WARN: slot not enabled for"
- "evaluate context command.\n");
+ dev_warn(&udev->dev,
+ "WARN: slot not enabled for evaluate context command.\n");
ret = -EINVAL;
break;
case COMP_CTX_STATE:
- dev_warn(&udev->dev, "WARN: invalid context state for "
- "evaluate context command.\n");
+ dev_warn(&udev->dev,
+ "WARN: invalid context state for evaluate context command.\n");
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
ret = -EINVAL;
break;
case COMP_DEV_ERR:
- dev_warn(&udev->dev, "ERROR: Incompatible device for evaluate "
- "context command.\n");
+ dev_warn(&udev->dev,
+ "ERROR: Incompatible device for evaluate context command.\n");
ret = -ENODEV;
break;
case COMP_MEL_ERR:
@@ -1912,8 +1886,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
ret = 0;
break;
default:
- xhci_err(xhci, "ERROR: unexpected command completion "
- "code 0x%x.\n", *cmd_status);
+ xhci_err(xhci, "ERROR: unexpected command completion code 0x%x.\n",
+ *cmd_status);
ret = -EINVAL;
break;
}
@@ -2750,8 +2724,19 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
ret = 0;
goto command_cleanup;
}
- xhci_dbg(xhci, "New Input Control Context:\n");
+ /* Fix up Context Entries field. Minimum value is EP0 == BIT(1). */
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+ for (i = 31; i >= 1; i--) {
+ __le32 le32 = cpu_to_le32(BIT(i));
+
+ if ((virt_dev->eps[i-1].ring && !(ctrl_ctx->drop_flags & le32))
+ || (ctrl_ctx->add_flags & le32) || i == 1) {
+ slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
+ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(i));
+ break;
+ }
+ }
+ xhci_dbg(xhci, "New Input Control Context:\n");
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
@@ -4303,8 +4288,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
return USB3_LPM_DISABLED;
}
-/* Returns the hub-encoded U1 timeout value.
- * The U1 timeout should be the maximum of the following values:
+/* The U1 timeout should be the maximum of the following values:
* - For control endpoints, U1 system exit latency (SEL) * 3
* - For bulk endpoints, U1 SEL * 5
* - For interrupt endpoints:
@@ -4312,7 +4296,8 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
* - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
* - For isochronous endpoints, max(105% of bInterval, U1 SEL * 2)
*/
-static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u1_timeout(
+ struct usb_device *udev,
struct usb_endpoint_descriptor *desc)
{
unsigned long long timeout_ns;
@@ -4344,11 +4329,28 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
return 0;
}
- /* The U1 timeout is encoded in 1us intervals. */
- timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
- /* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
+ return timeout_ns;
+}
+
+/* Returns the hub-encoded U1 timeout value. */
+static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc)
+{
+ unsigned long long timeout_ns;
+
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
+ else
+ timeout_ns = udev->u1_params.sel;
+
+ /* The U1 timeout is encoded in 1us intervals.
+ * Don't return a timeout of zero, because that's USB3_LPM_DISABLED.
+ */
if (timeout_ns == USB3_LPM_DISABLED)
- timeout_ns++;
+ timeout_ns = 1;
+ else
+ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
/* If the necessary timeout value is bigger than what we can set in the
* USB 3.0 hub, we have to disable hub-initiated U1.
@@ -4360,14 +4362,14 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1);
}
-/* Returns the hub-encoded U2 timeout value.
- * The U2 timeout should be the maximum of:
+/* The U2 timeout should be the maximum of:
* - 10 ms (to avoid the bandwidth impact on the scheduler)
* - largest bInterval of any active periodic endpoint (to avoid going
* into lower power link states between intervals).
* - the U2 Exit Latency of the device
*/
-static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u2_timeout(
+ struct usb_device *udev,
struct usb_endpoint_descriptor *desc)
{
unsigned long long timeout_ns;
@@ -4383,6 +4385,21 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
if (u2_del_ns > timeout_ns)
timeout_ns = u2_del_ns;
+ return timeout_ns;
+}
+
+/* Returns the hub-encoded U2 timeout value. */
+static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc)
+{
+ unsigned long long timeout_ns;
+
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
+ else
+ timeout_ns = udev->u2_params.sel;
+
/* The U2 timeout is encoded in 256us intervals */
timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
/* If the necessary timeout value is bigger than what we can set in the
@@ -4401,13 +4418,10 @@ static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
enum usb3_link_state state,
u16 *timeout)
{
- if (state == USB3_LPM_U1) {
- if (xhci->quirks & XHCI_INTEL_HOST)
- return xhci_calculate_intel_u1_timeout(udev, desc);
- } else {
- if (xhci->quirks & XHCI_INTEL_HOST)
- return xhci_calculate_intel_u2_timeout(udev, desc);
- }
+ if (state == USB3_LPM_U1)
+ return xhci_calculate_u1_timeout(xhci, udev, desc);
+ else if (state == USB3_LPM_U2)
+ return xhci_calculate_u2_timeout(xhci, udev, desc);
return USB3_LPM_DISABLED;
}
@@ -4484,7 +4498,8 @@ static int xhci_check_tier_policy(struct xhci_hcd *xhci,
{
if (xhci->quirks & XHCI_INTEL_HOST)
return xhci_check_intel_tier_policy(udev, state);
- return -EINVAL;
+ else
+ return 0;
}
/* Returns the U1 or U2 timeout that should be enabled.
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index f43c61989cef..47cb143716a1 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -149,8 +149,6 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
case USB3503_MODE_STANDBY:
usb3503_reset(hub, 0);
-
- hub->mode = mode;
dev_info(dev, "switched to STANDBY mode\n");
break;
@@ -192,7 +190,8 @@ static int usb3503_probe(struct usb3503 *hub)
clk = devm_clk_get(dev, "refclk");
if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
- dev_err(dev, "unable to request refclk (%d)\n", err);
+ dev_err(dev, "unable to request refclk (%ld)\n",
+ PTR_ERR(clk));
return PTR_ERR(clk);
}
@@ -346,6 +345,37 @@ static int usb3503_platform_probe(struct platform_device *pdev)
return usb3503_probe(hub);
}
+#ifdef CONFIG_PM_SLEEP
+static int usb3503_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct usb3503 *hub = i2c_get_clientdata(client);
+
+ usb3503_switch_mode(hub, USB3503_MODE_STANDBY);
+
+ if (hub->clk)
+ clk_disable_unprepare(hub->clk);
+
+ return 0;
+}
+
+static int usb3503_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct usb3503 *hub = i2c_get_clientdata(client);
+
+ if (hub->clk)
+ clk_prepare_enable(hub->clk);
+
+ usb3503_switch_mode(hub, hub->mode);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend,
+ usb3503_i2c_resume);
+
static const struct i2c_device_id usb3503_id[] = {
{ USB3503_I2C_NAME, 0 },
{ }
@@ -364,6 +394,7 @@ MODULE_DEVICE_TABLE(of, usb3503_of_match);
static struct i2c_driver usb3503_i2c_driver = {
.driver = {
.name = USB3503_I2C_NAME,
+ .pm = &usb3503_i2c_pm_ops,
.of_match_table = of_match_ptr(usb3503_of_match),
},
.probe = usb3503_i2c_probe,
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index bbe4f8e6e8d7..50dc69e1666f 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -33,7 +33,6 @@
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/usb/of.h>
-#include <asm/mach-types.h>
#include <linux/usb/ehci_def.h>
#include <linux/usb/tegra_usb_phy.h>
#include <linux/regulator/consumer.h>
@@ -686,10 +685,8 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
return gpio_direction_output(phy->reset_gpio, 0);
}
-static void tegra_usb_phy_close(struct usb_phy *x)
+static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
if (!IS_ERR(phy->vbus))
regulator_disable(phy->vbus);
@@ -1061,14 +1058,13 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
if (err < 0)
return err;
- tegra_phy->u_phy.shutdown = tegra_usb_phy_close;
tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
platform_set_drvdata(pdev, tegra_phy);
err = usb_add_phy_dev(&tegra_phy->u_phy);
if (err < 0) {
- tegra_usb_phy_close(&tegra_phy->u_phy);
+ tegra_usb_phy_close(tegra_phy);
return err;
}
@@ -1080,6 +1076,7 @@ static int tegra_usb_phy_remove(struct platform_device *pdev)
struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
usb_remove_phy(&tegra_phy->u_phy);
+ tegra_usb_phy_close(tegra_phy);
return 0;
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index d7440b7557af..e020ad28a00c 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -62,8 +62,6 @@ static void klsi_105_close(struct usb_serial_port *port);
static void klsi_105_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static int klsi_105_tiocmget(struct tty_struct *tty);
-static int klsi_105_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear);
static void klsi_105_process_read_urb(struct urb *urb);
static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
void *dest, size_t size);
@@ -93,7 +91,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
- .tiocmset = klsi_105_tiocmset,
.port_probe = klsi_105_port_probe,
.port_remove = klsi_105_port_remove,
.throttle = usb_serial_generic_throttle,
@@ -602,33 +599,6 @@ static int klsi_105_tiocmget(struct tty_struct *tty)
return (int)line_state;
}
-static int klsi_105_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- int retval = -EINVAL;
-
-/* if this ever gets implemented, it should be done something like this:
- struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- int control;
-
- spin_lock_irqsave (&priv->lock, flags);
- if (set & TIOCM_RTS)
- priv->control_state |= TIOCM_RTS;
- if (set & TIOCM_DTR)
- priv->control_state |= TIOCM_DTR;
- if (clear & TIOCM_RTS)
- priv->control_state &= ~TIOCM_RTS;
- if (clear & TIOCM_DTR)
- priv->control_state &= ~TIOCM_DTR;
- control = priv->control_state;
- spin_unlock_irqrestore (&priv->lock, flags);
- retval = mct_u232_set_modem_ctrl(serial, control);
-*/
- return retval;
-}
-
module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 393be562d875..3d88eefdf1d1 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1181,10 +1181,7 @@ static void mos7840_close(struct usb_serial_port *port)
/* Freeing Write URBs */
for (j = 0; j < NUM_URBS; ++j) {
if (mos7840_port->write_urb_pool[j]) {
- if (mos7840_port->write_urb_pool[j]->transfer_buffer)
- kfree(mos7840_port->write_urb_pool[j]->
- transfer_buffer);
-
+ kfree(mos7840_port->write_urb_pool[j]->transfer_buffer);
usb_free_urb(mos7840_port->write_urb_pool[j]);
}
}