]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
net/ethoc: support private memory configurations
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 5 Aug 2016 15:26:20 +0000 (18:26 +0300)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 15 Aug 2016 18:34:48 +0000 (13:34 -0500)
The ethoc device can be configured to have a private memory region
instead of having access to the main memory. In that case egress packets
must be copied into that memory for transmission and pointers to that
memory need to be passed to net_process_received_packet or returned from
the recv callback.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/ethoc.c
include/dm/platform_data/net_ethoc.h

index 198827f912277d2be5771146d548b187c9913428..d825aaa88795a7af9214e8253124a3e28e928b9a 100644 (file)
@@ -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;
 }
 
index 1d8c73c037f950ee76e6a38ad7516b96c1e7bd64..3f94bde7b26295413c03b4d998988763819061a7 100644 (file)
@@ -13,6 +13,7 @@
 
 struct ethoc_eth_pdata {
        struct eth_pdata eth_pdata;
+       phys_addr_t packet_base;
 };
 
 #endif