diff --git a/Documentation/devicetree/bindings/phy/apple,t6050-dp-phy.yaml b/Documentation/devicetree/bindings/phy/apple,t6050-dp-phy.yaml index 52cb96f4a965b..fdc2e60461700 100644 --- a/Documentation/devicetree/bindings/phy/apple,t6050-dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/apple,t6050-dp-phy.yaml @@ -37,6 +37,7 @@ properties: const: 1 apple,port-index: + $ref: /schemas/types.yaml#/definitions/uint32 enum: [1, 2] description: Native Type-C port; the debug/proxy port is excluded @@ -74,14 +75,20 @@ properties: description: Offset, mask and value tuples for the PIPE handler power-domains: + description: + A combo PHY may name the USB controller's domain fourth ("usb"). Its + USB2 PHY and digital banks are in that domain, and the PHY then holds it + while it runs, also on a port with no USB controller bound. minItems: 3 - maxItems: 3 + maxItems: 4 power-domain-names: + minItems: 3 items: - const: usb-aon - const: common - const: wrapper + - const: usb apple,tunable-axi2af: $ref: /schemas/types.yaml#/definitions/uint32-array @@ -184,6 +191,10 @@ allOf: properties: '#phy-cells': const: 0 + power-domains: + maxItems: 3 + power-domain-names: + maxItems: 3 if: required: - mode-switch diff --git a/drivers/phy/apple/atc-t6050-combo.h b/drivers/phy/apple/atc-t6050-combo.h index 1066748dc1afe..3c3454ceb64de 100644 --- a/drivers/phy/apple/atc-t6050-combo.h +++ b/drivers/phy/apple/atc-t6050-combo.h @@ -94,6 +94,8 @@ static int combo_stop(struct t6050_dp *dp) if (!ret) dp->usb2_active = false; } + if (!ret && dp->ndomains > 3) + ret = atc_domain_set(&dp->domain[3], false); if (!ret) ret = atc_domain_set(&dp->domain[1], false); if (!ret) @@ -118,6 +120,12 @@ static int combo_start(struct t6050_dp *dp, enum combo_mode mode) ret = atc_domain_set(&dp->domain[0], true); if (!ret) ret = atc_domain_set(&dp->domain[1], true); + /* + * The USB2 PHY and digital banks are unclocked without the USB domain, + * which a USB controller holds only while one is bound to this port. + */ + if (!ret && dp->ndomains > 3) + ret = atc_domain_set(&dp->domain[3], true); if (!ret) ret = APPLE_T6050_USB_RUN(&dp->usb_platform, apple_t6050_usb2_host); if (!ret) diff --git a/drivers/phy/apple/atc-t6050-dp.c b/drivers/phy/apple/atc-t6050-dp.c index cafee096a6250..4479153919488 100644 --- a/drivers/phy/apple/atc-t6050-dp.c +++ b/drivers/phy/apple/atc-t6050-dp.c @@ -83,7 +83,9 @@ struct t6050_dp { void __iomem *banks[45]; struct resource resources[45]; struct apple_tunable *tunables[ARRAY_SIZE(tunable_names)]; - struct atc_domain domain[3]; /* USB AON, common, wrapper: native order. */ + /* USB AON, common, wrapper: native order; a combo may add USB. */ + struct atc_domain domain[4]; + unsigned int ndomains; u32 training[4][16]; u32 voltage[4], pre[4]; int rate; @@ -605,14 +607,14 @@ static int t6050_typec_register(struct t6050_dp *dp) static int t6050_dp_probe(struct platform_device *pdev) { - static const char * const domains[] = {"usb-aon", "common", "wrapper"}; + static const char * const domains[] = {"usb-aon", "common", "wrapper", "usb"}; struct device *dev = &pdev->dev; struct t6050_dp *dp; struct phy_provider *provider; struct phy *phy; struct resource *core; void __iomem *base; - int ret; + int ndomains, ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); if (!dp) @@ -741,10 +743,16 @@ static int t6050_dp_probe(struct platform_device *pdev) if (ret) return ret; } - /* Three named domains prevent automatic wrapper enable at probe time. */ - if (of_count_phandle_with_args(dev->of_node, "power-domains", "#power-domain-cells") != 3) + /* + * Named domains prevent automatic wrapper enable at probe time. A combo + * PHY may also name the USB controller's domain, which its USB2 banks + * are in (combo_start()). + */ + ndomains = of_count_phandle_with_args(dev->of_node, "power-domains", "#power-domain-cells"); + if (ndomains != 3 && !(dp->combo && ndomains == 4)) return -EINVAL; - for (unsigned int i = 0; i < ARRAY_SIZE(domains); i++) { + dp->ndomains = ndomains; + for (unsigned int i = 0; i < dp->ndomains; i++) { dp->domain[i].dev = dev_pm_domain_attach_by_name(dev, domains[i]); if (IS_ERR_OR_NULL(dp->domain[i].dev)) return dev_err_probe(dev, dp->domain[i].dev ? PTR_ERR(dp->domain[i].dev) : -ENODEV,