* [U-Boot] [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs @ 2018-04-11 15:07 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:07 UTC (permalink / raw) To: u-boot This patchset adds support for USB for the Amlogic Meson GXL SoCs following the work done for Linux by Martin Blumenstingl at [1] [2] [3]. The support consist of : - A port of dwc3-of-simple from Linux to U-boot - A change to support more than 2 PHYs in the DWC3 DM driver - An USB2 PHY Driver and an USB3 PHY Driver The DWC3 Controller has up to 4 PHYs connected : - 2 USB2 PHYs and an USB3 PHY for GXL SoCs - 3 USB2 PHYs and an USB3 PHY for the GXM SoC Variant This is enabled by the "usb: host: dwc3: Add support for multiple PHYs" patch. This patch is based on the "xhci-dwc3: Couple of fixes for USB3 support" serie from Vignesh R, on the u-boot-usb tree. The DWC3 Controller glue is generic enough to use the dwc3-of-simple from Linux and can be easily ported to U-Boot as a Simple-Bus with Glue-Specific clocks and Reset lines setup. This depends on the recently applied : - clk: Add get/enable/disable/release for a bulk of clocks at [4] - reset: Add get/assert/deassert/release for bulk of reset signals at [5] in order to manage the clocks and resets of the Glue in a clean fashion. The USB PHY driver supports the standard generic PHY interface and supports the power-on/off calls and set the Host mode by default. They are based on the excellent work from Martin Blumenstingl merged in linux. Changes since v2: - Drop #if and use the empty stubs for clock & reset API Changes since v1: - switch to submitted clk/reset bulk API - splitted dwc3 multiple phy init error between poweroff & exit [1] https://lkml.kernel.org/r/20180303184700.21480-1-martin.blumenstingl at googlemail.com [2] https://lkml.kernel.org/r/20180128202245.25021-1-martin.blumenstingl at googlemail.com [3] https://lkml.kernel.org/r/20180303214309.25643-1-martin.blumenstingl at googlemail.com [4] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/006952.html [5] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/006949.html Neil Armstrong (3): usb: host: Add simple of glue driver for DWC3 USB Controllers integration usb: host: dwc3: Add support for multiple PHYs phy: Add Amlogic Meson USB2 & USB3 Generic PHY drivers drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/meson-gxl-usb2.c | 238 ++++++++++++++++++++++++++++++++++++++ drivers/phy/meson-gxl-usb3.c | 201 ++++++++++++++++++++++++++++++++ drivers/usb/host/Kconfig | 7 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/dwc3-of-simple.c | 109 +++++++++++++++++ drivers/usb/host/xhci-dwc3.c | 113 ++++++++++-------- 8 files changed, 631 insertions(+), 47 deletions(-) create mode 100644 drivers/phy/meson-gxl-usb2.c create mode 100644 drivers/phy/meson-gxl-usb3.c create mode 100644 drivers/usb/host/dwc3-of-simple.c -- 2.7.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs @ 2018-04-11 15:07 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:07 UTC (permalink / raw) To: linus-amlogic This patchset adds support for USB for the Amlogic Meson GXL SoCs following the work done for Linux by Martin Blumenstingl at [1] [2] [3]. The support consist of : - A port of dwc3-of-simple from Linux to U-boot - A change to support more than 2 PHYs in the DWC3 DM driver - An USB2 PHY Driver and an USB3 PHY Driver The DWC3 Controller has up to 4 PHYs connected : - 2 USB2 PHYs and an USB3 PHY for GXL SoCs - 3 USB2 PHYs and an USB3 PHY for the GXM SoC Variant This is enabled by the "usb: host: dwc3: Add support for multiple PHYs" patch. This patch is based on the "xhci-dwc3: Couple of fixes for USB3 support" serie from Vignesh R, on the u-boot-usb tree. The DWC3 Controller glue is generic enough to use the dwc3-of-simple from Linux and can be easily ported to U-Boot as a Simple-Bus with Glue-Specific clocks and Reset lines setup. This depends on the recently applied : - clk: Add get/enable/disable/release for a bulk of clocks at [4] - reset: Add get/assert/deassert/release for bulk of reset signals at [5] in order to manage the clocks and resets of the Glue in a clean fashion. The USB PHY driver supports the standard generic PHY interface and supports the power-on/off calls and set the Host mode by default. They are based on the excellent work from Martin Blumenstingl merged in linux. Changes since v2: - Drop #if and use the empty stubs for clock & reset API Changes since v1: - switch to submitted clk/reset bulk API - splitted dwc3 multiple phy init error between poweroff & exit [1] https://lkml.kernel.org/r/20180303184700.21480-1-martin.blumenstingl at googlemail.com [2] https://lkml.kernel.org/r/20180128202245.25021-1-martin.blumenstingl at googlemail.com [3] https://lkml.kernel.org/r/20180303214309.25643-1-martin.blumenstingl at googlemail.com [4] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/006952.html [5] http://lists.infradead.org/pipermail/linux-amlogic/2018-April/006949.html Neil Armstrong (3): usb: host: Add simple of glue driver for DWC3 USB Controllers integration usb: host: dwc3: Add support for multiple PHYs phy: Add Amlogic Meson USB2 & USB3 Generic PHY drivers drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/meson-gxl-usb2.c | 238 ++++++++++++++++++++++++++++++++++++++ drivers/phy/meson-gxl-usb3.c | 201 ++++++++++++++++++++++++++++++++ drivers/usb/host/Kconfig | 7 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/dwc3-of-simple.c | 109 +++++++++++++++++ drivers/usb/host/xhci-dwc3.c | 113 ++++++++++-------- 8 files changed, 631 insertions(+), 47 deletions(-) create mode 100644 drivers/phy/meson-gxl-usb2.c create mode 100644 drivers/phy/meson-gxl-usb3.c create mode 100644 drivers/usb/host/dwc3-of-simple.c -- 2.7.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration 2018-04-11 15:07 ` Neil Armstrong @ 2018-04-11 15:08 ` Neil Armstrong -1 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: u-boot This is a port of the dwc3-of-simple driver from Linux to enable/deassert clock and resets of a simple DWC3 Controller HW glue. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/usb/host/Kconfig | 7 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 drivers/usb/host/dwc3-of-simple.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a7249b7..6caa615 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 Say Y or if your system has a Dual Role SuperSpeed USB controller based on the DesignWare USB3 IP Core. +config USB_XHCI_DWC3_OF_SIMPLE + bool "DesignWare USB3 DRD Generic OF Simple Glue Layer" + select MISC + help + Support USB2/3 functionality in simple SoC integrations with + USB controller based on the DesignWare USB3 IP Core. + config USB_XHCI_MVEBU bool "MVEBU USB 3.0 support" default y diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 9819489..abe4f90 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o # xhci obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o +obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o diff --git a/drivers/usb/host/dwc3-of-simple.c b/drivers/usb/host/dwc3-of-simple.c new file mode 100644 index 0000000..54a5f60 --- /dev/null +++ b/drivers/usb/host/dwc3-of-simple.c @@ -0,0 +1,109 @@ +/* + * dwc3-of-simple.c - OF glue layer for simple integrations + * + * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi <balbi@ti.com> + * + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <reset.h> +#include <clk.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct dwc3_of_simple { + struct clk_bulk clks; + struct reset_ctl_bulk resets; +}; + +static int dwc3_of_simple_reset_init(struct udevice *dev, + struct dwc3_of_simple *simple) +{ + int ret; + + ret = reset_get_bulk(dev, &simple->resets); + if (ret == -ENOTSUPP) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(&simple->resets); + if (ret) { + reset_release_bulk(&simple->resets); + return ret; + } + + return 0; +} + +static int dwc3_of_simple_clk_init(struct udevice *dev, + struct dwc3_of_simple *simple) +{ + int ret; + + ret = clk_get_bulk(dev, &simple->clks); + if (ret == -ENOTSUPP) + return 0; + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_enable_bulk(&simple->clks); + if (ret) { + clk_release_bulk(&simple->clks); + return ret; + } +#endif + + return 0; +} + +static int dwc3_of_simple_probe(struct udevice *dev) +{ + struct dwc3_of_simple *simple = dev_get_platdata(dev); + int ret; + + ret = dwc3_of_simple_clk_init(dev, simple); + if (ret) + return ret; + + ret = dwc3_of_simple_reset_init(dev, simple); + if (ret) + return ret; + + return 0; +} + +static int dwc3_of_simple_remove(struct udevice *dev) +{ + struct dwc3_of_simple *simple = dev_get_platdata(dev); + + reset_release_bulk(&simple->resets); + + clk_release_bulk(&simple->clks); + + return dm_scan_fdt_dev(dev); +} + +static const struct udevice_id dwc3_of_simple_ids[] = { + { .compatible = "amlogic,meson-gxl-dwc3" }, + { } +}; + +U_BOOT_DRIVER(dwc3_of_simple) = { + .name = "dwc3-of-simple", + .id = UCLASS_SIMPLE_BUS, + .of_match = dwc3_of_simple_ids, + .probe = dwc3_of_simple_probe, + .remove = dwc3_of_simple_remove, + .platdata_auto_alloc_size = sizeof(struct dwc3_of_simple), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration @ 2018-04-11 15:08 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: linus-amlogic This is a port of the dwc3-of-simple driver from Linux to enable/deassert clock and resets of a simple DWC3 Controller HW glue. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/usb/host/Kconfig | 7 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 drivers/usb/host/dwc3-of-simple.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a7249b7..6caa615 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 Say Y or if your system has a Dual Role SuperSpeed USB controller based on the DesignWare USB3 IP Core. +config USB_XHCI_DWC3_OF_SIMPLE + bool "DesignWare USB3 DRD Generic OF Simple Glue Layer" + select MISC + help + Support USB2/3 functionality in simple SoC integrations with + USB controller based on the DesignWare USB3 IP Core. + config USB_XHCI_MVEBU bool "MVEBU USB 3.0 support" default y diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 9819489..abe4f90 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o # xhci obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o +obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o diff --git a/drivers/usb/host/dwc3-of-simple.c b/drivers/usb/host/dwc3-of-simple.c new file mode 100644 index 0000000..54a5f60 --- /dev/null +++ b/drivers/usb/host/dwc3-of-simple.c @@ -0,0 +1,109 @@ +/* + * dwc3-of-simple.c - OF glue layer for simple integrations + * + * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi <balbi@ti.com> + * + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <reset.h> +#include <clk.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct dwc3_of_simple { + struct clk_bulk clks; + struct reset_ctl_bulk resets; +}; + +static int dwc3_of_simple_reset_init(struct udevice *dev, + struct dwc3_of_simple *simple) +{ + int ret; + + ret = reset_get_bulk(dev, &simple->resets); + if (ret == -ENOTSUPP) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(&simple->resets); + if (ret) { + reset_release_bulk(&simple->resets); + return ret; + } + + return 0; +} + +static int dwc3_of_simple_clk_init(struct udevice *dev, + struct dwc3_of_simple *simple) +{ + int ret; + + ret = clk_get_bulk(dev, &simple->clks); + if (ret == -ENOTSUPP) + return 0; + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_enable_bulk(&simple->clks); + if (ret) { + clk_release_bulk(&simple->clks); + return ret; + } +#endif + + return 0; +} + +static int dwc3_of_simple_probe(struct udevice *dev) +{ + struct dwc3_of_simple *simple = dev_get_platdata(dev); + int ret; + + ret = dwc3_of_simple_clk_init(dev, simple); + if (ret) + return ret; + + ret = dwc3_of_simple_reset_init(dev, simple); + if (ret) + return ret; + + return 0; +} + +static int dwc3_of_simple_remove(struct udevice *dev) +{ + struct dwc3_of_simple *simple = dev_get_platdata(dev); + + reset_release_bulk(&simple->resets); + + clk_release_bulk(&simple->clks); + + return dm_scan_fdt_dev(dev); +} + +static const struct udevice_id dwc3_of_simple_ids[] = { + { .compatible = "amlogic,meson-gxl-dwc3" }, + { } +}; + +U_BOOT_DRIVER(dwc3_of_simple) = { + .name = "dwc3-of-simple", + .id = UCLASS_SIMPLE_BUS, + .of_match = dwc3_of_simple_ids, + .probe = dwc3_of_simple_probe, + .remove = dwc3_of_simple_remove, + .platdata_auto_alloc_size = sizeof(struct dwc3_of_simple), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration 2018-04-11 15:08 ` Neil Armstrong @ 2018-04-11 16:17 ` Jean-Jacques Hiblot -1 siblings, 0 replies; 18+ messages in thread From: Jean-Jacques Hiblot @ 2018-04-11 16:17 UTC (permalink / raw) To: u-boot On 11/04/2018 17:08, Neil Armstrong wrote: > This is a port of the dwc3-of-simple driver from Linux to enable/deassert > clock and resets of a simple DWC3 Controller HW glue. > > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> > --- > drivers/usb/host/Kconfig | 7 +++ > drivers/usb/host/Makefile | 1 + > drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 117 insertions(+) > create mode 100644 drivers/usb/host/dwc3-of-simple.c > > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index a7249b7..6caa615 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 > Say Y or if your system has a Dual Role SuperSpeed > USB controller based on the DesignWare USB3 IP Core. > > +config USB_XHCI_DWC3_OF_SIMPLE > + bool "DesignWare USB3 DRD Generic OF Simple Glue Layer" > + select MISC > + help > + Support USB2/3 functionality in simple SoC integrations with > + USB controller based on the DesignWare USB3 IP Core. > + > config USB_XHCI_MVEBU > bool "MVEBU USB 3.0 support" > default y > diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile > index 9819489..abe4f90 100644 > --- a/drivers/usb/host/Makefile > +++ b/drivers/usb/host/Makefile > @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o > # xhci > obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o > obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o > +obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o > obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o > obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o > obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o > diff --git a/drivers/usb/host/dwc3-of-simple.c b/drivers/usb/host/dwc3-of-simple.c > new file mode 100644 > index 0000000..54a5f60 > --- /dev/null > +++ b/drivers/usb/host/dwc3-of-simple.c > @@ -0,0 +1,109 @@ > +/* > + * dwc3-of-simple.c - OF glue layer for simple integrations > + * > + * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com > + * > + * Author: Felipe Balbi <balbi@ti.com> > + * > + * Copyright (C) 2018 BayLibre, SAS > + * Author: Neil Armstrong <narmstron@baylibre.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <fdtdec.h> > +#include <reset.h> > +#include <clk.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct dwc3_of_simple { > + struct clk_bulk clks; > + struct reset_ctl_bulk resets; > +}; > + > +static int dwc3_of_simple_reset_init(struct udevice *dev, > + struct dwc3_of_simple *simple) > +{ > + int ret; > + > + ret = reset_get_bulk(dev, &simple->resets); > + if (ret == -ENOTSUPP) > + return 0; > + else if (ret) > + return ret; > + > + ret = reset_deassert_bulk(&simple->resets); > + if (ret) { > + reset_release_bulk(&simple->resets); > + return ret; > + } > + > + return 0; > +} > + > +static int dwc3_of_simple_clk_init(struct udevice *dev, > + struct dwc3_of_simple *simple) > +{ > + int ret; > + > + ret = clk_get_bulk(dev, &simple->clks); > + if (ret == -ENOTSUPP) Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> > + return 0; > + if (ret) > + return ret; > + > +#if CONFIG_IS_ENABLED(CLK) > + ret = clk_enable_bulk(&simple->clks); > + if (ret) { > + clk_release_bulk(&simple->clks); > + return ret; > + } > +#endif > + > + return 0; > +} > + > +static int dwc3_of_simple_probe(struct udevice *dev) > +{ > + struct dwc3_of_simple *simple = dev_get_platdata(dev); > + int ret; > + > + ret = dwc3_of_simple_clk_init(dev, simple); > + if (ret) > + return ret; > + > + ret = dwc3_of_simple_reset_init(dev, simple); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int dwc3_of_simple_remove(struct udevice *dev) > +{ > + struct dwc3_of_simple *simple = dev_get_platdata(dev); > + > + reset_release_bulk(&simple->resets); > + > + clk_release_bulk(&simple->clks); > + > + return dm_scan_fdt_dev(dev); > +} > + > +static const struct udevice_id dwc3_of_simple_ids[] = { > + { .compatible = "amlogic,meson-gxl-dwc3" }, > + { } > +}; > + > +U_BOOT_DRIVER(dwc3_of_simple) = { > + .name = "dwc3-of-simple", > + .id = UCLASS_SIMPLE_BUS, > + .of_match = dwc3_of_simple_ids, > + .probe = dwc3_of_simple_probe, > + .remove = dwc3_of_simple_remove, > + .platdata_auto_alloc_size = sizeof(struct dwc3_of_simple), > + .flags = DM_FLAG_ALLOC_PRIV_DMA, > +}; ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration @ 2018-04-11 16:17 ` Jean-Jacques Hiblot 0 siblings, 0 replies; 18+ messages in thread From: Jean-Jacques Hiblot @ 2018-04-11 16:17 UTC (permalink / raw) To: linus-amlogic On 11/04/2018 17:08, Neil Armstrong wrote: > This is a port of the dwc3-of-simple driver from Linux to enable/deassert > clock and resets of a simple DWC3 Controller HW glue. > > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> > --- > drivers/usb/host/Kconfig | 7 +++ > drivers/usb/host/Makefile | 1 + > drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 117 insertions(+) > create mode 100644 drivers/usb/host/dwc3-of-simple.c > > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index a7249b7..6caa615 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 > Say Y or if your system has a Dual Role SuperSpeed > USB controller based on the DesignWare USB3 IP Core. > > +config USB_XHCI_DWC3_OF_SIMPLE > + bool "DesignWare USB3 DRD Generic OF Simple Glue Layer" > + select MISC > + help > + Support USB2/3 functionality in simple SoC integrations with > + USB controller based on the DesignWare USB3 IP Core. > + > config USB_XHCI_MVEBU > bool "MVEBU USB 3.0 support" > default y > diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile > index 9819489..abe4f90 100644 > --- a/drivers/usb/host/Makefile > +++ b/drivers/usb/host/Makefile > @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o > # xhci > obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o > obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o > +obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o > obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o > obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o > obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o > diff --git a/drivers/usb/host/dwc3-of-simple.c b/drivers/usb/host/dwc3-of-simple.c > new file mode 100644 > index 0000000..54a5f60 > --- /dev/null > +++ b/drivers/usb/host/dwc3-of-simple.c > @@ -0,0 +1,109 @@ > +/* > + * dwc3-of-simple.c - OF glue layer for simple integrations > + * > + * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com > + * > + * Author: Felipe Balbi <balbi@ti.com> > + * > + * Copyright (C) 2018 BayLibre, SAS > + * Author: Neil Armstrong <narmstron@baylibre.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <fdtdec.h> > +#include <reset.h> > +#include <clk.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct dwc3_of_simple { > + struct clk_bulk clks; > + struct reset_ctl_bulk resets; > +}; > + > +static int dwc3_of_simple_reset_init(struct udevice *dev, > + struct dwc3_of_simple *simple) > +{ > + int ret; > + > + ret = reset_get_bulk(dev, &simple->resets); > + if (ret == -ENOTSUPP) > + return 0; > + else if (ret) > + return ret; > + > + ret = reset_deassert_bulk(&simple->resets); > + if (ret) { > + reset_release_bulk(&simple->resets); > + return ret; > + } > + > + return 0; > +} > + > +static int dwc3_of_simple_clk_init(struct udevice *dev, > + struct dwc3_of_simple *simple) > +{ > + int ret; > + > + ret = clk_get_bulk(dev, &simple->clks); > + if (ret == -ENOTSUPP) Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> > + return 0; > + if (ret) > + return ret; > + > +#if CONFIG_IS_ENABLED(CLK) > + ret = clk_enable_bulk(&simple->clks); > + if (ret) { > + clk_release_bulk(&simple->clks); > + return ret; > + } > +#endif > + > + return 0; > +} > + > +static int dwc3_of_simple_probe(struct udevice *dev) > +{ > + struct dwc3_of_simple *simple = dev_get_platdata(dev); > + int ret; > + > + ret = dwc3_of_simple_clk_init(dev, simple); > + if (ret) > + return ret; > + > + ret = dwc3_of_simple_reset_init(dev, simple); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int dwc3_of_simple_remove(struct udevice *dev) > +{ > + struct dwc3_of_simple *simple = dev_get_platdata(dev); > + > + reset_release_bulk(&simple->resets); > + > + clk_release_bulk(&simple->clks); > + > + return dm_scan_fdt_dev(dev); > +} > + > +static const struct udevice_id dwc3_of_simple_ids[] = { > + { .compatible = "amlogic,meson-gxl-dwc3" }, > + { } > +}; > + > +U_BOOT_DRIVER(dwc3_of_simple) = { > + .name = "dwc3-of-simple", > + .id = UCLASS_SIMPLE_BUS, > + .of_match = dwc3_of_simple_ids, > + .probe = dwc3_of_simple_probe, > + .remove = dwc3_of_simple_remove, > + .platdata_auto_alloc_size = sizeof(struct dwc3_of_simple), > + .flags = DM_FLAG_ALLOC_PRIV_DMA, > +}; ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration 2018-04-11 16:17 ` Jean-Jacques Hiblot @ 2018-04-12 8:05 ` Neil Armstrong -1 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-12 8:05 UTC (permalink / raw) To: u-boot Hi Jean-Jacques, On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: > > > On 11/04/2018 17:08, Neil Armstrong wrote: >> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >> clock and resets of a simple DWC3 Controller HW glue. >> >> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >> --- >> drivers/usb/host/Kconfig | 7 +++ >> drivers/usb/host/Makefile | 1 + >> drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 117 insertions(+) >> create mode 100644 drivers/usb/host/dwc3-of-simple.c >> >> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >> index a7249b7..6caa615 100644 >> --- a/drivers/usb/host/Kconfig >> +++ b/drivers/usb/host/Kconfig >> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 [...] >> + >> +static int dwc3_of_simple_clk_init(struct udevice *dev, >> + struct dwc3_of_simple *simple) >> +{ >> + int ret; >> + >> + ret = clk_get_bulk(dev, &simple->clks); >> + if (ret == -ENOTSUPP) > > Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework You are right, I naively used the same between reset and clock... > > tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> > >> + return 0; >> + if (ret) >> + return ret; >> + >> +#if CONFIG_IS_ENABLED(CLK) >> + ret = clk_enable_bulk(&simple->clks); >> + if (ret) { >> + clk_release_bulk(&simple->clks); >> + return ret; >> + } >> +#endif >> + >> + return 0; >> +} [...] Thanks, Neil ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration @ 2018-04-12 8:05 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-12 8:05 UTC (permalink / raw) To: linus-amlogic Hi Jean-Jacques, On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: > > > On 11/04/2018 17:08, Neil Armstrong wrote: >> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >> clock and resets of a simple DWC3 Controller HW glue. >> >> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >> --- >> ? drivers/usb/host/Kconfig????????? |?? 7 +++ >> ? drivers/usb/host/Makefile???????? |?? 1 + >> ? drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >> ? 3 files changed, 117 insertions(+) >> ? create mode 100644 drivers/usb/host/dwc3-of-simple.c >> >> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >> index a7249b7..6caa615 100644 >> --- a/drivers/usb/host/Kconfig >> +++ b/drivers/usb/host/Kconfig >> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 [...] >> + >> +static int dwc3_of_simple_clk_init(struct udevice *dev, >> +?????????????????? struct dwc3_of_simple *simple) >> +{ >> +??? int ret; >> + >> +??? ret = clk_get_bulk(dev, &simple->clks); >> +??? if (ret == -ENOTSUPP) > > Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework You are right, I naively used the same between reset and clock... > > tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> > >> +??????? return 0; >> +??? if (ret) >> +??????? return ret; >> + >> +#if CONFIG_IS_ENABLED(CLK) >> +??? ret = clk_enable_bulk(&simple->clks); >> +??? if (ret) { >> +??????? clk_release_bulk(&simple->clks); >> +??????? return ret; >> +??? } >> +#endif >> + >> +??? return 0; >> +} [...] Thanks, Neil ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration 2018-04-12 8:05 ` Neil Armstrong @ 2018-04-12 8:07 ` Ben Dooks -1 siblings, 0 replies; 18+ messages in thread From: Ben Dooks @ 2018-04-12 8:07 UTC (permalink / raw) To: u-boot On 12/04/18 09:05, Neil Armstrong wrote: > Hi Jean-Jacques, > > On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: >> >> >> On 11/04/2018 17:08, Neil Armstrong wrote: >>> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >>> clock and resets of a simple DWC3 Controller HW glue. >>> >>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >>> --- >>> drivers/usb/host/Kconfig | 7 +++ >>> drivers/usb/host/Makefile | 1 + >>> drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >>> 3 files changed, 117 insertions(+) >>> create mode 100644 drivers/usb/host/dwc3-of-simple.c >>> >>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >>> index a7249b7..6caa615 100644 >>> --- a/drivers/usb/host/Kconfig >>> +++ b/drivers/usb/host/Kconfig >>> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 > [...] > >>> + >>> +static int dwc3_of_simple_clk_init(struct udevice *dev, >>> + struct dwc3_of_simple *simple) >>> +{ >>> + int ret; >>> + >>> + ret = clk_get_bulk(dev, &simple->clks); >>> + if (ret == -ENOTSUPP) >> >> Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework > > You are right, I naively used the same between reset and clock... > >> >> tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> >> >>> + return 0; >>> + if (ret) >>> + return ret; >>> + >>> +#if CONFIG_IS_ENABLED(CLK) >>> + ret = clk_enable_bulk(&simple->clks); >>> + if (ret) { >>> + clk_release_bulk(&simple->clks); >>> + return ret; >>> + } >>> +#endif >>> + >>> + return 0; >>> +} Is the above #if CONFIG_IS_ENABLED(CLK) avoidable? > > [...] > Thanks, > Neil > > _______________________________________________ > linux-amlogic mailing list > linux-amlogic at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-amlogic > -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration @ 2018-04-12 8:07 ` Ben Dooks 0 siblings, 0 replies; 18+ messages in thread From: Ben Dooks @ 2018-04-12 8:07 UTC (permalink / raw) To: linus-amlogic On 12/04/18 09:05, Neil Armstrong wrote: > Hi Jean-Jacques, > > On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: >> >> >> On 11/04/2018 17:08, Neil Armstrong wrote: >>> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >>> clock and resets of a simple DWC3 Controller HW glue. >>> >>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >>> --- >>> ? drivers/usb/host/Kconfig????????? |?? 7 +++ >>> ? drivers/usb/host/Makefile???????? |?? 1 + >>> ? drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >>> ? 3 files changed, 117 insertions(+) >>> ? create mode 100644 drivers/usb/host/dwc3-of-simple.c >>> >>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >>> index a7249b7..6caa615 100644 >>> --- a/drivers/usb/host/Kconfig >>> +++ b/drivers/usb/host/Kconfig >>> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 > [...] > >>> + >>> +static int dwc3_of_simple_clk_init(struct udevice *dev, >>> +?????????????????? struct dwc3_of_simple *simple) >>> +{ >>> +??? int ret; >>> + >>> +??? ret = clk_get_bulk(dev, &simple->clks); >>> +??? if (ret == -ENOTSUPP) >> >> Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework > > You are right, I naively used the same between reset and clock... > >> >> tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> >> >>> +??????? return 0; >>> +??? if (ret) >>> +??????? return ret; >>> + >>> +#if CONFIG_IS_ENABLED(CLK) >>> +??? ret = clk_enable_bulk(&simple->clks); >>> +??? if (ret) { >>> +??????? clk_release_bulk(&simple->clks); >>> +??????? return ret; >>> +??? } >>> +#endif >>> + >>> +??? return 0; >>> +} Is the above #if CONFIG_IS_ENABLED(CLK) avoidable? > > [...] > Thanks, > Neil > > _______________________________________________ > linux-amlogic mailing list > linux-amlogic at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-amlogic > -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration 2018-04-12 8:07 ` Ben Dooks @ 2018-04-12 8:08 ` Neil Armstrong -1 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-12 8:08 UTC (permalink / raw) To: u-boot On 12/04/2018 10:07, Ben Dooks wrote: > On 12/04/18 09:05, Neil Armstrong wrote: >> Hi Jean-Jacques, >> >> On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: >>> >>> >>> On 11/04/2018 17:08, Neil Armstrong wrote: >>>> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >>>> clock and resets of a simple DWC3 Controller HW glue. >>>> >>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >>>> --- >>>> drivers/usb/host/Kconfig | 7 +++ >>>> drivers/usb/host/Makefile | 1 + >>>> drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >>>> 3 files changed, 117 insertions(+) >>>> create mode 100644 drivers/usb/host/dwc3-of-simple.c >>>> >>>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >>>> index a7249b7..6caa615 100644 >>>> --- a/drivers/usb/host/Kconfig >>>> +++ b/drivers/usb/host/Kconfig >>>> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 >> [...] >> >>>> + >>>> +static int dwc3_of_simple_clk_init(struct udevice *dev, >>>> + struct dwc3_of_simple *simple) >>>> +{ >>>> + int ret; >>>> + >>>> + ret = clk_get_bulk(dev, &simple->clks); >>>> + if (ret == -ENOTSUPP) >>> >>> Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework >> >> You are right, I naively used the same between reset and clock... >> >>> >>> tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> >>> >>>> + return 0; >>>> + if (ret) >>>> + return ret; >>>> + >>>> +#if CONFIG_IS_ENABLED(CLK) >>>> + ret = clk_enable_bulk(&simple->clks); >>>> + if (ret) { >>>> + clk_release_bulk(&simple->clks); >>>> + return ret; >>>> + } >>>> +#endif >>>> + >>>> + return 0; >>>> +} > > Is the above #if CONFIG_IS_ENABLED(CLK) avoidable? No unless some changes in clk.h Neil > >> >> [...] >> Thanks, >> Neil >> >> _______________________________________________ >> linux-amlogic mailing list >> linux-amlogic at lists.infradead.org >> http://lists.infradead.org/mailman/listinfo/linux-amlogic >> > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration @ 2018-04-12 8:08 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-12 8:08 UTC (permalink / raw) To: linus-amlogic On 12/04/2018 10:07, Ben Dooks wrote: > On 12/04/18 09:05, Neil Armstrong wrote: >> Hi Jean-Jacques, >> >> On 11/04/2018 18:17, Jean-Jacques Hiblot wrote: >>> >>> >>> On 11/04/2018 17:08, Neil Armstrong wrote: >>>> This is a port of the dwc3-of-simple driver from Linux to enable/deassert >>>> clock and resets of a simple DWC3 Controller HW glue. >>>> >>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> >>>> --- >>>> ?? drivers/usb/host/Kconfig????????? |?? 7 +++ >>>> ?? drivers/usb/host/Makefile???????? |?? 1 + >>>> ?? drivers/usb/host/dwc3-of-simple.c | 109 ++++++++++++++++++++++++++++++++++++++ >>>> ?? 3 files changed, 117 insertions(+) >>>> ?? create mode 100644 drivers/usb/host/dwc3-of-simple.c >>>> >>>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig >>>> index a7249b7..6caa615 100644 >>>> --- a/drivers/usb/host/Kconfig >>>> +++ b/drivers/usb/host/Kconfig >>>> @@ -21,6 +21,13 @@ config USB_XHCI_DWC3 >> [...] >> >>>> + >>>> +static int dwc3_of_simple_clk_init(struct udevice *dev, >>>> +?????????????????? struct dwc3_of_simple *simple) >>>> +{ >>>> +??? int ret; >>>> + >>>> +??? ret = clk_get_bulk(dev, &simple->clks); >>>> +??? if (ret == -ENOTSUPP) >>> >>> Must be ENOSYS instead of ENOTSUPP, otherwise probe fails on platform not using the clk framework >> >> You are right, I naively used the same between reset and clock... >> >>> >>> tested-by: Jean-Jacques hiblot <jjhiblot@ti.com> >>> >>>> +??????? return 0; >>>> +??? if (ret) >>>> +??????? return ret; >>>> + >>>> +#if CONFIG_IS_ENABLED(CLK) >>>> +??? ret = clk_enable_bulk(&simple->clks); >>>> +??? if (ret) { >>>> +??????? clk_release_bulk(&simple->clks); >>>> +??????? return ret; >>>> +??? } >>>> +#endif >>>> + >>>> +??? return 0; >>>> +} > > Is the above #if CONFIG_IS_ENABLED(CLK) avoidable? No unless some changes in clk.h Neil > >> >> [...] >> Thanks, >> Neil >> >> _______________________________________________ >> linux-amlogic mailing list >> linux-amlogic at lists.infradead.org >> http://lists.infradead.org/mailman/listinfo/linux-amlogic >> > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 2/3] usb: host: dwc3: Add support for multiple PHYs 2018-04-11 15:07 ` Neil Armstrong @ 2018-04-11 15:08 ` Neil Armstrong -1 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: u-boot DWC3 Ips can have more than 1 PHY for USB2 and 1 PHY for USB3, add support for a generic number of PHYs and adapt the code to handle a generic number of PHYs. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/usb/host/xhci-dwc3.c | 113 +++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 1022dd5..c100735 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -22,8 +22,8 @@ DECLARE_GLOBAL_DATA_PTR; struct xhci_dwc3_platdata { - struct phy usb_phy; - struct phy usb3_phy; + struct phy *usb_phys; + int num_phys; }; void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) @@ -113,45 +113,82 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) } #ifdef CONFIG_DM_USB -static int xhci_dwc3_setup_phy(struct udevice *dev, int index, struct phy *phy) +static int xhci_dwc3_setup_phy(struct udevice *dev, int count) { - int ret = 0; + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int i, ret; + + if (!count) + return 0; - ret = generic_phy_get_by_index(dev, index, phy); - if (ret) { - if (ret != -ENOENT) { - pr_err("Failed to get USB PHY for %s\n", dev->name); + plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), + GFP_KERNEL); + if (!plat->usb_phys) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]); + if (ret && ret != -ENOENT) { + pr_err("Failed to get USB PHY%d for %s\n", + i, dev->name); return ret; } - } else { - ret = generic_phy_init(phy); + + ++plat->num_phys; + } + + for (i = 0; i < plat->num_phys; i++) { + ret = generic_phy_init(&plat->usb_phys[i]); if (ret) { - pr_err("Can't init USB PHY for %s\n", dev->name); - return ret; + pr_err("Can't init USB PHY%d for %s\n", + i, dev->name); + goto phys_init_err; } - ret = generic_phy_power_on(phy); + } + + for (i = 0; i < plat->num_phys; i++) { + ret = generic_phy_power_on(&plat->usb_phys[i]); if (ret) { - pr_err("Can't power on USB PHY for %s\n", dev->name); - generic_phy_exit(phy); - return ret; + pr_err("Can't power USB PHY%d for %s\n", + i, dev->name); + goto phys_poweron_err; } } return 0; + + +phys_poweron_err: + for (; i >= 0; i--) + generic_phy_power_off(&plat->usb_phys[i]); + + for (i = 0; i < plat->num_phys; i++) + generic_phy_exit(&plat->usb_phys[i]); + + return ret; + +phys_init_err: + for (; i >= 0; i--) + generic_phy_exit(&plat->usb_phys[i]); + + return ret; } -static int xhci_dwc3_shutdown_phy(struct phy *phy) +static int xhci_dwc3_shutdown_phy(struct udevice *dev) { - int ret = 0; + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int i, ret; - if (generic_phy_valid(phy)) { - ret = generic_phy_power_off(phy); - if (ret) - return ret; + for (i = 0; i < plat->num_phys; i++) { + if (!generic_phy_valid(&plat->usb_phys[i])) + continue; - ret = generic_phy_exit(phy); - if (ret) - return ret; + ret = generic_phy_power_off(&plat->usb_phys[i]); + ret |= generic_phy_exit(&plat->usb_phys[i]); + if (ret) { + pr_err("Can't shutdown USB PHY%d for %s\n", + i, dev->name); + } } return 0; @@ -159,7 +196,6 @@ static int xhci_dwc3_shutdown_phy(struct phy *phy) static int xhci_dwc3_probe(struct udevice *dev) { - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); struct xhci_hcor *hcor; struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; @@ -170,18 +206,10 @@ static int xhci_dwc3_probe(struct udevice *dev) hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); - ret = xhci_dwc3_setup_phy(dev, 0, &plat->usb_phy); - if (ret) { - pr_err("Failed to setup USB PHY for %s\n", dev->name); + ret = xhci_dwc3_setup_phy(dev, dev_count_phandle_with_args( + dev, "phys", "#phy-cells")); + if (ret) return ret; - } - - ret = xhci_dwc3_setup_phy(dev, 1, &plat->usb3_phy); - if (ret) { - pr_err("Failed to setup USB3 PHY for %s\n", dev->name); - xhci_dwc3_shutdown_phy(&plat->usb_phy); - return ret; - } dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); @@ -199,16 +227,7 @@ static int xhci_dwc3_probe(struct udevice *dev) static int xhci_dwc3_remove(struct udevice *dev) { - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); - int ret; - - ret = xhci_dwc3_shutdown_phy(&plat->usb_phy); - if (ret) - pr_err("Can't shutdown USB PHY for %s\n", dev->name); - - ret = xhci_dwc3_shutdown_phy(&plat->usb3_phy); - if (ret) - pr_err("Can't shutdown USB3 PHY for %s\n", dev->name); + xhci_dwc3_shutdown_phy(dev); return xhci_deregister(dev); } -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 u-boot 2/3] usb: host: dwc3: Add support for multiple PHYs @ 2018-04-11 15:08 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: linus-amlogic DWC3 Ips can have more than 1 PHY for USB2 and 1 PHY for USB3, add support for a generic number of PHYs and adapt the code to handle a generic number of PHYs. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/usb/host/xhci-dwc3.c | 113 +++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 1022dd5..c100735 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -22,8 +22,8 @@ DECLARE_GLOBAL_DATA_PTR; struct xhci_dwc3_platdata { - struct phy usb_phy; - struct phy usb3_phy; + struct phy *usb_phys; + int num_phys; }; void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) @@ -113,45 +113,82 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) } #ifdef CONFIG_DM_USB -static int xhci_dwc3_setup_phy(struct udevice *dev, int index, struct phy *phy) +static int xhci_dwc3_setup_phy(struct udevice *dev, int count) { - int ret = 0; + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int i, ret; + + if (!count) + return 0; - ret = generic_phy_get_by_index(dev, index, phy); - if (ret) { - if (ret != -ENOENT) { - pr_err("Failed to get USB PHY for %s\n", dev->name); + plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), + GFP_KERNEL); + if (!plat->usb_phys) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]); + if (ret && ret != -ENOENT) { + pr_err("Failed to get USB PHY%d for %s\n", + i, dev->name); return ret; } - } else { - ret = generic_phy_init(phy); + + ++plat->num_phys; + } + + for (i = 0; i < plat->num_phys; i++) { + ret = generic_phy_init(&plat->usb_phys[i]); if (ret) { - pr_err("Can't init USB PHY for %s\n", dev->name); - return ret; + pr_err("Can't init USB PHY%d for %s\n", + i, dev->name); + goto phys_init_err; } - ret = generic_phy_power_on(phy); + } + + for (i = 0; i < plat->num_phys; i++) { + ret = generic_phy_power_on(&plat->usb_phys[i]); if (ret) { - pr_err("Can't power on USB PHY for %s\n", dev->name); - generic_phy_exit(phy); - return ret; + pr_err("Can't power USB PHY%d for %s\n", + i, dev->name); + goto phys_poweron_err; } } return 0; + + +phys_poweron_err: + for (; i >= 0; i--) + generic_phy_power_off(&plat->usb_phys[i]); + + for (i = 0; i < plat->num_phys; i++) + generic_phy_exit(&plat->usb_phys[i]); + + return ret; + +phys_init_err: + for (; i >= 0; i--) + generic_phy_exit(&plat->usb_phys[i]); + + return ret; } -static int xhci_dwc3_shutdown_phy(struct phy *phy) +static int xhci_dwc3_shutdown_phy(struct udevice *dev) { - int ret = 0; + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int i, ret; - if (generic_phy_valid(phy)) { - ret = generic_phy_power_off(phy); - if (ret) - return ret; + for (i = 0; i < plat->num_phys; i++) { + if (!generic_phy_valid(&plat->usb_phys[i])) + continue; - ret = generic_phy_exit(phy); - if (ret) - return ret; + ret = generic_phy_power_off(&plat->usb_phys[i]); + ret |= generic_phy_exit(&plat->usb_phys[i]); + if (ret) { + pr_err("Can't shutdown USB PHY%d for %s\n", + i, dev->name); + } } return 0; @@ -159,7 +196,6 @@ static int xhci_dwc3_shutdown_phy(struct phy *phy) static int xhci_dwc3_probe(struct udevice *dev) { - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); struct xhci_hcor *hcor; struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; @@ -170,18 +206,10 @@ static int xhci_dwc3_probe(struct udevice *dev) hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); - ret = xhci_dwc3_setup_phy(dev, 0, &plat->usb_phy); - if (ret) { - pr_err("Failed to setup USB PHY for %s\n", dev->name); + ret = xhci_dwc3_setup_phy(dev, dev_count_phandle_with_args( + dev, "phys", "#phy-cells")); + if (ret) return ret; - } - - ret = xhci_dwc3_setup_phy(dev, 1, &plat->usb3_phy); - if (ret) { - pr_err("Failed to setup USB3 PHY for %s\n", dev->name); - xhci_dwc3_shutdown_phy(&plat->usb_phy); - return ret; - } dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); @@ -199,16 +227,7 @@ static int xhci_dwc3_probe(struct udevice *dev) static int xhci_dwc3_remove(struct udevice *dev) { - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); - int ret; - - ret = xhci_dwc3_shutdown_phy(&plat->usb_phy); - if (ret) - pr_err("Can't shutdown USB PHY for %s\n", dev->name); - - ret = xhci_dwc3_shutdown_phy(&plat->usb3_phy); - if (ret) - pr_err("Can't shutdown USB3 PHY for %s\n", dev->name); + xhci_dwc3_shutdown_phy(dev); return xhci_deregister(dev); } -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 3/3] phy: Add Amlogic Meson USB2 & USB3 Generic PHY drivers 2018-04-11 15:07 ` Neil Armstrong @ 2018-04-11 15:08 ` Neil Armstrong -1 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: u-boot The Amlogic Meson GXL and GXM (simple variant) embeds up to 3 USB2 PHYs and an USB3 PHY. This patch adds drivers for these for the standard generic PHY interface and supports the power-on/off calls and set the Host mode by default. They are based on the excellent work from Martin Blumenstingl merged in linux. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/meson-gxl-usb2.c | 238 +++++++++++++++++++++++++++++++++++++++++++ drivers/phy/meson-gxl-usb3.c | 201 ++++++++++++++++++++++++++++++++++++ 4 files changed, 448 insertions(+) create mode 100644 drivers/phy/meson-gxl-usb2.c create mode 100644 drivers/phy/meson-gxl-usb3.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 3b9a09c..99a6d95 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -85,4 +85,12 @@ config STI_USB_PHY used by USB2 and USB3 Host controllers available on STiH407 SoC families. +config MESON_GXL_USB_PHY + bool "Amlogic Meson GXL USB PHYs" + depends on PHY && ARCH_MESON && MESON_GXL + imply REGMAP + help + This is the generic phy driver for the Amlogic Meson GXL + USB2 and USB3 PHYS. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 668040b..6c1610e 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o +obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c new file mode 100644 index 0000000..15c9c89 --- /dev/null +++ b/drivers/phy/meson-gxl-usb2.c @@ -0,0 +1,238 @@ +/* + * Meson GXL and GXM USB2 PHY driver + * + * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <power/regulator.h> +#include <clk.h> + +#include <linux/bitops.h> +#include <linux/compat.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* bits [31:27] are read-only */ +#define U2P_R0 0x0 + #define U2P_R0_BYPASS_SEL BIT(0) + #define U2P_R0_BYPASS_DM_EN BIT(1) + #define U2P_R0_BYPASS_DP_EN BIT(2) + #define U2P_R0_TXBITSTUFF_ENH BIT(3) + #define U2P_R0_TXBITSTUFF_EN BIT(4) + #define U2P_R0_DM_PULLDOWN BIT(5) + #define U2P_R0_DP_PULLDOWN BIT(6) + #define U2P_R0_DP_VBUS_VLD_EXT_SEL BIT(7) + #define U2P_R0_DP_VBUS_VLD_EXT BIT(8) + #define U2P_R0_ADP_PRB_EN BIT(9) + #define U2P_R0_ADP_DISCHARGE BIT(10) + #define U2P_R0_ADP_CHARGE BIT(11) + #define U2P_R0_DRV_VBUS BIT(12) + #define U2P_R0_ID_PULLUP BIT(13) + #define U2P_R0_LOOPBACK_EN_B BIT(14) + #define U2P_R0_OTG_DISABLE BIT(15) + #define U2P_R0_COMMON_ONN BIT(16) + #define U2P_R0_FSEL_MASK GENMASK(19, 17) + #define U2P_R0_REF_CLK_SEL_MASK GENMASK(21, 20) + #define U2P_R0_POWER_ON_RESET BIT(22) + #define U2P_R0_V_ATE_TEST_EN_B_MASK GENMASK(24, 23) + #define U2P_R0_ID_SET_ID_DQ BIT(25) + #define U2P_R0_ATE_RESET BIT(26) + #define U2P_R0_FSV_MINUS BIT(27) + #define U2P_R0_FSV_PLUS BIT(28) + #define U2P_R0_BYPASS_DM_DATA BIT(29) + #define U2P_R0_BYPASS_DP_DATA BIT(30) + +#define U2P_R1 0x4 + #define U2P_R1_BURN_IN_TEST BIT(0) + #define U2P_R1_ACA_ENABLE BIT(1) + #define U2P_R1_DCD_ENABLE BIT(2) + #define U2P_R1_VDAT_SRC_EN_B BIT(3) + #define U2P_R1_VDAT_DET_EN_B BIT(4) + #define U2P_R1_CHARGES_SEL BIT(5) + #define U2P_R1_TX_PREEMP_PULSE_TUNE BIT(6) + #define U2P_R1_TX_PREEMP_AMP_TUNE_MASK GENMASK(8, 7) + #define U2P_R1_TX_RES_TUNE_MASK GENMASK(10, 9) + #define U2P_R1_TX_RISE_TUNE_MASK GENMASK(12, 11) + #define U2P_R1_TX_VREF_TUNE_MASK GENMASK(16, 13) + #define U2P_R1_TX_FSLS_TUNE_MASK GENMASK(20, 17) + #define U2P_R1_TX_HSXV_TUNE_MASK GENMASK(22, 21) + #define U2P_R1_OTG_TUNE_MASK GENMASK(25, 23) + #define U2P_R1_SQRX_TUNE_MASK GENMASK(28, 26) + #define U2P_R1_COMP_DIS_TUNE_MASK GENMASK(31, 29) + +/* bits [31:14] are read-only */ +#define U2P_R2 0x8 + #define U2P_R2_TESTDATA_IN_MASK GENMASK(7, 0) + #define U2P_R2_TESTADDR_MASK GENMASK(11, 8) + #define U2P_R2_TESTDATA_OUT_SEL BIT(12) + #define U2P_R2_TESTCLK BIT(13) + #define U2P_R2_TESTDATA_OUT_MASK GENMASK(17, 14) + #define U2P_R2_ACA_PIN_RANGE_C BIT(18) + #define U2P_R2_ACA_PIN_RANGE_B BIT(19) + #define U2P_R2_ACA_PIN_RANGE_A BIT(20) + #define U2P_R2_ACA_PIN_GND BIT(21) + #define U2P_R2_ACA_PIN_FLOAT BIT(22) + #define U2P_R2_CHARGE_DETECT BIT(23) + #define U2P_R2_DEVICE_SESSION_VALID BIT(24) + #define U2P_R2_ADP_PROBE BIT(25) + #define U2P_R2_ADP_SENSE BIT(26) + #define U2P_R2_SESSION_END BIT(27) + #define U2P_R2_VBUS_VALID BIT(28) + #define U2P_R2_B_VALID BIT(29) + #define U2P_R2_A_VALID BIT(30) + #define U2P_R2_ID_DIG BIT(31) + +#define U2P_R3 0xc + +#define RESET_COMPLETE_TIME 500 + +struct phy_meson_gxl_usb2_priv { + struct regmap *regmap; +#if CONFIG_IS_ENABLED(DM_REGULATOR) + struct udevice *phy_supply; +#endif +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; +#endif +}; + +static void phy_meson_gxl_usb2_reset(struct phy_meson_gxl_usb2_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + + /* reset the PHY and wait until settings are stabilized */ + val |= U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + udelay(RESET_COMPLETE_TIME); + + val &= ~U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + udelay(RESET_COMPLETE_TIME); +} + +static void +phy_meson_gxl_usb2_set_host_mode(struct phy_meson_gxl_usb2_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + val |= U2P_R0_DM_PULLDOWN; + val |= U2P_R0_DP_PULLDOWN; + val &= ~U2P_R0_ID_PULLUP; + regmap_write(priv->regmap, U2P_R0, val); + + phy_meson_gxl_usb2_reset(priv); +} + +static int phy_meson_gxl_usb2_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + /* power on the PHY by taking it out of reset mode */ + val &= ~U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + + phy_meson_gxl_usb2_set_host_mode(priv); + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->phy_supply) { + int ret = regulator_set_enable(priv->phy_supply, true); + if (ret) + return ret; + } +#endif + + return 0; +} + +static int phy_meson_gxl_usb2_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + /* power off the PHY by putting it into reset mode */ + val |= U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->phy_supply) { + int ret = regulator_set_enable(priv->phy_supply, false); + if (ret) { + pr_err("Error disabling PHY supply\n"); + return ret; + } + } +#endif + + return 0; +} + +struct phy_ops meson_gxl_usb2_phy_ops = { + .power_on = phy_meson_gxl_usb2_power_on, + .power_off = phy_meson_gxl_usb2_power_off, +}; + +int meson_gxl_usb2_phy_probe(struct udevice *dev) +{ + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + int ret; + + ret = regmap_init_mem(dev, &priv->regmap); + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + pr_err("failed to enable PHY clock\n"); + clk_free(&priv->clk); + return ret; + } +#endif + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); + if (ret && ret != -ENOENT) { + pr_err("Failed to get PHY regulator\n"); + return ret; + } +#endif + + return 0; +} + +static const struct udevice_id meson_gxl_usb2_phy_ids[] = { + { .compatible = "amlogic,meson-gxl-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(meson_gxl_usb2_phy) = { + .name = "meson_gxl_usb2_phy", + .id = UCLASS_PHY, + .of_match = meson_gxl_usb2_phy_ids, + .probe = meson_gxl_usb2_phy_probe, + .ops = &meson_gxl_usb2_phy_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb2_priv), +}; diff --git a/drivers/phy/meson-gxl-usb3.c b/drivers/phy/meson-gxl-usb3.c new file mode 100644 index 0000000..a385fbd --- /dev/null +++ b/drivers/phy/meson-gxl-usb3.c @@ -0,0 +1,201 @@ +/* + * Meson GXL USB3 PHY driver + * + * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com> + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <clk.h> + +#include <linux/bitops.h> +#include <linux/compat.h> +#include <linux/bitfield.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define USB_R0 0x00 + #define USB_R0_P30_FSEL_MASK GENMASK(5, 0) + #define USB_R0_P30_PHY_RESET BIT(6) + #define USB_R0_P30_TEST_POWERDOWN_HSP BIT(7) + #define USB_R0_P30_TEST_POWERDOWN_SSP BIT(8) + #define USB_R0_P30_ACJT_LEVEL_MASK GENMASK(13, 9) + #define USB_R0_P30_TX_BOOST_LEVEL_MASK GENMASK(16, 14) + #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17) + #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18) + #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19) + #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29) + #define USB_R0_U2D_ACT BIT(31) + +#define USB_R1 0x04 + #define USB_R1_U3H_BIGENDIAN_GS BIT(0) + #define USB_R1_U3H_PME_ENABLE BIT(1) + #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(6, 2) + #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(11, 7) + #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(15, 12) + #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16) + #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17) + #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18) + #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19) + #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25) + +#define USB_R2 0x08 + #define USB_R2_P30_CR_DATA_IN_MASK GENMASK(15, 0) + #define USB_R2_P30_CR_READ BIT(16) + #define USB_R2_P30_CR_WRITE BIT(17) + #define USB_R2_P30_CR_CAP_ADDR BIT(18) + #define USB_R2_P30_CR_CAP_DATA BIT(19) + #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20) + #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26) + +#define USB_R3 0x0c + #define USB_R3_P30_SSC_ENABLE BIT(0) + #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1) + #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4) + #define USB_R3_P30_REF_SSP_EN BIT(13) + #define USB_R3_P30_LOS_BIAS_MASK GENMASK(18, 16) + #define USB_R3_P30_LOS_LEVEL_MASK GENMASK(23, 19) + #define USB_R3_P30_MPLL_MULTIPLIER_MASK GENMASK(30, 24) + +#define USB_R4 0x10 + #define USB_R4_P21_PORT_RESET_0 BIT(0) + #define USB_R4_P21_SLEEP_M0 BIT(1) + #define USB_R4_MEM_PD_MASK GENMASK(3, 2) + #define USB_R4_P21_ONLY BIT(4) + +#define USB_R5 0x14 + #define USB_R5_ID_DIG_SYNC BIT(0) + #define USB_R5_ID_DIG_REG BIT(1) + #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2) + #define USB_R5_ID_DIG_EN_0 BIT(4) + #define USB_R5_ID_DIG_EN_1 BIT(5) + #define USB_R5_ID_DIG_CURR BIT(6) + #define USB_R5_ID_DIG_IRQ BIT(7) + #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8) + #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16) + +/* read-only register */ +#define USB_R6 0x18 + #define USB_R6_P30_CR_DATA_OUT_MASK GENMASK(15, 0) + #define USB_R6_P30_CR_ACK BIT(16) + +struct phy_meson_gxl_usb3_priv { + struct regmap *regmap; +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; +#endif +}; + +static int +phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, USB_R0, &val); + val &= ~USB_R0_U2D_ACT; + regmap_write(priv->regmap, USB_R0, val); + + regmap_read(priv->regmap, USB_R4, &val); + val &= ~USB_R4_P21_SLEEP_M0; + regmap_write(priv->regmap, USB_R4, val); + + return 0; +} + +static int phy_meson_gxl_usb3_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R5, &val); + val |= USB_R5_ID_DIG_EN_0; + val |= USB_R5_ID_DIG_EN_1; + val &= ~USB_R5_ID_DIG_TH_MASK; + val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff); + regmap_write(priv->regmap, USB_R5, val); + + return phy_meson_gxl_usb3_set_host_mode(priv); +} + +static int phy_meson_gxl_usb3_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R5, &val); + val &= ~USB_R5_ID_DIG_EN_0; + val &= ~USB_R5_ID_DIG_EN_1; + regmap_write(priv->regmap, USB_R5, val); + + return 0; +} + +static int phy_meson_gxl_usb3_init(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R1, &val); + val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK; + val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20); + regmap_write(priv->regmap, USB_R1, val); + + return 0; +} + +struct phy_ops meson_gxl_usb3_phy_ops = { + .init = phy_meson_gxl_usb3_init, + .power_on = phy_meson_gxl_usb3_power_on, + .power_off = phy_meson_gxl_usb3_power_off, +}; + +int meson_gxl_usb3_phy_probe(struct udevice *dev) +{ + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + int ret; + + ret = regmap_init_mem(dev, &priv->regmap); + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + pr_err("failed to enable PHY clock\n"); + clk_free(&priv->clk); + return ret; + } +#endif + + return 0; +} + +static const struct udevice_id meson_gxl_usb3_phy_ids[] = { + { .compatible = "amlogic,meson-gxl-usb3-phy" }, + { } +}; + +U_BOOT_DRIVER(meson_gxl_usb3_phy) = { + .name = "meson_gxl_usb3_phy", + .id = UCLASS_PHY, + .of_match = meson_gxl_usb3_phy_ids, + .probe = meson_gxl_usb3_phy_probe, + .ops = &meson_gxl_usb3_phy_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv), +}; -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 u-boot 3/3] phy: Add Amlogic Meson USB2 & USB3 Generic PHY drivers @ 2018-04-11 15:08 ` Neil Armstrong 0 siblings, 0 replies; 18+ messages in thread From: Neil Armstrong @ 2018-04-11 15:08 UTC (permalink / raw) To: linus-amlogic The Amlogic Meson GXL and GXM (simple variant) embeds up to 3 USB2 PHYs and an USB3 PHY. This patch adds drivers for these for the standard generic PHY interface and supports the power-on/off calls and set the Host mode by default. They are based on the excellent work from Martin Blumenstingl merged in linux. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/meson-gxl-usb2.c | 238 +++++++++++++++++++++++++++++++++++++++++++ drivers/phy/meson-gxl-usb3.c | 201 ++++++++++++++++++++++++++++++++++++ 4 files changed, 448 insertions(+) create mode 100644 drivers/phy/meson-gxl-usb2.c create mode 100644 drivers/phy/meson-gxl-usb3.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 3b9a09c..99a6d95 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -85,4 +85,12 @@ config STI_USB_PHY used by USB2 and USB3 Host controllers available on STiH407 SoC families. +config MESON_GXL_USB_PHY + bool "Amlogic Meson GXL USB PHYs" + depends on PHY && ARCH_MESON && MESON_GXL + imply REGMAP + help + This is the generic phy driver for the Amlogic Meson GXL + USB2 and USB3 PHYS. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 668040b..6c1610e 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o +obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c new file mode 100644 index 0000000..15c9c89 --- /dev/null +++ b/drivers/phy/meson-gxl-usb2.c @@ -0,0 +1,238 @@ +/* + * Meson GXL and GXM USB2 PHY driver + * + * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <power/regulator.h> +#include <clk.h> + +#include <linux/bitops.h> +#include <linux/compat.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* bits [31:27] are read-only */ +#define U2P_R0 0x0 + #define U2P_R0_BYPASS_SEL BIT(0) + #define U2P_R0_BYPASS_DM_EN BIT(1) + #define U2P_R0_BYPASS_DP_EN BIT(2) + #define U2P_R0_TXBITSTUFF_ENH BIT(3) + #define U2P_R0_TXBITSTUFF_EN BIT(4) + #define U2P_R0_DM_PULLDOWN BIT(5) + #define U2P_R0_DP_PULLDOWN BIT(6) + #define U2P_R0_DP_VBUS_VLD_EXT_SEL BIT(7) + #define U2P_R0_DP_VBUS_VLD_EXT BIT(8) + #define U2P_R0_ADP_PRB_EN BIT(9) + #define U2P_R0_ADP_DISCHARGE BIT(10) + #define U2P_R0_ADP_CHARGE BIT(11) + #define U2P_R0_DRV_VBUS BIT(12) + #define U2P_R0_ID_PULLUP BIT(13) + #define U2P_R0_LOOPBACK_EN_B BIT(14) + #define U2P_R0_OTG_DISABLE BIT(15) + #define U2P_R0_COMMON_ONN BIT(16) + #define U2P_R0_FSEL_MASK GENMASK(19, 17) + #define U2P_R0_REF_CLK_SEL_MASK GENMASK(21, 20) + #define U2P_R0_POWER_ON_RESET BIT(22) + #define U2P_R0_V_ATE_TEST_EN_B_MASK GENMASK(24, 23) + #define U2P_R0_ID_SET_ID_DQ BIT(25) + #define U2P_R0_ATE_RESET BIT(26) + #define U2P_R0_FSV_MINUS BIT(27) + #define U2P_R0_FSV_PLUS BIT(28) + #define U2P_R0_BYPASS_DM_DATA BIT(29) + #define U2P_R0_BYPASS_DP_DATA BIT(30) + +#define U2P_R1 0x4 + #define U2P_R1_BURN_IN_TEST BIT(0) + #define U2P_R1_ACA_ENABLE BIT(1) + #define U2P_R1_DCD_ENABLE BIT(2) + #define U2P_R1_VDAT_SRC_EN_B BIT(3) + #define U2P_R1_VDAT_DET_EN_B BIT(4) + #define U2P_R1_CHARGES_SEL BIT(5) + #define U2P_R1_TX_PREEMP_PULSE_TUNE BIT(6) + #define U2P_R1_TX_PREEMP_AMP_TUNE_MASK GENMASK(8, 7) + #define U2P_R1_TX_RES_TUNE_MASK GENMASK(10, 9) + #define U2P_R1_TX_RISE_TUNE_MASK GENMASK(12, 11) + #define U2P_R1_TX_VREF_TUNE_MASK GENMASK(16, 13) + #define U2P_R1_TX_FSLS_TUNE_MASK GENMASK(20, 17) + #define U2P_R1_TX_HSXV_TUNE_MASK GENMASK(22, 21) + #define U2P_R1_OTG_TUNE_MASK GENMASK(25, 23) + #define U2P_R1_SQRX_TUNE_MASK GENMASK(28, 26) + #define U2P_R1_COMP_DIS_TUNE_MASK GENMASK(31, 29) + +/* bits [31:14] are read-only */ +#define U2P_R2 0x8 + #define U2P_R2_TESTDATA_IN_MASK GENMASK(7, 0) + #define U2P_R2_TESTADDR_MASK GENMASK(11, 8) + #define U2P_R2_TESTDATA_OUT_SEL BIT(12) + #define U2P_R2_TESTCLK BIT(13) + #define U2P_R2_TESTDATA_OUT_MASK GENMASK(17, 14) + #define U2P_R2_ACA_PIN_RANGE_C BIT(18) + #define U2P_R2_ACA_PIN_RANGE_B BIT(19) + #define U2P_R2_ACA_PIN_RANGE_A BIT(20) + #define U2P_R2_ACA_PIN_GND BIT(21) + #define U2P_R2_ACA_PIN_FLOAT BIT(22) + #define U2P_R2_CHARGE_DETECT BIT(23) + #define U2P_R2_DEVICE_SESSION_VALID BIT(24) + #define U2P_R2_ADP_PROBE BIT(25) + #define U2P_R2_ADP_SENSE BIT(26) + #define U2P_R2_SESSION_END BIT(27) + #define U2P_R2_VBUS_VALID BIT(28) + #define U2P_R2_B_VALID BIT(29) + #define U2P_R2_A_VALID BIT(30) + #define U2P_R2_ID_DIG BIT(31) + +#define U2P_R3 0xc + +#define RESET_COMPLETE_TIME 500 + +struct phy_meson_gxl_usb2_priv { + struct regmap *regmap; +#if CONFIG_IS_ENABLED(DM_REGULATOR) + struct udevice *phy_supply; +#endif +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; +#endif +}; + +static void phy_meson_gxl_usb2_reset(struct phy_meson_gxl_usb2_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + + /* reset the PHY and wait until settings are stabilized */ + val |= U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + udelay(RESET_COMPLETE_TIME); + + val &= ~U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + udelay(RESET_COMPLETE_TIME); +} + +static void +phy_meson_gxl_usb2_set_host_mode(struct phy_meson_gxl_usb2_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + val |= U2P_R0_DM_PULLDOWN; + val |= U2P_R0_DP_PULLDOWN; + val &= ~U2P_R0_ID_PULLUP; + regmap_write(priv->regmap, U2P_R0, val); + + phy_meson_gxl_usb2_reset(priv); +} + +static int phy_meson_gxl_usb2_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + /* power on the PHY by taking it out of reset mode */ + val &= ~U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + + phy_meson_gxl_usb2_set_host_mode(priv); + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->phy_supply) { + int ret = regulator_set_enable(priv->phy_supply, true); + if (ret) + return ret; + } +#endif + + return 0; +} + +static int phy_meson_gxl_usb2_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, U2P_R0, &val); + /* power off the PHY by putting it into reset mode */ + val |= U2P_R0_POWER_ON_RESET; + regmap_write(priv->regmap, U2P_R0, val); + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->phy_supply) { + int ret = regulator_set_enable(priv->phy_supply, false); + if (ret) { + pr_err("Error disabling PHY supply\n"); + return ret; + } + } +#endif + + return 0; +} + +struct phy_ops meson_gxl_usb2_phy_ops = { + .power_on = phy_meson_gxl_usb2_power_on, + .power_off = phy_meson_gxl_usb2_power_off, +}; + +int meson_gxl_usb2_phy_probe(struct udevice *dev) +{ + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); + int ret; + + ret = regmap_init_mem(dev, &priv->regmap); + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + pr_err("failed to enable PHY clock\n"); + clk_free(&priv->clk); + return ret; + } +#endif + +#if CONFIG_IS_ENABLED(DM_REGULATOR) + ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); + if (ret && ret != -ENOENT) { + pr_err("Failed to get PHY regulator\n"); + return ret; + } +#endif + + return 0; +} + +static const struct udevice_id meson_gxl_usb2_phy_ids[] = { + { .compatible = "amlogic,meson-gxl-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(meson_gxl_usb2_phy) = { + .name = "meson_gxl_usb2_phy", + .id = UCLASS_PHY, + .of_match = meson_gxl_usb2_phy_ids, + .probe = meson_gxl_usb2_phy_probe, + .ops = &meson_gxl_usb2_phy_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb2_priv), +}; diff --git a/drivers/phy/meson-gxl-usb3.c b/drivers/phy/meson-gxl-usb3.c new file mode 100644 index 0000000..a385fbd --- /dev/null +++ b/drivers/phy/meson-gxl-usb3.c @@ -0,0 +1,201 @@ +/* + * Meson GXL USB3 PHY driver + * + * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com> + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstron@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <clk.h> + +#include <linux/bitops.h> +#include <linux/compat.h> +#include <linux/bitfield.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define USB_R0 0x00 + #define USB_R0_P30_FSEL_MASK GENMASK(5, 0) + #define USB_R0_P30_PHY_RESET BIT(6) + #define USB_R0_P30_TEST_POWERDOWN_HSP BIT(7) + #define USB_R0_P30_TEST_POWERDOWN_SSP BIT(8) + #define USB_R0_P30_ACJT_LEVEL_MASK GENMASK(13, 9) + #define USB_R0_P30_TX_BOOST_LEVEL_MASK GENMASK(16, 14) + #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17) + #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18) + #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19) + #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29) + #define USB_R0_U2D_ACT BIT(31) + +#define USB_R1 0x04 + #define USB_R1_U3H_BIGENDIAN_GS BIT(0) + #define USB_R1_U3H_PME_ENABLE BIT(1) + #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(6, 2) + #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(11, 7) + #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(15, 12) + #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16) + #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17) + #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18) + #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19) + #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25) + +#define USB_R2 0x08 + #define USB_R2_P30_CR_DATA_IN_MASK GENMASK(15, 0) + #define USB_R2_P30_CR_READ BIT(16) + #define USB_R2_P30_CR_WRITE BIT(17) + #define USB_R2_P30_CR_CAP_ADDR BIT(18) + #define USB_R2_P30_CR_CAP_DATA BIT(19) + #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20) + #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26) + +#define USB_R3 0x0c + #define USB_R3_P30_SSC_ENABLE BIT(0) + #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1) + #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4) + #define USB_R3_P30_REF_SSP_EN BIT(13) + #define USB_R3_P30_LOS_BIAS_MASK GENMASK(18, 16) + #define USB_R3_P30_LOS_LEVEL_MASK GENMASK(23, 19) + #define USB_R3_P30_MPLL_MULTIPLIER_MASK GENMASK(30, 24) + +#define USB_R4 0x10 + #define USB_R4_P21_PORT_RESET_0 BIT(0) + #define USB_R4_P21_SLEEP_M0 BIT(1) + #define USB_R4_MEM_PD_MASK GENMASK(3, 2) + #define USB_R4_P21_ONLY BIT(4) + +#define USB_R5 0x14 + #define USB_R5_ID_DIG_SYNC BIT(0) + #define USB_R5_ID_DIG_REG BIT(1) + #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2) + #define USB_R5_ID_DIG_EN_0 BIT(4) + #define USB_R5_ID_DIG_EN_1 BIT(5) + #define USB_R5_ID_DIG_CURR BIT(6) + #define USB_R5_ID_DIG_IRQ BIT(7) + #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8) + #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16) + +/* read-only register */ +#define USB_R6 0x18 + #define USB_R6_P30_CR_DATA_OUT_MASK GENMASK(15, 0) + #define USB_R6_P30_CR_ACK BIT(16) + +struct phy_meson_gxl_usb3_priv { + struct regmap *regmap; +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; +#endif +}; + +static int +phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv) +{ + uint val; + + regmap_read(priv->regmap, USB_R0, &val); + val &= ~USB_R0_U2D_ACT; + regmap_write(priv->regmap, USB_R0, val); + + regmap_read(priv->regmap, USB_R4, &val); + val &= ~USB_R4_P21_SLEEP_M0; + regmap_write(priv->regmap, USB_R4, val); + + return 0; +} + +static int phy_meson_gxl_usb3_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R5, &val); + val |= USB_R5_ID_DIG_EN_0; + val |= USB_R5_ID_DIG_EN_1; + val &= ~USB_R5_ID_DIG_TH_MASK; + val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff); + regmap_write(priv->regmap, USB_R5, val); + + return phy_meson_gxl_usb3_set_host_mode(priv); +} + +static int phy_meson_gxl_usb3_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R5, &val); + val &= ~USB_R5_ID_DIG_EN_0; + val &= ~USB_R5_ID_DIG_EN_1; + regmap_write(priv->regmap, USB_R5, val); + + return 0; +} + +static int phy_meson_gxl_usb3_init(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + uint val; + + regmap_read(priv->regmap, USB_R1, &val); + val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK; + val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20); + regmap_write(priv->regmap, USB_R1, val); + + return 0; +} + +struct phy_ops meson_gxl_usb3_phy_ops = { + .init = phy_meson_gxl_usb3_init, + .power_on = phy_meson_gxl_usb3_power_on, + .power_off = phy_meson_gxl_usb3_power_off, +}; + +int meson_gxl_usb3_phy_probe(struct udevice *dev) +{ + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); + int ret; + + ret = regmap_init_mem(dev, &priv->regmap); + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + pr_err("failed to enable PHY clock\n"); + clk_free(&priv->clk); + return ret; + } +#endif + + return 0; +} + +static const struct udevice_id meson_gxl_usb3_phy_ids[] = { + { .compatible = "amlogic,meson-gxl-usb3-phy" }, + { } +}; + +U_BOOT_DRIVER(meson_gxl_usb3_phy) = { + .name = "meson_gxl_usb3_phy", + .id = UCLASS_PHY, + .of_match = meson_gxl_usb3_phy_ids, + .probe = meson_gxl_usb3_phy_probe, + .ops = &meson_gxl_usb3_phy_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv), +}; -- 2.7.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [U-Boot] [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs 2018-04-11 15:07 ` Neil Armstrong @ 2018-04-11 15:20 ` Marek Vasut -1 siblings, 0 replies; 18+ messages in thread From: Marek Vasut @ 2018-04-11 15:20 UTC (permalink / raw) To: u-boot On 04/11/2018 05:07 PM, Neil Armstrong wrote: > This patchset adds support for USB for the Amlogic Meson GXL SoCs following > the work done for Linux by Martin Blumenstingl at [1] [2] [3]. > > The support consist of : > - A port of dwc3-of-simple from Linux to U-boot > - A change to support more than 2 PHYs in the DWC3 DM driver > - An USB2 PHY Driver and an USB3 PHY Driver > > The DWC3 Controller has up to 4 PHYs connected : > - 2 USB2 PHYs and an USB3 PHY for GXL SoCs > - 3 USB2 PHYs and an USB3 PHY for the GXM SoC Variant > This is enabled by the "usb: host: dwc3: Add support for multiple PHYs" patch. > This patch is based on the "xhci-dwc3: Couple of fixes for USB3 support" > serie from Vignesh R, on the u-boot-usb tree. > > The DWC3 Controller glue is generic enough to use the dwc3-of-simple from Linux > and can be easily ported to U-Boot as a Simple-Bus with Glue-Specific clocks > and Reset lines setup. > > This depends on the recently applied : > - clk: Add get/enable/disable/release for a bulk of clocks at [4] > - reset: Add get/assert/deassert/release for bulk of reset signals at [5] > in order to manage the clocks and resets of the Glue in a clean fashion. > > The USB PHY driver supports the standard generic PHY interface and supports > the power-on/off calls and set the Host mode by default. > They are based on the excellent work from Martin Blumenstingl merged in linux. > > Changes since v2: > - Drop #if and use the empty stubs for clock & reset API > > Changes since v1: > - switch to submitted clk/reset bulk API > - splitted dwc3 multiple phy init error between poweroff & exit > Applied all, thanks. -- Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs @ 2018-04-11 15:20 ` Marek Vasut 0 siblings, 0 replies; 18+ messages in thread From: Marek Vasut @ 2018-04-11 15:20 UTC (permalink / raw) To: linus-amlogic On 04/11/2018 05:07 PM, Neil Armstrong wrote: > This patchset adds support for USB for the Amlogic Meson GXL SoCs following > the work done for Linux by Martin Blumenstingl at [1] [2] [3]. > > The support consist of : > - A port of dwc3-of-simple from Linux to U-boot > - A change to support more than 2 PHYs in the DWC3 DM driver > - An USB2 PHY Driver and an USB3 PHY Driver > > The DWC3 Controller has up to 4 PHYs connected : > - 2 USB2 PHYs and an USB3 PHY for GXL SoCs > - 3 USB2 PHYs and an USB3 PHY for the GXM SoC Variant > This is enabled by the "usb: host: dwc3: Add support for multiple PHYs" patch. > This patch is based on the "xhci-dwc3: Couple of fixes for USB3 support" > serie from Vignesh R, on the u-boot-usb tree. > > The DWC3 Controller glue is generic enough to use the dwc3-of-simple from Linux > and can be easily ported to U-Boot as a Simple-Bus with Glue-Specific clocks > and Reset lines setup. > > This depends on the recently applied : > - clk: Add get/enable/disable/release for a bulk of clocks at [4] > - reset: Add get/assert/deassert/release for bulk of reset signals at [5] > in order to manage the clocks and resets of the Glue in a clean fashion. > > The USB PHY driver supports the standard generic PHY interface and supports > the power-on/off calls and set the Host mode by default. > They are based on the excellent work from Martin Blumenstingl merged in linux. > > Changes since v2: > - Drop #if and use the empty stubs for clock & reset API > > Changes since v1: > - switch to submitted clk/reset bulk API > - splitted dwc3 multiple phy init error between poweroff & exit > Applied all, thanks. -- Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2018-04-12 8:08 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-04-11 15:07 [U-Boot] [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs Neil Armstrong 2018-04-11 15:07 ` Neil Armstrong 2018-04-11 15:08 ` [U-Boot] [PATCH v3 u-boot 1/3] usb: host: Add simple of glue driver for DWC3 USB Controllers integration Neil Armstrong 2018-04-11 15:08 ` Neil Armstrong 2018-04-11 16:17 ` [U-Boot] " Jean-Jacques Hiblot 2018-04-11 16:17 ` Jean-Jacques Hiblot 2018-04-12 8:05 ` Neil Armstrong 2018-04-12 8:05 ` Neil Armstrong 2018-04-12 8:07 ` Ben Dooks 2018-04-12 8:07 ` Ben Dooks 2018-04-12 8:08 ` Neil Armstrong 2018-04-12 8:08 ` Neil Armstrong 2018-04-11 15:08 ` [U-Boot] [PATCH v3 u-boot 2/3] usb: host: dwc3: Add support for multiple PHYs Neil Armstrong 2018-04-11 15:08 ` Neil Armstrong 2018-04-11 15:08 ` [U-Boot] [PATCH v3 u-boot 3/3] phy: Add Amlogic Meson USB2 & USB3 Generic PHY drivers Neil Armstrong 2018-04-11 15:08 ` Neil Armstrong 2018-04-11 15:20 ` [U-Boot] [PATCH v3 u-boot 0/3] Add USB Support for Amlogic Meson GXL SoCs Marek Vasut 2018-04-11 15:20 ` Marek Vasut
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.