summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-08-09 13:50:27 -0600
committerTom Rini <[email protected]>2026-08-09 13:50:27 -0600
commit28515d7ff5285e0b942f15577e3198f15c667a25 (patch)
tree58fa57dff52f8c7ecb0e7a13c454b853af5f5419
parent9167d2079afecfa5881bad8665a2a4636061e3f4 (diff)
parent08b77aac333cb437df57a7f746fa712042ccde61 (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.dts4
-rw-r--r--arch/arm/dts/mt8183.dtsi17
-rw-r--r--arch/arm/dts/mt8512-bm1-emmc.dts6
-rw-r--r--arch/arm/dts/mt8512.dtsi19
-rw-r--r--doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt46
-rw-r--r--doc/device-tree-bindings/usb/mediatek,mtu3.txt79
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/usb/mtu3/Kconfig39
-rw-r--r--drivers/usb/mtu3/Makefile10
-rw-r--r--drivers/usb/mtu3/mtu3.h12
-rw-r--r--drivers/usb/mtu3/mtu3_core.c4
-rw-r--r--drivers/usb/mtu3/mtu3_dr.h4
-rw-r--r--drivers/usb/mtu3/mtu3_host.c11
-rw-r--r--drivers/usb/mtu3/mtu3_hw_regs.h11
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c227
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[] = {