diff options
| author | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-25 21:16:51 +0000 | 
|---|---|---|
| committer | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-25 21:16:51 +0000 | 
| commit | 0b1b6a028308ee9df70d00a9de2fafd2538ac01c (patch) | |
| tree | 9fde69e62a7f7eb03a0ea5f94db8ccaa77f02613 /target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch | |
| parent | 0cddb5e96a70c9d1449da52ecbb9d99f8d13974d (diff) | |
[brcm63xx] add preliminary support for 3.6 kernel
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33936 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch')
| -rw-r--r-- | target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch | 381 | 
1 files changed, 381 insertions, 0 deletions
diff --git a/target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch b/target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch new file mode 100644 index 000000000..90999fa95 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.6/414-bcm63xx_enet-split-dma-registers-access.patch @@ -0,0 +1,381 @@ +From 305579c1f946ed1aa6c125252ace21c53d47c11d Mon Sep 17 00:00:00 2001 +From: Maxime Bizon <mbizon@freebox.fr> +Date: Thu, 21 Jan 2010 17:50:54 +0100 +Subject: [PATCH 30/63] bcm63xx_enet: split dma registers access. + +--- + arch/mips/bcm63xx/dev-enet.c                     |   23 +++- + arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h |    4 +- + drivers/net/ethernet/broadcom/bcm63xx_enet.c     |  179 ++++++++++++++-------- + 3 files changed, 138 insertions(+), 68 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 +@@ -172,7 +172,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_HSSPI_SIZE			1536 +--- 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) +@@ -801,8 +823,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) +@@ -891,28 +913,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); +@@ -930,26 +952,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); +@@ -1026,14 +1048,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--); +@@ -1059,8 +1081,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); +@@ -1598,7 +1620,7 @@ static int __devinit bcm_enet_probe(stru +  + 	/* 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); +@@ -1904,30 +1926,61 @@ struct platform_driver bcm63xx_enet_driv + static int __devinit bcm_enet_shared_probe(struct platform_device *pdev) + { + 	struct resource *res; ++	int ret, i, requested[3]; +  +-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +-	if (!res) +-		return -ENODEV; ++	memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base)); ++	memset(requested, 0, sizeof (requested)); +  +-	if (!request_mem_region(res->start, resource_size(res), +-				"bcm63xx_enet_dma")) +-		return -EBUSY; ++	for (i = 0; i < 3; i++) { ++		void __iomem *p; +  +-	bcm_enet_shared_base = ioremap(res->start, resource_size(res)); +-	if (!bcm_enet_shared_base) { +-		release_mem_region(res->start, resource_size(res)); +-		return -ENOMEM; ++		res = platform_get_resource(pdev, IORESOURCE_MEM, i); ++		if (!res) { ++			ret = -EINVAL; ++			goto fail; ++		} ++ ++		if (!request_mem_region(res->start, resource_size(res), ++					"bcm63xx_enet_dma")) { ++			ret = -EBUSY; ++			goto fail; ++		} ++		requested[i] = 0; ++ ++		p = ioremap(res->start, resource_size(res)); ++		if (!p) { ++			ret = -ENOMEM; ++			goto fail; ++		} ++ ++		bcm_enet_shared_base[i] = p; + 	} ++ + 	return 0; ++ ++fail: ++	for (i = 0; i < 3; i++) { ++		res = platform_get_resource(pdev, IORESOURCE_MEM, i); ++		if (!res) ++			continue; ++		if (bcm_enet_shared_base[i]) ++			iounmap(bcm_enet_shared_base[i]); ++		if (requested[i]) ++			release_mem_region(res->start, resource_size(res)); ++	} ++	return ret; + } +  + static int __devexit bcm_enet_shared_remove(struct platform_device *pdev) + { + 	struct resource *res; ++	int i; +  +-	iounmap(bcm_enet_shared_base); +-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +-	release_mem_region(res->start, resource_size(res)); ++	for (i = 0; i < 3; i++) { ++		iounmap(bcm_enet_shared_base[i]); ++		res = platform_get_resource(pdev, IORESOURCE_MEM, i); ++		release_mem_region(res->start, resource_size(res)); ++	} + 	return 0; + } +   | 
