From a265e5ef426ed224bfd2ee3d05535e6c573a16ba Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 16 Aug 2018 14:37:03 +0200 Subject: [PATCH 1/4] phy: Fix warning due to missing definition of structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this sort of warning if generic-phy.h is included: include/generic-phy.h:52:42: warning: ‘struct ofnode_phandle_args’ declared inside parameter list will not be visible outside of this definition or declaration int (*of_xlate)(struct phy *phy, struct ofnode_phandle_args *args); Signed-off-by: Marek Vasut --- include/generic-phy.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/generic-phy.h b/include/generic-phy.h index 3d26249..947c582 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -7,6 +7,7 @@ #ifndef __GENERIC_PHY_H #define __GENERIC_PHY_H +struct ofnode_phandle_args; /** * struct phy - A handle to (allowing control of) a single phy port. From b43cdf9b3fe246a8920d2b62ee41fc1722315ef0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 8 Aug 2018 14:29:55 +0200 Subject: [PATCH 2/4] usb: ehci: Make the PHY handling generic Pull out the EHCI PHY functions into the ehci-hcd.c to let other EHCI drivers use them. Signed-off-by: Marek Vasut --- drivers/usb/host/ehci-generic.c | 56 ++-------------------------------- drivers/usb/host/ehci-hcd.c | 66 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 5 ++++ 3 files changed, 74 insertions(+), 53 deletions(-) diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 5a56f66..cc2f338 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -26,56 +26,6 @@ struct generic_ehci { int reset_count; }; -static int ehci_setup_phy(struct udevice *dev, int index) -{ - struct generic_ehci *priv = dev_get_priv(dev); - int ret; - - ret = generic_phy_get_by_index(dev, index, &priv->phy); - if (ret) { - if (ret != -ENOENT) { - dev_err(dev, "failed to get usb phy\n"); - return ret; - } - } else { - ret = generic_phy_init(&priv->phy); - if (ret) { - dev_err(dev, "failed to init usb phy\n"); - return ret; - } - - ret = generic_phy_power_on(&priv->phy); - if (ret) { - dev_err(dev, "failed to power on usb phy\n"); - return generic_phy_exit(&priv->phy); - } - } - - return 0; -} - -static int ehci_shutdown_phy(struct udevice *dev) -{ - struct generic_ehci *priv = dev_get_priv(dev); - int ret = 0; - - if (generic_phy_valid(&priv->phy)) { - ret = generic_phy_power_off(&priv->phy); - if (ret) { - dev_err(dev, "failed to power off usb phy\n"); - return ret; - } - - ret = generic_phy_exit(&priv->phy); - if (ret) { - dev_err(dev, "failed to power off usb phy\n"); - return ret; - } - } - - return 0; -} - static int ehci_usb_probe(struct udevice *dev) { struct generic_ehci *priv = dev_get_priv(dev); @@ -145,7 +95,7 @@ static int ehci_usb_probe(struct udevice *dev) } } - err = ehci_setup_phy(dev, 0); + err = ehci_setup_phy(dev, &priv->phy, 0); if (err) goto reset_err; @@ -160,7 +110,7 @@ static int ehci_usb_probe(struct udevice *dev) return 0; phy_err: - ret = ehci_shutdown_phy(dev); + ret = ehci_shutdown_phy(dev, &priv->phy); if (ret) dev_err(dev, "failed to shutdown usb phy\n"); @@ -185,7 +135,7 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret; - ret = ehci_shutdown_phy(dev); + ret = ehci_shutdown_phy(dev, &priv->phy); if (ret) return ret; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 663f748..199b3a8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1675,3 +1675,69 @@ struct dm_usb_ops ehci_usb_ops = { }; #endif + +#ifdef CONFIG_PHY +int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index) +{ + int ret; + + if (!phy) + return 0; + + ret = generic_phy_get_by_index(dev, index, phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + } else { + ret = generic_phy_init(phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + + ret = generic_phy_power_on(phy); + if (ret) { + dev_err(dev, "failed to power on usb phy\n"); + return generic_phy_exit(phy); + } + } + + return 0; +} + +int ehci_shutdown_phy(struct udevice *dev, struct phy *phy) +{ + int ret = 0; + + if (!phy) + return 0; + + if (generic_phy_valid(phy)) { + ret = generic_phy_power_off(phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + + ret = generic_phy_exit(phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + } + + return 0; +} +#else +int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index) +{ + return 0; +} + +int ehci_shutdown_phy(struct udevice *dev, struct phy *phy) +{ + return 0; +} +#endif diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 07de472..7945016 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -9,6 +9,7 @@ #define USB_EHCI_H #include +#include /* Section 2.2.3 - N_PORTS */ #define MAX_HC_PORTS 15 @@ -288,4 +289,8 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr, int ehci_deregister(struct udevice *dev); extern struct dm_usb_ops ehci_usb_ops; +/* EHCI PHY functions */ +int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index); +int ehci_shutdown_phy(struct udevice *dev, struct phy *phy); + #endif /* USB_EHCI_H */ From 1335e7745f77f122cf4196b8da2aa2fc5edad475 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Aug 2018 12:27:10 +0200 Subject: [PATCH 3/4] usb: ehci: Add PHY support to ehci-pci Add support for operating a PHY attached to ehci-pci. There are systems where the EHCI controller is internally wired to a PCI bus and has a PHY connected to it as well, ie. the R-Car Gen2. Signed-off-by: Marek Vasut --- drivers/usb/host/ehci-pci.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a56e5bd..6150f3d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -16,17 +16,23 @@ /* Information about a USB port */ struct ehci_pci_priv { struct ehci_ctrl ehci; + struct phy phy; }; #ifdef CONFIG_DM_USB - -static void ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr, +static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) { + struct ehci_pci_priv *priv = dev_get_priv(dev); struct ehci_hccr *hccr; struct ehci_hcor *hcor; + int ret; u32 cmd; + ret = ehci_setup_phy(dev, &priv->phy, 0); + if (ret) + return ret; + hccr = (struct ehci_hccr *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hcor = (struct ehci_hcor *)((uintptr_t) hccr + @@ -43,6 +49,8 @@ static void ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr, dm_pci_read_config32(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MASTER; dm_pci_write_config32(dev, PCI_COMMAND, cmd); + + return 0; } #else @@ -120,12 +128,27 @@ static int ehci_pci_probe(struct udevice *dev) { struct ehci_hccr *hccr; struct ehci_hcor *hcor; + int ret; - ehci_pci_init(dev, &hccr, &hcor); + ret = ehci_pci_init(dev, &hccr, &hcor); + if (ret) + return ret; return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); } +static int ehci_pci_remove(struct udevice *dev) +{ + struct ehci_pci_priv *priv = dev_get_priv(dev); + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + return ehci_shutdown_phy(dev, &priv->phy); +} + static const struct udevice_id ehci_pci_ids[] = { { .compatible = "ehci-pci" }, { } @@ -135,7 +158,7 @@ U_BOOT_DRIVER(ehci_pci) = { .name = "ehci_pci", .id = UCLASS_USB, .probe = ehci_pci_probe, - .remove = ehci_deregister, + .remove = ehci_pci_remove, .of_match = ehci_pci_ids, .ops = &ehci_usb_ops, .platdata_auto_alloc_size = sizeof(struct usb_platdata), From 88c34b8da62cfb4188ff9a59acb32f88ce9ed1b0 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Wed, 29 Aug 2018 00:08:48 +0800 Subject: [PATCH 4/4] usb: dwc2: Add reset ctrl to driver Add code to reset all reset signals as in usb DT node. A reset property is an optional feature, so only print out a warning and do not fail if a reset property is not present. If a reset property is discovered, then use it to deassert, thus bringing the IP out of reset. Signed-off-by: Ley Foon Tan --- drivers/usb/host/dwc2.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index cbe065b..b6f008a 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "dwc2.h" @@ -49,6 +50,8 @@ struct dwc2_priv { */ bool hnp_srp_disable; bool oc_disable; + + struct reset_ctl_bulk resets; }; #ifndef CONFIG_DM_USB @@ -1124,11 +1127,43 @@ int _submit_int_msg(struct dwc2_priv *priv, struct usb_device *dev, } } +static int dwc2_reset(struct udevice *dev) +{ + int ret; + struct dwc2_priv *priv = dev_get_priv(dev); + + ret = reset_get_bulk(dev, &priv->resets); + if (ret) { + dev_warn(dev, "Can't get reset: %d\n", ret); + /* Return 0 if error due to !CONFIG_DM_RESET and reset + * DT property is not present. + */ + if (ret == -ENOENT || ret == -ENOTSUPP) + return 0; + else + return ret; + } + + ret = reset_deassert_bulk(&priv->resets); + if (ret) { + reset_release_bulk(&priv->resets); + dev_err(dev, "Failed to reset: %d\n", ret); + return ret; + } + + return 0; +} + static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) { struct dwc2_core_regs *regs = priv->regs; uint32_t snpsid; int i, j; + int ret; + + ret = dwc2_reset(dev); + if (ret) + return ret; snpsid = readl(®s->gsnpsid); dev_info(dev, "Core Release: %x.%03x\n", @@ -1303,6 +1338,8 @@ static int dwc2_usb_remove(struct udevice *dev) dwc2_uninit_common(priv->regs); + reset_release_bulk(&priv->resets); + return 0; }