|
@@ -104,18 +104,20 @@ 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;
|
|
|
+ const struct stmmac_of_data *data;
|
|
|
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 = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
|
|
|
+ if (!plat)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+
|
|
|
+ data = of_device_get_match_data(&pdev->dev);
|
|
|
+ if (data) {
|
|
|
plat->has_gmac = data->has_gmac;
|
|
|
plat->enh_desc = data->enh_desc;
|
|
|
plat->tx_coe = data->tx_coe;
|
|
@@ -151,7 +153,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 +184,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 +230,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 +248,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,45 +285,61 @@ 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;
|
|
|
- }
|
|
|
+ stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res);
|
|
|
+ if (IS_ERR(stmmac_res->addr))
|
|
|
+ return PTR_ERR(stmmac_res->addr);
|
|
|
|
|
|
- /* Set default value for multicast hash bins */
|
|
|
- plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
|
|
|
|
|
|
- /* Set default value for unicast filter entries */
|
|
|
- plat_dat->unicast_filter_entries = 1;
|
|
|
+/**
|
|
|
+ * 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)
|
|
|
+{
|
|
|
+ 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) {
|
|
|
- ret = stmmac_probe_config_dt(pdev, plat_dat, &stmmac_res.mac);
|
|
|
- if (ret) {
|
|
|
- pr_err("%s: main dt probe failed", __func__);
|
|
|
- return ret;
|
|
|
+ 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 setup (if needed) */
|