]>
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> | |
f1dcc19b | 7 | #include <dm.h> |
5c1fe1ff | 8 | |
5c1fe1ff HS |
9 | /* |
10 | * The u-boot networking stack is a little weird. It seems like the | |
11 | * networking core allocates receive buffers up front without any | |
12 | * regard to the hardware that's supposed to actually receive those | |
13 | * packets. | |
14 | * | |
15 | * The MACB receives packets into 128-byte receive buffers, so the | |
16 | * buffers allocated by the core isn't very practical to use. We'll | |
17 | * allocate our own, but we need one such buffer in case a packet | |
18 | * wraps around the DMA ring so that we have to copy it. | |
19 | * | |
6d0f6bcf | 20 | * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific |
5c1fe1ff HS |
21 | * configuration header. This way, the core allocates one RX buffer |
22 | * and one TX buffer, each of which can hold a ethernet packet of | |
23 | * maximum size. | |
24 | * | |
25 | * For some reason, the networking core unconditionally specifies a | |
26 | * 32-byte packet "alignment" (which really should be called | |
27 | * "padding"). MACB shouldn't need that, but we'll refrain from any | |
28 | * core modifications here... | |
29 | */ | |
30 | ||
31 | #include <net.h> | |
f1dcc19b | 32 | #ifndef CONFIG_DM_ETH |
89973f8a | 33 | #include <netdev.h> |
f1dcc19b | 34 | #endif |
5c1fe1ff | 35 | #include <malloc.h> |
0f751d6e | 36 | #include <miiphy.h> |
5c1fe1ff HS |
37 | |
38 | #include <linux/mii.h> | |
39 | #include <asm/io.h> | |
40 | #include <asm/dma-mapping.h> | |
41 | #include <asm/arch/clk.h> | |
5d97dff0 | 42 | #include <linux/errno.h> |
5c1fe1ff HS |
43 | |
44 | #include "macb.h" | |
45 | ||
a212b66d WY |
46 | DECLARE_GLOBAL_DATA_PTR; |
47 | ||
ceef983b AB |
48 | #define MACB_RX_BUFFER_SIZE 4096 |
49 | #define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128) | |
50 | #define MACB_TX_RING_SIZE 16 | |
51 | #define MACB_TX_TIMEOUT 1000 | |
52 | #define MACB_AUTONEG_TIMEOUT 5000000 | |
5c1fe1ff HS |
53 | |
54 | struct macb_dma_desc { | |
55 | u32 addr; | |
56 | u32 ctrl; | |
57 | }; | |
58 | ||
5ae0e382 WJ |
59 | #define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) |
60 | #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) | |
61 | #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) | |
ade4ea4d | 62 | #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) |
5ae0e382 | 63 | |
5c1fe1ff HS |
64 | #define RXADDR_USED 0x00000001 |
65 | #define RXADDR_WRAP 0x00000002 | |
66 | ||
67 | #define RXBUF_FRMLEN_MASK 0x00000fff | |
68 | #define RXBUF_FRAME_START 0x00004000 | |
69 | #define RXBUF_FRAME_END 0x00008000 | |
70 | #define RXBUF_TYPEID_MATCH 0x00400000 | |
71 | #define RXBUF_ADDR4_MATCH 0x00800000 | |
72 | #define RXBUF_ADDR3_MATCH 0x01000000 | |
73 | #define RXBUF_ADDR2_MATCH 0x02000000 | |
74 | #define RXBUF_ADDR1_MATCH 0x04000000 | |
75 | #define RXBUF_BROADCAST 0x80000000 | |
76 | ||
77 | #define TXBUF_FRMLEN_MASK 0x000007ff | |
78 | #define TXBUF_FRAME_END 0x00008000 | |
79 | #define TXBUF_NOCRC 0x00010000 | |
80 | #define TXBUF_EXHAUSTED 0x08000000 | |
81 | #define TXBUF_UNDERRUN 0x10000000 | |
82 | #define TXBUF_MAXRETRY 0x20000000 | |
83 | #define TXBUF_WRAP 0x40000000 | |
84 | #define TXBUF_USED 0x80000000 | |
85 | ||
86 | struct macb_device { | |
87 | void *regs; | |
88 | ||
89 | unsigned int rx_tail; | |
90 | unsigned int tx_head; | |
91 | unsigned int tx_tail; | |
d5555b70 SG |
92 | unsigned int next_rx_tail; |
93 | bool wrapped; | |
5c1fe1ff HS |
94 | |
95 | void *rx_buffer; | |
96 | void *tx_buffer; | |
97 | struct macb_dma_desc *rx_ring; | |
98 | struct macb_dma_desc *tx_ring; | |
99 | ||
100 | unsigned long rx_buffer_dma; | |
101 | unsigned long rx_ring_dma; | |
102 | unsigned long tx_ring_dma; | |
103 | ||
ade4ea4d WJ |
104 | struct macb_dma_desc *dummy_desc; |
105 | unsigned long dummy_desc_dma; | |
106 | ||
5c1fe1ff | 107 | const struct device *dev; |
f1dcc19b | 108 | #ifndef CONFIG_DM_ETH |
5c1fe1ff | 109 | struct eth_device netdev; |
f1dcc19b | 110 | #endif |
5c1fe1ff | 111 | unsigned short phy_addr; |
b1a0006e | 112 | struct mii_dev *bus; |
a212b66d WY |
113 | |
114 | #ifdef CONFIG_DM_ETH | |
115 | phy_interface_t phy_interface; | |
116 | #endif | |
5c1fe1ff | 117 | }; |
f1dcc19b | 118 | #ifndef CONFIG_DM_ETH |
5c1fe1ff | 119 | #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) |
f1dcc19b | 120 | #endif |
5c1fe1ff | 121 | |
d256be29 BS |
122 | static int macb_is_gem(struct macb_device *macb) |
123 | { | |
124 | return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; | |
125 | } | |
126 | ||
75b03cf1 GC |
127 | #ifndef cpu_is_sama5d2 |
128 | #define cpu_is_sama5d2() 0 | |
129 | #endif | |
130 | ||
131 | #ifndef cpu_is_sama5d4 | |
132 | #define cpu_is_sama5d4() 0 | |
133 | #endif | |
134 | ||
135 | static int gem_is_gigabit_capable(struct macb_device *macb) | |
136 | { | |
137 | /* | |
1cc0a9f4 | 138 | * The GEM controllers embedded in SAMA5D2 and SAMA5D4 are |
75b03cf1 GC |
139 | * configured to support only 10/100. |
140 | */ | |
141 | return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4(); | |
142 | } | |
143 | ||
5c1fe1ff HS |
144 | static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) |
145 | { | |
146 | unsigned long netctl; | |
147 | unsigned long netstat; | |
148 | unsigned long frame; | |
149 | ||
150 | netctl = macb_readl(macb, NCR); | |
151 | netctl |= MACB_BIT(MPE); | |
152 | macb_writel(macb, NCR, netctl); | |
153 | ||
154 | frame = (MACB_BF(SOF, 1) | |
155 | | MACB_BF(RW, 1) | |
156 | | MACB_BF(PHYA, macb->phy_addr) | |
157 | | MACB_BF(REGA, reg) | |
158 | | MACB_BF(CODE, 2) | |
159 | | MACB_BF(DATA, value)); | |
160 | macb_writel(macb, MAN, frame); | |
161 | ||
162 | do { | |
163 | netstat = macb_readl(macb, NSR); | |
164 | } while (!(netstat & MACB_BIT(IDLE))); | |
165 | ||
166 | netctl = macb_readl(macb, NCR); | |
167 | netctl &= ~MACB_BIT(MPE); | |
168 | macb_writel(macb, NCR, netctl); | |
169 | } | |
170 | ||
171 | static u16 macb_mdio_read(struct macb_device *macb, u8 reg) | |
172 | { | |
173 | unsigned long netctl; | |
174 | unsigned long netstat; | |
175 | unsigned long frame; | |
176 | ||
177 | netctl = macb_readl(macb, NCR); | |
178 | netctl |= MACB_BIT(MPE); | |
179 | macb_writel(macb, NCR, netctl); | |
180 | ||
181 | frame = (MACB_BF(SOF, 1) | |
182 | | MACB_BF(RW, 2) | |
183 | | MACB_BF(PHYA, macb->phy_addr) | |
184 | | MACB_BF(REGA, reg) | |
185 | | MACB_BF(CODE, 2)); | |
186 | macb_writel(macb, MAN, frame); | |
187 | ||
188 | do { | |
189 | netstat = macb_readl(macb, NSR); | |
190 | } while (!(netstat & MACB_BIT(IDLE))); | |
191 | ||
192 | frame = macb_readl(macb, MAN); | |
193 | ||
194 | netctl = macb_readl(macb, NCR); | |
195 | netctl &= ~MACB_BIT(MPE); | |
196 | macb_writel(macb, NCR, netctl); | |
197 | ||
198 | return MACB_BFEXT(DATA, frame); | |
199 | } | |
200 | ||
1b8c18b9 | 201 | void __weak arch_get_mdio_control(const char *name) |
416ce623 SH |
202 | { |
203 | return; | |
204 | } | |
205 | ||
b1a0006e | 206 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) |
0f751d6e | 207 | |
5a49f174 | 208 | int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg) |
0f751d6e | 209 | { |
5a49f174 | 210 | u16 value = 0; |
f1dcc19b | 211 | #ifdef CONFIG_DM_ETH |
5a49f174 | 212 | struct udevice *dev = eth_get_dev_by_name(bus->name); |
f1dcc19b SG |
213 | struct macb_device *macb = dev_get_priv(dev); |
214 | #else | |
5a49f174 | 215 | struct eth_device *dev = eth_get_dev_by_name(bus->name); |
0f751d6e | 216 | struct macb_device *macb = to_macb(dev); |
f1dcc19b | 217 | #endif |
0f751d6e | 218 | |
ceef983b | 219 | if (macb->phy_addr != phy_adr) |
0f751d6e SH |
220 | return -1; |
221 | ||
5a49f174 JH |
222 | arch_get_mdio_control(bus->name); |
223 | value = macb_mdio_read(macb, reg); | |
0f751d6e | 224 | |
5a49f174 | 225 | return value; |
0f751d6e SH |
226 | } |
227 | ||
5a49f174 JH |
228 | int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg, |
229 | u16 value) | |
0f751d6e | 230 | { |
f1dcc19b | 231 | #ifdef CONFIG_DM_ETH |
5a49f174 | 232 | struct udevice *dev = eth_get_dev_by_name(bus->name); |
f1dcc19b SG |
233 | struct macb_device *macb = dev_get_priv(dev); |
234 | #else | |
5a49f174 | 235 | struct eth_device *dev = eth_get_dev_by_name(bus->name); |
0f751d6e | 236 | struct macb_device *macb = to_macb(dev); |
f1dcc19b | 237 | #endif |
0f751d6e | 238 | |
ceef983b | 239 | if (macb->phy_addr != phy_adr) |
0f751d6e SH |
240 | return -1; |
241 | ||
5a49f174 | 242 | arch_get_mdio_control(bus->name); |
0f751d6e SH |
243 | macb_mdio_write(macb, reg, value); |
244 | ||
245 | return 0; | |
246 | } | |
247 | #endif | |
248 | ||
5ae0e382 WJ |
249 | #define RX 1 |
250 | #define TX 0 | |
251 | static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) | |
252 | { | |
253 | if (rx) | |
592a7495 HS |
254 | invalidate_dcache_range(macb->rx_ring_dma, |
255 | ALIGN(macb->rx_ring_dma + MACB_RX_DMA_DESC_SIZE, | |
256 | PKTALIGN)); | |
5ae0e382 | 257 | else |
592a7495 HS |
258 | invalidate_dcache_range(macb->tx_ring_dma, |
259 | ALIGN(macb->tx_ring_dma + MACB_TX_DMA_DESC_SIZE, | |
260 | PKTALIGN)); | |
5ae0e382 WJ |
261 | } |
262 | ||
263 | static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) | |
264 | { | |
265 | if (rx) | |
266 | flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + | |
592a7495 | 267 | ALIGN(MACB_RX_DMA_DESC_SIZE, PKTALIGN)); |
5ae0e382 WJ |
268 | else |
269 | flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + | |
592a7495 | 270 | ALIGN(MACB_TX_DMA_DESC_SIZE, PKTALIGN)); |
5ae0e382 WJ |
271 | } |
272 | ||
273 | static inline void macb_flush_rx_buffer(struct macb_device *macb) | |
274 | { | |
275 | flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + | |
592a7495 | 276 | ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); |
5ae0e382 WJ |
277 | } |
278 | ||
279 | static inline void macb_invalidate_rx_buffer(struct macb_device *macb) | |
280 | { | |
281 | invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + | |
592a7495 | 282 | ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); |
5ae0e382 | 283 | } |
0f751d6e | 284 | |
07d38a17 | 285 | #if defined(CONFIG_CMD_NET) |
5c1fe1ff | 286 | |
d5555b70 SG |
287 | static int _macb_send(struct macb_device *macb, const char *name, void *packet, |
288 | int length) | |
5c1fe1ff | 289 | { |
5c1fe1ff HS |
290 | unsigned long paddr, ctrl; |
291 | unsigned int tx_head = macb->tx_head; | |
292 | int i; | |
293 | ||
294 | paddr = dma_map_single(packet, length, DMA_TO_DEVICE); | |
295 | ||
296 | ctrl = length & TXBUF_FRMLEN_MASK; | |
297 | ctrl |= TXBUF_FRAME_END; | |
ceef983b | 298 | if (tx_head == (MACB_TX_RING_SIZE - 1)) { |
5c1fe1ff HS |
299 | ctrl |= TXBUF_WRAP; |
300 | macb->tx_head = 0; | |
ceef983b | 301 | } else { |
5c1fe1ff | 302 | macb->tx_head++; |
ceef983b | 303 | } |
5c1fe1ff HS |
304 | |
305 | macb->tx_ring[tx_head].ctrl = ctrl; | |
306 | macb->tx_ring[tx_head].addr = paddr; | |
04fcb5d3 | 307 | barrier(); |
5ae0e382 WJ |
308 | macb_flush_ring_desc(macb, TX); |
309 | /* Do we need check paddr and length is dcache line aligned? */ | |
f589f8cc | 310 | flush_dcache_range(paddr, paddr + ALIGN(length, ARCH_DMA_MINALIGN)); |
5c1fe1ff HS |
311 | macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); |
312 | ||
313 | /* | |
314 | * I guess this is necessary because the networking core may | |
315 | * re-use the transmit buffer as soon as we return... | |
316 | */ | |
ceef983b | 317 | for (i = 0; i <= MACB_TX_TIMEOUT; i++) { |
04fcb5d3 | 318 | barrier(); |
5ae0e382 | 319 | macb_invalidate_ring_desc(macb, TX); |
04fcb5d3 HS |
320 | ctrl = macb->tx_ring[tx_head].ctrl; |
321 | if (ctrl & TXBUF_USED) | |
5c1fe1ff | 322 | break; |
5c1fe1ff | 323 | udelay(1); |
5c1fe1ff HS |
324 | } |
325 | ||
326 | dma_unmap_single(packet, length, paddr); | |
327 | ||
ceef983b | 328 | if (i <= MACB_TX_TIMEOUT) { |
5c1fe1ff | 329 | if (ctrl & TXBUF_UNDERRUN) |
d5555b70 | 330 | printf("%s: TX underrun\n", name); |
5c1fe1ff | 331 | if (ctrl & TXBUF_EXHAUSTED) |
d5555b70 | 332 | printf("%s: TX buffers exhausted in mid frame\n", name); |
04fcb5d3 | 333 | } else { |
d5555b70 | 334 | printf("%s: TX timeout\n", name); |
5c1fe1ff HS |
335 | } |
336 | ||
337 | /* No one cares anyway */ | |
338 | return 0; | |
339 | } | |
340 | ||
341 | static void reclaim_rx_buffers(struct macb_device *macb, | |
342 | unsigned int new_tail) | |
343 | { | |
344 | unsigned int i; | |
345 | ||
346 | i = macb->rx_tail; | |
5ae0e382 WJ |
347 | |
348 | macb_invalidate_ring_desc(macb, RX); | |
5c1fe1ff HS |
349 | while (i > new_tail) { |
350 | macb->rx_ring[i].addr &= ~RXADDR_USED; | |
351 | i++; | |
ceef983b | 352 | if (i > MACB_RX_RING_SIZE) |
5c1fe1ff HS |
353 | i = 0; |
354 | } | |
355 | ||
356 | while (i < new_tail) { | |
357 | macb->rx_ring[i].addr &= ~RXADDR_USED; | |
358 | i++; | |
359 | } | |
360 | ||
04fcb5d3 | 361 | barrier(); |
5ae0e382 | 362 | macb_flush_ring_desc(macb, RX); |
5c1fe1ff HS |
363 | macb->rx_tail = new_tail; |
364 | } | |
365 | ||
d5555b70 | 366 | static int _macb_recv(struct macb_device *macb, uchar **packetp) |
5c1fe1ff | 367 | { |
d5555b70 | 368 | unsigned int next_rx_tail = macb->next_rx_tail; |
5c1fe1ff HS |
369 | void *buffer; |
370 | int length; | |
5c1fe1ff HS |
371 | u32 status; |
372 | ||
d5555b70 | 373 | macb->wrapped = false; |
5c1fe1ff | 374 | for (;;) { |
5ae0e382 WJ |
375 | macb_invalidate_ring_desc(macb, RX); |
376 | ||
d5555b70 SG |
377 | if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED)) |
378 | return -EAGAIN; | |
5c1fe1ff | 379 | |
d5555b70 | 380 | status = macb->rx_ring[next_rx_tail].ctrl; |
5c1fe1ff | 381 | if (status & RXBUF_FRAME_START) { |
d5555b70 SG |
382 | if (next_rx_tail != macb->rx_tail) |
383 | reclaim_rx_buffers(macb, next_rx_tail); | |
384 | macb->wrapped = false; | |
5c1fe1ff HS |
385 | } |
386 | ||
387 | if (status & RXBUF_FRAME_END) { | |
388 | buffer = macb->rx_buffer + 128 * macb->rx_tail; | |
389 | length = status & RXBUF_FRMLEN_MASK; | |
5ae0e382 WJ |
390 | |
391 | macb_invalidate_rx_buffer(macb); | |
d5555b70 | 392 | if (macb->wrapped) { |
5c1fe1ff HS |
393 | unsigned int headlen, taillen; |
394 | ||
ceef983b | 395 | headlen = 128 * (MACB_RX_RING_SIZE |
5c1fe1ff HS |
396 | - macb->rx_tail); |
397 | taillen = length - headlen; | |
1fd92db8 | 398 | memcpy((void *)net_rx_packets[0], |
5c1fe1ff | 399 | buffer, headlen); |
1fd92db8 | 400 | memcpy((void *)net_rx_packets[0] + headlen, |
5c1fe1ff | 401 | macb->rx_buffer, taillen); |
d5555b70 SG |
402 | *packetp = (void *)net_rx_packets[0]; |
403 | } else { | |
404 | *packetp = buffer; | |
5c1fe1ff HS |
405 | } |
406 | ||
d5555b70 SG |
407 | if (++next_rx_tail >= MACB_RX_RING_SIZE) |
408 | next_rx_tail = 0; | |
409 | macb->next_rx_tail = next_rx_tail; | |
410 | return length; | |
5c1fe1ff | 411 | } else { |
d5555b70 SG |
412 | if (++next_rx_tail >= MACB_RX_RING_SIZE) { |
413 | macb->wrapped = true; | |
414 | next_rx_tail = 0; | |
5c1fe1ff HS |
415 | } |
416 | } | |
04fcb5d3 | 417 | barrier(); |
5c1fe1ff | 418 | } |
5c1fe1ff HS |
419 | } |
420 | ||
d5555b70 | 421 | static void macb_phy_reset(struct macb_device *macb, const char *name) |
5c1fe1ff | 422 | { |
5c1fe1ff | 423 | int i; |
f2134f8e | 424 | u16 status, adv; |
5c1fe1ff HS |
425 | |
426 | adv = ADVERTISE_CSMA | ADVERTISE_ALL; | |
427 | macb_mdio_write(macb, MII_ADVERTISE, adv); | |
d5555b70 | 428 | printf("%s: Starting autonegotiation...\n", name); |
5c1fe1ff HS |
429 | macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE |
430 | | BMCR_ANRESTART)); | |
431 | ||
ceef983b | 432 | for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { |
5c1fe1ff HS |
433 | status = macb_mdio_read(macb, MII_BMSR); |
434 | if (status & BMSR_ANEGCOMPLETE) | |
435 | break; | |
436 | udelay(100); | |
437 | } | |
438 | ||
439 | if (status & BMSR_ANEGCOMPLETE) | |
d5555b70 | 440 | printf("%s: Autonegotiation complete\n", name); |
5c1fe1ff HS |
441 | else |
442 | printf("%s: Autonegotiation timed out (status=0x%04x)\n", | |
d5555b70 | 443 | name, status); |
f2134f8e | 444 | } |
5c1fe1ff | 445 | |
fc01ea1e | 446 | #ifdef CONFIG_MACB_SEARCH_PHY |
a212b66d | 447 | static int macb_phy_find(struct macb_device *macb, const char *name) |
fc01ea1e GR |
448 | { |
449 | int i; | |
450 | u16 phy_id; | |
451 | ||
452 | /* Search for PHY... */ | |
453 | for (i = 0; i < 32; i++) { | |
454 | macb->phy_addr = i; | |
455 | phy_id = macb_mdio_read(macb, MII_PHYSID1); | |
456 | if (phy_id != 0xffff) { | |
a212b66d | 457 | printf("%s: PHY present at %d\n", name, i); |
fc01ea1e GR |
458 | return 1; |
459 | } | |
460 | } | |
461 | ||
462 | /* PHY isn't up to snuff */ | |
a212b66d | 463 | printf("%s: PHY not found\n", name); |
fc01ea1e GR |
464 | |
465 | return 0; | |
466 | } | |
467 | #endif /* CONFIG_MACB_SEARCH_PHY */ | |
468 | ||
a212b66d WY |
469 | #ifdef CONFIG_DM_ETH |
470 | static int macb_phy_init(struct udevice *dev, const char *name) | |
471 | #else | |
d5555b70 | 472 | static int macb_phy_init(struct macb_device *macb, const char *name) |
a212b66d | 473 | #endif |
f2134f8e | 474 | { |
a212b66d WY |
475 | #ifdef CONFIG_DM_ETH |
476 | struct macb_device *macb = dev_get_priv(dev); | |
477 | #endif | |
b1a0006e BS |
478 | #ifdef CONFIG_PHYLIB |
479 | struct phy_device *phydev; | |
480 | #endif | |
f2134f8e HS |
481 | u32 ncfgr; |
482 | u16 phy_id, status, adv, lpa; | |
483 | int media, speed, duplex; | |
484 | int i; | |
485 | ||
d5555b70 | 486 | arch_get_mdio_control(name); |
fc01ea1e GR |
487 | #ifdef CONFIG_MACB_SEARCH_PHY |
488 | /* Auto-detect phy_addr */ | |
a212b66d | 489 | if (!macb_phy_find(macb, name)) |
fc01ea1e | 490 | return 0; |
fc01ea1e GR |
491 | #endif /* CONFIG_MACB_SEARCH_PHY */ |
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 WY |
501 | #ifdef CONFIG_DM_ETH |
502 | phydev = phy_connect(macb->bus, macb->phy_addr, dev, | |
503 | macb->phy_interface); | |
504 | #else | |
8314ccd8 | 505 | /* need to consider other phy interface mode */ |
d5555b70 | 506 | phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, |
8314ccd8 | 507 | PHY_INTERFACE_MODE_RGMII); |
a212b66d | 508 | #endif |
8314ccd8 BS |
509 | if (!phydev) { |
510 | printf("phy_connect failed\n"); | |
511 | return -ENODEV; | |
512 | } | |
513 | ||
b1a0006e BS |
514 | phy_config(phydev); |
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 WY |
665 | #ifdef CONFIG_DM_ETH |
666 | if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) | |
667 | gem_writel(macb, UR, GEM_BIT(RGMII)); | |
668 | else | |
669 | gem_writel(macb, UR, 0); | |
670 | #else | |
cabf61ce | 671 | #if defined(CONFIG_RGMII) || defined(CONFIG_RMII) |
d256be29 BS |
672 | gem_writel(macb, UR, GEM_BIT(RGMII)); |
673 | #else | |
674 | gem_writel(macb, UR, 0); | |
a212b66d | 675 | #endif |
d256be29 BS |
676 | #endif |
677 | } else { | |
5c1fe1ff | 678 | /* choose RMII or MII mode. This depends on the board */ |
a212b66d WY |
679 | #ifdef CONFIG_DM_ETH |
680 | #ifdef CONFIG_AT91FAMILY | |
681 | if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) { | |
682 | macb_writel(macb, USRIO, | |
683 | MACB_BIT(RMII) | MACB_BIT(CLKEN)); | |
684 | } else { | |
685 | macb_writel(macb, USRIO, MACB_BIT(CLKEN)); | |
686 | } | |
687 | #else | |
688 | if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) | |
689 | macb_writel(macb, USRIO, 0); | |
690 | else | |
691 | macb_writel(macb, USRIO, MACB_BIT(MII)); | |
692 | #endif | |
693 | #else | |
5c1fe1ff | 694 | #ifdef CONFIG_RMII |
d8f64b44 | 695 | #ifdef CONFIG_AT91FAMILY |
7263ef19 SP |
696 | macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); |
697 | #else | |
5c1fe1ff | 698 | macb_writel(macb, USRIO, 0); |
7263ef19 SP |
699 | #endif |
700 | #else | |
d8f64b44 | 701 | #ifdef CONFIG_AT91FAMILY |
7263ef19 | 702 | macb_writel(macb, USRIO, MACB_BIT(CLKEN)); |
5c1fe1ff HS |
703 | #else |
704 | macb_writel(macb, USRIO, MACB_BIT(MII)); | |
705 | #endif | |
7263ef19 | 706 | #endif /* CONFIG_RMII */ |
a212b66d | 707 | #endif |
d256be29 | 708 | } |
5c1fe1ff | 709 | |
a212b66d WY |
710 | #ifdef CONFIG_DM_ETH |
711 | if (!macb_phy_init(dev, name)) | |
712 | #else | |
d5555b70 | 713 | if (!macb_phy_init(macb, name)) |
a212b66d | 714 | #endif |
422b1a01 | 715 | return -1; |
5c1fe1ff HS |
716 | |
717 | /* Enable TX and RX */ | |
718 | macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); | |
719 | ||
422b1a01 | 720 | return 0; |
5c1fe1ff HS |
721 | } |
722 | ||
d5555b70 | 723 | static void _macb_halt(struct macb_device *macb) |
5c1fe1ff | 724 | { |
5c1fe1ff HS |
725 | u32 ncr, tsr; |
726 | ||
727 | /* Halt the controller and wait for any ongoing transmission to end. */ | |
728 | ncr = macb_readl(macb, NCR); | |
729 | ncr |= MACB_BIT(THALT); | |
730 | macb_writel(macb, NCR, ncr); | |
731 | ||
732 | do { | |
733 | tsr = macb_readl(macb, TSR); | |
734 | } while (tsr & MACB_BIT(TGO)); | |
735 | ||
736 | /* Disable TX and RX, and clear statistics */ | |
737 | macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); | |
738 | } | |
739 | ||
d5555b70 | 740 | static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) |
6bb46790 | 741 | { |
6bb46790 BW |
742 | u32 hwaddr_bottom; |
743 | u16 hwaddr_top; | |
744 | ||
745 | /* set hardware address */ | |
d5555b70 SG |
746 | hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | |
747 | enetaddr[2] << 16 | enetaddr[3] << 24; | |
6bb46790 | 748 | macb_writel(macb, SA1B, hwaddr_bottom); |
d5555b70 | 749 | hwaddr_top = enetaddr[4] | enetaddr[5] << 8; |
6bb46790 BW |
750 | macb_writel(macb, SA1T, hwaddr_top); |
751 | return 0; | |
752 | } | |
753 | ||
d256be29 BS |
754 | static u32 macb_mdc_clk_div(int id, struct macb_device *macb) |
755 | { | |
756 | u32 config; | |
757 | unsigned long macb_hz = get_macb_pclk_rate(id); | |
758 | ||
759 | if (macb_hz < 20000000) | |
760 | config = MACB_BF(CLK, MACB_CLK_DIV8); | |
761 | else if (macb_hz < 40000000) | |
762 | config = MACB_BF(CLK, MACB_CLK_DIV16); | |
763 | else if (macb_hz < 80000000) | |
764 | config = MACB_BF(CLK, MACB_CLK_DIV32); | |
765 | else | |
766 | config = MACB_BF(CLK, MACB_CLK_DIV64); | |
767 | ||
768 | return config; | |
769 | } | |
770 | ||
771 | static u32 gem_mdc_clk_div(int id, struct macb_device *macb) | |
772 | { | |
773 | u32 config; | |
774 | unsigned long macb_hz = get_macb_pclk_rate(id); | |
775 | ||
776 | if (macb_hz < 20000000) | |
777 | config = GEM_BF(CLK, GEM_CLK_DIV8); | |
778 | else if (macb_hz < 40000000) | |
779 | config = GEM_BF(CLK, GEM_CLK_DIV16); | |
780 | else if (macb_hz < 80000000) | |
781 | config = GEM_BF(CLK, GEM_CLK_DIV32); | |
782 | else if (macb_hz < 120000000) | |
783 | config = GEM_BF(CLK, GEM_CLK_DIV48); | |
784 | else if (macb_hz < 160000000) | |
785 | config = GEM_BF(CLK, GEM_CLK_DIV64); | |
786 | else | |
787 | config = GEM_BF(CLK, GEM_CLK_DIV96); | |
788 | ||
789 | return config; | |
790 | } | |
791 | ||
32e4f6bf BS |
792 | /* |
793 | * Get the DMA bus width field of the network configuration register that we | |
794 | * should program. We find the width from decoding the design configuration | |
795 | * register to find the maximum supported data bus width. | |
796 | */ | |
797 | static u32 macb_dbw(struct macb_device *macb) | |
798 | { | |
799 | switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) { | |
800 | case 4: | |
801 | return GEM_BF(DBW, GEM_DBW128); | |
802 | case 2: | |
803 | return GEM_BF(DBW, GEM_DBW64); | |
804 | case 1: | |
805 | default: | |
806 | return GEM_BF(DBW, GEM_DBW32); | |
807 | } | |
808 | } | |
809 | ||
d5555b70 SG |
810 | static void _macb_eth_initialize(struct macb_device *macb) |
811 | { | |
812 | int id = 0; /* This is not used by functions we call */ | |
813 | u32 ncfgr; | |
814 | ||
815 | /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ | |
816 | macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, | |
817 | &macb->rx_buffer_dma); | |
818 | macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, | |
819 | &macb->rx_ring_dma); | |
820 | macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, | |
821 | &macb->tx_ring_dma); | |
822 | macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE, | |
823 | &macb->dummy_desc_dma); | |
824 | ||
825 | /* | |
826 | * Do some basic initialization so that we at least can talk | |
827 | * to the PHY | |
828 | */ | |
829 | if (macb_is_gem(macb)) { | |
830 | ncfgr = gem_mdc_clk_div(id, macb); | |
831 | ncfgr |= macb_dbw(macb); | |
832 | } else { | |
833 | ncfgr = macb_mdc_clk_div(id, macb); | |
834 | } | |
835 | ||
836 | macb_writel(macb, NCFGR, ncfgr); | |
837 | } | |
838 | ||
f1dcc19b | 839 | #ifndef CONFIG_DM_ETH |
d5555b70 SG |
840 | static int macb_send(struct eth_device *netdev, void *packet, int length) |
841 | { | |
842 | struct macb_device *macb = to_macb(netdev); | |
843 | ||
844 | return _macb_send(macb, netdev->name, packet, length); | |
845 | } | |
846 | ||
847 | static int macb_recv(struct eth_device *netdev) | |
848 | { | |
849 | struct macb_device *macb = to_macb(netdev); | |
850 | uchar *packet; | |
851 | int length; | |
852 | ||
853 | macb->wrapped = false; | |
854 | for (;;) { | |
855 | macb->next_rx_tail = macb->rx_tail; | |
856 | length = _macb_recv(macb, &packet); | |
857 | if (length >= 0) { | |
858 | net_process_received_packet(packet, length); | |
859 | reclaim_rx_buffers(macb, macb->next_rx_tail); | |
860 | } else if (length < 0) { | |
861 | return length; | |
862 | } | |
863 | } | |
864 | } | |
865 | ||
866 | static int macb_init(struct eth_device *netdev, bd_t *bd) | |
867 | { | |
868 | struct macb_device *macb = to_macb(netdev); | |
869 | ||
870 | return _macb_init(macb, netdev->name); | |
871 | } | |
872 | ||
873 | static void macb_halt(struct eth_device *netdev) | |
874 | { | |
875 | struct macb_device *macb = to_macb(netdev); | |
876 | ||
877 | return _macb_halt(macb); | |
878 | } | |
879 | ||
880 | static int macb_write_hwaddr(struct eth_device *netdev) | |
881 | { | |
882 | struct macb_device *macb = to_macb(netdev); | |
883 | ||
884 | return _macb_write_hwaddr(macb, netdev->enetaddr); | |
885 | } | |
886 | ||
5c1fe1ff HS |
887 | int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) |
888 | { | |
889 | struct macb_device *macb; | |
890 | struct eth_device *netdev; | |
5c1fe1ff HS |
891 | |
892 | macb = malloc(sizeof(struct macb_device)); | |
893 | if (!macb) { | |
894 | printf("Error: Failed to allocate memory for MACB%d\n", id); | |
895 | return -1; | |
896 | } | |
897 | memset(macb, 0, sizeof(struct macb_device)); | |
898 | ||
899 | netdev = &macb->netdev; | |
900 | ||
5c1fe1ff HS |
901 | macb->regs = regs; |
902 | macb->phy_addr = phy_addr; | |
903 | ||
d256be29 BS |
904 | if (macb_is_gem(macb)) |
905 | sprintf(netdev->name, "gmac%d", id); | |
906 | else | |
907 | sprintf(netdev->name, "macb%d", id); | |
908 | ||
5c1fe1ff HS |
909 | netdev->init = macb_init; |
910 | netdev->halt = macb_halt; | |
911 | netdev->send = macb_send; | |
912 | netdev->recv = macb_recv; | |
6bb46790 | 913 | netdev->write_hwaddr = macb_write_hwaddr; |
5c1fe1ff | 914 | |
d5555b70 | 915 | _macb_eth_initialize(macb); |
5c1fe1ff HS |
916 | |
917 | eth_register(netdev); | |
918 | ||
b1a0006e | 919 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) |
5a49f174 JH |
920 | int retval; |
921 | struct mii_dev *mdiodev = mdio_alloc(); | |
922 | if (!mdiodev) | |
923 | return -ENOMEM; | |
924 | strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN); | |
925 | mdiodev->read = macb_miiphy_read; | |
926 | mdiodev->write = macb_miiphy_write; | |
927 | ||
928 | retval = mdio_register(mdiodev); | |
929 | if (retval < 0) | |
930 | return retval; | |
b1a0006e | 931 | macb->bus = miiphy_get_dev_by_name(netdev->name); |
0f751d6e | 932 | #endif |
5c1fe1ff HS |
933 | return 0; |
934 | } | |
f1dcc19b SG |
935 | #endif /* !CONFIG_DM_ETH */ |
936 | ||
937 | #ifdef CONFIG_DM_ETH | |
938 | ||
939 | static int macb_start(struct udevice *dev) | |
940 | { | |
a212b66d | 941 | return _macb_init(dev, dev->name); |
f1dcc19b SG |
942 | } |
943 | ||
944 | static int macb_send(struct udevice *dev, void *packet, int length) | |
945 | { | |
946 | struct macb_device *macb = dev_get_priv(dev); | |
947 | ||
948 | return _macb_send(macb, dev->name, packet, length); | |
949 | } | |
950 | ||
951 | static int macb_recv(struct udevice *dev, int flags, uchar **packetp) | |
952 | { | |
953 | struct macb_device *macb = dev_get_priv(dev); | |
954 | ||
955 | macb->next_rx_tail = macb->rx_tail; | |
956 | macb->wrapped = false; | |
957 | ||
958 | return _macb_recv(macb, packetp); | |
959 | } | |
960 | ||
961 | static int macb_free_pkt(struct udevice *dev, uchar *packet, int length) | |
962 | { | |
963 | struct macb_device *macb = dev_get_priv(dev); | |
964 | ||
965 | reclaim_rx_buffers(macb, macb->next_rx_tail); | |
966 | ||
967 | return 0; | |
968 | } | |
969 | ||
970 | static void macb_stop(struct udevice *dev) | |
971 | { | |
972 | struct macb_device *macb = dev_get_priv(dev); | |
973 | ||
974 | _macb_halt(macb); | |
975 | } | |
976 | ||
977 | static int macb_write_hwaddr(struct udevice *dev) | |
978 | { | |
979 | struct eth_pdata *plat = dev_get_platdata(dev); | |
980 | struct macb_device *macb = dev_get_priv(dev); | |
981 | ||
982 | return _macb_write_hwaddr(macb, plat->enetaddr); | |
983 | } | |
984 | ||
985 | static const struct eth_ops macb_eth_ops = { | |
986 | .start = macb_start, | |
987 | .send = macb_send, | |
988 | .recv = macb_recv, | |
989 | .stop = macb_stop, | |
990 | .free_pkt = macb_free_pkt, | |
991 | .write_hwaddr = macb_write_hwaddr, | |
992 | }; | |
993 | ||
994 | static int macb_eth_probe(struct udevice *dev) | |
995 | { | |
996 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
997 | struct macb_device *macb = dev_get_priv(dev); | |
998 | ||
a212b66d WY |
999 | #ifdef CONFIG_DM_ETH |
1000 | const char *phy_mode; | |
1001 | ||
1002 | phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); | |
1003 | if (phy_mode) | |
1004 | macb->phy_interface = phy_get_interface_by_name(phy_mode); | |
1005 | if (macb->phy_interface == -1) { | |
1006 | debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); | |
1007 | return -EINVAL; | |
1008 | } | |
1009 | #endif | |
1010 | ||
f1dcc19b SG |
1011 | macb->regs = (void *)pdata->iobase; |
1012 | ||
1013 | _macb_eth_initialize(macb); | |
1014 | #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) | |
5a49f174 JH |
1015 | int retval; |
1016 | struct mii_dev *mdiodev = mdio_alloc(); | |
1017 | if (!mdiodev) | |
1018 | return -ENOMEM; | |
1019 | strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); | |
1020 | mdiodev->read = macb_miiphy_read; | |
1021 | mdiodev->write = macb_miiphy_write; | |
1022 | ||
1023 | retval = mdio_register(mdiodev); | |
1024 | if (retval < 0) | |
1025 | return retval; | |
f1dcc19b SG |
1026 | macb->bus = miiphy_get_dev_by_name(dev->name); |
1027 | #endif | |
1028 | ||
1029 | return 0; | |
1030 | } | |
1031 | ||
1032 | static int macb_eth_ofdata_to_platdata(struct udevice *dev) | |
1033 | { | |
1034 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
1035 | ||
1036 | pdata->iobase = dev_get_addr(dev); | |
1037 | return 0; | |
1038 | } | |
1039 | ||
1040 | static const struct udevice_id macb_eth_ids[] = { | |
1041 | { .compatible = "cdns,macb" }, | |
1042 | { } | |
1043 | }; | |
1044 | ||
1045 | U_BOOT_DRIVER(eth_macb) = { | |
1046 | .name = "eth_macb", | |
1047 | .id = UCLASS_ETH, | |
1048 | .of_match = macb_eth_ids, | |
1049 | .ofdata_to_platdata = macb_eth_ofdata_to_platdata, | |
1050 | .probe = macb_eth_probe, | |
1051 | .ops = &macb_eth_ops, | |
1052 | .priv_auto_alloc_size = sizeof(struct macb_device), | |
1053 | .platdata_auto_alloc_size = sizeof(struct eth_pdata), | |
1054 | }; | |
1055 | #endif | |
5c1fe1ff | 1056 | |
07d38a17 | 1057 | #endif |