blob: 750331d0540fc188400dde49b9732e08f80b367d [file] [log] [blame]
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +01001/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +01005 */
6#include <common.h>
7
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +01008/*
9 * The u-boot networking stack is a little weird. It seems like the
10 * networking core allocates receive buffers up front without any
11 * regard to the hardware that's supposed to actually receive those
12 * packets.
13 *
14 * The MACB receives packets into 128-byte receive buffers, so the
15 * buffers allocated by the core isn't very practical to use. We'll
16 * allocate our own, but we need one such buffer in case a packet
17 * wraps around the DMA ring so that we have to copy it.
18 *
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020019 * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010020 * configuration header. This way, the core allocates one RX buffer
21 * and one TX buffer, each of which can hold a ethernet packet of
22 * maximum size.
23 *
24 * For some reason, the networking core unconditionally specifies a
25 * 32-byte packet "alignment" (which really should be called
26 * "padding"). MACB shouldn't need that, but we'll refrain from any
27 * core modifications here...
28 */
29
30#include <net.h>
Ben Warren89973f82008-08-31 22:22:04 -070031#include <netdev.h>
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010032#include <malloc.h>
Semih Hazar0f751d62009-12-17 15:07:15 +020033#include <miiphy.h>
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010034
35#include <linux/mii.h>
36#include <asm/io.h>
37#include <asm/dma-mapping.h>
38#include <asm/arch/clk.h>
Bo Shen8314ccd2013-08-19 10:35:47 +080039#include <asm-generic/errno.h>
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010040
41#include "macb.h"
42
Andreas Bießmannceef9832014-05-26 22:55:18 +020043#define MACB_RX_BUFFER_SIZE 4096
44#define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128)
45#define MACB_TX_RING_SIZE 16
46#define MACB_TX_TIMEOUT 1000
47#define MACB_AUTONEG_TIMEOUT 5000000
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010048
49struct macb_dma_desc {
50 u32 addr;
51 u32 ctrl;
52};
53
54#define RXADDR_USED 0x00000001
55#define RXADDR_WRAP 0x00000002
56
57#define RXBUF_FRMLEN_MASK 0x00000fff
58#define RXBUF_FRAME_START 0x00004000
59#define RXBUF_FRAME_END 0x00008000
60#define RXBUF_TYPEID_MATCH 0x00400000
61#define RXBUF_ADDR4_MATCH 0x00800000
62#define RXBUF_ADDR3_MATCH 0x01000000
63#define RXBUF_ADDR2_MATCH 0x02000000
64#define RXBUF_ADDR1_MATCH 0x04000000
65#define RXBUF_BROADCAST 0x80000000
66
67#define TXBUF_FRMLEN_MASK 0x000007ff
68#define TXBUF_FRAME_END 0x00008000
69#define TXBUF_NOCRC 0x00010000
70#define TXBUF_EXHAUSTED 0x08000000
71#define TXBUF_UNDERRUN 0x10000000
72#define TXBUF_MAXRETRY 0x20000000
73#define TXBUF_WRAP 0x40000000
74#define TXBUF_USED 0x80000000
75
76struct macb_device {
77 void *regs;
78
79 unsigned int rx_tail;
80 unsigned int tx_head;
81 unsigned int tx_tail;
82
83 void *rx_buffer;
84 void *tx_buffer;
85 struct macb_dma_desc *rx_ring;
86 struct macb_dma_desc *tx_ring;
87
88 unsigned long rx_buffer_dma;
89 unsigned long rx_ring_dma;
90 unsigned long tx_ring_dma;
91
92 const struct device *dev;
93 struct eth_device netdev;
94 unsigned short phy_addr;
Bo Shenb1a00062013-04-24 15:59:27 +080095 struct mii_dev *bus;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +010096};
97#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
98
Bo Shend256be22013-04-24 15:59:28 +080099static int macb_is_gem(struct macb_device *macb)
100{
101 return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2;
102}
103
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100104static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
105{
106 unsigned long netctl;
107 unsigned long netstat;
108 unsigned long frame;
109
110 netctl = macb_readl(macb, NCR);
111 netctl |= MACB_BIT(MPE);
112 macb_writel(macb, NCR, netctl);
113
114 frame = (MACB_BF(SOF, 1)
115 | MACB_BF(RW, 1)
116 | MACB_BF(PHYA, macb->phy_addr)
117 | MACB_BF(REGA, reg)
118 | MACB_BF(CODE, 2)
119 | MACB_BF(DATA, value));
120 macb_writel(macb, MAN, frame);
121
122 do {
123 netstat = macb_readl(macb, NSR);
124 } while (!(netstat & MACB_BIT(IDLE)));
125
126 netctl = macb_readl(macb, NCR);
127 netctl &= ~MACB_BIT(MPE);
128 macb_writel(macb, NCR, netctl);
129}
130
131static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
132{
133 unsigned long netctl;
134 unsigned long netstat;
135 unsigned long frame;
136
137 netctl = macb_readl(macb, NCR);
138 netctl |= MACB_BIT(MPE);
139 macb_writel(macb, NCR, netctl);
140
141 frame = (MACB_BF(SOF, 1)
142 | MACB_BF(RW, 2)
143 | MACB_BF(PHYA, macb->phy_addr)
144 | MACB_BF(REGA, reg)
145 | MACB_BF(CODE, 2));
146 macb_writel(macb, MAN, frame);
147
148 do {
149 netstat = macb_readl(macb, NSR);
150 } while (!(netstat & MACB_BIT(IDLE)));
151
152 frame = macb_readl(macb, MAN);
153
154 netctl = macb_readl(macb, NCR);
155 netctl &= ~MACB_BIT(MPE);
156 macb_writel(macb, NCR, netctl);
157
158 return MACB_BFEXT(DATA, frame);
159}
160
Joe Hershberger1b8c18b2013-06-24 19:06:38 -0500161void __weak arch_get_mdio_control(const char *name)
Shiraz Hashim416ce622012-12-13 17:22:52 +0530162{
163 return;
164}
165
Bo Shenb1a00062013-04-24 15:59:27 +0800166#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Semih Hazar0f751d62009-12-17 15:07:15 +0200167
Mike Frysinger5700bb62010-07-27 18:35:08 -0400168int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
Semih Hazar0f751d62009-12-17 15:07:15 +0200169{
170 struct eth_device *dev = eth_get_dev_by_name(devname);
171 struct macb_device *macb = to_macb(dev);
172
Andreas Bießmannceef9832014-05-26 22:55:18 +0200173 if (macb->phy_addr != phy_adr)
Semih Hazar0f751d62009-12-17 15:07:15 +0200174 return -1;
175
Shiraz Hashim416ce622012-12-13 17:22:52 +0530176 arch_get_mdio_control(devname);
Semih Hazar0f751d62009-12-17 15:07:15 +0200177 *value = macb_mdio_read(macb, reg);
178
179 return 0;
180}
181
Mike Frysinger5700bb62010-07-27 18:35:08 -0400182int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
Semih Hazar0f751d62009-12-17 15:07:15 +0200183{
184 struct eth_device *dev = eth_get_dev_by_name(devname);
185 struct macb_device *macb = to_macb(dev);
186
Andreas Bießmannceef9832014-05-26 22:55:18 +0200187 if (macb->phy_addr != phy_adr)
Semih Hazar0f751d62009-12-17 15:07:15 +0200188 return -1;
189
Shiraz Hashim416ce622012-12-13 17:22:52 +0530190 arch_get_mdio_control(devname);
Semih Hazar0f751d62009-12-17 15:07:15 +0200191 macb_mdio_write(macb, reg, value);
192
193 return 0;
194}
195#endif
196
197
Jon Loeliger07d38a12007-07-09 17:30:01 -0500198#if defined(CONFIG_CMD_NET)
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100199
Joe Hershberger9d9a89b2012-05-21 14:45:31 +0000200static int macb_send(struct eth_device *netdev, void *packet, int length)
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100201{
202 struct macb_device *macb = to_macb(netdev);
203 unsigned long paddr, ctrl;
204 unsigned int tx_head = macb->tx_head;
205 int i;
206
207 paddr = dma_map_single(packet, length, DMA_TO_DEVICE);
208
209 ctrl = length & TXBUF_FRMLEN_MASK;
210 ctrl |= TXBUF_FRAME_END;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200211 if (tx_head == (MACB_TX_RING_SIZE - 1)) {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100212 ctrl |= TXBUF_WRAP;
213 macb->tx_head = 0;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200214 } else {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100215 macb->tx_head++;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200216 }
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100217
218 macb->tx_ring[tx_head].ctrl = ctrl;
219 macb->tx_ring[tx_head].addr = paddr;
Haavard Skinnemoen04fcb5d2007-05-02 13:22:38 +0200220 barrier();
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100221 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
222
223 /*
224 * I guess this is necessary because the networking core may
225 * re-use the transmit buffer as soon as we return...
226 */
Andreas Bießmannceef9832014-05-26 22:55:18 +0200227 for (i = 0; i <= MACB_TX_TIMEOUT; i++) {
Haavard Skinnemoen04fcb5d2007-05-02 13:22:38 +0200228 barrier();
229 ctrl = macb->tx_ring[tx_head].ctrl;
230 if (ctrl & TXBUF_USED)
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100231 break;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100232 udelay(1);
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100233 }
234
235 dma_unmap_single(packet, length, paddr);
236
Andreas Bießmannceef9832014-05-26 22:55:18 +0200237 if (i <= MACB_TX_TIMEOUT) {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100238 if (ctrl & TXBUF_UNDERRUN)
239 printf("%s: TX underrun\n", netdev->name);
240 if (ctrl & TXBUF_EXHAUSTED)
241 printf("%s: TX buffers exhausted in mid frame\n",
242 netdev->name);
Haavard Skinnemoen04fcb5d2007-05-02 13:22:38 +0200243 } else {
244 printf("%s: TX timeout\n", netdev->name);
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100245 }
246
247 /* No one cares anyway */
248 return 0;
249}
250
251static void reclaim_rx_buffers(struct macb_device *macb,
252 unsigned int new_tail)
253{
254 unsigned int i;
255
256 i = macb->rx_tail;
257 while (i > new_tail) {
258 macb->rx_ring[i].addr &= ~RXADDR_USED;
259 i++;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200260 if (i > MACB_RX_RING_SIZE)
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100261 i = 0;
262 }
263
264 while (i < new_tail) {
265 macb->rx_ring[i].addr &= ~RXADDR_USED;
266 i++;
267 }
268
Haavard Skinnemoen04fcb5d2007-05-02 13:22:38 +0200269 barrier();
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100270 macb->rx_tail = new_tail;
271}
272
273static int macb_recv(struct eth_device *netdev)
274{
275 struct macb_device *macb = to_macb(netdev);
276 unsigned int rx_tail = macb->rx_tail;
277 void *buffer;
278 int length;
279 int wrapped = 0;
280 u32 status;
281
282 for (;;) {
283 if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED))
284 return -1;
285
286 status = macb->rx_ring[rx_tail].ctrl;
287 if (status & RXBUF_FRAME_START) {
288 if (rx_tail != macb->rx_tail)
289 reclaim_rx_buffers(macb, rx_tail);
290 wrapped = 0;
291 }
292
293 if (status & RXBUF_FRAME_END) {
294 buffer = macb->rx_buffer + 128 * macb->rx_tail;
295 length = status & RXBUF_FRMLEN_MASK;
296 if (wrapped) {
297 unsigned int headlen, taillen;
298
Andreas Bießmannceef9832014-05-26 22:55:18 +0200299 headlen = 128 * (MACB_RX_RING_SIZE
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100300 - macb->rx_tail);
301 taillen = length - headlen;
302 memcpy((void *)NetRxPackets[0],
303 buffer, headlen);
304 memcpy((void *)NetRxPackets[0] + headlen,
305 macb->rx_buffer, taillen);
306 buffer = (void *)NetRxPackets[0];
307 }
308
309 NetReceive(buffer, length);
Andreas Bießmannceef9832014-05-26 22:55:18 +0200310 if (++rx_tail >= MACB_RX_RING_SIZE)
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100311 rx_tail = 0;
312 reclaim_rx_buffers(macb, rx_tail);
313 } else {
Andreas Bießmannceef9832014-05-26 22:55:18 +0200314 if (++rx_tail >= MACB_RX_RING_SIZE) {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100315 wrapped = 1;
316 rx_tail = 0;
317 }
318 }
Haavard Skinnemoen04fcb5d2007-05-02 13:22:38 +0200319 barrier();
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100320 }
321
322 return 0;
323}
324
Haavard Skinnemoenf2134f82007-05-02 13:31:53 +0200325static void macb_phy_reset(struct macb_device *macb)
326{
327 struct eth_device *netdev = &macb->netdev;
328 int i;
329 u16 status, adv;
330
331 adv = ADVERTISE_CSMA | ADVERTISE_ALL;
332 macb_mdio_write(macb, MII_ADVERTISE, adv);
333 printf("%s: Starting autonegotiation...\n", netdev->name);
334 macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
335 | BMCR_ANRESTART));
336
Andreas Bießmannceef9832014-05-26 22:55:18 +0200337 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Haavard Skinnemoenf2134f82007-05-02 13:31:53 +0200338 status = macb_mdio_read(macb, MII_BMSR);
339 if (status & BMSR_ANEGCOMPLETE)
340 break;
341 udelay(100);
342 }
343
344 if (status & BMSR_ANEGCOMPLETE)
345 printf("%s: Autonegotiation complete\n", netdev->name);
346 else
347 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
348 netdev->name, status);
349}
350
Gunnar Rangoyfc01ea12009-01-23 12:56:31 +0100351#ifdef CONFIG_MACB_SEARCH_PHY
352static int macb_phy_find(struct macb_device *macb)
353{
354 int i;
355 u16 phy_id;
356
357 /* Search for PHY... */
358 for (i = 0; i < 32; i++) {
359 macb->phy_addr = i;
360 phy_id = macb_mdio_read(macb, MII_PHYSID1);
361 if (phy_id != 0xffff) {
362 printf("%s: PHY present at %d\n", macb->netdev.name, i);
363 return 1;
364 }
365 }
366
367 /* PHY isn't up to snuff */
Andreas Bießmann6ed0e942012-08-16 01:50:04 +0000368 printf("%s: PHY not found\n", macb->netdev.name);
Gunnar Rangoyfc01ea12009-01-23 12:56:31 +0100369
370 return 0;
371}
372#endif /* CONFIG_MACB_SEARCH_PHY */
373
374
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100375static int macb_phy_init(struct macb_device *macb)
376{
377 struct eth_device *netdev = &macb->netdev;
Bo Shenb1a00062013-04-24 15:59:27 +0800378#ifdef CONFIG_PHYLIB
379 struct phy_device *phydev;
380#endif
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100381 u32 ncfgr;
382 u16 phy_id, status, adv, lpa;
383 int media, speed, duplex;
384 int i;
385
Shiraz Hashim416ce622012-12-13 17:22:52 +0530386 arch_get_mdio_control(netdev->name);
Gunnar Rangoyfc01ea12009-01-23 12:56:31 +0100387#ifdef CONFIG_MACB_SEARCH_PHY
388 /* Auto-detect phy_addr */
Andreas Bießmannceef9832014-05-26 22:55:18 +0200389 if (!macb_phy_find(macb))
Gunnar Rangoyfc01ea12009-01-23 12:56:31 +0100390 return 0;
Gunnar Rangoyfc01ea12009-01-23 12:56:31 +0100391#endif /* CONFIG_MACB_SEARCH_PHY */
392
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100393 /* Check if the PHY is up to snuff... */
394 phy_id = macb_mdio_read(macb, MII_PHYSID1);
395 if (phy_id == 0xffff) {
396 printf("%s: No PHY present\n", netdev->name);
397 return 0;
398 }
399
Bo Shenb1a00062013-04-24 15:59:27 +0800400#ifdef CONFIG_PHYLIB
Bo Shen8314ccd2013-08-19 10:35:47 +0800401 /* need to consider other phy interface mode */
402 phydev = phy_connect(macb->bus, macb->phy_addr, netdev,
403 PHY_INTERFACE_MODE_RGMII);
404 if (!phydev) {
405 printf("phy_connect failed\n");
406 return -ENODEV;
407 }
408
Bo Shenb1a00062013-04-24 15:59:27 +0800409 phy_config(phydev);
410#endif
411
Haavard Skinnemoenf2134f82007-05-02 13:31:53 +0200412 status = macb_mdio_read(macb, MII_BMSR);
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100413 if (!(status & BMSR_LSTATUS)) {
Haavard Skinnemoenf2134f82007-05-02 13:31:53 +0200414 /* Try to re-negotiate if we don't have link already. */
415 macb_phy_reset(macb);
416
Andreas Bießmannceef9832014-05-26 22:55:18 +0200417 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100418 status = macb_mdio_read(macb, MII_BMSR);
419 if (status & BMSR_LSTATUS)
420 break;
Haavard Skinnemoenf2134f82007-05-02 13:31:53 +0200421 udelay(100);
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100422 }
423 }
424
425 if (!(status & BMSR_LSTATUS)) {
426 printf("%s: link down (status: 0x%04x)\n",
427 netdev->name, status);
428 return 0;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100429 }
Bo Shend256be22013-04-24 15:59:28 +0800430
431 /* First check for GMAC */
432 if (macb_is_gem(macb)) {
433 lpa = macb_mdio_read(macb, MII_STAT1000);
434 if (lpa & (1 << 11)) {
435 speed = 1000;
436 duplex = 1;
437 } else {
438 if (lpa & (1 << 10)) {
439 speed = 1000;
440 duplex = 1;
441 } else {
442 speed = 0;
443 }
444 }
445
446 if (speed == 1000) {
447 printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n",
448 netdev->name,
449 speed,
450 duplex ? "full" : "half",
451 lpa);
452
453 ncfgr = macb_readl(macb, NCFGR);
454 ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD));
455 if (speed)
456 ncfgr |= GEM_BIT(GBE);
457 if (duplex)
458 ncfgr |= MACB_BIT(FD);
459 macb_writel(macb, NCFGR, ncfgr);
460
461 return 1;
462 }
463 }
464
465 /* fall back for EMAC checking */
466 adv = macb_mdio_read(macb, MII_ADVERTISE);
467 lpa = macb_mdio_read(macb, MII_LPA);
468 media = mii_nway_result(lpa & adv);
469 speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
470 ? 1 : 0);
471 duplex = (media & ADVERTISE_FULL) ? 1 : 0;
472 printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
473 netdev->name,
474 speed ? "100" : "10",
475 duplex ? "full" : "half",
476 lpa);
477
478 ncfgr = macb_readl(macb, NCFGR);
479 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
480 if (speed)
481 ncfgr |= MACB_BIT(SPD);
482 if (duplex)
483 ncfgr |= MACB_BIT(FD);
484 macb_writel(macb, NCFGR, ncfgr);
485
486 return 1;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100487}
488
489static int macb_init(struct eth_device *netdev, bd_t *bd)
490{
491 struct macb_device *macb = to_macb(netdev);
492 unsigned long paddr;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100493 int i;
494
495 /*
496 * macb_halt should have been called at some point before now,
497 * so we'll assume the controller is idle.
498 */
499
500 /* initialize DMA descriptors */
501 paddr = macb->rx_buffer_dma;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200502 for (i = 0; i < MACB_RX_RING_SIZE; i++) {
503 if (i == (MACB_RX_RING_SIZE - 1))
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100504 paddr |= RXADDR_WRAP;
505 macb->rx_ring[i].addr = paddr;
506 macb->rx_ring[i].ctrl = 0;
507 paddr += 128;
508 }
Andreas Bießmannceef9832014-05-26 22:55:18 +0200509 for (i = 0; i < MACB_TX_RING_SIZE; i++) {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100510 macb->tx_ring[i].addr = 0;
Andreas Bießmannceef9832014-05-26 22:55:18 +0200511 if (i == (MACB_TX_RING_SIZE - 1))
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100512 macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP;
513 else
514 macb->tx_ring[i].ctrl = TXBUF_USED;
515 }
Andreas Bießmannceef9832014-05-26 22:55:18 +0200516 macb->rx_tail = 0;
517 macb->tx_head = 0;
518 macb->tx_tail = 0;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100519
520 macb_writel(macb, RBQP, macb->rx_ring_dma);
521 macb_writel(macb, TBQP, macb->tx_ring_dma);
522
Bo Shend256be22013-04-24 15:59:28 +0800523 if (macb_is_gem(macb)) {
524#ifdef CONFIG_RGMII
525 gem_writel(macb, UR, GEM_BIT(RGMII));
526#else
527 gem_writel(macb, UR, 0);
528#endif
529 } else {
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100530 /* choose RMII or MII mode. This depends on the board */
531#ifdef CONFIG_RMII
Bo Shend8f64b42013-04-24 15:59:26 +0800532#ifdef CONFIG_AT91FAMILY
Stelian Pop7263ef12008-01-03 21:15:56 +0000533 macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
534#else
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100535 macb_writel(macb, USRIO, 0);
Stelian Pop7263ef12008-01-03 21:15:56 +0000536#endif
537#else
Bo Shend8f64b42013-04-24 15:59:26 +0800538#ifdef CONFIG_AT91FAMILY
Stelian Pop7263ef12008-01-03 21:15:56 +0000539 macb_writel(macb, USRIO, MACB_BIT(CLKEN));
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100540#else
541 macb_writel(macb, USRIO, MACB_BIT(MII));
542#endif
Stelian Pop7263ef12008-01-03 21:15:56 +0000543#endif /* CONFIG_RMII */
Bo Shend256be22013-04-24 15:59:28 +0800544 }
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100545
546 if (!macb_phy_init(macb))
Ben Warren422b1a02008-01-09 18:15:53 -0500547 return -1;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100548
549 /* Enable TX and RX */
550 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
551
Ben Warren422b1a02008-01-09 18:15:53 -0500552 return 0;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100553}
554
555static void macb_halt(struct eth_device *netdev)
556{
557 struct macb_device *macb = to_macb(netdev);
558 u32 ncr, tsr;
559
560 /* Halt the controller and wait for any ongoing transmission to end. */
561 ncr = macb_readl(macb, NCR);
562 ncr |= MACB_BIT(THALT);
563 macb_writel(macb, NCR, ncr);
564
565 do {
566 tsr = macb_readl(macb, TSR);
567 } while (tsr & MACB_BIT(TGO));
568
569 /* Disable TX and RX, and clear statistics */
570 macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
571}
572
Ben Warren6bb46792010-06-01 11:55:42 -0700573static int macb_write_hwaddr(struct eth_device *dev)
574{
575 struct macb_device *macb = to_macb(dev);
576 u32 hwaddr_bottom;
577 u16 hwaddr_top;
578
579 /* set hardware address */
andreas.devel@googlemail.com6c169c12011-06-09 02:08:46 +0000580 hwaddr_bottom = dev->enetaddr[0] | dev->enetaddr[1] << 8 |
581 dev->enetaddr[2] << 16 | dev->enetaddr[3] << 24;
Ben Warren6bb46792010-06-01 11:55:42 -0700582 macb_writel(macb, SA1B, hwaddr_bottom);
andreas.devel@googlemail.com6c169c12011-06-09 02:08:46 +0000583 hwaddr_top = dev->enetaddr[4] | dev->enetaddr[5] << 8;
Ben Warren6bb46792010-06-01 11:55:42 -0700584 macb_writel(macb, SA1T, hwaddr_top);
585 return 0;
586}
587
Bo Shend256be22013-04-24 15:59:28 +0800588static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
589{
590 u32 config;
591 unsigned long macb_hz = get_macb_pclk_rate(id);
592
593 if (macb_hz < 20000000)
594 config = MACB_BF(CLK, MACB_CLK_DIV8);
595 else if (macb_hz < 40000000)
596 config = MACB_BF(CLK, MACB_CLK_DIV16);
597 else if (macb_hz < 80000000)
598 config = MACB_BF(CLK, MACB_CLK_DIV32);
599 else
600 config = MACB_BF(CLK, MACB_CLK_DIV64);
601
602 return config;
603}
604
605static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
606{
607 u32 config;
608 unsigned long macb_hz = get_macb_pclk_rate(id);
609
610 if (macb_hz < 20000000)
611 config = GEM_BF(CLK, GEM_CLK_DIV8);
612 else if (macb_hz < 40000000)
613 config = GEM_BF(CLK, GEM_CLK_DIV16);
614 else if (macb_hz < 80000000)
615 config = GEM_BF(CLK, GEM_CLK_DIV32);
616 else if (macb_hz < 120000000)
617 config = GEM_BF(CLK, GEM_CLK_DIV48);
618 else if (macb_hz < 160000000)
619 config = GEM_BF(CLK, GEM_CLK_DIV64);
620 else
621 config = GEM_BF(CLK, GEM_CLK_DIV96);
622
623 return config;
624}
625
Bo Shen32e4f6b2013-09-18 15:07:44 +0800626/*
627 * Get the DMA bus width field of the network configuration register that we
628 * should program. We find the width from decoding the design configuration
629 * register to find the maximum supported data bus width.
630 */
631static u32 macb_dbw(struct macb_device *macb)
632{
633 switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
634 case 4:
635 return GEM_BF(DBW, GEM_DBW128);
636 case 2:
637 return GEM_BF(DBW, GEM_DBW64);
638 case 1:
639 default:
640 return GEM_BF(DBW, GEM_DBW32);
641 }
642}
643
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100644int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
645{
646 struct macb_device *macb;
647 struct eth_device *netdev;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100648 u32 ncfgr;
649
650 macb = malloc(sizeof(struct macb_device));
651 if (!macb) {
652 printf("Error: Failed to allocate memory for MACB%d\n", id);
653 return -1;
654 }
655 memset(macb, 0, sizeof(struct macb_device));
656
657 netdev = &macb->netdev;
658
Andreas Bießmannceef9832014-05-26 22:55:18 +0200659 macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE,
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100660 &macb->rx_buffer_dma);
Andreas Bießmannceef9832014-05-26 22:55:18 +0200661 macb->rx_ring = dma_alloc_coherent(MACB_RX_RING_SIZE
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100662 * sizeof(struct macb_dma_desc),
663 &macb->rx_ring_dma);
Andreas Bießmannceef9832014-05-26 22:55:18 +0200664 macb->tx_ring = dma_alloc_coherent(MACB_TX_RING_SIZE
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100665 * sizeof(struct macb_dma_desc),
666 &macb->tx_ring_dma);
667
668 macb->regs = regs;
669 macb->phy_addr = phy_addr;
670
Bo Shend256be22013-04-24 15:59:28 +0800671 if (macb_is_gem(macb))
672 sprintf(netdev->name, "gmac%d", id);
673 else
674 sprintf(netdev->name, "macb%d", id);
675
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100676 netdev->init = macb_init;
677 netdev->halt = macb_halt;
678 netdev->send = macb_send;
679 netdev->recv = macb_recv;
Ben Warren6bb46792010-06-01 11:55:42 -0700680 netdev->write_hwaddr = macb_write_hwaddr;
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100681
682 /*
683 * Do some basic initialization so that we at least can talk
684 * to the PHY
685 */
Bo Shend256be22013-04-24 15:59:28 +0800686 if (macb_is_gem(macb)) {
687 ncfgr = gem_mdc_clk_div(id, macb);
Bo Shen32e4f6b2013-09-18 15:07:44 +0800688 ncfgr |= macb_dbw(macb);
Bo Shend256be22013-04-24 15:59:28 +0800689 } else {
690 ncfgr = macb_mdc_clk_div(id, macb);
691 }
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100692
693 macb_writel(macb, NCFGR, ncfgr);
694
695 eth_register(netdev);
696
Bo Shenb1a00062013-04-24 15:59:27 +0800697#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Semih Hazar0f751d62009-12-17 15:07:15 +0200698 miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
Bo Shenb1a00062013-04-24 15:59:27 +0800699 macb->bus = miiphy_get_dev_by_name(netdev->name);
Semih Hazar0f751d62009-12-17 15:07:15 +0200700#endif
Haavard Skinnemoen5c1fe1f2006-01-20 10:03:34 +0100701 return 0;
702}
703
Jon Loeliger07d38a12007-07-09 17:30:01 -0500704#endif