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