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 -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dwmac->reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dwmac->reg)) return PTR_ERR(dwmac->reg); plat_dat->bsp_priv = dwmac; plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); }
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; struct net_device *ndev; struct stmmac_priv *stpriv; 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) { ret = -ENOMEM; goto err_remove_config_dt; } ret = socfpga_dwmac_parse_data(dwmac, dev); if (ret) { dev_err(dev, "Unable to parse OF data\n"); goto err_remove_config_dt; } plat_dat->bsp_priv = dwmac; plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_remove_config_dt; ndev = platform_get_drvdata(pdev); stpriv = netdev_priv(ndev); /* The socfpga driver needs to control the stmmac reset to set the phy * mode. Create a copy of the core reset handle so it can be used by * the driver later. */ dwmac->stmmac_rst = stpriv->stmmac_rst; ret = socfpga_dwmac_set_phy_mode(dwmac); if (ret) goto err_dvr_remove; return 0; err_dvr_remove: stmmac_dvr_remove(&pdev->dev); err_remove_config_dt: stmmac_remove_config_dt(pdev, plat_dat); return ret; }
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) goto err_remove_config_dt; } ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_exit; return 0; err_exit: if (plat_dat->exit) plat_dat->exit(pdev, plat_dat->bsp_priv); err_remove_config_dt: if (pdev->dev.of_node) stmmac_remove_config_dt(pdev, plat_dat); return ret; }
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; 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->fix_mac_speed = rk_fix_speed; plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data); if (IS_ERR(plat_dat->bsp_priv)) { ret = PTR_ERR(plat_dat->bsp_priv); goto err_remove_config_dt; } ret = rk_gmac_clk_init(plat_dat); if (ret) return ret; ret = rk_gmac_powerup(plat_dat->bsp_priv); if (ret) goto err_remove_config_dt; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_gmac_powerdown; return 0; err_gmac_powerdown: rk_gmac_powerdown(plat_dat->bsp_priv); err_remove_config_dt: stmmac_remove_config_dt(pdev, plat_dat); return ret; }
static int oxnas_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct device_node *sysctrl; struct oxnas_dwmac *dwmac; int ret; sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0); if (!sysctrl) { dev_err(&pdev->dev, "failed to get sys-ctrl node\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 -ENOMEM; dwmac->dev = &pdev->dev; plat_dat->bsp_priv = dwmac; dwmac->regmap = syscon_node_to_regmap(sysctrl); if (IS_ERR(dwmac->regmap)) { dev_err(&pdev->dev, "failed to have sysctrl regmap\n"); return PTR_ERR(dwmac->regmap); } dwmac->clk = devm_clk_get(&pdev->dev, "gmac"); if (IS_ERR(dwmac->clk)) return PTR_ERR(dwmac->clk); ret = oxnas_dwmac_init(dwmac); if (ret) return ret; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) clk_disable_unprepare(dwmac->clk); return ret; }
static int stm32_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct stm32_dwmac *dwmac; 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) { ret = -ENOMEM; goto err_remove_config_dt; } ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); if (ret) { dev_err(&pdev->dev, "Unable to parse OF data\n"); goto err_remove_config_dt; } plat_dat->bsp_priv = dwmac; ret = stm32_dwmac_init(plat_dat); if (ret) goto err_remove_config_dt; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_clk_disable; return 0; err_clk_disable: stm32_dwmac_clk_disable(dwmac); err_remove_config_dt: stmmac_remove_config_dt(pdev, plat_dat); return ret; }
static int lpc18xx_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct regmap *reg; u8 ethmode; 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); plat_dat->has_gmac = true; 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); } if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII; } 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(reg, LPC18XX_CREG_CREG6, LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode); return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); }
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; 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->suspend = rk_gmac_suspend; plat_dat->resume = rk_gmac_resume; 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 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 -ENOMEM; gmac->pdev = pdev; err = ipq806x_gmac_of_parse(gmac); if (IS_ERR(err)) { dev_err(dev, "device tree parsing error\n"); return PTR_ERR(err); } regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL, QSGMII_PCS_CAL_LCKDT_CTL_RST); /* Inter frame gap is set to 12 */ val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET | 12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET; /* We also initiate an AXI low power exit request */ val |= NSS_COMMON_GMAC_CTL_CSYS_REQ; switch (gmac->phy_mode) { case PHY_INTERFACE_MODE_RGMII: val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL; break; case PHY_INTERFACE_MODE_SGMII: val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL; break; default: dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", phy_modes(gmac->phy_mode)); return -EINVAL; } regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val); /* Configure the clock src according to the mode */ regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val); val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id)); switch (gmac->phy_mode) { case PHY_INTERFACE_MODE_RGMII: val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id); break; case PHY_INTERFACE_MODE_SGMII: val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id); break; default: dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", phy_modes(gmac->phy_mode)); return -EINVAL; } regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val); /* Enable PTP clock */ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val); val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id); regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val); if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) { regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id), QSGMII_PHY_CDR_EN | QSGMII_PHY_RX_FRONT_EN | QSGMII_PHY_RX_SIGNAL_DETECT_EN | QSGMII_PHY_TX_DRIVER_EN | QSGMII_PHY_QSGMII_EN | 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET | 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET | 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET | 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET | 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET); } plat_dat->has_gmac = true; plat_dat->bsp_priv = gmac; plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); }
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) { ret = -ENOMEM; goto err_remove_config_dt; } 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"); ret = PTR_ERR(gmac->tx_clk); goto err_remove_config_dt; } /* Optional regulator for PHY */ gmac->regulator = devm_regulator_get_optional(dev, "phy"); if (IS_ERR(gmac->regulator)) { if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto err_remove_config_dt; } 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) goto err_remove_config_dt; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_gmac_exit; return 0; err_gmac_exit: sun7i_gmac_exit(pdev, plat_dat->bsp_priv); err_remove_config_dt: stmmac_remove_config_dt(pdev, plat_dat); return ret; }
static int meson8b_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct resource *res; struct meson8b_dwmac *dwmac; 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) { ret = -ENOMEM; goto err_remove_config_dt; } res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dwmac->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dwmac->regs)) { ret = PTR_ERR(dwmac->regs); goto err_remove_config_dt; } dwmac->pdev = pdev; dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node); if (dwmac->phy_mode < 0) { dev_err(&pdev->dev, "missing phy-mode property\n"); ret = -EINVAL; goto err_remove_config_dt; } /* use 2ns as fallback since this value was previously hardcoded */ if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns", &dwmac->tx_delay_ns)) dwmac->tx_delay_ns = 2; ret = meson8b_init_rgmii_tx_clk(dwmac); if (ret) goto err_remove_config_dt; ret = meson8b_init_prg_eth(dwmac); if (ret) goto err_remove_config_dt; plat_dat->bsp_priv = dwmac; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_clk_disable; return 0; err_clk_disable: if (phy_interface_mode_is_rgmii(dwmac->phy_mode)) clk_disable_unprepare(dwmac->rgmii_tx_en_clk); err_remove_config_dt: stmmac_remove_config_dt(pdev, plat_dat); return ret; }