net: stmmac: Support enhanced addressing mode for DWMAC 4.10
authorThierry Reding <treding@nvidia.com>
Wed, 2 Oct 2019 14:52:58 +0000 (16:52 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 Oct 2019 19:00:50 +0000 (12:00 -0700)
The address width of the controller can be read from hardware feature
registers much like on XGMAC. Add support for parsing the ADDR64 field
so that the DMA mask can be set accordingly.

This avoids getting swiotlb involved for DMA on Tegra186 and later.

Also make sure that the upper 32 bits of the DMA address are written to
the DMA descriptors when enhanced addressing mode is used. Similarily,
for each channel, the upper 32 bits of the DMA descriptor ring's base
address also need to be programmed to make sure the correct memory can
be fetched when the DMA descriptor ring is located beyond the 32-bit
boundary.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h

index 89a3420eba421ad41dd99fb5dd7f67d940ef1b4b..2fe45fa3c482efa6ef9e94ce7b59b58d83fa0213 100644 (file)
@@ -205,6 +205,7 @@ enum power_event {
 #define GMAC_HW_HASH_TB_SZ             GENMASK(25, 24)
 #define GMAC_HW_FEAT_AVSEL             BIT(20)
 #define GMAC_HW_TSOEN                  BIT(18)
+#define GMAC_HW_ADDR64                 GENMASK(15, 14)
 #define GMAC_HW_TXFIFOSIZE             GENMASK(10, 6)
 #define GMAC_HW_RXFIFOSIZE             GENMASK(4, 0)
 
index 15eb1abba91da920926309ecc133a8a24bbdcc1b..707ab5eba8da86f5f80ad423c178eaed1c872b82 100644 (file)
@@ -431,8 +431,8 @@ static void dwmac4_get_addr(struct dma_desc *p, unsigned int *addr)
 
 static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr)
 {
-       p->des0 = cpu_to_le32(addr);
-       p->des1 = 0;
+       p->des0 = cpu_to_le32(lower_32_bits(addr));
+       p->des1 = cpu_to_le32(upper_32_bits(addr));
 }
 
 static void dwmac4_clear(struct dma_desc *p)
index 68c157979b947be5f9c0a1d3847646362ec37957..229059cef949e229f08d11bfc9c4dccaa33e026f 100644 (file)
@@ -79,6 +79,10 @@ static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr,
        value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
        writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
 
+       if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame))
+               writel(upper_32_bits(dma_rx_phy),
+                      ioaddr + DMA_CHAN_RX_BASE_ADDR_HI(chan));
+
        writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RX_BASE_ADDR(chan));
 }
 
@@ -97,6 +101,10 @@ static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr,
 
        writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
 
+       if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame))
+               writel(upper_32_bits(dma_tx_phy),
+                      ioaddr + DMA_CHAN_TX_BASE_ADDR_HI(chan));
+
        writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
 }
 
@@ -132,6 +140,9 @@ static void dwmac4_dma_init(void __iomem *ioaddr,
        if (dma_cfg->aal)
                value |= DMA_SYS_BUS_AAL;
 
+       if (dma_cfg->eame)
+               value |= DMA_SYS_BUS_EAME;
+
        writel(value, ioaddr + DMA_SYS_BUS_MODE);
 }
 
@@ -356,6 +367,23 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
        dma_cap->hash_tb_sz = (hw_cap & GMAC_HW_HASH_TB_SZ) >> 24;
        dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
        dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
+
+       dma_cap->addr64 = (hw_cap & GMAC_HW_ADDR64) >> 14;
+       switch (dma_cap->addr64) {
+       case 0:
+               dma_cap->addr64 = 32;
+               break;
+       case 1:
+               dma_cap->addr64 = 40;
+               break;
+       case 2:
+               dma_cap->addr64 = 48;
+               break;
+       default:
+               dma_cap->addr64 = 32;
+               break;
+       }
+
        /* RX and TX FIFO sizes are encoded as log2(n / 128). Undo that by
         * shifting and store the sizes in bytes.
         */
index b66da0237d2ab5c06e1ce910b6cdecd9a05dd7da..5299fa1001a3a2a0cb20c2a094c8b18271aff9bb 100644 (file)
@@ -65,6 +65,7 @@
 #define DMA_SYS_BUS_MB                 BIT(14)
 #define DMA_AXI_1KBBE                  BIT(13)
 #define DMA_SYS_BUS_AAL                        BIT(12)
+#define DMA_SYS_BUS_EAME               BIT(11)
 #define DMA_AXI_BLEN256                        BIT(7)
 #define DMA_AXI_BLEN128                        BIT(6)
 #define DMA_AXI_BLEN64                 BIT(5)
@@ -91,7 +92,9 @@
 #define DMA_CHAN_CONTROL(x)            DMA_CHANX_BASE_ADDR(x)
 #define DMA_CHAN_TX_CONTROL(x)         (DMA_CHANX_BASE_ADDR(x) + 0x4)
 #define DMA_CHAN_RX_CONTROL(x)         (DMA_CHANX_BASE_ADDR(x) + 0x8)
+#define DMA_CHAN_TX_BASE_ADDR_HI(x)    (DMA_CHANX_BASE_ADDR(x) + 0x10)
 #define DMA_CHAN_TX_BASE_ADDR(x)       (DMA_CHANX_BASE_ADDR(x) + 0x14)
+#define DMA_CHAN_RX_BASE_ADDR_HI(x)    (DMA_CHANX_BASE_ADDR(x) + 0x18)
 #define DMA_CHAN_RX_BASE_ADDR(x)       (DMA_CHANX_BASE_ADDR(x) + 0x1c)
 #define DMA_CHAN_TX_END_ADDR(x)                (DMA_CHANX_BASE_ADDR(x) + 0x20)
 #define DMA_CHAN_RX_END_ADDR(x)                (DMA_CHANX_BASE_ADDR(x) + 0x28)