diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/atm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/core/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 8 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 32 | ||||
-rw-r--r-- | drivers/usb/dwc2/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 5 | ||||
-rw-r--r-- | drivers/usb/host/ehci-exynos.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/ohci-exynos.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 156 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 8 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 9 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rza.h | 1 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rza2.c | 72 | ||||
-rw-r--r-- | drivers/usb/usbip/stub_main.c | 8 |
18 files changed, 227 insertions, 104 deletions
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig index 989aaa3b080d..3d958a1a1a71 100644 --- a/drivers/usb/atm/Kconfig +++ b/drivers/usb/atm/Kconfig @@ -7,7 +7,6 @@ menuconfig USB_ATM tristate "USB DSL modem support" depends on ATM select CRC32 - default n help Say Y here if you want to connect a USB Digital Subscriber Line (DSL) modem to your computer's USB port. You will then need to choose your diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index bdb6bd0b63a6..ecaacc8ed311 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -45,7 +45,6 @@ config USB_DYNAMIC_MINORS config USB_OTG bool "OTG support" depends on PM - default n help The most notable feature of USB OTG is support for a "Dual-Role" device, which can act as either a device diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fa783531ee88..aa17dab6c4ea 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2130,6 +2130,9 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) if (ps->privileges_dropped) return -EACCES; + if (!connected(ps)) + return -ENODEV; + /* alloc buffer */ size = _IOC_SIZE(ctl->ioctl_code); if (size > 0) { @@ -2146,11 +2149,6 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) } } - if (!connected(ps)) { - kfree(buf); - return -ENODEV; - } - if (ps->dev->state != USB_STATE_CONFIGURED) retval = -EHOSTUNREACH; else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2f94568ba385..572e8c26a129 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3999,6 +3999,9 @@ static int usb_set_lpm_timeout(struct usb_device *udev, * control transfers to set the hub timeout or enable device-initiated U1/U2 * will be successful. * + * If the control transfer to enable device-initiated U1/U2 entry fails, then + * hub-initiated U1/U2 will be disabled. + * * If we cannot set the parent hub U1/U2 timeout, we attempt to let the xHCI * driver know about it. If that call fails, it should be harmless, and just * take up more slightly more bus bandwidth for unnecessary U1/U2 exit latency. @@ -4053,23 +4056,24 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, * host know that this link state won't be enabled. */ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); - } else { - /* Only a configured device will accept the Set Feature - * U1/U2_ENABLE - */ - if (udev->actconfig) - usb_set_device_initiated_lpm(udev, state, true); + return; + } - /* As soon as usb_set_lpm_timeout(timeout) returns 0, the - * hub-initiated LPM is enabled. Thus, LPM is enabled no - * matter the result of usb_set_device_initiated_lpm(). - * The only difference is whether device is able to initiate - * LPM. - */ + /* Only a configured device will accept the Set Feature + * U1/U2_ENABLE + */ + if (udev->actconfig && + usb_set_device_initiated_lpm(udev, state, true) == 0) { if (state == USB3_LPM_U1) udev->usb3_lpm_u1_enabled = 1; else if (state == USB3_LPM_U2) udev->usb3_lpm_u2_enabled = 1; + } else { + /* Don't request U1/U2 entry if the device + * cannot transition to U1/U2. + */ + usb_set_lpm_timeout(udev, state, 0); + hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); } } @@ -4139,7 +4143,7 @@ int usb_disable_lpm(struct usb_device *udev) if (!udev || !udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || - udev->state < USB_STATE_DEFAULT) + udev->state < USB_STATE_CONFIGURED) return 0; hcd = bus_to_hcd(udev->bus); @@ -4198,7 +4202,7 @@ void usb_enable_lpm(struct usb_device *udev) if (!udev || !udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || - udev->state < USB_STATE_DEFAULT) + udev->state < USB_STATE_CONFIGURED) return; udev->lpm_disable_count--; diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index 68d095ae2865..16e1aa304edc 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -58,7 +58,6 @@ config USB_DWC2_PCI tristate "DWC2 PCI" depends on USB_PCI depends on USB_GADGET || !USB_GADGET - default n select NOP_USB_XCEIV help The Designware USB2.0 PCI interface module for controllers diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index d7c9e4fca895..94fc3c462930 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -153,7 +153,6 @@ config USB_ETH_EEM depends on USB_ETH select USB_LIBCOMPOSITE select USB_F_EEM - default n help CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM and therefore can be supported by more hardware. Technically ECM and @@ -419,7 +418,6 @@ config USB_G_MULTI_RNDIS config USB_G_MULTI_CDC bool "CDC Ethernet + CDC Serial + Storage configuration" depends on USB_G_MULTI - default n select USB_F_ECM help This option enables a configuration with CDC Ethernet (ECM), CDC diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d809671c5fea..fb3406ea8592 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -161,7 +161,6 @@ config USB_EHCI_PCI config USB_EHCI_HCD_PMC_MSP tristate "EHCI support for on-chip PMC MSP71xx USB controller" depends on MSP_HAS_USB - default n select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO ---help--- @@ -308,7 +307,6 @@ config USB_CNS3XXX_EHCI config USB_EHCI_HCD_PLATFORM tristate "Generic EHCI driver for a platform device" - default n ---help--- Adds an EHCI host driver for a generic platform device, which provides a memory space and an irq. @@ -318,7 +316,6 @@ config USB_EHCI_HCD_PLATFORM config USB_OCTEON_EHCI bool "Octeon on-chip EHCI support (DEPRECATED)" depends on CAVIUM_OCTEON_SOC - default n select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select USB_EHCI_HCD_PLATFORM help @@ -526,7 +523,6 @@ config USB_OHCI_HCD_SSB depends on (SSB = y || SSB = USB_OHCI_HCD) select USB_HCD_SSB select USB_OHCI_HCD_PLATFORM - default n ---help--- This option is deprecated now and the driver was removed, use USB_HCD_SSB and USB_OHCI_HCD_PLATFORM instead. @@ -569,7 +565,6 @@ config USB_CNS3XXX_OHCI config USB_OHCI_HCD_PLATFORM tristate "Generic OHCI driver for a platform device" - default n ---help--- Adds an OHCI host driver for a generic platform device, which provides a memory space and an irq. diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 8e3bab1e0c1f..3a29a1a8519c 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -39,6 +39,7 @@ static struct hc_driver __read_mostly exynos_ehci_hc_driver; struct exynos_ehci_hcd { struct clk *clk; + struct device_node *of_node; struct phy *phy[PHY_NUMBER]; }; @@ -203,6 +204,13 @@ static int exynos_ehci_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; + /* + * Workaround: reset of_node pointer to avoid conflict between Exynos + * EHCI port subnodes and generic USB device bindings + */ + exynos_ehci->of_node = pdev->dev.of_node; + pdev->dev.of_node = NULL; + /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); @@ -219,6 +227,7 @@ static int exynos_ehci_probe(struct platform_device *pdev) fail_add_hcd: exynos_ehci_phy_disable(&pdev->dev); + pdev->dev.of_node = exynos_ehci->of_node; fail_io: clk_disable_unprepare(exynos_ehci->clk); fail_clk: @@ -231,6 +240,8 @@ static int exynos_ehci_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); + pdev->dev.of_node = exynos_ehci->of_node; + usb_remove_hcd(hcd); exynos_ehci_phy_disable(&pdev->dev); diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index c0c4dcca6f3c..905c6317e0c3 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -30,6 +30,7 @@ static struct hc_driver __read_mostly exynos_ohci_hc_driver; struct exynos_ohci_hcd { struct clk *clk; + struct device_node *of_node; struct phy *phy[PHY_NUMBER]; }; @@ -170,6 +171,13 @@ static int exynos_ohci_probe(struct platform_device *pdev) goto fail_io; } + /* + * Workaround: reset of_node pointer to avoid conflict between Exynos + * OHCI port subnodes and generic USB device bindings + */ + exynos_ohci->of_node = pdev->dev.of_node; + pdev->dev.of_node = NULL; + err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); @@ -180,6 +188,7 @@ static int exynos_ohci_probe(struct platform_device *pdev) fail_add_hcd: exynos_ohci_phy_disable(&pdev->dev); + pdev->dev.of_node = exynos_ohci->of_node; fail_io: clk_disable_unprepare(exynos_ohci->clk); fail_clk: @@ -192,6 +201,8 @@ static int exynos_ohci_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); + pdev->dev.of_node = exynos_ohci->of_node; + usb_remove_hcd(hcd); exynos_ohci_phy_disable(&pdev->dev); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index fbcd34911025..a033f7d855e0 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -274,7 +274,7 @@ static const struct ohci_driver_overrides pci_overrides __initconst = { .reset = ohci_pci_reset, }; -static const struct pci_device_id pci_ids [] = { { +static const struct pci_device_id pci_ids[] = { { /* handle any USB OHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), .driver_data = (unsigned long) &ohci_pci_hc_driver, diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index 7fdbff23ae8b..d6b3fef3e55b 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig @@ -8,7 +8,6 @@ config USB_RENESAS_USBHS depends on USB_GADGET depends on ARCH_RENESAS || SUPERH || COMPILE_TEST depends on EXTCON || !EXTCON # if EXTCON=m, USBHS cannot be built-in - default n help Renesas USBHS is a discrete USB host and peripheral controller chip that supports both full and high speed USB 2.0 data transfers. diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile index 5c5b51bb48ef..a1fed56b0957 100644 --- a/drivers/usb/renesas_usbhs/Makefile +++ b/drivers/usb/renesas_usbhs/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o -renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o rcar3.o rza.o +renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o rcar3.o rza.o rza2.o ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),) renesas_usbhs-y += mod_host.o diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 249fbee97f3f..c7c9c5d75a56 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -43,15 +43,6 @@ * | .... | +-----------+ */ - -#define USBHSF_RUNTIME_PWCTRL (1 << 0) - -/* status */ -#define usbhsc_flags_init(p) do {(p)->flags = 0; } while (0) -#define usbhsc_flags_set(p, b) ((p)->flags |= (b)) -#define usbhsc_flags_clr(p, b) ((p)->flags &= ~(b)) -#define usbhsc_flags_has(p, b) ((p)->flags & (b)) - /* * platform call back * @@ -123,6 +114,12 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable) u16 mask = DCFM | DRPD | DPRPU | HSE | USBE; u16 val = HSE | USBE; + /* CNEN bit is required for function operation */ + if (usbhs_get_dparam(priv, has_cnen)) { + mask |= CNEN; + val |= CNEN; + } + /* * if enable * @@ -479,7 +476,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) dev_dbg(&pdev->dev, "%s enable\n", __func__); /* power on */ - if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, enable); /* bus init */ @@ -499,7 +496,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) usbhsc_bus_init(priv); /* power off */ - if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, enable); usbhs_mod_change(priv, -1); @@ -535,53 +532,107 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) return 0; } +static const struct usbhs_of_data rcar_gen2_data = { + .platform_callback = &usbhs_rcar2_ops, + .param = { + .type = USBHS_TYPE_RCAR_GEN2, + .has_usb_dmac = 1, + .pipe_configs = usbhsc_new_pipe, + .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), + } +}; + +static const struct usbhs_of_data rcar_gen3_data = { + .platform_callback = &usbhs_rcar3_ops, + .param = { + .type = USBHS_TYPE_RCAR_GEN3, + .has_usb_dmac = 1, + .pipe_configs = usbhsc_new_pipe, + .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), + } +}; + +static const struct usbhs_of_data rcar_gen3_with_pll_data = { + .platform_callback = &usbhs_rcar3_with_pll_ops, + .param = { + .type = USBHS_TYPE_RCAR_GEN3_WITH_PLL, + .has_usb_dmac = 1, + .pipe_configs = usbhsc_new_pipe, + .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), + } +}; + +static const struct usbhs_of_data rza1_data = { + .platform_callback = &usbhs_rza1_ops, + .param = { + .type = USBHS_TYPE_RZA1, + .pipe_configs = usbhsc_new_pipe, + .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), + } +}; + +static const struct usbhs_of_data rza2_data = { + .platform_callback = &usbhs_rza2_ops, + .param = { + .type = USBHS_TYPE_RZA2, + .has_cnen = 1, + .cfifo_byte_addr = 1, + .pipe_configs = usbhsc_new_pipe, + .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), + } +}; + /* * platform functions */ static const struct of_device_id usbhs_of_match[] = { { .compatible = "renesas,usbhs-r8a774c0", - .data = (void *)USBHS_TYPE_RCAR_GEN3_WITH_PLL, + .data = &rcar_gen3_with_pll_data, }, { .compatible = "renesas,usbhs-r8a7790", - .data = (void *)USBHS_TYPE_RCAR_GEN2, + .data = &rcar_gen2_data, }, { .compatible = "renesas,usbhs-r8a7791", - .data = (void *)USBHS_TYPE_RCAR_GEN2, + .data = &rcar_gen2_data, }, { .compatible = "renesas,usbhs-r8a7794", - .data = (void *)USBHS_TYPE_RCAR_GEN2, + .data = &rcar_gen2_data, }, { .compatible = "renesas,usbhs-r8a7795", - .data = (void *)USBHS_TYPE_RCAR_GEN3, + .data = &rcar_gen3_data, }, { .compatible = "renesas,usbhs-r8a7796", - .data = (void *)USBHS_TYPE_RCAR_GEN3, + .data = &rcar_gen3_data, }, { .compatible = "renesas,usbhs-r8a77990", - .data = (void *)USBHS_TYPE_RCAR_GEN3_WITH_PLL, + .data = &rcar_gen3_with_pll_data, }, { .compatible = "renesas,usbhs-r8a77995", - .data = (void *)USBHS_TYPE_RCAR_GEN3_WITH_PLL, + .data = &rcar_gen3_with_pll_data, }, { .compatible = "renesas,rcar-gen2-usbhs", - .data = (void *)USBHS_TYPE_RCAR_GEN2, + .data = &rcar_gen2_data, }, { .compatible = "renesas,rcar-gen3-usbhs", - .data = (void *)USBHS_TYPE_RCAR_GEN3, + .data = &rcar_gen3_data, }, { .compatible = "renesas,rza1-usbhs", - .data = (void *)USBHS_TYPE_RZA1, + .data = &rza1_data, + }, + { + .compatible = "renesas,rza2-usbhs", + .data = &rza2_data, }, { }, }; @@ -591,6 +642,7 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev) { struct renesas_usbhs_platform_info *info; struct renesas_usbhs_driver_param *dparam; + const struct usbhs_of_data *data; u32 tmp; int gpio; @@ -598,8 +650,15 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev) if (!info) return NULL; + data = of_device_get_match_data(dev); + if (!data) + return NULL; + dparam = &info->driver_param; - dparam->type = (uintptr_t)of_device_get_match_data(dev); + memcpy(dparam, &data->param, sizeof(data->param)); + memcpy(&info->platform_callback, data->platform_callback, + sizeof(*data->platform_callback)); + if (!of_property_read_u32(dev->of_node, "renesas,buswait", &tmp)) dparam->buswait_bwait = tmp; gpio = of_get_named_gpio_flags(dev->of_node, "renesas,enable-gpio", 0, @@ -607,19 +666,6 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev) if (gpio > 0) dparam->enable_gpio = gpio; - if (dparam->type == USBHS_TYPE_RCAR_GEN2 || - dparam->type == USBHS_TYPE_RCAR_GEN3 || - dparam->type == USBHS_TYPE_RCAR_GEN3_WITH_PLL) { - dparam->has_usb_dmac = 1; - dparam->pipe_configs = usbhsc_new_pipe; - dparam->pipe_size = ARRAY_SIZE(usbhsc_new_pipe); - } - - if (dparam->type == USBHS_TYPE_RZA1) { - dparam->pipe_configs = usbhsc_new_pipe; - dparam->pipe_size = ARRAY_SIZE(usbhsc_new_pipe); - } - return info; } @@ -676,29 +722,13 @@ static int usbhs_probe(struct platform_device *pdev) &info->driver_param, sizeof(struct renesas_usbhs_driver_param)); - switch (priv->dparam.type) { - case USBHS_TYPE_RCAR_GEN2: - priv->pfunc = usbhs_rcar2_ops; - break; - case USBHS_TYPE_RCAR_GEN3: - priv->pfunc = usbhs_rcar3_ops; - break; - case USBHS_TYPE_RCAR_GEN3_WITH_PLL: - priv->pfunc = usbhs_rcar3_with_pll_ops; - break; - case USBHS_TYPE_RZA1: - priv->pfunc = usbhs_rza1_ops; - break; - default: - if (!info->platform_callback.get_id) { - dev_err(&pdev->dev, "no platform callbacks"); - return -EINVAL; - } - memcpy(&priv->pfunc, - &info->platform_callback, - sizeof(struct renesas_usbhs_platform_callback)); - break; + if (!info->platform_callback.get_id) { + dev_err(&pdev->dev, "no platform callbacks"); + return -EINVAL; } + memcpy(&priv->pfunc, + &info->platform_callback, + sizeof(struct renesas_usbhs_platform_callback)); /* set driver callback functions for platform */ dfunc = &info->driver_callback; @@ -715,7 +745,7 @@ static int usbhs_probe(struct platform_device *pdev) /* FIXME */ /* runtime power control ? */ if (priv->pfunc.get_vbus) - usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL); + usbhs_get_dparam(priv, runtime_pwctrl) = 1; /* * priv settings @@ -789,7 +819,7 @@ static int usbhs_probe(struct platform_device *pdev) /* power control */ pm_runtime_enable(&pdev->dev); - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { + if (!usbhs_get_dparam(priv, runtime_pwctrl)) { usbhsc_power_ctrl(priv, 1); usbhs_mod_autonomy_mode(priv); } @@ -830,7 +860,7 @@ static int usbhs_remove(struct platform_device *pdev) dfunc->notify_hotplug = NULL; /* power off */ - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (!usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, 0); pm_runtime_disable(&pdev->dev); @@ -855,7 +885,7 @@ static __maybe_unused int usbhsc_suspend(struct device *dev) usbhs_mod_change(priv, -1); } - if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (mod || !usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, 0); return 0; @@ -866,7 +896,7 @@ static __maybe_unused int usbhsc_resume(struct device *dev) struct usbhs_priv *priv = dev_get_drvdata(dev); struct platform_device *pdev = usbhs_priv_to_pdev(priv); - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { + if (!usbhs_get_dparam(priv, runtime_pwctrl)) { usbhsc_power_ctrl(priv, 1); usbhs_mod_autonomy_mode(priv); } diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index 3777af848a35..de74ebd1a347 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -104,6 +104,7 @@ struct usbhs_priv; /* SYSCFG */ #define SCKE (1 << 10) /* USB Module Clock Enable */ +#define CNEN (1 << 8) /* Single-ended receiver operation Enable */ #define HSE (1 << 7) /* High-Speed Operation Enable */ #define DCFM (1 << 6) /* Controller Function Select */ #define DRPD (1 << 5) /* D+ Line/D- Line Resistance Control */ @@ -260,8 +261,6 @@ struct usbhs_priv { spinlock_t lock; - u32 flags; - /* * module control */ @@ -282,6 +281,11 @@ struct usbhs_priv { struct clk *clks[2]; }; +struct usbhs_of_data { + const struct renesas_usbhs_platform_callback *platform_callback; + const struct renesas_usbhs_driver_param param; +}; + /* * common */ diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 39fa2fc1b8b7..452b456ac24e 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -543,8 +543,13 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) } /* the rest operation */ - for (i = 0; i < len; i++) - iowrite8(buf[i], addr + (0x03 - (i & 0x03))); + if (usbhs_get_dparam(priv, cfifo_byte_addr)) { + for (i = 0; i < len; i++) + iowrite8(buf[i], addr + (i & 0x03)); + } else { + for (i = 0; i < len; i++) + iowrite8(buf[i], addr + (0x03 - (i & 0x03))); + } /* * variable update diff --git a/drivers/usb/renesas_usbhs/rza.h b/drivers/usb/renesas_usbhs/rza.h index ca917ca54f6d..073a53d1d442 100644 --- a/drivers/usb/renesas_usbhs/rza.h +++ b/drivers/usb/renesas_usbhs/rza.h @@ -2,3 +2,4 @@ #include "common.h" extern const struct renesas_usbhs_platform_callback usbhs_rza1_ops; +extern const struct renesas_usbhs_platform_callback usbhs_rza2_ops; diff --git a/drivers/usb/renesas_usbhs/rza2.c b/drivers/usb/renesas_usbhs/rza2.c new file mode 100644 index 000000000000..9d8551f93533 --- /dev/null +++ b/drivers/usb/renesas_usbhs/rza2.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas USB driver RZ/A2 initialization and power control + * + * Copyright (C) 2019 Chris Brandt + * Copyright (C) 2019 Renesas Electronics Corporation + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/of_device.h> +#include <linux/phy/phy.h> +#include "common.h" +#include "rza.h" + +static int usbhs_rza2_hardware_init(struct platform_device *pdev) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + struct phy *phy = phy_get(&pdev->dev, "usb"); + + if (IS_ERR(phy)) + return PTR_ERR(phy); + + priv->phy = phy; + return 0; +} + +static int usbhs_rza2_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + + phy_put(priv->phy); + priv->phy = NULL; + + return 0; +} + +static int usbhs_rza2_power_ctrl(struct platform_device *pdev, + void __iomem *base, int enable) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + int retval = 0; + + if (!priv->phy) + return -ENODEV; + + if (enable) { + retval = phy_init(priv->phy); + usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); + udelay(100); /* Wait for PLL to become stable */ + if (!retval) + retval = phy_power_on(priv->phy); + } else { + usbhs_bset(priv, SUSPMODE, SUSPM, 0); + phy_power_off(priv->phy); + phy_exit(priv->phy); + } + + return retval; +} + +static int usbhs_rza2_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +const struct renesas_usbhs_platform_callback usbhs_rza2_ops = { + .hardware_init = usbhs_rza2_hardware_init, + .hardware_exit = usbhs_rza2_hardware_exit, + .power_ctrl = usbhs_rza2_power_ctrl, + .get_id = usbhs_rza2_get_id, +}; diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index bf8a5feb0ee9..2e4bfccd4bfc 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -201,7 +201,7 @@ static DRIVER_ATTR_RW(match_busid); static int do_rebind(char *busid, struct bus_id_priv *busid_priv) { - int ret; + int ret = 0; /* device_attach() callers should hold parent lock for USB */ if (busid_priv->udev->dev.parent) @@ -209,11 +209,9 @@ static int do_rebind(char *busid, struct bus_id_priv *busid_priv) ret = device_attach(&busid_priv->udev->dev); if (busid_priv->udev->dev.parent) device_unlock(busid_priv->udev->dev.parent); - if (ret < 0) { + if (ret < 0) dev_err(&busid_priv->udev->dev, "rebind failed\n"); - return ret; - } - return 0; + return ret; } static void stub_device_rebind(void) |