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 <jacky_chou@aspeedtech.com>
---
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 <linux/if_vlan.h>
#include <linux/of_net.h>
#include <linux/phy_fixed.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
#include <net/ip.h>
#include <net/ncsi.h>
@@ -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
> + 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);
The index is not really interesting here, it is not something a DT
author uses. It is the delay in ps in the .dts file which is too big.
Andrew
Hi Jacky,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 01cc760632b875c4ad0d8fec0b0c01896b8a36d4]
url: https://github.com/intel-lab-lkp/linux/commits/Jacky-Chou/dt-bindings-net-ftgmac100-Add-delay-properties-for-AST2600/20251103-154258
base: 01cc760632b875c4ad0d8fec0b0c01896b8a36d4
patch link: https://lore.kernel.org/r/20251103-rgmii_delay_2600-v3-4-e2af2656f7d7%40aspeedtech.com
patch subject: [PATCH net-next v3 4/4] net: ftgmac100: Add RGMII delay support for AST2600
config: arm-defconfig (https://download.01.org/0day-ci/archive/20251104/202511041023.QGAHaAZ3-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project d2625a438020ad35330cda29c3def102c1687b1b)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251104/202511041023.QGAHaAZ3-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511041023.QGAHaAZ3-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/net/ethernet/faraday/ftgmac100.c:1865:13: warning: variable 'rgmii_delay_unit' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
1865 | } else if (of_device_is_compatible(np, "aspeed,ast2600-mac23")) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/faraday/ftgmac100.c:1870:53: note: uninitialized use occurs here
1870 | rgmii_tx_delay = DIV_ROUND_CLOSEST(rgmii_tx_delay, rgmii_delay_unit);
| ^~~~~~~~~~~~~~~~
drivers/net/ethernet/faraday/ftgmac100.c:1865:9: note: remove the 'if' if its condition is always true
1865 | } else if (of_device_is_compatible(np, "aspeed,ast2600-mac23")) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/faraday/ftgmac100.c:1844:22: note: initialize the variable 'rgmii_delay_unit' to silence this warning
1844 | u32 rgmii_delay_unit;
| ^
| = 0
1 warning generated.
vim +1865 drivers/net/ethernet/faraday/ftgmac100.c
1838
1839 static int ftgmac100_set_ast2600_rgmii_delay(struct platform_device *pdev,
1840 u32 rgmii_tx_delay,
1841 u32 rgmii_rx_delay)
1842 {
1843 struct device_node *np = pdev->dev.of_node;
1844 u32 rgmii_delay_unit;
1845 struct regmap *scu;
1846 int dly_mask;
1847 int dly_reg;
1848 int id;
1849
1850 scu = syscon_regmap_lookup_by_phandle(np, "scu");
1851 if (IS_ERR(scu)) {
1852 dev_err(&pdev->dev, "failed to get scu");
1853 return PTR_ERR(scu);
1854 }
1855
1856 id = of_alias_get_id(np, "ethernet");
1857 if (id < 0 || id > 3) {
1858 dev_err(&pdev->dev, "get wrong alise id %d\n", id);
1859 return -EINVAL;
1860 }
1861
1862 if (of_device_is_compatible(np, "aspeed,ast2600-mac01")) {
1863 dly_reg = AST2600_MAC01_CLK_DLY;
1864 rgmii_delay_unit = AST2600_MAC01_CLK_DLY_UNIT;
> 1865 } else if (of_device_is_compatible(np, "aspeed,ast2600-mac23")) {
1866 dly_reg = AST2600_MAC23_CLK_DLY;
1867 rgmii_delay_unit = AST2600_MAC23_CLK_DLY_UNIT;
1868 }
1869
1870 rgmii_tx_delay = DIV_ROUND_CLOSEST(rgmii_tx_delay, rgmii_delay_unit);
1871 if (rgmii_tx_delay >= 32) {
1872 dev_err(&pdev->dev,
1873 "The index %u of TX delay setting is out of range\n",
1874 rgmii_tx_delay);
1875 return -EINVAL;
1876 }
1877
1878 rgmii_rx_delay = DIV_ROUND_CLOSEST(rgmii_rx_delay, rgmii_delay_unit);
1879 if (rgmii_rx_delay >= 32) {
1880 dev_err(&pdev->dev,
1881 "The index %u of RX delay setting is out of range\n",
1882 rgmii_rx_delay);
1883 return -EINVAL;
1884 }
1885
1886 /* Due to the hardware design reason, for MAC23 on AST2600, the zero
1887 * delay ns on RX is configured by setting value 0x1a.
1888 * List as below:
1889 * 0x1a -> 0 ns, 0x1b -> 0.25 ns, ... , 0x1f -> 1.25 ns,
1890 * 0x00 -> 1.5 ns, 0x01 -> 1.75 ns, ... , 0x19 -> 7.75 ns, 0x1a -> 0 ns
1891 */
1892 if (of_device_is_compatible(np, "aspeed,ast2600-mac23"))
1893 rgmii_rx_delay = (AST2600_MAC23_RX_DLY_0_NS + rgmii_rx_delay) &
1894 AST2600_MAC_TX_RX_DLY_MASK;
1895
1896 if (id == 0 || id == 2) {
1897 dly_mask = ASPEED_MAC0_2_TX_DLY | ASPEED_MAC0_2_RX_DLY;
1898 rgmii_tx_delay = FIELD_PREP(ASPEED_MAC0_2_TX_DLY, rgmii_tx_delay);
1899 rgmii_rx_delay = FIELD_PREP(ASPEED_MAC0_2_RX_DLY, rgmii_rx_delay);
1900 } else {
1901 dly_mask = ASPEED_MAC1_3_TX_DLY | ASPEED_MAC1_3_RX_DLY;
1902 rgmii_tx_delay = FIELD_PREP(ASPEED_MAC1_3_TX_DLY, rgmii_tx_delay);
1903 rgmii_rx_delay = FIELD_PREP(ASPEED_MAC1_3_RX_DLY, rgmii_rx_delay);
1904 }
1905
1906 regmap_update_bits(scu, dly_reg, dly_mask, rgmii_tx_delay | rgmii_rx_delay);
1907
1908 return 0;
1909 }
1910
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2026 Red Hat, Inc.