summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/ti/davinci_emac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/ti/davinci_emac.c')
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c208
1 files changed, 145 insertions, 63 deletions
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 4da93a5d7ec6..fce89a0ab06e 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -57,7 +57,12 @@
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
#include <linux/davinci_emac.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
#include <asm/irq.h>
#include <asm/page.h>
@@ -339,6 +344,9 @@ struct emac_priv {
u32 rx_addr_type;
atomic_t cur_tx;
const char *phy_id;
+#ifdef CONFIG_OF
+ struct device_node *phy_node;
+#endif
struct phy_device *phydev;
spinlock_t lock;
/*platform specific members*/
@@ -346,10 +354,6 @@ struct emac_priv {
void (*int_disable) (void);
};
-/* clock frequency for EMAC */
-static struct clk *emac_clk;
-static unsigned long emac_bus_frequency;
-
/* EMAC TX Host Error description strings */
static char *emac_txhost_errcodes[16] = {
"No error", "SOP error", "Ownership bit not set in SOP buffer",
@@ -375,7 +379,7 @@ static char *emac_rxhost_errcodes[16] = {
#define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
/**
- * emac_dump_regs: Dump important EMAC registers to debug terminal
+ * emac_dump_regs - Dump important EMAC registers to debug terminal
* @priv: The DaVinci EMAC private adapter structure
*
* Executes ethtool set cmd & sets phy mode
@@ -466,7 +470,7 @@ static void emac_dump_regs(struct emac_priv *priv)
}
/**
- * emac_get_drvinfo: Get EMAC driver information
+ * emac_get_drvinfo - Get EMAC driver information
* @ndev: The DaVinci EMAC network adapter
* @info: ethtool info structure containing name and version
*
@@ -481,7 +485,7 @@ static void emac_get_drvinfo(struct net_device *ndev,
}
/**
- * emac_get_settings: Get EMAC settings
+ * emac_get_settings - Get EMAC settings
* @ndev: The DaVinci EMAC network adapter
* @ecmd: ethtool command
*
@@ -500,7 +504,7 @@ static int emac_get_settings(struct net_device *ndev,
}
/**
- * emac_set_settings: Set EMAC settings
+ * emac_set_settings - Set EMAC settings
* @ndev: The DaVinci EMAC network adapter
* @ecmd: ethtool command
*
@@ -518,7 +522,7 @@ static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
}
/**
- * emac_get_coalesce : Get interrupt coalesce settings for this device
+ * emac_get_coalesce - Get interrupt coalesce settings for this device
* @ndev : The DaVinci EMAC network adapter
* @coal : ethtool coalesce settings structure
*
@@ -536,7 +540,7 @@ static int emac_get_coalesce(struct net_device *ndev,
}
/**
- * emac_set_coalesce : Set interrupt coalesce settings for this device
+ * emac_set_coalesce - Set interrupt coalesce settings for this device
* @ndev : The DaVinci EMAC network adapter
* @coal : ethtool coalesce settings structure
*
@@ -614,11 +618,9 @@ static int emac_set_coalesce(struct net_device *ndev,
}
-/**
- * ethtool_ops: DaVinci EMAC Ethtool structure
+/* ethtool_ops: DaVinci EMAC Ethtool structure
*
* Ethtool support for EMAC adapter
- *
*/
static const struct ethtool_ops ethtool_ops = {
.get_drvinfo = emac_get_drvinfo,
@@ -631,7 +633,7 @@ static const struct ethtool_ops ethtool_ops = {
};
/**
- * emac_update_phystatus: Update Phy status
+ * emac_update_phystatus - Update Phy status
* @priv: The DaVinci EMAC private adapter structure
*
* Updates phy status and takes action for network queue if required
@@ -697,7 +699,7 @@ static void emac_update_phystatus(struct emac_priv *priv)
}
/**
- * hash_get: Calculate hash value from mac address
+ * hash_get - Calculate hash value from mac address
* @addr: mac address to delete from hash table
*
* Calculates hash value from mac address
@@ -723,9 +725,9 @@ static u32 hash_get(u8 *addr)
}
/**
- * hash_add: Hash function to add mac addr from hash table
+ * hash_add - Hash function to add mac addr from hash table
* @priv: The DaVinci EMAC private adapter structure
- * mac_addr: mac address to delete from hash table
+ * @mac_addr: mac address to delete from hash table
*
* Adds mac address to the internal hash table
*
@@ -765,9 +767,9 @@ static int hash_add(struct emac_priv *priv, u8 *mac_addr)
}
/**
- * hash_del: Hash function to delete mac addr from hash table
+ * hash_del - Hash function to delete mac addr from hash table
* @priv: The DaVinci EMAC private adapter structure
- * mac_addr: mac address to delete from hash table
+ * @mac_addr: mac address to delete from hash table
*
* Removes mac address from the internal hash table
*
@@ -807,7 +809,7 @@ static int hash_del(struct emac_priv *priv, u8 *mac_addr)
#define EMAC_ALL_MULTI_CLR 3
/**
- * emac_add_mcast: Set multicast address in the EMAC adapter (Internal)
+ * emac_add_mcast - Set multicast address in the EMAC adapter (Internal)
* @priv: The DaVinci EMAC private adapter structure
* @action: multicast operation to perform
* mac_addr: mac address to set
@@ -855,7 +857,7 @@ static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr)
}
/**
- * emac_dev_mcast_set: Set multicast address in the EMAC adapter
+ * emac_dev_mcast_set - Set multicast address in the EMAC adapter
* @ndev: The DaVinci EMAC network adapter
*
* Set multicast addresses in EMAC adapter
@@ -901,7 +903,7 @@ static void emac_dev_mcast_set(struct net_device *ndev)
*************************************************************************/
/**
- * emac_int_disable: Disable EMAC module interrupt (from adapter)
+ * emac_int_disable - Disable EMAC module interrupt (from adapter)
* @priv: The DaVinci EMAC private adapter structure
*
* Disable EMAC interrupt on the adapter
@@ -931,7 +933,7 @@ static void emac_int_disable(struct emac_priv *priv)
}
/**
- * emac_int_enable: Enable EMAC module interrupt (from adapter)
+ * emac_int_enable - Enable EMAC module interrupt (from adapter)
* @priv: The DaVinci EMAC private adapter structure
*
* Enable EMAC interrupt on the adapter
@@ -967,7 +969,7 @@ static void emac_int_enable(struct emac_priv *priv)
}
/**
- * emac_irq: EMAC interrupt handler
+ * emac_irq - EMAC interrupt handler
* @irq: interrupt number
* @dev_id: EMAC network adapter data structure ptr
*
@@ -1060,7 +1062,7 @@ static void emac_tx_handler(void *token, int len, int status)
}
/**
- * emac_dev_xmit: EMAC Transmit function
+ * emac_dev_xmit - EMAC Transmit function
* @skb: SKB pointer
* @ndev: The DaVinci EMAC network adapter
*
@@ -1111,7 +1113,7 @@ fail_tx:
}
/**
- * emac_dev_tx_timeout: EMAC Transmit timeout function
+ * emac_dev_tx_timeout - EMAC Transmit timeout function
* @ndev: The DaVinci EMAC network adapter
*
* Called when system detects that a skb timeout period has expired
@@ -1138,7 +1140,7 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
}
/**
- * emac_set_type0addr: Set EMAC Type0 mac address
+ * emac_set_type0addr - Set EMAC Type0 mac address
* @priv: The DaVinci EMAC private adapter structure
* @ch: RX channel number
* @mac_addr: MAC address to set in device
@@ -1165,7 +1167,7 @@ static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr)
}
/**
- * emac_set_type1addr: Set EMAC Type1 mac address
+ * emac_set_type1addr - Set EMAC Type1 mac address
* @priv: The DaVinci EMAC private adapter structure
* @ch: RX channel number
* @mac_addr: MAC address to set in device
@@ -1187,7 +1189,7 @@ static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr)
}
/**
- * emac_set_type2addr: Set EMAC Type2 mac address
+ * emac_set_type2addr - Set EMAC Type2 mac address
* @priv: The DaVinci EMAC private adapter structure
* @ch: RX channel number
* @mac_addr: MAC address to set in device
@@ -1213,7 +1215,7 @@ static void emac_set_type2addr(struct emac_priv *priv, u32 ch,
}
/**
- * emac_setmac: Set mac address in the adapter (internal function)
+ * emac_setmac - Set mac address in the adapter (internal function)
* @priv: The DaVinci EMAC private adapter structure
* @ch: RX channel number
* @mac_addr: MAC address to set in device
@@ -1242,7 +1244,7 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
}
/**
- * emac_dev_setmac_addr: Set mac address in the adapter
+ * emac_dev_setmac_addr - Set mac address in the adapter
* @ndev: The DaVinci EMAC network adapter
* @addr: MAC address to set in device
*
@@ -1277,7 +1279,7 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
}
/**
- * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
+ * emac_hw_enable - Enable EMAC hardware for packet transmission/reception
* @priv: The DaVinci EMAC private adapter structure
*
* Enables EMAC hardware for packet processing - enables PHY, enables RX
@@ -1347,7 +1349,7 @@ static int emac_hw_enable(struct emac_priv *priv)
}
/**
- * emac_poll: EMAC NAPI Poll function
+ * emac_poll - EMAC NAPI Poll function
* @ndev: The DaVinci EMAC network adapter
* @budget: Number of receive packets to process (as told by NAPI layer)
*
@@ -1430,7 +1432,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
#ifdef CONFIG_NET_POLL_CONTROLLER
/**
- * emac_poll_controller: EMAC Poll controller function
+ * emac_poll_controller - EMAC Poll controller function
* @ndev: The DaVinci EMAC network adapter
*
* Polled functionality used by netconsole and others in non interrupt mode
@@ -1489,7 +1491,7 @@ static void emac_adjust_link(struct net_device *ndev)
*************************************************************************/
/**
- * emac_devioctl: EMAC adapter ioctl
+ * emac_devioctl - EMAC adapter ioctl
* @ndev: The DaVinci EMAC network adapter
* @ifrq: request parameter
* @cmd: command parameter
@@ -1516,7 +1518,7 @@ static int match_first_device(struct device *dev, void *data)
}
/**
- * emac_dev_open: EMAC device open
+ * emac_dev_open - EMAC device open
* @ndev: The DaVinci EMAC network adapter
*
* Called when system wants to start the interface. We init TX/RX channels
@@ -1535,6 +1537,8 @@ static int emac_dev_open(struct net_device *ndev)
int k = 0;
struct emac_priv *priv = netdev_priv(ndev);
+ pm_runtime_get(&priv->pdev->dev);
+
netif_carrier_off(ndev);
for (cnt = 0; cnt < ETH_ALEN; cnt++)
ndev->dev_addr[cnt] = priv->mac_addr[cnt];
@@ -1604,7 +1608,7 @@ static int emac_dev_open(struct net_device *ndev)
priv->phy_id);
ret = PTR_ERR(priv->phydev);
priv->phydev = NULL;
- return ret;
+ goto err;
}
priv->link = 0;
@@ -1645,11 +1649,15 @@ rollback:
res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1);
m = res->end;
}
- return -EBUSY;
+
+ ret = -EBUSY;
+err:
+ pm_runtime_put(&priv->pdev->dev);
+ return ret;
}
/**
- * emac_dev_stop: EMAC device stop
+ * emac_dev_stop - EMAC device stop
* @ndev: The DaVinci EMAC network adapter
*
* Called when system wants to stop or down the interface. We stop the network
@@ -1687,11 +1695,12 @@ static int emac_dev_stop(struct net_device *ndev)
if (netif_msg_drv(priv))
dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
+ pm_runtime_put(&priv->pdev->dev);
return 0;
}
/**
- * emac_dev_getnetstats: EMAC get statistics function
+ * emac_dev_getnetstats - EMAC get statistics function
* @ndev: The DaVinci EMAC network adapter
*
* Called when system wants to get statistics from the device.
@@ -1762,8 +1771,79 @@ static const struct net_device_ops emac_netdev_ops = {
#endif
};
+#ifdef CONFIG_OF
+static struct emac_platform_data
+ *davinci_emac_of_get_pdata(struct platform_device *pdev,
+ struct emac_priv *priv)
+{
+ struct device_node *np;
+ struct emac_platform_data *pdata = NULL;
+ const u8 *mac_addr;
+ u32 data;
+ int ret;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ goto nodata;
+ }
+
+ np = pdev->dev.of_node;
+ if (!np)
+ goto nodata;
+ else
+ pdata->version = EMAC_VERSION_2;
+
+ if (!is_valid_ether_addr(pdata->mac_addr)) {
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
+ }
+
+ ret = of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", &data);
+ if (!ret)
+ pdata->ctrl_reg_offset = data;
+
+ ret = of_property_read_u32(np, "ti,davinci-ctrl-mod-reg-offset",
+ &data);
+ if (!ret)
+ pdata->ctrl_mod_reg_offset = data;
+
+ ret = of_property_read_u32(np, "ti,davinci-ctrl-ram-offset", &data);
+ if (!ret)
+ pdata->ctrl_ram_offset = data;
+
+ ret = of_property_read_u32(np, "ti,davinci-ctrl-ram-size", &data);
+ if (!ret)
+ pdata->ctrl_ram_size = data;
+
+ ret = of_property_read_u32(np, "ti,davinci-rmii-en", &data);
+ if (!ret)
+ pdata->rmii_en = data;
+
+ ret = of_property_read_u32(np, "ti,davinci-no-bd-ram", &data);
+ if (!ret)
+ pdata->no_bd_ram = data;
+
+ priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (!priv->phy_node)
+ pdata->phy_id = "";
+
+ pdev->dev.platform_data = pdata;
+nodata:
+ return pdata;
+}
+#else
+static struct emac_platform_data
+ *davinci_emac_of_get_pdata(struct platform_device *pdev,
+ struct emac_priv *priv)
+{
+ return pdev->dev.platform_data;
+}
+#endif
/**
- * davinci_emac_probe: EMAC device probe
+ * davinci_emac_probe - EMAC device probe
* @pdev: The DaVinci EMAC device that we are removing
*
* Called when probing for emac devicesr. We get details of instances and
@@ -1780,6 +1860,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
struct emac_platform_data *pdata;
struct device *emac_dev;
struct cpdma_params dma_params;
+ struct clk *emac_clk;
+ unsigned long emac_bus_frequency;
+
/* obtain emac clock from kernel */
emac_clk = clk_get(&pdev->dev, NULL);
@@ -1788,12 +1871,14 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
return -EBUSY;
}
emac_bus_frequency = clk_get_rate(emac_clk);
+ clk_put(emac_clk);
+
/* TODO: Probe PHY here if possible */
ndev = alloc_etherdev(sizeof(struct emac_priv));
if (!ndev) {
rc = -ENOMEM;
- goto free_clk;
+ goto no_ndev;
}
platform_set_drvdata(pdev, ndev);
@@ -1804,7 +1889,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
spin_lock_init(&priv->lock);
- pdata = pdev->dev.platform_data;
+ pdata = davinci_emac_of_get_pdata(pdev, priv);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
rc = -ENODEV;
@@ -1909,15 +1994,13 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
SET_ETHTOOL_OPS(ndev, &ethtool_ops);
netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
- clk_enable(emac_clk);
-
/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
rc = register_netdev(ndev);
if (rc) {
dev_err(&pdev->dev, "error in register_netdev\n");
rc = -ENODEV;
- goto netdev_reg_err;
+ goto no_irq_res;
}
@@ -1926,10 +2009,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
"(regs: %p, irq: %d)\n",
(void *)priv->emac_base_phys, ndev->irq);
}
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_resume(&pdev->dev);
+
return 0;
-netdev_reg_err:
- clk_disable(emac_clk);
no_irq_res:
if (priv->txchan)
cpdma_chan_destroy(priv->txchan);
@@ -1943,13 +2028,12 @@ no_dma:
probe_quit:
free_netdev(ndev);
-free_clk:
- clk_put(emac_clk);
+no_ndev:
return rc;
}
/**
- * davinci_emac_remove: EMAC device remove
+ * davinci_emac_remove - EMAC device remove
* @pdev: The DaVinci EMAC device that we are removing
*
* Called when removing the device driver. We disable clock usage and release
@@ -1978,9 +2062,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
iounmap(priv->remap_addr);
free_netdev(ndev);
- clk_disable(emac_clk);
- clk_put(emac_clk);
-
return 0;
}
@@ -1992,8 +2073,6 @@ static int davinci_emac_suspend(struct device *dev)
if (netif_running(ndev))
emac_dev_stop(ndev);
- clk_disable(emac_clk);
-
return 0;
}
@@ -2002,8 +2081,6 @@ static int davinci_emac_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
- clk_enable(emac_clk);
-
if (netif_running(ndev))
emac_dev_open(ndev);
@@ -2015,21 +2092,26 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {
.resume = davinci_emac_resume,
};
-/**
- * davinci_emac_driver: EMAC platform driver structure
- */
+static const struct of_device_id davinci_emac_of_match[] = {
+ {.compatible = "ti,davinci-dm6467-emac", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
+
+/* davinci_emac_driver: EMAC platform driver structure */
static struct platform_driver davinci_emac_driver = {
.driver = {
.name = "davinci_emac",
.owner = THIS_MODULE,
.pm = &davinci_emac_pm_ops,
+ .of_match_table = of_match_ptr(davinci_emac_of_match),
},
.probe = davinci_emac_probe,
.remove = __devexit_p(davinci_emac_remove),
};
/**
- * davinci_emac_init: EMAC driver module init
+ * davinci_emac_init - EMAC driver module init
*
* Called when initializing the driver. We register the driver with
* the platform.
@@ -2041,7 +2123,7 @@ static int __init davinci_emac_init(void)
late_initcall(davinci_emac_init);
/**
- * davinci_emac_exit: EMAC driver module exit
+ * davinci_emac_exit - EMAC driver module exit
*
* Called when exiting the driver completely. We unregister the driver with
* the platform and exit