diff --git a/patch/kernel/meson64-dev/1000-ARM64-dts-meson-gxl-add-USB-host-support.patch b/patch/kernel/meson64-dev/1000-ARM64-dts-meson-gxl-add-USB-host-support.patch new file mode 100644 index 000000000..c97fd1ddd --- /dev/null +++ b/patch/kernel/meson64-dev/1000-ARM64-dts-meson-gxl-add-USB-host-support.patch @@ -0,0 +1,90 @@ +From 6006726ba262f50d61f3a001cc87fbc82dd8318a Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sun, 20 Nov 2016 00:23:52 +0100 +Subject: [PATCH 73/79] ARM64: dts: meson-gxl: add USB host support + +This adds USB host support to the Meson GXL SoC. A dwc3 controller is +used for host-mode, while a dwc2 controller is used for device-mode only. +The dwc3 controller's internal roothub has two USB2 ports enabled but no +USB3 port. Each of the ports is supplied by a separate PHY. The USB pins +are connected to the SoC's USBHOST_A and USBOTG_B pins. +Due to the way the roothub works internally the USB PHYs are left +enabled. When the dwc3 controller is disabled the PHY is never powered on +so it does not draw any extra power. However, when the dwc3 host +controller is enabled then all PHYs also have to be enabled, otherwise +USB devices will not be detected (regardless of whether they are plugged +into an enabled port or not). This means that only the dwc3 controller +has to be enabled on boards with USB support (instead of requiring all +boards to enable the PHYs additionally with the chance of forgetting to +enable one and breaking all other ports with that as well). + +Signed-off-by: Martin Blumenstingl +Signed-off-by: Neil Armstrong +--- + arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 50 ++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +index 1e65b0f..c33c29f 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +@@ -49,6 +49,56 @@ + + / { + compatible = "amlogic,meson-gxl"; ++ ++ soc { ++ ++ usb0: usb@c9000000 { ++ compatible = "snps,dwc3"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0xc9000000 0x0 0x100000>; ++ interrupts = ; ++ dr_mode = "host"; ++ maximum-speed = "high-speed"; ++ snps,dis_u2_susphy_quirk; ++ status = "disabled"; ++ ++ dwc3_roothub: roothub@0 { ++ compatible = "usb1d6b,3", "usb1d6b,2"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ port@1 { ++ reg = <1>; ++ phys = <&usb2_phy0>; ++ phy-names = "usb2-phy"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ phys = <&usb2_phy1>; ++ phy-names = "usb2-phy"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&apb { ++ usb2_phy0: phy@78000 { ++ compatible = "amlogic,meson-gxl-usb2-phy"; ++ #phy-cells = <0>; ++ reg = <0x0 0x78000 0x0 0x20>; ++ status = "okay"; ++ }; ++ ++ usb2_phy1: phy@78020 { ++ compatible = "amlogic,meson-gxl-usb2-phy"; ++ #phy-cells = <0>; ++ reg = <0x0 0x78020 0x0 0x20>; ++ status = "okay"; ++ }; + }; + + ðmac { +-- +1.9.1 + diff --git a/patch/kernel/meson64-dev/1001-usb-host-add-a-generic-platform-USB-roothub-driver.patch b/patch/kernel/meson64-dev/1001-usb-host-add-a-generic-platform-USB-roothub-driver.patch new file mode 100644 index 000000000..7cfb43b43 --- /dev/null +++ b/patch/kernel/meson64-dev/1001-usb-host-add-a-generic-platform-USB-roothub-driver.patch @@ -0,0 +1,293 @@ +From acfe799c4e00a726cdb0bbd37aaaa123070ed59e Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Tue, 10 Jan 2017 18:59:43 +0100 +Subject: [PATCH 75/79] usb: host: add a generic platform USB roothub driver + +Many SoC platforms have separate devices for the USB PHY which are +registered through the generic PHY framework. These PHYs have to be +enabled to make the USB controller actually work. They also have to be +disabled again on shutdown/suspend. + +Currently (at least) the following HCI platform drivers are using custom +code to obtain all PHYs via devicetree for the roothub/controller and +disable/enable them when required: +- ehci-platform.c has ehci_platform_power_{on,off} +- xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off} +- ohci-platform.c has ohci_platform_power_{on,off} + +These drivers are not using the generic devicetree USB device bindings +yet which were only introduced recently (documentation is available in +devicetree/bindings/usb/usb-device.txt). +With this new driver the usb2-phy and usb3-phy can be specified directly +in the child-node of the corresponding port of the roothub via +devicetree. This can be extended by not just parsing PHYs (some of the +other drivers listed above are for example also parsing a list of clocks +as well) when required. + +Signed-off-by: Martin Blumenstingl +Signed-off-by: Neil Armstrong +--- + .../devicetree/bindings/usb/usb-roothub.txt | 46 +++++++ + drivers/usb/host/Kconfig | 3 + + drivers/usb/host/Makefile | 2 + + drivers/usb/host/platform-roothub.c | 146 +++++++++++++++++++++ + drivers/usb/host/platform-roothub.h | 14 ++ + 5 files changed, 211 insertions(+) + create mode 100644 Documentation/devicetree/bindings/usb/usb-roothub.txt + create mode 100644 drivers/usb/host/platform-roothub.c + create mode 100644 drivers/usb/host/platform-roothub.h + +diff --git a/Documentation/devicetree/bindings/usb/usb-roothub.txt b/Documentation/devicetree/bindings/usb/usb-roothub.txt +new file mode 100644 +index 0000000..23b24b6 +--- /dev/null ++++ b/Documentation/devicetree/bindings/usb/usb-roothub.txt +@@ -0,0 +1,46 @@ ++Generic USB root-hub Properties ++ ++similar to the USB device bindings (documented in usb-device.txt from the ++current directory) this provides support for configuring the root-hub. ++ ++Required properties: ++- compatible: should be at least one of "usb1d6b,3", "usb1d6b,2" ++- reg: must be 0. ++- address-cells: must be 1 ++- size-cells: must be 0 ++ ++Required sub-nodes: ++a sub-node per actual USB port is required. each sub-node supports the ++following properties: ++ Required properties: ++ - reg: the port number on the root-hub (mandatory) ++ Optional properties: ++ - phys: optional, from the *Generic PHY* bindings (mandatory needed ++ when phy-names is given) ++ - phy-names: optional, from the *Generic PHY* bindings; supported names ++ are "usb2-phy" or "usb3-phy" ++ ++Example: ++ &usb1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ roothub@0 { ++ compatible = "usb1d6b,3", "usb1d6b,2"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ port@1 { ++ reg = <1>; ++ usb-phy = <&usb2_phy1>, <&usb3_phy1>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ usb-phy = <&usb2_phy2>, <&usb3_phy2>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ }; ++ }; ++ } +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index ababb91..3f450e0 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -797,6 +797,9 @@ config USB_HCD_SSB + + If unsure, say N. + ++config USB_PLATFORM_ROOTHUB ++ bool ++ + config USB_HCD_TEST_MODE + bool "HCD test mode support" + ---help--- +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index c77b0a3..93f0dd2 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -29,6 +29,8 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ + + obj-$(CONFIG_USB_PCI) += pci-quirks.o + ++obj-$(CONFIG_USB_PLATFORM_ROOTHUB) += platform-roothub.o ++ + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o + obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o + obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o +diff --git a/drivers/usb/host/platform-roothub.c b/drivers/usb/host/platform-roothub.c +new file mode 100644 +index 0000000..84837e4 +--- /dev/null ++++ b/drivers/usb/host/platform-roothub.c +@@ -0,0 +1,146 @@ ++/* ++ * platform roothub driver - a virtual PHY device which passes all phy_* ++ * function calls to multiple (actual) PHY devices. This is comes handy when ++ * initializing all PHYs on a root-hub (to keep them all in the same state). ++ * ++ * Copyright (C) 2017 Martin Blumenstingl ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "platform-roothub.h" ++ ++#define ROOTHUB_PORTNUM 0 ++ ++struct platform_roothub { ++ struct phy *phy; ++ struct list_head list; ++}; ++ ++static struct platform_roothub *platform_roothub_alloc(struct device *dev) ++{ ++ struct platform_roothub *roothub_entry; ++ ++ roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL); ++ if (!roothub_entry) ++ return ERR_PTR(-ENOMEM); ++ ++ INIT_LIST_HEAD(&roothub_entry->list); ++ ++ return roothub_entry; ++} ++ ++static int platform_roothub_add_phy(struct device *dev, ++ struct device_node *port_np, ++ const char *con_id, struct list_head *list) ++{ ++ struct platform_roothub *roothub_entry; ++ struct phy *phy = devm_of_phy_get(dev, port_np, con_id); ++ ++ if (IS_ERR_OR_NULL(phy)) { ++ if (!phy || PTR_ERR(phy) == -ENODEV) ++ return 0; ++ else ++ return PTR_ERR(phy); ++ } ++ ++ roothub_entry = platform_roothub_alloc(dev); ++ if (IS_ERR(roothub_entry)) ++ return PTR_ERR(roothub_entry); ++ ++ roothub_entry->phy = phy; ++ ++ list_add_tail(&roothub_entry->list, list); ++ ++ return 0; ++} ++ ++struct platform_roothub *platform_roothub_init(struct device *dev) ++{ ++ struct device_node *roothub_np, *port_np; ++ struct platform_roothub *plat_roothub; ++ int err; ++ ++ roothub_np = usb_of_get_child_node(dev->of_node, ROOTHUB_PORTNUM); ++ if (!of_device_is_available(roothub_np)) ++ return NULL; ++ ++ plat_roothub = platform_roothub_alloc(dev); ++ if (IS_ERR(plat_roothub)) ++ return plat_roothub; ++ ++ for_each_available_child_of_node(roothub_np, port_np) { ++ err = platform_roothub_add_phy(dev, port_np, "usb2-phy", ++ &plat_roothub->list); ++ if (err) ++ return ERR_PTR(err); ++ ++ err = platform_roothub_add_phy(dev, port_np, "usb3-phy", ++ &plat_roothub->list); ++ if (err) ++ return ERR_PTR(err); ++ } ++ ++ return plat_roothub; ++} ++EXPORT_SYMBOL_GPL(platform_roothub_init); ++ ++int platform_roothub_power_on(struct platform_roothub *plat_roothub) ++{ ++ struct platform_roothub *roothub_entry; ++ struct list_head *head; ++ int err; ++ ++ if (!plat_roothub) ++ return 0; ++ ++ head = &plat_roothub->list; ++ ++ list_for_each_entry(roothub_entry, head, list) { ++ err = phy_init(roothub_entry->phy); ++ if (err) ++ goto err_out; ++ ++ err = phy_power_on(roothub_entry->phy); ++ if (err) { ++ phy_exit(roothub_entry->phy); ++ goto err_out; ++ } ++ } ++ ++ return 0; ++ ++err_out: ++ list_for_each_entry_continue_reverse(roothub_entry, head, list) { ++ phy_power_off(roothub_entry->phy); ++ phy_exit(roothub_entry->phy); ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(platform_roothub_power_on); ++ ++void platform_roothub_power_off(struct platform_roothub *plat_roothub) ++{ ++ struct platform_roothub *roothub_entry; ++ ++ if (!plat_roothub) ++ return; ++ ++ list_for_each_entry_reverse(roothub_entry, &plat_roothub->list, list) { ++ phy_power_off(roothub_entry->phy); ++ phy_exit(roothub_entry->phy); ++ } ++} ++EXPORT_SYMBOL_GPL(platform_roothub_power_off); +diff --git a/drivers/usb/host/platform-roothub.h b/drivers/usb/host/platform-roothub.h +new file mode 100644 +index 0000000..bde0bf2 +--- /dev/null ++++ b/drivers/usb/host/platform-roothub.h +@@ -0,0 +1,14 @@ ++#ifndef USB_HOST_PLATFORM_ROOTHUB_H ++#define USB_HOST_PLATFORM_ROOTHUB_H ++ ++struct phy; ++struct device_node; ++ ++struct platform_roothub; ++ ++struct platform_roothub *platform_roothub_init(struct device *dev); ++ ++int platform_roothub_power_on(struct platform_roothub *plat_roothub); ++void platform_roothub_power_off(struct platform_roothub *plat_roothub); ++ ++#endif /* USB_HOST_PLATFORM_ROOTHUB_H */ +-- +1.9.1 + diff --git a/patch/kernel/meson64-dev/1002-usb-host-xhci-plat-integrate-the-platform-roothub.patch b/patch/kernel/meson64-dev/1002-usb-host-xhci-plat-integrate-the-platform-roothub.patch new file mode 100644 index 000000000..09e4f6af3 --- /dev/null +++ b/patch/kernel/meson64-dev/1002-usb-host-xhci-plat-integrate-the-platform-roothub.patch @@ -0,0 +1,146 @@ +From 9dfd5d48fbcd31b12825e81d532aca76c2b769f8 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Wed, 11 Jan 2017 11:34:59 +0100 +Subject: [PATCH 76/79] usb: host: xhci: plat: integrate the platform-roothub + +This enables the platform-roothub for the xhci-plat driver. This allows +specifying a PHY for each port via devicetree. All PHYs will then be +enabled/disabled by the platform-roothub driver. + +One example where this is required is the Amlogic GXL and GXM SoCs: +They are using a dwc3 USB controller with up to three ports enabled on +the internal roothub. Using only the top-level "phy" properties does not +work here since one can only specify one "usb2-phy" and one "usb3-phy", +while actually at least two "usb2-phy" have to be specified. + +Signed-off-by: Martin Blumenstingl +Signed-off-by: Neil Armstrong +--- + Documentation/devicetree/bindings/usb/usb-xhci.txt | 7 ++++++ + drivers/usb/host/Kconfig | 1 + + drivers/usb/host/xhci-plat.c | 26 +++++++++++++++++++++- + drivers/usb/host/xhci.h | 3 +++ + 4 files changed, 36 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt +index 2d80b60..31b4f68 100644 +--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt +@@ -29,6 +29,13 @@ Optional properties: + - usb3-lpm-capable: determines if platform is USB3 LPM capable + - quirk-broken-port-ped: set if the controller has broken port disable mechanism + ++sub-nodes: ++- optionally there can be a node for the root-hub, see usb-roothub.txt in the ++ current directory ++- one or more nodes with reg 1-31 for each port to which a device is connected. ++ See usb-device.txt in the current directory for more information. ++ ++ + Example: + usb@f0931000 { + compatible = "generic-xhci"; +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 3f450e0..d6279d7 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -36,6 +36,7 @@ config USB_XHCI_PCI + config USB_XHCI_PLATFORM + tristate "Generic xHCI driver for a platform device" + select USB_XHCI_RCAR if ARCH_RENESAS ++ select USB_PLATFORM_ROOTHUB + ---help--- + Adds an xHCI host driver for a generic platform device, which + provides a memory space and an irq. +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index c04144b..4de20b5 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -285,10 +285,20 @@ static int xhci_plat_probe(struct platform_device *pdev) + goto put_usb3_hcd; + } + +- ret = usb_add_hcd(hcd, irq, IRQF_SHARED); ++ xhci->platform_roothub = platform_roothub_init(sysdev); ++ if (IS_ERR(xhci->platform_roothub)) { ++ ret = PTR_ERR(xhci->platform_roothub); ++ goto disable_clk; ++ } ++ ++ ret = platform_roothub_power_on(xhci->platform_roothub); + if (ret) + goto disable_usb_phy; + ++ ret = usb_add_hcd(hcd, irq, IRQF_SHARED); ++ if (ret) ++ goto disable_platform_roothub; ++ + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + +@@ -311,6 +321,9 @@ static int xhci_plat_probe(struct platform_device *pdev) + dealloc_usb2_hcd: + usb_remove_hcd(hcd); + ++disable_platform_roothub: ++ platform_roothub_power_off(xhci->platform_roothub); ++ + disable_usb_phy: + usb_phy_shutdown(hcd->usb_phy); + +@@ -342,6 +355,8 @@ static int xhci_plat_remove(struct platform_device *dev) + usb_remove_hcd(xhci->shared_hcd); + usb_phy_shutdown(hcd->usb_phy); + ++ platform_roothub_power_off(xhci->platform_roothub); ++ + usb_remove_hcd(hcd); + usb_put_hcd(xhci->shared_hcd); + +@@ -374,6 +389,11 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) + if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) + clk_disable_unprepare(xhci->clk); + ++ if (ret) ++ return ret; ++ ++ platform_roothub_power_off(xhci->platform_roothub); ++ + return ret; + } + +@@ -386,6 +406,10 @@ static int __maybe_unused xhci_plat_resume(struct device *dev) + if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) + clk_prepare_enable(xhci->clk); + ++ ret = platform_roothub_power_on(xhci->platform_roothub); ++ if (ret) ++ return ret; ++ + ret = xhci_priv_resume_quirk(hcd); + if (ret) + return ret; +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 73a28a9..7f3d15e 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -34,6 +34,8 @@ + #include "xhci-ext-caps.h" + #include "pci-quirks.h" + ++#include "platform-roothub.h" ++ + /* xHCI PCI Configuration Registers */ + #define XHCI_SBRN_OFFSET (0x60) + +@@ -1725,6 +1727,7 @@ struct xhci_hcd { + int msix_count; + /* optional clock */ + struct clk *clk; ++ struct platform_roothub *platform_roothub; + /* data structures */ + struct xhci_device_context_array *dcbaa; + struct xhci_ring *cmd_ring; +-- +1.9.1 + diff --git a/patch/kernel/meson64-dev/1003-ARM64-dts-meson-gx-Enable-USB-on-GXL-and-GXM-boards.patch b/patch/kernel/meson64-dev/1003-ARM64-dts-meson-gx-Enable-USB-on-GXL-and-GXM-boards.patch new file mode 100644 index 000000000..600e80f2c --- /dev/null +++ b/patch/kernel/meson64-dev/1003-ARM64-dts-meson-gx-Enable-USB-on-GXL-and-GXM-boards.patch @@ -0,0 +1,64 @@ +From 7079f88717e54f9ea48c1cbfba09b53cc8b9aefd Mon Sep 17 00:00:00 2001 +From: Neil Armstrong +Date: Thu, 13 Jul 2017 15:02:33 +0200 +Subject: [PATCH 77/79] ARM64: dts: meson-gx: Enable USB on GXL and GXM boards + +Signed-off-by: Neil Armstrong +--- + arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 4 ++++ + arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts | 4 ++++ + arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi | 4 ++++ + arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 4 ++++ + 4 files changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi +index 54718ee..bf49f6f 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi +@@ -234,3 +234,7 @@ + remote-endpoint = <&hdmi_connector_in>; + }; + }; ++ ++&usb0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts +index 55ec11a..19bb39b 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts +@@ -249,3 +249,7 @@ + remote-endpoint = <&hdmi_connector_in>; + }; + }; ++ ++&usb0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi +index f3eea8e..a07c34d 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi +@@ -171,3 +171,7 @@ + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; + }; ++ ++&usb0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts +index 3a327dd..1b7038d 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts +@@ -215,3 +215,7 @@ + remote-endpoint = <&hdmi_connector_in>; + }; + }; ++ ++&usb0 { ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/patch/kernel/meson64-dev/1004-phy-meson-add-USB2-PHY-support-for-Meson-GXL-and-GXM.patch b/patch/kernel/meson64-dev/1004-phy-meson-add-USB2-PHY-support-for-Meson-GXL-and-GXM.patch new file mode 100644 index 000000000..504a0d77d --- /dev/null +++ b/patch/kernel/meson64-dev/1004-phy-meson-add-USB2-PHY-support-for-Meson-GXL-and-GXM.patch @@ -0,0 +1,325 @@ +From c7975e835ec6c8dea399b649597f6fe8461214cb Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 1 Apr 2017 11:18:30 +0200 +Subject: [PATCH 79/79] phy: meson: add USB2 PHY support for Meson GXL and GXM + +This adds a new driver for the USB2 PHYs found on Meson GXL and GXM SoCs +(both SoCs are using the same USB PHY register layout). + +The USB2 PHY is a simple PHY which only has a few registers to configure +the mode (host/device) and a reset register (to enable/disable the PHY). + +Unfortunately there are no datasheets available for this PHY. The driver +was written by reading the code from Amlogic's GPL kernel sources and +by analyzing the registers on an actual GXL and GXM device running the +kernel that was shipped on the boards I have. + +Signed-off-by: Martin Blumenstingl +Signed-off-by: Neil Armstrong +--- + drivers/phy/Kconfig | 12 ++ + drivers/phy/Makefile | 1 + + drivers/phy/phy-meson-gxl-usb2.c | 261 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 274 insertions(+) + create mode 100644 drivers/phy/phy-meson-gxl-usb2.c + +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index afaf7b6..27189e2 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -530,4 +530,16 @@ config PHY_MESON8B_USB2 + and GXBB SoCs. + If unsure, say N. + ++config PHY_MESON_GXL_USB ++ tristate "Meson GXL and GXM USB2 PHY drivers" ++ default ARCH_MESON ++ depends on OF && (ARCH_MESON || COMPILE_TEST) ++ depends on USB_SUPPORT ++ select GENERIC_PHY ++ select REGMAP_MMIO ++ help ++ Enable this to support the Meson USB2 PHYs found in Meson ++ GXL and GXM SoCs. ++ If unsure, say N. ++ + endmenu +diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile +index f8047b4..bea10c6 100644 +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -64,3 +64,4 @@ obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o + obj-$(CONFIG_ARCH_TEGRA) += tegra/ + obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o + obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o ++obj-$(CONFIG_PHY_MESON_GXL_USB) += phy-meson-gxl-usb2.o +diff --git a/drivers/phy/phy-meson-gxl-usb2.c b/drivers/phy/phy-meson-gxl-usb2.c +new file mode 100644 +index 0000000..f5fbd3c +--- /dev/null ++++ b/drivers/phy/phy-meson-gxl-usb2.c +@@ -0,0 +1,261 @@ ++/* ++ * Meson GXL and GXM USB2 PHY driver ++ * ++ * Copyright (C) 2017 Martin Blumenstingl ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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_DATA_IN_MASK GENMASK(3, 0) ++ #define U2P_R2_DATA_IN_EN_MASK GENMASK(7, 4) ++ #define U2P_R2_ADDR_MASK GENMASK(11, 8) ++ #define U2P_R2_DATA_OUT_SEL BIT(12) ++ #define U2P_R2_CLK BIT(13) ++ #define U2P_R2_DATA_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; ++ enum phy_mode mode; ++ int is_enabled; ++}; ++ ++static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = { ++ .reg_bits = 8, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = U2P_R3, ++}; ++ ++static int phy_meson_gxl_usb2_reset(struct phy *phy) ++{ ++ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); ++ ++ if (!priv->is_enabled) ++ return 0; ++ ++ /* reset the PHY and wait until settings are stabilized */ ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, ++ U2P_R0_POWER_ON_RESET); ++ udelay(RESET_COMPLETE_TIME); ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); ++ udelay(RESET_COMPLETE_TIME); ++ ++ return 0; ++} ++ ++static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode) ++{ ++ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); ++ ++ switch (mode) { ++ case PHY_MODE_USB_HOST: ++ case PHY_MODE_USB_OTG: ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN, ++ U2P_R0_DM_PULLDOWN); ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN, ++ U2P_R0_DP_PULLDOWN); ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0); ++ break; ++ ++ case PHY_MODE_USB_DEVICE: ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN, ++ 0); ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN, ++ 0); ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, ++ U2P_R0_ID_PULLUP); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ phy_meson_gxl_usb2_reset(phy); ++ ++ priv->mode = mode; ++ ++ return 0; ++} ++ ++static int phy_meson_gxl_usb2_power_off(struct phy *phy) ++{ ++ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); ++ ++ priv->is_enabled = 0; ++ ++ /* power off the PHY by putting it into reset mode */ ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, ++ U2P_R0_POWER_ON_RESET); ++ ++ return 0; ++} ++ ++static int phy_meson_gxl_usb2_power_on(struct phy *phy) ++{ ++ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); ++ int ret; ++ ++ priv->is_enabled = 1; ++ ++ /* power on the PHY by taking it out of reset mode */ ++ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); ++ ++ ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode); ++ if (ret) { ++ phy_meson_gxl_usb2_power_off(phy); ++ ++ dev_err(&phy->dev, "Failed to initialize PHY with mode %d\n", ++ priv->mode); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct phy_ops phy_meson_gxl_usb2_ops = { ++ .power_on = phy_meson_gxl_usb2_power_on, ++ .power_off = phy_meson_gxl_usb2_power_off, ++ .set_mode = phy_meson_gxl_usb2_set_mode, ++ .reset = phy_meson_gxl_usb2_reset, ++ .owner = THIS_MODULE, ++}; ++ ++static int phy_meson_gxl_usb2_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ struct phy_meson_gxl_usb2_priv *priv; ++ struct phy *phy; ++ void __iomem *base; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, priv); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->mode = PHY_MODE_USB_HOST; ++ ++ priv->regmap = devm_regmap_init_mmio(dev, base, ++ &phy_meson_gxl_usb2_regmap_conf); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_ops); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(phy); ++ } ++ ++ phy_set_drvdata(phy, priv); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id phy_meson_gxl_usb2_of_match[] = { ++ { .compatible = "amlogic,meson-gxl-usb2-phy", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, phy_meson_gxl_usb2_of_match); ++ ++static struct platform_driver phy_meson_gxl_usb2_driver = { ++ .probe = phy_meson_gxl_usb2_probe, ++ .driver = { ++ .name = "phy-meson-gxl-usb2", ++ .of_match_table = phy_meson_gxl_usb2_of_match, ++ }, ++}; ++module_platform_driver(phy_meson_gxl_usb2_driver); ++ ++MODULE_AUTHOR("Martin Blumenstingl "); ++MODULE_DESCRIPTION("Meson GXL and GXM USB2 PHY driver"); ++MODULE_LICENSE("GPL v2"); +-- +1.9.1 + diff --git a/patch/kernel/meson64-dev/1005_USB_Adjust_for_4.13.patch b/patch/kernel/meson64-dev/1005_USB_Adjust_for_4.13.patch new file mode 100644 index 000000000..aff63c948 --- /dev/null +++ b/patch/kernel/meson64-dev/1005_USB_Adjust_for_4.13.patch @@ -0,0 +1,28 @@ +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts +index 3f0d83b..7590383 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts +@@ -129,6 +129,10 @@ + }; + }; + ++&usb0 { ++ status = "okay"; ++}; ++ + /* SD card */ + &sd_emmc_b { + status = "okay"; +diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile +index f252201..10b2165 100644 +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -7,7 +7,7 @@ obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o + obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o + obj-$(CONFIG_PHY_XGENE) += phy-xgene.o + obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o +- ++obj-$(CONFIG_PHY_MESON_GXL_USB) += phy-meson-gxl-usb2.o + obj-$(CONFIG_ARCH_SUNXI) += allwinner/ + obj-$(CONFIG_ARCH_MESON) += amlogic/ + obj-$(CONFIG_ARCH_RENESAS) += renesas/