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; }
/** * stmmac_pci_probe * * @pdev: pci device pointer * @id: pointer to table of device id/id's. * * Description: This probing function gets called for all PCI devices which * match the ID table and are not "owned" by other driver yet. This function * gets passed a "struct pci_dev *" for each device whose entry in the ID table * matches the device. The probe functions returns zero when the driver choose * to take "ownership" of the device or an error code(-ve no) otherwise. */ static int stmmac_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data; struct plat_stmmacenet_data *plat; struct stmmac_resources res; int i; int ret; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) return -ENOMEM; plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(*plat->mdio_bus_data), GFP_KERNEL); if (!plat->mdio_bus_data) return -ENOMEM; plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); if (!plat->dma_cfg) return -ENOMEM; /* Enable pci device */ ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", __func__); return ret; } /* Get the base address of device */ for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { if (pci_resource_len(pdev, i) == 0) continue; ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev)); if (ret) return ret; break; } pci_set_master(pdev); ret = info->setup(pdev, plat); if (ret) return ret; pci_enable_msi(pdev); memset(&res, 0, sizeof(res)); res.addr = pcim_iomap_table(pdev)[i]; res.wol_irq = pdev->irq; res.irq = pdev->irq; return stmmac_dvr_probe(&pdev->dev, plat, &res); }
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); }
/** * stmmac_pltfr_probe * @pdev: platform device pointer * Description: platform_device probe function. It allocates * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat = NULL; const char *mac = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; if (!request_mem_region(res->start, resource_size(res), pdev->name)) { pr_err("%s: ERROR: memory allocation failed" "cannot get the I/O addr 0x%x\n", __func__, (unsigned int)res->start); return -EBUSY; } addr = ioremap(res->start, resource_size(res)); if (!addr) { pr_err("%s: ERROR: memory mapping failed", __func__); ret = -ENOMEM; goto out_release_region; } if (pdev->dev.of_node) { plat_dat = devm_kzalloc(&pdev->dev, sizeof(struct plat_stmmacenet_data), GFP_KERNEL); if (!plat_dat) { pr_err("%s: ERROR: no memory", __func__); ret = -ENOMEM; goto out_unmap; } ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); if (ret) { pr_err("%s: main dt probe failed", __func__); goto out_unmap; } } else { plat_dat = pdev->dev.platform_data; } /* Custom initialisation (if needed)*/ if (plat_dat->init) { ret = plat_dat->init(pdev); if (unlikely(ret)) goto out_unmap; } priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); if (!priv) { pr_err("%s: main driver probe failed", __func__); goto out_unmap; } /* Get MAC address if available (DT) */ if (mac) memcpy(priv->dev->dev_addr, mac, ETH_ALEN); /* Get the MAC information */ priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); if (priv->dev->irq == -ENXIO) { pr_err("%s: ERROR: MAC IRQ configuration " "information not found\n", __func__); ret = -ENXIO; goto out_unmap; } /* * On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code * named as "eth_wake_irq" * * In case the wake up interrupt is not passed from the platform * so the driver will continue to use the mac irq (ndev->irq) */ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); if (priv->wol_irq == -ENXIO) priv->wol_irq = priv->dev->irq; platform_set_drvdata(pdev, priv->dev); pr_debug("STMMAC platform driver registration completed"); return 0; out_unmap: iounmap(addr); platform_set_drvdata(pdev, NULL); out_release_region: release_mem_region(res->start, resource_size(res)); return ret; }
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); }
/** * stmmac_pci_probe * * @pdev: pci device pointer * @id: pointer to table of device id/id's. * * Description: This probing function gets called for all PCI devices which * match the ID table and are not "owned" by other driver yet. This function * gets passed a "struct pci_dev *" for each device whose entry in the ID table * matches the device. The probe functions returns zero when the driver choose * to take "ownership" of the device or an error code(-ve no) otherwise. */ static int __devinit stmmac_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret = 0; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; int i; /* Enable pci device */ ret = pci_enable_device(pdev); if (ret) { pr_err("%s : ERROR: failed to enable %s device\n", __func__, pci_name(pdev)); return ret; } if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) { pr_err("%s: ERROR: failed to get PCI region\n", __func__); ret = -ENODEV; goto err_out_req_reg_failed; } /* Get the base address of device */ for (i = 0; i <= 5; i++) { if (pci_resource_len(pdev, i) == 0) continue; addr = pci_iomap(pdev, i, 0); if (addr == NULL) { pr_err("%s: ERROR: cannot map register memory, aborting", __func__); ret = -EIO; goto err_out_map_failed; } break; } pci_set_master(pdev); stmmac_default_data(); priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr); if (!priv) { pr_err("%s: main driver probe failed", __func__); goto err_out; } priv->dev->irq = pdev->irq; priv->wol_irq = pdev->irq; pci_set_drvdata(pdev, priv->dev); pr_debug("STMMAC platform driver registration completed"); return 0; err_out: pci_clear_master(pdev); err_out_map_failed: pci_release_regions(pdev); err_out_req_reg_failed: pci_disable_device(pdev); 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; }
/** * stmmac_pltfr_probe * @pdev: platform device pointer * Description: platform_device probe function. It allocates * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; //addr =phys_to_virt(); struct resource *res; struct device *dev = &pdev->dev; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat = NULL; const char *mac = NULL; #ifdef CONFIG_DWMAC_MESON switch_mod_gate_by_name("ethernet",1); #endif res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; addr = devm_ioremap_resource(dev, res); //addr = ( void* )(0xfe0c0000); printk("ethernet base addr is %x\n", (unsigned int)addr); plat_dat = dev_get_platdata(&pdev->dev); if (pdev->dev.of_node) { 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; } ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); if (ret) { pr_err("%s: main dt probe failed", __func__); return ret; } } /* 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; } priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); if (IS_ERR(priv)) { pr_err("%s: main driver probe failed", __func__); return PTR_ERR(priv); } /* Get MAC address if available (DT) */ if (mac) memcpy(priv->dev->dev_addr, mac, ETH_ALEN); /* Get the MAC information */ priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); if (priv->dev->irq < 0) { if (priv->dev->irq != -EPROBE_DEFER) { netdev_err(priv->dev, "MAC IRQ configuration information not found\n"); } return priv->dev->irq; } /* * On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code * named as "eth_wake_irq" * * In case the wake up interrupt is not passed from the platform * so the driver will continue to use the mac irq (ndev->irq) */ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); if (priv->wol_irq < 0) { if (priv->wol_irq == -EPROBE_DEFER) return -EPROBE_DEFER; priv->wol_irq = priv->dev->irq; } priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); if (priv->lpi_irq == -EPROBE_DEFER) return -EPROBE_DEFER; platform_set_drvdata(pdev, priv->dev); pr_debug("STMMAC platform driver registration completed"); return 0; }
/** * stmmac_pltfr_probe * @pdev: platform device pointer * Description: platform_device probe function. It allocates * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; if (!request_mem_region(res->start, resource_size(res), pdev->name)) { pr_err("%s: ERROR: memory allocation failed" "cannot get the I/O addr 0x%x\n", __func__, (unsigned int)res->start); return -EBUSY; } addr = ioremap(res->start, resource_size(res)); if (!addr) { pr_err("%s: ERROR: memory mapping failed", __func__); ret = -ENOMEM; goto out_release_region; } plat_dat = pdev->dev.platform_data; priv = stmmac_dvr_probe(&(pdev->dev), plat_dat); if (!priv) { pr_err("%s: main drivr probe failed", __func__); goto out_release_region; } priv->ioaddr = addr; /* Set the I/O base addr */ priv->dev->base_addr = (unsigned long)addr; /* Get the MAC information */ priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); if (priv->dev->irq == -ENXIO) { pr_err("%s: ERROR: MAC IRQ configuration " "information not found\n", __func__); ret = -ENXIO; goto out_unmap; } /* * On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code * named as "eth_wake_irq" * * In case the wake up interrupt is not passed from the platform * so the driver will continue to use the mac irq (ndev->irq) */ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); if (priv->wol_irq == -ENXIO) priv->wol_irq = priv->dev->irq; platform_set_drvdata(pdev, priv->dev); /* Custom initialisation */ if (priv->plat->init) { ret = priv->plat->init(pdev); if (unlikely(ret)) goto out_unmap; } pr_debug("STMMAC platform driver registration completed"); return 0; out_unmap: iounmap(addr); platform_set_drvdata(pdev, NULL); out_release_region: release_mem_region(res->start, resource_size(res)); return ret; }
/** * stmmac_pltfr_probe * @pdev: platform device pointer * Description: platform_device probe function. It allocates * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; struct device *dev = &pdev->dev; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat = NULL; const char *mac = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; addr = devm_ioremap_resource(dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); if (pdev->dev.of_node) { 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; } ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); if (ret) { pr_err("%s: main dt probe failed", __func__); return ret; } } else { plat_dat = pdev->dev.platform_data; } /* Custom initialisation (if needed)*/ if (plat_dat->init) { ret = plat_dat->init(pdev); if (unlikely(ret)) return ret; } gmac_clk_init(&(pdev->dev)); priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); if (!priv) { pr_err("%s: main driver probe failed", __func__); return -ENODEV; } /* Get MAC address if available (DT) */ if (mac) memcpy(priv->dev->dev_addr, mac, ETH_ALEN); /* Get the MAC information */ priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); if (priv->dev->irq == -ENXIO) { pr_err("%s: ERROR: MAC IRQ configuration " "information not found\n", __func__); return -ENXIO; } /* * On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code * named as "eth_wake_irq" * * In case the wake up interrupt is not passed from the platform * so the driver will continue to use the mac irq (ndev->irq) */ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); if (priv->wol_irq == -ENXIO) priv->wol_irq = priv->dev->irq; priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); platform_set_drvdata(pdev, priv->dev); pr_debug("STMMAC platform driver registration completed"); return 0; }
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; }