Blame view

drivers/net/at91_emac.c 12.4 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
c041e9d21   Jens Scharsig   new at91_emac net...
2
3
4
5
6
7
  /*
   * Copyright (C) 2009 BuS Elektronik GmbH & Co. KG
   * Jens Scharsig (esw@bus-elektronik.de)
   *
   * (C) Copyright 2003
   * Author : Hamid Ikdoumi (Atmel)
c041e9d21   Jens Scharsig   new at91_emac net...
8
9
10
11
   */
  
  #include <common.h>
  #include <asm/io.h>
c041e9d21   Jens Scharsig   new at91_emac net...
12
13
  #include <asm/arch/hardware.h>
  #include <asm/arch/at91_emac.h>
cd4de1d92   Wenyou Yang   drivers: at91: cl...
14
  #include <asm/arch/clk.h>
c041e9d21   Jens Scharsig   new at91_emac net...
15
  #include <asm/arch/at91_pio.h>
c041e9d21   Jens Scharsig   new at91_emac net...
16
17
18
19
20
21
22
23
24
25
26
27
28
  #include <net.h>
  #include <netdev.h>
  #include <malloc.h>
  #include <miiphy.h>
  #include <linux/mii.h>
  
  #undef MII_DEBUG
  #undef ET_DEBUG
  
  #if (CONFIG_SYS_RX_ETH_BUFFER > 1024)
  #error AT91 EMAC supports max 1024 RX buffers. \
  	Please decrease the CONFIG_SYS_RX_ETH_BUFFER value
  #endif
836cd4535   Eric Bénard   cpuat91: unbreak ...
29
30
31
  #ifndef CONFIG_DRIVER_AT91EMAC_PHYADDR
  #define CONFIG_DRIVER_AT91EMAC_PHYADDR	0
  #endif
c041e9d21   Jens Scharsig   new at91_emac net...
32
33
34
35
36
37
38
39
40
41
42
43
  /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */
  #if (AT91C_MASTER_CLOCK > 80000000)
  	#define HCLK_DIV	AT91_EMAC_CFG_MCLK_64
  #elif (AT91C_MASTER_CLOCK > 40000000)
  	#define HCLK_DIV	AT91_EMAC_CFG_MCLK_32
  #elif (AT91C_MASTER_CLOCK > 20000000)
  	#define HCLK_DIV	AT91_EMAC_CFG_MCLK_16
  #else
  	#define HCLK_DIV	AT91_EMAC_CFG_MCLK_8
  #endif
  
  #ifdef ET_DEBUG
f49620665   Wolfgang Denk   drivers/net/at91_...
44
  #define DEBUG_AT91EMAC	1
c041e9d21   Jens Scharsig   new at91_emac net...
45
  #else
f49620665   Wolfgang Denk   drivers/net/at91_...
46
  #define DEBUG_AT91EMAC	0
c041e9d21   Jens Scharsig   new at91_emac net...
47
48
49
  #endif
  
  #ifdef MII_DEBUG
f49620665   Wolfgang Denk   drivers/net/at91_...
50
  #define DEBUG_AT91PHY	1
c041e9d21   Jens Scharsig   new at91_emac net...
51
  #else
f49620665   Wolfgang Denk   drivers/net/at91_...
52
  #define DEBUG_AT91PHY	0
c041e9d21   Jens Scharsig   new at91_emac net...
53
54
55
  #endif
  
  #ifndef CONFIG_DRIVER_AT91EMAC_QUIET
f49620665   Wolfgang Denk   drivers/net/at91_...
56
  #define VERBOSEP	1
c041e9d21   Jens Scharsig   new at91_emac net...
57
  #else
f49620665   Wolfgang Denk   drivers/net/at91_...
58
  #define VERBOSEP	0
c041e9d21   Jens Scharsig   new at91_emac net...
59
60
61
62
63
64
65
66
67
  #endif
  
  #define RBF_ADDR      0xfffffffc
  #define RBF_OWNER     (1<<0)
  #define RBF_WRAP      (1<<1)
  #define RBF_BROADCAST (1<<31)
  #define RBF_MULTICAST (1<<30)
  #define RBF_UNICAST   (1<<29)
  #define RBF_EXTERNAL  (1<<28)
6052cbab4   Loïc Minier   Fix misc spelling...
68
  #define RBF_UNKNOWN   (1<<27)
c041e9d21   Jens Scharsig   new at91_emac net...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  #define RBF_SIZE      0x07ff
  #define RBF_LOCAL4    (1<<26)
  #define RBF_LOCAL3    (1<<25)
  #define RBF_LOCAL2    (1<<24)
  #define RBF_LOCAL1    (1<<23)
  
  #define RBF_FRAMEMAX CONFIG_SYS_RX_ETH_BUFFER
  #define RBF_FRAMELEN 0x600
  
  typedef struct {
  	unsigned long addr, size;
  } rbf_t;
  
  typedef struct {
  	rbf_t 		rbfdt[RBF_FRAMEMAX];
  	unsigned long	rbindex;
  } emac_device;
  
  void at91emac_EnableMDIO(at91_emac_t *at91mac)
  {
  	/* Mac CTRL reg set for MDIO enable */
  	writel(readl(&at91mac->ctl) | AT91_EMAC_CTL_MPE, &at91mac->ctl);
  }
  
  void at91emac_DisableMDIO(at91_emac_t *at91mac)
  {
  	/* Mac CTRL reg set for MDIO disable */
  	writel(readl(&at91mac->ctl) & ~AT91_EMAC_CTL_MPE, &at91mac->ctl);
  }
  
  int  at91emac_read(at91_emac_t *at91mac, unsigned char addr,
  		unsigned char reg, unsigned short *value)
  {
38bda019e   Andreas Bießmann   at91_emac.c: poll...
102
  	unsigned long netstat;
c041e9d21   Jens Scharsig   new at91_emac net...
103
104
105
106
107
108
  	at91emac_EnableMDIO(at91mac);
  
  	writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_R |
  		AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
  		AT91_EMAC_MAN_PHYA(addr),
  		&at91mac->man);
38bda019e   Andreas Bießmann   at91_emac.c: poll...
109
110
111
  
  	do {
  		netstat = readl(&at91mac->sr);
f49620665   Wolfgang Denk   drivers/net/at91_...
112
113
  		debug_cond(DEBUG_AT91PHY, "poll SR %08lx
  ", netstat);
38bda019e   Andreas Bießmann   at91_emac.c: poll...
114
  	} while (!(netstat & AT91_EMAC_SR_IDLE));
c041e9d21   Jens Scharsig   new at91_emac net...
115
116
117
  	*value = readl(&at91mac->man) & AT91_EMAC_MAN_DATA_MASK;
  
  	at91emac_DisableMDIO(at91mac);
f49620665   Wolfgang Denk   drivers/net/at91_...
118
119
120
  	debug_cond(DEBUG_AT91PHY,
  		"AT91PHY read %p REG(%d)=%x
  ", at91mac, reg, *value);
c041e9d21   Jens Scharsig   new at91_emac net...
121
122
123
124
125
126
127
  
  	return 0;
  }
  
  int  at91emac_write(at91_emac_t *at91mac, unsigned char addr,
  		unsigned char reg, unsigned short value)
  {
38bda019e   Andreas Bießmann   at91_emac.c: poll...
128
  	unsigned long netstat;
f49620665   Wolfgang Denk   drivers/net/at91_...
129
130
131
  	debug_cond(DEBUG_AT91PHY,
  		"AT91PHY write %p REG(%d)=%p
  ", at91mac, reg, &value);
c041e9d21   Jens Scharsig   new at91_emac net...
132
133
134
135
136
137
138
  
  	at91emac_EnableMDIO(at91mac);
  
  	writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_W |
  		AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
  		AT91_EMAC_MAN_PHYA(addr) | (value & AT91_EMAC_MAN_DATA_MASK),
  		&at91mac->man);
38bda019e   Andreas Bießmann   at91_emac.c: poll...
139
140
141
  
  	do {
  		netstat = readl(&at91mac->sr);
f49620665   Wolfgang Denk   drivers/net/at91_...
142
143
  		debug_cond(DEBUG_AT91PHY, "poll SR %08lx
  ", netstat);
38bda019e   Andreas Bießmann   at91_emac.c: poll...
144
  	} while (!(netstat & AT91_EMAC_SR_IDLE));
c041e9d21   Jens Scharsig   new at91_emac net...
145
146
  
  	at91emac_DisableMDIO(at91mac);
38bda019e   Andreas Bießmann   at91_emac.c: poll...
147

c041e9d21   Jens Scharsig   new at91_emac net...
148
149
150
151
  	return 0;
  }
  
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
d7fb9bcfb   Ben Warren   Fix compile warni...
152
  at91_emac_t *get_emacbase_by_name(const char *devname)
c041e9d21   Jens Scharsig   new at91_emac net...
153
154
155
156
157
158
  {
  	struct eth_device *netdev;
  
  	netdev = eth_get_dev_by_name(devname);
  	return (at91_emac_t *) netdev->iobase;
  }
5a49f1748   Joe Hershberger   net: mii: Use spa...
159
  int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg)
c041e9d21   Jens Scharsig   new at91_emac net...
160
  {
5a49f1748   Joe Hershberger   net: mii: Use spa...
161
  	unsigned short value = 0;
c041e9d21   Jens Scharsig   new at91_emac net...
162
  	at91_emac_t *emac;
5a49f1748   Joe Hershberger   net: mii: Use spa...
163
164
165
  	emac = get_emacbase_by_name(bus->name);
  	at91emac_read(emac , addr, reg, &value);
  	return value;
c041e9d21   Jens Scharsig   new at91_emac net...
166
  }
5a49f1748   Joe Hershberger   net: mii: Use spa...
167
168
  int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg,
  		       u16 value)
c041e9d21   Jens Scharsig   new at91_emac net...
169
170
  {
  	at91_emac_t *emac;
5a49f1748   Joe Hershberger   net: mii: Use spa...
171
  	emac = get_emacbase_by_name(bus->name);
c041e9d21   Jens Scharsig   new at91_emac net...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  	at91emac_write(emac, addr, reg, value);
  	return 0;
  }
  
  #endif
  
  static int at91emac_phy_reset(struct eth_device *netdev)
  {
  	int i;
  	u16 status, adv;
  	at91_emac_t *emac;
  
  	emac = (at91_emac_t *) netdev->iobase;
  
  	adv = ADVERTISE_CSMA | ADVERTISE_ALL;
836cd4535   Eric Bénard   cpuat91: unbreak ...
187
188
  	at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  		MII_ADVERTISE, adv);
f49620665   Wolfgang Denk   drivers/net/at91_...
189
190
  	debug_cond(VERBOSEP, "%s: Starting autonegotiation...
  ", netdev->name);
836cd4535   Eric Bénard   cpuat91: unbreak ...
191
192
  	at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR,
  		(BMCR_ANENABLE | BMCR_ANRESTART));
c041e9d21   Jens Scharsig   new at91_emac net...
193

e63ac4cf1   Andreas Bießmann   drivers/net/at91_...
194
  	for (i = 0; i < 30000; i++) {
836cd4535   Eric Bénard   cpuat91: unbreak ...
195
196
  		at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  			MII_BMSR, &status);
c041e9d21   Jens Scharsig   new at91_emac net...
197
198
199
200
201
202
  		if (status & BMSR_ANEGCOMPLETE)
  			break;
  		udelay(100);
  	}
  
  	if (status & BMSR_ANEGCOMPLETE) {
f49620665   Wolfgang Denk   drivers/net/at91_...
203
204
205
  		debug_cond(VERBOSEP,
  			"%s: Autonegotiation complete
  ", netdev->name);
c041e9d21   Jens Scharsig   new at91_emac net...
206
207
208
209
  	} else {
  		printf("%s: Autonegotiation timed out (status=0x%04x)
  ",
  		       netdev->name, status);
77179067d   Andreas Bießmann   drivers/net/at91_...
210
  		return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  	}
  	return 0;
  }
  
  static int at91emac_phy_init(struct eth_device *netdev)
  {
  	u16 phy_id, status, adv, lpa;
  	int media, speed, duplex;
  	int i;
  	at91_emac_t *emac;
  
  	emac = (at91_emac_t *) netdev->iobase;
  
  	/* Check if the PHY is up to snuff... */
836cd4535   Eric Bénard   cpuat91: unbreak ...
225
226
  	at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  		MII_PHYSID1, &phy_id);
c041e9d21   Jens Scharsig   new at91_emac net...
227
228
229
  	if (phy_id == 0xffff) {
  		printf("%s: No PHY present
  ", netdev->name);
77179067d   Andreas Bießmann   drivers/net/at91_...
230
  		return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
231
  	}
836cd4535   Eric Bénard   cpuat91: unbreak ...
232
233
  	at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  		MII_BMSR, &status);
c041e9d21   Jens Scharsig   new at91_emac net...
234
235
236
237
  
  	if (!(status & BMSR_LSTATUS)) {
  		/* Try to re-negotiate if we don't have link already. */
  		if (at91emac_phy_reset(netdev))
77179067d   Andreas Bießmann   drivers/net/at91_...
238
  			return -2;
c041e9d21   Jens Scharsig   new at91_emac net...
239
240
  
  		for (i = 0; i < 100000 / 100; i++) {
836cd4535   Eric Bénard   cpuat91: unbreak ...
241
242
  			at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  				MII_BMSR, &status);
c041e9d21   Jens Scharsig   new at91_emac net...
243
244
245
246
247
248
  			if (status & BMSR_LSTATUS)
  				break;
  			udelay(100);
  		}
  	}
  	if (!(status & BMSR_LSTATUS)) {
f49620665   Wolfgang Denk   drivers/net/at91_...
249
250
  		debug_cond(VERBOSEP, "%s: link down
  ", netdev->name);
77179067d   Andreas Bießmann   drivers/net/at91_...
251
  		return -3;
c041e9d21   Jens Scharsig   new at91_emac net...
252
  	} else {
836cd4535   Eric Bénard   cpuat91: unbreak ...
253
254
255
256
  		at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  			MII_ADVERTISE, &adv);
  		at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
  			MII_LPA, &lpa);
c041e9d21   Jens Scharsig   new at91_emac net...
257
258
259
260
  		media = mii_nway_result(lpa & adv);
  		speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
  			 ? 1 : 0);
  		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
f49620665   Wolfgang Denk   drivers/net/at91_...
261
262
  		debug_cond(VERBOSEP, "%s: link up, %sMbps %s-duplex
  ",
c041e9d21   Jens Scharsig   new at91_emac net...
263
264
265
266
267
268
269
270
271
272
  		       netdev->name,
  		       speed ? "100" : "10",
  		       duplex ? "full" : "half");
  	}
  	return 0;
  }
  
  int at91emac_UpdateLinkSpeed(at91_emac_t *emac)
  {
  	unsigned short stat1;
836cd4535   Eric Bénard   cpuat91: unbreak ...
273
  	at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &stat1);
c041e9d21   Jens Scharsig   new at91_emac net...
274
275
  
  	if (!(stat1 & BMSR_LSTATUS))	/* link status up? */
77179067d   Andreas Bießmann   drivers/net/at91_...
276
  		return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  
  	if (stat1 & BMSR_100FULL) {
  		/*set Emac for 100BaseTX and Full Duplex  */
  		writel(readl(&emac->cfg) |
  			AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD,
  			&emac->cfg);
  		return 0;
  	}
  
  	if (stat1 & BMSR_10FULL) {
  		/*set MII for 10BaseT and Full Duplex  */
  		writel((readl(&emac->cfg) &
  			~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)
  			) | AT91_EMAC_CFG_FD,
  			&emac->cfg);
  		return 0;
  	}
  
  	if (stat1 & BMSR_100HALF) {
  		/*set MII for 100BaseTX and Half Duplex  */
  		writel((readl(&emac->cfg) &
  			~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)
  			) | AT91_EMAC_CFG_SPD,
  			&emac->cfg);
  		return 0;
  	}
  
  	if (stat1 & BMSR_10HALF) {
  		/*set MII for 10BaseT and Half Duplex  */
  		writel((readl(&emac->cfg) &
  			~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)),
  			&emac->cfg);
  		return 0;
  	}
77179067d   Andreas Bießmann   drivers/net/at91_...
311
  	return 0;
c041e9d21   Jens Scharsig   new at91_emac net...
312
313
314
315
316
317
318
319
  }
  
  static int at91emac_init(struct eth_device *netdev, bd_t *bd)
  {
  	int i;
  	u32 value;
  	emac_device *dev;
  	at91_emac_t *emac;
807339944   Jens Scharsig   update arm/at91rm...
320
  	at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIO;
c041e9d21   Jens Scharsig   new at91_emac net...
321
322
323
324
325
  
  	emac = (at91_emac_t *) netdev->iobase;
  	dev = (emac_device *) netdev->priv;
  
  	/* PIO Disable Register */
807339944   Jens Scharsig   update arm/at91rm...
326
327
328
329
330
  	value =	ATMEL_PMX_AA_EMDIO |	ATMEL_PMX_AA_EMDC |
  		ATMEL_PMX_AA_ERXER |	ATMEL_PMX_AA_ERX1 |
  		ATMEL_PMX_AA_ERX0 |	ATMEL_PMX_AA_ECRS |
  		ATMEL_PMX_AA_ETX1 |	ATMEL_PMX_AA_ETX0 |
  		ATMEL_PMX_AA_ETXEN |	ATMEL_PMX_AA_EREFCK;
c041e9d21   Jens Scharsig   new at91_emac net...
331
332
  
  	writel(value, &pio->pioa.pdr);
2dc63f736   Wenyou Yang   gpio: at91_gpio: ...
333
  	writel(value, &pio->pioa.mux.pio2.asr);
c041e9d21   Jens Scharsig   new at91_emac net...
334
335
  
  #ifdef CONFIG_RMII
807339944   Jens Scharsig   update arm/at91rm...
336
  	value = ATMEL_PMX_BA_ERXCK;
c041e9d21   Jens Scharsig   new at91_emac net...
337
  #else
807339944   Jens Scharsig   update arm/at91rm...
338
339
340
341
  	value = ATMEL_PMX_BA_ERXCK |	ATMEL_PMX_BA_ECOL |
  		ATMEL_PMX_BA_ERXDV |	ATMEL_PMX_BA_ERX3 |
  		ATMEL_PMX_BA_ERX2 |	ATMEL_PMX_BA_ETXER |
  		ATMEL_PMX_BA_ETX3 |	ATMEL_PMX_BA_ETX2;
c041e9d21   Jens Scharsig   new at91_emac net...
342
343
  #endif
  	writel(value, &pio->piob.pdr);
2dc63f736   Wenyou Yang   gpio: at91_gpio: ...
344
  	writel(value, &pio->piob.mux.pio2.bsr);
c041e9d21   Jens Scharsig   new at91_emac net...
345

cd4de1d92   Wenyou Yang   drivers: at91: cl...
346
  	at91_periph_clk_enable(ATMEL_ID_EMAC);
c041e9d21   Jens Scharsig   new at91_emac net...
347
  	writel(readl(&emac->ctl) | AT91_EMAC_CTL_CSR, &emac->ctl);
c041e9d21   Jens Scharsig   new at91_emac net...
348
349
  	/* Init Ethernet buffers */
  	for (i = 0; i < RBF_FRAMEMAX; i++) {
1fd92db83   Joe Hershberger   net: cosmetic: Fi...
350
  		dev->rbfdt[i].addr = (unsigned long) net_rx_packets[i];
c041e9d21   Jens Scharsig   new at91_emac net...
351
352
353
354
355
356
357
358
359
360
361
362
363
  		dev->rbfdt[i].size = 0;
  	}
  	dev->rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
  	dev->rbindex = 0;
  	writel((u32) &(dev->rbfdt[0]), &emac->rbqp);
  
  	writel(readl(&emac->rsr) &
  		~(AT91_EMAC_RSR_OVR | AT91_EMAC_RSR_REC | AT91_EMAC_RSR_BNA),
  		&emac->rsr);
  
  	value = AT91_EMAC_CFG_CAF |	AT91_EMAC_CFG_NBC |
  		HCLK_DIV;
  #ifdef CONFIG_RMII
836cd4535   Eric Bénard   cpuat91: unbreak ...
364
  	value |= AT91_EMAC_CFG_RMII;
c041e9d21   Jens Scharsig   new at91_emac net...
365
366
367
368
369
370
371
372
373
374
  #endif
  	writel(value, &emac->cfg);
  
  	writel(readl(&emac->ctl) | AT91_EMAC_CTL_TE | AT91_EMAC_CTL_RE,
  		&emac->ctl);
  
  	if (!at91emac_phy_init(netdev)) {
  		at91emac_UpdateLinkSpeed(emac);
  		return 0;
  	}
77179067d   Andreas Bießmann   drivers/net/at91_...
375
  	return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
376
377
378
379
380
381
382
383
384
  }
  
  static void at91emac_halt(struct eth_device *netdev)
  {
  	at91_emac_t *emac;
  
  	emac = (at91_emac_t *) netdev->iobase;
  	writel(readl(&emac->ctl) & ~(AT91_EMAC_CTL_TE | AT91_EMAC_CTL_RE),
  		&emac->ctl);
f49620665   Wolfgang Denk   drivers/net/at91_...
385
386
  	debug_cond(DEBUG_AT91EMAC, "halt MAC
  ");
c041e9d21   Jens Scharsig   new at91_emac net...
387
  }
9577501c6   Joe Hershberger   drivers/net/at91_...
388
  static int at91emac_send(struct eth_device *netdev, void *packet, int length)
c041e9d21   Jens Scharsig   new at91_emac net...
389
390
391
392
393
394
395
396
397
398
399
  {
  	at91_emac_t *emac;
  
  	emac = (at91_emac_t *) netdev->iobase;
  
  	while (!(readl(&emac->tsr) & AT91_EMAC_TSR_BNQ))
  		;
  	writel((u32) packet, &emac->tar);
  	writel(AT91_EMAC_TCR_LEN(length), &emac->tcr);
  	while (AT91_EMAC_TCR_LEN(readl(&emac->tcr)))
  		;
f49620665   Wolfgang Denk   drivers/net/at91_...
400
401
  	debug_cond(DEBUG_AT91EMAC, "Send %d
  ", length);
c041e9d21   Jens Scharsig   new at91_emac net...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
  	writel(readl(&emac->tsr) | AT91_EMAC_TSR_COMP, &emac->tsr);
  	return 0;
  }
  
  static int at91emac_recv(struct eth_device *netdev)
  {
  	emac_device *dev;
  	at91_emac_t *emac;
  	rbf_t *rbfp;
  	int size;
  
  	emac = (at91_emac_t *) netdev->iobase;
  	dev = (emac_device *) netdev->priv;
  
  	rbfp = &dev->rbfdt[dev->rbindex];
  	while (rbfp->addr & RBF_OWNER)	{
  		size = rbfp->size & RBF_SIZE;
1fd92db83   Joe Hershberger   net: cosmetic: Fi...
419
  		net_process_received_packet(net_rx_packets[dev->rbindex], size);
c041e9d21   Jens Scharsig   new at91_emac net...
420

f49620665   Wolfgang Denk   drivers/net/at91_...
421
422
  		debug_cond(DEBUG_AT91EMAC, "Recv[%ld]: %d bytes @ %lx
  ",
c041e9d21   Jens Scharsig   new at91_emac net...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  			dev->rbindex, size, rbfp->addr);
  
  		rbfp->addr &= ~RBF_OWNER;
  		rbfp->size = 0;
  		if (dev->rbindex < (RBF_FRAMEMAX-1))
  			dev->rbindex++;
  		else
  			dev->rbindex = 0;
  
  		rbfp = &(dev->rbfdt[dev->rbindex]);
  		if (!(rbfp->addr & RBF_OWNER))
  			writel(readl(&emac->rsr) | AT91_EMAC_RSR_REC,
  				&emac->rsr);
  	}
  
  	if (readl(&emac->isr) & AT91_EMAC_IxR_RBNA) {
  		/* EMAC silicon bug 41.3.1 workaround 1 */
  		writel(readl(&emac->ctl) & ~AT91_EMAC_CTL_RE, &emac->ctl);
  		writel(readl(&emac->ctl) | AT91_EMAC_CTL_RE, &emac->ctl);
  		dev->rbindex = 0;
  		printf("%s: reset receiver (EMAC dead lock bug)
  ",
  			netdev->name);
  	}
  	return 0;
  }
409943a98   Eric Bénard   at91_emac: Write ...
449
450
  static int at91emac_write_hwaddr(struct eth_device *netdev)
  {
409943a98   Eric Bénard   at91_emac: Write ...
451
  	at91_emac_t *emac;
409943a98   Eric Bénard   at91_emac: Write ...
452
  	emac = (at91_emac_t *) netdev->iobase;
409943a98   Eric Bénard   at91_emac: Write ...
453

cd4de1d92   Wenyou Yang   drivers: at91: cl...
454
  	at91_periph_clk_enable(ATMEL_ID_EMAC);
f49620665   Wolfgang Denk   drivers/net/at91_...
455
456
457
  	debug_cond(DEBUG_AT91EMAC,
  		"init MAC-ADDR %02x:%02x:%02x:%02x:%02x:%02x
  ",
2321bfe42   andreas.devel@googlemail.com   at91_emac: fix co...
458
459
460
461
462
463
  		netdev->enetaddr[5], netdev->enetaddr[4], netdev->enetaddr[3],
  		netdev->enetaddr[2], netdev->enetaddr[1], netdev->enetaddr[0]);
  	writel( (netdev->enetaddr[0] | netdev->enetaddr[1] << 8 |
  			netdev->enetaddr[2] << 16 | netdev->enetaddr[3] << 24),
  			&emac->sa2l);
  	writel((netdev->enetaddr[4] | netdev->enetaddr[5] << 8), &emac->sa2h);
f49620665   Wolfgang Denk   drivers/net/at91_...
464
465
  	debug_cond(DEBUG_AT91EMAC, "init MAC-ADDR %x%x
  ",
409943a98   Eric Bénard   at91_emac: Write ...
466
467
468
  		readl(&emac->sa2h), readl(&emac->sa2l));
  	return 0;
  }
c041e9d21   Jens Scharsig   new at91_emac net...
469
470
471
472
473
474
475
  int at91emac_register(bd_t *bis, unsigned long iobase)
  {
  	emac_device *emac;
  	emac_device *emacfix;
  	struct eth_device *dev;
  
  	if (iobase == 0)
807339944   Jens Scharsig   update arm/at91rm...
476
  		iobase = ATMEL_BASE_EMAC;
c041e9d21   Jens Scharsig   new at91_emac net...
477
478
  	emac = malloc(sizeof(*emac)+512);
  	if (emac == NULL)
77179067d   Andreas Bießmann   drivers/net/at91_...
479
  		return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
480
481
482
  	dev = malloc(sizeof(*dev));
  	if (dev == NULL) {
  		free(emac);
77179067d   Andreas Bießmann   drivers/net/at91_...
483
  		return -1;
c041e9d21   Jens Scharsig   new at91_emac net...
484
485
486
487
488
489
  	}
  	/* alignment as per Errata (64 bytes) is insufficient! */
  	emacfix = (emac_device *) (((unsigned long) emac + 0x1ff) & 0xFFFFFE00);
  	memset(emacfix, 0, sizeof(emac_device));
  
  	memset(dev, 0, sizeof(*dev));
192bc6948   Ben Whitten   Fix GCC format-se...
490
  	strcpy(dev->name, "emac");
c041e9d21   Jens Scharsig   new at91_emac net...
491
492
493
494
495
496
  	dev->iobase = iobase;
  	dev->priv = emacfix;
  	dev->init = at91emac_init;
  	dev->halt = at91emac_halt;
  	dev->send = at91emac_send;
  	dev->recv = at91emac_recv;
409943a98   Eric Bénard   at91_emac: Write ...
497
  	dev->write_hwaddr = at91emac_write_hwaddr;
c041e9d21   Jens Scharsig   new at91_emac net...
498
499
500
501
  
  	eth_register(dev);
  
  #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
5a49f1748   Joe Hershberger   net: mii: Use spa...
502
503
504
505
506
507
508
509
510
511
512
  	int retval;
  	struct mii_dev *mdiodev = mdio_alloc();
  	if (!mdiodev)
  		return -ENOMEM;
  	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
  	mdiodev->read = at91emac_mii_read;
  	mdiodev->write = at91emac_mii_write;
  
  	retval = mdio_register(mdiodev);
  	if (retval < 0)
  		return retval;
c041e9d21   Jens Scharsig   new at91_emac net...
513
514
515
  #endif
  	return 1;
  }