aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/mvpp2.c
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2017-02-20 11:29:16 +0100
committerStefan Roese <sr@denx.de>2017-03-29 07:40:54 +0200
commitc8feeb2b93a2b320d2a533e0443f95c61e157293 (patch)
treeaa2becbb0e517192092b82070dca00c2ba2e03e4 /drivers/net/mvpp2.c
parentf50a0118d12e362f84ec10240c9e00048779adc5 (diff)
downloadu-boot-c8feeb2b93a2b320d2a533e0443f95c61e157293.zip
u-boot-c8feeb2b93a2b320d2a533e0443f95c61e157293.tar.gz
u-boot-c8feeb2b93a2b320d2a533e0443f95c61e157293.tar.bz2
net: mvpp2: adjust the allocation/free of BM pools for PPv2.2
This commit adjusts the allocation and freeing of BM pools to support PPv2.2. This involves: - Checking that the number of buffer pointers is a multiple of 16, as required by the hardware. - Adjusting the size of the DMA coherent area allocated for buffer pointers. Indeed, PPv2.2 needs space for 2 pointers of 64-bits per buffer, as opposed to 2 pointers of 32-bits per buffer in PPv2.1. The size in bytes is now stored in a new field of the mvpp2_bm_pool structure. - On PPv2.2, getting the physical and virtual address of each buffer requires reading the MVPP2_BM_ADDR_HIGH_ALLOC to get the high order bits of those addresses. A new utility function mvpp2_bm_bufs_get_addrs() is introduced to handle this. - On PPv2.2, releasing a buffer requires writing the high order 32 bits of the physical address to MVPP2_BM_PHY_VIRT_HIGH_RLS_REG. We no longer need to write the virtual address to MVPP2_BM_VIRT_RLS_REG. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Stefan Roese <sr@denx.de> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'drivers/net/mvpp2.c')
-rw-r--r--drivers/net/mvpp2.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 605c8bc..4f4e674 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -251,14 +251,23 @@ do { \
#define MVPP2_BM_PHY_ALLOC_REG(pool) (0x6400 + ((pool) * 4))
#define MVPP2_BM_PHY_ALLOC_GRNTD_MASK BIT(0)
#define MVPP2_BM_VIRT_ALLOC_REG 0x6440
+#define MVPP2_BM_ADDR_HIGH_ALLOC 0x6444
+#define MVPP2_BM_ADDR_HIGH_PHYS_MASK 0xff
+#define MVPP2_BM_ADDR_HIGH_VIRT_MASK 0xff00
+#define MVPP2_BM_ADDR_HIGH_VIRT_SHIFT 8
#define MVPP2_BM_PHY_RLS_REG(pool) (0x6480 + ((pool) * 4))
#define MVPP2_BM_PHY_RLS_MC_BUFF_MASK BIT(0)
#define MVPP2_BM_PHY_RLS_PRIO_EN_MASK BIT(1)
#define MVPP2_BM_PHY_RLS_GRNTD_MASK BIT(2)
#define MVPP2_BM_VIRT_RLS_REG 0x64c0
-#define MVPP2_BM_MC_RLS_REG 0x64c4
+#define MVPP21_BM_MC_RLS_REG 0x64c4
#define MVPP2_BM_MC_ID_MASK 0xfff
#define MVPP2_BM_FORCE_RELEASE_MASK BIT(12)
+#define MVPP22_BM_ADDR_HIGH_RLS_REG 0x64c4
+#define MVPP22_BM_ADDR_HIGH_PHYS_RLS_MASK 0xff
+#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK 0xff00
+#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT 8
+#define MVPP22_BM_MC_RLS_REG 0x64d4
/* TX Scheduler registers */
#define MVPP2_TXP_SCHED_PORT_INDEX_REG 0x8000
@@ -2332,6 +2341,12 @@ static int mvpp2_bm_pool_create(struct udevice *dev,
{
u32 val;
+ /* Number of buffer pointers must be a multiple of 16, as per
+ * hardware constraints
+ */
+ if (!IS_ALIGNED(size, 16))
+ return -EINVAL;
+
bm_pool->virt_addr = buffer_loc.bm_pool[bm_pool->id];
bm_pool->dma_addr = (dma_addr_t)buffer_loc.bm_pool[bm_pool->id];
if (!bm_pool->virt_addr)
@@ -2345,7 +2360,7 @@ static int mvpp2_bm_pool_create(struct udevice *dev,
}
mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id),
- bm_pool->dma_addr);
+ lower_32_bits(bm_pool->dma_addr));
mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size);
val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
@@ -2488,6 +2503,21 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
dma_addr_t buf_dma_addr,
unsigned long buf_phys_addr)
{
+ if (port->priv->hw_version == MVPP22) {
+ u32 val = 0;
+
+ if (sizeof(dma_addr_t) == 8)
+ val |= upper_32_bits(buf_dma_addr) &
+ MVPP22_BM_ADDR_HIGH_PHYS_RLS_MASK;
+
+ if (sizeof(phys_addr_t) == 8)
+ val |= (upper_32_bits(buf_phys_addr)
+ << MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) &
+ MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK;
+
+ mvpp2_write(port->priv, MVPP22_BM_ADDR_HIGH_RLS_REG, val);
+ }
+
/* MVPP2_BM_VIRT_RLS_REG is not interpreted by HW, and simply
* returned in the "cookie" field of the RX
* descriptor. Instead of storing the virtual address, we
@@ -4237,7 +4267,10 @@ static int mvpp2_base_probe(struct udevice *dev)
for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
buffer_loc.bm_pool[i] =
(unsigned long *)((unsigned long)bd_space + size);
- size += MVPP2_BM_POOL_SIZE_MAX * sizeof(u32);
+ if (priv->hw_version == MVPP21)
+ size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u32);
+ else
+ size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u64);
}
for (i = 0; i < MVPP2_BM_LONG_BUF_NUM; i++) {