diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 67223f73ee606..a2a4fc5a9915e 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -17,9 +17,9 @@ Description: USB ports. Valid values: - 0 - Primary USB port - 1 - Secondary USB port + primary - Primary USB port + secondary - Secondary USB port The attribute is writable only while EUD is disabled. Reading the attribute returns the currently selected - USB port number. + USB port. diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml index ecad7781644ce..8ca0292490a2c 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml @@ -95,14 +95,6 @@ properties: - device - dual - usb-role-switch: - $ref: /schemas/types.yaml#/definitions/phandle - description: - A phandle to the USB role-switch provider. The provider is typically - a dual-role (DRD) USB controller node that declares the boolean - 'usb-role-switch' property. Use this when the connector is not - directly linked to the provider in the OF graph. - typec-power-opmode: description: Determines the power operation mode that the Type C connector will support and will advertise through CC pins when it has no power diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 12560342f37fb..21f75038a81c6 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -32,32 +32,76 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports description: - These ports attach to endpoints of DWC3 controller nodes and Type-C - connector nodes. The controller has the "usb-role-switch" property. - EUD supports up to 2 USB ports. For single-port configurations, use - port@0 and port@1. For dual-port configurations, use all four ports. + These ports is to be attached to the endpoint of the DWC3 controller node + and type C connector node. The controller has the "usb-role-switch" + property. properties: port@0: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the primary DWC3 controller. + description: This port is to be attached to the DWC3 controller. port@1: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the primary Type-C connector. + description: This port is to be attached to the type C connector. - port@2: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the secondary DWC3 controller. + '#address-cells': + const: 1 - port@3: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the secondary Type-C connector. + '#size-cells': + const: 0 + +patternProperties: + "^eud-path@[0-1]$": + type: object + description: + Represents one High-Speed UTMI path that EUD intercepts. Use eud-path nodes + to associate role-switching behavior with specific port connections, allowing + EUD to manage role transitions independently for each UTMI path. + + properties: + reg: + maxItems: 1 + description: Path number + + usb-role-switch: + type: boolean + description: + Indicates that EUD should act as a role switch for this path. + In device role, debug mode inserts the EUD hub into the UTMI path. In + host role, the EUD hub is bypassed and UTMI traffic flows directly + between the PHY and the USB controller. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: + These ports are to be attached to the endpoint of the USB controller node + and USB connector node. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB controller. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB connector. + + required: + - reg + - ports + + additionalProperties: false required: - compatible - reg - - ports + +oneOf: + - required: + - ports + - required: + - eud-path@0 additionalProperties: false diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 6b57ab6b74836..cad1d78f9e629 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4723,22 +4723,28 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - ports { - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - port@0 { - reg = <0>; + eud0: eud-path@0 { + reg = <0>; + usb-role-switch; - eud_ep: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; - }; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; - port@1 { - reg = <1>; + port@0 { + reg = <0>; + eud_usb: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; - eud_con: endpoint { + port@1 { + reg = <1>; + eud_con: endpoint { + }; }; }; }; @@ -4965,7 +4971,7 @@ reg = <0>; usb_1_dwc3_hs: endpoint { - remote-endpoint = <&eud_ep>; + remote-endpoint = <&eud_usb>; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts index 9f0cfd0b5005e..c213e06a4428c 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts @@ -89,7 +89,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts index ca9c1a09ca733..e9c0463daa53d 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts @@ -65,7 +65,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts index eb7e228787c24..650c4fbc1606d 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts @@ -75,7 +75,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 6db3b2a9ff811..a0db2a2745d27 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -185,7 +185,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index 05cd73b5bcbe2..387c38aa87d2d 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -84,7 +84,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts index f99a47334452f..a2e160f3f46ec 100644 --- a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts +++ b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts @@ -90,7 +90,6 @@ reg = <0>; power-role = "dual"; data-role = "dual"; - usb-role-switch = <&usb_1>; ports { #address-cells = <1>; diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index ae03ae45e50e4..18169727a413e 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -132,7 +132,6 @@ config USB_DWC3_QCOM depends on ARCH_QCOM || COMPILE_TEST depends on EXTCON || !EXTCON depends on OF - depends on USB_QCOM_EUD || !USB_QCOM_EUD default USB_DWC3 help Some Qualcomm SoCs use DesignWare Core IP for USB2/3 diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 4c00b6b87f6d5..f43f73ac36ff1 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,6 @@ #include #include #include -#include #include "core.h" #include "glue.h" @@ -563,7 +561,6 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role) { struct dwc3_qcom *qcom = to_dwc3_qcom(dwc); - struct device_node *eud_node; if (qcom->current_role == next_role) return; @@ -573,13 +570,6 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol return; } - /* Notify EUD of role change */ - eud_node = of_graph_get_remote_node(qcom->dev->of_node, 0, -1); - if (eud_node) { - qcom_eud_usb_role_notify(eud_node, dwc->usb2_generic_phy[0], next_role); - of_node_put(eud_node); - } - if (qcom->current_role == USB_ROLE_DEVICE) dwc3_qcom_vbus_override_enable(qcom, false); else if (qcom->current_role != USB_ROLE_DEVICE) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 2d9190c756f9c..0b56b773dbdf7 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -147,7 +147,6 @@ config USB_APPLEDISPLAY config USB_QCOM_EUD tristate "QCOM Embedded USB Debugger(EUD) Driver" depends on ARCH_QCOM || COMPILE_TEST - depends on OF select QCOM_SCM select USB_ROLE_SWITCH help diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 5b5cf11d6f526..187cbffbab13d 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -12,13 +12,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #define EUD_REG_INT1_EN_MASK 0x0024 @@ -38,14 +36,28 @@ #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) +static const char * const eud_port_names[] = { + "primary", + "secondary", +}; + +struct eud_path { + struct eud_chip *chip; + struct phy *phy; + struct usb_role_switch *controller_sw; + struct usb_role_switch *eud_sw; + enum usb_role curr_role; + char name[16]; + u8 num; +}; + struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw[EUD_MAX_PORTS]; - struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; - phys_addr_t mode_mgr; + struct eud_path *paths[EUD_MAX_PORTS]; /* serializes EUD control operations */ struct mutex state_lock; + phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; @@ -63,7 +75,7 @@ static int eud_phy_enable(struct eud_chip *chip) if (chip->phy_enabled) return 0; - phy = chip->phy[chip->port_idx]; + phy = chip->paths[chip->port_idx]->phy; ret = phy_init(phy); if (ret) { @@ -92,7 +104,7 @@ static void eud_phy_disable(struct eud_chip *chip) if (!chip->phy_enabled) return; - phy = chip->phy[chip->port_idx]; + phy = chip->paths[chip->port_idx]->phy; phy_power_off(phy); phy_exit(phy); @@ -147,7 +159,7 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); - enum usb_role role; + struct eud_path *path; bool enable; int ret; @@ -178,9 +190,9 @@ static ssize_t enable_store(struct device *dev, * debugging, making it incompatible with USB host mode configuration. * Prevent enabling EUD in this configuration to avoid hardware conflicts. */ - role = usb_role_switch_get_role(chip->role_sw[chip->port_idx]); - if (role == USB_ROLE_HOST) { - dev_err(chip->dev, "Cannot enable EUD: USB port is in host mode\n"); + path = chip->paths[chip->port_idx]; + if (path->curr_role == USB_ROLE_HOST) { + dev_err(chip->dev, "cannot enable EUD: USB port is in host mode\n"); return -EBUSY; } @@ -208,25 +220,21 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr, char { struct eud_chip *chip = dev_get_drvdata(dev); - return sysfs_emit(buf, "%u\n", chip->port_idx); + return sysfs_emit(buf, "%s\n", eud_port_names[chip->port_idx]); } static ssize_t port_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); - u8 port; - int ret; + int port; - ret = kstrtou8(buf, 0, &port); - if (ret) - return ret; - - /* Only port 0 and port 1 are valid */ - if (port >= EUD_MAX_PORTS) - return -EINVAL; + port = sysfs_match_string(eud_port_names, buf); + if (port < 0) + return port; - if (!chip->phy[port]) { + /* Check if the corresponding path is available */ + if (!chip->paths[port]) { dev_err(chip->dev, "EUD not supported on selected port\n"); return -EOPNOTSUPP; } @@ -307,8 +315,11 @@ static irqreturn_t handle_eud_irq(int irq, void *data) static irqreturn_t handle_eud_irq_thread(int irq, void *data) { struct eud_chip *chip = data; + struct eud_path *path; int ret; + path = chip->paths[chip->port_idx]; + /* * EUD virtual attach/detach event handling for low power debugging: * @@ -326,9 +337,9 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) * switch framework. */ if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_NONE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); @@ -339,129 +350,147 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) +static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { - struct device_node *controller_node; - struct phy *phy; - struct usb_role_switch *role_sw; + struct eud_path *path = usb_role_switch_get_drvdata(sw); + struct eud_chip *chip = path->chip; + int ret; + + guard(mutex)(&chip->state_lock); /* - * Multiply port_id by 2 to get controller port number: - * port_id 0 -> port@0 (primary USB controller) - * port_id 1 -> port@2 (secondary USB controller) + * EUD must be disabled when USB operates in host mode. EUD functions by + * presenting itself as a USB device to the host PC for debugging, making + * it incompatible with host mode configuration. + * + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to maintain user intent. */ - controller_node = of_graph_get_remote_node(chip->dev->of_node, - port_id * 2, -1); - if (!controller_node) - return dev_err_probe(chip->dev, -ENODEV, - "failed to get controller node for port %u\n", port_id); - phy = devm_of_phy_get_by_index(chip->dev, controller_node, 0); - if (IS_ERR(phy)) { - of_node_put(controller_node); - return dev_err_probe(chip->dev, PTR_ERR(phy), - "failed to get HS PHY for port %u\n", port_id); + /* Only act if EUD is enabled and this is the active path */ + if (chip->enabled && path->num == chip->port_idx) { + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable EUD for host mode: %d\n", + ret); + return ret; + } + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to re-enable EUD after host mode: %d\n", + ret); + return ret; + } + chip->eud_disabled_for_host = false; + } } - chip->phy[port_id] = phy; - /* Only fetch role switch if usb-role-switch property exists */ - if (!of_property_read_bool(controller_node, "usb-role-switch")) { - of_node_put(controller_node); - return 0; + ret = usb_role_switch_set_role(path->controller_sw, role); + if (ret) { + dev_err(path->chip->dev, "failed to set role %s for port %u: %d\n", + usb_role_string(role), path->num, ret); + return ret; } - role_sw = usb_role_switch_find_by_fwnode(of_fwnode_handle(controller_node)); - of_node_put(controller_node); + path->curr_role = role; - if (!role_sw) - return dev_err_probe(chip->dev, -EPROBE_DEFER, - "failed to get role switch for port %u\n", port_id); + return 0; +} - chip->role_sw[port_id] = role_sw; +static void eud_path_role_switch_release(void *data) +{ + struct eud_path *path = data; - return 0; + usb_role_switch_unregister(path->eud_sw); + usb_role_switch_put(path->controller_sw); } -/** - * qcom_eud_usb_role_notify - Notify EUD of USB role change - * @eud_node: Device node of the EUD device - * @phy: HSUSB PHY of the port changing role - * @role: New role being set - * - * Notifies EUD that a USB port is changing roles. EUD will disable itself - * if the port is switching to HOST mode, as EUD is incompatible with host - * mode operation. This API should be called by the USB controller driver - * when it switches the USB role. - * - * The PHY parameter is used to identify which physical USB port is changing - * roles. This is important in multi-port systems where EUD may be active on - * one port while another port changes roles. - * - * This is a best-effort notification - failures are logged but do not affect - * the role change operation. - */ -void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, - enum usb_role role) +static int eud_init_path(struct eud_chip *chip, struct device_node *np) { - struct platform_device *pdev; - struct eud_chip *chip; + struct usb_role_switch_desc role_sw_desc; + struct usb_role_switch *sw; + struct device_node *controller_node; + struct eud_path *path; + u32 path_num; int ret; - if (!of_device_is_compatible(eud_node, "qcom,eud")) - return; + ret = of_property_read_u32(np, "reg", &path_num); + if (ret) { + /* Legacy DT uses 'ports' node without 'reg' property; treat as path 0 */ + if (of_node_name_eq(np, "ports")) + path_num = 0; + else + return dev_err_probe(chip->dev, ret, "unexpected child node '%s'\n", + np->name); + } - pdev = of_find_device_by_node(eud_node); - if (!pdev) - return; + if (path_num >= EUD_MAX_PORTS) + return dev_err_probe(chip->dev, -EINVAL, "invalid path number: %u (max %d)\n", + path_num, EUD_MAX_PORTS - 1); - chip = platform_get_drvdata(pdev); - if (!chip) - goto put_dev; + path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL); + if (!path) + return -ENOMEM; + + path->chip = chip; + path->num = path_num; - mutex_lock(&chip->state_lock); + controller_node = of_graph_get_remote_node(np, 0, -1); + if (!controller_node) + return dev_err_probe(chip->dev, -ENODEV, + "failed to get controller node for path %u\n", path_num); - /* Only act if this notification is for the currently active EUD port */ - if (!chip->enabled || chip->phy[chip->port_idx] != phy) { - mutex_unlock(&chip->state_lock); - goto put_dev; + path->phy = devm_of_phy_get_by_index(chip->dev, controller_node, 0); + if (IS_ERR(path->phy)) { + of_node_put(controller_node); + return dev_err_probe(chip->dev, PTR_ERR(path->phy), + "failed to get PHY for path %d\n", path_num); } - /* - * chip->enabled preserves user's sysfs configuration and is not modified - * during host mode transitions to preserve user intent. - */ - if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { - ret = disable_eud(chip); - if (ret) - dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", ret); - else - chip->eud_disabled_for_host = true; - } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { - ret = enable_eud(chip); - if (ret) - dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", ret); - else - chip->eud_disabled_for_host = false; + path->curr_role = USB_ROLE_NONE; + + /* Fetch controller role switch if it is role switch capable */ + if (of_property_read_bool(controller_node, "usb-role-switch")) { + sw = usb_role_switch_find_by_fwnode(of_fwnode_handle(controller_node)); + if (!sw) { + of_node_put(controller_node); + return dev_err_probe(chip->dev, -EPROBE_DEFER, + "Failed to get controller role switch for path %d\n", + path_num); + } + path->controller_sw = sw; } - mutex_unlock(&chip->state_lock); + of_node_put(controller_node); -put_dev: - platform_device_put(pdev); -} -EXPORT_SYMBOL_GPL(qcom_eud_usb_role_notify); + role_sw_desc.fwnode = of_fwnode_handle(np); + role_sw_desc.set = eud_role_switch_set; + role_sw_desc.driver_data = path; + snprintf(path->name, sizeof(path->name), "eud-path%u", path_num); + role_sw_desc.name = path->name; + + path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc); + if (IS_ERR(path->eud_sw)) { + usb_role_switch_put(path->controller_sw); + return dev_err_probe(chip->dev, PTR_ERR(path->eud_sw), + "Failed to register EUD role switch for path %d\n", path_num); + } -static void eud_role_switch_release(void *data) -{ - struct eud_chip *chip = data; - int i; + ret = devm_add_action_or_reset(chip->dev, eud_path_role_switch_release, path); + if (ret) + return ret; + + chip->paths[path_num] = path; - for (i = 0; i < EUD_MAX_PORTS; i++) - usb_role_switch_put(chip->role_sw[i]); + return 0; } static int eud_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct eud_chip *chip; struct resource *res; int ret; @@ -474,20 +503,15 @@ static int eud_probe(struct platform_device *pdev) mutex_init(&chip->state_lock); - /* - * Parse the DT resources for primary port. - * This is the default EUD port and is mandatory. - */ - ret = eud_parse_dt_port(chip, 0); - if (ret) - return ret; - - /* Secondary port is optional */ - eud_parse_dt_port(chip, 1); + for_each_child_of_node_scoped(np, child) { + ret = eud_init_path(chip, child); + if (ret) + return ret; + } - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); - if (ret) - return ret; + /* Primary path is mandatory. Secondary is optional */ + if (!chip->paths[0]) + return dev_err_probe(chip->dev, -ENODEV, "primary path not found\n"); chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) @@ -518,14 +542,8 @@ static void eud_remove(struct platform_device *pdev) { struct eud_chip *chip = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - mutex_lock(&chip->state_lock); - if (chip->enabled) { + if (chip->enabled) disable_eud(chip); - chip->enabled = false; - } - mutex_unlock(&chip->state_lock); device_init_wakeup(&pdev->dev, false); disable_irq_wake(chip->irq); diff --git a/include/linux/usb/qcom_eud.h b/include/linux/usb/qcom_eud.h deleted file mode 100644 index fe560426b78f3..0000000000000 --- a/include/linux/usb/qcom_eud.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -#ifndef __LINUX_USB_QCOM_EUD_H -#define __LINUX_USB_QCOM_EUD_H - -#include - -#if IS_ENABLED(CONFIG_USB_QCOM_EUD) -void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, - enum usb_role role); -#else -static inline void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, - enum usb_role role) -{ -} -#endif - -#endif /* __LINUX_USB_QCOM_EUD_H */