From b1cffac4792b007866f57bd77b4486ad738855da Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Wed, 18 Jun 2025 11:41:09 +0100 Subject: [PATCH 1/2] net: stmmac: loongson1: provide match data struct Provide a structure for match data rather than using the function pointer as match data. This allows stronger type-checking for the function itself, and allows extensions to the match data. Signed-off-by: Russell King (Oracle) Reviewed-by: Simon Horman Reviewed-by: Andrew Lunn Reviewed-by: Keguang Zhang Tested-by: Keguang Zhang # on LS1B & LS1C Link: https://patch.msgid.link/E1uRqE9-004c7G-CB@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c index 3e86810717d3..78d9540be10c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c @@ -46,6 +46,10 @@ struct ls1x_dwmac { struct regmap *regmap; }; +struct ls1x_data { + int (*init)(struct platform_device *pdev, void *bsp_priv); +}; + static int ls1b_dwmac_syscon_init(struct platform_device *pdev, void *priv) { struct ls1x_dwmac *dwmac = priv; @@ -143,9 +147,9 @@ static int ls1x_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; + const struct ls1x_data *data; struct regmap *regmap; struct ls1x_dwmac *dwmac; - int (*init)(struct platform_device *pdev, void *priv); int ret; ret = stmmac_get_platform_resources(pdev, &stmmac_res); @@ -159,8 +163,8 @@ static int ls1x_dwmac_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(regmap), "Unable to find syscon\n"); - init = of_device_get_match_data(&pdev->dev); - if (!init) { + data = of_device_get_match_data(&pdev->dev); + if (!data) { dev_err(&pdev->dev, "No of match data provided\n"); return -EINVAL; } @@ -175,21 +179,29 @@ static int ls1x_dwmac_probe(struct platform_device *pdev) "dt configuration failed\n"); plat_dat->bsp_priv = dwmac; - plat_dat->init = init; + plat_dat->init = data->init; dwmac->plat_dat = plat_dat; dwmac->regmap = regmap; return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } +static const struct ls1x_data ls1b_dwmac_data = { + .init = ls1b_dwmac_syscon_init, +}; + +static const struct ls1x_data ls1c_dwmac_data = { + .init = ls1c_dwmac_syscon_init, +}; + static const struct of_device_id ls1x_dwmac_match[] = { { .compatible = "loongson,ls1b-gmac", - .data = &ls1b_dwmac_syscon_init, + .data = &ls1b_dwmac_data, }, { .compatible = "loongson,ls1c-emac", - .data = &ls1c_dwmac_syscon_init, + .data = &ls1c_dwmac_data, }, { } }; From e3527bf4dc338ebf12488fdec3e7a952bf3db5dd Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Wed, 18 Jun 2025 11:41:14 +0100 Subject: [PATCH 2/2] net: stmmac: loongson1: get ls1b resource only once ls1b_dwmac_syscon_init() was getting the stmmac iomem resource to detect which GMAC block is being used. Move this to a separate setup() function that only runs at probe time, so it can sensibly behave with an unrecognised resource adress. Use this to set a MAC index (id) which is then used in place of testing the base address. Signed-off-by: Russell King (Oracle) Reviewed-by: Simon Horman Reviewed-by: Keguang Zhang Tested-by: Keguang Zhang # on LS1B & LS1C Link: https://patch.msgid.link/E1uRqEE-004c7M-Go@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c index 78d9540be10c..32b5d1492e2e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c @@ -44,28 +44,50 @@ struct ls1x_dwmac { struct plat_stmmacenet_data *plat_dat; struct regmap *regmap; + unsigned int id; }; struct ls1x_data { + int (*setup)(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat); int (*init)(struct platform_device *pdev, void *bsp_priv); }; +static int ls1b_dwmac_setup(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat) +{ + struct ls1x_dwmac *dwmac = plat_dat->bsp_priv; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + /* This shouldn't fail - stmmac_get_platform_resources() + * already mapped this resource. + */ + dev_err(&pdev->dev, "Could not get IO_MEM resources\n"); + return -EINVAL; + } + + if (res->start == LS1B_GMAC0_BASE) { + dwmac->id = 0; + } else if (res->start == LS1B_GMAC1_BASE) { + dwmac->id = 1; + } else { + dev_err(&pdev->dev, "Invalid Ethernet MAC base address %pR", + res); + return -EINVAL; + } + + return 0; +} + static int ls1b_dwmac_syscon_init(struct platform_device *pdev, void *priv) { struct ls1x_dwmac *dwmac = priv; struct plat_stmmacenet_data *plat = dwmac->plat_dat; struct regmap *regmap = dwmac->regmap; - struct resource *res; - unsigned long reg_base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Could not get IO_MEM resources\n"); - return -EINVAL; - } - reg_base = (unsigned long)res->start; - - if (reg_base == LS1B_GMAC0_BASE) { + if (dwmac->id == 0) { switch (plat->phy_interface) { case PHY_INTERFACE_MODE_RGMII_ID: regmap_update_bits(regmap, LS1X_SYSCON0, @@ -84,7 +106,7 @@ static int ls1b_dwmac_syscon_init(struct platform_device *pdev, void *priv) } regmap_update_bits(regmap, LS1X_SYSCON0, GMAC0_SHUT, 0); - } else if (reg_base == LS1B_GMAC1_BASE) { + } else if (dwmac->id == 1) { regmap_update_bits(regmap, LS1X_SYSCON0, GMAC1_USE_UART1 | GMAC1_USE_UART0, GMAC1_USE_UART1 | GMAC1_USE_UART0); @@ -108,10 +130,6 @@ static int ls1b_dwmac_syscon_init(struct platform_device *pdev, void *priv) } regmap_update_bits(regmap, LS1X_SYSCON1, GMAC1_SHUT, 0); - } else { - dev_err(&pdev->dev, "Invalid Ethernet MAC base address %lx", - reg_base); - return -EINVAL; } return 0; @@ -183,10 +201,17 @@ static int ls1x_dwmac_probe(struct platform_device *pdev) dwmac->plat_dat = plat_dat; dwmac->regmap = regmap; + if (data->setup) { + ret = data->setup(pdev, plat_dat); + if (ret) + return ret; + } + return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } static const struct ls1x_data ls1b_dwmac_data = { + .setup = ls1b_dwmac_setup, .init = ls1b_dwmac_syscon_init, };