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   The full GNU General Public License is included in this distribution in
227ac6653aSJeff Kirsher   the file called "COPYING".
237ac6653aSJeff Kirsher 
247ac6653aSJeff Kirsher   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
257ac6653aSJeff Kirsher *******************************************************************************/
267ac6653aSJeff Kirsher 
277ac6653aSJeff Kirsher #include <asm/io.h>
287ac6653aSJeff Kirsher #include "dwmac100.h"
297ac6653aSJeff Kirsher #include "dwmac_dma.h"
307ac6653aSJeff Kirsher 
3150ca903aSNiklas Cassel static void dwmac100_dma_init(void __iomem *ioaddr,
3250ca903aSNiklas Cassel 			      struct stmmac_dma_cfg *dma_cfg,
3350ca903aSNiklas Cassel 			      u32 dma_tx, u32 dma_rx, int atds)
347ac6653aSJeff Kirsher {
357ac6653aSJeff Kirsher 	/* Enable Application Access by writing to DMA CSR0 */
3650ca903aSNiklas Cassel 	writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
377ac6653aSJeff Kirsher 	       ioaddr + DMA_BUS_MODE);
387ac6653aSJeff Kirsher 
397ac6653aSJeff Kirsher 	/* Mask interrupts by writing to CSR7 */
407ac6653aSJeff Kirsher 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
417ac6653aSJeff Kirsher 
42ceb69499SGiuseppe CAVALLARO 	/* RX/TX descriptor base addr lists must be written into
43ceb69499SGiuseppe CAVALLARO 	 * DMA CSR3 and CSR4, respectively
44ceb69499SGiuseppe CAVALLARO 	 */
457ac6653aSJeff Kirsher 	writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
467ac6653aSJeff Kirsher 	writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
477ac6653aSJeff Kirsher }
487ac6653aSJeff Kirsher 
49ceb69499SGiuseppe CAVALLARO /* Store and Forward capability is not used at all.
50ceb69499SGiuseppe CAVALLARO  *
51ceb69499SGiuseppe CAVALLARO  * The transmit threshold can be programmed by setting the TTC bits in the DMA
52ceb69499SGiuseppe CAVALLARO  * control register.
53ceb69499SGiuseppe CAVALLARO  */
547ac6653aSJeff Kirsher static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
55f88203a2SVince Bridgers 					int rxmode, int rxfifosz)
567ac6653aSJeff Kirsher {
577ac6653aSJeff Kirsher 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
587ac6653aSJeff Kirsher 
597ac6653aSJeff Kirsher 	if (txmode <= 32)
607ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_32;
617ac6653aSJeff Kirsher 	else if (txmode <= 64)
627ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_64;
637ac6653aSJeff Kirsher 	else
647ac6653aSJeff Kirsher 		csr6 |= DMA_CONTROL_TTC_128;
657ac6653aSJeff Kirsher 
667ac6653aSJeff Kirsher 	writel(csr6, ioaddr + DMA_CONTROL);
677ac6653aSJeff Kirsher }
687ac6653aSJeff Kirsher 
69fbf68229SLABBE Corentin static void dwmac100_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
707ac6653aSJeff Kirsher {
717ac6653aSJeff Kirsher 	int i;
727ac6653aSJeff Kirsher 
73f4458b92SThor Thayer 	for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++)
74fbf68229SLABBE Corentin 		reg_space[DMA_BUS_MODE / 4 + i] =
75fbf68229SLABBE Corentin 			readl(ioaddr + DMA_BUS_MODE + i * 4);
7683d7af64SGiuseppe CAVALLARO 
77fbf68229SLABBE Corentin 	reg_space[DMA_CUR_TX_BUF_ADDR / 4] =
78fbf68229SLABBE Corentin 		readl(ioaddr + DMA_CUR_TX_BUF_ADDR);
79fbf68229SLABBE Corentin 	reg_space[DMA_CUR_RX_BUF_ADDR / 4] =
80fbf68229SLABBE Corentin 		readl(ioaddr + DMA_CUR_RX_BUF_ADDR);
817ac6653aSJeff Kirsher }
827ac6653aSJeff Kirsher 
83ceb69499SGiuseppe CAVALLARO /* DMA controller has two counters to track the number of the missed frames. */
847ac6653aSJeff Kirsher static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
857ac6653aSJeff Kirsher 				       void __iomem *ioaddr)
867ac6653aSJeff Kirsher {
877ac6653aSJeff Kirsher 	struct net_device_stats *stats = (struct net_device_stats *)data;
887ac6653aSJeff Kirsher 	u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
897ac6653aSJeff Kirsher 
907ac6653aSJeff Kirsher 	if (unlikely(csr8)) {
917ac6653aSJeff Kirsher 		if (csr8 & DMA_MISSED_FRAME_OVE) {
927ac6653aSJeff Kirsher 			stats->rx_over_errors += 0x800;
937ac6653aSJeff Kirsher 			x->rx_overflow_cntr += 0x800;
947ac6653aSJeff Kirsher 		} else {
957ac6653aSJeff Kirsher 			unsigned int ove_cntr;
967ac6653aSJeff Kirsher 			ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
977ac6653aSJeff Kirsher 			stats->rx_over_errors += ove_cntr;
987ac6653aSJeff Kirsher 			x->rx_overflow_cntr += ove_cntr;
997ac6653aSJeff Kirsher 		}
1007ac6653aSJeff Kirsher 
1017ac6653aSJeff Kirsher 		if (csr8 & DMA_MISSED_FRAME_OVE_M) {
1027ac6653aSJeff Kirsher 			stats->rx_missed_errors += 0xffff;
1037ac6653aSJeff Kirsher 			x->rx_missed_cntr += 0xffff;
1047ac6653aSJeff Kirsher 		} else {
1057ac6653aSJeff Kirsher 			unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
1067ac6653aSJeff Kirsher 			stats->rx_missed_errors += miss_f;
1077ac6653aSJeff Kirsher 			x->rx_missed_cntr += miss_f;
1087ac6653aSJeff Kirsher 		}
1097ac6653aSJeff Kirsher 	}
1107ac6653aSJeff Kirsher }
1117ac6653aSJeff Kirsher 
1127ac6653aSJeff Kirsher const struct stmmac_dma_ops dwmac100_dma_ops = {
113495db273SGiuseppe Cavallaro 	.reset = dwmac_dma_reset,
1147ac6653aSJeff Kirsher 	.init = dwmac100_dma_init,
1157ac6653aSJeff Kirsher 	.dump_regs = dwmac100_dump_dma_regs,
1167ac6653aSJeff Kirsher 	.dma_mode = dwmac100_dma_operation_mode,
1177ac6653aSJeff Kirsher 	.dma_diagnostic_fr = dwmac100_dma_diagnostic_fr,
1187ac6653aSJeff Kirsher 	.enable_dma_transmission = dwmac_enable_dma_transmission,
1197ac6653aSJeff Kirsher 	.enable_dma_irq = dwmac_enable_dma_irq,
1207ac6653aSJeff Kirsher 	.disable_dma_irq = dwmac_disable_dma_irq,
1217ac6653aSJeff Kirsher 	.start_tx = dwmac_dma_start_tx,
1227ac6653aSJeff Kirsher 	.stop_tx = dwmac_dma_stop_tx,
1237ac6653aSJeff Kirsher 	.start_rx = dwmac_dma_start_rx,
1247ac6653aSJeff Kirsher 	.stop_rx = dwmac_dma_stop_rx,
1257ac6653aSJeff Kirsher 	.dma_interrupt = dwmac_dma_interrupt,
1267ac6653aSJeff Kirsher };
127