diff options
Diffstat (limited to 'drivers/net/ethernet/ti/cpsw.c')
-rw-r--r-- | drivers/net/ethernet/ti/cpsw.c | 95 |
1 files changed, 58 insertions, 37 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 874fb297e..fc958067d 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -29,6 +29,7 @@ #include <linux/workqueue.h> #include <linux/delay.h> #include <linux/pm_runtime.h> +#include <linux/gpio.h> #include <linux/of.h> #include <linux/of_mdio.h> #include <linux/of_net.h> @@ -1789,7 +1790,6 @@ static void cpsw_get_drvinfo(struct net_device *ndev, strlcpy(info->driver, "cpsw", sizeof(info->driver)); strlcpy(info->version, "1.0", sizeof(info->version)); strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info)); - info->regdump_len = cpsw_get_regs_len(ndev); } static u32 cpsw_get_msglevel(struct net_device *ndev) @@ -2026,11 +2026,8 @@ static int cpsw_probe_dt(struct cpsw_priv *priv, for_each_child_of_node(node, slave_node) { struct cpsw_slave_data *slave_data = data->slave_data + i; const void *mac_addr = NULL; - u32 phyid; int lenp; const __be32 *parp; - struct device_node *mdio_node; - struct platform_device *mdio; /* This is no slave child node, continue */ if (strcmp(slave_node->name, "slave")) @@ -2038,20 +2035,45 @@ static int cpsw_probe_dt(struct cpsw_priv *priv, priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0); parp = of_get_property(slave_node, "phy_id", &lenp); - if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { - dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i); + if (of_phy_is_fixed_link(slave_node)) { + struct device_node *phy_node; + struct phy_device *phy_dev; + + /* In the case of a fixed PHY, the DT node associated + * to the PHY is the Ethernet MAC DT node. + */ + ret = of_phy_register_fixed_link(slave_node); + if (ret) + return ret; + phy_node = of_node_get(slave_node); + phy_dev = of_phy_find_device(phy_node); + if (!phy_dev) + return -ENODEV; + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, phy_dev->bus->id, phy_dev->addr); + } else if (parp) { + u32 phyid; + struct device_node *mdio_node; + struct platform_device *mdio; + + if (lenp != (sizeof(__be32) * 2)) { + dev_err(&pdev->dev, "Invalid slave[%d] phy_id property\n", i); + goto no_phy_slave; + } + mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); + phyid = be32_to_cpup(parp+1); + mdio = of_find_device_by_node(mdio_node); + of_node_put(mdio_node); + if (!mdio) { + dev_err(&pdev->dev, "Missing mdio platform device\n"); + return -EINVAL; + } + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, mdio->name, phyid); + } else { + dev_err(&pdev->dev, "No slave[%d] phy_id or fixed-link property\n", i); goto no_phy_slave; } - mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); - phyid = be32_to_cpup(parp+1); - mdio = of_find_device_by_node(mdio_node); - of_node_put(mdio_node); - if (!mdio) { - dev_err(&pdev->dev, "Missing mdio platform device\n"); - return -EINVAL; - } - snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), - PHY_ID_FMT, mdio->name, phyid); slave_data->phy_if = of_get_phy_mode(slave_node); if (slave_data->phy_if < 0) { dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n", @@ -2064,13 +2086,10 @@ no_phy_slave: if (mac_addr) { memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); } else { - if (of_machine_is_compatible("ti,am33xx")) { - ret = cpsw_am33xx_cm_get_macid(&pdev->dev, - 0x630, i, - slave_data->mac_addr); - if (ret) - return ret; - } + ret = ti_cm_get_macid(&pdev->dev, i, + slave_data->mac_addr); + if (ret) + return ret; } if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", @@ -2214,6 +2233,7 @@ static int cpsw_probe(struct platform_device *pdev) void __iomem *ss_regs; struct resource *res, *ss_res; const struct of_device_id *of_id; + struct gpio_descs *mode; u32 slave_offset, sliver_offset, slave_size; int ret = 0, i; int irq; @@ -2239,6 +2259,13 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_ndev_ret; } + mode = devm_gpiod_get_array_optional(&pdev->dev, "mode", GPIOD_OUT_LOW); + if (IS_ERR(mode)) { + ret = PTR_ERR(mode); + dev_err(&pdev->dev, "gpio request failed, ret %d\n", ret); + goto clean_ndev_ret; + } + /* * This may be required here for child devices. */ @@ -2400,7 +2427,7 @@ static int cpsw_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 1); if (ndev->irq < 0) { dev_err(priv->dev, "error getting irq resource\n"); - ret = -ENOENT; + ret = ndev->irq; goto clean_ale_ret; } @@ -2421,8 +2448,10 @@ static int cpsw_probe(struct platform_device *pdev) /* RX IRQ */ irq = platform_get_irq(pdev, 1); - if (irq < 0) + if (irq < 0) { + ret = irq; goto clean_ale_ret; + } priv->irqs_table[0] = irq; ret = devm_request_irq(&pdev->dev, irq, cpsw_rx_interrupt, @@ -2434,8 +2463,10 @@ static int cpsw_probe(struct platform_device *pdev) /* TX IRQ */ irq = platform_get_irq(pdev, 2); - if (irq < 0) + if (irq < 0) { + ret = irq; goto clean_ale_ret; + } priv->irqs_table[1] = irq; ret = devm_request_irq(&pdev->dev, irq, cpsw_tx_interrupt, @@ -2585,17 +2616,7 @@ static struct platform_driver cpsw_driver = { .remove = cpsw_remove, }; -static int __init cpsw_init(void) -{ - return platform_driver_register(&cpsw_driver); -} -late_initcall(cpsw_init); - -static void __exit cpsw_exit(void) -{ - platform_driver_unregister(&cpsw_driver); -} -module_exit(cpsw_exit); +module_platform_driver(cpsw_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cyril Chemparathy <cyril@ti.com>"); |