17ac6653aSJeff Kirsher /*******************************************************************************
27ac6653aSJeff Kirsher   This is the driver for the MAC 10/100 on-chip Ethernet controller
37ac6653aSJeff Kirsher   currently tested on all the ST boards based on STb7109 and stx7200 SoCs.
47ac6653aSJeff Kirsher 
57ac6653aSJeff Kirsher   DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
67ac6653aSJeff Kirsher   this code.
77ac6653aSJeff Kirsher 
87ac6653aSJeff Kirsher   This contains the functions to handle the dma.
97ac6653aSJeff Kirsher 
107ac6653aSJeff Kirsher   Copyright (C) 2007-2009  STMicroelectronics Ltd
117ac6653aSJeff Kirsher 
127ac6653aSJeff Kirsher   This program is free software; you can redistribute it and/or modify it
137ac6653aSJeff Kirsher   under the terms and conditions of the GNU General Public License,
147ac6653aSJeff Kirsher   version 2, as published by the Free Software Foundation.
157ac6653aSJeff Kirsher 
167ac6653aSJeff Kirsher   This program is distributed in the hope it will be useful, but WITHOUT
177ac6653aSJeff Kirsher   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187ac6653aSJeff Kirsher   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
197ac6653aSJeff Kirsher   more details.
207ac6653aSJeff Kirsher 
217ac6653aSJeff Kirsher   You should have received a copy of the GNU General Public License along with
227ac6653aSJeff Kirsher   this program; if not, write to the Free Software Foundation, Inc.,
237ac6653aSJeff Kirsher   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
247ac6653aSJeff Kirsher 
257ac6653aSJeff Kirsher   The full GNU General Public License is included in this distribution in
267ac6653aSJeff Kirsher   the file called "COPYING".
277ac6653aSJeff Kirsher 
287ac6653aSJeff Kirsher   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
297ac6653aSJeff Kirsher *******************************************************************************/
307ac6653aSJeff Kirsher 
317ac6653aSJeff Kirsher #include <asm/io.h>
327ac6653aSJeff Kirsher #include "dwmac100.h"
337ac6653aSJeff Kirsher #include "dwmac_dma.h"
347ac6653aSJeff Kirsher 
35c24602efSGiuseppe CAVALLARO static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
36c24602efSGiuseppe CAVALLARO 			     int burst_len, u32 dma_tx, u32 dma_rx, int atds)
377ac6653aSJeff Kirsher {
387ac6653aSJeff Kirsher 	u32 value = readl(ioaddr + DMA_BUS_MODE);
397ac6653aSJeff Kirsher 	int limit;
407ac6653aSJeff Kirsher 
417ac6653aSJeff Kirsher 	/* DMA SW reset */
427ac6653aSJeff Kirsher 	value |= DMA_BUS_MODE_SFT_RESET;
437ac6653aSJeff Kirsher 	writel(value, ioaddr + DMA_BUS_MODE);
44bbc17546SFrancesco Virlinzi 	limit = 10;
457ac6653aSJeff Kirsher 	while (limit--) {
467ac6653aSJeff Kirsher 		if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
477ac6653aSJeff Kirsher 			break;
48bbc17546SFrancesco Virlinzi 		mdelay(10);
497ac6653aSJeff Kirsher 	}
507ac6653aSJeff Kirsher 	if (limit < 0)
517ac6653aSJeff Kirsher 		return -EBUSY;
527ac6653aSJeff Kirsher 
537ac6653aSJeff Kirsher 	/* Enable Application Access by writing to DMA CSR0 */
547ac6653aSJeff Kirsher 	writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
557ac6653aSJeff Kirsher 	       ioaddr + DMA_BUS_MODE);
567ac6653aSJeff Kirsher 
577ac6653aSJeff Kirsher 	/* Mask interrupts by writing to CSR7 */
587ac6653aSJeff Kirsher 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
597ac6653aSJeff Kirsher 
60ceb69499SGiuseppe CAVALLARO 	/* RX/TX descriptor base addr lists must be written into
61ceb69499SGiuseppe CAVALLARO 	 * DMA CSR3 and CSR4, respectively
62ceb69499SGiuseppe CAVALLARO 	 */
637ac6653aSJeff Kirsher 	writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
647ac6653aSJeff Kirsher 	writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
657ac6653aSJeff Kirsher 
667ac6653aSJeff Kirsher 	return 0;
677ac6653aSJeff Kirsher }
687ac6653aSJeff Kirsher 
69ceb69499SGiuseppe CAVALLARO /* Store and Forward capability is not used at all.
70ceb69499SGiuseppe CAVALLARO  *
71ceb69499SGiuseppe CAVALLARO  * The transmit threshold can be programmed by setting the TTC bits in the DMA
72ceb69499SGiuseppe CAVALLARO  * control register.
73ceb69499SGiuseppe CAVALLARO  */
747ac6653aSJeff Kirsher static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
757ac6653aSJeff Kirsher 					int rxmode)
767ac6653aSJeff Kirsher {
777ac6653aSJeff Kirsher 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
787ac6653aSJeff Kirsher 
797ac6653aSJeff Kirsher 	if (txmode <= 32)
807ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_32;
817ac6653aSJeff Kirsher 	else if (txmode <= 64)
827ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_64;
837ac6653aSJeff Kirsher 	else
847ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_128;
857ac6653aSJeff Kirsher 
867ac6653aSJeff Kirsher 	writel(csr6, ioaddr + DMA_CONTROL);
877ac6653aSJeff Kirsher }
887ac6653aSJeff Kirsher 
897ac6653aSJeff Kirsher static void dwmac100_dump_dma_regs(void __iomem *ioaddr)
907ac6653aSJeff Kirsher {
917ac6653aSJeff Kirsher 	int i;
927ac6653aSJeff Kirsher 
9383d7af64SGiuseppe CAVALLARO 	pr_debug("DWMAC 100 DMA CSR\n");
947ac6653aSJeff Kirsher 	for (i = 0; i < 9; i++)
957ac6653aSJeff Kirsher 		pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i,
967ac6653aSJeff Kirsher 			 (DMA_BUS_MODE + i * 4),
977ac6653aSJeff Kirsher 			 readl(ioaddr + DMA_BUS_MODE + i * 4));
9883d7af64SGiuseppe CAVALLARO 
9983d7af64SGiuseppe CAVALLARO 	pr_debug("\tCSR20 (0x%x): 0x%08x, CSR21 (0x%x): 0x%08x\n",
10083d7af64SGiuseppe CAVALLARO 		 DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR),
1017ac6653aSJeff Kirsher 		 DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR));
1027ac6653aSJeff Kirsher }
1037ac6653aSJeff Kirsher 
104ceb69499SGiuseppe CAVALLARO /* DMA controller has two counters to track the number of the missed frames. */
1057ac6653aSJeff Kirsher static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
1067ac6653aSJeff Kirsher 				       void __iomem *ioaddr)
1077ac6653aSJeff Kirsher {
1087ac6653aSJeff Kirsher 	struct net_device_stats *stats = (struct net_device_stats *)data;
1097ac6653aSJeff Kirsher 	u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
1107ac6653aSJeff Kirsher 
1117ac6653aSJeff Kirsher 	if (unlikely(csr8)) {
1127ac6653aSJeff Kirsher 		if (csr8 & DMA_MISSED_FRAME_OVE) {
1137ac6653aSJeff Kirsher 			stats->rx_over_errors += 0x800;
1147ac6653aSJeff Kirsher 			x->rx_overflow_cntr += 0x800;
1157ac6653aSJeff Kirsher 		} else {
1167ac6653aSJeff Kirsher 			unsigned int ove_cntr;
1177ac6653aSJeff Kirsher 			ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
1187ac6653aSJeff Kirsher 			stats->rx_over_errors += ove_cntr;
1197ac6653aSJeff Kirsher 			x->rx_overflow_cntr += ove_cntr;
1207ac6653aSJeff Kirsher 		}
1217ac6653aSJeff Kirsher 
1227ac6653aSJeff Kirsher 		if (csr8 & DMA_MISSED_FRAME_OVE_M) {
1237ac6653aSJeff Kirsher 			stats->rx_missed_errors += 0xffff;
1247ac6653aSJeff Kirsher 			x->rx_missed_cntr += 0xffff;
1257ac6653aSJeff Kirsher 		} else {
1267ac6653aSJeff Kirsher 			unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
1277ac6653aSJeff Kirsher 			stats->rx_missed_errors += miss_f;
1287ac6653aSJeff Kirsher 			x->rx_missed_cntr += miss_f;
1297ac6653aSJeff Kirsher 		}
1307ac6653aSJeff Kirsher 	}
1317ac6653aSJeff Kirsher }
1327ac6653aSJeff Kirsher 
1337ac6653aSJeff Kirsher const struct stmmac_dma_ops dwmac100_dma_ops = {
1347ac6653aSJeff Kirsher 	.init = dwmac100_dma_init,
1357ac6653aSJeff Kirsher 	.dump_regs = dwmac100_dump_dma_regs,
1367ac6653aSJeff Kirsher 	.dma_mode = dwmac100_dma_operation_mode,
1377ac6653aSJeff Kirsher 	.dma_diagnostic_fr = dwmac100_dma_diagnostic_fr,
1387ac6653aSJeff Kirsher 	.enable_dma_transmission = dwmac_enable_dma_transmission,
1397ac6653aSJeff Kirsher 	.enable_dma_irq = dwmac_enable_dma_irq,
1407ac6653aSJeff Kirsher 	.disable_dma_irq = dwmac_disable_dma_irq,
1417ac6653aSJeff Kirsher 	.start_tx = dwmac_dma_start_tx,
1427ac6653aSJeff Kirsher 	.stop_tx = dwmac_dma_stop_tx,
1437ac6653aSJeff Kirsher 	.start_rx = dwmac_dma_start_rx,
1447ac6653aSJeff Kirsher 	.stop_rx = dwmac_dma_stop_rx,
1457ac6653aSJeff Kirsher 	.dma_interrupt = dwmac_dma_interrupt,
1467ac6653aSJeff Kirsher };
147