summaryrefslogtreecommitdiff
path: root/drivers/net/ethoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethoc.c')
-rw-r--r--drivers/net/ethoc.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 198827f..d825aaa 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -179,6 +179,8 @@ struct ethoc {
u32 num_rx;
u32 cur_rx;
void __iomem *iobase;
+ void __iomem *packet;
+ phys_addr_t packet_phys;
};
/**
@@ -247,6 +249,7 @@ static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
static int ethoc_init_ring(struct ethoc *priv)
{
struct ethoc_bd bd;
+ phys_addr_t addr = priv->packet_phys;
int i;
priv->cur_tx = 0;
@@ -258,6 +261,10 @@ static int ethoc_init_ring(struct ethoc *priv)
bd.addr = 0;
for (i = 0; i < priv->num_tx; i++) {
+ if (addr) {
+ bd.addr = addr;
+ addr += PKTSIZE_ALIGN;
+ }
if (i == priv->num_tx - 1)
bd.stat |= TX_BD_WRAP;
@@ -267,7 +274,12 @@ static int ethoc_init_ring(struct ethoc *priv)
bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
for (i = 0; i < priv->num_rx; i++) {
- bd.addr = virt_to_phys(net_rx_packets[i]);
+ if (addr) {
+ bd.addr = addr;
+ addr += PKTSIZE_ALIGN;
+ } else {
+ bd.addr = virt_to_phys(net_rx_packets[i]);
+ }
if (i == priv->num_rx - 1)
bd.stat |= RX_BD_WRAP;
@@ -367,7 +379,10 @@ static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
int size = bd.stat >> 16;
size -= 4; /* strip the CRC */
- *packetp = net_rx_packets[i];
+ if (priv->packet)
+ *packetp = priv->packet + entry * PKTSIZE_ALIGN;
+ else
+ *packetp = net_rx_packets[i];
return size;
} else {
return 0;
@@ -430,8 +445,15 @@ static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
bd.stat |= TX_BD_PAD;
else
bd.stat &= ~TX_BD_PAD;
- bd.addr = virt_to_phys(packet);
+ if (priv->packet) {
+ void *p = priv->packet + entry * PKTSIZE_ALIGN;
+
+ memcpy(p, packet, length);
+ packet = p;
+ } else {
+ bd.addr = virt_to_phys(packet);
+ }
flush_dcache_range((ulong)packet, (ulong)packet + length);
bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
bd.stat |= TX_BD_LEN(length);
@@ -468,12 +490,17 @@ static int ethoc_free_pkt_common(struct ethoc *priv)
struct ethoc_bd bd;
u32 i = priv->cur_rx % priv->num_rx;
u32 entry = priv->num_tx + i;
+ void *src;
ethoc_read_bd(priv, entry, &bd);
+ if (priv->packet)
+ src = priv->packet + entry * PKTSIZE_ALIGN;
+ else
+ src = net_rx_packets[i];
/* clear the buffer descriptor so it can be reused */
- flush_dcache_range((ulong)net_rx_packets[i],
- (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
+ flush_dcache_range((ulong)src,
+ (ulong)src + PKTSIZE_ALIGN);
bd.stat &= ~RX_BD_STATS;
bd.stat |= RX_BD_EMPTY;
ethoc_write_bd(priv, entry, &bd);
@@ -529,8 +556,12 @@ static void ethoc_stop(struct udevice *dev)
static int ethoc_ofdata_to_platdata(struct udevice *dev)
{
struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+ fdt_addr_t addr;
pdata->eth_pdata.iobase = dev_get_addr(dev);
+ addr = dev_get_addr_index(dev, 1);
+ if (addr != FDT_ADDR_T_NONE)
+ pdata->packet_base = addr;
return 0;
}
@@ -540,6 +571,11 @@ static int ethoc_probe(struct udevice *dev)
struct ethoc *priv = dev_get_priv(dev);
priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+ if (pdata->packet_base) {
+ priv->packet_phys = pdata->packet_base;
+ priv->packet = ioremap(pdata->packet_base,
+ (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
+ }
return 0;
}