From 9f6ef85007a9bda0070764fe815193ff8b9524cd Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Fri, 16 Feb 2024 20:19:05 +0800 Subject: [PATCH 1/6] phy: hisi-inno-phy: add support for hi3798mv200-usb2-phy This should be considered a dirty hack. The proper solution would be extracting write_reg logic to a separate regmap driver. Leaving only "write BIT(2) to address 0x6" to the PHY driver. The initial commit is already doing things wrong. The following patches adding hi3798mv100 support is also very confusing. The name of the enumeration "PHY_TYPE_x" is very misleading as if it's the phy which is different across SoCs. But actually it's the bus (i.e. how to write to a given address) which is different, not the PHY. # Describe the purpose of this series. The information you put here # will be used by the project maintainer to make a decision whether # your patches should be reviewed, and in what priority order. Please be # very detailed and link to any relevant discussions or sites that the # maintainer can review to better understand your proposed changes. If you # only have a single patch in your series, the contents of the cover # letter will be appended to the "under-the-cut" portion of the patch. # Lines starting with # will be removed from the cover letter. You can # use them to add notes or reminders to yourself. If you want to use # markdown headers in your cover letter, start the line with ">#". # You can add trailers to the cover letter. Any email addresses found in # these trailers will be added to the addresses specified/generated # during the b4 send stage. You can also run "b4 prep --auto-to-cc" to # auto-populate the To: and Cc: trailers based on the code being # modified. To: Vinod Koul To: Kishon Vijay Abraham I To: Rob Herring To: Krzysztof Kozlowski To: Conor Dooley To: Jiancheng Xue To: Shawn Guo To: Philipp Zabel Cc: Cc: Cc: Cc: Kishon Vijay Abraham I Cc: David Yang Signed-off-by: Yang Xiwen --- Changes in v4: - split phy test bus operation to a dedicated driver, now it's clear PHY is compatible. - split YAML convertion into two commits, the other add mv100 compatible (Krzysztof Kozlowski) - Link to v3: https://lore.kernel.org/r/20240220-inno-phy-v3-0-893cdf8633b4@outlook.com Changes in v3: - address a few binding issue mistakenly missing in v2 (Krzysztof Kozlowski) - add msg about hi3798mv100 being added to compatible list - remove minItems for compatible - remove | for reg: - fix existing dts (hi3798cv200.dtsi) due to binding change. - Link to v2: https://lore.kernel.org/r/20240217-inno-phy-v2-0-3bf7e87b0e9e@outlook.com Changes in v2: - rewrite commit msg to show why hisilicon,hi3798mv100-usb2-phy is added during YAML convertion. - split required: to multiple line - add allOf to wrap if: - remove perictrl wrapper and the second phy in the example - tested the binding both for mv200 and cv200 dts. fix some silly errors. - remove Pengcheng Li from To: Above all are suggested by Krzysztof - use reset_control_array_* APIs to ensure all resets are controlled - Link to v1: https://lore.kernel.org/r/20240216-inno-phy-v1-0-1ab912f0533f@outlook.com --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 4, "change-id": "20240216-inno-phy-a2d872f6b74b", "prefixes": [ "RFC" ], "history": { "v1": [ "20240216-inno-phy-v1-0-1ab912f0533f@outlook.com" ], "v2": [ "20240217-inno-phy-v2-0-3bf7e87b0e9e@outlook.com" ], "v3": [ "20240220-inno-phy-v3-0-893cdf8633b4@outlook.com" ] } } } From c6d48881286326c9297ef0e306b8ef8a6f4e2e97 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Fri, 16 Feb 2024 21:07:27 +0800 Subject: [PATCH 2/6] phy: hisilicon: hisi-inno-phy: enable clocks for every ports This is needed for port1 to work. Fixes: ba8b0ee81fbb ("phy: add inno-usb2-phy driver for hi3798cv200 SoC") Signed-off-by: Yang Xiwen --- drivers/phy/hisilicon/phy-hisi-inno-usb2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c index c138cd4807d6f9..b7e740eb475220 100644 --- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c @@ -86,8 +86,10 @@ static void hisi_inno_phy_write_reg(struct hisi_inno_phy_priv *priv, static void hisi_inno_phy_setup(struct hisi_inno_phy_priv *priv) { + int i; /* The phy clk is controlled by the port0 register 0x06. */ - hisi_inno_phy_write_reg(priv, 0, 0x06, PHY_CLK_ENABLE); + for (i = 0; i < INNO_PHY_PORT_NUM; i++) + hisi_inno_phy_write_reg(priv, i, 0x06, PHY_CLK_ENABLE); msleep(PHY_CLK_STABLE_TIME); } From 3a3e904643f853d19c10a0de4bee8c0905180dda Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Fri, 16 Feb 2024 20:59:26 +0800 Subject: [PATCH 3/6] dt-bindings: phy: hisi-inno-usb2: convert to YAML convert the legacy text binding to YAML. While at it, remove "hisilicon,inno-usb2-phy" fallback compatible. Signed-off-by: Yang Xiwen --- .../bindings/phy/hisilicon,inno-usb2-phy.yaml | 91 +++++++++++++++++++ .../bindings/phy/phy-hisi-inno-usb2.txt | 71 --------------- 2 files changed, 91 insertions(+), 71 deletions(-) create mode 100644 Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml delete mode 100644 Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt diff --git a/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml new file mode 100644 index 00000000000000..ba82405ddf510b --- /dev/null +++ b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/hisilicon,inno-usb2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HiSilicon HiSTB SoCs INNO USB2 PHY device + +maintainers: + - Yang Xiwen + +properties: + compatible: + items: + - enum: + - hisilicon,hi3798cv200-usb2-phy + + reg: + maxItems: 1 + description: Should be the address space for PHY configuration register in + peripheral controller, e.g. PERI_USB0 for USB 2.0 PHY01 on Hi3798CV200 SoC, + or direct MMIO address space. + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + clocks: + maxItems: 1 + description: reference clock + + resets: + maxItems: 1 + +patternProperties: + 'phy@[0-9a-f]+': + type: object + additionalProperties: false + description: individual ports provided by INNO PHY + + properties: + reg: + maxItems: 1 + description: should be the port index (if under a perictrl node) + or port address space + + '#phy-cells': + const: 0 + + resets: + maxItems: 1 + + required: + - reg + - '#phy-cells' + - resets + +required: + - compatible + - clocks + - reg + - '#address-cells' + - '#size-cells' + - resets + +additionalProperties: false + +examples: + - | + usb2-phy@120 { + compatible = "hisilicon,hi3798cv200-usb2-phy"; + reg = <0x120 0x4>; + clocks = <&clk_ref>; + resets = <&crg 0xbc 4>; + #address-cells = <1>; + #size-cells = <0>; + + phy@0 { + reg = <0>; + #phy-cells = <0>; + resets = <&crg 0xbc 8>; + }; + + phy@1 { + reg = <1>; + #phy-cells = <0>; + resets = <&crg 0xbc 9>; + }; + }; diff --git a/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt deleted file mode 100644 index 104953e849e798..00000000000000 --- a/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt +++ /dev/null @@ -1,71 +0,0 @@ -Device tree bindings for HiSilicon INNO USB2 PHY - -Required properties: -- compatible: Should be one of the following strings: - "hisilicon,inno-usb2-phy", - "hisilicon,hi3798cv200-usb2-phy". -- reg: Should be the address space for PHY configuration register in peripheral - controller, e.g. PERI_USB0 for USB 2.0 PHY01 on Hi3798CV200 SoC. -- clocks: The phandle and clock specifier pair for INNO USB2 PHY device - reference clock. -- resets: The phandle and reset specifier pair for INNO USB2 PHY device reset - signal. -- #address-cells: Must be 1. -- #size-cells: Must be 0. - -The INNO USB2 PHY device should be a child node of peripheral controller that -contains the PHY configuration register, and each device supports up to 2 PHY -ports which are represented as child nodes of INNO USB2 PHY device. - -Required properties for PHY port node: -- reg: The PHY port instance number. -- #phy-cells: Defined by generic PHY bindings. Must be 0. -- resets: The phandle and reset specifier pair for PHY port reset signal. - -Refer to phy/phy-bindings.txt for the generic PHY binding properties - -Example: - -perictrl: peripheral-controller@8a20000 { - compatible = "hisilicon,hi3798cv200-perictrl", "simple-mfd"; - reg = <0x8a20000 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x8a20000 0x1000>; - - usb2_phy1: usb2-phy@120 { - compatible = "hisilicon,hi3798cv200-usb2-phy"; - reg = <0x120 0x4>; - clocks = <&crg HISTB_USB2_PHY1_REF_CLK>; - resets = <&crg 0xbc 4>; - #address-cells = <1>; - #size-cells = <0>; - - usb2_phy1_port0: phy@0 { - reg = <0>; - #phy-cells = <0>; - resets = <&crg 0xbc 8>; - }; - - usb2_phy1_port1: phy@1 { - reg = <1>; - #phy-cells = <0>; - resets = <&crg 0xbc 9>; - }; - }; - - usb2_phy2: usb2-phy@124 { - compatible = "hisilicon,hi3798cv200-usb2-phy"; - reg = <0x124 0x4>; - clocks = <&crg HISTB_USB2_PHY2_REF_CLK>; - resets = <&crg 0xbc 6>; - #address-cells = <1>; - #size-cells = <0>; - - usb2_phy2_port0: phy@0 { - reg = <0>; - #phy-cells = <0>; - resets = <&crg 0xbc 10>; - }; - }; -}; From 2ad41ab263779aa760fb528b45abea167db35543 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Sun, 3 Mar 2024 17:14:45 +0800 Subject: [PATCH 4/6] dt-bindings: phy: hisilicon,inno-usb2-phy: add support for Hi3798MV100 INNO PHY Hi3798MV100 also has a similar INNO USB2 PHY with slightly different register fields offsets. Document it in the binding. Signed-off-by: Yang Xiwen --- .../devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml index ba82405ddf510b..7f0811a2dc2b6f 100644 --- a/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml @@ -14,6 +14,7 @@ properties: items: - enum: - hisilicon,hi3798cv200-usb2-phy + - hisilicon,hi3798mv100-usb2-phy reg: maxItems: 1 From 3ef32909decb49ca2e329e1dd43ff25dbd1881d7 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Sun, 3 Mar 2024 17:15:48 +0800 Subject: [PATCH 5/6] dt-bindings: phy: hisi-inno-usb2: add compatible of hisilicon,hi3798mv200-usb2-phy Hi3798MV200 INNO USB2 PHY is attached directly to system bus. Add compatible "hisilicon,hi3798mv200-usb2-phy" for it. Signed-off-by: Yang Xiwen --- .../bindings/phy/hisilicon,inno-usb2-phy.yaml | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml index 7f0811a2dc2b6f..bdc2250897d25b 100644 --- a/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/hisilicon,inno-usb2-phy.yaml @@ -15,6 +15,7 @@ properties: - enum: - hisilicon,hi3798cv200-usb2-phy - hisilicon,hi3798mv100-usb2-phy + - hisilicon,hi3798mv200-usb2-phy reg: maxItems: 1 @@ -22,18 +23,29 @@ properties: peripheral controller, e.g. PERI_USB0 for USB 2.0 PHY01 on Hi3798CV200 SoC, or direct MMIO address space. + ranges: + maxItems: 1 + '#address-cells': const: 1 '#size-cells': - const: 0 + enum: [0, 1] clocks: maxItems: 1 description: reference clock resets: - maxItems: 1 + minItems: 1 + items: + - description: port reset + - description: optional external test bus reset + + reset-names: + items: + - const: port + - const: test patternProperties: 'phy@[0-9a-f]+': @@ -53,6 +65,9 @@ patternProperties: resets: maxItems: 1 + phy_type: + const: utmi + required: - reg - '#phy-cells' @@ -66,6 +81,21 @@ required: - '#size-cells' - resets +allOf: + - if: + properties: + compatible: + contains: + const: hisilicon,hi3798mv200-usb2-phy + then: + required: + - ranges + - reset-names + else: + properties: + ranges: false + reset-names: false + additionalProperties: false examples: From 6260c8ee3754da5efb99c1a6446a1c52c4691a94 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Fri, 16 Feb 2024 22:41:24 +0800 Subject: [PATCH 6/6] phy: hisilicon: hisi-inno-phy: add support for Hi3798MV200 INNO PHY Direct MMIO resgiter access is used by Hi3798MV200. For other models, of_iomap() returns NULL due to insufficient length. So they are unaffected. Also Hi3798MV200 INNO PHY has an extra reset required to be deasserted, switch to reset_control_bulk_() APIs for that. Signed-off-by: Yang Xiwen --- drivers/phy/hisilicon/phy-hisi-inno-usb2.c | 66 +++++++++++++--------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c index b7e740eb475220..6bf545cc9c7d77 100644 --- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #define PHY_TYPE_0 0 #define PHY_TYPE_1 1 +#define PHY_TYPE_MMIO 2 #define PHY_TEST_DATA GENMASK(7, 0) #define PHY_TEST_ADDR_OFFSET 8 @@ -43,6 +45,7 @@ #define PHY_CLK_ENABLE BIT(2) struct hisi_inno_phy_port { + void __iomem *base; struct reset_control *utmi_rst; struct hisi_inno_phy_priv *priv; }; @@ -50,7 +53,7 @@ struct hisi_inno_phy_port { struct hisi_inno_phy_priv { void __iomem *mmio; struct clk *ref_clk; - struct reset_control *por_rst; + struct reset_control *rsts; unsigned int type; struct hisi_inno_phy_port ports[INNO_PHY_PORT_NUM]; }; @@ -62,26 +65,31 @@ static void hisi_inno_phy_write_reg(struct hisi_inno_phy_priv *priv, u32 val; u32 value; - if (priv->type == PHY_TYPE_0) - val = (data & PHY_TEST_DATA) | - ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) | - ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) | - PHY0_TEST_WREN | PHY0_TEST_RST; - else - val = (data & PHY_TEST_DATA) | - ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) | - ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) | - PHY1_TEST_WREN | PHY1_TEST_RST; - writel(val, reg); - - value = val; - if (priv->type == PHY_TYPE_0) - value |= PHY0_TEST_CLK; - else - value |= PHY1_TEST_CLK; - writel(value, reg); - - writel(val, reg); + if (priv->ports[port].base) + // stride is 4 + writel(data, (u32 *)priv->ports[port].base + addr); + else { + if (priv->type == PHY_TYPE_0) + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) | + ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) | + PHY0_TEST_WREN | PHY0_TEST_RST; + else + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) | + ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) | + PHY1_TEST_WREN | PHY1_TEST_RST; + writel(val, reg); + + value = val; + if (priv->type == PHY_TYPE_0) + value |= PHY0_TEST_CLK; + else + value |= PHY1_TEST_CLK; + writel(value, reg); + + writel(val, reg); + } } static void hisi_inno_phy_setup(struct hisi_inno_phy_priv *priv) @@ -104,7 +112,7 @@ static int hisi_inno_phy_init(struct phy *phy) return ret; udelay(REF_CLK_STABLE_TIME); - reset_control_deassert(priv->por_rst); + reset_control_deassert(priv->rsts); udelay(POR_RST_COMPLETE_TIME); /* Set up phy registers */ @@ -122,7 +130,7 @@ static int hisi_inno_phy_exit(struct phy *phy) struct hisi_inno_phy_priv *priv = port->priv; reset_control_assert(port->utmi_rst); - reset_control_assert(priv->por_rst); + reset_control_assert(priv->rsts); clk_disable_unprepare(priv->ref_clk); return 0; @@ -158,15 +166,16 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) if (IS_ERR(priv->ref_clk)) return PTR_ERR(priv->ref_clk); - priv->por_rst = devm_reset_control_get_exclusive(dev, NULL); - if (IS_ERR(priv->por_rst)) - return PTR_ERR(priv->por_rst); + priv->rsts = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->rsts)) + return PTR_ERR(priv->rsts); priv->type = (uintptr_t) of_device_get_match_data(dev); for_each_child_of_node(np, child) { struct reset_control *rst; struct phy *phy; + void __iomem *base; rst = of_reset_control_get_exclusive(child, NULL); if (IS_ERR(rst)) { @@ -174,7 +183,10 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) return PTR_ERR(rst); } + base = of_iomap(child, 0); + priv->ports[i].utmi_rst = rst; + priv->ports[i].base = base; priv->ports[i].priv = priv; phy = devm_phy_create(dev, child, &hisi_inno_phy_ops); @@ -205,6 +217,8 @@ static const struct of_device_id hisi_inno_phy_of_match[] = { .data = (void *) PHY_TYPE_0 }, { .compatible = "hisilicon,hi3798mv100-usb2-phy", .data = (void *) PHY_TYPE_1 }, + { .compatible = "hisilicon,hi3798mv200-usb2-phy", + .data = (void *) PHY_TYPE_MMIO }, { }, }; MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match);