1 /*
2 * Copyright (c) 2026 Justin Hibbits
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/param.h>
8 #include <sys/systm.h>
9 #include <sys/bus.h>
10 #include <sys/kernel.h>
11 #include <sys/malloc.h>
12 #include <sys/mbuf.h>
13 #include <sys/module.h>
14 #include <sys/rman.h>
15 #include <sys/socket.h>
16 #include <sys/sysctl.h>
17 #include <sys/sockio.h>
18
19 #include <machine/bus.h>
20 #include <machine/resource.h>
21
22 #include <net/ethernet.h>
23 #include <net/if.h>
24 #include <net/if_dl.h>
25 #include <net/if_media.h>
26 #include <net/if_types.h>
27 #include <net/if_arp.h>
28
29 #include <dev/mii/mii.h>
30 #include <dev/mii/miivar.h>
31 #include <dev/ofw/ofw_bus.h>
32 #include <dev/ofw/ofw_bus_subr.h>
33 #include <dev/ofw/openfirm.h>
34
35 #include "miibus_if.h"
36
37 #include "dpaa_eth.h"
38 #include "fman.h"
39 #include "fman_port.h"
40 #include "if_memac.h"
41
42 #include "fman_if.h"
43 #include "fman_port_if.h"
44
45 #define MEMAC_MIN_FRAME_SIZE 64
46 #define MEMAC_MAX_FRAME_SIZE 32736
47
48 #define MEMAC_COMMAND_CONFIG 0x008
49 #define COMMAND_CONFIG_RXSTP 0x20000000
50 #define COMMAND_CONFIG_NO_LEN_CHK 0x00020000
51 #define COMMAND_CONFIG_SWR 0x00001000
52 #define COMMAND_CONFIG_TXP 0x00000800
53 #define COMMAND_CONFIG_CRC 0x00000040
54 #define COMMAND_CONFIG_PROMISC 0x00000010
55 #define COMMAND_CONFIG_RX_EN 0x00000002
56 #define COMMAND_CONFIG_TX_EN 0x00000001
57 #define MEMAC_MAC_ADDR_0 0x00c
58 #define MEMAC_MAC_ADDR_1 0x010
59 #define MEMAC_REG_MAXFRM 0x14
60 #define MEMAC_REG_TX_FIFO_SECTIONS 0x020
61 #define TX_FIFO_SECTIONS_TX_EMPTY_M 0xffff0000
62 #define TX_FIFO_SECTIONS_TX_EMPTY_S 16
63 #define TX_FIFO_SECTIONS_TX_AVAIL_M 0x0000ffff
64
65 #define HASHTABLE_CTRL 0x02c
66 #define CTRL_MCAST 0x00000100
67 #define CTRL_HASH_ADDR_M 0x0000003f
68 #define HASHTABLE_SIZE 64
69 #define MEMAC_IEVENT 0x040
70 #define IEVENT_RX_EMPTY 0x00000040
71 #define IEVENT_TX_EMPTY 0x00000020
72 #define MEMAC_CL01_PAUSE_QUANTA 0x054
73 #define MEMAC_IF_MODE 0x300
74 #define IF_MODE_ENA 0x00008000
75 #define IF_MODE_SSP_M 0x00006000
76 #define IF_MODE_SSP_100MB 0x00000000
77 #define IF_MODE_SSP_10MB 0x00002000
78 #define IF_MODE_SSP_1GB 0x00004000
79 #define IF_MODE_SFD 0x00001000
80 #define IF_MODE_MSG 0x00000200
81 #define IF_MODE_HG 0x00000100
82 #define IF_MODE_HD 0x00000040
83 #define IF_MODE_RLP 0x00000020
84 #define IF_MODE_RG 0x00000004
85 #define IF_MODE_IFMODE_M 0x00000003
86 #define IF_MODE_IFMODE_XGMII 0x00000000
87 #define IF_MODE_IFMODE_MII 0x00000001
88 #define IF_MODE_IFMODE_GMII 0x00000002
89
90 #define DEFAULT_PAUSE_QUANTA 0xf000
91
92
93 /**
94 * @group FMan MAC routines.
95 * @{
96 */
97 #define MEMAC_MAC_EXCEPTIONS_END (-1)
98
99 static void memac_if_init_locked(struct memac_softc *sc);
100
101 static int
memac_fm_mac_init(struct memac_softc * sc,uint8_t * mac)102 memac_fm_mac_init(struct memac_softc *sc, uint8_t *mac)
103 {
104 uint32_t reg;
105
106 FMAN_GET_REVISION(device_get_parent(sc->sc_base.sc_dev), &sc->sc_base.sc_rev_major,
107 &sc->sc_base.sc_rev_minor);
108
109 if (FMAN_RESET_MAC(device_get_parent(sc->sc_base.sc_dev), sc->sc_base.sc_eth_id) != 0)
110 return (ENXIO);
111
112 reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
113 reg |= COMMAND_CONFIG_SWR;
114 bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG, reg);
115
116 while (bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG) & COMMAND_CONFIG_SWR)
117 ;
118
119 /* TODO: TX_FIFO_SECTIONS */
120 /* TODO: CL01 pause quantum */
121 bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG,
122 COMMAND_CONFIG_NO_LEN_CHK | COMMAND_CONFIG_TXP | COMMAND_CONFIG_CRC);
123
124 reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_IF_MODE);
125 reg &= ~(IF_MODE_IFMODE_M | IF_MODE_RG);
126 switch (sc->sc_base.sc_mac_enet_mode) {
127 case MII_CONTYPE_RGMII:
128 reg |= IF_MODE_RG;
129 /* FALLTHROUGH */
130 case MII_CONTYPE_GMII:
131 case MII_CONTYPE_SGMII:
132 case MII_CONTYPE_QSGMII:
133 reg |= IF_MODE_IFMODE_GMII;
134 break;
135 case MII_CONTYPE_RMII:
136 reg |= IF_MODE_RG;
137 /* FALLTHROUGH */
138 case MII_CONTYPE_MII:
139 reg |= IF_MODE_IFMODE_MII;
140 break;
141 }
142
143 bus_write_4(sc->sc_base.sc_mem, MEMAC_IF_MODE, reg);
144
145 return (0);
146 }
147 /** @} */
148
149
150 /**
151 * @group IFnet routines.
152 * @{
153 */
154 static int
memac_set_mtu(struct memac_softc * sc,unsigned int mtu)155 memac_set_mtu(struct memac_softc *sc, unsigned int mtu)
156 {
157
158 mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN;
159
160 MEMAC_LOCK_ASSERT(sc);
161
162 if (mtu >= MEMAC_MIN_FRAME_SIZE && mtu <= MEMAC_MAX_FRAME_SIZE) {
163 bus_write_4(sc->sc_base.sc_mem, MEMAC_REG_MAXFRM, mtu);
164 return (mtu);
165 }
166
167 return (0);
168 }
169
170 static u_int
memac_hash_maddr(void * arg,struct sockaddr_dl * sdl,u_int cnt)171 memac_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
172 {
173 struct memac_softc *sc = arg;
174 uint8_t *addr = LLADDR(sdl);
175 uint32_t hash = 0;
176 uint8_t a, h;
177
178 /* Hash is 6 bits, composed if [XOR{47:40},XOR{39:32},....] */
179 for (int i = 0; i < 6; i++) {
180 a = addr[i];
181 h = 0;
182 for (int j = 0; j < 8; j++, a >>= 1) {
183 h ^= (a & 0x1);
184 }
185 hash |= (h << i);
186 }
187 bus_write_4(sc->sc_base.sc_mem, HASHTABLE_CTRL, hash | CTRL_MCAST);
188
189 return (1);
190 }
191
192 static void
memac_setup_multicast(struct memac_softc * sc)193 memac_setup_multicast(struct memac_softc *sc)
194 {
195
196 if (if_getflags(sc->sc_base.sc_ifnet) & IFF_ALLMULTI) {
197 for (int i = 0; i < HASHTABLE_SIZE; i++)
198 bus_write_4(sc->sc_base.sc_mem,
199 HASHTABLE_CTRL, CTRL_MCAST | i);
200 } else {
201 /* Clear the hash table */
202 for (int i = 0; i < HASHTABLE_SIZE; i++)
203 bus_write_4(sc->sc_base.sc_mem,
204 HASHTABLE_CTRL, i);
205 }
206
207 if_foreach_llmaddr(sc->sc_base.sc_ifnet, memac_hash_maddr, sc);
208 }
209
210 static void
memac_setup_promisc(struct memac_softc * sc)211 memac_setup_promisc(struct memac_softc *sc)
212 {
213 uint32_t reg;
214
215 reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
216 reg &= ~COMMAND_CONFIG_PROMISC;
217
218 if ((if_getflags(sc->sc_base.sc_ifnet) & IFF_PROMISC) != 0)
219 bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG,
220 reg | COMMAND_CONFIG_PROMISC);
221 }
222
223 static void
memac_if_graceful_stop(struct memac_softc * sc)224 memac_if_graceful_stop(struct memac_softc *sc)
225 {
226 struct resource *regs = sc->sc_base.sc_mem;
227 uint32_t reg;
228
229 reg = bus_read_4(regs, MEMAC_COMMAND_CONFIG);
230 reg |= COMMAND_CONFIG_RXSTP;
231
232 bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg);
233 while ((bus_read_4(regs, MEMAC_IEVENT) & IEVENT_RX_EMPTY) == 0)
234 ;
235 reg &= COMMAND_CONFIG_RX_EN;
236 bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg);
237
238 while ((bus_read_4(regs, MEMAC_IEVENT) & IEVENT_TX_EMPTY) == 0)
239 ;
240 bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg & ~COMMAND_CONFIG_TX_EN);
241 }
242
243 static void
memac_mac_enable(struct memac_softc * sc)244 memac_mac_enable(struct memac_softc *sc)
245 {
246 uint32_t reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
247
248 reg |= (COMMAND_CONFIG_RX_EN | COMMAND_CONFIG_TX_EN);
249
250 bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG, reg);
251 }
252
253 static int
memac_if_enable_locked(struct memac_softc * sc)254 memac_if_enable_locked(struct memac_softc *sc)
255 {
256 int error;
257
258 MEMAC_LOCK_ASSERT(sc);
259
260 memac_set_mtu(sc, if_getmtu(sc->sc_base.sc_ifnet));
261 memac_mac_enable(sc);
262
263 error = FMAN_PORT_ENABLE(sc->sc_base.sc_rx_port);
264 if (error != 0)
265 return (EIO);
266
267 error = FMAN_PORT_ENABLE(sc->sc_base.sc_tx_port);
268 if (error != 0)
269 return (EIO);
270
271 bus_write_4(sc->sc_base.sc_mem, MEMAC_IEVENT, 0);
272 memac_setup_multicast(sc);
273 memac_setup_promisc(sc);
274
275 if_setdrvflagbits(sc->sc_base.sc_ifnet, IFF_DRV_RUNNING, 0);
276
277 /* Refresh link state */
278 memac_miibus_statchg(sc->sc_base.sc_dev);
279
280 return (0);
281 }
282
283 static int
memac_if_disable_locked(struct memac_softc * sc)284 memac_if_disable_locked(struct memac_softc *sc)
285 {
286 int error;
287
288 MEMAC_LOCK_ASSERT(sc);
289
290 error = FMAN_PORT_DISABLE(sc->sc_base.sc_tx_port);
291 if (error != 0)
292 return (EIO);
293
294 memac_if_graceful_stop(sc);
295
296 error = FMAN_PORT_DISABLE(sc->sc_base.sc_rx_port);
297 if (error != 0)
298 return (EIO);
299
300 if_setdrvflagbits(sc->sc_base.sc_ifnet, 0, IFF_DRV_RUNNING);
301
302 return (0);
303 }
304
305 static int
memac_if_ioctl(if_t ifp,u_long command,caddr_t data)306 memac_if_ioctl(if_t ifp, u_long command, caddr_t data)
307 {
308 struct memac_softc *sc;
309 struct ifreq *ifr;
310 uint32_t changed;
311 int error;
312
313 sc = if_getsoftc(ifp);
314 ifr = (struct ifreq *)data;
315 error = 0;
316
317 /* Basic functionality to achieve media status reports */
318 switch (command) {
319 case SIOCSIFMTU:
320 MEMAC_LOCK(sc);
321 if (memac_set_mtu(sc, ifr->ifr_mtu))
322 if_setmtu(ifp, ifr->ifr_mtu);
323 else
324 error = EINVAL;
325 MEMAC_UNLOCK(sc);
326 break;
327 case SIOCSIFFLAGS:
328 MEMAC_LOCK(sc);
329 if (if_getflags(ifp) & IFF_UP) {
330 if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))
331 memac_if_init_locked(sc);
332 } else if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
333 error = memac_if_disable_locked(sc);
334
335 MEMAC_UNLOCK(sc);
336 break;
337
338 case SIOCADDMULTI:
339 case SIOCDELMULTI:
340 if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) {
341 MEMAC_LOCK(sc);
342 memac_setup_multicast(sc);
343 MEMAC_UNLOCK(sc);
344 }
345 break;
346
347 case SIOCSIFCAP:
348 changed = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
349 if ((changed & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0)
350 if_togglecapenable(ifp,
351 IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
352 if ((changed & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) != 0) {
353 if_togglecapenable(ifp,
354 IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
355 if_togglehwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
356 }
357 if ((changed & IFCAP_LRO) != 0)
358 if_togglecapenable(ifp, IFCAP_LRO);
359 break;
360
361 case SIOCGIFMEDIA:
362 case SIOCSIFMEDIA:
363 error = ifmedia_ioctl(ifp, ifr, &sc->sc_base.sc_mii->mii_media,
364 command);
365 break;
366
367 default:
368 error = ether_ioctl(ifp, command, data);
369 }
370
371 return (error);
372 }
373
374 static void
memac_if_tick(void * arg)375 memac_if_tick(void *arg)
376 {
377 struct memac_softc *sc;
378
379 sc = arg;
380
381 /* TODO */
382 MEMAC_LOCK(sc);
383
384 mii_tick(sc->sc_base.sc_mii);
385 callout_reset(&sc->sc_base.sc_tick_callout, hz, memac_if_tick, sc);
386
387 MEMAC_UNLOCK(sc);
388 }
389
390 static void
memac_if_deinit_locked(struct memac_softc * sc)391 memac_if_deinit_locked(struct memac_softc *sc)
392 {
393
394 MEMAC_LOCK_ASSERT(sc);
395
396 MEMAC_UNLOCK(sc);
397 callout_drain(&sc->sc_base.sc_tick_callout);
398 MEMAC_LOCK(sc);
399 }
400
401 static void
memac_if_set_macaddr(struct memac_softc * sc,const char * addr)402 memac_if_set_macaddr(struct memac_softc *sc, const char *addr)
403 {
404 uint32_t reg;
405
406 reg = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
407 bus_write_4(sc->sc_base.sc_mem, MEMAC_MAC_ADDR_0, reg);
408 reg = (addr[5] << 8) | (addr[4]);
409 bus_write_4(sc->sc_base.sc_mem, MEMAC_MAC_ADDR_1, reg);
410 }
411
412 static void
memac_if_init_locked(struct memac_softc * sc)413 memac_if_init_locked(struct memac_softc *sc)
414 {
415 int error;
416 const char *macaddr;
417
418 MEMAC_LOCK_ASSERT(sc);
419
420 macaddr = if_getlladdr(sc->sc_base.sc_ifnet);
421 memac_if_set_macaddr(sc, macaddr);
422
423 /* Start MII polling */
424 if (sc->sc_base.sc_mii)
425 callout_reset(&sc->sc_base.sc_tick_callout, hz,
426 memac_if_tick, sc);
427
428 if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) {
429 error = memac_if_enable_locked(sc);
430 if (error != 0)
431 goto err;
432 } else {
433 error = memac_if_disable_locked(sc);
434 if (error != 0)
435 goto err;
436 }
437
438 if_link_state_change(sc->sc_base.sc_ifnet, LINK_STATE_UP);
439
440 bus_write_4(sc->sc_base.sc_mem, MEMAC_CL01_PAUSE_QUANTA,
441 DEFAULT_PAUSE_QUANTA);
442
443 return;
444
445 err:
446 memac_if_deinit_locked(sc);
447 device_printf(sc->sc_base.sc_dev, "initialization error.\n");
448 return;
449 }
450
451 static void
memac_if_init(void * data)452 memac_if_init(void *data)
453 {
454 struct memac_softc *sc;
455
456 sc = data;
457
458 MEMAC_LOCK(sc);
459 memac_if_init_locked(sc);
460 MEMAC_UNLOCK(sc);
461 }
462
463 static void
memac_if_start(if_t ifp)464 memac_if_start(if_t ifp)
465 {
466 struct memac_softc *sc;
467
468 sc = if_getsoftc(ifp);
469 MEMAC_LOCK(sc);
470 dpaa_eth_if_start_locked(&sc->sc_base);
471 MEMAC_UNLOCK(sc);
472 }
473
474 static void
memac_if_watchdog(if_t ifp)475 memac_if_watchdog(if_t ifp)
476 {
477 /* TODO */
478 }
479 /** @} */
480
481
482 /**
483 * @group IFmedia routines.
484 * @{
485 */
486 static int
memac_ifmedia_upd(if_t ifp)487 memac_ifmedia_upd(if_t ifp)
488 {
489 struct memac_softc *sc = if_getsoftc(ifp);
490
491 return (0);
492 MEMAC_LOCK(sc);
493 mii_mediachg(sc->sc_base.sc_mii);
494 MEMAC_UNLOCK(sc);
495
496 return (0);
497 }
498
499 static void
memac_ifmedia_fixed_sts(if_t ifp,struct ifmediareq * ifmr)500 memac_ifmedia_fixed_sts(if_t ifp, struct ifmediareq *ifmr)
501 {
502 struct memac_softc *sc = if_getsoftc(ifp);
503
504 MEMAC_LOCK(sc);
505 ifmr->ifm_count = 1;
506 ifmr->ifm_mask = 0;
507 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
508 ifmr->ifm_current = ifmr->ifm_active =
509 sc->sc_base.sc_mii->mii_media.ifm_cur->ifm_media;
510 ifmr->ifm_active = ifmr->ifm_current;
511
512 /*
513 * In non-PHY usecases, we need to signal link state up, otherwise
514 * certain things requiring a link event (e.g async DHCP client) from
515 * devd do not happen.
516 */
517 if (if_getlinkstate(ifp) == LINK_STATE_UNKNOWN) {
518 if_link_state_change(ifp, LINK_STATE_UP);
519 }
520
521 /* We assume the link is static, as in a peer switch. */
522
523 MEMAC_UNLOCK(sc);
524
525 return;
526 }
527
528 static void
memac_ifmedia_sts(if_t ifp,struct ifmediareq * ifmr)529 memac_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
530 {
531 struct memac_softc *sc = if_getsoftc(ifp);
532
533 MEMAC_LOCK(sc);
534
535 mii_pollstat(sc->sc_base.sc_mii);
536
537 ifmr->ifm_active = sc->sc_base.sc_mii->mii_media_active;
538 ifmr->ifm_status = sc->sc_base.sc_mii->mii_media_status;
539
540 MEMAC_UNLOCK(sc);
541 }
542 /** @} */
543
544
545 /**
546 * @group dTSEC bus interface.
547 * @{
548 */
549
550 int
memac_attach(device_t dev)551 memac_attach(device_t dev)
552 {
553 struct memac_softc *sc;
554 int error;
555 if_t ifp;
556
557 sc = device_get_softc(dev);
558
559 sc->sc_base.sc_dev = dev;
560
561 /* Init locks */
562 mtx_init(&sc->sc_base.sc_lock, device_get_nameunit(dev),
563 "mEMAC Global Lock", MTX_DEF);
564
565 mtx_init(&sc->sc_base.sc_mii_lock, device_get_nameunit(dev),
566 "mEMAC MII Lock", MTX_DEF);
567
568 /* Init callouts */
569 callout_init(&sc->sc_base.sc_tick_callout, CALLOUT_MPSAFE);
570
571 /* Create network interface for upper layers */
572 ifp = sc->sc_base.sc_ifnet = if_alloc(IFT_ETHER);
573
574 /* Create RX buffer pool */
575 error = dpaa_eth_pool_rx_init(&sc->sc_base);
576 if (error != 0)
577 return (EIO);
578
579 /* Create RX frame queue range */
580 error = dpaa_eth_fq_rx_init(&sc->sc_base);
581 if (error != 0)
582 return (EIO);
583
584 /* Create frame info pool */
585 error = dpaa_eth_fi_pool_init(&sc->sc_base);
586 if (error != 0)
587 return (EIO);
588
589 /* Create TX frame queue range */
590 error = dpaa_eth_fq_tx_init(&sc->sc_base);
591 if (error != 0)
592 return (EIO);
593
594 /* Init FMan MAC module. */
595 error = memac_fm_mac_init(sc, sc->sc_base.sc_mac_addr);
596 if (error != 0) {
597 memac_detach(dev);
598 return (ENXIO);
599 }
600
601 dpaa_eth_fm_port_rx_init(&sc->sc_base);
602 dpaa_eth_fm_port_tx_init(&sc->sc_base);
603
604 if_setsoftc(ifp, sc);
605
606 if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST);
607 if_setinitfn(ifp, memac_if_init);
608 if_setstartfn(ifp, memac_if_start);
609 if_setioctlfn(ifp, memac_if_ioctl);
610 if_setsendqlen(ifp, IFQ_MAXLEN);
611 if_setsendqready(ifp);
612
613 if (sc->sc_base.sc_phy_addr >= 0)
614 if_initname(ifp, device_get_name(sc->sc_base.sc_dev),
615 device_get_unit(sc->sc_base.sc_dev));
616 else
617 if_initname(ifp, "memac_phy",
618 device_get_unit(sc->sc_base.sc_dev));
619
620
621 if_setcapabilities(ifp, IFCAP_JUMBO_MTU |
622 IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM |
623 IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 |
624 IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 |
625 IFCAP_LRO);
626 if_setcapenable(ifp, if_getcapabilities(ifp));
627 if_sethwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
628
629 /* Attach PHY(s) */
630 if (!sc->sc_fixed_link) {
631 error = mii_attach(sc->sc_base.sc_dev, &sc->sc_base.sc_mii_dev,
632 ifp, memac_ifmedia_upd, memac_ifmedia_sts, BMSR_DEFCAPMASK,
633 sc->sc_base.sc_phy_addr, MII_OFFSET_ANY, 0);
634 if (error) {
635 device_printf(sc->sc_base.sc_dev,
636 "attaching PHYs failed: %d\n", error);
637 memac_detach(sc->sc_base.sc_dev);
638 return (error);
639 }
640 sc->sc_base.sc_mii = device_get_softc(sc->sc_base.sc_mii_dev);
641 } else {
642 phandle_t node;
643 uint32_t type = IFM_ETHER;
644 uint32_t speed;
645
646 node = ofw_bus_find_child(ofw_bus_get_node(dev), "fixed-link");
647 if (OF_getencprop(node, "speed", &speed, sizeof(speed)) <= 0) {
648 device_printf(dev,
649 "fixed link has no speed property\n");
650 memac_detach(sc->sc_base.sc_dev);
651 return (ENXIO);
652 }
653 switch (speed) {
654 case 10:
655 type |= IFM_10_T;
656 break;
657 case 100:
658 type |= IFM_100_TX;
659 break;
660 case 1000:
661 type |= IFM_1000_T;
662 break;
663 case 2500:
664 type |= IFM_2500_T;
665 break;
666 case 5000:
667 type |= IFM_5000_T;
668 break;
669 case 10000:
670 type |= IFM_10G_T;
671 break;
672 }
673 if (OF_hasprop(node, "full-duplex"))
674 type |= IFM_FDX;
675 sc->sc_base.sc_mii = malloc(sizeof(*sc->sc_base.sc_mii),
676 M_DEVBUF, M_WAITOK | M_ZERO);
677 ifmedia_init(&sc->sc_base.sc_mii->mii_media, 0,
678 memac_ifmedia_upd, memac_ifmedia_fixed_sts);
679 ifmedia_add(&sc->sc_base.sc_mii->mii_media, type, 0, NULL);
680 ifmedia_set(&sc->sc_base.sc_mii->mii_media, type);
681 }
682
683 /* Attach to stack */
684 ether_ifattach(ifp, sc->sc_base.sc_mac_addr);
685
686 return (0);
687 }
688
689 int
memac_detach(device_t dev)690 memac_detach(device_t dev)
691 {
692 struct memac_softc *sc;
693 if_t ifp;
694
695 sc = device_get_softc(dev);
696 ifp = sc->sc_base.sc_ifnet;
697
698 if (device_is_attached(dev)) {
699 ether_ifdetach(ifp);
700 /* Shutdown interface */
701 MEMAC_LOCK(sc);
702 memac_if_deinit_locked(sc);
703 MEMAC_UNLOCK(sc);
704 }
705
706 if (sc->sc_base.sc_ifnet) {
707 if_free(sc->sc_base.sc_ifnet);
708 sc->sc_base.sc_ifnet = NULL;
709 }
710
711 /* Free RX/TX FQRs */
712 dpaa_eth_fq_rx_free(&sc->sc_base);
713 dpaa_eth_fq_tx_free(&sc->sc_base);
714
715 /* Free frame info pool */
716 dpaa_eth_fi_pool_free(&sc->sc_base);
717
718 /* Free RX buffer pool */
719 dpaa_eth_pool_rx_free(&sc->sc_base);
720
721 /* Destroy lock */
722 mtx_destroy(&sc->sc_base.sc_lock);
723
724 return (0);
725 }
726
727 int
memac_suspend(device_t dev)728 memac_suspend(device_t dev)
729 {
730
731 return (0);
732 }
733
734 int
memac_resume(device_t dev)735 memac_resume(device_t dev)
736 {
737
738 return (0);
739 }
740
741 int
memac_shutdown(device_t dev)742 memac_shutdown(device_t dev)
743 {
744
745 return (0);
746 }
747 /** @} */
748
749
750 /**
751 * @group MII bus interface.
752 * @{
753 */
754 int
memac_miibus_readreg(device_t dev,int phy,int reg)755 memac_miibus_readreg(device_t dev, int phy, int reg)
756 {
757 struct memac_softc *sc;
758
759 sc = device_get_softc(dev);
760
761 return (MIIBUS_READREG(sc->sc_base.sc_mdio, phy, reg));
762 }
763
764 int
memac_miibus_writereg(device_t dev,int phy,int reg,int value)765 memac_miibus_writereg(device_t dev, int phy, int reg, int value)
766 {
767
768 struct memac_softc *sc;
769
770 sc = device_get_softc(dev);
771
772 return (MIIBUS_WRITEREG(sc->sc_base.sc_mdio, phy, reg, value));
773 }
774
775 void
memac_miibus_statchg(device_t dev)776 memac_miibus_statchg(device_t dev)
777 {
778 struct memac_softc *sc;
779 uint32_t reg;
780 bool duplex;
781 int speed;
782
783 sc = device_get_softc(dev);
784
785 MEMAC_LOCK_ASSERT(sc);
786
787 duplex = ((sc->sc_base.sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
788
789 switch (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active)) {
790 case IFM_AUTO:
791 speed = IF_MODE_ENA;
792 break;
793 case IFM_1000_T:
794 case IFM_1000_SX:
795 if (!duplex) {
796 device_printf(sc->sc_base.sc_dev,
797 "Only full-duplex supported for 1Gbps speeds");
798 return;
799 }
800 speed = IF_MODE_SSP_1GB;
801 break;
802
803 case IFM_100_TX:
804 speed = IF_MODE_SSP_100MB;
805 break;
806 default:
807 speed = IF_MODE_SSP_10MB;
808 break;
809 }
810
811 reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_IF_MODE);
812 reg &= ~(IF_MODE_ENA | IF_MODE_SSP_M | IF_MODE_SFD);
813 reg |= 0x2;
814
815 if (duplex)
816 reg |= IF_MODE_SFD;
817 else
818 reg |= IF_MODE_HD;
819 reg |= speed;
820 bus_write_4(sc->sc_base.sc_mem, MEMAC_IF_MODE, reg);
821 }
822 /** @} */
823