xref: /rk3399_rockchip-uboot/drivers/net/sunxi_emac.c (revision b70ed300b0dcf23e46265904ddc4fbf9a72b99b8)
1*b70ed300SStefan Roese /*
2*b70ed300SStefan Roese  * sunxi_emac.c -- Allwinner A10 ethernet driver
3*b70ed300SStefan Roese  *
4*b70ed300SStefan Roese  * (C) Copyright 2012, Stefan Roese <sr@denx.de>
5*b70ed300SStefan Roese  *
6*b70ed300SStefan Roese  * SPDX-License-Identifier:	GPL-2.0+
7*b70ed300SStefan Roese  */
8*b70ed300SStefan Roese 
9*b70ed300SStefan Roese #include <common.h>
10*b70ed300SStefan Roese #include <linux/err.h>
11*b70ed300SStefan Roese #include <malloc.h>
12*b70ed300SStefan Roese #include <miiphy.h>
13*b70ed300SStefan Roese #include <net.h>
14*b70ed300SStefan Roese #include <asm/io.h>
15*b70ed300SStefan Roese #include <asm/arch/clock.h>
16*b70ed300SStefan Roese #include <asm/arch/gpio.h>
17*b70ed300SStefan Roese 
18*b70ed300SStefan Roese /* EMAC register  */
19*b70ed300SStefan Roese struct emac_regs {
20*b70ed300SStefan Roese 	u32 ctl;	/* 0x00 */
21*b70ed300SStefan Roese 	u32 tx_mode;	/* 0x04 */
22*b70ed300SStefan Roese 	u32 tx_flow;	/* 0x08 */
23*b70ed300SStefan Roese 	u32 tx_ctl0;	/* 0x0c */
24*b70ed300SStefan Roese 	u32 tx_ctl1;	/* 0x10 */
25*b70ed300SStefan Roese 	u32 tx_ins;	/* 0x14 */
26*b70ed300SStefan Roese 	u32 tx_pl0;	/* 0x18 */
27*b70ed300SStefan Roese 	u32 tx_pl1;	/* 0x1c */
28*b70ed300SStefan Roese 	u32 tx_sta;	/* 0x20 */
29*b70ed300SStefan Roese 	u32 tx_io_data;	/* 0x24 */
30*b70ed300SStefan Roese 	u32 tx_io_data1;/* 0x28 */
31*b70ed300SStefan Roese 	u32 tx_tsvl0;	/* 0x2c */
32*b70ed300SStefan Roese 	u32 tx_tsvh0;	/* 0x30 */
33*b70ed300SStefan Roese 	u32 tx_tsvl1;	/* 0x34 */
34*b70ed300SStefan Roese 	u32 tx_tsvh1;	/* 0x38 */
35*b70ed300SStefan Roese 	u32 rx_ctl;	/* 0x3c */
36*b70ed300SStefan Roese 	u32 rx_hash0;	/* 0x40 */
37*b70ed300SStefan Roese 	u32 rx_hash1;	/* 0x44 */
38*b70ed300SStefan Roese 	u32 rx_sta;	/* 0x48 */
39*b70ed300SStefan Roese 	u32 rx_io_data;	/* 0x4c */
40*b70ed300SStefan Roese 	u32 rx_fbc;	/* 0x50 */
41*b70ed300SStefan Roese 	u32 int_ctl;	/* 0x54 */
42*b70ed300SStefan Roese 	u32 int_sta;	/* 0x58 */
43*b70ed300SStefan Roese 	u32 mac_ctl0;	/* 0x5c */
44*b70ed300SStefan Roese 	u32 mac_ctl1;	/* 0x60 */
45*b70ed300SStefan Roese 	u32 mac_ipgt;	/* 0x64 */
46*b70ed300SStefan Roese 	u32 mac_ipgr;	/* 0x68 */
47*b70ed300SStefan Roese 	u32 mac_clrt;	/* 0x6c */
48*b70ed300SStefan Roese 	u32 mac_maxf;	/* 0x70 */
49*b70ed300SStefan Roese 	u32 mac_supp;	/* 0x74 */
50*b70ed300SStefan Roese 	u32 mac_test;	/* 0x78 */
51*b70ed300SStefan Roese 	u32 mac_mcfg;	/* 0x7c */
52*b70ed300SStefan Roese 	u32 mac_mcmd;	/* 0x80 */
53*b70ed300SStefan Roese 	u32 mac_madr;	/* 0x84 */
54*b70ed300SStefan Roese 	u32 mac_mwtd;	/* 0x88 */
55*b70ed300SStefan Roese 	u32 mac_mrdd;	/* 0x8c */
56*b70ed300SStefan Roese 	u32 mac_mind;	/* 0x90 */
57*b70ed300SStefan Roese 	u32 mac_ssrr;	/* 0x94 */
58*b70ed300SStefan Roese 	u32 mac_a0;	/* 0x98 */
59*b70ed300SStefan Roese 	u32 mac_a1;	/* 0x9c */
60*b70ed300SStefan Roese };
61*b70ed300SStefan Roese 
62*b70ed300SStefan Roese /* SRAMC register  */
63*b70ed300SStefan Roese struct sunxi_sramc_regs {
64*b70ed300SStefan Roese 	u32 ctrl0;
65*b70ed300SStefan Roese 	u32 ctrl1;
66*b70ed300SStefan Roese };
67*b70ed300SStefan Roese 
68*b70ed300SStefan Roese /* 0: Disable       1: Aborted frame enable(default) */
69*b70ed300SStefan Roese #define EMAC_TX_AB_M		(0x1 << 0)
70*b70ed300SStefan Roese /* 0: CPU           1: DMA(default) */
71*b70ed300SStefan Roese #define EMAC_TX_TM		(0x1 << 1)
72*b70ed300SStefan Roese 
73*b70ed300SStefan Roese #define EMAC_TX_SETUP		(0)
74*b70ed300SStefan Roese 
75*b70ed300SStefan Roese /* 0: DRQ asserted  1: DRQ automatically(default) */
76*b70ed300SStefan Roese #define EMAC_RX_DRQ_MODE	(0x1 << 1)
77*b70ed300SStefan Roese /* 0: CPU           1: DMA(default) */
78*b70ed300SStefan Roese #define EMAC_RX_TM		(0x1 << 2)
79*b70ed300SStefan Roese /* 0: Normal(default)        1: Pass all Frames */
80*b70ed300SStefan Roese #define EMAC_RX_PA		(0x1 << 4)
81*b70ed300SStefan Roese /* 0: Normal(default)        1: Pass Control Frames */
82*b70ed300SStefan Roese #define EMAC_RX_PCF		(0x1 << 5)
83*b70ed300SStefan Roese /* 0: Normal(default)        1: Pass Frames with CRC Error */
84*b70ed300SStefan Roese #define EMAC_RX_PCRCE		(0x1 << 6)
85*b70ed300SStefan Roese /* 0: Normal(default)        1: Pass Frames with Length Error */
86*b70ed300SStefan Roese #define EMAC_RX_PLE		(0x1 << 7)
87*b70ed300SStefan Roese /* 0: Normal                 1: Pass Frames length out of range(default) */
88*b70ed300SStefan Roese #define EMAC_RX_POR		(0x1 << 8)
89*b70ed300SStefan Roese /* 0: Not accept             1: Accept unicast Packets(default) */
90*b70ed300SStefan Roese #define EMAC_RX_UCAD		(0x1 << 16)
91*b70ed300SStefan Roese /* 0: Normal(default)        1: DA Filtering */
92*b70ed300SStefan Roese #define EMAC_RX_DAF		(0x1 << 17)
93*b70ed300SStefan Roese /* 0: Not accept             1: Accept multicast Packets(default) */
94*b70ed300SStefan Roese #define EMAC_RX_MCO		(0x1 << 20)
95*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable Hash filter */
96*b70ed300SStefan Roese #define EMAC_RX_MHF		(0x1 << 21)
97*b70ed300SStefan Roese /* 0: Not accept             1: Accept Broadcast Packets(default) */
98*b70ed300SStefan Roese #define EMAC_RX_BCO		(0x1 << 22)
99*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable SA Filtering */
100*b70ed300SStefan Roese #define EMAC_RX_SAF		(0x1 << 24)
101*b70ed300SStefan Roese /* 0: Normal(default)        1: Inverse Filtering */
102*b70ed300SStefan Roese #define EMAC_RX_SAIF		(0x1 << 25)
103*b70ed300SStefan Roese 
104*b70ed300SStefan Roese #define EMAC_RX_SETUP		(EMAC_RX_POR | EMAC_RX_UCAD | EMAC_RX_DAF | \
105*b70ed300SStefan Roese 				 EMAC_RX_MCO | EMAC_RX_BCO)
106*b70ed300SStefan Roese 
107*b70ed300SStefan Roese /* 0: Disable                1: Enable Receive Flow Control(default) */
108*b70ed300SStefan Roese #define EMAC_MAC_CTL0_RFC	(0x1 << 2)
109*b70ed300SStefan Roese /* 0: Disable                1: Enable Transmit Flow Control(default) */
110*b70ed300SStefan Roese #define EMAC_MAC_CTL0_TFC	(0x1 << 3)
111*b70ed300SStefan Roese 
112*b70ed300SStefan Roese #define EMAC_MAC_CTL0_SETUP	(EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
113*b70ed300SStefan Roese 
114*b70ed300SStefan Roese /* 0: Disable                1: Enable MAC Frame Length Checking(default) */
115*b70ed300SStefan Roese #define EMAC_MAC_CTL1_FLC	(0x1 << 1)
116*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable Huge Frame */
117*b70ed300SStefan Roese #define EMAC_MAC_CTL1_HF	(0x1 << 2)
118*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable MAC Delayed CRC */
119*b70ed300SStefan Roese #define EMAC_MAC_CTL1_DCRC	(0x1 << 3)
120*b70ed300SStefan Roese /* 0: Disable                1: Enable MAC CRC(default) */
121*b70ed300SStefan Roese #define EMAC_MAC_CTL1_CRC	(0x1 << 4)
122*b70ed300SStefan Roese /* 0: Disable                1: Enable MAC PAD Short frames(default) */
123*b70ed300SStefan Roese #define EMAC_MAC_CTL1_PC	(0x1 << 5)
124*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable MAC PAD Short frames and append CRC */
125*b70ed300SStefan Roese #define EMAC_MAC_CTL1_VC	(0x1 << 6)
126*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable MAC auto detect Short frames */
127*b70ed300SStefan Roese #define EMAC_MAC_CTL1_ADP	(0x1 << 7)
128*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable */
129*b70ed300SStefan Roese #define EMAC_MAC_CTL1_PRE	(0x1 << 8)
130*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable */
131*b70ed300SStefan Roese #define EMAC_MAC_CTL1_LPE	(0x1 << 9)
132*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable no back off */
133*b70ed300SStefan Roese #define EMAC_MAC_CTL1_NB	(0x1 << 12)
134*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable */
135*b70ed300SStefan Roese #define EMAC_MAC_CTL1_BNB	(0x1 << 13)
136*b70ed300SStefan Roese /* 0: Disable(default)       1: Enable */
137*b70ed300SStefan Roese #define EMAC_MAC_CTL1_ED	(0x1 << 14)
138*b70ed300SStefan Roese 
139*b70ed300SStefan Roese #define EMAC_MAC_CTL1_SETUP	(EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
140*b70ed300SStefan Roese 				 EMAC_MAC_CTL1_PC)
141*b70ed300SStefan Roese 
142*b70ed300SStefan Roese #define EMAC_MAC_IPGT		0x15
143*b70ed300SStefan Roese 
144*b70ed300SStefan Roese #define EMAC_MAC_NBTB_IPG1	0xc
145*b70ed300SStefan Roese #define EMAC_MAC_NBTB_IPG2	0x12
146*b70ed300SStefan Roese 
147*b70ed300SStefan Roese #define EMAC_MAC_CW		0x37
148*b70ed300SStefan Roese #define EMAC_MAC_RM		0xf
149*b70ed300SStefan Roese 
150*b70ed300SStefan Roese #define EMAC_MAC_MFL		0x0600
151*b70ed300SStefan Roese 
152*b70ed300SStefan Roese /* Receive status */
153*b70ed300SStefan Roese #define EMAC_CRCERR		(0x1 << 4)
154*b70ed300SStefan Roese #define EMAC_LENERR		(0x3 << 5)
155*b70ed300SStefan Roese 
156*b70ed300SStefan Roese #define DMA_CPU_TRRESHOLD	2000
157*b70ed300SStefan Roese 
158*b70ed300SStefan Roese struct emac_eth_dev {
159*b70ed300SStefan Roese 	u32 speed;
160*b70ed300SStefan Roese 	u32 duplex;
161*b70ed300SStefan Roese 	u32 phy_configured;
162*b70ed300SStefan Roese 	int link_printed;
163*b70ed300SStefan Roese };
164*b70ed300SStefan Roese 
165*b70ed300SStefan Roese struct emac_rxhdr {
166*b70ed300SStefan Roese 	s16 rx_len;
167*b70ed300SStefan Roese 	u16 rx_status;
168*b70ed300SStefan Roese };
169*b70ed300SStefan Roese 
170*b70ed300SStefan Roese static void emac_inblk_32bit(void *reg, void *data, int count)
171*b70ed300SStefan Roese {
172*b70ed300SStefan Roese 	int cnt = (count + 3) >> 2;
173*b70ed300SStefan Roese 
174*b70ed300SStefan Roese 	if (cnt) {
175*b70ed300SStefan Roese 		u32 *buf = data;
176*b70ed300SStefan Roese 
177*b70ed300SStefan Roese 		do {
178*b70ed300SStefan Roese 			u32 x = readl(reg);
179*b70ed300SStefan Roese 			*buf++ = x;
180*b70ed300SStefan Roese 		} while (--cnt);
181*b70ed300SStefan Roese 	}
182*b70ed300SStefan Roese }
183*b70ed300SStefan Roese 
184*b70ed300SStefan Roese static void emac_outblk_32bit(void *reg, void *data, int count)
185*b70ed300SStefan Roese {
186*b70ed300SStefan Roese 	int cnt = (count + 3) >> 2;
187*b70ed300SStefan Roese 
188*b70ed300SStefan Roese 	if (cnt) {
189*b70ed300SStefan Roese 		const u32 *buf = data;
190*b70ed300SStefan Roese 
191*b70ed300SStefan Roese 		do {
192*b70ed300SStefan Roese 			writel(*buf++, reg);
193*b70ed300SStefan Roese 		} while (--cnt);
194*b70ed300SStefan Roese 	}
195*b70ed300SStefan Roese }
196*b70ed300SStefan Roese 
197*b70ed300SStefan Roese /* Read a word from phyxcer */
198*b70ed300SStefan Roese static int emac_phy_read(const char *devname, unsigned char addr,
199*b70ed300SStefan Roese 			  unsigned char reg, unsigned short *value)
200*b70ed300SStefan Roese {
201*b70ed300SStefan Roese 	struct eth_device *dev = eth_get_dev_by_name(devname);
202*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
203*b70ed300SStefan Roese 
204*b70ed300SStefan Roese 	/* issue the phy address and reg */
205*b70ed300SStefan Roese 	writel(addr << 8 | reg, &regs->mac_madr);
206*b70ed300SStefan Roese 
207*b70ed300SStefan Roese 	/* pull up the phy io line */
208*b70ed300SStefan Roese 	writel(0x1, &regs->mac_mcmd);
209*b70ed300SStefan Roese 
210*b70ed300SStefan Roese 	/* Wait read complete */
211*b70ed300SStefan Roese 	mdelay(1);
212*b70ed300SStefan Roese 
213*b70ed300SStefan Roese 	/* push down the phy io line */
214*b70ed300SStefan Roese 	writel(0x0, &regs->mac_mcmd);
215*b70ed300SStefan Roese 
216*b70ed300SStefan Roese 	/* and write data */
217*b70ed300SStefan Roese 	*value = readl(&regs->mac_mrdd);
218*b70ed300SStefan Roese 
219*b70ed300SStefan Roese 	return 0;
220*b70ed300SStefan Roese }
221*b70ed300SStefan Roese 
222*b70ed300SStefan Roese /* Write a word to phyxcer */
223*b70ed300SStefan Roese static int emac_phy_write(const char *devname, unsigned char addr,
224*b70ed300SStefan Roese 			   unsigned char reg, unsigned short value)
225*b70ed300SStefan Roese {
226*b70ed300SStefan Roese 	struct eth_device *dev = eth_get_dev_by_name(devname);
227*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
228*b70ed300SStefan Roese 
229*b70ed300SStefan Roese 	/* issue the phy address and reg */
230*b70ed300SStefan Roese 	writel(addr << 8 | reg, &regs->mac_madr);
231*b70ed300SStefan Roese 
232*b70ed300SStefan Roese 	/* pull up the phy io line */
233*b70ed300SStefan Roese 	writel(0x1, &regs->mac_mcmd);
234*b70ed300SStefan Roese 
235*b70ed300SStefan Roese 	/* Wait write complete */
236*b70ed300SStefan Roese 	mdelay(1);
237*b70ed300SStefan Roese 
238*b70ed300SStefan Roese 	/* push down the phy io line */
239*b70ed300SStefan Roese 	writel(0x0, &regs->mac_mcmd);
240*b70ed300SStefan Roese 
241*b70ed300SStefan Roese 	/* and write data */
242*b70ed300SStefan Roese 	writel(value, &regs->mac_mwtd);
243*b70ed300SStefan Roese 
244*b70ed300SStefan Roese 	return 0;
245*b70ed300SStefan Roese }
246*b70ed300SStefan Roese 
247*b70ed300SStefan Roese static void emac_setup(struct eth_device *dev)
248*b70ed300SStefan Roese {
249*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
250*b70ed300SStefan Roese 	u32 reg_val;
251*b70ed300SStefan Roese 	u16 phy_val;
252*b70ed300SStefan Roese 	u32 duplex_flag;
253*b70ed300SStefan Roese 
254*b70ed300SStefan Roese 	/* Set up TX */
255*b70ed300SStefan Roese 	writel(EMAC_TX_SETUP, &regs->tx_mode);
256*b70ed300SStefan Roese 
257*b70ed300SStefan Roese 	/* Set up RX */
258*b70ed300SStefan Roese 	writel(EMAC_RX_SETUP, &regs->rx_ctl);
259*b70ed300SStefan Roese 
260*b70ed300SStefan Roese 	/* Set MAC */
261*b70ed300SStefan Roese 	/* Set MAC CTL0 */
262*b70ed300SStefan Roese 	writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
263*b70ed300SStefan Roese 
264*b70ed300SStefan Roese 	/* Set MAC CTL1 */
265*b70ed300SStefan Roese 	emac_phy_read(dev->name, 1, 0, &phy_val);
266*b70ed300SStefan Roese 	debug("PHY SETUP, reg 0 value: %x\n", phy_val);
267*b70ed300SStefan Roese 	duplex_flag = !!(phy_val & (1 << 8));
268*b70ed300SStefan Roese 
269*b70ed300SStefan Roese 	reg_val = 0;
270*b70ed300SStefan Roese 	if (duplex_flag)
271*b70ed300SStefan Roese 		reg_val = (0x1 << 0);
272*b70ed300SStefan Roese 	writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
273*b70ed300SStefan Roese 
274*b70ed300SStefan Roese 	/* Set up IPGT */
275*b70ed300SStefan Roese 	writel(EMAC_MAC_IPGT, &regs->mac_ipgt);
276*b70ed300SStefan Roese 
277*b70ed300SStefan Roese 	/* Set up IPGR */
278*b70ed300SStefan Roese 	writel(EMAC_MAC_NBTB_IPG2 | (EMAC_MAC_NBTB_IPG1 << 8), &regs->mac_ipgr);
279*b70ed300SStefan Roese 
280*b70ed300SStefan Roese 	/* Set up Collison window */
281*b70ed300SStefan Roese 	writel(EMAC_MAC_RM | (EMAC_MAC_CW << 8), &regs->mac_clrt);
282*b70ed300SStefan Roese 
283*b70ed300SStefan Roese 	/* Set up Max Frame Length */
284*b70ed300SStefan Roese 	writel(EMAC_MAC_MFL, &regs->mac_maxf);
285*b70ed300SStefan Roese }
286*b70ed300SStefan Roese 
287*b70ed300SStefan Roese static void emac_reset(struct eth_device *dev)
288*b70ed300SStefan Roese {
289*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
290*b70ed300SStefan Roese 
291*b70ed300SStefan Roese 	debug("resetting device\n");
292*b70ed300SStefan Roese 
293*b70ed300SStefan Roese 	/* RESET device */
294*b70ed300SStefan Roese 	writel(0, &regs->ctl);
295*b70ed300SStefan Roese 	udelay(200);
296*b70ed300SStefan Roese 
297*b70ed300SStefan Roese 	writel(1, &regs->ctl);
298*b70ed300SStefan Roese 	udelay(200);
299*b70ed300SStefan Roese }
300*b70ed300SStefan Roese 
301*b70ed300SStefan Roese static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)
302*b70ed300SStefan Roese {
303*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
304*b70ed300SStefan Roese 	struct emac_eth_dev *priv = dev->priv;
305*b70ed300SStefan Roese 	u16 phy_reg;
306*b70ed300SStefan Roese 
307*b70ed300SStefan Roese 	/* Init EMAC */
308*b70ed300SStefan Roese 
309*b70ed300SStefan Roese 	/* Flush RX FIFO */
310*b70ed300SStefan Roese 	setbits_le32(&regs->rx_ctl, 0x8);
311*b70ed300SStefan Roese 	udelay(1);
312*b70ed300SStefan Roese 
313*b70ed300SStefan Roese 	/* Init MAC */
314*b70ed300SStefan Roese 
315*b70ed300SStefan Roese 	/* Soft reset MAC */
316*b70ed300SStefan Roese 	clrbits_le32(&regs->mac_ctl0, 0x1 << 15);
317*b70ed300SStefan Roese 
318*b70ed300SStefan Roese 	/* Clear RX counter */
319*b70ed300SStefan Roese 	writel(0x0, &regs->rx_fbc);
320*b70ed300SStefan Roese 	udelay(1);
321*b70ed300SStefan Roese 
322*b70ed300SStefan Roese 	/* Set up EMAC */
323*b70ed300SStefan Roese 	emac_setup(dev);
324*b70ed300SStefan Roese 
325*b70ed300SStefan Roese 	writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
326*b70ed300SStefan Roese 	       dev->enetaddr[2], &regs->mac_a1);
327*b70ed300SStefan Roese 	writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
328*b70ed300SStefan Roese 	       dev->enetaddr[5], &regs->mac_a0);
329*b70ed300SStefan Roese 
330*b70ed300SStefan Roese 	mdelay(1);
331*b70ed300SStefan Roese 
332*b70ed300SStefan Roese 	emac_reset(dev);
333*b70ed300SStefan Roese 
334*b70ed300SStefan Roese 	/* PHY POWER UP */
335*b70ed300SStefan Roese 	emac_phy_read(dev->name, 1, 0, &phy_reg);
336*b70ed300SStefan Roese 	emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11)));
337*b70ed300SStefan Roese 	mdelay(1);
338*b70ed300SStefan Roese 
339*b70ed300SStefan Roese 	emac_phy_read(dev->name, 1, 0, &phy_reg);
340*b70ed300SStefan Roese 
341*b70ed300SStefan Roese 	priv->speed = miiphy_speed(dev->name, 0);
342*b70ed300SStefan Roese 	priv->duplex = miiphy_duplex(dev->name, 0);
343*b70ed300SStefan Roese 
344*b70ed300SStefan Roese 	/* Print link status only once */
345*b70ed300SStefan Roese 	if (!priv->link_printed) {
346*b70ed300SStefan Roese 		printf("ENET Speed is %d Mbps - %s duplex connection\n",
347*b70ed300SStefan Roese 		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
348*b70ed300SStefan Roese 		priv->link_printed = 1;
349*b70ed300SStefan Roese 	}
350*b70ed300SStefan Roese 
351*b70ed300SStefan Roese 	/* Set EMAC SPEED depend on PHY */
352*b70ed300SStefan Roese 	clrsetbits_le32(&regs->mac_supp, 1 << 8,
353*b70ed300SStefan Roese 			((phy_reg & (0x1 << 13)) >> 13) << 8);
354*b70ed300SStefan Roese 
355*b70ed300SStefan Roese 	/* Set duplex depend on phy */
356*b70ed300SStefan Roese 	clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
357*b70ed300SStefan Roese 			((phy_reg & (0x1 << 8)) >> 8) << 0);
358*b70ed300SStefan Roese 
359*b70ed300SStefan Roese 	/* Enable RX/TX */
360*b70ed300SStefan Roese 	setbits_le32(&regs->ctl, 0x7);
361*b70ed300SStefan Roese 
362*b70ed300SStefan Roese 	return 0;
363*b70ed300SStefan Roese }
364*b70ed300SStefan Roese 
365*b70ed300SStefan Roese static void sunxi_emac_eth_halt(struct eth_device *dev)
366*b70ed300SStefan Roese {
367*b70ed300SStefan Roese 	/* Nothing to do here */
368*b70ed300SStefan Roese }
369*b70ed300SStefan Roese 
370*b70ed300SStefan Roese static int sunxi_emac_eth_recv(struct eth_device *dev)
371*b70ed300SStefan Roese {
372*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
373*b70ed300SStefan Roese 	struct emac_rxhdr rxhdr;
374*b70ed300SStefan Roese 	u32 rxcount;
375*b70ed300SStefan Roese 	u32 reg_val;
376*b70ed300SStefan Roese 	int rx_len;
377*b70ed300SStefan Roese 	int rx_status;
378*b70ed300SStefan Roese 	int good_packet;
379*b70ed300SStefan Roese 
380*b70ed300SStefan Roese 	/* Check packet ready or not */
381*b70ed300SStefan Roese 
382*b70ed300SStefan Roese 	/* Race warning: The first packet might arrive with
383*b70ed300SStefan Roese 	 * the interrupts disabled, but the second will fix
384*b70ed300SStefan Roese 	 */
385*b70ed300SStefan Roese 	rxcount = readl(&regs->rx_fbc);
386*b70ed300SStefan Roese 	if (!rxcount) {
387*b70ed300SStefan Roese 		/* Had one stuck? */
388*b70ed300SStefan Roese 		rxcount = readl(&regs->rx_fbc);
389*b70ed300SStefan Roese 		if (!rxcount)
390*b70ed300SStefan Roese 			return 0;
391*b70ed300SStefan Roese 	}
392*b70ed300SStefan Roese 
393*b70ed300SStefan Roese 	reg_val = readl(&regs->rx_io_data);
394*b70ed300SStefan Roese 	if (reg_val != 0x0143414d) {
395*b70ed300SStefan Roese 		/* Disable RX */
396*b70ed300SStefan Roese 		clrbits_le32(&regs->ctl, 0x1 << 2);
397*b70ed300SStefan Roese 
398*b70ed300SStefan Roese 		/* Flush RX FIFO */
399*b70ed300SStefan Roese 		setbits_le32(&regs->rx_ctl, 0x1 << 3);
400*b70ed300SStefan Roese 		while (readl(&regs->rx_ctl) & (0x1 << 3))
401*b70ed300SStefan Roese 			;
402*b70ed300SStefan Roese 
403*b70ed300SStefan Roese 		/* Enable RX */
404*b70ed300SStefan Roese 		setbits_le32(&regs->ctl, 0x1 << 2);
405*b70ed300SStefan Roese 
406*b70ed300SStefan Roese 		return 0;
407*b70ed300SStefan Roese 	}
408*b70ed300SStefan Roese 
409*b70ed300SStefan Roese 	/* A packet ready now
410*b70ed300SStefan Roese 	 * Get status/length
411*b70ed300SStefan Roese 	 */
412*b70ed300SStefan Roese 	good_packet = 1;
413*b70ed300SStefan Roese 
414*b70ed300SStefan Roese 	emac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
415*b70ed300SStefan Roese 
416*b70ed300SStefan Roese 	rx_len = rxhdr.rx_len;
417*b70ed300SStefan Roese 	rx_status = rxhdr.rx_status;
418*b70ed300SStefan Roese 
419*b70ed300SStefan Roese 	/* Packet Status check */
420*b70ed300SStefan Roese 	if (rx_len < 0x40) {
421*b70ed300SStefan Roese 		good_packet = 0;
422*b70ed300SStefan Roese 		debug("RX: Bad Packet (runt)\n");
423*b70ed300SStefan Roese 	}
424*b70ed300SStefan Roese 
425*b70ed300SStefan Roese 	/* rx_status is identical to RSR register. */
426*b70ed300SStefan Roese 	if (0 & rx_status & (EMAC_CRCERR | EMAC_LENERR)) {
427*b70ed300SStefan Roese 		good_packet = 0;
428*b70ed300SStefan Roese 		if (rx_status & EMAC_CRCERR)
429*b70ed300SStefan Roese 			printf("crc error\n");
430*b70ed300SStefan Roese 		if (rx_status & EMAC_LENERR)
431*b70ed300SStefan Roese 			printf("length error\n");
432*b70ed300SStefan Roese 	}
433*b70ed300SStefan Roese 
434*b70ed300SStefan Roese 	/* Move data from EMAC */
435*b70ed300SStefan Roese 	if (good_packet) {
436*b70ed300SStefan Roese 		if (rx_len > DMA_CPU_TRRESHOLD) {
437*b70ed300SStefan Roese 			printf("Received packet is too big (len=%d)\n", rx_len);
438*b70ed300SStefan Roese 		} else {
439*b70ed300SStefan Roese 			emac_inblk_32bit((void *)&regs->rx_io_data,
440*b70ed300SStefan Roese 					 NetRxPackets[0], rx_len);
441*b70ed300SStefan Roese 
442*b70ed300SStefan Roese 			/* Pass to upper layer */
443*b70ed300SStefan Roese 			NetReceive(NetRxPackets[0], rx_len);
444*b70ed300SStefan Roese 			return rx_len;
445*b70ed300SStefan Roese 		}
446*b70ed300SStefan Roese 	}
447*b70ed300SStefan Roese 
448*b70ed300SStefan Roese 	return 0;
449*b70ed300SStefan Roese }
450*b70ed300SStefan Roese 
451*b70ed300SStefan Roese static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len)
452*b70ed300SStefan Roese {
453*b70ed300SStefan Roese 	struct emac_regs *regs = (struct emac_regs *)dev->iobase;
454*b70ed300SStefan Roese 
455*b70ed300SStefan Roese 	/* Select channel 0 */
456*b70ed300SStefan Roese 	writel(0, &regs->tx_ins);
457*b70ed300SStefan Roese 
458*b70ed300SStefan Roese 	/* Write packet */
459*b70ed300SStefan Roese 	emac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
460*b70ed300SStefan Roese 
461*b70ed300SStefan Roese 	/* Set TX len */
462*b70ed300SStefan Roese 	writel(len, &regs->tx_pl0);
463*b70ed300SStefan Roese 
464*b70ed300SStefan Roese 	/* Start translate from fifo to phy */
465*b70ed300SStefan Roese 	setbits_le32(&regs->tx_ctl0, 1);
466*b70ed300SStefan Roese 
467*b70ed300SStefan Roese 	return 0;
468*b70ed300SStefan Roese }
469*b70ed300SStefan Roese 
470*b70ed300SStefan Roese int sunxi_emac_initialize(void)
471*b70ed300SStefan Roese {
472*b70ed300SStefan Roese 	struct sunxi_ccm_reg *const ccm =
473*b70ed300SStefan Roese 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
474*b70ed300SStefan Roese 	struct sunxi_sramc_regs *sram =
475*b70ed300SStefan Roese 		(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
476*b70ed300SStefan Roese 	struct emac_regs *regs =
477*b70ed300SStefan Roese 		(struct emac_regs *)SUNXI_EMAC_BASE;
478*b70ed300SStefan Roese 	struct eth_device *dev;
479*b70ed300SStefan Roese 	struct emac_eth_dev *priv;
480*b70ed300SStefan Roese 	int pin;
481*b70ed300SStefan Roese 
482*b70ed300SStefan Roese 	dev = malloc(sizeof(*dev));
483*b70ed300SStefan Roese 	if (dev == NULL)
484*b70ed300SStefan Roese 		return -ENOMEM;
485*b70ed300SStefan Roese 
486*b70ed300SStefan Roese 	priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev));
487*b70ed300SStefan Roese 	if (!priv) {
488*b70ed300SStefan Roese 		free(dev);
489*b70ed300SStefan Roese 		return -ENOMEM;
490*b70ed300SStefan Roese 	}
491*b70ed300SStefan Roese 
492*b70ed300SStefan Roese 	memset(dev, 0, sizeof(*dev));
493*b70ed300SStefan Roese 	memset(priv, 0, sizeof(struct emac_eth_dev));
494*b70ed300SStefan Roese 
495*b70ed300SStefan Roese 	/* Map SRAM to EMAC */
496*b70ed300SStefan Roese 	setbits_le32(&sram->ctrl1, 0x5 << 2);
497*b70ed300SStefan Roese 
498*b70ed300SStefan Roese 	/* Configure pin mux settings for MII Ethernet */
499*b70ed300SStefan Roese 	for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
500*b70ed300SStefan Roese 		sunxi_gpio_set_cfgpin(pin, SUNXI_GPA0_EMAC);
501*b70ed300SStefan Roese 
502*b70ed300SStefan Roese 	/* Set up clock gating */
503*b70ed300SStefan Roese 	setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC);
504*b70ed300SStefan Roese 
505*b70ed300SStefan Roese 	/* Set MII clock */
506*b70ed300SStefan Roese 	clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
507*b70ed300SStefan Roese 
508*b70ed300SStefan Roese 	dev->iobase = (int)regs;
509*b70ed300SStefan Roese 	dev->priv = priv;
510*b70ed300SStefan Roese 	dev->init = sunxi_emac_eth_init;
511*b70ed300SStefan Roese 	dev->halt = sunxi_emac_eth_halt;
512*b70ed300SStefan Roese 	dev->send = sunxi_emac_eth_send;
513*b70ed300SStefan Roese 	dev->recv = sunxi_emac_eth_recv;
514*b70ed300SStefan Roese 	strcpy(dev->name, "emac");
515*b70ed300SStefan Roese 
516*b70ed300SStefan Roese 	eth_register(dev);
517*b70ed300SStefan Roese 
518*b70ed300SStefan Roese 	miiphy_register(dev->name, emac_phy_read, emac_phy_write);
519*b70ed300SStefan Roese 
520*b70ed300SStefan Roese 	return 0;
521*b70ed300SStefan Roese }
522