diff options
| author | Tom Rini <[email protected]> | 2026-08-09 13:50:27 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-08-09 13:50:27 -0600 |
| commit | 28515d7ff5285e0b942f15577e3198f15c667a25 (patch) | |
| tree | 58fa57dff52f8c7ecb0e7a13c454b853af5f5419 | |
| parent | 9167d2079afecfa5881bad8665a2a4636061e3f4 (diff) | |
| parent | 08b77aac333cb437df57a7f746fa712042ccde61 (diff) | |
Merge branch 'main' of https://git.u-boot-project.org/u-boot/custodians/u-boot-usb
- MTU3 DT bindings alignment with Linux DT bindings.
| -rw-r--r-- | arch/arm/dts/mt8183-pumpkin.dts | 4 | ||||
| -rw-r--r-- | arch/arm/dts/mt8183.dtsi | 17 | ||||
| -rw-r--r-- | arch/arm/dts/mt8512-bm1-emmc.dts | 6 | ||||
| -rw-r--r-- | arch/arm/dts/mt8512.dtsi | 19 | ||||
| -rw-r--r-- | doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt | 46 | ||||
| -rw-r--r-- | doc/device-tree-bindings/usb/mediatek,mtu3.txt | 79 | ||||
| -rw-r--r-- | drivers/Makefile | 3 | ||||
| -rw-r--r-- | drivers/usb/mtu3/Kconfig | 39 | ||||
| -rw-r--r-- | drivers/usb/mtu3/Makefile | 10 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3.h | 12 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_core.c | 4 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_dr.h | 4 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_host.c | 11 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_hw_regs.h | 11 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_plat.c | 227 |
15 files changed, 240 insertions, 252 deletions
diff --git a/arch/arm/dts/mt8183-pumpkin.dts b/arch/arm/dts/mt8183-pumpkin.dts index 470a7693997..623561b6a63 100644 --- a/arch/arm/dts/mt8183-pumpkin.dts +++ b/arch/arm/dts/mt8183-pumpkin.dts @@ -88,10 +88,6 @@ }; &usb { - status = "okay"; -}; - -&ssusb { mediatek,force-vbus; maximum-speed = "high-speed"; dr_mode = "peripheral"; diff --git a/arch/arm/dts/mt8183.dtsi b/arch/arm/dts/mt8183.dtsi index 294aa2b8979..323a88a7ac9 100644 --- a/arch/arm/dts/mt8183.dtsi +++ b/arch/arm/dts/mt8183.dtsi @@ -236,9 +236,9 @@ }; }; - usb: usb@11200000 { + usb: usb@11201000 { compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3"; - reg = <0 0x11200000 0 0x3e00>, + reg = <0 0x11201000 0 0x2e00>, <0 0x11203e00 0 0x0100>; reg-names = "mac", "ippc"; interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>; @@ -251,16 +251,9 @@ ranges; status = "disabled"; - ssusb: ssusb@11200000 { - compatible = "mediatek,ssusb"; - reg = <0 0x11200000 0 0x3e00>; - reg-names = "mac"; - interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>; - status = "disabled"; - }; - - usb_host: xhci@11200000 { - compatible = "mediatek,mtk-xhci"; + usb_host: usb@11200000 { + compatible = "mediatek,mt8183-xhci", + "mediatek,mtk-xhci"; reg = <0 0x11200000 0 0x1000>; reg-names = "mac"; interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>; diff --git a/arch/arm/dts/mt8512-bm1-emmc.dts b/arch/arm/dts/mt8512-bm1-emmc.dts index 12511b5fed4..13d3f804cb4 100644 --- a/arch/arm/dts/mt8512-bm1-emmc.dts +++ b/arch/arm/dts/mt8512-bm1-emmc.dts @@ -114,13 +114,9 @@ }; }; -&ssusb { +&usb3 { dr_mode = "peripheral"; maximum-speed = "high-speed"; - status = "okay"; -}; - -&usb3 { vbus-supply = <&usb_p0_vbus>; status = "okay"; }; diff --git a/arch/arm/dts/mt8512.dtsi b/arch/arm/dts/mt8512.dtsi index bdb84f8ef00..eb0a09826f9 100644 --- a/arch/arm/dts/mt8512.dtsi +++ b/arch/arm/dts/mt8512.dtsi @@ -101,27 +101,18 @@ status = "disabled"; }; - usb3: usb@11213e00 { + usb3: usb@11211000 { compatible = "mediatek,mt8512-mtu3", "mediatek,mtu3"; - reg = <0x11213e00 0x0100>; - reg-names = "ippc"; + reg = <0x11211000 0x2e00>, + <0x11213e00 0x0100>; + reg-names = "mac", "ippc"; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_LOW>; phys = <&u2port0 PHY_TYPE_USB2>, <&u2port1 PHY_TYPE_USB2>; clocks = <&infracfg CLK_INFRA_USB_SYS>, <&topckgen CLK_TOP_SSUSB_TOP_CK_EN>, <&infracfg CLK_INFRA_ICUSB>; clock-names = "sys_ck", "ref_ck", "mcu_ck"; - #address-cells = <1>; - #size-cells = <1>; - ranges; status = "disabled"; - - ssusb: usb@11210000 { - compatible = "mediatek,ssusb"; - reg = <0x11210000 0x3e00>; - interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_LOW>; - reg-names = "mac"; - status = "disabled"; - }; }; u3phy: usb-phy@11cc0000 { diff --git a/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt b/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt deleted file mode 100644 index e26e9618eb9..00000000000 --- a/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt +++ /dev/null @@ -1,46 +0,0 @@ -MediaTek xHCI - -The device node for USB3 host controller on MediaTek SoCs. - -Required properties: - - compatible : should be one of - "mediatek,mtk-xhci" - "mediatek,mt8195-xhci" - - reg : specifies physical base address and size of the registers - - reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control - - power-domains : a phandle to USB power domain node to control USB's - MTCMOS - - vusb33-supply : regulator of USB avdd3.3v - - - clocks : a list of phandle + clock-specifier pairs, one for each - entry in clock-names - - clock-names : must contain - "sys_ck": controller clock used by normal mode, - the following ones are optional: - "ref_ck": reference clock used by low power mode etc, - "mcu_ck": mcu_bus clock for register access, - "dma_ck": dma_bus clock for data transfer by DMA, - "xhci_ck": controller clock - - - phys : list of all the USB PHYs on this HCD - - phy-names: name specifier for the USB PHY - -Optional properties: - - vbus-supply : reference to the VBUS regulator; - - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, - bit1 for u3port1, ... etc; - - mediatek,u2p-dis-msk : mask to disable u2ports, bit0 for u2port0, - bit1 for u2port1, ... etc; - -Example: -xhci: usb@1a0c0000 { - compatible = "mediatek,mt7629-xhci", "mediatek,mtk-xhci"; - reg = <0x1a0c0000 0x1000>, <0x1a0c3e00 0x0100>; - reg-names = "mac", "ippc"; - power-domains = <&scpsys MT7629_POWER_DOMAIN_HIF1>; - clocks = <&ssusbsys CLK_SSUSB_SYS_EN>, <&ssusbsys CLK_SSUSB_REF_EN>, - <&ssusbsys CLK_SSUSB_MCU_EN>, <&ssusbsys CLK_SSUSB_DMA_EN>; - clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck"; - phys = <&u2port0 PHY_TYPE_USB2>, <&u3port0 PHY_TYPE_USB3>; - status = "disabled"; -}; diff --git a/doc/device-tree-bindings/usb/mediatek,mtu3.txt b/doc/device-tree-bindings/usb/mediatek,mtu3.txt deleted file mode 100644 index ab877bfa89f..00000000000 --- a/doc/device-tree-bindings/usb/mediatek,mtu3.txt +++ /dev/null @@ -1,79 +0,0 @@ -The device node for Mediatek USB3 DRD controller - -Required properties: - - compatible : should be "mediatek,<soc-model>-mtu3", "mediatek,mtu3", - soc-model is the name of SoC, such as mt8512 etc, - when using "mediatek,mtu3" compatible string, you need SoC specific - ones in addition, one of: - - "mediatek,mt8512-mtu3" - - reg : specifies physical base address and size of the registers - - reg-names: should be - - "ippc" : IP Port Control - - power-domains : a phandle to USB power domain node to control USB's MTCMOS - - clocks : a list of phandle + clock-specifier pairs, one for each - entry in clock-names - - clock-names : must contain "sys_ck" for clock of controller, - the following clocks are optional: - "ref_ck", "mcu_ck", "dma_ck" and "xhci_ck"; - - phys : list of all the USB PHYs on this HCD - - #address-cells, #size-cells : used for sub-nodes with 'reg' property - - ranges : allows valid 1:1 translation between child's address space and - parent's address space - -Optional properties: - - vusb33-supply : regulator of USB AVDD3.3v - - vbus-supply : regulator of VBUS 5v, needed when supports host mode. - -Sub-nodes: -Required properties: - - compatible : should be "mediatek,ssusb" - - reg : specifies physical base address and size of the registers - - reg-names: should be - - "mac" : SSUSB MAC, include xHCI and device - - interrupts : interrupt used by xHCI or device - - dr_mode : should be one of "host" or "peripheral", - see : usb/generic.txt - -Optional properties: - - pinctrl-names : a pinctrl state named "default" is optional - - pinctrl-0 : pin control group - See: pinctrl/pinctrl-bindings.txt - - - device mode: - - maximum-speed : valid arguments are "full-speed", "high-speed", - "super-speed" and "super-speed-plus", - see: usb/generic.txt - - mediatek,force-vbus : force vbus as valid by SW - - - host mode (dr_mode is "host"): - - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, - bit1 for u3port1, ... etc; - -Example: -usb3: usb@11213e00 { - compatible = "mediatek,mt8512-mtu3", "mediatek,mtu3"; - reg = <0x11213e00 0x0100>; - reg-names = "ippc"; - phys = <&u2port0 PHY_TYPE_USB2>, <&u2port1 PHY_TYPE_USB2>; - power-domains = <&scpsys MT8512_POWER_DOMAIN_USB>; - clocks = <&infracfg CLK_INFRA_USB_SYS>, - <&topckgen CLK_TOP_SSUSB_TOP_CK_EN>, - <&infracfg CLK_INFRA_ICUSB>; - clock-names = "sys_ck", "ref_ck", "mcu_ck"; - vusb33-supply = <reg_3p3v>; - vbus-supply = <&usb_p0_vbus>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - status = "disabled"; - - ssusb: usb@11210000 { - compatible = "mediatek,ssusb"; - reg = <0x11210000 0x3e00>; - interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_LOW>; - reg-names = "mac"; - dr_mode = "peripheral"; - maximum-speed = "high-speed"; - status = "disabled"; - }; -}; diff --git a/drivers/Makefile b/drivers/Makefile index 43d0ba33281..4c7ba741acb 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -66,7 +66,8 @@ obj-$(CONFIG_DRAM_SUN20I_D1) += ram/ obj-$(CONFIG_SPL_DM_RESET) += reset/ obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/ obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/ -obj-$(CONFIG_SPL_USB_GADGET) += usb/common/ +obj-$(CONFIG_SPL_DM_USB) += usb/common/ +obj-$(CONFIG_SPL_USB_MTU3) += usb/mtu3/ obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/udc/ obj-$(CONFIG_SPL_WATCHDOG) += watchdog/ obj-$(CONFIG_SPL_USB_HOST) += usb/host/ diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 5ec498ec953..8623adfdf51 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -42,3 +42,42 @@ config USB_MTU3_DEBUG Say Y here to enable debugging messages in the MTU3 Driver. endif + +config SPL_USB_MTU3 + bool "MediaTek USB3 controller support in SPL" + depends on ARCH_MEDIATEK + depends on SPL_DM_USB + depends on SPL_USB_HOST || (SPL_DM_USB_GADGET && SPL_USB_GADGET) + help + Enable the MediaTek USB3 controller in SPL. Select host or peripheral + mode below. + +if SPL_USB_MTU3 + +choice + bool "MTU3 SPL Mode Selection" + default SPL_USB_MTU3_GADGET if SPL_USB_GADGET + default SPL_USB_MTU3_HOST if (SPL_USB_HOST && !SPL_USB_GADGET) + help + Select whether the MTU3 controller operates as an xHCI host or a USB + peripheral in SPL. + +config SPL_USB_MTU3_HOST + bool "Host mode in SPL" + depends on SPL_USB_HOST && USB_XHCI_HCD + select SPL_OF_TRANSLATE + help + Enable the MTU3 xHCI host controller in SPL so USB devices can be + accessed before U-Boot proper starts. + +config SPL_USB_MTU3_GADGET + bool "Gadget mode in SPL" + depends on SPL_DM_USB_GADGET && SPL_USB_GADGET + select USB_GADGET_DUALSPEED + help + Enable the MTU3 peripheral controller in SPL so USB gadget + functions can use it before U-Boot proper starts. + +endchoice + +endif diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile index 234f3a380a3..d1f0cd24875 100644 --- a/drivers/usb/mtu3/Makefile +++ b/drivers/usb/mtu3/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 -ccflags-$(CONFIG_USB_MTU3_DEBUG) += -DDEBUG +ccflags-$(CONFIG_$(PHASE_)USB_MTU3_DEBUG) += -DDEBUG -obj-$(CONFIG_USB_MTU3) += mtu3.o +obj-$(CONFIG_$(PHASE_)USB_MTU3) += mtu3.o mtu3-y := mtu3_plat.o -obj-$(CONFIG_USB_MTU3_GADGET) += mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o -obj-$(CONFIG_USB_MTU3_GADGET) += mtu3_qmu.o -obj-$(CONFIG_USB_MTU3_HOST) += mtu3_host.o +obj-$(CONFIG_$(PHASE_)USB_MTU3_GADGET) += mtu3_core.o mtu3_gadget_ep0.o +obj-$(CONFIG_$(PHASE_)USB_MTU3_GADGET) += mtu3_gadget.o mtu3_qmu.o +obj-$(CONFIG_$(PHASE_)USB_MTU3_HOST) += mtu3_host.o diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index c812cd6fdcf..5e35e4754cd 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -137,15 +137,13 @@ enum mtu3_dr_force_mode { }; /** - * @mac_base: register base address of MAC, include xHCI and device + * @mac_base: register base address of the device MAC * @ippc_base: register base address of IP Power and Clock interface (IPPC) * @vusb33_supply: usb3.3V shared by device/host IP * @vbus_supply: vbus 5v of OTG port * @clks: optional clocks, include "sys_ck", "ref_ck", "mcu_ck", * "dma_ck" and "xhci_ck" * @phys: phys used - * @dr_mode: works in which mode: - * host only, device only or dual-role mode */ struct ssusb_mtk { struct udevice *dev; @@ -158,13 +156,14 @@ struct ssusb_mtk { struct udevice *vbus_supply; struct clk_bulk clks; struct phy_bulk phys; - /* otg */ - enum usb_dr_mode dr_mode; }; /** * @ctrl: xHCI controller, needs to come first in this struct! * @hcd: xHCI's register base address + * @vusb33_supply: regulator from the xHCI child node + * @vbus_supply: regulator from the xHCI child node or its MTU3 parent + * @clks: clocks from the xHCI child node * @u2_ports: number of usb2 host ports * @u3_ports: number of usb3 host ports * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to @@ -176,6 +175,9 @@ struct mtu3_host { void __iomem *ippc_base; struct ssusb_mtk *ssusb; struct udevice *dev; + struct udevice *vusb33_supply; + struct udevice *vbus_supply; + struct clk_bulk clks; u32 u2_ports; u32 u3_ports; u32 u3p_dis_msk; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index d9df55ac5fe..f296a72cf18 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -842,8 +842,8 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) mtu->ippc_base = ssusb->ippc_base; mtu->mac_base = ssusb->mac_base; mtu->ssusb = ssusb; - mtu->max_speed = usb_get_maximum_speed(dev_ofnode(dev)); - mtu->force_vbus = dev_read_bool(dev, "mediatek,force-vbus"); + mtu->max_speed = usb_get_maximum_speed(dev_ofnode(ssusb->dev)); + mtu->force_vbus = dev_read_bool(ssusb->dev, "mediatek,force-vbus"); ret = mtu3_hw_init(mtu); if (ret) { diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h index ec0e50c04ca..89fbde03625 100644 --- a/drivers/usb/mtu3/mtu3_dr.h +++ b/drivers/usb/mtu3/mtu3_dr.h @@ -10,7 +10,7 @@ #ifndef _MTU3_DR_H_ #define _MTU3_DR_H_ -#if IS_ENABLED(CONFIG_USB_MTU3_HOST) +#if CONFIG_IS_ENABLED(USB_MTU3_HOST) int ssusb_host_init(struct ssusb_mtk *ssusb); void ssusb_host_exit(struct ssusb_mtk *ssusb); @@ -27,7 +27,7 @@ static inline void ssusb_host_exit(struct ssusb_mtk *ssusb) #endif -#if IS_ENABLED(CONFIG_USB_MTU3_GADGET) +#if CONFIG_IS_ENABLED(USB_MTU3_GADGET) int ssusb_gadget_init(struct ssusb_mtk *ssusb); void ssusb_gadget_exit(struct ssusb_mtk *ssusb); irqreturn_t mtu3_irq(int irq, void *data); diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index 8001fc2d9bd..f1675065c54 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -110,11 +110,11 @@ int ssusb_host_init(struct ssusb_mtk *ssusb) int ret; u3h->ssusb = ssusb; - u3h->hcd = ssusb->mac_base; u3h->ippc_base = ssusb->ippc_base; /* optional property, ignore the error */ - dev_read_u32(dev, "mediatek,u3p-dis-msk", &u3h->u3p_dis_msk); + dev_read_u32(ssusb->dev, "mediatek,u3p-dis-msk", + &u3h->u3p_dis_msk); host_ports_num_get(u3h); ret = ssusb_host_enable(u3h); @@ -123,12 +123,6 @@ int ssusb_host_init(struct ssusb_mtk *ssusb) ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); - ret = regulator_set_enable(ssusb->vbus_supply, true); - if (ret < 0 && ret != -ENOSYS) { - dev_err(dev, "failed to enable vbus %d!\n", ret); - return ret; - } - dev_info(dev, "%s done...\n", __func__); return 0; @@ -136,6 +130,5 @@ int ssusb_host_init(struct ssusb_mtk *ssusb) void ssusb_host_exit(struct ssusb_mtk *ssusb) { - regulator_set_enable(ssusb->vbus_supply, false); ssusb_host_disable(ssusb->u3h); } diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index 9c2a7e1f466..2ac72953e34 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -11,12 +11,11 @@ #define _SSUSB_HW_REGS_H_ /* segment offset of MAC register */ -#define SSUSB_XCHI_BASE 0x0000 -#define SSUSB_DEV_BASE 0x1000 -#define SSUSB_EPCTL_CSR_BASE 0x1800 -#define SSUSB_USB3_MAC_CSR_BASE 0x2400 -#define SSUSB_USB3_SYS_CSR_BASE 0x2400 -#define SSUSB_USB2_CSR_BASE 0x3400 +#define SSUSB_DEV_BASE 0x0000 +#define SSUSB_EPCTL_CSR_BASE 0x0800 +#define SSUSB_USB3_MAC_CSR_BASE 0x1400 +#define SSUSB_USB3_SYS_CSR_BASE 0x1400 +#define SSUSB_USB2_CSR_BASE 0x2400 /* IPPC register in Infra */ #define SSUSB_SIFSLV_IPPC_BASE 0x0000 diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 26fee141f6e..73107167ada 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -135,7 +135,6 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) static int get_ssusb_rscs(struct udevice *dev, struct ssusb_mtk *ssusb) { - struct udevice *child; int ret; ret = device_get_supply_regulator(dev, "vusb33-supply", @@ -154,37 +153,20 @@ static int get_ssusb_rscs(struct udevice *dev, struct ssusb_mtk *ssusb) return ret; } - ssusb->ippc_base = devfdt_remap_addr_name(dev, "ippc"); + ssusb->ippc_base = dev_remap_addr_name(dev, "ippc"); if (!ssusb->ippc_base) { dev_err(dev, "error mapping memory for ippc\n"); return -ENODEV; } - ret = device_find_first_child(dev, &child); - if (ret || !child) { - dev_err(dev, "failed to get child %d!\n", ret); - return ret; - } - - ssusb->mac_base = devfdt_remap_addr_name(child, "mac"); + ssusb->mac_base = dev_remap_addr_name(dev, "mac"); if (!ssusb->mac_base) { dev_err(dev, "error mapping memory for mac\n"); return -ENODEV; } - ssusb->dr_mode = usb_get_dr_mode(dev_ofnode(child)); - - if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN || - ssusb->dr_mode == USB_DR_MODE_OTG) - ssusb->dr_mode = USB_DR_MODE_PERIPHERAL; - - if (IS_ENABLED(CONFIG_USB_MTU3_GADGET)) - ssusb->dr_mode = USB_DR_MODE_PERIPHERAL; - else if (IS_ENABLED(CONFIG_USB_MTU3_HOST)) - ssusb->dr_mode = USB_DR_MODE_HOST; - - dev_info(dev, "dr_mode: %d, ippc: 0x%p, mac: 0x%p\n", - ssusb->dr_mode, ssusb->ippc_base, ssusb->mac_base); + dev_info(dev, "ippc: 0x%p, mac: 0x%p\n", + ssusb->ippc_base, ssusb->mac_base); return 0; } @@ -217,11 +199,6 @@ static int mtu3_remove(struct udevice *dev) return 0; } -static const struct udevice_id ssusb_of_match[] = { - {.compatible = "mediatek,ssusb",}, - {}, -}; - #if CONFIG_IS_ENABLED(DM_USB_GADGET) static int mtu3_gadget_probe(struct udevice *dev) { @@ -257,16 +234,90 @@ static const struct usb_gadget_generic_ops mtu3_gadget_ops = { U_BOOT_DRIVER(mtu3_peripheral) = { .name = "mtu3-peripheral", .id = UCLASS_USB_GADGET_GENERIC, - .of_match = ssusb_of_match, .ops = &mtu3_gadget_ops, .probe = mtu3_gadget_probe, .remove = mtu3_gadget_remove, .priv_auto = sizeof(struct mtu3), }; + +static int mtu3_bind_gadget(struct udevice *parent) +{ + struct udevice *dev; + int ret; + + /* Node-less device: name it after the controller for diagnostics. */ + ret = device_bind_driver(parent, "mtu3-peripheral", + ofnode_get_name(dev_ofnode(parent)), &dev); + if (ret) + dev_err(parent, "failed to bind peripheral mode: %d\n", ret); + + return ret; +} +#else +static int mtu3_bind_gadget(struct udevice *parent) +{ + return -ENODEV; +} #endif #if defined(CONFIG_SPL_USB_HOST) || \ (!defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_HOST)) +static int mtu3_host_rscs_init(struct mtu3_host *u3h) +{ + struct ssusb_mtk *ssusb = u3h->ssusb; + int ret; + + ret = clk_get_bulk(u3h->dev, &u3h->clks); + if (ret) { + dev_err(u3h->dev, "failed to get clocks %d!\n", ret); + return ret; + } + + ret = device_get_supply_regulator(u3h->dev, "vusb33-supply", + &u3h->vusb33_supply); + if (ret) + dev_dbg(u3h->dev, "can't get optional vusb33 %d\n", ret); + + ret = device_get_supply_regulator(u3h->dev, "vbus-supply", + &u3h->vbus_supply); + if (ret) { + dev_dbg(u3h->dev, "can't get optional vbus regulator %d\n", + ret); + u3h->vbus_supply = ssusb->vbus_supply; + } + + ret = regulator_set_enable_if_allowed(u3h->vusb33_supply, true); + if (ret && ret != -ENOSYS) { + dev_err(u3h->dev, "failed to enable vusb33 %d!\n", ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(u3h->vbus_supply, true); + if (ret && ret != -ENOSYS) { + dev_err(u3h->dev, "failed to enable vbus %d!\n", ret); + goto vbus_err; + } + + ret = clk_enable_bulk(&u3h->clks); + if (ret) + goto clks_err; + + return 0; + +clks_err: + regulator_set_enable_if_allowed(u3h->vbus_supply, false); +vbus_err: + regulator_set_enable_if_allowed(u3h->vusb33_supply, false); + return ret; +} + +static void mtu3_host_rscs_exit(struct mtu3_host *u3h) +{ + clk_disable_bulk(&u3h->clks); + regulator_set_enable_if_allowed(u3h->vbus_supply, false); + regulator_set_enable_if_allowed(u3h->vusb33_supply, false); +} + static int mtu3_host_probe(struct udevice *dev) { struct ssusb_mtk *ssusb = dev_to_ssusb(dev->parent); @@ -276,15 +327,36 @@ static int mtu3_host_probe(struct udevice *dev) u3h->dev = dev; ssusb->u3h = u3h; - rc = ssusb_host_init(ssusb); + u3h->ssusb = ssusb; + u3h->hcd = dev_remap_addr_name(dev, "mac"); + if (!u3h->hcd) { + dev_err(dev, "error mapping memory for xHCI mac\n"); + return -ENODEV; + } + + rc = mtu3_host_rscs_init(u3h); if (rc) return rc; + rc = ssusb_host_init(ssusb); + if (rc) + goto rscs_err; + u3h->ctrl.quirks = XHCI_MTK_HOST; hcor = (struct xhci_hcor *)((uintptr_t)u3h->hcd + HC_LENGTH(xhci_readl(&u3h->hcd->cr_capbase))); - return xhci_register(dev, u3h->hcd, hcor); + rc = xhci_register(dev, u3h->hcd, hcor); + if (rc) + goto host_err; + + return 0; + +host_err: + ssusb_host_exit(ssusb); +rscs_err: + mtu3_host_rscs_exit(u3h); + return rc; } static int mtu3_host_remove(struct udevice *dev) @@ -293,68 +365,99 @@ static int mtu3_host_remove(struct udevice *dev) xhci_deregister(dev); ssusb_host_exit(u3h->ssusb); + mtu3_host_rscs_exit(u3h); return 0; } U_BOOT_DRIVER(mtu3_host) = { .name = "mtu3-host", .id = UCLASS_USB, - .of_match = ssusb_of_match, .probe = mtu3_host_probe, .remove = mtu3_host_remove, .priv_auto = sizeof(struct mtu3_host), .ops = &xhci_usb_ops, .flags = DM_FLAG_ALLOC_PRIV_DMA, }; -#endif -static int mtu3_glue_bind(struct udevice *parent) +static int mtu3_bind_host(struct udevice *parent) { struct udevice *dev; - enum usb_dr_mode dr_mode; - const char *driver; const char *name; ofnode node; int ret; - node = ofnode_by_compatible(dev_ofnode(parent), "mediatek,ssusb"); - if (!ofnode_valid(node)) + ofnode_for_each_subnode(node, dev_ofnode(parent)) { + if (ofnode_is_enabled(node) && + ofnode_device_is_compatible(node, "mediatek,mtk-xhci")) + break; + } + if (!ofnode_valid(node)) { + dev_err(parent, "failed to find enabled xHCI child node\n"); return -ENODEV; + } name = ofnode_get_name(node); - dr_mode = usb_get_dr_mode(node); + ret = device_bind_driver_to_node(parent, "mtu3-host", name, node, + &dev); + if (ret) + dev_err(parent, "failed to bind host mode: %d\n", ret); + + return ret; +} +#else +static int mtu3_bind_host(struct udevice *parent) +{ + return -ENODEV; +} +#endif + +static int mtu3_glue_bind(struct udevice *parent) +{ + enum usb_dr_mode dr_mode; + ofnode node; + + /* Reject the old layout before misinterpreting its register offsets. */ + ofnode_for_each_subnode(node, dev_ofnode(parent)) { + if (ofnode_device_is_compatible(node, "mediatek,ssusb")) { + dev_err(parent, + "legacy mediatek,ssusb child is unsupported\n"); + /* Only -ENODEV keeps the failure contained to USB. */ + return -ENODEV; + } + } + + dr_mode = usb_get_dr_mode(dev_ofnode(parent)); + if (dr_mode == USB_DR_MODE_UNKNOWN) { + /* Absent defaults to otg, an unparsable value is an error. */ + if (dev_read_string(parent, "dr_mode")) { + dev_err(parent, "invalid dr_mode\n"); + return -ENODEV; + } + + dr_mode = USB_DR_MODE_OTG; + } switch (dr_mode) { -#if CONFIG_IS_ENABLED(DM_USB_GADGET) case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: - dev_dbg(parent, "%s: dr_mode: peripheral\n", __func__); - driver = "mtu3-peripheral"; + if (CONFIG_IS_ENABLED(USB_MTU3_GADGET)) + return mtu3_bind_gadget(parent); break; -#endif - -#if defined(CONFIG_SPL_USB_HOST) || \ - (!defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_HOST)) case USB_DR_MODE_HOST: - dev_dbg(parent, "%s: dr_mode: host\n", __func__); - driver = "mtu3-host"; + if (CONFIG_IS_ENABLED(USB_MTU3_HOST)) + return mtu3_bind_host(parent); + break; + case USB_DR_MODE_OTG: + if (CONFIG_IS_ENABLED(USB_MTU3_GADGET)) + return mtu3_bind_gadget(parent); + if (CONFIG_IS_ENABLED(USB_MTU3_HOST)) + return mtu3_bind_host(parent); break; -#endif default: - dev_err(parent, "%s: unsupported dr_mode %d\n", - __func__, dr_mode); - return -ENODEV; - }; - - dev_dbg(parent, "%s: node name: %s, driver %s, dr_mode %d\n", - __func__, name, driver, dr_mode); - - ret = device_bind_driver_to_node(parent, driver, name, node, &dev); - if (ret) - dev_err(parent, "%s: not able to bind usb device mode\n", - __func__); + break; + } - return ret; + dev_err(parent, "dr_mode %d is unsupported by this build\n", dr_mode); + return -ENODEV; } static const struct udevice_id mtu3_of_match[] = { |
