]>
Commit | Line | Data |
---|---|---|
5c1fe1ff HS |
1 | /* |
2 | * Copyright (C) 2005-2006 Atmel Corporation | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5c1fe1ff HS |
5 | */ |
6 | #include <common.h> | |
577aa3b3 | 7 | #include <clk.h> |
f1dcc19b | 8 | #include <dm.h> |
5c1fe1ff | 9 | |
5c1fe1ff HS |
10 | /* |
11 | * The u-boot networking stack is a little weird. It seems like the | |
12 | * networking core allocates receive buffers up front without any | |
13 | * regard to the hardware that's supposed to actually receive those | |
14 | * packets. | |
15 | * | |
16 | * The MACB receives packets into 128-byte receive buffers, so the | |
17 | * buffers allocated by the core isn't very practical to use. We'll | |
18 | * allocate our own, but we need one such buffer in case a packet | |
19 | * wraps around the DMA ring so that we have to copy it. | |
20 | * | |
6d0f6bcf | 21 | * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific |
5c1fe1ff HS |
22 | * configuration header. This way, the core allocates one RX buffer |
23 | * and one TX buffer, each of which can hold a ethernet packet of | |
24 | * maximum size. | |
25 | * | |
26 | * For some reason, the networking core unconditionally specifies a | |
27 | * 32-byte packet "alignment" (which really should be called | |
28 | * "padding"). MACB shouldn't need that, but we'll refrain from any | |
29 | * core modifications here... | |
30 | */ | |
31 | ||
32 | #include <net.h> | |
f1dcc19b | 33 | #ifndef CONFIG_DM_ETH |
89973f8a | 34 | #include <netdev.h> |
f1dcc19b | 35 | #endif |
5c1fe1ff | 36 | #include <malloc.h> |
0f751d6e | 37 | #include <miiphy.h> |
5c1fe1ff HS |
38 | |
39 | #include <linux/mii.h> | |
40 | #include <asm/io.h> | |
41 | #include <asm/dma-mapping.h> | |
42 | #include <asm/arch/clk.h> | |
5d97dff0 | 43 | #include <linux/errno.h> |
5c1fe1ff HS |
44 | |
45 | #include "macb.h" | |
46 | ||
a212b66d WY |
47 | DECLARE_GLOBAL_DATA_PTR; |
48 | ||
ceef983b AB |
49 | #define MACB_RX_BUFFER_SIZE 4096 |
50 | #define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128) | |
51 | #define MACB_TX_RING_SIZE 16 | |
52 | #define MACB_TX_TIMEOUT 1000 | |
53 | #define MACB_AUTONEG_TIMEOUT 5000000 | |
5c1fe1ff | 54 | |
4bf56913 WL |
55 | #ifdef CONFIG_MACB_ZYNQ |
56 | /* INCR4 AHB bursts */ | |
57 | #define MACB_ZYNQ_GEM_DMACR_BLENGTH 0x00000004 | |
58 | /* Use full configured addressable space (8 Kb) */ | |
59 | #define MACB_ZYNQ_GEM_DMACR_RXSIZE 0x00000300 | |
60 | /* Use full configured addressable space (4 Kb) */ | |
61 | #define MACB_ZYNQ_GEM_DMACR_TXSIZE 0x00000400 | |
62 | /* Set RXBUF with use of 128 byte */ | |
63 | #define MACB_ZYNQ_GEM_DMACR_RXBUF 0x00020000 | |
64 | #define MACB_ZYNQ_GEM_DMACR_INIT \ | |
65 | (MACB_ZYNQ_GEM_DMACR_BLENGTH | \ | |
66 | MACB_ZYNQ_GEM_DMACR_RXSIZE | \ | |
67 | MACB_ZYNQ_GEM_DMACR_TXSIZE | \ | |
68 | MACB_ZYNQ_GEM_DMACR_RXBUF) | |
69 | #endif | |
70 | ||
5c1fe1ff HS |
71 | struct macb_dma_desc { |
72 | u32 addr; | |
73 | u32 ctrl; | |
74 | }; | |
75 | ||
5ae0e382 WJ |
76 | #define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) |
77 | #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) | |
78 | #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) | |
ade4ea4d | 79 | #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) |
5ae0e382 | 80 | |
5c1fe1ff HS |
81 | #define RXADDR_USED 0x00000001 |
82 | #define RXADDR_WRAP 0x00000002 | |
83 | ||
84 | #define RXBUF_FRMLEN_MASK 0x00000fff | |
85 | #define RXBUF_FRAME_START 0x00004000 | |
86 | #define RXBUF_FRAME_END 0x00008000 | |
87 | #define RXBUF_TYPEID_MATCH 0x00400000 | |
88 | #define RXBUF_ADDR4_MATCH 0x00800000 | |
89 | #define RXBUF_ADDR3_MATCH 0x01000000 | |
90 | #define RXBUF_ADDR2_MATCH 0x02000000 | |
91 | #define RXBUF_ADDR1_MATCH 0x04000000 | |
92 | #define RXBUF_BROADCAST 0x80000000 | |
93 | ||
94 | #define TXBUF_FRMLEN_MASK 0x000007ff | |
95 | #define TXBUF_FRAME_END 0x00008000 | |
96 | #define TXBUF_NOCRC 0x00010000 | |
97 | #define TXBUF_EXHAUSTED 0x08000000 | |
98 | #define TXBUF_UNDERRUN 0x10000000 | |
99 | #define TXBUF_MAXRETRY 0x20000000 | |
100 | #define TXBUF_WRAP 0x40000000 | |
101 | #define TXBUF_USED 0x80000000 | |
102 | ||
103 | struct macb_device { | |
104 | void *regs; | |
105 | ||
106 | unsigned int rx_tail; | |
107 | unsigned int tx_head; | |
108 | unsigned int tx_tail; | |
d5555b70 SG |
109 | unsigned int next_rx_tail; |
110 | bool wrapped; | |
5c1fe1ff HS |
111 | |
112 | void *rx_buffer; | |
113 | void *tx_buffer; | |
114 | struct macb_dma_desc *rx_ring; | |
115 | struct macb_dma_desc *tx_ring; | |
116 | ||
117 | unsigned long rx_buffer_dma; | |
118 | unsigned long rx_ring_dma; | |
119 | unsigned long tx_ring_dma; | |
120 | ||
ade4ea4d WJ |
121 | struct macb_dma_desc *dummy_desc; |
122 | unsigned long dummy_desc_dma; | |
123 | ||
5c1fe1ff | 124 | const struct device *dev; |
f1dcc19b | 125 | #ifndef CONFIG_DM_ETH |
5c1fe1ff | 126 | struct eth_device netdev; |
f1dcc19b | 127 | #endif |
5c1fe1ff | 128 | unsigned short phy_addr; |
b1a0006e | 129 | struct mii_dev *bus; |
1870d4d7 WY |
130 | #ifdef CONFIG_PHYLIB |
131 | struct phy_device *phydev; | |
132 | #endif | |
a212b66d WY |
133 | |
134 | #ifdef CONFIG_DM_ETH | |
3fd2b3aa | 135 | #ifdef CONFIG_CLK |
577aa3b3 | 136 | unsigned long pclk_rate; |
3fd2b3aa | 137 | #endif |
a212b66d WY |
138 | phy_interface_t phy_interface; |
139 | #endif | |
5c1fe1ff | 140 | }; |
f1dcc19b | 141 | #ifndef CONFIG_DM_ETH |
5c1fe1ff | 142 | #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) |
f1dcc19b | 143 | #endif |
5c1fe1ff | 144 | |
d256be29 BS |
145 | static int macb_is_gem(struct macb_device *macb) |
146 | { | |
147 | return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; | |
148 | } | |
149 | ||
75b03cf1 GC |
150 | #ifndef cpu_is_sama5d2 |
151 | #define cpu_is_sama5d2() 0 | |
152 | #endif | |
153 | ||
154 | #ifndef cpu_is_sama5d4 | |
155 | #define cpu_is_sama5d4() 0 | |
156 | #endif | |
157 | ||
158 | static int gem_is_gigabit_capable(struct macb_device *macb) | |
159 | { | |
160 | /* | |
1cc0a9f4 | 161 | * The GEM controllers embedded in SAMA5D2 and SAMA5D4 are |
75b03cf1 GC |
162 | * configured to support only 10/100. |
163 | */ | |
164 | return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4(); | |
165 | } | |
166 | ||
5c1fe1ff HS |
167 | static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) |
168 | { | |
169 | unsigned long netctl; | |
170 | unsigned long netstat; | |
171 | unsigned long frame; | |
172 | ||
173 | netctl = macb_readl(macb, NCR); | |
174 | netctl |= MACB_BIT(MPE); | |
175 | macb_writel(macb, NCR, netctl); | |
176 | ||
177 | frame = (MACB_BF(SOF, 1) | |
178 | | MACB_BF(RW, 1) | |
179 | | MACB_BF(PHYA, macb->phy_addr) | |
180 | | MACB_BF(REGA, reg) | |
181 | | MACB_BF(CODE, 2) | |
182 | | MACB_BF(DATA, value)); | |
183 | macb_writel(macb, MAN, frame); | |
184 | ||
185 | do { | |
186 | netstat = macb_readl(macb, NSR); | |
187 | } while (!(netstat & MACB_BIT(IDLE))); | |
188 | ||
189 | netctl = macb_readl(macb, NCR); | |
190 | netctl &= ~MACB_BIT(MPE); | |
191 | macb_writel(macb, NCR, netctl); | |
192 | } | |
193 | ||
194 | static u16 macb_mdio_read(struct macb_device *macb, u8 reg) | |
195 | { | |
196 | unsigned long netctl; | |
197 | unsigned long netstat; | |
198 | unsigned long frame; | |
199 | ||
200 | netctl = macb_readl(macb, NCR); | |
201 | netctl |= MACB_BIT(MPE); | |
202 | macb_writel(macb, NCR, netctl); | |
203 | ||
204 | frame = (MACB_BF(SOF, 1) | |
205 | | MACB_BF(RW, 2) | |
206 | | MACB_BF(PHYA, macb->phy_addr) | |
207 | | MACB_BF(REGA, reg) | |
208 | | MACB_BF(CODE, 2)); | |
209 | macb_writel(macb, MAN, frame); | |
210 | ||
211 | do { | |
212 | netstat = macb_readl(macb, NSR); | |
213 | } while (!(netstat & MACB_BIT(IDLE))); | |
214 | ||
215 | frame = macb_readl(macb, MAN); | |
216 | ||
217 | netctl = macb_readl(macb, NCR); | |
218 | netctl &= ~MACB_BIT(MPE); | |
219 | macb_writel(macb, NCR, netctl); | |
220 | ||
221 | return MACB_BFEXT(DATA, frame); | |
222 | } | |
223 | ||
1b8c18b9 | 224 | void __weak arch_get_mdio_control(const char *name) |
416ce623 SH |
225 | { |
226 | return; | |
227 | } | |
228 | ||
b1a0006e | 229 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) |
0f751d6e | 230 | |
5a49f174 | 231 | int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg) |
0f751d6e | 232 | { |
5a49f174 | 233 | u16 value = 0; |
f1dcc19b | 234 | #ifdef CONFIG_DM_ETH |
5a49f174 | 235 | struct udevice *dev = eth_get_dev_by_name(bus->name); |
f1dcc19b SG |
236 | struct macb_device *macb = dev_get_priv(dev); |
237 | #else | |
5a49f174 | 238 | struct eth_device *dev = eth_get_dev_by_name(bus->name); |
0f751d6e | 239 | struct macb_device *macb = to_macb(dev); |
f1dcc19b | 240 | #endif |
0f751d6e | 241 | |
ceef983b | 242 | if (macb->phy_addr != phy_adr) |
0f751d6e SH |
243 | return -1; |
244 | ||
5a49f174 JH |
245 | arch_get_mdio_control(bus->name); |
246 | value = macb_mdio_read(macb, reg); | |
0f751d6e | 247 | |
5a49f174 | 248 | return value; |
0f751d6e SH |
249 | } |
250 | ||
5a49f174 JH |
251 | int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg, |
252 | u16 value) | |
0f751d6e | 253 | { |
f1dcc19b | 254 | #ifdef CONFIG_DM_ETH |
5a49f174 | 255 | struct udevice *dev = eth_get_dev_by_name(bus->name); |
f1dcc19b SG |
256 | struct macb_device *macb = dev_get_priv(dev); |
257 | #else | |
5a49f174 | 258 | struct eth_device *dev = eth_get_dev_by_name(bus->name); |
0f751d6e | 259 | struct macb_device *macb = to_macb(dev); |
f1dcc19b | 260 | #endif |
0f751d6e | 261 | |
ceef983b | 262 | if (macb->phy_addr != phy_adr) |
0f751d6e SH |
263 | return -1; |
264 | ||
5a49f174 | 265 | arch_get_mdio_control(bus->name); |
0f751d6e SH |
266 | macb_mdio_write(macb, reg, value); |
267 | ||
268 | return 0; | |
269 | } | |
270 | #endif | |
271 | ||
5ae0e382 WJ |
272 | #define RX 1 |
273 | #define TX 0 | |
274 | static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) | |
275 | { | |
276 | if (rx) | |
592a7495 HS |
277 | invalidate_dcache_range(macb->rx_ring_dma, |
278 | ALIGN(macb->rx_ring_dma + MACB_RX_DMA_DESC_SIZE, | |
279 | PKTALIGN)); | |
5ae0e382 | 280 | else |
592a7495 HS |
281 | invalidate_dcache_range(macb->tx_ring_dma, |
282 | ALIGN(macb->tx_ring_dma + MACB_TX_DMA_DESC_SIZE, | |
283 | PKTALIGN)); | |
5ae0e382 WJ |
284 | } |
285 | ||
286 | static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) | |
287 | { | |
288 | if (rx) | |
289 | flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + | |
592a7495 | 290 | ALIGN(MACB_RX_DMA_DESC_SIZE, PKTALIGN)); |
5ae0e382 WJ |
291 | else |
292 | flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + | |
592a7495 | 293 | ALIGN(MACB_TX_DMA_DESC_SIZE, PKTALIGN)); |
5ae0e382 WJ |
294 | } |
295 | ||
296 | static inline void macb_flush_rx_buffer(struct macb_device *macb) | |
297 | { | |
298 | flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + | |
592a7495 | 299 | ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); |
5ae0e382 WJ |
300 | } |
301 | ||
302 | static inline void macb_invalidate_rx_buffer(struct macb_device *macb) | |
303 | { | |
304 | invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + | |
592a7495 | 305 | ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); |
5ae0e382 | 306 | } |
0f751d6e | 307 | |
07d38a17 | 308 | #if defined(CONFIG_CMD_NET) |
5c1fe1ff | 309 | |
d5555b70 SG |
310 | static int _macb_send(struct macb_device *macb, const char *name, void *packet, |
311 | int length) | |
5c1fe1ff | 312 | { |
5c1fe1ff HS |
313 | unsigned long paddr, ctrl; |
314 | unsigned int tx_head = macb->tx_head; | |
315 | int i; | |
316 | ||
317 | paddr = dma_map_single(packet, length, DMA_TO_DEVICE); | |
318 | ||
319 | ctrl = length & TXBUF_FRMLEN_MASK; | |
320 | ctrl |= TXBUF_FRAME_END; | |
ceef983b | 321 | if (tx_head == (MACB_TX_RING_SIZE - 1)) { |
5c1fe1ff HS |
322 | ctrl |= TXBUF_WRAP; |
323 | macb->tx_head = 0; | |
ceef983b | 324 | } else { |
5c1fe1ff | 325 | macb->tx_head++; |
ceef983b | 326 | } |
5c1fe1ff HS |
327 | |
328 | macb->tx_ring[tx_head].ctrl = ctrl; | |
329 | macb->tx_ring[tx_head].addr = paddr; | |
04fcb5d3 | 330 | barrier(); |
5ae0e382 WJ |
331 | macb_flush_ring_desc(macb, TX); |
332 | /* Do we need check paddr and length is dcache line aligned? */ | |
f589f8cc | 333 | flush_dcache_range(paddr, paddr + ALIGN(length, ARCH_DMA_MINALIGN)); |
5c1fe1ff HS |
334 | macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); |
335 | ||
336 | /* | |
337 | * I guess this is necessary because the networking core may | |
338 | * re-use the transmit buffer as soon as we return... | |
339 | */ | |
ceef983b | 340 | for (i = 0; i <= MACB_TX_TIMEOUT; i++) { |
04fcb5d3 | 341 | barrier(); |
5ae0e382 | 342 | macb_invalidate_ring_desc(macb, TX); |
04fcb5d3 HS |
343 | ctrl = macb->tx_ring[tx_head].ctrl; |
344 | if (ctrl & TXBUF_USED) | |
5c1fe1ff | 345 | break; |
5c1fe1ff | 346 | udelay(1); |
5c1fe1ff HS |
347 | } |
348 | ||
349 | dma_unmap_single(packet, length, paddr); | |
350 | ||
ceef983b | 351 | if (i <= MACB_TX_TIMEOUT) { |
5c1fe1ff | 352 | if (ctrl & TXBUF_UNDERRUN) |
d5555b70 | 353 | printf("%s: TX underrun\n", name); |
5c1fe1ff | 354 | if (ctrl & TXBUF_EXHAUSTED) |
d5555b70 | 355 | printf("%s: TX buffers exhausted in mid frame\n", name); |
04fcb5d3 | 356 | } else { |
d5555b70 | 357 | printf("%s: TX timeout\n", name); |
5c1fe1ff HS |
358 | } |
359 | ||
360 | /* No one cares anyway */ | |
361 | return 0; | |
362 | } | |
363 | ||
364 | static void reclaim_rx_buffers(struct macb_device *macb, | |
365 | unsigned int new_tail) | |
366 | { | |
367 | unsigned int i; | |
368 | ||
369 | i = macb->rx_tail; | |
5ae0e382 WJ |
370 | |
371 | macb_invalidate_ring_desc(macb, RX); | |
5c1fe1ff HS |
372 | while (i > new_tail) { |
373 | macb->rx_ring[i].addr &= ~RXADDR_USED; | |
374 | i++; | |
ceef983b | 375 | if (i > MACB_RX_RING_SIZE) |
5c1fe1ff HS |
376 | i = 0; |
377 | } | |
378 | ||
379 | while (i < new_tail) { | |
380 | macb->rx_ring[i].addr &= ~RXADDR_USED; | |
381 | i++; | |
382 | } | |
383 | ||
04fcb5d3 | 384 | barrier(); |
5ae0e382 | 385 | macb_flush_ring_desc(macb, RX); |
5c1fe1ff HS |
386 | macb->rx_tail = new_tail; |
387 | } | |
388 | ||
d5555b70 | 389 | static int _macb_recv(struct macb_device *macb, uchar **packetp) |
5c1fe1ff | 390 | { |
d5555b70 | 391 | unsigned int next_rx_tail = macb->next_rx_tail; |
5c1fe1ff HS |
392 | void *buffer; |
393 | int length; | |
5c1fe1ff HS |
394 | u32 status; |
395 | ||
d5555b70 | 396 | macb->wrapped = false; |
5c1fe1ff | 397 | for (;;) { |
5ae0e382 WJ |
398 | macb_invalidate_ring_desc(macb, RX); |
399 | ||
d5555b70 SG |
400 | if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED)) |
401 | return -EAGAIN; | |
5c1fe1ff | 402 | |
d5555b70 | 403 | status = macb->rx_ring[next_rx_tail].ctrl; |
5c1fe1ff | 404 | if (status & RXBUF_FRAME_START) { |
d5555b70 SG |
405 | if (next_rx_tail != macb->rx_tail) |
406 | reclaim_rx_buffers(macb, next_rx_tail); | |
407 | macb->wrapped = false; | |
5c1fe1ff HS |
408 | } |
409 | ||
410 | if (status & RXBUF_FRAME_END) { | |
411 | buffer = macb->rx_buffer + 128 * macb->rx_tail; | |
412 | length = status & RXBUF_FRMLEN_MASK; | |
5ae0e382 WJ |
413 | |
414 | macb_invalidate_rx_buffer(macb); | |
d5555b70 | 415 | if (macb->wrapped) { |
5c1fe1ff HS |
416 | unsigned int headlen, taillen; |
417 | ||
ceef983b | 418 | headlen = 128 * (MACB_RX_RING_SIZE |
5c1fe1ff HS |
419 | - macb->rx_tail); |
420 | taillen = length - headlen; | |
1fd92db8 | 421 | memcpy((void *)net_rx_packets[0], |
5c1fe1ff | 422 | buffer, headlen); |
1fd92db8 | 423 | memcpy((void *)net_rx_packets[0] + headlen, |
5c1fe1ff | 424 | macb->rx_buffer, taillen); |
d5555b70 SG |
425 | *packetp = (void *)net_rx_packets[0]; |
426 | } else { | |
427 | *packetp = buffer; | |
5c1fe1ff HS |
428 | } |
429 | ||
d5555b70 SG |
430 | if (++next_rx_tail >= MACB_RX_RING_SIZE) |
431 | next_rx_tail = 0; | |
432 | macb->next_rx_tail = next_rx_tail; | |
433 | return length; | |
5c1fe1ff | 434 | } else { |
d5555b70 SG |
435 | if (++next_rx_tail >= MACB_RX_RING_SIZE) { |
436 | macb->wrapped = true; | |
437 | next_rx_tail = 0; | |
5c1fe1ff HS |
438 | } |
439 | } | |
04fcb5d3 | 440 | barrier(); |
5c1fe1ff | 441 | } |
5c1fe1ff HS |
442 | } |
443 | ||
d5555b70 | 444 | static void macb_phy_reset(struct macb_device *macb, const char *name) |
5c1fe1ff | 445 | { |
5c1fe1ff | 446 | int i; |
f2134f8e | 447 | u16 status, adv; |
5c1fe1ff HS |
448 | |
449 | adv = ADVERTISE_CSMA | ADVERTISE_ALL; | |
450 | macb_mdio_write(macb, MII_ADVERTISE, adv); | |
d5555b70 | 451 | printf("%s: Starting autonegotiation...\n", name); |
5c1fe1ff HS |
452 | macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE |
453 | | BMCR_ANRESTART)); | |
454 | ||
ceef983b | 455 | for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { |
5c1fe1ff HS |
456 | status = macb_mdio_read(macb, MII_BMSR); |
457 | if (status & BMSR_ANEGCOMPLETE) | |
458 | break; | |
459 | udelay(100); | |
460 | } | |
461 | ||
462 | if (status & BMSR_ANEGCOMPLETE) | |
d5555b70 | 463 | printf("%s: Autonegotiation complete\n", name); |
5c1fe1ff HS |
464 | else |
465 | printf("%s: Autonegotiation timed out (status=0x%04x)\n", | |
d5555b70 | 466 | name, status); |
f2134f8e | 467 | } |
5c1fe1ff | 468 | |
a212b66d | 469 | static int macb_phy_find(struct macb_device *macb, const char *name) |
fc01ea1e GR |
470 | { |
471 | int i; | |
472 | u16 phy_id; | |
473 | ||
474 | /* Search for PHY... */ | |
475 | for (i = 0; i < 32; i++) { | |
476 | macb->phy_addr = i; | |
477 | phy_id = macb_mdio_read(macb, MII_PHYSID1); | |
478 | if (phy_id != 0xffff) { | |
a212b66d | 479 | printf("%s: PHY present at %d\n", name, i); |
4bf56913 | 480 | return 0; |
fc01ea1e GR |
481 | } |
482 | } | |
483 | ||
484 | /* PHY isn't up to snuff */ | |
a212b66d | 485 | printf("%s: PHY not found\n", name); |
fc01ea1e | 486 | |
4bf56913 WL |
487 | return -ENODEV; |
488 | } | |
489 | ||
490 | /** | |
491 | * macb_linkspd_cb - Linkspeed change callback function | |
492 | * @regs: Base Register of MACB devices | |
493 | * @speed: Linkspeed | |
494 | * Returns 0 when operation success and negative errno number | |
495 | * when operation failed. | |
496 | */ | |
497 | int __weak macb_linkspd_cb(void *regs, unsigned int speed) | |
498 | { | |
fc01ea1e GR |
499 | return 0; |
500 | } | |
fc01ea1e | 501 | |
a212b66d WY |
502 | #ifdef CONFIG_DM_ETH |
503 | static int macb_phy_init(struct udevice *dev, const char *name) | |
504 | #else | |
d5555b70 | 505 | static int macb_phy_init(struct macb_device *macb, const char *name) |
a212b66d | 506 | #endif |
f2134f8e | 507 | { |
a212b66d WY |
508 | #ifdef CONFIG_DM_ETH |
509 | struct macb_device *macb = dev_get_priv(dev); | |
b1a0006e | 510 | #endif |
f2134f8e HS |
511 | u32 ncfgr; |
512 | u16 phy_id, status, adv, lpa; | |
513 | int media, speed, duplex; | |
4bf56913 | 514 | int ret; |
f2134f8e HS |
515 | int i; |
516 | ||
d5555b70 | 517 | arch_get_mdio_control(name); |
fc01ea1e | 518 | /* Auto-detect phy_addr */ |
4bf56913 WL |
519 | ret = macb_phy_find(macb, name); |
520 | if (ret) | |
521 | return ret; | |
fc01ea1e | 522 | |
f2134f8e HS |
523 | /* Check if the PHY is up to snuff... */ |
524 | phy_id = macb_mdio_read(macb, MII_PHYSID1); | |
525 | if (phy_id == 0xffff) { | |
d5555b70 | 526 | printf("%s: No PHY present\n", name); |
4bf56913 | 527 | return -ENODEV; |
f2134f8e HS |
528 | } |
529 | ||
b1a0006e | 530 | #ifdef CONFIG_PHYLIB |
a212b66d | 531 | #ifdef CONFIG_DM_ETH |
1870d4d7 | 532 | macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev, |
a212b66d WY |
533 | macb->phy_interface); |
534 | #else | |
8314ccd8 | 535 | /* need to consider other phy interface mode */ |
1870d4d7 | 536 | macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, |
8314ccd8 | 537 | PHY_INTERFACE_MODE_RGMII); |
a212b66d | 538 | #endif |
1870d4d7 | 539 | if (!macb->phydev) { |
8314ccd8 BS |
540 | printf("phy_connect failed\n"); |
541 | return -ENODEV; | |
542 | } | |
543 | ||
1870d4d7 | 544 | phy_config(macb->phydev); |
b1a0006e BS |
545 | #endif |
546 | ||
f2134f8e | 547 | status = macb_mdio_read(macb, MII_BMSR); |
5c1fe1ff | 548 | if (!(status & BMSR_LSTATUS)) { |
f2134f8e | 549 | /* Try to re-negotiate if we don't have link already. */ |
d5555b70 | 550 | macb_phy_reset(macb, name); |
f2134f8e | 551 | |
ceef983b | 552 | for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { |
5c1fe1ff HS |
553 | status = macb_mdio_read(macb, MII_BMSR); |
554 | if (status & BMSR_LSTATUS) | |
555 | break; | |
f2134f8e | 556 | udelay(100); |
5c1fe1ff HS |
557 | } |
558 | } | |
559 | ||
560 | if (!(status & BMSR_LSTATUS)) { | |
561 | printf("%s: link down (status: 0x%04x)\n", | |
d5555b70 | 562 | name, status); |
4bf56913 | 563 | return -ENETDOWN; |
5c1fe1ff | 564 | } |
d256be29 | 565 | |
75b03cf1 GC |
566 | /* First check for GMAC and that it is GiB capable */ |
567 | if (gem_is_gigabit_capable(macb)) { | |
d256be29 | 568 | lpa = macb_mdio_read(macb, MII_STAT1000); |
d256be29 | 569 | |
47609577 AB |
570 | if (lpa & (LPA_1000FULL | LPA_1000HALF)) { |
571 | duplex = ((lpa & LPA_1000FULL) ? 1 : 0); | |
572 | ||
573 | printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n", | |
d5555b70 | 574 | name, |
d256be29 BS |
575 | duplex ? "full" : "half", |
576 | lpa); | |
577 | ||
578 | ncfgr = macb_readl(macb, NCFGR); | |
47609577 AB |
579 | ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); |
580 | ncfgr |= GEM_BIT(GBE); | |
581 | ||
d256be29 BS |
582 | if (duplex) |
583 | ncfgr |= MACB_BIT(FD); | |
47609577 | 584 | |
d256be29 BS |
585 | macb_writel(macb, NCFGR, ncfgr); |
586 | ||
4bf56913 WL |
587 | ret = macb_linkspd_cb(macb->regs, _1000BASET); |
588 | if (ret) | |
589 | return ret; | |
590 | ||
591 | return 0; | |
d256be29 BS |
592 | } |
593 | } | |
594 | ||
595 | /* fall back for EMAC checking */ | |
596 | adv = macb_mdio_read(macb, MII_ADVERTISE); | |
597 | lpa = macb_mdio_read(macb, MII_LPA); | |
598 | media = mii_nway_result(lpa & adv); | |
599 | speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) | |
600 | ? 1 : 0); | |
601 | duplex = (media & ADVERTISE_FULL) ? 1 : 0; | |
602 | printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", | |
d5555b70 | 603 | name, |
d256be29 BS |
604 | speed ? "100" : "10", |
605 | duplex ? "full" : "half", | |
606 | lpa); | |
607 | ||
608 | ncfgr = macb_readl(macb, NCFGR); | |
c83cb5f6 | 609 | ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); |
4bf56913 | 610 | if (speed) { |
d256be29 | 611 | ncfgr |= MACB_BIT(SPD); |
4bf56913 WL |
612 | ret = macb_linkspd_cb(macb->regs, _100BASET); |
613 | } else { | |
614 | ret = macb_linkspd_cb(macb->regs, _10BASET); | |
615 | } | |
616 | ||
617 | if (ret) | |
618 | return ret; | |
619 | ||
d256be29 BS |
620 | if (duplex) |
621 | ncfgr |= MACB_BIT(FD); | |
622 | macb_writel(macb, NCFGR, ncfgr); | |
623 | ||
4bf56913 | 624 | return 0; |
5c1fe1ff HS |
625 | } |
626 | ||
ade4ea4d WJ |
627 | static int gmac_init_multi_queues(struct macb_device *macb) |
628 | { | |
629 | int i, num_queues = 1; | |
630 | u32 queue_mask; | |
631 | ||
632 | /* bit 0 is never set but queue 0 always exists */ | |
633 | queue_mask = gem_readl(macb, DCFG6) & 0xff; | |
634 | queue_mask |= 0x1; | |
635 | ||
636 | for (i = 1; i < MACB_MAX_QUEUES; i++) | |
637 | if (queue_mask & (1 << i)) | |
638 | num_queues++; | |
639 | ||
640 | macb->dummy_desc->ctrl = TXBUF_USED; | |
641 | macb->dummy_desc->addr = 0; | |
642 | flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + | |
592a7495 | 643 | ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN)); |
ade4ea4d WJ |
644 | |
645 | for (i = 1; i < num_queues; i++) | |
646 | gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); | |
647 | ||
648 | return 0; | |
649 | } | |
650 | ||
a212b66d WY |
651 | #ifdef CONFIG_DM_ETH |
652 | static int _macb_init(struct udevice *dev, const char *name) | |
653 | #else | |
d5555b70 | 654 | static int _macb_init(struct macb_device *macb, const char *name) |
a212b66d | 655 | #endif |
5c1fe1ff | 656 | { |
a212b66d WY |
657 | #ifdef CONFIG_DM_ETH |
658 | struct macb_device *macb = dev_get_priv(dev); | |
659 | #endif | |
5c1fe1ff | 660 | unsigned long paddr; |
4bf56913 | 661 | int ret; |
5c1fe1ff HS |
662 | int i; |
663 | ||
664 | /* | |
665 | * macb_halt should have been called at some point before now, | |
666 | * so we'll assume the controller is idle. | |
667 | */ | |
668 | ||
669 | /* initialize DMA descriptors */ | |
670 | paddr = macb->rx_buffer_dma; | |
ceef983b AB |
671 | for (i = 0; i < MACB_RX_RING_SIZE; i++) { |
672 | if (i == (MACB_RX_RING_SIZE - 1)) | |
5c1fe1ff HS |
673 | paddr |= RXADDR_WRAP; |
674 | macb->rx_ring[i].addr = paddr; | |
675 | macb->rx_ring[i].ctrl = 0; | |
676 | paddr += 128; | |
677 | } | |
5ae0e382 WJ |
678 | macb_flush_ring_desc(macb, RX); |
679 | macb_flush_rx_buffer(macb); | |
680 | ||
ceef983b | 681 | for (i = 0; i < MACB_TX_RING_SIZE; i++) { |
5c1fe1ff | 682 | macb->tx_ring[i].addr = 0; |
ceef983b | 683 | if (i == (MACB_TX_RING_SIZE - 1)) |
5c1fe1ff HS |
684 | macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; |
685 | else | |
686 | macb->tx_ring[i].ctrl = TXBUF_USED; | |
687 | } | |
5ae0e382 WJ |
688 | macb_flush_ring_desc(macb, TX); |
689 | ||
ceef983b AB |
690 | macb->rx_tail = 0; |
691 | macb->tx_head = 0; | |
692 | macb->tx_tail = 0; | |
d5555b70 | 693 | macb->next_rx_tail = 0; |
5c1fe1ff | 694 | |
4bf56913 WL |
695 | #ifdef CONFIG_MACB_ZYNQ |
696 | macb_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT); | |
697 | #endif | |
698 | ||
5c1fe1ff HS |
699 | macb_writel(macb, RBQP, macb->rx_ring_dma); |
700 | macb_writel(macb, TBQP, macb->tx_ring_dma); | |
701 | ||
d256be29 | 702 | if (macb_is_gem(macb)) { |
ade4ea4d WJ |
703 | /* Check the multi queue and initialize the queue for tx */ |
704 | gmac_init_multi_queues(macb); | |
705 | ||
cabf61ce BS |
706 | /* |
707 | * When the GMAC IP with GE feature, this bit is used to | |
708 | * select interface between RGMII and GMII. | |
709 | * When the GMAC IP without GE feature, this bit is used | |
710 | * to select interface between RMII and MII. | |
711 | */ | |
a212b66d | 712 | #ifdef CONFIG_DM_ETH |
6de046ea WY |
713 | if ((macb->phy_interface == PHY_INTERFACE_MODE_RMII) || |
714 | (macb->phy_interface == PHY_INTERFACE_MODE_RGMII)) | |
a212b66d WY |
715 | gem_writel(macb, UR, GEM_BIT(RGMII)); |
716 | else | |
717 | gem_writel(macb, UR, 0); | |
718 | #else | |
cabf61ce | 719 | #if defined(CONFIG_RGMII) || defined(CONFIG_RMII) |
d256be29 BS |
720 | gem_writel(macb, UR, GEM_BIT(RGMII)); |
721 | #else | |
722 | gem_writel(macb, UR, 0); | |
a212b66d | 723 | #endif |
d256be29 BS |
724 | #endif |
725 | } else { | |
5c1fe1ff | 726 | /* choose RMII or MII mode. This depends on the board */ |
a212b66d WY |
727 | #ifdef CONFIG_DM_ETH |
728 | #ifdef CONFIG_AT91FAMILY | |
729 | if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) { | |
730 | macb_writel(macb, USRIO, | |
731 | MACB_BIT(RMII) | MACB_BIT(CLKEN)); | |
732 | } else { | |
733 | macb_writel(macb, USRIO, MACB_BIT(CLKEN)); | |
734 | } | |
735 | #else | |
736 | if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) | |
737 | macb_writel(macb, USRIO, 0); | |
738 | else | |
739 | macb_writel(macb, USRIO, MACB_BIT(MII)); | |
740 | #endif | |
741 | #else | |
5c1fe1ff | 742 | #ifdef CONFIG_RMII |
d8f64b44 | 743 | #ifdef CONFIG_AT91FAMILY |
7263ef19 SP |
744 | macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); |
745 | #else | |
5c1fe1ff | 746 | macb_writel(macb, USRIO, 0); |
7263ef19 SP |
747 | #endif |
748 | #else | |
d8f64b44 | 749 | #ifdef CONFIG_AT91FAMILY |
7263ef19 | 750 | macb_writel(macb, USRIO, MACB_BIT(CLKEN)); |
5c1fe1ff HS |
751 | #else |
752 | macb_writel(macb, USRIO, MACB_BIT(MII)); | |
753 | #endif | |
7263ef19 | 754 | #endif /* CONFIG_RMII */ |
a212b66d | 755 | #endif |
d256be29 | 756 | } |
5c1fe1ff | 757 | |
a212b66d | 758 | #ifdef CONFIG_DM_ETH |
4bf56913 | 759 | ret = macb_phy_init(dev, name); |
a212b66d | 760 | #else |
4bf56913 | 761 | ret = macb_phy_init(macb, name); |
a212b66d | 762 | #endif |
4bf56913 WL |
763 | if (ret) |
764 | return ret; | |
5c1fe1ff HS |
765 | |
766 | /* Enable TX and RX */ | |
767 | macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); | |
768 | ||
422b1a01 | 769 | return 0; |
5c1fe1ff HS |
770 | } |
771 | ||
d5555b70 | 772 | static void _macb_halt(struct macb_device *macb) |
5c1fe1ff | 773 | { |
5c1fe1ff HS |
774 | u32 ncr, tsr; |
775 | ||
776 | /* Halt the controller and wait for any ongoing transmission to end. */ | |
777 | ncr = macb_readl(macb, NCR); | |
778 | ncr |= MACB_BIT(THALT); | |
779 | macb_writel(macb, NCR, ncr); | |
780 | ||
781 | do { | |
782 | tsr = macb_readl(macb, TSR); | |
783 | } while (tsr & MACB_BIT(TGO)); | |
784 | ||
785 | /* Disable TX and RX, and clear statistics */ | |
786 | macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); | |
787 | } | |
788 | ||
d5555b70 | 789 | static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) |
6bb46790 | 790 | { |
6bb46790 BW |
791 | u32 hwaddr_bottom; |
792 | u16 hwaddr_top; | |
793 | ||
794 | /* set hardware address */ | |
d5555b70 SG |
795 | hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | |
796 | enetaddr[2] << 16 | enetaddr[3] << 24; | |
6bb46790 | 797 | macb_writel(macb, SA1B, hwaddr_bottom); |
d5555b70 | 798 | hwaddr_top = enetaddr[4] | enetaddr[5] << 8; |
6bb46790 BW |
799 | macb_writel(macb, SA1T, hwaddr_top); |
800 | return 0; | |
801 | } | |
802 | ||
d256be29 BS |
803 | static u32 macb_mdc_clk_div(int id, struct macb_device *macb) |
804 | { | |
805 | u32 config; | |
3fd2b3aa | 806 | #if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK) |
577aa3b3 WY |
807 | unsigned long macb_hz = macb->pclk_rate; |
808 | #else | |
d256be29 | 809 | unsigned long macb_hz = get_macb_pclk_rate(id); |
577aa3b3 | 810 | #endif |
d256be29 BS |
811 | |
812 | if (macb_hz < 20000000) | |
813 | config = MACB_BF(CLK, MACB_CLK_DIV8); | |
814 | else if (macb_hz < 40000000) | |
815 | config = MACB_BF(CLK, MACB_CLK_DIV16); | |
816 | else if (macb_hz < 80000000) | |
817 | config = MACB_BF(CLK, MACB_CLK_DIV32); | |
818 | else | |
819 | config = MACB_BF(CLK, MACB_CLK_DIV64); | |
820 | ||
821 | return config; | |
822 | } | |
823 | ||
824 | static u32 gem_mdc_clk_div(int id, struct macb_device *macb) | |
825 | { | |
826 | u32 config; | |
577aa3b3 | 827 | |
3fd2b3aa | 828 | #if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK) |
577aa3b3 WY |
829 | unsigned long macb_hz = macb->pclk_rate; |
830 | #else | |
d256be29 | 831 | unsigned long macb_hz = get_macb_pclk_rate(id); |
577aa3b3 | 832 | #endif |
d256be29 BS |
833 | |
834 | if (macb_hz < 20000000) | |
835 | config = GEM_BF(CLK, GEM_CLK_DIV8); | |
836 | else if (macb_hz < 40000000) | |
837 | config = GEM_BF(CLK, GEM_CLK_DIV16); | |
838 | else if (macb_hz < 80000000) | |
839 | config = GEM_BF(CLK, GEM_CLK_DIV32); | |
840 | else if (macb_hz < 120000000) | |
841 | config = GEM_BF(CLK, GEM_CLK_DIV48); | |
842 | else if (macb_hz < 160000000) | |
843 | config = GEM_BF(CLK, GEM_CLK_DIV64); | |
844 | else | |
845 | config = GEM_BF(CLK, GEM_CLK_DIV96); | |
846 | ||
847 | return config; | |
848 | } | |
849 | ||
32e4f6bf BS |
850 | /* |
851 | * Get the DMA bus width field of the network configuration register that we | |
852 | * should program. We find the width from decoding the design configuration | |
853 | * register to find the maximum supported data bus width. | |
854 | */ | |
855 | static u32 macb_dbw(struct macb_device *macb) | |
856 | { | |
857 | switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) { | |
858 | case 4: | |
859 | return GEM_BF(DBW, GEM_DBW128); | |
860 | case 2: | |
861 | return GEM_BF(DBW, GEM_DBW64); | |
862 | case 1: | |
863 | default: | |
864 | return GEM_BF(DBW, GEM_DBW32); | |
865 | } | |
866 | } | |
867 | ||
d5555b70 SG |
868 | static void _macb_eth_initialize(struct macb_device *macb) |
869 | { | |
870 | int id = 0; /* This is not used by functions we call */ | |
871 | u32 ncfgr; | |
872 | ||
873 | /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ | |
874 | macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, | |
875 | &macb->rx_buffer_dma); | |
876 | macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, | |
877 | &macb->rx_ring_dma); | |
878 | macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, | |
879 | &macb->tx_ring_dma); | |
880 | macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE, | |
881 | &macb->dummy_desc_dma); | |
882 | ||
883 | /* | |
884 | * Do some basic initialization so that we at least can talk | |
885 | * to the PHY | |
886 | */ | |
887 | if (macb_is_gem(macb)) { | |
888 | ncfgr = gem_mdc_clk_div(id, macb); | |
889 | ncfgr |= macb_dbw(macb); | |
890 | } else { | |
891 | ncfgr = macb_mdc_clk_div(id, macb); | |
892 | } | |
893 | ||
894 | macb_writel(macb, NCFGR, ncfgr); | |
895 | } | |
896 | ||
f1dcc19b | 897 | #ifndef CONFIG_DM_ETH |
d5555b70 SG |
898 | static int macb_send(struct eth_device *netdev, void *packet, int length) |
899 | { | |
900 | struct macb_device *macb = to_macb(netdev); | |
901 | ||
902 | return _macb_send(macb, netdev->name, packet, length); | |
903 | } | |
904 | ||
905 | static int macb_recv(struct eth_device *netdev) | |
906 | { | |
907 | struct macb_device *macb = to_macb(netdev); | |
908 | uchar *packet; | |
909 | int length; | |
910 | ||
911 | macb->wrapped = false; | |
912 | for (;;) { | |
913 | macb->next_rx_tail = macb->rx_tail; | |
914 | length = _macb_recv(macb, &packet); | |
915 | if (length >= 0) { | |
916 | net_process_received_packet(packet, length); | |
917 | reclaim_rx_buffers(macb, macb->next_rx_tail); | |
918 | } else if (length < 0) { | |
919 | return length; | |
920 | } | |
921 | } | |
922 | } | |
923 | ||
924 | static int macb_init(struct eth_device *netdev, bd_t *bd) | |
925 | { | |
926 | struct macb_device *macb = to_macb(netdev); | |
927 | ||
928 | return _macb_init(macb, netdev->name); | |
929 | } | |
930 | ||
931 | static void macb_halt(struct eth_device *netdev) | |
932 | { | |
933 | struct macb_device *macb = to_macb(netdev); | |
934 | ||
935 | return _macb_halt(macb); | |
936 | } | |
937 | ||
938 | static int macb_write_hwaddr(struct eth_device *netdev) | |
939 | { | |
940 | struct macb_device *macb = to_macb(netdev); | |
941 | ||
942 | return _macb_write_hwaddr(macb, netdev->enetaddr); | |
943 | } | |
944 | ||
5c1fe1ff HS |
945 | int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) |
946 | { | |
947 | struct macb_device *macb; | |
948 | struct eth_device *netdev; | |
5c1fe1ff HS |
949 | |
950 | macb = malloc(sizeof(struct macb_device)); | |
951 | if (!macb) { | |
952 | printf("Error: Failed to allocate memory for MACB%d\n", id); | |
953 | return -1; | |
954 | } | |
955 | memset(macb, 0, sizeof(struct macb_device)); | |
956 | ||
957 | netdev = &macb->netdev; | |
958 | ||
5c1fe1ff HS |
959 | macb->regs = regs; |
960 | macb->phy_addr = phy_addr; | |
961 | ||
d256be29 BS |
962 | if (macb_is_gem(macb)) |
963 | sprintf(netdev->name, "gmac%d", id); | |
964 | else | |
965 | sprintf(netdev->name, "macb%d", id); | |
966 | ||
5c1fe1ff HS |
967 | netdev->init = macb_init; |
968 | netdev->halt = macb_halt; | |
969 | netdev->send = macb_send; | |
970 | netdev->recv = macb_recv; | |
6bb46790 | 971 | netdev->write_hwaddr = macb_write_hwaddr; |
5c1fe1ff | 972 | |
d5555b70 | 973 | _macb_eth_initialize(macb); |
5c1fe1ff HS |
974 | |
975 | eth_register(netdev); | |
976 | ||
b1a0006e | 977 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) |
5a49f174 JH |
978 | int retval; |
979 | struct mii_dev *mdiodev = mdio_alloc(); | |
980 | if (!mdiodev) | |
981 | return -ENOMEM; | |
982 | strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN); | |
983 | mdiodev->read = macb_miiphy_read; | |
984 | mdiodev->write = macb_miiphy_write; | |
985 | ||
986 | retval = mdio_register(mdiodev); | |
987 | if (retval < 0) | |
988 | return retval; | |
b1a0006e | 989 | macb->bus = miiphy_get_dev_by_name(netdev->name); |
0f751d6e | 990 | #endif |
5c1fe1ff HS |
991 | return 0; |
992 | } | |
f1dcc19b SG |
993 | #endif /* !CONFIG_DM_ETH */ |
994 | ||
995 | #ifdef CONFIG_DM_ETH | |
996 | ||
997 | static int macb_start(struct udevice *dev) | |
998 | { | |
a212b66d | 999 | return _macb_init(dev, dev->name); |
f1dcc19b SG |
1000 | } |
1001 | ||
1002 | static int macb_send(struct udevice *dev, void *packet, int length) | |
1003 | { | |
1004 | struct macb_device *macb = dev_get_priv(dev); | |
1005 | ||
1006 | return _macb_send(macb, dev->name, packet, length); | |
1007 | } | |
1008 | ||
1009 | static int macb_recv(struct udevice *dev, int flags, uchar **packetp) | |
1010 | { | |
1011 | struct macb_device *macb = dev_get_priv(dev); | |
1012 | ||
1013 | macb->next_rx_tail = macb->rx_tail; | |
1014 | macb->wrapped = false; | |
1015 | ||
1016 | return _macb_recv(macb, packetp); | |
1017 | } | |
1018 | ||
1019 | static int macb_free_pkt(struct udevice *dev, uchar *packet, int length) | |
1020 | { | |
1021 | struct macb_device *macb = dev_get_priv(dev); | |
1022 | ||
1023 | reclaim_rx_buffers(macb, macb->next_rx_tail); | |
1024 | ||
1025 | return 0; | |
1026 | } | |
1027 | ||
1028 | static void macb_stop(struct udevice *dev) | |
1029 | { | |
1030 | struct macb_device *macb = dev_get_priv(dev); | |
1031 | ||
1032 | _macb_halt(macb); | |
1033 | } | |
1034 | ||
1035 | static int macb_write_hwaddr(struct udevice *dev) | |
1036 | { | |
1037 | struct eth_pdata *plat = dev_get_platdata(dev); | |
1038 | struct macb_device *macb = dev_get_priv(dev); | |
1039 | ||
1040 | return _macb_write_hwaddr(macb, plat->enetaddr); | |
1041 | } | |
1042 | ||
1043 | static const struct eth_ops macb_eth_ops = { | |
1044 | .start = macb_start, | |
1045 | .send = macb_send, | |
1046 | .recv = macb_recv, | |
1047 | .stop = macb_stop, | |
1048 | .free_pkt = macb_free_pkt, | |
1049 | .write_hwaddr = macb_write_hwaddr, | |
1050 | }; | |
1051 | ||
3fd2b3aa | 1052 | #ifdef CONFIG_CLK |
577aa3b3 WY |
1053 | static int macb_enable_clk(struct udevice *dev) |
1054 | { | |
1055 | struct macb_device *macb = dev_get_priv(dev); | |
1056 | struct clk clk; | |
1057 | ulong clk_rate; | |
1058 | int ret; | |
1059 | ||
1060 | ret = clk_get_by_index(dev, 0, &clk); | |
1061 | if (ret) | |
1062 | return -EINVAL; | |
1063 | ||
4bf56913 WL |
1064 | /* |
1065 | * Zynq clock driver didn't support for enable or disable | |
1066 | * clock. Hence, clk_enable() didn't apply for Zynq | |
1067 | */ | |
1068 | #ifndef CONFIG_MACB_ZYNQ | |
577aa3b3 WY |
1069 | ret = clk_enable(&clk); |
1070 | if (ret) | |
1071 | return ret; | |
4bf56913 | 1072 | #endif |
577aa3b3 WY |
1073 | |
1074 | clk_rate = clk_get_rate(&clk); | |
1075 | if (!clk_rate) | |
1076 | return -EINVAL; | |
1077 | ||
1078 | macb->pclk_rate = clk_rate; | |
1079 | ||
1080 | return 0; | |
1081 | } | |
3fd2b3aa | 1082 | #endif |
577aa3b3 | 1083 | |
f1dcc19b SG |
1084 | static int macb_eth_probe(struct udevice *dev) |
1085 | { | |
1086 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
1087 | struct macb_device *macb = dev_get_priv(dev); | |
a212b66d | 1088 | const char *phy_mode; |
1870d4d7 | 1089 | __maybe_unused int ret; |
a212b66d | 1090 | |
e160f7d4 SG |
1091 | phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", |
1092 | NULL); | |
a212b66d WY |
1093 | if (phy_mode) |
1094 | macb->phy_interface = phy_get_interface_by_name(phy_mode); | |
1095 | if (macb->phy_interface == -1) { | |
1096 | debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); | |
1097 | return -EINVAL; | |
1098 | } | |
a212b66d | 1099 | |
f1dcc19b SG |
1100 | macb->regs = (void *)pdata->iobase; |
1101 | ||
3fd2b3aa | 1102 | #ifdef CONFIG_CLK |
1870d4d7 | 1103 | ret = macb_enable_clk(dev); |
577aa3b3 WY |
1104 | if (ret) |
1105 | return ret; | |
3fd2b3aa | 1106 | #endif |
577aa3b3 | 1107 | |
f1dcc19b | 1108 | _macb_eth_initialize(macb); |
577aa3b3 | 1109 | |
f1dcc19b | 1110 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) |
1870d4d7 WY |
1111 | macb->bus = mdio_alloc(); |
1112 | if (!macb->bus) | |
5a49f174 | 1113 | return -ENOMEM; |
1870d4d7 WY |
1114 | strncpy(macb->bus->name, dev->name, MDIO_NAME_LEN); |
1115 | macb->bus->read = macb_miiphy_read; | |
1116 | macb->bus->write = macb_miiphy_write; | |
5a49f174 | 1117 | |
1870d4d7 WY |
1118 | ret = mdio_register(macb->bus); |
1119 | if (ret < 0) | |
1120 | return ret; | |
f1dcc19b SG |
1121 | macb->bus = miiphy_get_dev_by_name(dev->name); |
1122 | #endif | |
1123 | ||
1124 | return 0; | |
1125 | } | |
1126 | ||
1870d4d7 WY |
1127 | static int macb_eth_remove(struct udevice *dev) |
1128 | { | |
1129 | struct macb_device *macb = dev_get_priv(dev); | |
1130 | ||
1131 | #ifdef CONFIG_PHYLIB | |
1132 | free(macb->phydev); | |
1133 | #endif | |
1134 | mdio_unregister(macb->bus); | |
1135 | mdio_free(macb->bus); | |
1136 | ||
1137 | return 0; | |
1138 | } | |
1139 | ||
4bf56913 WL |
1140 | /** |
1141 | * macb_late_eth_ofdata_to_platdata | |
1142 | * @dev: udevice struct | |
1143 | * Returns 0 when operation success and negative errno number | |
1144 | * when operation failed. | |
1145 | */ | |
1146 | int __weak macb_late_eth_ofdata_to_platdata(struct udevice *dev) | |
1147 | { | |
1148 | return 0; | |
1149 | } | |
1150 | ||
f1dcc19b SG |
1151 | static int macb_eth_ofdata_to_platdata(struct udevice *dev) |
1152 | { | |
1153 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
1154 | ||
a821c4af | 1155 | pdata->iobase = devfdt_get_addr(dev); |
4bf56913 WL |
1156 | |
1157 | return macb_late_eth_ofdata_to_platdata(dev); | |
f1dcc19b SG |
1158 | } |
1159 | ||
1160 | static const struct udevice_id macb_eth_ids[] = { | |
1161 | { .compatible = "cdns,macb" }, | |
75460253 WY |
1162 | { .compatible = "cdns,at91sam9260-macb" }, |
1163 | { .compatible = "atmel,sama5d2-gem" }, | |
1164 | { .compatible = "atmel,sama5d3-gem" }, | |
1165 | { .compatible = "atmel,sama5d4-gem" }, | |
4bf56913 | 1166 | { .compatible = "cdns,zynq-gem" }, |
f1dcc19b SG |
1167 | { } |
1168 | }; | |
1169 | ||
1170 | U_BOOT_DRIVER(eth_macb) = { | |
1171 | .name = "eth_macb", | |
1172 | .id = UCLASS_ETH, | |
1173 | .of_match = macb_eth_ids, | |
1174 | .ofdata_to_platdata = macb_eth_ofdata_to_platdata, | |
1175 | .probe = macb_eth_probe, | |
1870d4d7 | 1176 | .remove = macb_eth_remove, |
f1dcc19b SG |
1177 | .ops = &macb_eth_ops, |
1178 | .priv_auto_alloc_size = sizeof(struct macb_device), | |
1179 | .platdata_auto_alloc_size = sizeof(struct eth_pdata), | |
1180 | }; | |
1181 | #endif | |
5c1fe1ff | 1182 | |
07d38a17 | 1183 | #endif |