diff options
Diffstat (limited to 'target/linux/brcm63xx/patches-3.10/046-bcm63xx_enet-split-DMA-channel-register-accesses.patch')
-rw-r--r-- | target/linux/brcm63xx/patches-3.10/046-bcm63xx_enet-split-DMA-channel-register-accesses.patch | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/target/linux/brcm63xx/patches-3.10/046-bcm63xx_enet-split-DMA-channel-register-accesses.patch b/target/linux/brcm63xx/patches-3.10/046-bcm63xx_enet-split-DMA-channel-register-accesses.patch new file mode 100644 index 0000000000..9bf78e439f --- /dev/null +++ b/target/linux/brcm63xx/patches-3.10/046-bcm63xx_enet-split-DMA-channel-register-accesses.patch @@ -0,0 +1,346 @@ +From 33cab1696444a8e333cf0490bfe04c32d583fd51 Mon Sep 17 00:00:00 2001 +From: Maxime Bizon <mbizon@freebox.fr> +Date: Tue, 4 Jun 2013 20:53:34 +0000 +Subject: [PATCH 2/3] bcm63xx_enet: split DMA channel register accesses + +The current bcm63xx_enet driver always uses bcmenet_shared_base whenever +it needs to access DMA channel configuration space or access the DMA +channel state RAM. Split these register in 3 parts to be more accurate: + +- global DMA configuration +- per DMA channel configuration space +- per DMA channel state RAM space + +This is preliminary to support new chips where the global DMA +configuration remains the same, but there is a varying number of DMA +channels located at a different memory offset. + +Signed-off-by: Maxime Bizon <mbizon@freebox.fr> +Signed-off-by: Jonas Gorski <jogo@openwrt.org> +--- + arch/mips/bcm63xx/dev-enet.c | 23 +++- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 +- + drivers/net/ethernet/broadcom/bcm63xx_enet.c | 139 +++++++++++++--------- + 3 files changed, 105 insertions(+), 61 deletions(-) + +--- a/arch/mips/bcm63xx/dev-enet.c ++++ b/arch/mips/bcm63xx/dev-enet.c +@@ -19,6 +19,16 @@ static struct resource shared_res[] = { + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, ++ { ++ .start = -1, /* filled at runtime */ ++ .end = -1, /* filled at runtime */ ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = -1, /* filled at runtime */ ++ .end = -1, /* filled at runtime */ ++ .flags = IORESOURCE_MEM, ++ }, + }; + + static struct platform_device bcm63xx_enet_shared_device = { +@@ -110,10 +120,15 @@ int __init bcm63xx_enet_register(int uni + if (!shared_device_registered) { + shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); + shared_res[0].end = shared_res[0].start; +- if (BCMCPU_IS_6338()) +- shared_res[0].end += (RSET_ENETDMA_SIZE / 2) - 1; +- else +- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; ++ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; ++ ++ shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); ++ shared_res[1].end = shared_res[1].start; ++ shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1; ++ ++ shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); ++ shared_res[2].end = shared_res[2].start; ++ shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1; + + ret = platform_device_register(&bcm63xx_enet_shared_device); + if (ret) +--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h ++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +@@ -187,7 +187,9 @@ enum bcm63xx_regs_set { + #define BCM_6358_RSET_SPI_SIZE 1804 + #define BCM_6368_RSET_SPI_SIZE 1804 + #define RSET_ENET_SIZE 2048 +-#define RSET_ENETDMA_SIZE 2048 ++#define RSET_ENETDMA_SIZE 256 ++#define RSET_ENETDMAC_SIZE(chans) (16 * (chans)) ++#define RSET_ENETDMAS_SIZE(chans) (16 * (chans)) + #define RSET_ENETSW_SIZE 65536 + #define RSET_UART_SIZE 24 + #define RSET_UDC_SIZE 256 +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +@@ -41,8 +41,8 @@ static int copybreak __read_mostly = 128 + module_param(copybreak, int, 0); + MODULE_PARM_DESC(copybreak, "Receive copy threshold"); + +-/* io memory shared between all devices */ +-static void __iomem *bcm_enet_shared_base; ++/* io registers memory shared between all devices */ ++static void __iomem *bcm_enet_shared_base[3]; + + /* + * io helpers to access mac registers +@@ -63,13 +63,35 @@ static inline void enet_writel(struct bc + */ + static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off) + { +- return bcm_readl(bcm_enet_shared_base + off); ++ return bcm_readl(bcm_enet_shared_base[0] + off); + } + + static inline void enet_dma_writel(struct bcm_enet_priv *priv, + u32 val, u32 off) + { +- bcm_writel(val, bcm_enet_shared_base + off); ++ bcm_writel(val, bcm_enet_shared_base[0] + off); ++} ++ ++static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off) ++{ ++ return bcm_readl(bcm_enet_shared_base[1] + off); ++} ++ ++static inline void enet_dmac_writel(struct bcm_enet_priv *priv, ++ u32 val, u32 off) ++{ ++ bcm_writel(val, bcm_enet_shared_base[1] + off); ++} ++ ++static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off) ++{ ++ return bcm_readl(bcm_enet_shared_base[2] + off); ++} ++ ++static inline void enet_dmas_writel(struct bcm_enet_priv *priv, ++ u32 val, u32 off) ++{ ++ bcm_writel(val, bcm_enet_shared_base[2] + off); + } + + /* +@@ -353,8 +375,8 @@ static int bcm_enet_receive_queue(struct + bcm_enet_refill_rx(dev); + + /* kick rx dma */ +- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, +- ENETDMA_CHANCFG_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, ++ ENETDMAC_CHANCFG_REG(priv->rx_chan)); + } + + return processed; +@@ -429,10 +451,10 @@ static int bcm_enet_poll(struct napi_str + dev = priv->net_dev; + + /* ack interrupts */ +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IR_REG(priv->rx_chan)); +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IR_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IR_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IR_REG(priv->tx_chan)); + + /* reclaim sent skb */ + tx_work_done = bcm_enet_tx_reclaim(dev, 0); +@@ -451,10 +473,10 @@ static int bcm_enet_poll(struct napi_str + napi_complete(napi); + + /* restore rx/tx interrupt */ +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IRMASK_REG(priv->rx_chan)); +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IRMASK_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IRMASK_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IRMASK_REG(priv->tx_chan)); + + return rx_work_done; + } +@@ -497,8 +519,8 @@ static irqreturn_t bcm_enet_isr_dma(int + priv = netdev_priv(dev); + + /* mask rx/tx interrupts */ +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + + napi_schedule(&priv->napi); + +@@ -557,8 +579,8 @@ static int bcm_enet_start_xmit(struct sk + wmb(); + + /* kick tx dma */ +- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, +- ENETDMA_CHANCFG_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, ++ ENETDMAC_CHANCFG_REG(priv->tx_chan)); + + /* stop queue if no more desc available */ + if (!priv->tx_desc_count) +@@ -833,8 +855,8 @@ static int bcm_enet_open(struct net_devi + + /* mask all interrupts and request them */ + enet_writel(priv, 0, ENET_IRMASK_REG); +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + + ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev); + if (ret) +@@ -919,28 +941,28 @@ static int bcm_enet_open(struct net_devi + } + + /* write rx & tx ring addresses */ +- enet_dma_writel(priv, priv->rx_desc_dma, +- ENETDMA_RSTART_REG(priv->rx_chan)); +- enet_dma_writel(priv, priv->tx_desc_dma, +- ENETDMA_RSTART_REG(priv->tx_chan)); ++ enet_dmas_writel(priv, priv->rx_desc_dma, ++ ENETDMAS_RSTART_REG(priv->rx_chan)); ++ enet_dmas_writel(priv, priv->tx_desc_dma, ++ ENETDMAS_RSTART_REG(priv->tx_chan)); + + /* clear remaining state ram for rx & tx channel */ +- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->tx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->tx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan)); ++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan)); + + /* set max rx/tx length */ + enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG); + enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG); + + /* set dma maximum burst len */ +- enet_dma_writel(priv, BCMENET_DMA_MAXBURST, +- ENETDMA_MAXBURST_REG(priv->rx_chan)); +- enet_dma_writel(priv, BCMENET_DMA_MAXBURST, +- ENETDMA_MAXBURST_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, ++ ENETDMAC_MAXBURST_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, ++ ENETDMAC_MAXBURST_REG(priv->tx_chan)); + + /* set correct transmit fifo watermark */ + enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG); +@@ -958,26 +980,26 @@ static int bcm_enet_open(struct net_devi + val |= ENET_CTL_ENABLE_MASK; + enet_writel(priv, val, ENET_CTL_REG); + enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); +- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, +- ENETDMA_CHANCFG_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, ++ ENETDMAC_CHANCFG_REG(priv->rx_chan)); + + /* watch "mib counters about to overflow" interrupt */ + enet_writel(priv, ENET_IR_MIB, ENET_IR_REG); + enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG); + + /* watch "packet transferred" interrupt in rx and tx */ +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IR_REG(priv->rx_chan)); +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IR_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IR_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IR_REG(priv->tx_chan)); + + /* make sure we enable napi before rx interrupt */ + napi_enable(&priv->napi); + +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IRMASK_REG(priv->rx_chan)); +- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, +- ENETDMA_IRMASK_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IRMASK_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, ++ ENETDMAC_IRMASK_REG(priv->tx_chan)); + + if (priv->has_phy) + phy_start(priv->phydev); +@@ -1057,14 +1079,14 @@ static void bcm_enet_disable_dma(struct + { + int limit; + +- enet_dma_writel(priv, 0, ENETDMA_CHANCFG_REG(chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan)); + + limit = 1000; + do { + u32 val; + +- val = enet_dma_readl(priv, ENETDMA_CHANCFG_REG(chan)); +- if (!(val & ENETDMA_CHANCFG_EN_MASK)) ++ val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan)); ++ if (!(val & ENETDMAC_CHANCFG_EN_MASK)) + break; + udelay(1); + } while (limit--); +@@ -1090,8 +1112,8 @@ static int bcm_enet_stop(struct net_devi + + /* mask all interrupts */ + enet_writel(priv, 0, ENET_IRMASK_REG); +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); +- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); ++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + + /* make sure no mib update is scheduled */ + cancel_work_sync(&priv->mib_update_task); +@@ -1636,7 +1658,7 @@ static int bcm_enet_probe(struct platfor + + /* stop if shared driver failed, assume driver->probe will be + * called in the same order we register devices (correct ?) */ +- if (!bcm_enet_shared_base) ++ if (!bcm_enet_shared_base[0]) + return -ENODEV; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1882,14 +1904,19 @@ struct platform_driver bcm63xx_enet_driv + static int bcm_enet_shared_probe(struct platform_device *pdev) + { + struct resource *res; ++ void __iomem *p[3]; ++ unsigned int i; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) +- return -ENODEV; ++ memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base)); + +- bcm_enet_shared_base = devm_request_and_ioremap(&pdev->dev, res); +- if (!bcm_enet_shared_base) +- return -ENOMEM; ++ for (i = 0; i < 3; i++) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, i); ++ p[i] = devm_ioremap_resource(&pdev->dev, res); ++ if (!p[i]) ++ return -ENOMEM; ++ } ++ ++ memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base)); + + return 0; + } |