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.c648
1 files changed, 340 insertions, 308 deletions
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 07b176bcf929..ed8116fb05e9 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* DaVinci Ethernet Medium Access Controller
*
@@ -6,21 +7,6 @@
* Copyright (C) 2009 Texas Instruments.
*
* ---------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ---------------------------------------------------------------------------
* History:
* 0-5 A number of folks worked on this driver in bits and pieces but the major
* contribution came from Suraj Iyer and Anant Gole
@@ -52,6 +38,8 @@
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
#include <linux/semaphore.h>
#include <linux/phy.h>
#include <linux/bitops.h>
@@ -60,13 +48,14 @@
#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_mdio.h>
#include <linux/of_net.h>
+#include <linux/mfd/syscon.h>
#include <asm/irq.h>
#include <asm/page.h>
+#include "cpsw.h"
#include "davinci_cpdma.h"
static int debug_level;
@@ -122,7 +111,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
#define EMAC_DEF_RX_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 */
/* Buffer descriptor parameters */
#define EMAC_DEF_TX_MAX_SERVICE (32) /* TX max service BD's */
@@ -178,11 +166,11 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
/* EMAC mac_status register */
#define EMAC_MACSTATUS_TXERRCODE_MASK (0xF00000)
#define EMAC_MACSTATUS_TXERRCODE_SHIFT (20)
-#define EMAC_MACSTATUS_TXERRCH_MASK (0x7)
+#define EMAC_MACSTATUS_TXERRCH_MASK (0x70000)
#define EMAC_MACSTATUS_TXERRCH_SHIFT (16)
#define EMAC_MACSTATUS_RXERRCODE_MASK (0xF000)
#define EMAC_MACSTATUS_RXERRCODE_SHIFT (12)
-#define EMAC_MACSTATUS_RXERRCH_MASK (0x7)
+#define EMAC_MACSTATUS_RXERRCH_MASK (0x700)
#define EMAC_MACSTATUS_RXERRCH_SHIFT (8)
/* EMAC RX register masks */
@@ -342,10 +330,7 @@ struct emac_priv {
u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
u32 rx_addr_type;
const char *phy_id;
-#ifdef CONFIG_OF
struct device_node *phy_node;
-#endif
- struct phy_device *phydev;
spinlock_t lock;
/*platform specific members*/
void (*int_enable) (void);
@@ -377,97 +362,6 @@ 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
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Executes ethtool set cmd & sets phy mode
- *
- */
-static void emac_dump_regs(struct emac_priv *priv)
-{
- struct device *emac_dev = &priv->ndev->dev;
-
- /* Print important registers in EMAC */
- dev_info(emac_dev, "EMAC Basic registers\n");
- if (priv->version == EMAC_VERSION_1) {
- dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n",
- emac_ctrl_read(EMAC_CTRL_EWCTL),
- emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
- }
- dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
- emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
- dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
- "RXMaxLen=%08X\n", emac_read(EMAC_RXMBPENABLE),
- emac_read(EMAC_RXUNICASTSET), emac_read(EMAC_RXMAXLEN));
- dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
- "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
- emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
- dev_info(emac_dev, "EMAC Statistics\n");
- dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
- emac_read(EMAC_RXGOODFRAMES));
- dev_info(emac_dev, "EMAC: rx_broadcast_frames:%d\n",
- emac_read(EMAC_RXBCASTFRAMES));
- dev_info(emac_dev, "EMAC: rx_multicast_frames:%d\n",
- emac_read(EMAC_RXMCASTFRAMES));
- dev_info(emac_dev, "EMAC: rx_pause_frames:%d\n",
- emac_read(EMAC_RXPAUSEFRAMES));
- dev_info(emac_dev, "EMAC: rx_crcerrors:%d\n",
- emac_read(EMAC_RXCRCERRORS));
- dev_info(emac_dev, "EMAC: rx_align_code_errors:%d\n",
- emac_read(EMAC_RXALIGNCODEERRORS));
- dev_info(emac_dev, "EMAC: rx_oversized_frames:%d\n",
- emac_read(EMAC_RXOVERSIZED));
- dev_info(emac_dev, "EMAC: rx_jabber_frames:%d\n",
- emac_read(EMAC_RXJABBER));
- dev_info(emac_dev, "EMAC: rx_undersized_frames:%d\n",
- emac_read(EMAC_RXUNDERSIZED));
- dev_info(emac_dev, "EMAC: rx_fragments:%d\n",
- emac_read(EMAC_RXFRAGMENTS));
- dev_info(emac_dev, "EMAC: rx_filtered_frames:%d\n",
- emac_read(EMAC_RXFILTERED));
- dev_info(emac_dev, "EMAC: rx_qos_filtered_frames:%d\n",
- emac_read(EMAC_RXQOSFILTERED));
- dev_info(emac_dev, "EMAC: rx_octets:%d\n",
- emac_read(EMAC_RXOCTETS));
- dev_info(emac_dev, "EMAC: tx_goodframes:%d\n",
- emac_read(EMAC_TXGOODFRAMES));
- dev_info(emac_dev, "EMAC: tx_bcastframes:%d\n",
- emac_read(EMAC_TXBCASTFRAMES));
- dev_info(emac_dev, "EMAC: tx_mcastframes:%d\n",
- emac_read(EMAC_TXMCASTFRAMES));
- dev_info(emac_dev, "EMAC: tx_pause_frames:%d\n",
- emac_read(EMAC_TXPAUSEFRAMES));
- dev_info(emac_dev, "EMAC: tx_deferred_frames:%d\n",
- emac_read(EMAC_TXDEFERRED));
- dev_info(emac_dev, "EMAC: tx_collision_frames:%d\n",
- emac_read(EMAC_TXCOLLISION));
- dev_info(emac_dev, "EMAC: tx_single_coll_frames:%d\n",
- emac_read(EMAC_TXSINGLECOLL));
- dev_info(emac_dev, "EMAC: tx_mult_coll_frames:%d\n",
- emac_read(EMAC_TXMULTICOLL));
- dev_info(emac_dev, "EMAC: tx_excessive_collisions:%d\n",
- emac_read(EMAC_TXEXCESSIVECOLL));
- dev_info(emac_dev, "EMAC: tx_late_collisions:%d\n",
- emac_read(EMAC_TXLATECOLL));
- dev_info(emac_dev, "EMAC: tx_underrun:%d\n",
- emac_read(EMAC_TXUNDERRUN));
- dev_info(emac_dev, "EMAC: tx_carrier_sense_errors:%d\n",
- emac_read(EMAC_TXCARRIERSENSE));
- dev_info(emac_dev, "EMAC: tx_octets:%d\n",
- emac_read(EMAC_TXOCTETS));
- dev_info(emac_dev, "EMAC: net_octets:%d\n",
- emac_read(EMAC_NETOCTETS));
- dev_info(emac_dev, "EMAC: rx_sof_overruns:%d\n",
- emac_read(EMAC_RXSOFOVERRUNS));
- dev_info(emac_dev, "EMAC: rx_mof_overruns:%d\n",
- emac_read(EMAC_RXMOFOVERRUNS));
- dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
- emac_read(EMAC_RXDMAOVERRUNS));
-
- cpdma_ctlr_dump(priv->dma);
-}
-
-/**
* emac_get_drvinfo - Get EMAC driver information
* @ndev: The DaVinci EMAC network adapter
* @info: ethtool info structure containing name and version
@@ -478,57 +372,24 @@ static void emac_dump_regs(struct emac_priv *priv)
static void emac_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
{
- strlcpy(info->driver, emac_version_string, sizeof(info->driver));
- strlcpy(info->version, EMAC_MODULE_VERSION, sizeof(info->version));
-}
-
-/**
- * emac_get_settings - Get EMAC settings
- * @ndev: The DaVinci EMAC network adapter
- * @ecmd: ethtool command
- *
- * Executes ethool get command
- *
- */
-static int emac_get_settings(struct net_device *ndev,
- struct ethtool_cmd *ecmd)
-{
- struct emac_priv *priv = netdev_priv(ndev);
- if (priv->phydev)
- return phy_ethtool_gset(priv->phydev, ecmd);
- else
- return -EOPNOTSUPP;
-
-}
-
-/**
- * emac_set_settings - Set EMAC settings
- * @ndev: The DaVinci EMAC network adapter
- * @ecmd: ethtool command
- *
- * Executes ethool set command
- *
- */
-static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
-{
- struct emac_priv *priv = netdev_priv(ndev);
- if (priv->phydev)
- return phy_ethtool_sset(priv->phydev, ecmd);
- else
- return -EOPNOTSUPP;
-
+ strscpy(info->driver, emac_version_string, sizeof(info->driver));
+ strscpy(info->version, EMAC_MODULE_VERSION, sizeof(info->version));
}
/**
* emac_get_coalesce - Get interrupt coalesce settings for this device
* @ndev : The DaVinci EMAC network adapter
* @coal : ethtool coalesce settings structure
+ * @kernel_coal: ethtool CQE mode setting structure
+ * @extack: extack for reporting error messages
*
* Fetch the current interrupt coalesce settings
*
*/
static int emac_get_coalesce(struct net_device *ndev,
- struct ethtool_coalesce *coal)
+ struct ethtool_coalesce *coal,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
{
struct emac_priv *priv = netdev_priv(ndev);
@@ -541,19 +402,35 @@ static int emac_get_coalesce(struct net_device *ndev,
* emac_set_coalesce - Set interrupt coalesce settings for this device
* @ndev : The DaVinci EMAC network adapter
* @coal : ethtool coalesce settings structure
+ * @kernel_coal: ethtool CQE mode setting structure
+ * @extack: extack for reporting error messages
*
* Set interrupt coalesce parameters
*
*/
static int emac_set_coalesce(struct net_device *ndev,
- struct ethtool_coalesce *coal)
+ struct ethtool_coalesce *coal,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
{
struct emac_priv *priv = netdev_priv(ndev);
u32 int_ctrl, num_interrupts = 0;
u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0;
- if (!coal->rx_coalesce_usecs)
- return -EINVAL;
+ if (!coal->rx_coalesce_usecs) {
+ priv->coal_intvl = 0;
+
+ switch (priv->version) {
+ case EMAC_VERSION_2:
+ emac_ctrl_write(EMAC_DM646X_CMINTCTRL, 0);
+ break;
+ default:
+ emac_ctrl_write(EMAC_CTRL_EWINTTCNT, 0);
+ break;
+ }
+
+ return 0;
+ }
coal_intvl = coal->rx_coalesce_usecs;
@@ -621,13 +498,14 @@ static int emac_set_coalesce(struct net_device *ndev,
* Ethtool support for EMAC adapter
*/
static const struct ethtool_ops ethtool_ops = {
+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS,
.get_drvinfo = emac_get_drvinfo,
- .get_settings = emac_get_settings,
- .set_settings = emac_set_settings,
.get_link = ethtool_op_get_link,
.get_coalesce = emac_get_coalesce,
.set_coalesce = emac_set_coalesce,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
};
/**
@@ -648,8 +526,8 @@ static void emac_update_phystatus(struct emac_priv *priv)
mac_control = emac_read(EMAC_MACCONTROL);
cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
DUPLEX_FULL : DUPLEX_HALF;
- if (priv->phydev)
- new_duplex = priv->phydev->duplex;
+ if (ndev->phydev)
+ new_duplex = ndev->phydev->duplex;
else
new_duplex = DUPLEX_FULL;
@@ -723,14 +601,14 @@ static u32 hash_get(u8 *addr)
}
/**
- * hash_add - Hash function to add mac addr from hash table
+ * emac_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
*
* Adds mac address to the internal hash table
*
*/
-static int hash_add(struct emac_priv *priv, u8 *mac_addr)
+static int emac_hash_add(struct emac_priv *priv, u8 *mac_addr)
{
struct device *emac_dev = &priv->ndev->dev;
u32 rc = 0;
@@ -739,7 +617,7 @@ static int hash_add(struct emac_priv *priv, u8 *mac_addr)
if (hash_value >= EMAC_NUM_MULTICAST_BITS) {
if (netif_msg_drv(priv)) {
- dev_err(emac_dev, "DaVinci EMAC: hash_add(): Invalid "\
+ dev_err(emac_dev, "DaVinci EMAC: emac_hash_add(): Invalid "\
"Hash %08x, should not be greater than %08x",
hash_value, (EMAC_NUM_MULTICAST_BITS - 1));
}
@@ -765,14 +643,14 @@ static int hash_add(struct emac_priv *priv, u8 *mac_addr)
}
/**
- * hash_del - Hash function to delete mac addr from hash table
+ * emac_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
*
* Removes mac address from the internal hash table
*
*/
-static int hash_del(struct emac_priv *priv, u8 *mac_addr)
+static int emac_hash_del(struct emac_priv *priv, u8 *mac_addr)
{
u32 hash_value;
u32 hash_bit;
@@ -810,7 +688,7 @@ static int hash_del(struct emac_priv *priv, u8 *mac_addr)
* 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
+ * @mac_addr: mac address to set
*
* Set multicast addresses in EMAC adapter - internal function
*
@@ -822,10 +700,10 @@ static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr)
switch (action) {
case EMAC_MULTICAST_ADD:
- update = hash_add(priv, mac_addr);
+ update = emac_hash_add(priv, mac_addr);
break;
case EMAC_MULTICAST_DEL:
- update = hash_del(priv, mac_addr);
+ update = emac_hash_del(priv, mac_addr);
break;
case EMAC_ALL_MULTI_SET:
update = 1;
@@ -876,8 +754,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);
@@ -922,6 +799,16 @@ static void emac_int_disable(struct emac_priv *priv)
if (priv->int_disable)
priv->int_disable();
+ /* NOTE: Rx Threshold and Misc interrupts are not enabled */
+
+ /* ack rxen only then a new pulse will be generated */
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
+ EMAC_DM646X_MAC_EOI_C0_RXEN);
+
+ /* ack txen- only then a new pulse will be generated */
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
+ EMAC_DM646X_MAC_EOI_C0_TXEN);
+
local_irq_restore(flags);
} else {
@@ -951,15 +838,6 @@ static void emac_int_enable(struct emac_priv *priv)
* register */
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
-
- /* ack rxen only then a new pulse will be generated */
- emac_write(EMAC_DM646X_MACEOIVECTOR,
- EMAC_DM646X_MAC_EOI_C0_RXEN);
-
- /* ack txen- only then a new pulse will be generated */
- emac_write(EMAC_DM646X_MACEOIVECTOR,
- EMAC_DM646X_MAC_EOI_C0_TXEN);
-
} else {
/* Set DM644x control registers for interrupt control */
emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
@@ -1069,7 +947,7 @@ static void emac_tx_handler(void *token, int len, int status)
*
* Returns success(NETDEV_TX_OK) or error code (typically out of desc's)
*/
-static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct device *emac_dev = &ndev->dev;
int ret_code;
@@ -1082,7 +960,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
goto fail_tx;
}
- ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
+ ret_code = skb_put_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
if (unlikely(ret_code < 0)) {
if (netif_msg_tx_err(priv) && net_ratelimit())
dev_err(emac_dev, "DaVinci EMAC: packet pad failed");
@@ -1116,6 +994,7 @@ fail_tx:
/**
* emac_dev_tx_timeout - EMAC Transmit timeout function
* @ndev: The DaVinci EMAC network adapter
+ * @txqueue: the index of the hung transmit queue
*
* Called when system detects that a skb timeout period has expired
* potentially due to a fault in the adapter in not being able to send
@@ -1123,7 +1002,7 @@ fail_tx:
* error and re-initialize the TX channel for hardware operation
*
*/
-static void emac_dev_tx_timeout(struct net_device *ndev)
+static void emac_dev_tx_timeout(struct net_device *ndev, unsigned int txqueue)
{
struct emac_priv *priv = netdev_priv(ndev);
struct device *emac_dev = &ndev->dev;
@@ -1131,8 +1010,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
if (netif_msg_tx_err(priv))
dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
- emac_dump_regs(priv);
-
ndev->stats.tx_errors++;
emac_int_disable(priv);
cpdma_chan_stop(priv->txchan);
@@ -1264,7 +1141,7 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
/* Store mac addr in priv and rx channel and set it in EMAC hw */
memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
- memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
+ eth_hw_addr_set(ndev, sa->sa_data);
/* MAC address is configured only after the interface is enabled. */
if (netif_running(ndev)) {
@@ -1350,7 +1227,7 @@ static int emac_hw_enable(struct emac_priv *priv)
/**
* emac_poll - EMAC NAPI Poll function
- * @ndev: The DaVinci EMAC network adapter
+ * @napi: pointer to the napi_struct containing The DaVinci EMAC network adapter
* @budget: Number of receive packets to process (as told by NAPI layer)
*
* NAPI Poll function implemented to process packets as per budget. We check
@@ -1368,7 +1245,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
struct net_device *ndev = priv->ndev;
struct device *emac_dev = &ndev->dev;
u32 status = 0;
- u32 num_tx_pkts = 0, num_rx_pkts = 0;
+ u32 num_rx_pkts = 0;
/* Check interrupt vectors and call packet processing */
status = emac_read(EMAC_MACINVECTOR);
@@ -1379,8 +1256,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
if (status & mask) {
- num_tx_pkts = cpdma_chan_process(priv->txchan,
- EMAC_DEF_TX_MAX_SERVICE);
+ cpdma_chan_process(priv->txchan, EMAC_DEF_TX_MAX_SERVICE);
} /* TX processing */
mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
@@ -1423,7 +1299,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
&emac_rxhost_errcodes[cause][0], ch);
}
} else if (num_rx_pkts < budget) {
- napi_complete(napi);
+ napi_complete_done(napi, num_rx_pkts);
emac_int_enable(priv);
}
@@ -1451,7 +1327,7 @@ static void emac_poll_controller(struct net_device *ndev)
static void emac_adjust_link(struct net_device *ndev)
{
struct emac_priv *priv = netdev_priv(ndev);
- struct phy_device *phydev = priv->phydev;
+ struct phy_device *phydev = ndev->phydev;
unsigned long flags;
int new_state = 0;
@@ -1480,7 +1356,7 @@ static void emac_adjust_link(struct net_device *ndev)
}
if (new_state) {
emac_update_phystatus(priv);
- phy_print_status(priv->phydev);
+ phy_print_status(ndev->phydev);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1502,18 +1378,23 @@ static void emac_adjust_link(struct net_device *ndev)
*/
static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
{
- struct emac_priv *priv = netdev_priv(ndev);
-
if (!(netif_running(ndev)))
return -EINVAL;
/* TODO: Add phy read and write and private statistics get feature */
- return phy_mii_ioctl(priv->phydev, ifrq, cmd);
+ if (ndev->phydev)
+ return phy_mii_ioctl(ndev->phydev, ifrq, cmd);
+ else
+ return -EOPNOTSUPP;
}
-static int match_first_device(struct device *dev, void *data)
+static int match_first_device(struct device *dev, const void *data)
{
+ if (dev->parent && dev->parent->of_node)
+ return of_device_is_compatible(dev->parent->of_node,
+ "ti,davinci_mdio");
+
return !strncmp(dev_name(dev), "davinci_mdio", 12);
}
@@ -1530,18 +1411,23 @@ static int match_first_device(struct device *dev, void *data)
static int emac_dev_open(struct net_device *ndev)
{
struct device *emac_dev = &ndev->dev;
- u32 cnt;
struct resource *res;
- int ret;
+ 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);
+ struct phy_device *phydev = NULL;
+ struct device *phy = NULL;
+
+ ret = pm_runtime_resume_and_get(&priv->pdev->dev);
+ if (ret < 0) {
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, ret);
+ return ret;
+ }
netif_carrier_off(ndev);
- for (cnt = 0; cnt < ETH_ALEN; cnt++)
- ndev->dev_addr[cnt] = priv->mac_addr[cnt];
+ eth_hw_addr_set(ndev, priv->mac_addr);
/* Configuration items */
priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
@@ -1557,22 +1443,39 @@ static int emac_dev_open(struct net_device *ndev)
if (!skb)
break;
- ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
- skb_tailroom(skb), 0);
+ ret = cpdma_chan_idle_submit(priv->rxchan, skb, skb->data,
+ skb_tailroom(skb), 0);
if (WARN_ON(ret < 0))
break;
}
/* Request IRQ */
+ if (dev_of_node(&priv->pdev->dev)) {
+ while ((ret = platform_get_irq_optional(priv->pdev, res_num)) != -ENXIO) {
+ if (ret < 0)
+ goto rollback;
- while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
- for (i = res->start; i <= res->end; i++) {
- if (devm_request_irq(&priv->pdev->dev, i, emac_irq,
- IRQF_DISABLED,
- ndev->name, ndev))
+ ret = request_irq(ret, emac_irq, 0, ndev->name, ndev);
+ if (ret) {
+ dev_err(emac_dev, "DaVinci EMAC: request_irq() failed\n");
goto rollback;
+ }
+ res_num++;
}
- k++;
+ } else {
+ while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, res_num))) {
+ for (irq_num = res->start; irq_num <= res->end; irq_num++) {
+ ret = request_irq(irq_num, emac_irq, 0, ndev->name, ndev);
+ if (ret) {
+ dev_err(emac_dev, "DaVinci EMAC: request_irq() failed\n");
+ goto rollback;
+ }
+ }
+ res_num++;
+ }
+ /* prepare counters for rollback in case of an error */
+ res_num--;
+ irq_num--;
}
/* Start/Enable EMAC hardware */
@@ -1583,32 +1486,48 @@ static int emac_dev_open(struct net_device *ndev)
struct ethtool_coalesce coal;
coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
- emac_set_coalesce(ndev, &coal);
+ emac_set_coalesce(ndev, &coal, NULL, NULL);
}
cpdma_ctlr_start(priv->dma);
- priv->phydev = NULL;
- /* use the first phy on the bus if pdata did not give us a phy id */
- if (!priv->phy_id) {
- struct device *phy;
+ if (priv->phy_node) {
+ phydev = of_phy_connect(ndev, priv->phy_node,
+ &emac_adjust_link, 0, 0);
+ if (!phydev) {
+ dev_err(emac_dev, "could not connect to phy %pOF\n",
+ priv->phy_node);
+ ret = -ENODEV;
+ goto err;
+ }
+ }
+ /* use the first phy on the bus if pdata did not give us a phy id */
+ if (!phydev && !priv->phy_id) {
+ /* NOTE: we can't use bus_find_device_by_name() here because
+ * the device name is not guaranteed to be 'davinci_mdio'. On
+ * some systems it can be 'davinci_mdio.0' so we need to use
+ * strncmp() against the first part of the string to correctly
+ * match it.
+ */
phy = bus_find_device(&mdio_bus_type, NULL, NULL,
match_first_device);
- if (phy)
+ if (phy) {
priv->phy_id = dev_name(phy);
+ if (!priv->phy_id || !*priv->phy_id)
+ put_device(phy);
+ }
}
- if (priv->phy_id && *priv->phy_id) {
- priv->phydev = phy_connect(ndev, priv->phy_id,
- &emac_adjust_link,
- PHY_INTERFACE_MODE_MII);
-
- if (IS_ERR(priv->phydev)) {
+ if (!phydev && priv->phy_id && *priv->phy_id) {
+ phydev = phy_connect(ndev, priv->phy_id,
+ &emac_adjust_link,
+ PHY_INTERFACE_MODE_MII);
+ put_device(phy); /* reference taken by bus_find_device */
+ if (IS_ERR(phydev)) {
dev_err(emac_dev, "could not connect to phy %s\n",
priv->phy_id);
- ret = PTR_ERR(priv->phydev);
- priv->phydev = NULL;
+ ret = PTR_ERR(phydev);
goto err;
}
@@ -1616,11 +1535,10 @@ static int emac_dev_open(struct net_device *ndev)
priv->speed = 0;
priv->duplex = ~0;
- dev_info(emac_dev, "attached PHY driver [%s] "
- "(mii_bus:phy_addr=%s, id=%x)\n",
- priv->phydev->drv->name, dev_name(&priv->phydev->dev),
- priv->phydev->phy_id);
- } else {
+ phy_attached_info(phydev);
+ }
+
+ if (!phydev) {
/* No PHY , fix the link, speed and duplex settings */
dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
priv->link = 1;
@@ -1629,22 +1547,39 @@ static int emac_dev_open(struct net_device *ndev)
emac_update_phystatus(priv);
}
- if (!netif_running(ndev)) /* debug only - to avoid compiler warning */
- emac_dump_regs(priv);
-
if (netif_msg_drv(priv))
dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
- if (priv->phydev)
- phy_start(priv->phydev);
+ if (phydev)
+ phy_start(phydev);
return 0;
+err:
+ emac_int_disable(priv);
+ napi_disable(&priv->napi);
+
rollback:
+ if (dev_of_node(&priv->pdev->dev)) {
+ for (q = res_num - 1; q >= 0; q--) {
+ irq_num = platform_get_irq(priv->pdev, q);
+ if (irq_num > 0)
+ free_irq(irq_num, ndev);
+ }
+ } else {
+ 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;
- dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed");
- ret = -EBUSY;
-err:
+ for (m = irq_num; m >= res->start; m--)
+ free_irq(m, ndev);
+ }
+ }
+ cpdma_ctlr_stop(priv->dma);
pm_runtime_put(&priv->pdev->dev);
return ret;
}
@@ -1660,8 +1595,12 @@ err:
*/
static int emac_dev_stop(struct net_device *ndev)
{
+ struct resource *res;
+ int i = 0;
+ int irq_num;
struct emac_priv *priv = netdev_priv(ndev);
struct device *emac_dev = &ndev->dev;
+ int ret = 0;
/* inform the upper layers. */
netif_stop_queue(ndev);
@@ -1672,14 +1611,35 @@ static int emac_dev_stop(struct net_device *ndev)
cpdma_ctlr_stop(priv->dma);
emac_write(EMAC_SOFTRESET, 1);
- if (priv->phydev)
- phy_disconnect(priv->phydev);
+ if (ndev->phydev)
+ phy_disconnect(ndev->phydev);
+
+ /* Free IRQ */
+ if (dev_of_node(&priv->pdev->dev)) {
+ do {
+ ret = platform_get_irq_optional(priv->pdev, i);
+ if (ret < 0 && ret != -ENXIO)
+ break;
+ if (ret > 0) {
+ free_irq(ret, priv->ndev);
+ } else {
+ ret = 0;
+ break;
+ }
+ } while (++i);
+ } else {
+ while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) {
+ for (irq_num = res->start; irq_num <= res->end; irq_num++)
+ free_irq(irq_num, priv->ndev);
+ i++;
+ }
+ }
if (netif_msg_drv(priv))
dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
pm_runtime_put(&priv->pdev->dev);
- return 0;
+ return ret;
}
/**
@@ -1695,6 +1655,14 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
struct emac_priv *priv = netdev_priv(ndev);
u32 mac_control;
u32 stats_clear_mask;
+ int err;
+
+ err = pm_runtime_resume_and_get(&priv->pdev->dev);
+ if (err < 0) {
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, err);
+ return &ndev->stats;
+ }
/* update emac hardware stats and reset the registers*/
@@ -1737,6 +1705,8 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
+ pm_runtime_put(&priv->pdev->dev);
+
return &ndev->stats;
}
@@ -1746,7 +1716,7 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_start_xmit = emac_dev_xmit,
.ndo_set_rx_mode = emac_dev_mcast_set,
.ndo_set_mac_address = emac_dev_setmac_addr,
- .ndo_do_ioctl = emac_devioctl,
+ .ndo_eth_ioctl = emac_devioctl,
.ndo_tx_timeout = emac_dev_tx_timeout,
.ndo_get_stats = emac_dev_getnetstats,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1758,11 +1728,11 @@ static struct emac_platform_data *
davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
{
struct device_node *np;
+ 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 pdev->dev.platform_data;
+ return dev_get_platdata(&pdev->dev);
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -1771,11 +1741,8 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
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);
- }
+ if (!is_valid_ether_addr(pdata->mac_addr))
+ of_get_mac_address(np, pdata->mac_addr);
of_property_read_u32(np, "ti,davinci-ctrl-reg-offset",
&pdata->ctrl_reg_offset);
@@ -1794,14 +1761,37 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
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 = "";
+ if (!priv->phy_node) {
+ if (!of_phy_is_fixed_link(np))
+ pdata->phy_id = NULL;
+ else if (of_phy_register_fixed_link(np) >= 0)
+ priv->phy_node = of_node_get(np);
+ }
- pdev->dev.platform_data = pdata;
+ auxdata = pdev->dev.platform_data;
+ if (auxdata) {
+ pdata->interrupt_enable = auxdata->interrupt_enable;
+ pdata->interrupt_disable = auxdata->interrupt_disable;
+ }
+
+ auxdata = device_get_match_data(&pdev->dev);
+ if (auxdata) {
+ pdata->version = auxdata->version;
+ pdata->hw_ram_addr = auxdata->hw_ram_addr;
+ }
return pdata;
}
+static int davinci_emac_try_get_mac(struct platform_device *pdev,
+ int instance, u8 *mac_addr)
+{
+ if (!pdev->dev.of_node)
+ return -EINVAL;
+
+ return ti_cm_get_macid(&pdev->dev, instance, mac_addr);
+}
+
/**
* davinci_emac_probe - EMAC device probe
* @pdev: The DaVinci EMAC device that we are removing
@@ -1812,13 +1802,13 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
*/
static int davinci_emac_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
int rc = 0;
- struct resource *res;
+ struct resource *res, *res_ctrl;
struct net_device *ndev;
struct emac_priv *priv;
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;
@@ -1831,6 +1821,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
return -EBUSY;
}
emac_bus_frequency = clk_get_rate(emac_clk);
+ devm_clk_put(&pdev->dev, emac_clk);
/* TODO: Probe PHY here if possible */
@@ -1850,11 +1841,11 @@ static int davinci_emac_probe(struct platform_device *pdev)
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
rc = -ENODEV;
- goto no_pdata;
+ goto err_free_netdev;
}
/* 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;
@@ -1864,26 +1855,35 @@ static int 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);
- priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
- priv->remap_addr = devm_ioremap_resource(&pdev->dev, res);
+ priv->remap_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(priv->remap_addr)) {
rc = PTR_ERR(priv->remap_addr);
goto no_pdata;
}
+ priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
+
+ res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_ctrl) {
+ priv->ctrl_base =
+ devm_ioremap_resource(&pdev->dev, res_ctrl);
+ if (IS_ERR(priv->ctrl_base)) {
+ rc = PTR_ERR(priv->ctrl_base);
+ goto no_pdata;
+ }
+ } else {
+ priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
+ }
+
priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
ndev->base_addr = (unsigned long)priv->remap_addr;
- priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-
hw_ram_addr = pdata->hw_ram_addr;
if (!hw_ram_addr)
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;
@@ -1907,34 +1907,52 @@ static int davinci_emac_probe(struct platform_device *pdev)
goto no_pdata;
}
- priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
- emac_tx_handler);
- priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH),
- emac_rx_handler);
- if (WARN_ON(!priv->txchan || !priv->rxchan)) {
- rc = -ENOMEM;
- goto no_cpdma_chan;
+ priv->txchan = cpdma_chan_create(priv->dma, EMAC_DEF_TX_CH,
+ emac_tx_handler, 0);
+ if (IS_ERR(priv->txchan)) {
+ dev_err(&pdev->dev, "error initializing tx dma channel\n");
+ rc = PTR_ERR(priv->txchan);
+ goto err_free_dma;
}
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(&pdev->dev, "error getting irq res\n");
- rc = -ENOENT;
- goto no_cpdma_chan;
+ priv->rxchan = cpdma_chan_create(priv->dma, EMAC_DEF_RX_CH,
+ emac_rx_handler, 1);
+ if (IS_ERR(priv->rxchan)) {
+ dev_err(&pdev->dev, "error initializing rx dma channel\n");
+ rc = PTR_ERR(priv->rxchan);
+ goto err_free_txchan;
}
- ndev->irq = res->start;
+ rc = platform_get_irq(pdev, 0);
+ if (rc < 0)
+ goto err_free_rxchan;
+ ndev->irq = rc;
+
+ /* If the MAC address is not present, read the registers from the SoC */
if (!is_valid_ether_addr(priv->mac_addr)) {
- /* Use random MAC if none passed */
- 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);
+ rc = davinci_emac_try_get_mac(pdev, res_ctrl ? 0 : 1, priv->mac_addr);
+ if (!rc)
+ eth_hw_addr_set(ndev, priv->mac_addr);
+
+ if (!is_valid_ether_addr(priv->mac_addr)) {
+ /* Use random MAC if still none obtained. */
+ 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, &ethtool_ops);
- netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
+ ndev->ethtool_ops = &ethtool_ops;
+ netif_napi_add(ndev, &priv->napi, emac_poll);
+
+ pm_runtime_enable(&pdev->dev);
+ rc = pm_runtime_resume_and_get(&pdev->dev);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, rc);
+ goto err_napi_del;
+ }
/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -1942,28 +1960,33 @@ static int davinci_emac_probe(struct platform_device *pdev)
if (rc) {
dev_err(&pdev->dev, "error in register_netdev\n");
rc = -ENODEV;
- goto no_cpdma_chan;
+ pm_runtime_put(&pdev->dev);
+ goto err_napi_del;
}
if (netif_msg_probe(priv)) {
- dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
- "(regs: %p, irq: %d)\n",
- (void *)priv->emac_base_phys, ndev->irq);
+ dev_notice(&pdev->dev, "DaVinci EMAC Probe found device "
+ "(regs: %pa, irq: %d)\n",
+ &priv->emac_base_phys, ndev->irq);
}
-
- pm_runtime_enable(&pdev->dev);
- pm_runtime_resume(&pdev->dev);
+ pm_runtime_put(&pdev->dev);
return 0;
-no_cpdma_chan:
- if (priv->txchan)
- cpdma_chan_destroy(priv->txchan);
- if (priv->rxchan)
- cpdma_chan_destroy(priv->rxchan);
+err_napi_del:
+ netif_napi_del(&priv->napi);
+err_free_rxchan:
+ cpdma_chan_destroy(priv->rxchan);
+err_free_txchan:
+ cpdma_chan_destroy(priv->txchan);
+err_free_dma:
cpdma_ctlr_destroy(priv->dma);
no_pdata:
+ if (of_phy_is_fixed_link(np))
+ of_phy_deregister_fixed_link(np);
+ of_node_put(priv->phy_node);
+err_free_netdev:
free_netdev(ndev);
return rc;
}
@@ -1975,10 +1998,11 @@ no_pdata:
* 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 davinci_emac_remove(struct platform_device *pdev)
+static void davinci_emac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct emac_priv *priv = netdev_priv(ndev);
+ struct device_node *np = pdev->dev.of_node;
dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
@@ -1989,15 +2013,16 @@ static int davinci_emac_remove(struct platform_device *pdev)
cpdma_ctlr_destroy(priv->dma);
unregister_netdev(ndev);
+ of_node_put(priv->phy_node);
+ pm_runtime_disable(&pdev->dev);
+ if (of_phy_is_fixed_link(np))
+ of_phy_deregister_fixed_link(np);
free_netdev(ndev);
-
- return 0;
}
static int davinci_emac_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct net_device *ndev = platform_get_drvdata(pdev);
+ struct net_device *ndev = dev_get_drvdata(dev);
if (netif_running(ndev))
emac_dev_stop(ndev);
@@ -2007,8 +2032,7 @@ static int davinci_emac_suspend(struct device *dev)
static int davinci_emac_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct net_device *ndev = platform_get_drvdata(pdev);
+ struct net_device *ndev = dev_get_drvdata(dev);
if (netif_running(ndev))
emac_dev_open(ndev);
@@ -2021,21 +2045,29 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {
.resume = davinci_emac_resume,
};
-#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 emac_platform_data dm816_emac_data = {
+ .version = EMAC_VERSION_2,
+};
+
static const struct of_device_id davinci_emac_of_match[] = {
{.compatible = "ti,davinci-dm6467-emac", },
+ {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
+ {.compatible = "ti,dm816-emac", .data = &dm816_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),
+ .of_match_table = davinci_emac_of_match,
},
.probe = davinci_emac_probe,
.remove = davinci_emac_remove,