diff options
Diffstat (limited to 'drivers/net/ethernet/ti/davinci_emac.c')
| -rw-r--r-- | drivers/net/ethernet/ti/davinci_emac.c | 369 |
1 files changed, 217 insertions, 152 deletions
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 4fa0bcb25df..35a139e9a83 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -57,7 +57,13 @@ #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_device.h> +#include <linux/of_irq.h> +#include <linux/of_net.h> #include <asm/irq.h> #include <asm/page.h> @@ -115,7 +121,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_NUM_DESC (128) -#define EMAC_DEF_TX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -337,8 +342,10 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; 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 +353,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 +378,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 +469,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 * @@ -476,12 +479,12 @@ static void emac_dump_regs(struct emac_priv *priv) static void emac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { - strcpy(info->driver, emac_version_string); - strcpy(info->version, EMAC_MODULE_VERSION); + strlcpy(info->driver, emac_version_string, sizeof(info->driver)); + strlcpy(info->version, EMAC_MODULE_VERSION, sizeof(info->version)); } /** - * emac_get_settings: Get EMAC settings + * emac_get_settings - Get EMAC settings * @ndev: The DaVinci EMAC network adapter * @ecmd: ethtool command * @@ -500,7 +503,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 +521,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 +539,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 +617,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, @@ -627,10 +628,11 @@ static const struct ethtool_ops ethtool_ops = { .get_link = ethtool_op_get_link, .get_coalesce = emac_get_coalesce, .set_coalesce = emac_set_coalesce, + .get_ts_info = ethtool_op_get_ts_info, }; /** - * 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 @@ -696,7 +698,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 @@ -722,9 +724,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 * @@ -764,9 +766,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 * @@ -806,7 +808,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 @@ -854,7 +856,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 @@ -875,8 +877,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); - } - if (!netdev_mc_empty(ndev)) { + } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); @@ -900,7 +901,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 @@ -930,7 +931,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 @@ -966,7 +967,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 * @@ -992,10 +993,9 @@ static irqreturn_t emac_irq(int irq, void *dev_id) static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) { - struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + struct sk_buff *skb = netdev_alloc_skb(priv->ndev, priv->rx_buf_size); if (WARN_ON(!skb)) return NULL; - skb->dev = priv->ndev; skb_reserve(skb, NET_IP_ALIGN); return skb; } @@ -1009,7 +1009,7 @@ static void emac_rx_handler(void *token, int len, int status) int ret; /* free and bail if we are shutting down */ - if (unlikely(!netif_running(ndev) || !netif_carrier_ok(ndev))) { + if (unlikely(!netif_running(ndev))) { dev_kfree_skb_any(skb); return; } @@ -1037,8 +1037,10 @@ static void emac_rx_handler(void *token, int len, int status) recycle: ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, - skb_tailroom(skb), GFP_KERNEL); - if (WARN_ON(ret < 0)) + skb_tailroom(skb), 0); + + WARN_ON(ret == -ENOMEM); + if (unlikely(ret < 0)) dev_kfree_skb_any(skb); } @@ -1046,19 +1048,19 @@ static void emac_tx_handler(void *token, int len, int status) { struct sk_buff *skb = token; struct net_device *ndev = skb->dev; - struct emac_priv *priv = netdev_priv(ndev); - - atomic_dec(&priv->cur_tx); + /* Check whether the queue is stopped due to stalled tx dma, if the + * queue is stopped then start the queue as we have free desc for tx + */ if (unlikely(netif_queue_stopped(ndev))) - netif_start_queue(ndev); + netif_wake_queue(ndev); ndev->stats.tx_packets++; ndev->stats.tx_bytes += len; dev_kfree_skb_any(skb); } /** - * emac_dev_xmit: EMAC Transmit function + * emac_dev_xmit - EMAC Transmit function * @skb: SKB pointer * @ndev: The DaVinci EMAC network adapter * @@ -1090,14 +1092,17 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) skb_tx_timestamp(skb); ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, - GFP_KERNEL); + 0); if (unlikely(ret_code != 0)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); goto fail_tx; } - if (atomic_inc_return(&priv->cur_tx) >= EMAC_DEF_TX_NUM_DESC) + /* If there is no more tx desc left free then we need to + * tell the kernel to stop sending us tx frames. + */ + if (unlikely(!cpdma_check_free_tx_desc(priv->txchan))) netif_stop_queue(ndev); return NETDEV_TX_OK; @@ -1109,7 +1114,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 @@ -1136,7 +1141,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 @@ -1163,7 +1168,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 @@ -1185,7 +1190,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 @@ -1211,7 +1216,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 @@ -1240,7 +1245,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 * @@ -1255,7 +1260,7 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) struct sockaddr *sa = addr; if (!is_valid_ether_addr(sa->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; /* Store mac addr in priv and rx channel and set it in EMAC hw */ memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); @@ -1263,7 +1268,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } @@ -1275,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 @@ -1345,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) * @@ -1428,13 +1432,13 @@ 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 * */ -void emac_poll_controller(struct net_device *ndev) +static void emac_poll_controller(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); @@ -1487,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 @@ -1510,11 +1514,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) static int match_first_device(struct device *dev, void *data) { - return 1; + return !strncmp(dev_name(dev), "davinci_mdio", 12); } /** - * 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 @@ -1529,10 +1533,12 @@ static int emac_dev_open(struct net_device *ndev) u32 cnt; struct resource *res; int q, m, ret; + int res_num = 0, irq_num = 0; int i = 0; - 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]; @@ -1552,21 +1558,29 @@ static int emac_dev_open(struct net_device *ndev) break; ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, - skb_tailroom(skb), GFP_KERNEL); + skb_tailroom(skb), 0); if (WARN_ON(ret < 0)) break; } /* Request IRQ */ + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, + res_num))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) { + if (request_irq(irq_num, emac_irq, 0, ndev->name, + ndev)) { + dev_err(emac_dev, + "DaVinci EMAC: request_irq() failed\n"); + ret = -EBUSY; - while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { - for (i = res->start; i <= res->end; i++) { - if (request_irq(i, emac_irq, IRQF_DISABLED, - ndev->name, ndev)) goto rollback; + } } - k++; + res_num++; } + /* prepare counters for rollback in case of an error */ + res_num--; + irq_num--; /* Start/Enable EMAC hardware */ emac_hw_enable(priv); @@ -1594,7 +1608,7 @@ static int emac_dev_open(struct net_device *ndev) if (priv->phy_id && *priv->phy_id) { priv->phydev = phy_connect(ndev, priv->phy_id, - &emac_adjust_link, 0, + &emac_adjust_link, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { @@ -1602,7 +1616,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; @@ -1633,21 +1647,29 @@ static int emac_dev_open(struct net_device *ndev) return 0; -rollback: - - dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); +err: + emac_int_disable(priv); + napi_disable(&priv->napi); - for (q = k; k >= 0; k--) { - for (m = i; m >= res->start; m--) +rollback: + for (q = res_num; q >= 0; q--) { + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, q); + /* at the first iteration, irq_num is already set to the + * right value + */ + if (q != res_num) + irq_num = res->end; + + for (m = irq_num; m >= res->start; m--) free_irq(m, ndev); - res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); - m = res->end; } - return -EBUSY; + cpdma_ctlr_stop(priv->dma); + 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 @@ -1685,11 +1707,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. @@ -1760,40 +1783,105 @@ static const struct net_device_ops emac_netdev_ops = { #endif }; +static const struct of_device_id davinci_emac_of_match[]; + +static struct emac_platform_data * +davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) +{ + struct device_node *np; + const struct of_device_id *match; + const struct emac_platform_data *auxdata; + struct emac_platform_data *pdata = NULL; + const u8 *mac_addr; + + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) + return dev_get_platdata(&pdev->dev); + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + np = pdev->dev.of_node; + 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); + } + + of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", + &pdata->ctrl_reg_offset); + + of_property_read_u32(np, "ti,davinci-ctrl-mod-reg-offset", + &pdata->ctrl_mod_reg_offset); + + of_property_read_u32(np, "ti,davinci-ctrl-ram-offset", + &pdata->ctrl_ram_offset); + + of_property_read_u32(np, "ti,davinci-ctrl-ram-size", + &pdata->ctrl_ram_size); + + of_property_read_u8(np, "ti,davinci-rmii-en", &pdata->rmii_en); + + pdata->no_bd_ram = of_property_read_bool(np, "ti,davinci-no-bd-ram"); + + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy_node) + pdata->phy_id = NULL; + + auxdata = pdev->dev.platform_data; + if (auxdata) { + pdata->interrupt_enable = auxdata->interrupt_enable; + pdata->interrupt_disable = auxdata->interrupt_disable; + } + + match = of_match_device(davinci_emac_of_match, &pdev->dev); + if (match && match->data) { + auxdata = match->data; + pdata->version = auxdata->version; + pdata->hw_ram_addr = auxdata->hw_ram_addr; + } + + pdev->dev.platform_data = pdata; + + return pdata; +} + /** - * 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 * resource information from platform init and register a network device * and allocate resources necessary for driver to perform */ -static int __devinit davinci_emac_probe(struct platform_device *pdev) +static int davinci_emac_probe(struct platform_device *pdev) { int rc = 0; struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size, hw_ram_addr; + unsigned long hw_ram_addr; 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); + emac_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(emac_clk)) { dev_err(&pdev->dev, "failed to get EMAC clock\n"); return -EBUSY; } emac_bus_frequency = clk_get_rate(emac_clk); + /* TODO: Probe PHY here if possible */ ndev = alloc_etherdev(sizeof(struct emac_priv)); - if (!ndev) { - dev_err(&pdev->dev, "error allocating net_device\n"); - rc = -ENOMEM; - goto free_clk; - } + if (!ndev) + return -ENOMEM; platform_set_drvdata(pdev, ndev); priv = netdev_priv(ndev); @@ -1803,15 +1891,15 @@ 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; - goto probe_quit; + goto no_pdata; } /* MAC addr and PHY mask , RMII enable info from platform_data */ - memcpy(priv->mac_addr, pdata->mac_addr, 6); + memcpy(priv->mac_addr, pdata->mac_addr, ETH_ALEN); priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; @@ -1821,29 +1909,13 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->coal_intvl = 0; priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000); - emac_dev = &ndev->dev; /* Get EMAC platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev,"error getting res\n"); - rc = -ENOENT; - goto probe_quit; - } - priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; - size = resource_size(res); - if (!request_mem_region(res->start, size, ndev->name)) { - dev_err(&pdev->dev, "failed request_mem_region() for regs\n"); - rc = -ENXIO; - goto probe_quit; - } - - priv->remap_addr = ioremap(res->start, size); - if (!priv->remap_addr) { - dev_err(&pdev->dev, "unable to map IO\n"); - rc = -ENOMEM; - release_mem_region(res->start, size); - goto probe_quit; + priv->remap_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->remap_addr)) { + rc = PTR_ERR(priv->remap_addr); + goto no_pdata; } priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset; ndev->base_addr = (unsigned long)priv->remap_addr; @@ -1855,7 +1927,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; memset(&dma_params, 0, sizeof(dma_params)); - dma_params.dev = emac_dev; + dma_params.dev = &pdev->dev; dma_params.dmaregs = priv->emac_base; dma_params.rxthresh = priv->emac_base + 0x120; dma_params.rxfree = priv->emac_base + 0x140; @@ -1876,7 +1948,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) if (!priv->dma) { dev_err(&pdev->dev, "error initializing DMA\n"); rc = -ENOMEM; - goto no_dma; + goto no_pdata; } priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), @@ -1885,100 +1957,84 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) emac_rx_handler); if (WARN_ON(!priv->txchan || !priv->rxchan)) { rc = -ENOMEM; - goto no_irq_res; + goto no_cpdma_chan; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(&pdev->dev, "error getting irq res\n"); rc = -ENOENT; - goto no_irq_res; + goto no_cpdma_chan; } ndev->irq = res->start; if (!is_valid_ether_addr(priv->mac_addr)) { /* Use random MAC if none passed */ - random_ether_addr(priv->mac_addr); + eth_hw_addr_random(ndev); + memcpy(priv->mac_addr, ndev->dev_addr, ndev->addr_len); dev_warn(&pdev->dev, "using random MAC addr: %pM\n", priv->mac_addr); } ndev->netdev_ops = &emac_netdev_ops; - SET_ETHTOOL_OPS(ndev, ðtool_ops); + ndev->ethtool_ops = ðtool_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_cpdma_chan; } if (netif_msg_probe(priv)) { - dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ + dev_notice(&pdev->dev, "DaVinci EMAC Probe found device " "(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: +no_cpdma_chan: if (priv->txchan) cpdma_chan_destroy(priv->txchan); if (priv->rxchan) cpdma_chan_destroy(priv->rxchan); cpdma_ctlr_destroy(priv->dma); -no_dma: - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - iounmap(priv->remap_addr); - -probe_quit: +no_pdata: free_netdev(ndev); -free_clk: - clk_put(emac_clk); 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 * the resources taken up by the driver and unregister network device */ -static int __devexit davinci_emac_remove(struct platform_device *pdev) +static int davinci_emac_remove(struct platform_device *pdev) { - struct resource *res; struct net_device *ndev = platform_get_drvdata(pdev); struct emac_priv *priv = netdev_priv(ndev); dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); - platform_set_drvdata(pdev, NULL); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (priv->txchan) cpdma_chan_destroy(priv->txchan); if (priv->rxchan) cpdma_chan_destroy(priv->rxchan); cpdma_ctlr_destroy(priv->dma); - release_mem_region(res->start, resource_size(res)); - unregister_netdev(ndev); - iounmap(priv->remap_addr); free_netdev(ndev); - clk_disable(emac_clk); - clk_put(emac_clk); - return 0; } @@ -1990,8 +2046,6 @@ static int davinci_emac_suspend(struct device *dev) if (netif_running(ndev)) emac_dev_stop(ndev); - clk_disable(emac_clk); - return 0; } @@ -2000,8 +2054,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); @@ -2013,21 +2065,34 @@ static const struct dev_pm_ops davinci_emac_pm_ops = { .resume = davinci_emac_resume, }; -/** - * davinci_emac_driver: EMAC platform driver structure - */ +#if IS_ENABLED(CONFIG_OF) +static const struct emac_platform_data am3517_emac_data = { + .version = EMAC_VERSION_2, + .hw_ram_addr = 0x01e20000, +}; + +static const struct of_device_id davinci_emac_of_match[] = { + {.compatible = "ti,davinci-dm6467-emac", }, + {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, davinci_emac_of_match); +#endif + +/* 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), + .remove = 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. @@ -2039,7 +2104,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 |
