From 8ee2bf9ab792d0c02b13ca3acbd036debb7745d9 Mon Sep 17 00:00:00 2001 From: Sriramakrishnan Date: Thu, 19 Nov 2009 15:58:25 +0530 Subject: TI Davinci EMAC : Re-use driver for other platforms. The davinci EMAC peripheral is also available on other TI platforms -notably TI AM3517 SoC. This patch modifies the config option and the platform structure header files so that the driver can be reused on non-davinci platforms as well. Signed-off-by: Sriramakrishnan Acked-by: Chaithrika U S Acked-by: David S. Miller Signed-off-by: Kevin Hilman --- include/linux/davinci_emac.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/linux/davinci_emac.h (limited to 'include') diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h new file mode 100644 index 00000000000..ff5548747df --- /dev/null +++ b/include/linux/davinci_emac.h @@ -0,0 +1,36 @@ +/* + * TI DaVinci EMAC platform support + * + * Author: Kevin Hilman, Deep Root Systems, LLC + * + * 2007 (c) Deep Root Systems, LLC. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef _LINUX_DAVINCI_EMAC_H +#define _LINUX_DAVINCI_EMAC_H + +#include +#include + +struct emac_platform_data { + char mac_addr[ETH_ALEN]; + u32 ctrl_reg_offset; + u32 ctrl_mod_reg_offset; + u32 ctrl_ram_offset; + u32 mdio_reg_offset; + u32 ctrl_ram_size; + u32 phy_mask; + u32 mdio_max_freq; + u8 rmii_en; + u8 version; +}; + +enum { + EMAC_VERSION_1, /* DM644x */ + EMAC_VERSION_2, /* DM646x */ +}; + +void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context); +#endif -- cgit v1.2.3 From 01a9af36cd9d25fc71e28192974732d8053bd1c0 Mon Sep 17 00:00:00 2001 From: Sriramakrishnan Date: Thu, 19 Nov 2009 15:58:26 +0530 Subject: TI Davinci EMAC : add platform specific interrupt enable/disable logic. On certain SOCs, the EMAC controller is interfaced with a wrapper logic for handling interrupts. This patch implements a platform specific hook to cater to platforms that require custom interrupt handling logic Signed-off-by: Sriramakrishnan Acked-by: Chaithrika U S Acked-by: David S. Miller Signed-off-by: Kevin Hilman --- drivers/net/davinci_emac.c | 11 +++++++++++ include/linux/davinci_emac.h | 2 ++ 2 files changed, 13 insertions(+) (limited to 'include') diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 9ebac35d3af..c735b62baa0 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -487,6 +487,9 @@ struct emac_priv { struct mii_bus *mii_bus; struct phy_device *phydev; spinlock_t lock; + /*platform specific members*/ + void (*int_enable) (void); + void (*int_disable) (void); }; /* clock frequency for EMAC */ @@ -1001,6 +1004,8 @@ static void emac_int_disable(struct emac_priv *priv) emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0); emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0); /* NOTE: Rx Threshold and Misc interrupts are not disabled */ + if (priv->int_disable) + priv->int_disable(); local_irq_restore(flags); @@ -1020,6 +1025,9 @@ static void emac_int_disable(struct emac_priv *priv) static void emac_int_enable(struct emac_priv *priv) { if (priv->version == EMAC_VERSION_2) { + if (priv->int_enable) + priv->int_enable(); + emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff); emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff); @@ -2659,6 +2667,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->phy_mask = pdata->phy_mask; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; + priv->int_enable = pdata->interrupt_enable; + priv->int_disable = pdata->interrupt_disable; + emac_dev = &ndev->dev; /* Get EMAC platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index ff5548747df..6d894efd8a3 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -25,6 +25,8 @@ struct emac_platform_data { u32 mdio_max_freq; u8 rmii_en; u8 version; + void (*interrupt_enable) (void); + void (*interrupt_disable) (void); }; enum { -- cgit v1.2.3 From ad021ae8862209864dc8ebd3b7d3a55ce84b9ea2 Mon Sep 17 00:00:00 2001 From: Sriramakrishnan Date: Thu, 19 Nov 2009 15:58:27 +0530 Subject: TI Davinci EMAC : Abstract Buffer address translation logic. When programming the DMA engine, the next pointers must be programmed with physical address as seen from the DMA master address space. This address may be different from physical address of the buffer RAM area. This patch abstracts the buffer address translation logic. Signed-off-by: Sriramakrishnan Acked-by: Chaithrika U S Acked-by: David S. Miller Signed-off-by: Kevin Hilman --- drivers/net/davinci_emac.c | 41 ++++++++++++++++++++++++----------------- include/linux/davinci_emac.h | 1 + 2 files changed, 25 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index c735b62baa0..1605bc225b0 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -464,6 +464,7 @@ struct emac_priv { void __iomem *ctrl_base; void __iomem *emac_ctrl_ram; u32 ctrl_ram_size; + u32 hw_ram_addr; struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; u32 link; /* 1=link on, 0=link off */ @@ -497,11 +498,9 @@ static struct clk *emac_clk; static unsigned long emac_bus_frequency; static unsigned long mdio_max_freq; -/* EMAC internal utility function */ -static inline u32 emac_virt_to_phys(void __iomem *addr) -{ - return (u32 __force) io_v2p(addr); -} +#define emac_virt_to_phys(addr, priv) \ + (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ + + priv->hw_ram_addr) /* Cache macros - Packet buffers would be from skb pool which is cached */ #define EMAC_VIRT_NOCACHE(addr) (addr) @@ -1309,7 +1308,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) curr_bd = txch->active_queue_head; if (NULL == curr_bd) { emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed)); + emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); txch->no_active_pkts++; spin_unlock_irqrestore(&priv->tx_lock, flags); return 0; @@ -1319,7 +1318,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) while ((curr_bd) && ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd)); + emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); txch->active_queue_head = curr_bd->next; if (frame_status & EMAC_CPPI_EOQ_BIT) { if (curr_bd->next) { /* misqueued packet */ @@ -1406,7 +1405,7 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) txch->active_queue_tail = curr_bd; if (1 != txch->queue_active) { emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd)); + emac_virt_to_phys(curr_bd, priv)); txch->queue_active = 1; } ++txch->queue_reinit; @@ -1418,10 +1417,11 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) tail_bd->next = curr_bd; txch->active_queue_tail = curr_bd; tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd); + tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); frame_status = tail_bd->mode; if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), emac_virt_to_phys(curr_bd)); + emac_write(EMAC_TXHDP(ch), + emac_virt_to_phys(curr_bd, priv)); frame_status &= ~(EMAC_CPPI_EOQ_BIT); tail_bd->mode = frame_status; ++txch->end_of_queue_add; @@ -1611,7 +1611,8 @@ static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) } /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head); + curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, + priv); /* FIXME buff_ptr = dma_map_single(... data_ptr ...) */ curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr); curr_bd->off_b_len = rxch->buf_size; @@ -1886,7 +1887,7 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, rxch->active_queue_tail = curr_bd; if (0 != rxch->queue_active) { emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head)); + emac_virt_to_phys(rxch->active_queue_head, priv)); rxch->queue_active = 1; } } else { @@ -1897,11 +1898,11 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, rxch->active_queue_tail = curr_bd; tail_bd->next = curr_bd; tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd); + tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); frame_status = tail_bd->mode; if (frame_status & EMAC_CPPI_EOQ_BIT) { emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd)); + emac_virt_to_phys(curr_bd, priv)); frame_status &= ~(EMAC_CPPI_EOQ_BIT); tail_bd->mode = frame_status; ++rxch->end_of_queue_add; @@ -1994,7 +1995,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) curr_pkt->num_bufs = 1; curr_pkt->pkt_length = (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd)); + emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); ++rxch->processed_bd; last_bd = curr_bd; curr_bd = last_bd->next; @@ -2005,7 +2006,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) if (curr_bd) { ++rxch->mis_queued_packets; emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd)); + emac_virt_to_phys(curr_bd, priv)); } else { ++rxch->end_of_queue; rxch->queue_active = 0; @@ -2106,7 +2107,7 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXINTMASKSET, BIT(ch)); rxch->queue_active = 1; emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head)); + emac_virt_to_phys(rxch->active_queue_head, priv)); } /* Enable MII */ @@ -2702,6 +2703,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; + if (pdata->hw_ram_addr) + priv->hw_ram_addr = pdata->hw_ram_addr; + else + priv->hw_ram_addr = (u32 __force)res->start + + pdata->ctrl_ram_offset; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n"); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 6d894efd8a3..7c930dba477 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -19,6 +19,7 @@ struct emac_platform_data { u32 ctrl_reg_offset; u32 ctrl_mod_reg_offset; u32 ctrl_ram_offset; + u32 hw_ram_addr; u32 mdio_reg_offset; u32 ctrl_ram_size; u32 phy_mask; -- cgit v1.2.3