xref: /rk3399_rockchip-uboot/drivers/net/bcm-sf2-eth-gmac.c (revision 799e125cca9f75a6e3bc87676266f8da4ebefcfd)
1*799e125cSJiandong Zheng /*
2*799e125cSJiandong Zheng  * Copyright 2014 Broadcom Corporation.
3*799e125cSJiandong Zheng  *
4*799e125cSJiandong Zheng  * SPDX-License-Identifier:	GPL-2.0+
5*799e125cSJiandong Zheng  */
6*799e125cSJiandong Zheng 
7*799e125cSJiandong Zheng #ifdef BCM_GMAC_DEBUG
8*799e125cSJiandong Zheng #ifndef DEBUG
9*799e125cSJiandong Zheng #define DEBUG
10*799e125cSJiandong Zheng #endif
11*799e125cSJiandong Zheng #endif
12*799e125cSJiandong Zheng 
13*799e125cSJiandong Zheng #include <config.h>
14*799e125cSJiandong Zheng #include <common.h>
15*799e125cSJiandong Zheng #include <malloc.h>
16*799e125cSJiandong Zheng #include <net.h>
17*799e125cSJiandong Zheng #include <asm/io.h>
18*799e125cSJiandong Zheng #include <phy.h>
19*799e125cSJiandong Zheng 
20*799e125cSJiandong Zheng #include "bcm-sf2-eth.h"
21*799e125cSJiandong Zheng #include "bcm-sf2-eth-gmac.h"
22*799e125cSJiandong Zheng 
23*799e125cSJiandong Zheng #define SPINWAIT(exp, us) { \
24*799e125cSJiandong Zheng 	uint countdown = (us) + 9; \
25*799e125cSJiandong Zheng 	while ((exp) && (countdown >= 10)) {\
26*799e125cSJiandong Zheng 		udelay(10); \
27*799e125cSJiandong Zheng 		countdown -= 10; \
28*799e125cSJiandong Zheng 	} \
29*799e125cSJiandong Zheng }
30*799e125cSJiandong Zheng 
31*799e125cSJiandong Zheng static int gmac_disable_dma(struct eth_dma *dma, int dir);
32*799e125cSJiandong Zheng static int gmac_enable_dma(struct eth_dma *dma, int dir);
33*799e125cSJiandong Zheng 
34*799e125cSJiandong Zheng /* DMA Descriptor */
35*799e125cSJiandong Zheng typedef struct {
36*799e125cSJiandong Zheng 	/* misc control bits */
37*799e125cSJiandong Zheng 	uint32_t	ctrl1;
38*799e125cSJiandong Zheng 	/* buffer count and address extension */
39*799e125cSJiandong Zheng 	uint32_t	ctrl2;
40*799e125cSJiandong Zheng 	/* memory address of the date buffer, bits 31:0 */
41*799e125cSJiandong Zheng 	uint32_t	addrlow;
42*799e125cSJiandong Zheng 	/* memory address of the date buffer, bits 63:32 */
43*799e125cSJiandong Zheng 	uint32_t	addrhigh;
44*799e125cSJiandong Zheng } dma64dd_t;
45*799e125cSJiandong Zheng 
46*799e125cSJiandong Zheng uint32_t g_dmactrlflags;
47*799e125cSJiandong Zheng 
48*799e125cSJiandong Zheng static uint32_t dma_ctrlflags(uint32_t mask, uint32_t flags)
49*799e125cSJiandong Zheng {
50*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
51*799e125cSJiandong Zheng 
52*799e125cSJiandong Zheng 	g_dmactrlflags &= ~mask;
53*799e125cSJiandong Zheng 	g_dmactrlflags |= flags;
54*799e125cSJiandong Zheng 
55*799e125cSJiandong Zheng 	/* If trying to enable parity, check if parity is actually supported */
56*799e125cSJiandong Zheng 	if (g_dmactrlflags & DMA_CTRL_PEN) {
57*799e125cSJiandong Zheng 		uint32_t control;
58*799e125cSJiandong Zheng 
59*799e125cSJiandong Zheng 		control = readl(GMAC0_DMA_TX_CTRL_ADDR);
60*799e125cSJiandong Zheng 		writel(control | D64_XC_PD, GMAC0_DMA_TX_CTRL_ADDR);
61*799e125cSJiandong Zheng 		if (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_PD) {
62*799e125cSJiandong Zheng 			/*
63*799e125cSJiandong Zheng 			 * We *can* disable it, therefore it is supported;
64*799e125cSJiandong Zheng 			 * restore control register
65*799e125cSJiandong Zheng 			 */
66*799e125cSJiandong Zheng 			writel(control, GMAC0_DMA_TX_CTRL_ADDR);
67*799e125cSJiandong Zheng 		} else {
68*799e125cSJiandong Zheng 			/* Not supported, don't allow it to be enabled */
69*799e125cSJiandong Zheng 			g_dmactrlflags &= ~DMA_CTRL_PEN;
70*799e125cSJiandong Zheng 		}
71*799e125cSJiandong Zheng 	}
72*799e125cSJiandong Zheng 
73*799e125cSJiandong Zheng 	return g_dmactrlflags;
74*799e125cSJiandong Zheng }
75*799e125cSJiandong Zheng 
76*799e125cSJiandong Zheng static inline void reg32_clear_bits(uint32_t reg, uint32_t value)
77*799e125cSJiandong Zheng {
78*799e125cSJiandong Zheng 	uint32_t v = readl(reg);
79*799e125cSJiandong Zheng 	v &= ~(value);
80*799e125cSJiandong Zheng 	writel(v, reg);
81*799e125cSJiandong Zheng }
82*799e125cSJiandong Zheng 
83*799e125cSJiandong Zheng static inline void reg32_set_bits(uint32_t reg, uint32_t value)
84*799e125cSJiandong Zheng {
85*799e125cSJiandong Zheng 	uint32_t v = readl(reg);
86*799e125cSJiandong Zheng 	v |= value;
87*799e125cSJiandong Zheng 	writel(v, reg);
88*799e125cSJiandong Zheng }
89*799e125cSJiandong Zheng 
90*799e125cSJiandong Zheng #ifdef BCM_GMAC_DEBUG
91*799e125cSJiandong Zheng static void dma_tx_dump(struct eth_dma *dma)
92*799e125cSJiandong Zheng {
93*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
94*799e125cSJiandong Zheng 	uint8_t *bufp;
95*799e125cSJiandong Zheng 	int i;
96*799e125cSJiandong Zheng 
97*799e125cSJiandong Zheng 	printf("TX DMA Register:\n");
98*799e125cSJiandong Zheng 	printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n",
99*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_CTRL_ADDR),
100*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_PTR_ADDR),
101*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_ADDR_LOW_ADDR),
102*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_ADDR_HIGH_ADDR),
103*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_STATUS0_ADDR),
104*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_TX_STATUS1_ADDR));
105*799e125cSJiandong Zheng 
106*799e125cSJiandong Zheng 	printf("TX Descriptors:\n");
107*799e125cSJiandong Zheng 	for (i = 0; i < TX_BUF_NUM; i++) {
108*799e125cSJiandong Zheng 		descp = (dma64dd_t *)(dma->tx_desc_aligned) + i;
109*799e125cSJiandong Zheng 		printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n",
110*799e125cSJiandong Zheng 		       descp->ctrl1, descp->ctrl2,
111*799e125cSJiandong Zheng 		       descp->addrhigh, descp->addrlow);
112*799e125cSJiandong Zheng 	}
113*799e125cSJiandong Zheng 
114*799e125cSJiandong Zheng 	printf("TX Buffers:\n");
115*799e125cSJiandong Zheng 	/* Initialize TX DMA descriptor table */
116*799e125cSJiandong Zheng 	for (i = 0; i < TX_BUF_NUM; i++) {
117*799e125cSJiandong Zheng 		bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE);
118*799e125cSJiandong Zheng 		printf("buf%d:0x%x; ", i, (uint32_t)bufp);
119*799e125cSJiandong Zheng 	}
120*799e125cSJiandong Zheng 	printf("\n");
121*799e125cSJiandong Zheng }
122*799e125cSJiandong Zheng 
123*799e125cSJiandong Zheng static void dma_rx_dump(struct eth_dma *dma)
124*799e125cSJiandong Zheng {
125*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
126*799e125cSJiandong Zheng 	uint8_t *bufp;
127*799e125cSJiandong Zheng 	int i;
128*799e125cSJiandong Zheng 
129*799e125cSJiandong Zheng 	printf("RX DMA Register:\n");
130*799e125cSJiandong Zheng 	printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n",
131*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_CTRL_ADDR),
132*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_PTR_ADDR),
133*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_ADDR_LOW_ADDR),
134*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_ADDR_HIGH_ADDR),
135*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_STATUS0_ADDR),
136*799e125cSJiandong Zheng 	       readl(GMAC0_DMA_RX_STATUS1_ADDR));
137*799e125cSJiandong Zheng 
138*799e125cSJiandong Zheng 	printf("RX Descriptors:\n");
139*799e125cSJiandong Zheng 	for (i = 0; i < RX_BUF_NUM; i++) {
140*799e125cSJiandong Zheng 		descp = (dma64dd_t *)(dma->rx_desc_aligned) + i;
141*799e125cSJiandong Zheng 		printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n",
142*799e125cSJiandong Zheng 		       descp->ctrl1, descp->ctrl2,
143*799e125cSJiandong Zheng 		       descp->addrhigh, descp->addrlow);
144*799e125cSJiandong Zheng 	}
145*799e125cSJiandong Zheng 
146*799e125cSJiandong Zheng 	printf("RX Buffers:\n");
147*799e125cSJiandong Zheng 	for (i = 0; i < RX_BUF_NUM; i++) {
148*799e125cSJiandong Zheng 		bufp = dma->rx_buf + i * RX_BUF_SIZE;
149*799e125cSJiandong Zheng 		printf("buf%d:0x%x; ", i, (uint32_t)bufp);
150*799e125cSJiandong Zheng 	}
151*799e125cSJiandong Zheng 	printf("\n");
152*799e125cSJiandong Zheng }
153*799e125cSJiandong Zheng #endif
154*799e125cSJiandong Zheng 
155*799e125cSJiandong Zheng static int dma_tx_init(struct eth_dma *dma)
156*799e125cSJiandong Zheng {
157*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
158*799e125cSJiandong Zheng 	uint8_t *bufp;
159*799e125cSJiandong Zheng 	int i;
160*799e125cSJiandong Zheng 	uint32_t ctrl;
161*799e125cSJiandong Zheng 
162*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
163*799e125cSJiandong Zheng 
164*799e125cSJiandong Zheng 	/* clear descriptor memory */
165*799e125cSJiandong Zheng 	memset((void *)(dma->tx_desc_aligned), 0,
166*799e125cSJiandong Zheng 	       TX_BUF_NUM * sizeof(dma64dd_t));
167*799e125cSJiandong Zheng 	memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE);
168*799e125cSJiandong Zheng 
169*799e125cSJiandong Zheng 	/* Initialize TX DMA descriptor table */
170*799e125cSJiandong Zheng 	for (i = 0; i < TX_BUF_NUM; i++) {
171*799e125cSJiandong Zheng 		descp = (dma64dd_t *)(dma->tx_desc_aligned) + i;
172*799e125cSJiandong Zheng 		bufp = dma->tx_buf + i * TX_BUF_SIZE;
173*799e125cSJiandong Zheng 		/* clear buffer memory */
174*799e125cSJiandong Zheng 		memset((void *)bufp, 0, TX_BUF_SIZE);
175*799e125cSJiandong Zheng 
176*799e125cSJiandong Zheng 		ctrl = 0;
177*799e125cSJiandong Zheng 		/* if last descr set endOfTable */
178*799e125cSJiandong Zheng 		if (i == (TX_BUF_NUM-1))
179*799e125cSJiandong Zheng 			ctrl = D64_CTRL1_EOT;
180*799e125cSJiandong Zheng 		descp->ctrl1 = ctrl;
181*799e125cSJiandong Zheng 		descp->ctrl2 = 0;
182*799e125cSJiandong Zheng 		descp->addrlow = (uint32_t)bufp;
183*799e125cSJiandong Zheng 		descp->addrhigh = 0;
184*799e125cSJiandong Zheng 	}
185*799e125cSJiandong Zheng 
186*799e125cSJiandong Zheng 	/* flush descriptor and buffer */
187*799e125cSJiandong Zheng 	descp = dma->tx_desc_aligned;
188*799e125cSJiandong Zheng 	bufp = dma->tx_buf;
189*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)descp,
190*799e125cSJiandong Zheng 			   (unsigned long)(descp +
191*799e125cSJiandong Zheng 					   sizeof(dma64dd_t) * TX_BUF_NUM));
192*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)(bufp),
193*799e125cSJiandong Zheng 			   (unsigned long)(bufp + TX_BUF_SIZE * TX_BUF_NUM));
194*799e125cSJiandong Zheng 
195*799e125cSJiandong Zheng 	/* initialize the DMA channel */
196*799e125cSJiandong Zheng 	writel((uint32_t)(dma->tx_desc_aligned), GMAC0_DMA_TX_ADDR_LOW_ADDR);
197*799e125cSJiandong Zheng 	writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR);
198*799e125cSJiandong Zheng 
199*799e125cSJiandong Zheng 	/* now update the dma last descriptor */
200*799e125cSJiandong Zheng 	writel(((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK,
201*799e125cSJiandong Zheng 	       GMAC0_DMA_TX_PTR_ADDR);
202*799e125cSJiandong Zheng 
203*799e125cSJiandong Zheng 	return 0;
204*799e125cSJiandong Zheng }
205*799e125cSJiandong Zheng 
206*799e125cSJiandong Zheng static int dma_rx_init(struct eth_dma *dma)
207*799e125cSJiandong Zheng {
208*799e125cSJiandong Zheng 	uint32_t last_desc;
209*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
210*799e125cSJiandong Zheng 	uint8_t *bufp;
211*799e125cSJiandong Zheng 	uint32_t ctrl;
212*799e125cSJiandong Zheng 	int i;
213*799e125cSJiandong Zheng 
214*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
215*799e125cSJiandong Zheng 
216*799e125cSJiandong Zheng 	/* clear descriptor memory */
217*799e125cSJiandong Zheng 	memset((void *)(dma->rx_desc_aligned), 0,
218*799e125cSJiandong Zheng 	       RX_BUF_NUM * sizeof(dma64dd_t));
219*799e125cSJiandong Zheng 	/* clear buffer memory */
220*799e125cSJiandong Zheng 	memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE);
221*799e125cSJiandong Zheng 
222*799e125cSJiandong Zheng 	/* Initialize RX DMA descriptor table */
223*799e125cSJiandong Zheng 	for (i = 0; i < RX_BUF_NUM; i++) {
224*799e125cSJiandong Zheng 		descp = (dma64dd_t *)(dma->rx_desc_aligned) + i;
225*799e125cSJiandong Zheng 		bufp = dma->rx_buf + i * RX_BUF_SIZE;
226*799e125cSJiandong Zheng 		ctrl = 0;
227*799e125cSJiandong Zheng 		/* if last descr set endOfTable */
228*799e125cSJiandong Zheng 		if (i == (RX_BUF_NUM - 1))
229*799e125cSJiandong Zheng 			ctrl = D64_CTRL1_EOT;
230*799e125cSJiandong Zheng 		descp->ctrl1 = ctrl;
231*799e125cSJiandong Zheng 		descp->ctrl2 = RX_BUF_SIZE;
232*799e125cSJiandong Zheng 		descp->addrlow = (uint32_t)bufp;
233*799e125cSJiandong Zheng 		descp->addrhigh = 0;
234*799e125cSJiandong Zheng 
235*799e125cSJiandong Zheng 		last_desc = ((uint32_t)(descp) & D64_XP_LD_MASK)
236*799e125cSJiandong Zheng 				+ sizeof(dma64dd_t);
237*799e125cSJiandong Zheng 	}
238*799e125cSJiandong Zheng 
239*799e125cSJiandong Zheng 	descp = dma->rx_desc_aligned;
240*799e125cSJiandong Zheng 	bufp = dma->rx_buf;
241*799e125cSJiandong Zheng 	/* flush descriptor and buffer */
242*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)descp,
243*799e125cSJiandong Zheng 			   (unsigned long)(descp +
244*799e125cSJiandong Zheng 					   sizeof(dma64dd_t) * RX_BUF_NUM));
245*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)(bufp),
246*799e125cSJiandong Zheng 			   (unsigned long)(bufp + RX_BUF_SIZE * RX_BUF_NUM));
247*799e125cSJiandong Zheng 
248*799e125cSJiandong Zheng 	/* initailize the DMA channel */
249*799e125cSJiandong Zheng 	writel((uint32_t)descp, GMAC0_DMA_RX_ADDR_LOW_ADDR);
250*799e125cSJiandong Zheng 	writel(0, GMAC0_DMA_RX_ADDR_HIGH_ADDR);
251*799e125cSJiandong Zheng 
252*799e125cSJiandong Zheng 	/* now update the dma last descriptor */
253*799e125cSJiandong Zheng 	writel(last_desc, GMAC0_DMA_RX_PTR_ADDR);
254*799e125cSJiandong Zheng 
255*799e125cSJiandong Zheng 	return 0;
256*799e125cSJiandong Zheng }
257*799e125cSJiandong Zheng 
258*799e125cSJiandong Zheng static int dma_init(struct eth_dma *dma)
259*799e125cSJiandong Zheng {
260*799e125cSJiandong Zheng 	debug(" %s enter\n", __func__);
261*799e125cSJiandong Zheng 
262*799e125cSJiandong Zheng 	/*
263*799e125cSJiandong Zheng 	 * Default flags: For backwards compatibility both
264*799e125cSJiandong Zheng 	 * Rx Overflow Continue and Parity are DISABLED.
265*799e125cSJiandong Zheng 	 */
266*799e125cSJiandong Zheng 	dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
267*799e125cSJiandong Zheng 
268*799e125cSJiandong Zheng 	debug("rx burst len 0x%x\n",
269*799e125cSJiandong Zheng 	      (readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK)
270*799e125cSJiandong Zheng 	      >> D64_RC_BL_SHIFT);
271*799e125cSJiandong Zheng 	debug("tx burst len 0x%x\n",
272*799e125cSJiandong Zheng 	      (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_BL_MASK)
273*799e125cSJiandong Zheng 	      >> D64_XC_BL_SHIFT);
274*799e125cSJiandong Zheng 
275*799e125cSJiandong Zheng 	dma_tx_init(dma);
276*799e125cSJiandong Zheng 	dma_rx_init(dma);
277*799e125cSJiandong Zheng 
278*799e125cSJiandong Zheng 	/* From end of chip_init() */
279*799e125cSJiandong Zheng 	/* enable the overflow continue feature and disable parity */
280*799e125cSJiandong Zheng 	dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */,
281*799e125cSJiandong Zheng 		      DMA_CTRL_ROC /* value */);
282*799e125cSJiandong Zheng 
283*799e125cSJiandong Zheng 	return 0;
284*799e125cSJiandong Zheng }
285*799e125cSJiandong Zheng 
286*799e125cSJiandong Zheng static int dma_deinit(struct eth_dma *dma)
287*799e125cSJiandong Zheng {
288*799e125cSJiandong Zheng 	debug(" %s enter\n", __func__);
289*799e125cSJiandong Zheng 
290*799e125cSJiandong Zheng 	gmac_disable_dma(dma, MAC_DMA_RX);
291*799e125cSJiandong Zheng 	gmac_disable_dma(dma, MAC_DMA_TX);
292*799e125cSJiandong Zheng 
293*799e125cSJiandong Zheng 	free(dma->tx_buf);
294*799e125cSJiandong Zheng 	dma->tx_buf = NULL;
295*799e125cSJiandong Zheng 	free(dma->tx_desc);
296*799e125cSJiandong Zheng 	dma->tx_desc = NULL;
297*799e125cSJiandong Zheng 	dma->tx_desc_aligned = NULL;
298*799e125cSJiandong Zheng 
299*799e125cSJiandong Zheng 	free(dma->rx_buf);
300*799e125cSJiandong Zheng 	dma->rx_buf = NULL;
301*799e125cSJiandong Zheng 	free(dma->rx_desc);
302*799e125cSJiandong Zheng 	dma->rx_desc = NULL;
303*799e125cSJiandong Zheng 	dma->rx_desc_aligned = NULL;
304*799e125cSJiandong Zheng 
305*799e125cSJiandong Zheng 	return 0;
306*799e125cSJiandong Zheng }
307*799e125cSJiandong Zheng 
308*799e125cSJiandong Zheng int gmac_tx_packet(struct eth_dma *dma, void *packet, int length)
309*799e125cSJiandong Zheng {
310*799e125cSJiandong Zheng 	uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE;
311*799e125cSJiandong Zheng 
312*799e125cSJiandong Zheng 	/* kick off the dma */
313*799e125cSJiandong Zheng 	size_t len = length;
314*799e125cSJiandong Zheng 	int txout = dma->cur_tx_index;
315*799e125cSJiandong Zheng 	uint32_t flags;
316*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
317*799e125cSJiandong Zheng 	uint32_t ctrl;
318*799e125cSJiandong Zheng 	uint32_t last_desc = (((uint32_t)dma->tx_desc_aligned) +
319*799e125cSJiandong Zheng 			      sizeof(dma64dd_t)) & D64_XP_LD_MASK;
320*799e125cSJiandong Zheng 	size_t buflen;
321*799e125cSJiandong Zheng 
322*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
323*799e125cSJiandong Zheng 
324*799e125cSJiandong Zheng 	/* load the buffer */
325*799e125cSJiandong Zheng 	memcpy(bufp, packet, len);
326*799e125cSJiandong Zheng 
327*799e125cSJiandong Zheng 	/* Add 4 bytes for Ethernet FCS/CRC */
328*799e125cSJiandong Zheng 	buflen = len + 4;
329*799e125cSJiandong Zheng 
330*799e125cSJiandong Zheng 	ctrl = (buflen & D64_CTRL2_BC_MASK);
331*799e125cSJiandong Zheng 
332*799e125cSJiandong Zheng 	/* the transmit will only be one frame or set SOF, EOF */
333*799e125cSJiandong Zheng 	/* also set int on completion */
334*799e125cSJiandong Zheng 	flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF;
335*799e125cSJiandong Zheng 
336*799e125cSJiandong Zheng 	/* txout points to the descriptor to uset */
337*799e125cSJiandong Zheng 	/* if last descriptor then set EOT */
338*799e125cSJiandong Zheng 	if (txout == (TX_BUF_NUM - 1)) {
339*799e125cSJiandong Zheng 		flags |= D64_CTRL1_EOT;
340*799e125cSJiandong Zheng 		last_desc = ((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK;
341*799e125cSJiandong Zheng 	}
342*799e125cSJiandong Zheng 
343*799e125cSJiandong Zheng 	/* write the descriptor */
344*799e125cSJiandong Zheng 	descp = ((dma64dd_t *)(dma->tx_desc_aligned)) + txout;
345*799e125cSJiandong Zheng 	descp->addrlow = (uint32_t)bufp;
346*799e125cSJiandong Zheng 	descp->addrhigh = 0;
347*799e125cSJiandong Zheng 	descp->ctrl1 = flags;
348*799e125cSJiandong Zheng 	descp->ctrl2 = ctrl;
349*799e125cSJiandong Zheng 
350*799e125cSJiandong Zheng 	/* flush descriptor and buffer */
351*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)descp,
352*799e125cSJiandong Zheng 			   (unsigned long)(descp + sizeof(dma64dd_t)));
353*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)bufp,
354*799e125cSJiandong Zheng 			   (unsigned long)(bufp + TX_BUF_SIZE));
355*799e125cSJiandong Zheng 
356*799e125cSJiandong Zheng 	/* now update the dma last descriptor */
357*799e125cSJiandong Zheng 	writel(last_desc, GMAC0_DMA_TX_PTR_ADDR);
358*799e125cSJiandong Zheng 
359*799e125cSJiandong Zheng 	/* tx dma should be enabled so packet should go out */
360*799e125cSJiandong Zheng 
361*799e125cSJiandong Zheng 	/* update txout */
362*799e125cSJiandong Zheng 	dma->cur_tx_index = (txout + 1) & (TX_BUF_NUM - 1);
363*799e125cSJiandong Zheng 
364*799e125cSJiandong Zheng 	return 0;
365*799e125cSJiandong Zheng }
366*799e125cSJiandong Zheng 
367*799e125cSJiandong Zheng bool gmac_check_tx_done(struct eth_dma *dma)
368*799e125cSJiandong Zheng {
369*799e125cSJiandong Zheng 	/* wait for tx to complete */
370*799e125cSJiandong Zheng 	uint32_t intstatus;
371*799e125cSJiandong Zheng 	bool xfrdone = false;
372*799e125cSJiandong Zheng 
373*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
374*799e125cSJiandong Zheng 
375*799e125cSJiandong Zheng 	intstatus = readl(GMAC0_INT_STATUS_ADDR);
376*799e125cSJiandong Zheng 
377*799e125cSJiandong Zheng 	debug("int(0x%x)\n", intstatus);
378*799e125cSJiandong Zheng 	if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) {
379*799e125cSJiandong Zheng 		xfrdone = true;
380*799e125cSJiandong Zheng 		/* clear the int bits */
381*799e125cSJiandong Zheng 		intstatus &= ~(I_XI0 | I_XI1 | I_XI2 | I_XI3);
382*799e125cSJiandong Zheng 		writel(intstatus, GMAC0_INT_STATUS_ADDR);
383*799e125cSJiandong Zheng 	} else {
384*799e125cSJiandong Zheng 		debug("Tx int(0x%x)\n", intstatus);
385*799e125cSJiandong Zheng 	}
386*799e125cSJiandong Zheng 
387*799e125cSJiandong Zheng 	return xfrdone;
388*799e125cSJiandong Zheng }
389*799e125cSJiandong Zheng 
390*799e125cSJiandong Zheng int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf)
391*799e125cSJiandong Zheng {
392*799e125cSJiandong Zheng 	void *bufp, *datap;
393*799e125cSJiandong Zheng 	size_t rcvlen = 0, buflen = 0;
394*799e125cSJiandong Zheng 	uint32_t stat0 = 0, stat1 = 0;
395*799e125cSJiandong Zheng 	uint32_t control, offset;
396*799e125cSJiandong Zheng 	uint8_t statbuf[HWRXOFF*2];
397*799e125cSJiandong Zheng 
398*799e125cSJiandong Zheng 	int index, curr, active;
399*799e125cSJiandong Zheng 	dma64dd_t *descp = NULL;
400*799e125cSJiandong Zheng 
401*799e125cSJiandong Zheng 	/* udelay(50); */
402*799e125cSJiandong Zheng 
403*799e125cSJiandong Zheng 	/*
404*799e125cSJiandong Zheng 	 * this api will check if a packet has been received.
405*799e125cSJiandong Zheng 	 * If so it will return the address of the buffer and current
406*799e125cSJiandong Zheng 	 * descriptor index will be incremented to the
407*799e125cSJiandong Zheng 	 * next descriptor. Once done with the frame the buffer should be
408*799e125cSJiandong Zheng 	 * added back onto the descriptor and the lastdscr should be updated
409*799e125cSJiandong Zheng 	 * to this descriptor.
410*799e125cSJiandong Zheng 	 */
411*799e125cSJiandong Zheng 	index = dma->cur_rx_index;
412*799e125cSJiandong Zheng 	offset = (uint32_t)(dma->rx_desc_aligned);
413*799e125cSJiandong Zheng 	stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR) & D64_RS0_CD_MASK;
414*799e125cSJiandong Zheng 	stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR) & D64_RS0_CD_MASK;
415*799e125cSJiandong Zheng 	curr = ((stat0 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t);
416*799e125cSJiandong Zheng 	active = ((stat1 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t);
417*799e125cSJiandong Zheng 
418*799e125cSJiandong Zheng 	/* check if any frame */
419*799e125cSJiandong Zheng 	if (index == curr)
420*799e125cSJiandong Zheng 		return -1;
421*799e125cSJiandong Zheng 
422*799e125cSJiandong Zheng 	debug("received packet\n");
423*799e125cSJiandong Zheng 	debug("expect(0x%x) curr(0x%x) active(0x%x)\n", index, curr, active);
424*799e125cSJiandong Zheng 	/* remove warning */
425*799e125cSJiandong Zheng 	if (index == active)
426*799e125cSJiandong Zheng 		;
427*799e125cSJiandong Zheng 
428*799e125cSJiandong Zheng 	/* get the packet pointer that corresponds to the rx descriptor */
429*799e125cSJiandong Zheng 	bufp = dma->rx_buf + index * RX_BUF_SIZE;
430*799e125cSJiandong Zheng 
431*799e125cSJiandong Zheng 	descp = (dma64dd_t *)(dma->rx_desc_aligned) + index;
432*799e125cSJiandong Zheng 	/* flush descriptor and buffer */
433*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)descp,
434*799e125cSJiandong Zheng 			   (unsigned long)(descp + sizeof(dma64dd_t)));
435*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)bufp,
436*799e125cSJiandong Zheng 			   (unsigned long)(bufp + RX_BUF_SIZE));
437*799e125cSJiandong Zheng 
438*799e125cSJiandong Zheng 	buflen = (descp->ctrl2 & D64_CTRL2_BC_MASK);
439*799e125cSJiandong Zheng 
440*799e125cSJiandong Zheng 	stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR);
441*799e125cSJiandong Zheng 	stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR);
442*799e125cSJiandong Zheng 
443*799e125cSJiandong Zheng 	debug("bufp(0x%x) index(0x%x) buflen(0x%x) stat0(0x%x) stat1(0x%x)\n",
444*799e125cSJiandong Zheng 	      (uint32_t)bufp, index, buflen, stat0, stat1);
445*799e125cSJiandong Zheng 
446*799e125cSJiandong Zheng 	dma->cur_rx_index = (index + 1) & (RX_BUF_NUM - 1);
447*799e125cSJiandong Zheng 
448*799e125cSJiandong Zheng 	/* get buffer offset */
449*799e125cSJiandong Zheng 	control = readl(GMAC0_DMA_RX_CTRL_ADDR);
450*799e125cSJiandong Zheng 	offset = (control & D64_RC_RO_MASK) >> D64_RC_RO_SHIFT;
451*799e125cSJiandong Zheng 	rcvlen = *(uint16_t *)bufp;
452*799e125cSJiandong Zheng 
453*799e125cSJiandong Zheng 	debug("Received %d bytes\n", rcvlen);
454*799e125cSJiandong Zheng 	/* copy status into temp buf then copy data from rx buffer */
455*799e125cSJiandong Zheng 	memcpy(statbuf, bufp, offset);
456*799e125cSJiandong Zheng 	datap = (void *)((uint32_t)bufp + offset);
457*799e125cSJiandong Zheng 	memcpy(buf, datap, rcvlen);
458*799e125cSJiandong Zheng 
459*799e125cSJiandong Zheng 	/* update descriptor that is being added back on ring */
460*799e125cSJiandong Zheng 	descp->ctrl2 = RX_BUF_SIZE;
461*799e125cSJiandong Zheng 	descp->addrlow = (uint32_t)bufp;
462*799e125cSJiandong Zheng 	descp->addrhigh = 0;
463*799e125cSJiandong Zheng 	/* flush descriptor */
464*799e125cSJiandong Zheng 	flush_dcache_range((unsigned long)descp,
465*799e125cSJiandong Zheng 			   (unsigned long)(descp + sizeof(dma64dd_t)));
466*799e125cSJiandong Zheng 
467*799e125cSJiandong Zheng 	/* set the lastdscr for the rx ring */
468*799e125cSJiandong Zheng 	writel(((uint32_t)descp) & D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
469*799e125cSJiandong Zheng 
470*799e125cSJiandong Zheng 	return (int)rcvlen;
471*799e125cSJiandong Zheng }
472*799e125cSJiandong Zheng 
473*799e125cSJiandong Zheng static int gmac_disable_dma(struct eth_dma *dma, int dir)
474*799e125cSJiandong Zheng {
475*799e125cSJiandong Zheng 	int status;
476*799e125cSJiandong Zheng 
477*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
478*799e125cSJiandong Zheng 
479*799e125cSJiandong Zheng 	if (dir == MAC_DMA_TX) {
480*799e125cSJiandong Zheng 		/* address PR8249/PR7577 issue */
481*799e125cSJiandong Zheng 		/* suspend tx DMA first */
482*799e125cSJiandong Zheng 		writel(D64_XC_SE, GMAC0_DMA_TX_CTRL_ADDR);
483*799e125cSJiandong Zheng 		SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) &
484*799e125cSJiandong Zheng 				     D64_XS0_XS_MASK)) !=
485*799e125cSJiandong Zheng 			  D64_XS0_XS_DISABLED) &&
486*799e125cSJiandong Zheng 			 (status != D64_XS0_XS_IDLE) &&
487*799e125cSJiandong Zheng 			 (status != D64_XS0_XS_STOPPED), 10000);
488*799e125cSJiandong Zheng 
489*799e125cSJiandong Zheng 		/*
490*799e125cSJiandong Zheng 		 * PR2414 WAR: DMA engines are not disabled until
491*799e125cSJiandong Zheng 		 * transfer finishes
492*799e125cSJiandong Zheng 		 */
493*799e125cSJiandong Zheng 		writel(0, GMAC0_DMA_TX_CTRL_ADDR);
494*799e125cSJiandong Zheng 		SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) &
495*799e125cSJiandong Zheng 				     D64_XS0_XS_MASK)) !=
496*799e125cSJiandong Zheng 			  D64_XS0_XS_DISABLED), 10000);
497*799e125cSJiandong Zheng 
498*799e125cSJiandong Zheng 		/* wait for the last transaction to complete */
499*799e125cSJiandong Zheng 		udelay(2);
500*799e125cSJiandong Zheng 
501*799e125cSJiandong Zheng 		status = (status == D64_XS0_XS_DISABLED);
502*799e125cSJiandong Zheng 	} else {
503*799e125cSJiandong Zheng 		/*
504*799e125cSJiandong Zheng 		 * PR2414 WAR: DMA engines are not disabled until
505*799e125cSJiandong Zheng 		 * transfer finishes
506*799e125cSJiandong Zheng 		 */
507*799e125cSJiandong Zheng 		writel(0, GMAC0_DMA_RX_CTRL_ADDR);
508*799e125cSJiandong Zheng 		SPINWAIT(((status = (readl(GMAC0_DMA_RX_STATUS0_ADDR) &
509*799e125cSJiandong Zheng 				     D64_RS0_RS_MASK)) !=
510*799e125cSJiandong Zheng 			  D64_RS0_RS_DISABLED), 10000);
511*799e125cSJiandong Zheng 
512*799e125cSJiandong Zheng 		status = (status == D64_RS0_RS_DISABLED);
513*799e125cSJiandong Zheng 	}
514*799e125cSJiandong Zheng 
515*799e125cSJiandong Zheng 	return status;
516*799e125cSJiandong Zheng }
517*799e125cSJiandong Zheng 
518*799e125cSJiandong Zheng static int gmac_enable_dma(struct eth_dma *dma, int dir)
519*799e125cSJiandong Zheng {
520*799e125cSJiandong Zheng 	uint32_t control;
521*799e125cSJiandong Zheng 
522*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
523*799e125cSJiandong Zheng 
524*799e125cSJiandong Zheng 	if (dir == MAC_DMA_TX) {
525*799e125cSJiandong Zheng 		dma->cur_tx_index = 0;
526*799e125cSJiandong Zheng 
527*799e125cSJiandong Zheng 		/*
528*799e125cSJiandong Zheng 		 * These bits 20:18 (burstLen) of control register can be
529*799e125cSJiandong Zheng 		 * written but will take effect only if these bits are
530*799e125cSJiandong Zheng 		 * valid. So this will not affect previous versions
531*799e125cSJiandong Zheng 		 * of the DMA. They will continue to have those bits set to 0.
532*799e125cSJiandong Zheng 		 */
533*799e125cSJiandong Zheng 		control = readl(GMAC0_DMA_TX_CTRL_ADDR);
534*799e125cSJiandong Zheng 
535*799e125cSJiandong Zheng 		control |= D64_XC_XE;
536*799e125cSJiandong Zheng 		if ((g_dmactrlflags & DMA_CTRL_PEN) == 0)
537*799e125cSJiandong Zheng 			control |= D64_XC_PD;
538*799e125cSJiandong Zheng 
539*799e125cSJiandong Zheng 		writel(control, GMAC0_DMA_TX_CTRL_ADDR);
540*799e125cSJiandong Zheng 
541*799e125cSJiandong Zheng 		/* initailize the DMA channel */
542*799e125cSJiandong Zheng 		writel((uint32_t)(dma->tx_desc_aligned),
543*799e125cSJiandong Zheng 		       GMAC0_DMA_TX_ADDR_LOW_ADDR);
544*799e125cSJiandong Zheng 		writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR);
545*799e125cSJiandong Zheng 	} else {
546*799e125cSJiandong Zheng 		dma->cur_rx_index = 0;
547*799e125cSJiandong Zheng 
548*799e125cSJiandong Zheng 		control = (readl(GMAC0_DMA_RX_CTRL_ADDR) &
549*799e125cSJiandong Zheng 			   D64_RC_AE) | D64_RC_RE;
550*799e125cSJiandong Zheng 
551*799e125cSJiandong Zheng 		if ((g_dmactrlflags & DMA_CTRL_PEN) == 0)
552*799e125cSJiandong Zheng 			control |= D64_RC_PD;
553*799e125cSJiandong Zheng 
554*799e125cSJiandong Zheng 		if (g_dmactrlflags & DMA_CTRL_ROC)
555*799e125cSJiandong Zheng 			control |= D64_RC_OC;
556*799e125cSJiandong Zheng 
557*799e125cSJiandong Zheng 		/*
558*799e125cSJiandong Zheng 		 * These bits 20:18 (burstLen) of control register can be
559*799e125cSJiandong Zheng 		 * written but will take effect only if these bits are
560*799e125cSJiandong Zheng 		 * valid. So this will not affect previous versions
561*799e125cSJiandong Zheng 		 * of the DMA. They will continue to have those bits set to 0.
562*799e125cSJiandong Zheng 		 */
563*799e125cSJiandong Zheng 		control &= ~D64_RC_BL_MASK;
564*799e125cSJiandong Zheng 		/* Keep default Rx burstlen */
565*799e125cSJiandong Zheng 		control |= readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK;
566*799e125cSJiandong Zheng 		control |= HWRXOFF << D64_RC_RO_SHIFT;
567*799e125cSJiandong Zheng 
568*799e125cSJiandong Zheng 		writel(control, GMAC0_DMA_RX_CTRL_ADDR);
569*799e125cSJiandong Zheng 
570*799e125cSJiandong Zheng 		/*
571*799e125cSJiandong Zheng 		 * the rx descriptor ring should have
572*799e125cSJiandong Zheng 		 * the addresses set properly;
573*799e125cSJiandong Zheng 		 * set the lastdscr for the rx ring
574*799e125cSJiandong Zheng 		 */
575*799e125cSJiandong Zheng 		writel(((uint32_t)(dma->rx_desc_aligned) +
576*799e125cSJiandong Zheng 			(RX_BUF_NUM - 1) * RX_BUF_SIZE) &
577*799e125cSJiandong Zheng 		       D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
578*799e125cSJiandong Zheng 	}
579*799e125cSJiandong Zheng 
580*799e125cSJiandong Zheng 	return 0;
581*799e125cSJiandong Zheng }
582*799e125cSJiandong Zheng 
583*799e125cSJiandong Zheng bool gmac_mii_busywait(unsigned int timeout)
584*799e125cSJiandong Zheng {
585*799e125cSJiandong Zheng 	uint32_t tmp = 0;
586*799e125cSJiandong Zheng 
587*799e125cSJiandong Zheng 	while (timeout > 10) {
588*799e125cSJiandong Zheng 		tmp = readl(GMAC_MII_CTRL_ADDR);
589*799e125cSJiandong Zheng 		if (tmp & (1 << GMAC_MII_BUSY_SHIFT)) {
590*799e125cSJiandong Zheng 			udelay(10);
591*799e125cSJiandong Zheng 			timeout -= 10;
592*799e125cSJiandong Zheng 		} else {
593*799e125cSJiandong Zheng 			break;
594*799e125cSJiandong Zheng 		}
595*799e125cSJiandong Zheng 	}
596*799e125cSJiandong Zheng 	return tmp & (1 << GMAC_MII_BUSY_SHIFT);
597*799e125cSJiandong Zheng }
598*799e125cSJiandong Zheng 
599*799e125cSJiandong Zheng int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
600*799e125cSJiandong Zheng 			unsigned char reg, unsigned short *value)
601*799e125cSJiandong Zheng {
602*799e125cSJiandong Zheng 	uint32_t tmp = 0;
603*799e125cSJiandong Zheng 
604*799e125cSJiandong Zheng 	(void)devname;
605*799e125cSJiandong Zheng 
606*799e125cSJiandong Zheng 	/* Busy wait timeout is 1ms */
607*799e125cSJiandong Zheng 	if (gmac_mii_busywait(1000)) {
608*799e125cSJiandong Zheng 		error("%s: Prepare MII read: MII/MDIO busy\n", __func__);
609*799e125cSJiandong Zheng 		return -1;
610*799e125cSJiandong Zheng 	}
611*799e125cSJiandong Zheng 
612*799e125cSJiandong Zheng 	/* Read operation */
613*799e125cSJiandong Zheng 	tmp = GMAC_MII_DATA_READ_CMD;
614*799e125cSJiandong Zheng 	tmp |= (phyaddr << GMAC_MII_PHY_ADDR_SHIFT) |
615*799e125cSJiandong Zheng 		(reg << GMAC_MII_PHY_REG_SHIFT);
616*799e125cSJiandong Zheng 	debug("MII read cmd 0x%x, phy 0x%x, reg 0x%x\n", tmp, phyaddr, reg);
617*799e125cSJiandong Zheng 	writel(tmp, GMAC_MII_DATA_ADDR);
618*799e125cSJiandong Zheng 
619*799e125cSJiandong Zheng 	if (gmac_mii_busywait(1000)) {
620*799e125cSJiandong Zheng 		error("%s: MII read failure: MII/MDIO busy\n", __func__);
621*799e125cSJiandong Zheng 		return -1;
622*799e125cSJiandong Zheng 	}
623*799e125cSJiandong Zheng 
624*799e125cSJiandong Zheng 	*value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
625*799e125cSJiandong Zheng 	debug("MII read data 0x%x\n", *value);
626*799e125cSJiandong Zheng 	return 0;
627*799e125cSJiandong Zheng }
628*799e125cSJiandong Zheng 
629*799e125cSJiandong Zheng int gmac_miiphy_write(const char *devname, unsigned char phyaddr,
630*799e125cSJiandong Zheng 			 unsigned char reg, unsigned short value)
631*799e125cSJiandong Zheng {
632*799e125cSJiandong Zheng 	uint32_t tmp = 0;
633*799e125cSJiandong Zheng 
634*799e125cSJiandong Zheng 	(void)devname;
635*799e125cSJiandong Zheng 
636*799e125cSJiandong Zheng 	/* Busy wait timeout is 1ms */
637*799e125cSJiandong Zheng 	if (gmac_mii_busywait(1000)) {
638*799e125cSJiandong Zheng 		error("%s: Prepare MII write: MII/MDIO busy\n", __func__);
639*799e125cSJiandong Zheng 		return -1;
640*799e125cSJiandong Zheng 	}
641*799e125cSJiandong Zheng 
642*799e125cSJiandong Zheng 	/* Write operation */
643*799e125cSJiandong Zheng 	tmp = GMAC_MII_DATA_WRITE_CMD | (value & 0xffff);
644*799e125cSJiandong Zheng 	tmp |= ((phyaddr << GMAC_MII_PHY_ADDR_SHIFT) |
645*799e125cSJiandong Zheng 		(reg << GMAC_MII_PHY_REG_SHIFT));
646*799e125cSJiandong Zheng 	debug("MII write cmd 0x%x, phy 0x%x, reg 0x%x, data 0x%x\n",
647*799e125cSJiandong Zheng 	      tmp, phyaddr, reg, value);
648*799e125cSJiandong Zheng 	writel(tmp, GMAC_MII_DATA_ADDR);
649*799e125cSJiandong Zheng 
650*799e125cSJiandong Zheng 	if (gmac_mii_busywait(1000)) {
651*799e125cSJiandong Zheng 		error("%s: MII write failure: MII/MDIO busy\n", __func__);
652*799e125cSJiandong Zheng 		return -1;
653*799e125cSJiandong Zheng 	}
654*799e125cSJiandong Zheng 
655*799e125cSJiandong Zheng 	return 0;
656*799e125cSJiandong Zheng }
657*799e125cSJiandong Zheng 
658*799e125cSJiandong Zheng void gmac_init_reset(void)
659*799e125cSJiandong Zheng {
660*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
661*799e125cSJiandong Zheng 
662*799e125cSJiandong Zheng 	/* set command config reg CC_SR */
663*799e125cSJiandong Zheng 	reg32_set_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR);
664*799e125cSJiandong Zheng 	udelay(GMAC_RESET_DELAY);
665*799e125cSJiandong Zheng }
666*799e125cSJiandong Zheng 
667*799e125cSJiandong Zheng void gmac_clear_reset(void)
668*799e125cSJiandong Zheng {
669*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
670*799e125cSJiandong Zheng 
671*799e125cSJiandong Zheng 	/* clear command config reg CC_SR */
672*799e125cSJiandong Zheng 	reg32_clear_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR);
673*799e125cSJiandong Zheng 	udelay(GMAC_RESET_DELAY);
674*799e125cSJiandong Zheng }
675*799e125cSJiandong Zheng 
676*799e125cSJiandong Zheng static void gmac_enable_local(bool en)
677*799e125cSJiandong Zheng {
678*799e125cSJiandong Zheng 	uint32_t cmdcfg;
679*799e125cSJiandong Zheng 
680*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
681*799e125cSJiandong Zheng 
682*799e125cSJiandong Zheng 	/* read command config reg */
683*799e125cSJiandong Zheng 	cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR);
684*799e125cSJiandong Zheng 
685*799e125cSJiandong Zheng 	/* put mac in reset */
686*799e125cSJiandong Zheng 	gmac_init_reset();
687*799e125cSJiandong Zheng 
688*799e125cSJiandong Zheng 	cmdcfg |= CC_SR;
689*799e125cSJiandong Zheng 
690*799e125cSJiandong Zheng 	/* first deassert rx_ena and tx_ena while in reset */
691*799e125cSJiandong Zheng 	cmdcfg &= ~(CC_RE | CC_TE);
692*799e125cSJiandong Zheng 	/* write command config reg */
693*799e125cSJiandong Zheng 	writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR);
694*799e125cSJiandong Zheng 
695*799e125cSJiandong Zheng 	/* bring mac out of reset */
696*799e125cSJiandong Zheng 	gmac_clear_reset();
697*799e125cSJiandong Zheng 
698*799e125cSJiandong Zheng 	/* if not enable exit now */
699*799e125cSJiandong Zheng 	if (!en)
700*799e125cSJiandong Zheng 		return;
701*799e125cSJiandong Zheng 
702*799e125cSJiandong Zheng 	/* enable the mac transmit and receive paths now */
703*799e125cSJiandong Zheng 	udelay(2);
704*799e125cSJiandong Zheng 	cmdcfg &= ~CC_SR;
705*799e125cSJiandong Zheng 	cmdcfg |= (CC_RE | CC_TE);
706*799e125cSJiandong Zheng 
707*799e125cSJiandong Zheng 	/* assert rx_ena and tx_ena when out of reset to enable the mac */
708*799e125cSJiandong Zheng 	writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR);
709*799e125cSJiandong Zheng 
710*799e125cSJiandong Zheng 	return;
711*799e125cSJiandong Zheng }
712*799e125cSJiandong Zheng 
713*799e125cSJiandong Zheng int gmac_enable(void)
714*799e125cSJiandong Zheng {
715*799e125cSJiandong Zheng 	gmac_enable_local(1);
716*799e125cSJiandong Zheng 
717*799e125cSJiandong Zheng 	/* clear interrupts */
718*799e125cSJiandong Zheng 	writel(I_INTMASK, GMAC0_INT_STATUS_ADDR);
719*799e125cSJiandong Zheng 	return 0;
720*799e125cSJiandong Zheng }
721*799e125cSJiandong Zheng 
722*799e125cSJiandong Zheng int gmac_disable(void)
723*799e125cSJiandong Zheng {
724*799e125cSJiandong Zheng 	gmac_enable_local(0);
725*799e125cSJiandong Zheng 	return 0;
726*799e125cSJiandong Zheng }
727*799e125cSJiandong Zheng 
728*799e125cSJiandong Zheng int gmac_set_speed(int speed, int duplex)
729*799e125cSJiandong Zheng {
730*799e125cSJiandong Zheng 	uint32_t cmdcfg;
731*799e125cSJiandong Zheng 	uint32_t hd_ena;
732*799e125cSJiandong Zheng 	uint32_t speed_cfg;
733*799e125cSJiandong Zheng 
734*799e125cSJiandong Zheng 	hd_ena = duplex ? 0 : CC_HD;
735*799e125cSJiandong Zheng 	if (speed == 1000) {
736*799e125cSJiandong Zheng 		speed_cfg = 2;
737*799e125cSJiandong Zheng 	} else if (speed == 100) {
738*799e125cSJiandong Zheng 		speed_cfg = 1;
739*799e125cSJiandong Zheng 	} else if (speed == 10) {
740*799e125cSJiandong Zheng 		speed_cfg = 0;
741*799e125cSJiandong Zheng 	} else {
742*799e125cSJiandong Zheng 		error("%s: Invalid GMAC speed(%d)!\n", __func__, speed);
743*799e125cSJiandong Zheng 		return -1;
744*799e125cSJiandong Zheng 	}
745*799e125cSJiandong Zheng 
746*799e125cSJiandong Zheng 	cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR);
747*799e125cSJiandong Zheng 	cmdcfg &= ~(CC_ES_MASK | CC_HD);
748*799e125cSJiandong Zheng 	cmdcfg |= ((speed_cfg << CC_ES_SHIFT) | hd_ena);
749*799e125cSJiandong Zheng 
750*799e125cSJiandong Zheng 	printf("Change GMAC speed to %dMB\n", speed);
751*799e125cSJiandong Zheng 	debug("GMAC speed cfg 0x%x\n", cmdcfg);
752*799e125cSJiandong Zheng 	writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR);
753*799e125cSJiandong Zheng 
754*799e125cSJiandong Zheng 	return 0;
755*799e125cSJiandong Zheng }
756*799e125cSJiandong Zheng 
757*799e125cSJiandong Zheng int gmac_set_mac_addr(unsigned char *mac)
758*799e125cSJiandong Zheng {
759*799e125cSJiandong Zheng 	/* set our local address */
760*799e125cSJiandong Zheng 	debug("GMAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
761*799e125cSJiandong Zheng 	      mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
762*799e125cSJiandong Zheng 	writel(htonl(*(uint32_t *)mac), UNIMAC0_MAC_MSB_ADDR);
763*799e125cSJiandong Zheng 	writew(htons(*(uint32_t *)&mac[4]), UNIMAC0_MAC_LSB_ADDR);
764*799e125cSJiandong Zheng 
765*799e125cSJiandong Zheng 	return 0;
766*799e125cSJiandong Zheng }
767*799e125cSJiandong Zheng 
768*799e125cSJiandong Zheng int gmac_mac_init(struct eth_device *dev)
769*799e125cSJiandong Zheng {
770*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
771*799e125cSJiandong Zheng 	struct eth_dma *dma = &(eth->dma);
772*799e125cSJiandong Zheng 
773*799e125cSJiandong Zheng 	uint32_t tmp;
774*799e125cSJiandong Zheng 	uint32_t cmdcfg;
775*799e125cSJiandong Zheng 	int chipid;
776*799e125cSJiandong Zheng 
777*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
778*799e125cSJiandong Zheng 
779*799e125cSJiandong Zheng 	/* Always use GMAC0 */
780*799e125cSJiandong Zheng 	printf("Using GMAC%d\n", 0);
781*799e125cSJiandong Zheng 
782*799e125cSJiandong Zheng 	/* Reset AMAC0 core */
783*799e125cSJiandong Zheng 	writel(0, AMAC0_IDM_RESET_ADDR);
784*799e125cSJiandong Zheng 	tmp = readl(AMAC0_IO_CTRL_DIRECT_ADDR);
785*799e125cSJiandong Zheng 	/* Set clock */
786*799e125cSJiandong Zheng 	tmp &= ~(1 << AMAC0_IO_CTRL_CLK_250_SEL_SHIFT);
787*799e125cSJiandong Zheng 	tmp |= (1 << AMAC0_IO_CTRL_GMII_MODE_SHIFT);
788*799e125cSJiandong Zheng 	/* Set Tx clock */
789*799e125cSJiandong Zheng 	tmp &= ~(1 << AMAC0_IO_CTRL_DEST_SYNC_MODE_EN_SHIFT);
790*799e125cSJiandong Zheng 	writel(tmp, AMAC0_IO_CTRL_DIRECT_ADDR);
791*799e125cSJiandong Zheng 
792*799e125cSJiandong Zheng 	/* reset gmac */
793*799e125cSJiandong Zheng 	/*
794*799e125cSJiandong Zheng 	 * As AMAC is just reset, NO need?
795*799e125cSJiandong Zheng 	 * set eth_data into loopback mode to ensure no rx traffic
796*799e125cSJiandong Zheng 	 * gmac_loopback(eth_data, TRUE);
797*799e125cSJiandong Zheng 	 * ET_TRACE(("%s gmac loopback\n", __func__));
798*799e125cSJiandong Zheng 	 * udelay(1);
799*799e125cSJiandong Zheng 	 */
800*799e125cSJiandong Zheng 
801*799e125cSJiandong Zheng 	cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR);
802*799e125cSJiandong Zheng 	cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML |
803*799e125cSJiandong Zheng 		    CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI |
804*799e125cSJiandong Zheng 		    CC_PAD_EN | CC_PF);
805*799e125cSJiandong Zheng 	cmdcfg |= (CC_PROM | CC_NLC | CC_CFE);
806*799e125cSJiandong Zheng 	/* put mac in reset */
807*799e125cSJiandong Zheng 	gmac_init_reset();
808*799e125cSJiandong Zheng 	writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR);
809*799e125cSJiandong Zheng 	gmac_clear_reset();
810*799e125cSJiandong Zheng 
811*799e125cSJiandong Zheng 	/* enable clear MIB on read */
812*799e125cSJiandong Zheng 	reg32_set_bits(GMAC0_DEV_CTRL_ADDR, DC_MROR);
813*799e125cSJiandong Zheng 	/* PHY: set smi_master to drive mdc_clk */
814*799e125cSJiandong Zheng 	reg32_set_bits(GMAC0_PHY_CTRL_ADDR, PC_MTE);
815*799e125cSJiandong Zheng 
816*799e125cSJiandong Zheng 	/* clear persistent sw intstatus */
817*799e125cSJiandong Zheng 	writel(0, GMAC0_INT_STATUS_ADDR);
818*799e125cSJiandong Zheng 
819*799e125cSJiandong Zheng 	if (dma_init(dma) < 0) {
820*799e125cSJiandong Zheng 		error("%s: GMAC dma_init failed\n", __func__);
821*799e125cSJiandong Zheng 		goto err_exit;
822*799e125cSJiandong Zheng 	}
823*799e125cSJiandong Zheng 
824*799e125cSJiandong Zheng 	chipid = CHIPID;
825*799e125cSJiandong Zheng 	printf("%s: Chip ID: 0x%x\n", __func__, chipid);
826*799e125cSJiandong Zheng 
827*799e125cSJiandong Zheng 	/* set switch bypass mode */
828*799e125cSJiandong Zheng 	tmp = readl(SWITCH_GLOBAL_CONFIG_ADDR);
829*799e125cSJiandong Zheng 	tmp |= (1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT);
830*799e125cSJiandong Zheng 
831*799e125cSJiandong Zheng 	/* Switch mode */
832*799e125cSJiandong Zheng 	/* tmp &= ~(1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); */
833*799e125cSJiandong Zheng 
834*799e125cSJiandong Zheng 	writel(tmp, SWITCH_GLOBAL_CONFIG_ADDR);
835*799e125cSJiandong Zheng 
836*799e125cSJiandong Zheng 	tmp = readl(CRMU_CHIP_IO_PAD_CONTROL_ADDR);
837*799e125cSJiandong Zheng 	tmp &= ~(1 << CDRU_IOMUX_FORCE_PAD_IN_SHIFT);
838*799e125cSJiandong Zheng 	writel(tmp, CRMU_CHIP_IO_PAD_CONTROL_ADDR);
839*799e125cSJiandong Zheng 
840*799e125cSJiandong Zheng 	/* Set MDIO to internal GPHY */
841*799e125cSJiandong Zheng 	tmp = readl(GMAC_MII_CTRL_ADDR);
842*799e125cSJiandong Zheng 	/* Select internal MDC/MDIO bus*/
843*799e125cSJiandong Zheng 	tmp &= ~(1 << GMAC_MII_CTRL_BYP_SHIFT);
844*799e125cSJiandong Zheng 	/* select MDC/MDIO connecting to on-chip internal PHYs */
845*799e125cSJiandong Zheng 	tmp &= ~(1 << GMAC_MII_CTRL_EXT_SHIFT);
846*799e125cSJiandong Zheng 	/*
847*799e125cSJiandong Zheng 	 * give bit[6:0](MDCDIV) with required divisor to set
848*799e125cSJiandong Zheng 	 * the MDC clock frequency, 66MHZ/0x1A=2.5MHZ
849*799e125cSJiandong Zheng 	 */
850*799e125cSJiandong Zheng 	tmp |= 0x1A;
851*799e125cSJiandong Zheng 
852*799e125cSJiandong Zheng 	writel(tmp, GMAC_MII_CTRL_ADDR);
853*799e125cSJiandong Zheng 
854*799e125cSJiandong Zheng 	if (gmac_mii_busywait(1000)) {
855*799e125cSJiandong Zheng 		error("%s: Configure MDIO: MII/MDIO busy\n", __func__);
856*799e125cSJiandong Zheng 		goto err_exit;
857*799e125cSJiandong Zheng 	}
858*799e125cSJiandong Zheng 
859*799e125cSJiandong Zheng 	/* Configure GMAC0 */
860*799e125cSJiandong Zheng 	/* enable one rx interrupt per received frame */
861*799e125cSJiandong Zheng 	writel(1 << GMAC0_IRL_FRAMECOUNT_SHIFT, GMAC0_INTR_RECV_LAZY_ADDR);
862*799e125cSJiandong Zheng 
863*799e125cSJiandong Zheng 	/* read command config reg */
864*799e125cSJiandong Zheng 	cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR);
865*799e125cSJiandong Zheng 	/* enable 802.3x tx flow control (honor received PAUSE frames) */
866*799e125cSJiandong Zheng 	cmdcfg &= ~CC_RPI;
867*799e125cSJiandong Zheng 	/* enable promiscuous mode */
868*799e125cSJiandong Zheng 	cmdcfg |= CC_PROM;
869*799e125cSJiandong Zheng 	/* Disable loopback mode */
870*799e125cSJiandong Zheng 	cmdcfg &= ~CC_ML;
871*799e125cSJiandong Zheng 	/* set the speed */
872*799e125cSJiandong Zheng 	cmdcfg &= ~(CC_ES_MASK | CC_HD);
873*799e125cSJiandong Zheng 	/* Set to 1Gbps and full duplex by default */
874*799e125cSJiandong Zheng 	cmdcfg |= (2 << CC_ES_SHIFT);
875*799e125cSJiandong Zheng 
876*799e125cSJiandong Zheng 	/* put mac in reset */
877*799e125cSJiandong Zheng 	gmac_init_reset();
878*799e125cSJiandong Zheng 	/* write register */
879*799e125cSJiandong Zheng 	writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR);
880*799e125cSJiandong Zheng 	/* bring mac out of reset */
881*799e125cSJiandong Zheng 	gmac_clear_reset();
882*799e125cSJiandong Zheng 
883*799e125cSJiandong Zheng 	/* set max frame lengths; account for possible vlan tag */
884*799e125cSJiandong Zheng 	writel(PKTSIZE + 32, UNIMAC0_FRM_LENGTH_ADDR);
885*799e125cSJiandong Zheng 
886*799e125cSJiandong Zheng 	return 0;
887*799e125cSJiandong Zheng 
888*799e125cSJiandong Zheng err_exit:
889*799e125cSJiandong Zheng 	dma_deinit(dma);
890*799e125cSJiandong Zheng 	return -1;
891*799e125cSJiandong Zheng }
892*799e125cSJiandong Zheng 
893*799e125cSJiandong Zheng int gmac_add(struct eth_device *dev)
894*799e125cSJiandong Zheng {
895*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
896*799e125cSJiandong Zheng 	struct eth_dma *dma = &(eth->dma);
897*799e125cSJiandong Zheng 	void *tmp;
898*799e125cSJiandong Zheng 
899*799e125cSJiandong Zheng 	/*
900*799e125cSJiandong Zheng 	 * Desc has to be 16-byte aligned ?
901*799e125cSJiandong Zheng 	 * If it is 8-byte aligned by malloc, fail Tx
902*799e125cSJiandong Zheng 	 */
903*799e125cSJiandong Zheng 	tmp = malloc(sizeof(dma64dd_t) * TX_BUF_NUM + 8);
904*799e125cSJiandong Zheng 	if (tmp == NULL) {
905*799e125cSJiandong Zheng 		printf("%s: Failed to allocate TX desc Buffer\n", __func__);
906*799e125cSJiandong Zheng 		return -1;
907*799e125cSJiandong Zheng 	}
908*799e125cSJiandong Zheng 
909*799e125cSJiandong Zheng 	dma->tx_desc = (void *)tmp;
910*799e125cSJiandong Zheng 	dma->tx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
911*799e125cSJiandong Zheng 	debug("TX Descriptor Buffer: %p; length: 0x%x\n",
912*799e125cSJiandong Zheng 	      dma->tx_desc_aligned, sizeof(dma64dd_t) * TX_BUF_NUM);
913*799e125cSJiandong Zheng 
914*799e125cSJiandong Zheng 	tmp = malloc(TX_BUF_SIZE * TX_BUF_NUM);
915*799e125cSJiandong Zheng 	if (tmp == NULL) {
916*799e125cSJiandong Zheng 		printf("%s: Failed to allocate TX Data Buffer\n", __func__);
917*799e125cSJiandong Zheng 		free(dma->tx_desc);
918*799e125cSJiandong Zheng 		return -1;
919*799e125cSJiandong Zheng 	}
920*799e125cSJiandong Zheng 	dma->tx_buf = (uint8_t *)tmp;
921*799e125cSJiandong Zheng 	debug("TX Data Buffer: %p; length: 0x%x\n",
922*799e125cSJiandong Zheng 	      dma->tx_buf, TX_BUF_SIZE * TX_BUF_NUM);
923*799e125cSJiandong Zheng 
924*799e125cSJiandong Zheng 	/* Desc has to be 16-byte aligned ? */
925*799e125cSJiandong Zheng 	tmp = malloc(sizeof(dma64dd_t) * RX_BUF_NUM + 8);
926*799e125cSJiandong Zheng 	if (tmp == NULL) {
927*799e125cSJiandong Zheng 		printf("%s: Failed to allocate RX Descriptor\n", __func__);
928*799e125cSJiandong Zheng 		free(dma->tx_desc);
929*799e125cSJiandong Zheng 		free(dma->tx_buf);
930*799e125cSJiandong Zheng 		return -1;
931*799e125cSJiandong Zheng 	}
932*799e125cSJiandong Zheng 	dma->rx_desc = tmp;
933*799e125cSJiandong Zheng 	dma->rx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
934*799e125cSJiandong Zheng 	debug("RX Descriptor Buffer: %p, length: 0x%x\n",
935*799e125cSJiandong Zheng 	      dma->rx_desc_aligned, sizeof(dma64dd_t) * RX_BUF_NUM);
936*799e125cSJiandong Zheng 
937*799e125cSJiandong Zheng 	tmp = malloc(RX_BUF_SIZE * RX_BUF_NUM);
938*799e125cSJiandong Zheng 	if (tmp == NULL) {
939*799e125cSJiandong Zheng 		printf("%s: Failed to allocate RX Data Buffer\n", __func__);
940*799e125cSJiandong Zheng 		free(dma->tx_desc);
941*799e125cSJiandong Zheng 		free(dma->tx_buf);
942*799e125cSJiandong Zheng 		free(dma->rx_desc);
943*799e125cSJiandong Zheng 		return -1;
944*799e125cSJiandong Zheng 	}
945*799e125cSJiandong Zheng 	dma->rx_buf = tmp;
946*799e125cSJiandong Zheng 	debug("RX Data Buffer: %p; length: 0x%x\n",
947*799e125cSJiandong Zheng 	      dma->rx_buf, RX_BUF_SIZE * RX_BUF_NUM);
948*799e125cSJiandong Zheng 
949*799e125cSJiandong Zheng 	g_dmactrlflags = 0;
950*799e125cSJiandong Zheng 
951*799e125cSJiandong Zheng 	eth->phy_interface = PHY_INTERFACE_MODE_GMII;
952*799e125cSJiandong Zheng 
953*799e125cSJiandong Zheng 	dma->tx_packet = gmac_tx_packet;
954*799e125cSJiandong Zheng 	dma->check_tx_done = gmac_check_tx_done;
955*799e125cSJiandong Zheng 
956*799e125cSJiandong Zheng 	dma->check_rx_done = gmac_check_rx_done;
957*799e125cSJiandong Zheng 
958*799e125cSJiandong Zheng 	dma->enable_dma = gmac_enable_dma;
959*799e125cSJiandong Zheng 	dma->disable_dma = gmac_disable_dma;
960*799e125cSJiandong Zheng 
961*799e125cSJiandong Zheng 	eth->miiphy_read = gmac_miiphy_read;
962*799e125cSJiandong Zheng 	eth->miiphy_write = gmac_miiphy_write;
963*799e125cSJiandong Zheng 
964*799e125cSJiandong Zheng 	eth->mac_init = gmac_mac_init;
965*799e125cSJiandong Zheng 	eth->disable_mac = gmac_disable;
966*799e125cSJiandong Zheng 	eth->enable_mac = gmac_enable;
967*799e125cSJiandong Zheng 	eth->set_mac_addr = gmac_set_mac_addr;
968*799e125cSJiandong Zheng 	eth->set_mac_speed = gmac_set_speed;
969*799e125cSJiandong Zheng 
970*799e125cSJiandong Zheng 	return 0;
971*799e125cSJiandong Zheng }
972