|
@@ -62,12 +62,11 @@
|
|
|
#include <linux/bitops.h>
|
|
|
#include <linux/io.h>
|
|
|
#include <linux/uaccess.h>
|
|
|
+#include <linux/davinci_emac.h>
|
|
|
|
|
|
#include <asm/irq.h>
|
|
|
#include <asm/page.h>
|
|
|
|
|
|
-#include <mach/emac.h>
|
|
|
-
|
|
|
static int debug_level;
|
|
|
module_param(debug_level, int, 0);
|
|
|
MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
|
|
@@ -465,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 */
|
|
@@ -488,6 +488,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 */
|
|
@@ -495,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)
|
|
@@ -1002,6 +1003,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);
|
|
|
|
|
@@ -1021,6 +1024,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);
|
|
|
|
|
@@ -1302,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;
|
|
@@ -1312,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 */
|
|
@@ -1399,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;
|
|
@@ -1411,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;
|
|
@@ -1604,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;
|
|
@@ -1879,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 {
|
|
@@ -1890,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;
|
|
@@ -1987,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;
|
|
@@ -1998,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;
|
|
@@ -2099,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 */
|
|
@@ -2660,6 +2668,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);
|
|
@@ -2692,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");
|