diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 42 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 50 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | 59 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 73 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 78 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 83 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 95 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 138 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 9 |
12 files changed, 358 insertions, 318 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c index e817a1a44..b1e5f2470 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c @@ -16,6 +16,46 @@ #include "stmmac.h" #include "stmmac_platform.h" +static int dwmac_generic_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + if (pdev->dev.of_node) { + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); + } + } else { + plat_dat = dev_get_platdata(&pdev->dev); + if (!plat_dat) { + dev_err(&pdev->dev, "no platform data provided\n"); + return -EINVAL; + } + + /* Set default value for multicast hash bins */ + plat_dat->multicast_filter_bins = HASH_TABLE_SIZE; + + /* Set default value for unicast filter entries */ + plat_dat->unicast_filter_entries = 1; + } + + /* Custom initialisation (if needed) */ + if (plat_dat->init) { + ret = plat_dat->init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + } + + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); +} + static const struct of_device_id dwmac_generic_match[] = { { .compatible = "st,spear600-gmac"}, { .compatible = "snps,dwmac-3.610"}, @@ -27,7 +67,7 @@ static const struct of_device_id dwmac_generic_match[] = { MODULE_DEVICE_TABLE(of, dwmac_generic_match); static struct platform_driver dwmac_generic_driver = { - .probe = stmmac_pltfr_probe, + .probe = dwmac_generic_probe, .remove = stmmac_pltfr_remove, .driver = { .name = STMMAC_RESOURCE_NAME, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index f0e4bb4e3..9d89bdbf0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -248,23 +248,40 @@ static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac) return NULL; } -static void *ipq806x_gmac_setup(struct platform_device *pdev) +static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed) +{ + struct ipq806x_gmac *gmac = priv; + + ipq806x_gmac_set_speed(gmac, speed); +} + +static int ipq806x_gmac_probe(struct platform_device *pdev) { + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; struct device *dev = &pdev->dev; struct ipq806x_gmac *gmac; int val; void *err; + val = stmmac_get_platform_resources(pdev, &stmmac_res); + if (val) + return val; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); if (!gmac) - return ERR_PTR(-ENOMEM); + return -ENOMEM; gmac->pdev = pdev; err = ipq806x_gmac_of_parse(gmac); - if (err) { + if (IS_ERR(err)) { dev_err(dev, "device tree parsing error\n"); - return err; + return PTR_ERR(err); } regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL, @@ -285,7 +302,7 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev) default: dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", phy_modes(gmac->phy_mode)); - return NULL; + return -EINVAL; } regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val); @@ -304,7 +321,7 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev) default: dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", phy_modes(gmac->phy_mode)); - return NULL; + return -EINVAL; } regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val); @@ -327,30 +344,21 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev) 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET); } - return gmac; -} + plat_dat->has_gmac = true; + plat_dat->bsp_priv = gmac; + plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; -static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed) -{ - struct ipq806x_gmac *gmac = priv; - - ipq806x_gmac_set_speed(gmac, speed); + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); } -static const struct stmmac_of_data ipq806x_gmac_data = { - .has_gmac = 1, - .setup = ipq806x_gmac_setup, - .fix_mac_speed = ipq806x_gmac_fix_mac_speed, -}; - static const struct of_device_id ipq806x_gmac_dwmac_match[] = { - { .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data }, + { .compatible = "qcom,ipq806x-gmac" }, { } }; MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match); static struct platform_driver ipq806x_gmac_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = ipq806x_gmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "ipq806x-gmac-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c index cb888d3eb..78e9d1861 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c @@ -25,66 +25,53 @@ # define LPC18XX_CREG_CREG6_ETHMODE_MII 0x0 # define LPC18XX_CREG_CREG6_ETHMODE_RMII 0x4 -struct lpc18xx_dwmac_priv_data { +static int lpc18xx_dwmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; struct regmap *reg; - int interface; -}; + u8 ethmode; + int ret; -static void *lpc18xx_dwmac_setup(struct platform_device *pdev) -{ - struct lpc18xx_dwmac_priv_data *dwmac; + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; - dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) - return ERR_PTR(-ENOMEM); + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); - dwmac->interface = of_get_phy_mode(pdev->dev.of_node); - if (dwmac->interface < 0) - return ERR_PTR(dwmac->interface); + plat_dat->has_gmac = true; - dwmac->reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg"); - if (IS_ERR(dwmac->reg)) { - dev_err(&pdev->dev, "Syscon lookup failed\n"); - return dwmac->reg; + reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg"); + if (IS_ERR(reg)) { + dev_err(&pdev->dev, "syscon lookup failed\n"); + return PTR_ERR(reg); } - return dwmac; -} - -static int lpc18xx_dwmac_init(struct platform_device *pdev, void *priv) -{ - struct lpc18xx_dwmac_priv_data *dwmac = priv; - u8 ethmode; - - if (dwmac->interface == PHY_INTERFACE_MODE_MII) { + if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII; - } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) { + } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; } else { dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); return -EINVAL; } - regmap_update_bits(dwmac->reg, LPC18XX_CREG_CREG6, + regmap_update_bits(reg, LPC18XX_CREG_CREG6, LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode); - return 0; + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); } -static const struct stmmac_of_data lpc18xx_dwmac_data = { - .has_gmac = 1, - .setup = lpc18xx_dwmac_setup, - .init = lpc18xx_dwmac_init, -}; - static const struct of_device_id lpc18xx_dwmac_match[] = { - { .compatible = "nxp,lpc1850-dwmac", .data = &lpc18xx_dwmac_data }, + { .compatible = "nxp,lpc1850-dwmac" }, { } }; MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match); static struct platform_driver lpc18xx_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = lpc18xx_dwmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "lpc18xx-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 61a324a87..c1bac1912 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -47,36 +47,45 @@ static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) writel(val, dwmac->reg); } -static void *meson6_dwmac_setup(struct platform_device *pdev) +static int meson6_dwmac_probe(struct platform_device *pdev) { + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; struct meson_dwmac *dwmac; struct resource *res; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); if (!dwmac) - return ERR_PTR(-ENOMEM); + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dwmac->reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dwmac->reg)) - return ERR_CAST(dwmac->reg); + return PTR_ERR(dwmac->reg); - return dwmac; -} + plat_dat->bsp_priv = dwmac; + plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; -static const struct stmmac_of_data meson6_dwmac_data = { - .setup = meson6_dwmac_setup, - .fix_mac_speed = meson6_dwmac_fix_mac_speed, -}; + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); +} static const struct of_device_id meson6_dwmac_match[] = { - { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, + { .compatible = "amlogic,meson6-dwmac" }, { } }; MODULE_DEVICE_TABLE(of, meson6_dwmac_match); static struct platform_driver meson6_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = meson6_dwmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "meson6-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 00a1e1e09..11baa4b19 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -46,7 +46,7 @@ struct rk_priv_data { struct platform_device *pdev; int phy_iface; struct regulator *regulator; - struct rk_gmac_ops *ops; + const struct rk_gmac_ops *ops; bool clk_enabled; bool clock_input; @@ -177,7 +177,7 @@ static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) } } -struct rk_gmac_ops rk3288_ops = { +static const struct rk_gmac_ops rk3288_ops = { .set_to_rgmii = rk3288_set_to_rgmii, .set_to_rmii = rk3288_set_to_rmii, .set_rgmii_speed = rk3288_set_rgmii_speed, @@ -289,7 +289,7 @@ static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) } } -struct rk_gmac_ops rk3368_ops = { +static const struct rk_gmac_ops rk3368_ops = { .set_to_rgmii = rk3368_set_to_rgmii, .set_to_rmii = rk3368_set_to_rmii, .set_rgmii_speed = rk3368_set_rgmii_speed, @@ -448,7 +448,7 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable) } static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, - struct rk_gmac_ops *ops) + const struct rk_gmac_ops *ops) { struct rk_priv_data *bsp_priv; struct device *dev = &pdev->dev; @@ -529,16 +529,6 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, return bsp_priv; } -static void *rk3288_gmac_setup(struct platform_device *pdev) -{ - return rk_gmac_setup(pdev, &rk3288_ops); -} - -static void *rk3368_gmac_setup(struct platform_device *pdev) -{ - return rk_gmac_setup(pdev, &rk3368_ops); -} - static int rk_gmac_init(struct platform_device *pdev, void *priv) { struct rk_priv_data *bsp_priv = priv; @@ -576,31 +566,52 @@ static void rk_fix_speed(void *priv, unsigned int speed) dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); } -static const struct stmmac_of_data rk3288_gmac_data = { - .has_gmac = 1, - .fix_mac_speed = rk_fix_speed, - .setup = rk3288_gmac_setup, - .init = rk_gmac_init, - .exit = rk_gmac_exit, -}; +static int rk_gmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + const struct rk_gmac_ops *data; + int ret; -static const struct stmmac_of_data rk3368_gmac_data = { - .has_gmac = 1, - .fix_mac_speed = rk_fix_speed, - .setup = rk3368_gmac_setup, - .init = rk_gmac_init, - .exit = rk_gmac_exit, -}; + data = of_device_get_match_data(&pdev->dev); + if (!data) { + dev_err(&pdev->dev, "no of match data provided\n"); + return -EINVAL; + } + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + plat_dat->has_gmac = true; + plat_dat->init = rk_gmac_init; + plat_dat->exit = rk_gmac_exit; + plat_dat->fix_mac_speed = rk_fix_speed; + + plat_dat->bsp_priv = rk_gmac_setup(pdev, data); + if (IS_ERR(plat_dat->bsp_priv)) + return PTR_ERR(plat_dat->bsp_priv); + + ret = rk_gmac_init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); +} static const struct of_device_id rk_gmac_dwmac_match[] = { - { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data}, - { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_gmac_data}, + { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, + { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, { } }; MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match); static struct platform_driver rk_gmac_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = rk_gmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "rk_gmac-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 8141c5b84..401383b25 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -175,31 +175,6 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) return 0; } -static void *socfpga_dwmac_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - int ret; - struct socfpga_dwmac *dwmac; - - dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) - return ERR_PTR(-ENOMEM); - - ret = socfpga_dwmac_parse_data(dwmac, dev); - if (ret) { - dev_err(dev, "Unable to parse OF data\n"); - return ERR_PTR(ret); - } - - ret = socfpga_dwmac_setup(dwmac); - if (ret) { - dev_err(dev, "couldn't setup SoC glue (%d)\n", ret); - return ERR_PTR(ret); - } - - return dwmac; -} - static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv) { struct socfpga_dwmac *dwmac = priv; @@ -257,21 +232,58 @@ static int socfpga_dwmac_init(struct platform_device *pdev, void *priv) return ret; } -static const struct stmmac_of_data socfpga_gmac_data = { - .setup = socfpga_dwmac_probe, - .init = socfpga_dwmac_init, - .exit = socfpga_dwmac_exit, - .fix_mac_speed = socfpga_dwmac_fix_mac_speed, -}; +static int socfpga_dwmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct device *dev = &pdev->dev; + int ret; + struct socfpga_dwmac *dwmac; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return -ENOMEM; + + ret = socfpga_dwmac_parse_data(dwmac, dev); + if (ret) { + dev_err(dev, "Unable to parse OF data\n"); + return ret; + } + + ret = socfpga_dwmac_setup(dwmac); + if (ret) { + dev_err(dev, "couldn't setup SoC glue (%d)\n", ret); + return ret; + } + + plat_dat->bsp_priv = dwmac; + plat_dat->init = socfpga_dwmac_init; + plat_dat->exit = socfpga_dwmac_exit; + plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; + + ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); +} static const struct of_device_id socfpga_dwmac_match[] = { - { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data }, + { .compatible = "altr,socfpga-stmmac" }, { } }; MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); static struct platform_driver socfpga_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = socfpga_dwmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "socfpga-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index a2e8111c5..7f6f4a4fc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -21,6 +21,7 @@ #include <linux/regmap.h> #include <linux/clk.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_net.h> #include "stmmac_platform.h" @@ -128,6 +129,11 @@ struct sti_dwmac { struct device *dev; struct regmap *regmap; u32 speed; + void (*fix_retime_src)(void *priv, unsigned int speed); +}; + +struct sti_dwmac_of_data { + void (*fix_retime_src)(void *priv, unsigned int speed); }; static u32 phy_intf_sels[] = { @@ -222,8 +228,9 @@ static void stid127_fix_retime_src(void *priv, u32 spd) regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val); } -static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac) +static int sti_dwmac_init(struct platform_device *pdev, void *priv) { + struct sti_dwmac *dwmac = priv; struct regmap *regmap = dwmac->regmap; int iface = dwmac->interface; struct device *dev = dwmac->dev; @@ -241,28 +248,8 @@ static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac) val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; regmap_update_bits(regmap, reg, ENMII_MASK, val); -} - -static int stix4xx_init(struct platform_device *pdev, void *priv) -{ - struct sti_dwmac *dwmac = priv; - u32 spd = dwmac->speed; - - sti_dwmac_ctrl_init(dwmac); - - stih4xx_fix_retime_src(priv, spd); - - return 0; -} -static int stid127_init(struct platform_device *pdev, void *priv) -{ - struct sti_dwmac *dwmac = priv; - u32 spd = dwmac->speed; - - sti_dwmac_ctrl_init(dwmac); - - stid127_fix_retime_src(priv, spd); + dwmac->fix_retime_src(priv, dwmac->speed); return 0; } @@ -334,36 +321,58 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, return 0; } -static void *sti_dwmac_setup(struct platform_device *pdev) +static int sti_dwmac_probe(struct platform_device *pdev) { + struct plat_stmmacenet_data *plat_dat; + const struct sti_dwmac_of_data *data; + struct stmmac_resources stmmac_res; struct sti_dwmac *dwmac; int ret; + data = of_device_get_match_data(&pdev->dev); + if (!data) { + dev_err(&pdev->dev, "No OF match data provided\n"); + return -EINVAL; + } + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); if (!dwmac) - return ERR_PTR(-ENOMEM); + return -ENOMEM; ret = sti_dwmac_parse_data(dwmac, pdev); if (ret) { dev_err(&pdev->dev, "Unable to parse OF data\n"); - return ERR_PTR(ret); + return ret; } - return dwmac; + dwmac->fix_retime_src = data->fix_retime_src; + + plat_dat->bsp_priv = dwmac; + plat_dat->init = sti_dwmac_init; + plat_dat->exit = sti_dwmac_exit; + plat_dat->fix_mac_speed = data->fix_retime_src; + + ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); } -static const struct stmmac_of_data stih4xx_dwmac_data = { - .fix_mac_speed = stih4xx_fix_retime_src, - .setup = sti_dwmac_setup, - .init = stix4xx_init, - .exit = sti_dwmac_exit, +static const struct sti_dwmac_of_data stih4xx_dwmac_data = { + .fix_retime_src = stih4xx_fix_retime_src, }; -static const struct stmmac_of_data stid127_dwmac_data = { - .fix_mac_speed = stid127_fix_retime_src, - .setup = sti_dwmac_setup, - .init = stid127_init, - .exit = sti_dwmac_exit, +static const struct sti_dwmac_of_data stid127_dwmac_data = { + .fix_retime_src = stid127_fix_retime_src, }; static const struct of_device_id sti_dwmac_match[] = { @@ -376,7 +385,7 @@ static const struct of_device_id sti_dwmac_match[] = { MODULE_DEVICE_TABLE(of, sti_dwmac_match); static struct platform_driver sti_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = sti_dwmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "sti-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index 15048ca39..52b8ed9bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c @@ -33,35 +33,6 @@ struct sunxi_priv_data { struct regulator *regulator; }; -static void *sun7i_gmac_setup(struct platform_device *pdev) -{ - struct sunxi_priv_data *gmac; - struct device *dev = &pdev->dev; - - gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); - if (!gmac) - return ERR_PTR(-ENOMEM); - - gmac->interface = of_get_phy_mode(dev->of_node); - - gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); - if (IS_ERR(gmac->tx_clk)) { - dev_err(dev, "could not get tx clock\n"); - return gmac->tx_clk; - } - - /* Optional regulator for PHY */ - gmac->regulator = devm_regulator_get_optional(dev, "phy"); - if (IS_ERR(gmac->regulator)) { - if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) - return ERR_PTR(-EPROBE_DEFER); - dev_info(dev, "no regulator found\n"); - gmac->regulator = NULL; - } - - return gmac; -} - #define SUN7I_GMAC_GMII_RGMII_RATE 125000000 #define SUN7I_GMAC_MII_RATE 25000000 @@ -132,25 +103,67 @@ static void sun7i_fix_speed(void *priv, unsigned int speed) } } -/* of_data specifying hardware features and callbacks. - * hardware features were copied from Allwinner drivers. */ -static const struct stmmac_of_data sun7i_gmac_data = { - .has_gmac = 1, - .tx_coe = 1, - .fix_mac_speed = sun7i_fix_speed, - .setup = sun7i_gmac_setup, - .init = sun7i_gmac_init, - .exit = sun7i_gmac_exit, -}; +static int sun7i_gmac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct sunxi_priv_data *gmac; + struct device *dev = &pdev->dev; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); + if (!gmac) + return -ENOMEM; + + gmac->interface = of_get_phy_mode(dev->of_node); + + gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); + if (IS_ERR(gmac->tx_clk)) { + dev_err(dev, "could not get tx clock\n"); + return PTR_ERR(gmac->tx_clk); + } + + /* Optional regulator for PHY */ + gmac->regulator = devm_regulator_get_optional(dev, "phy"); + if (IS_ERR(gmac->regulator)) { + if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_info(dev, "no regulator found\n"); + gmac->regulator = NULL; + } + + /* platform data specifying hardware features and callbacks. + * hardware features were copied from Allwinner drivers. */ + plat_dat->tx_coe = 1; + plat_dat->has_gmac = true; + plat_dat->bsp_priv = gmac; + plat_dat->init = sun7i_gmac_init; + plat_dat->exit = sun7i_gmac_exit; + plat_dat->fix_mac_speed = sun7i_fix_speed; + + ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); +} static const struct of_device_id sun7i_dwmac_match[] = { - { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, + { .compatible = "allwinner,sun7i-a20-gmac" }, { } }; MODULE_DEVICE_TABLE(of, sun7i_dwmac_match); static struct platform_driver sun7i_dwmac_driver = { - .probe = stmmac_pltfr_probe, + .probe = sun7i_gmac_probe, .remove = stmmac_pltfr_remove, .driver = { .name = "sun7i-dwmac", diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 771cda2a4..2e51b816a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -721,10 +721,13 @@ static int stmmac_get_ts_info(struct net_device *dev, { struct stmmac_priv *priv = netdev_priv(dev); - if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) { + if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) { - info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RAW_HARDWARE; if (priv->ptp_clock) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index b735fa22a..ebf6abc48 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -161,11 +161,16 @@ int stmmac_mdio_reset(struct mii_bus *bus) if (!gpio_request(reset_gpio, "mdio-reset")) { gpio_direction_output(reset_gpio, active_low ? 1 : 0); - udelay(data->delays[0]); + if (data->delays[0]) + msleep(DIV_ROUND_UP(data->delays[0], 1000)); + gpio_set_value(reset_gpio, active_low ? 0 : 1); - udelay(data->delays[1]); + if (data->delays[1]) + msleep(DIV_ROUND_UP(data->delays[1], 1000)); + gpio_set_value(reset_gpio, active_low ? 1 : 0); - udelay(data->delays[2]); + if (data->delays[2]) + msleep(DIV_ROUND_UP(data->delays[2], 1000)); } } #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index bcdc8955c..d02691ba3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -104,32 +104,16 @@ static int dwmac1000_validate_ucast_entries(int ucast_entries) * this function is to read the driver parameters from device-tree and * set some private fields that will be used by the main at runtime. */ -static int stmmac_probe_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat, - const char **mac) +struct plat_stmmacenet_data * +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) { struct device_node *np = pdev->dev.of_node; + struct plat_stmmacenet_data *plat; struct stmmac_dma_cfg *dma_cfg; - const struct of_device_id *device; - struct device *dev = &pdev->dev; - - device = of_match_device(dev->driver->of_match_table, dev); - if (device->data) { - const struct stmmac_of_data *data = device->data; - plat->has_gmac = data->has_gmac; - plat->enh_desc = data->enh_desc; - plat->tx_coe = data->tx_coe; - plat->rx_coe = data->rx_coe; - plat->bugged_jumbo = data->bugged_jumbo; - plat->pmt = data->pmt; - plat->riwt_off = data->riwt_off; - plat->fix_mac_speed = data->fix_mac_speed; - plat->bus_setup = data->bus_setup; - plat->setup = data->setup; - plat->free = data->free; - plat->init = data->init; - plat->exit = data->exit; - } + + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); + if (!plat) + return ERR_PTR(-ENOMEM); *mac = of_get_mac_address(np); plat->interface = of_get_phy_mode(np); @@ -151,7 +135,7 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, /* If phy-handle is not specified, check if we have a fixed-phy */ if (!plat->phy_node && of_phy_is_fixed_link(np)) { if ((of_phy_register_fixed_link(np) < 0)) - return -ENODEV; + return ERR_PTR(-ENODEV); plat->phy_node = of_node_get(np); } @@ -182,6 +166,12 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, */ plat->maxmtu = JUMBO_LEN; + /* Set default value for multicast hash bins */ + plat->multicast_filter_bins = HASH_TABLE_SIZE; + + /* Set default value for unicast filter entries */ + plat->unicast_filter_entries = 1; + /* * Currently only the properties needed on SPEAr600 * are provided. All other properties should be added @@ -222,7 +212,7 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, GFP_KERNEL); if (!dma_cfg) { of_node_put(np); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } plat->dma_cfg = dma_cfg; of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); @@ -240,44 +230,34 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); } - return 0; + return plat; } #else -static int stmmac_probe_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat, - const char **mac) +struct plat_stmmacenet_data * +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) { - return -ENOSYS; + return ERR_PTR(-ENOSYS); } #endif /* CONFIG_OF */ +EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); -/** - * stmmac_pltfr_probe - platform driver probe. - * @pdev: platform device pointer - * Description: platform_device probe function. It is to allocate - * the necessary platform resources, invoke custom helper (if required) and - * invoke the main probe function. - */ -int stmmac_pltfr_probe(struct platform_device *pdev) +int stmmac_get_platform_resources(struct platform_device *pdev, + struct stmmac_resources *stmmac_res) { - struct stmmac_resources stmmac_res; - int ret = 0; struct resource *res; - struct device *dev = &pdev->dev; - struct plat_stmmacenet_data *plat_dat = NULL; - memset(&stmmac_res, 0, sizeof(stmmac_res)); + memset(stmmac_res, 0, sizeof(*stmmac_res)); /* Get IRQ information early to have an ability to ask for deferred * probe if needed before we went too far with resource allocation. */ - stmmac_res.irq = platform_get_irq_byname(pdev, "macirq"); - if (stmmac_res.irq < 0) { - if (stmmac_res.irq != -EPROBE_DEFER) { - dev_err(dev, + stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); + if (stmmac_res->irq < 0) { + if (stmmac_res->irq != -EPROBE_DEFER) { + dev_err(&pdev->dev, "MAC IRQ configuration information not found\n"); } - return stmmac_res.irq; + return stmmac_res->irq; } /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq @@ -287,64 +267,23 @@ int stmmac_pltfr_probe(struct platform_device *pdev) * In case the wake up interrupt is not passed from the platform * so the driver will continue to use the mac irq (ndev->irq) */ - stmmac_res.wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); - if (stmmac_res.wol_irq < 0) { - if (stmmac_res.wol_irq == -EPROBE_DEFER) + stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); + if (stmmac_res->wol_irq < 0) { + if (stmmac_res->wol_irq == -EPROBE_DEFER) return -EPROBE_DEFER; - stmmac_res.wol_irq = stmmac_res.irq; + stmmac_res->wol_irq = stmmac_res->irq; } - stmmac_res.lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); - if (stmmac_res.lpi_irq == -EPROBE_DEFER) + stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); + if (stmmac_res->lpi_irq == -EPROBE_DEFER) return -EPROBE_DEFER; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - stmmac_res.addr = devm_ioremap_resource(dev, res); - if (IS_ERR(stmmac_res.addr)) - return PTR_ERR(stmmac_res.addr); - - plat_dat = dev_get_platdata(&pdev->dev); - - if (!plat_dat) - plat_dat = devm_kzalloc(&pdev->dev, - sizeof(struct plat_stmmacenet_data), - GFP_KERNEL); - if (!plat_dat) { - pr_err("%s: ERROR: no memory", __func__); - return -ENOMEM; - } - - /* Set default value for multicast hash bins */ - plat_dat->multicast_filter_bins = HASH_TABLE_SIZE; - - /* Set default value for unicast filter entries */ - plat_dat->unicast_filter_entries = 1; - - if (pdev->dev.of_node) { - ret = stmmac_probe_config_dt(pdev, plat_dat, &stmmac_res.mac); - if (ret) { - pr_err("%s: main dt probe failed", __func__); - return ret; - } - } + stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res); - /* Custom setup (if needed) */ - if (plat_dat->setup) { - plat_dat->bsp_priv = plat_dat->setup(pdev); - if (IS_ERR(plat_dat->bsp_priv)) - return PTR_ERR(plat_dat->bsp_priv); - } - - /* Custom initialisation (if needed)*/ - if (plat_dat->init) { - ret = plat_dat->init(pdev, plat_dat->bsp_priv); - if (unlikely(ret)) - return ret; - } - - return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + return PTR_ERR_OR_ZERO(stmmac_res->addr); } -EXPORT_SYMBOL_GPL(stmmac_pltfr_probe); +EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); /** * stmmac_pltfr_remove @@ -361,9 +300,6 @@ int stmmac_pltfr_remove(struct platform_device *pdev) if (priv->plat->exit) priv->plat->exit(pdev, priv->plat->bsp_priv); - if (priv->plat->free) - priv->plat->free(pdev, priv->plat->bsp_priv); - return ret; } EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index 71da86d7b..ffeb8d9e2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -19,7 +19,14 @@ #ifndef __STMMAC_PLATFORM_H__ #define __STMMAC_PLATFORM_H__ -int stmmac_pltfr_probe(struct platform_device *pdev); +#include "stmmac.h" + +struct plat_stmmacenet_data * +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); + +int stmmac_get_platform_resources(struct platform_device *pdev, + struct stmmac_resources *stmmac_res); + int stmmac_pltfr_remove(struct platform_device *pdev); extern const struct dev_pm_ops stmmac_pltfr_pm_ops; |