aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/arc/emac_main.c
diff options
context:
space:
mode:
authorRomain Perier <romain.perier@gmail.com>2014-08-26 13:14:51 +0000
committerDavid S. Miller <davem@davemloft.net>2014-08-27 16:40:26 -0700
commit23d2d9a630b98a554cc328c6b69c56fd285e0129 (patch)
tree265d7e4ceba509f54b494db5cdeb8d000f811d97 /drivers/net/ethernet/arc/emac_main.c
parentethernet: arc: mdio changes for future SoC glue layer devtree support (diff)
downloadlinux-dev-23d2d9a630b98a554cc328c6b69c56fd285e0129.tar.xz
linux-dev-23d2d9a630b98a554cc328c6b69c56fd285e0129.zip
ethernet: arc: Add support for specific SoC layer device tree bindings
Some platforms have special bank registers which might be used to select the correct clock or the right mode for Media Indepent Interface controllers. Sometimes, it is also required to activate vcc regulators in the right order to supply the ethernet controller at the right time. This patch is an architecture refactoring of the arc-emac device driver. It adds a new software design which allows to add specific platform glue layer. Each platform has now its own module which performs custom initialization and remove for the target and then calls to the core driver. Signed-off-by: Romain Perier <romain.perier@gmail.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/arc/emac_main.c80
1 files changed, 22 insertions, 58 deletions
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index bbc3157bed92..b35c69e1b147 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -26,8 +26,6 @@
#include "emac.h"
-#define DRV_NAME "arc_emac"
-#define DRV_VERSION "1.0"
/**
* arc_emac_adjust_link - Adjust the PHY link duplex.
@@ -120,8 +118,10 @@ static int arc_emac_set_settings(struct net_device *ndev,
static void arc_emac_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
{
- strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
- strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ struct arc_emac_priv *priv = netdev_priv(ndev);
+
+ strlcpy(info->driver, priv->drv_name, sizeof(info->driver));
+ strlcpy(info->version, priv->drv_version, sizeof(info->version));
}
static const struct ethtool_ops arc_emac_ethtool_ops = {
@@ -671,19 +671,16 @@ static const struct net_device_ops arc_emac_netdev_ops = {
#endif
};
-static int arc_emac_probe(struct platform_device *pdev)
+int arc_emac_probe(struct net_device *ndev, int interface)
{
- struct device *dev = &pdev->dev;
+ struct device *dev = ndev->dev.parent;
struct resource res_regs;
struct device_node *phy_node;
struct arc_emac_priv *priv;
- struct net_device *ndev;
const char *mac_addr;
unsigned int id, clock_frequency, irq;
int err;
- if (!dev->of_node)
- return -ENODEV;
/* Get PHY from device tree */
phy_node = of_parse_phandle(dev->of_node, "phy", 0);
@@ -706,12 +703,6 @@ static int arc_emac_probe(struct platform_device *pdev)
return -ENODEV;
}
- ndev = alloc_etherdev(sizeof(struct arc_emac_priv));
- if (!ndev)
- return -ENOMEM;
-
- dev_set_drvdata(dev, ndev);
- SET_NETDEV_DEV(ndev, dev);
ndev->netdev_ops = &arc_emac_netdev_ops;
ndev->ethtool_ops = &arc_emac_ethtool_ops;
@@ -724,28 +715,25 @@ static int arc_emac_probe(struct platform_device *pdev)
priv->regs = devm_ioremap_resource(dev, &res_regs);
if (IS_ERR(priv->regs)) {
- err = PTR_ERR(priv->regs);
- goto out_netdev;
+ return PTR_ERR(priv->regs);
}
dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs);
- priv->clk = of_clk_get(dev->of_node, 0);
- if (IS_ERR(priv->clk)) {
- /* Get CPU clock frequency from device tree */
- if (of_property_read_u32(dev->of_node, "clock-frequency",
- &clock_frequency)) {
- dev_err(dev, "failed to retrieve <clock-frequency> from device tree\n");
- err = -EINVAL;
- goto out_netdev;
- }
- } else {
+ if (priv->clk) {
err = clk_prepare_enable(priv->clk);
if (err) {
dev_err(dev, "failed to enable clock\n");
- goto out_clkget;
+ return err;
}
clock_frequency = clk_get_rate(priv->clk);
+ } else {
+ /* Get CPU clock frequency from device tree */
+ if (of_property_read_u32(dev->of_node, "clock-frequency",
+ &clock_frequency)) {
+ dev_err(dev, "failed to retrieve <clock-frequency> from device tree\n");
+ return -EINVAL;
+ }
}
id = arc_reg_get(priv, R_ID);
@@ -806,7 +794,7 @@ static int arc_emac_probe(struct platform_device *pdev)
}
priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ interface);
if (!priv->phy_dev) {
dev_err(dev, "of_phy_connect() failed\n");
err = -ENODEV;
@@ -833,20 +821,15 @@ out_netif_api:
out_mdio:
arc_mdio_remove(priv);
out_clken:
- if (!IS_ERR(priv->clk))
+ if (priv->clk)
clk_disable_unprepare(priv->clk);
-out_clkget:
- if (!IS_ERR(priv->clk))
- clk_put(priv->clk);
-out_netdev:
- free_netdev(ndev);
return err;
}
+EXPORT_SYMBOL_GPL(arc_emac_probe);
-static int arc_emac_remove(struct platform_device *pdev)
+int arc_emac_remove(struct net_device *ndev)
{
- struct device *dev = &pdev->dev;
- struct net_device *ndev = dev_get_drvdata(dev);
+ struct device *dev = ndev->dev.parent;
struct arc_emac_priv *priv = netdev_priv(ndev);
phy_disconnect(priv->phy_dev);
@@ -857,31 +840,12 @@ static int arc_emac_remove(struct platform_device *pdev)
if (!IS_ERR(priv->clk)) {
clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
}
- free_netdev(ndev);
return 0;
}
-
-static const struct of_device_id arc_emac_dt_ids[] = {
- { .compatible = "snps,arc-emac" },
- { /* Sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, arc_emac_dt_ids);
-
-static struct platform_driver arc_emac_driver = {
- .probe = arc_emac_probe,
- .remove = arc_emac_remove,
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = arc_emac_dt_ids,
- },
-};
-
-module_platform_driver(arc_emac_driver);
+EXPORT_SYMBOL_GPL(arc_emac_remove);
MODULE_AUTHOR("Alexey Brodkin <abrodkin@synopsys.com>");
MODULE_DESCRIPTION("ARC EMAC driver");