Create the new compatibles to identify AST2600 MAC0/1 and MAC3/4. Add conditional schema constraints for Aspeed AST2600 MAC controllers: - For "aspeed,ast2600-mac01", require rx/tx-internal-delay-ps properties with 45ps step. - For "aspeed,ast2600-mac23", require rx/tx-internal-delay-ps properties with 250ps step. - Both require the "scu" property. Other compatible values remain unrestricted. Signed-off-by: Jacky Chou --- .../devicetree/bindings/net/faraday,ftgmac100.yaml | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml index d14410018bcf..de646e7e3bca 100644 --- a/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml +++ b/Documentation/devicetree/bindings/net/faraday,ftgmac100.yaml @@ -19,6 +19,12 @@ properties: - aspeed,ast2500-mac - aspeed,ast2600-mac - const: faraday,ftgmac100 + - items: + - enum: + - aspeed,ast2600-mac01 + - aspeed,ast2600-mac23 + - const: aspeed,ast2600-mac + - const: faraday,ftgmac100 reg: maxItems: 1 @@ -69,6 +75,12 @@ properties: mdio: $ref: /schemas/net/mdio.yaml# + scu: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the SCU (System Control Unit) syscon node for Aspeed platform. + This reference is used by the MAC controller to configure the RGMII delays. + required: - compatible - reg @@ -88,6 +100,44 @@ allOf: else: properties: resets: false + - if: + properties: + compatible: + contains: + const: aspeed,ast2600-mac01 + then: + properties: + rx-internal-delay-ps: + minimum: 0 + maximum: 1395 + multipleOf: 45 + tx-internal-delay-ps: + minimum: 0 + maximum: 1395 + multipleOf: 45 + required: + - scu + - rx-internal-delay-ps + - tx-internal-delay-ps + - if: + properties: + compatible: + contains: + const: aspeed,ast2600-mac23 + then: + properties: + rx-internal-delay-ps: + minimum: 0 + maximum: 7750 + multipleOf: 250 + tx-internal-delay-ps: + minimum: 0 + maximum: 7750 + multipleOf: 250 + required: + - scu + - rx-internal-delay-ps + - tx-internal-delay-ps unevaluatedProperties: false -- 2.34.1 For RGMII delay configuration, MAC0 and MAC1 use register SCU0x340, while MAC2 and MAC3 use SCU0x350. The Ethernet aliases are added to help identify the corresponding MAC index. Signed-off-by: Jacky Chou --- arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi index f8662c8ac089..03ad566a4ce8 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi @@ -40,6 +40,10 @@ aliases { mdio1 = &mdio1; mdio2 = &mdio2; mdio3 = &mdio3; + ethernet0 = &mac0; + ethernet1 = &mac1; + ethernet2 = &mac2; + ethernet3 = &mac3; }; -- 2.34.1 This change sets the rx-internal-delay-ps and tx-internal-delay-ps properties to control the RGMII signal delay. The phy-mode for MAC0–MAC3 is updated to "rgmii-id" to enable TX/RX internal delay on the PHY and disable the corresponding delay on the MAC. Signed-off-by: Jacky Chou --- arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts | 28 +++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts index de83c0eb1d6e..a65568e637bd 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts @@ -121,44 +121,64 @@ ethphy3: ethernet-phy@0 { }; &mac0 { + compatible = "aspeed,ast2600-mac01", "aspeed,ast2600-mac", "faraday,ftgmac100"; status = "okay"; - phy-mode = "rgmii-rxid"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii1_default>; + + rx-internal-delay-ps = <0>; + tx-internal-delay-ps = <0>; + scu = <&syscon>; }; &mac1 { + compatible = "aspeed,ast2600-mac01", "aspeed,ast2600-mac", "faraday,ftgmac100"; status = "okay"; - phy-mode = "rgmii-rxid"; + phy-mode = "rgmii-id"; phy-handle = <ðphy1>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii2_default>; + + rx-internal-delay-ps = <0>; + tx-internal-delay-ps = <0>; + scu = <&syscon>; }; &mac2 { + compatible = "aspeed,ast2600-mac23", "aspeed,ast2600-mac", "faraday,ftgmac100"; status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy2>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii3_default>; + + rx-internal-delay-ps = <0>; + tx-internal-delay-ps = <0>; + scu = <&syscon>; }; &mac3 { + compatible = "aspeed,ast2600-mac23", "aspeed,ast2600-mac", "faraday,ftgmac100"; status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii4_default>; + + rx-internal-delay-ps = <0>; + tx-internal-delay-ps = <0>; + scu = <&syscon>; }; &emmc_controller { -- 2.34.1 On the AST2600 platform, the RGMII delay is controlled via the SCU registers. The delay chain configuration differs between MAC0/1 and MAC2/3, even though all four MACs use a 32-stage delay chain. +------+----------+-----------+-------------+-------------+ | |Delay Unit|Delay Stage|TX Edge Stage|RX Edge Stage| +------+----------+-----------+-------------+-------------+ |MAC0/1| 45 ps| 32 | 0 | 0 | +------+----------+-----------+-------------+-------------+ |MAC2/3| 250 ps| 32 | 0 | 26 | +------+----------+-----------+-------------+-------------+ For MAC2/3, the "no delay" condition starts from stage 26. Setting the RX delay stage to 26 means that no additional RX delay is applied. Here lists the RX delay setting of MAC2/3 below. 26 -> 0 ns, 27 -> 0.25 ns, ... , 31 -> 1.25 ns, 0 -> 1.5 ns, 1 -> 1.75 ns, ... , 25 -> 7.75 ns Therefore, we calculate the delay stage from the rx-internal-delay-ps of MAC2/3 to add 26. If the stage is equel to or bigger than 32, the delay stage will be mask 0x1f to get the correct setting. The delay chain is like a ring for configuration. Example for the rx-internal-delay-ps of MAC2/3 is 2000 ps, we will get the delay stage is 2. Signed-off-by: Jacky Chou --- drivers/net/ethernet/faraday/ftgmac100.c | 110 +++++++++++++++++++++++++++++++ drivers/net/ethernet/faraday/ftgmac100.h | 15 +++++ 2 files changed, 125 insertions(+) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index a863f7841210..bc83ef079095 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include @@ -1833,6 +1836,108 @@ static bool ftgmac100_has_child_node(struct device_node *np, const char *name) return ret; } +static int ftgmac100_set_ast2600_rgmii_delay(struct platform_device *pdev, + u32 rgmii_tx_delay, + u32 rgmii_rx_delay) +{ + struct device_node *np = pdev->dev.of_node; + u32 rgmii_delay_unit; + struct regmap *scu; + int dly_mask; + int dly_reg; + int id; + + scu = syscon_regmap_lookup_by_phandle(np, "scu"); + if (IS_ERR(scu)) { + dev_err(&pdev->dev, "failed to get scu"); + return PTR_ERR(scu); + } + + id = of_alias_get_id(np, "ethernet"); + if (id < 0 || id > 3) { + dev_err(&pdev->dev, "get wrong alise id %d\n", id); + return -EINVAL; + } + + if (of_device_is_compatible(np, "aspeed,ast2600-mac01")) { + dly_reg = AST2600_MAC01_CLK_DLY; + rgmii_delay_unit = AST2600_MAC01_CLK_DLY_UNIT; + } else if (of_device_is_compatible(np, "aspeed,ast2600-mac23")) { + dly_reg = AST2600_MAC23_CLK_DLY; + rgmii_delay_unit = AST2600_MAC23_CLK_DLY_UNIT; + } + + rgmii_tx_delay = DIV_ROUND_CLOSEST(rgmii_tx_delay, rgmii_delay_unit); + if (rgmii_tx_delay >= 32) { + dev_err(&pdev->dev, + "The index %u of TX delay setting is out of range\n", + rgmii_tx_delay); + return -EINVAL; + } + + rgmii_rx_delay = DIV_ROUND_CLOSEST(rgmii_rx_delay, rgmii_delay_unit); + if (rgmii_rx_delay >= 32) { + dev_err(&pdev->dev, + "The index %u of RX delay setting is out of range\n", + rgmii_rx_delay); + return -EINVAL; + } + + /* Due to the hardware design reason, for MAC23 on AST2600, the zero + * delay ns on RX is configured by setting value 0x1a. + * List as below: + * 0x1a -> 0 ns, 0x1b -> 0.25 ns, ... , 0x1f -> 1.25 ns, + * 0x00 -> 1.5 ns, 0x01 -> 1.75 ns, ... , 0x19 -> 7.75 ns, 0x1a -> 0 ns + */ + if (of_device_is_compatible(np, "aspeed,ast2600-mac23")) + rgmii_rx_delay = (AST2600_MAC23_RX_DLY_0_NS + rgmii_rx_delay) & + AST2600_MAC_TX_RX_DLY_MASK; + + if (id == 0 || id == 2) { + dly_mask = ASPEED_MAC0_2_TX_DLY | ASPEED_MAC0_2_RX_DLY; + rgmii_tx_delay = FIELD_PREP(ASPEED_MAC0_2_TX_DLY, rgmii_tx_delay); + rgmii_rx_delay = FIELD_PREP(ASPEED_MAC0_2_RX_DLY, rgmii_rx_delay); + } else { + dly_mask = ASPEED_MAC1_3_TX_DLY | ASPEED_MAC1_3_RX_DLY; + rgmii_tx_delay = FIELD_PREP(ASPEED_MAC1_3_TX_DLY, rgmii_tx_delay); + rgmii_rx_delay = FIELD_PREP(ASPEED_MAC1_3_RX_DLY, rgmii_rx_delay); + } + + regmap_update_bits(scu, dly_reg, dly_mask, rgmii_tx_delay | rgmii_rx_delay); + + return 0; +} + +static int ftgmac100_set_internal_delay(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + u32 rgmii_tx_delay; + u32 rgmii_rx_delay; + int err; + + if (!(of_device_is_compatible(np, "aspeed,ast2600-mac01") || + of_device_is_compatible(np, "aspeed,ast2600-mac23"))) + return 0; + + err = of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay); + if (err) { + dev_err(&pdev->dev, "failed to get tx-internal-delay-ps\n"); + return err; + } + + err = of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_rx_delay); + if (err) { + dev_err(&pdev->dev, "failed to get tx-internal-delay-ps\n"); + return err; + } + + err = ftgmac100_set_ast2600_rgmii_delay(pdev, + rgmii_tx_delay, + rgmii_rx_delay); + + return err; +} + static int ftgmac100_probe(struct platform_device *pdev) { struct resource *res; @@ -2004,6 +2109,11 @@ static int ftgmac100_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "aspeed,ast2600-mac")) iowrite32(FTGMAC100_TM_DEFAULT, priv->base + FTGMAC100_OFFSET_TM); + + /* Configure RGMII delay if there are the corresponding compatibles */ + err = ftgmac100_set_internal_delay(pdev); + if (err) + goto err_phy_connect; } /* Default ring sizes */ diff --git a/drivers/net/ethernet/faraday/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h index 4968f6f0bdbc..6a2a9159bee4 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.h +++ b/drivers/net/ethernet/faraday/ftgmac100.h @@ -271,4 +271,19 @@ struct ftgmac100_rxdes { #define FTGMAC100_RXDES1_UDP_CHKSUM_ERR (1 << 26) #define FTGMAC100_RXDES1_IP_CHKSUM_ERR (1 << 27) +/* Aspeed SCU */ +#define AST2600_MAC01_CLK_DLY 0x340 +#define AST2600_MAC23_CLK_DLY 0x350 +#define AST2600_MAC01_CLK_DLY_UNIT 45 /* ps */ +#define AST2600_MAC01_TX_DLY_0_NS 0 +#define AST2600_MAC01_RX_DLY_0_NS 0 +#define AST2600_MAC23_CLK_DLY_UNIT 250 /* ps */ +#define AST2600_MAC23_TX_DLY_0_NS 0 +#define AST2600_MAC23_RX_DLY_0_NS 0x1a +#define AST2600_MAC_TX_RX_DLY_MASK 0x1f +#define ASPEED_MAC0_2_TX_DLY GENMASK(5, 0) +#define ASPEED_MAC0_2_RX_DLY GENMASK(17, 12) +#define ASPEED_MAC1_3_TX_DLY GENMASK(11, 6) +#define ASPEED_MAC1_3_RX_DLY GENMASK(23, 18) + #endif /* __FTGMAC100_H */ -- 2.34.1