source: rtems-libbsd/freebsd/sys/dev/dwc/if_dwc.c @ 6cd057d

55-freebsd-126-freebsd-12
Last change on this file since 6cd057d was 6cd057d, checked in by Sebastian Huber <sebastian.huber@…>, on 01/10/17 at 07:52:14

if_dwc: Fix IFCOUNTER_IPACKETS statistics

Input packets are counted in dwc_harvest_stats() as well.

  • Property mode set to 100644
File size: 32.6 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
5 * All rights reserved.
6 *
7 * This software was developed by SRI International and the University of
8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9 * ("CTSRD"), as part of the DARPA CRASH research programme.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Ethernet media access controller (EMAC)
35 * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
36 *
37 * EMAC is an instance of the Synopsys DesignWare 3504-0
38 * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD$");
43
44#include <rtems/bsd/sys/param.h>
45#include <sys/systm.h>
46#include <sys/bus.h>
47#include <sys/gpio.h>
48#include <sys/kernel.h>
49#include <rtems/bsd/sys/lock.h>
50#include <sys/malloc.h>
51#include <sys/mbuf.h>
52#include <sys/module.h>
53#include <sys/mutex.h>
54#include <sys/rman.h>
55#include <sys/socket.h>
56#include <sys/sockio.h>
57
58#include <net/bpf.h>
59#include <net/if.h>
60#include <net/ethernet.h>
61#include <net/if_dl.h>
62#include <net/if_media.h>
63#include <net/if_types.h>
64#include <net/if_var.h>
65
66#include <machine/bus.h>
67
68#include <dev/dwc/if_dwc.h>
69#include <dev/dwc/if_dwcvar.h>
70#include <dev/mii/mii.h>
71#include <dev/mii/miivar.h>
72#ifndef __rtems__
73#include <dev/ofw/ofw_bus.h>
74#include <dev/ofw/ofw_bus_subr.h>
75#endif /* __rtems__ */
76
77#ifdef EXT_RESOURCES
78#include <dev/extres/clk/clk.h>
79#include <dev/extres/hwreset/hwreset.h>
80#endif
81
82#include <rtems/bsd/local/if_dwc_if.h>
83#include <rtems/bsd/local/gpio_if.h>
84#include <rtems/bsd/local/miibus_if.h>
85
86#define READ4(_sc, _reg) \
87        bus_read_4((_sc)->res[0], _reg)
88#define WRITE4(_sc, _reg, _val) \
89        bus_write_4((_sc)->res[0], _reg, _val)
90
91#define MAC_RESET_TIMEOUT       100
92#define WATCHDOG_TIMEOUT_SECS   5
93#define STATS_HARVEST_INTERVAL  2
94
95#define DWC_LOCK(sc)                    mtx_lock(&(sc)->mtx)
96#define DWC_UNLOCK(sc)                  mtx_unlock(&(sc)->mtx)
97#define DWC_ASSERT_LOCKED(sc)           mtx_assert(&(sc)->mtx, MA_OWNED)
98#define DWC_ASSERT_UNLOCKED(sc)         mtx_assert(&(sc)->mtx, MA_NOTOWNED)
99
100#define DDESC_TDES0_OWN                 (1U << 31)
101#define DDESC_TDES0_TXINT               (1U << 30)
102#define DDESC_TDES0_TXLAST              (1U << 29)
103#define DDESC_TDES0_TXFIRST             (1U << 28)
104#define DDESC_TDES0_TXCRCDIS            (1U << 27)
105#define DDESC_TDES0_TXRINGEND           (1U << 21)
106#define DDESC_TDES0_TXCHAIN             (1U << 20)
107
108#define DDESC_RDES0_OWN                 (1U << 31)
109#define DDESC_RDES0_FL_MASK             0x3fff
110#define DDESC_RDES0_FL_SHIFT            16      /* Frame Length */
111#define DDESC_RDES1_CHAINED             (1U << 14)
112
113/* Alt descriptor bits. */
114#define DDESC_CNTL_TXINT                (1U << 31)
115#define DDESC_CNTL_TXLAST               (1U << 30)
116#define DDESC_CNTL_TXFIRST              (1U << 29)
117#define DDESC_CNTL_TXCRCDIS             (1U << 26)
118#define DDESC_CNTL_TXRINGEND            (1U << 25)
119#define DDESC_CNTL_TXCHAIN              (1U << 24)
120
121#define DDESC_CNTL_CHAINED              (1U << 24)
122
123/*
124 * A hardware buffer descriptor.  Rx and Tx buffers have the same descriptor
125 * layout, but the bits in the fields have different meanings.
126 */
127struct dwc_hwdesc
128{
129        uint32_t tdes0;         /* status for alt layout */
130        uint32_t tdes1;         /* cntl for alt layout */
131        uint32_t addr;          /* pointer to buffer data */
132        uint32_t addr_next;     /* link to next descriptor */
133};
134
135/*
136 * The hardware imposes alignment restrictions on various objects involved in
137 * DMA transfers.  These values are expressed in bytes (not bits).
138 */
139#define DWC_DESC_RING_ALIGN             2048
140
141static struct resource_spec dwc_spec[] = {
142        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
143        { SYS_RES_IRQ,          0,      RF_ACTIVE },
144        { -1, 0 }
145};
146
147static void dwc_txfinish_locked(struct dwc_softc *sc);
148static void dwc_rxfinish_locked(struct dwc_softc *sc);
149static void dwc_stop_locked(struct dwc_softc *sc);
150static void dwc_setup_rxfilter(struct dwc_softc *sc);
151
152static inline uint32_t
153next_rxidx(struct dwc_softc *sc, uint32_t curidx)
154{
155
156        return ((curidx + 1) % RX_DESC_COUNT);
157}
158
159static inline uint32_t
160next_txidx(struct dwc_softc *sc, uint32_t curidx)
161{
162
163        return ((curidx + 1) % TX_DESC_COUNT);
164}
165
166static void
167dwc_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
168{
169
170        if (error != 0)
171                return;
172        *(bus_addr_t *)arg = segs[0].ds_addr;
173}
174
175inline static uint32_t
176dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
177    uint32_t len)
178{
179        uint32_t flags;
180        uint32_t nidx;
181
182        nidx = next_txidx(sc, idx);
183
184        /* Addr/len 0 means we're clearing the descriptor after xmit done. */
185        if (paddr == 0 || len == 0) {
186                flags = 0;
187                --sc->txcount;
188        } else {
189                if (sc->mactype == DWC_GMAC_ALT_DESC)
190                        flags = DDESC_CNTL_TXCHAIN | DDESC_CNTL_TXFIRST
191                            | DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT;
192                else
193                        flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
194                            | DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
195                ++sc->txcount;
196        }
197
198        sc->txdesc_ring[idx].addr = (uint32_t)(paddr);
199        if (sc->mactype == DWC_GMAC_ALT_DESC) {
200                sc->txdesc_ring[idx].tdes0 = 0;
201                sc->txdesc_ring[idx].tdes1 = flags | len;
202        } else {
203                sc->txdesc_ring[idx].tdes0 = flags;
204                sc->txdesc_ring[idx].tdes1 = len;
205        }
206
207        if (paddr && len) {
208                wmb();
209                sc->txdesc_ring[idx].tdes0 |= DDESC_TDES0_OWN;
210                wmb();
211        }
212
213        return (nidx);
214}
215
216static int
217dwc_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp)
218{
219        struct bus_dma_segment seg;
220        int error, nsegs;
221        struct mbuf * m;
222
223        if ((m = m_defrag(*mp, M_NOWAIT)) == NULL)
224                return (ENOMEM);
225        *mp = m;
226
227        error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag, sc->txbuf_map[idx].map,
228            m, &seg, &nsegs, 0);
229        if (error != 0) {
230                return (ENOMEM);
231        }
232
233        KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
234
235        bus_dmamap_sync(sc->txbuf_tag, sc->txbuf_map[idx].map,
236            BUS_DMASYNC_PREWRITE);
237
238        sc->txbuf_map[idx].mbuf = m;
239
240        dwc_setup_txdesc(sc, idx, seg.ds_addr, seg.ds_len);
241
242        return (0);
243}
244
245static void
246dwc_txstart_locked(struct dwc_softc *sc)
247{
248        struct ifnet *ifp;
249        struct mbuf *m;
250        int enqueued;
251
252        DWC_ASSERT_LOCKED(sc);
253
254        if (!sc->link_is_up)
255                return;
256
257        ifp = sc->ifp;
258
259        if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
260                return;
261        }
262
263        enqueued = 0;
264
265        for (;;) {
266                if (sc->txcount == (TX_DESC_COUNT-1)) {
267                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
268                        break;
269                }
270
271                IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
272                if (m == NULL)
273                        break;
274                if (dwc_setup_txbuf(sc, sc->tx_idx_head, &m) != 0) {
275                        IFQ_DRV_PREPEND(&ifp->if_snd, m);
276                        break;
277                }
278                BPF_MTAP(ifp, m);
279                sc->tx_idx_head = next_txidx(sc, sc->tx_idx_head);
280                ++enqueued;
281        }
282
283        if (enqueued != 0) {
284                WRITE4(sc, TRANSMIT_POLL_DEMAND, 0x1);
285                sc->tx_watchdog_count = WATCHDOG_TIMEOUT_SECS;
286        }
287}
288
289static void
290dwc_txstart(struct ifnet *ifp)
291{
292        struct dwc_softc *sc = ifp->if_softc;
293
294        DWC_LOCK(sc);
295        dwc_txstart_locked(sc);
296        DWC_UNLOCK(sc);
297}
298
299static void
300dwc_stop_locked(struct dwc_softc *sc)
301{
302        struct ifnet *ifp;
303        uint32_t reg;
304
305        DWC_ASSERT_LOCKED(sc);
306
307        ifp = sc->ifp;
308        ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
309        sc->tx_watchdog_count = 0;
310        sc->stats_harvest_count = 0;
311
312        callout_stop(&sc->dwc_callout);
313
314        /* Stop DMA TX */
315        reg = READ4(sc, OPERATION_MODE);
316        reg &= ~(MODE_ST);
317        WRITE4(sc, OPERATION_MODE, reg);
318
319        /* Flush TX */
320        reg = READ4(sc, OPERATION_MODE);
321        reg |= (MODE_FTF);
322        WRITE4(sc, OPERATION_MODE, reg);
323
324        /* Stop transmitters */
325        reg = READ4(sc, MAC_CONFIGURATION);
326        reg &= ~(CONF_TE | CONF_RE);
327        WRITE4(sc, MAC_CONFIGURATION, reg);
328
329        /* Stop DMA RX */
330        reg = READ4(sc, OPERATION_MODE);
331        reg &= ~(MODE_SR);
332        WRITE4(sc, OPERATION_MODE, reg);
333}
334
335static void dwc_clear_stats(struct dwc_softc *sc)
336{
337        uint32_t reg;
338
339        reg = READ4(sc, MMC_CONTROL);
340        reg |= (MMC_CONTROL_CNTRST);
341        WRITE4(sc, MMC_CONTROL, reg);
342}
343
344static void
345dwc_harvest_stats(struct dwc_softc *sc)
346{
347        struct ifnet *ifp;
348
349        /* We don't need to harvest too often. */
350        if (++sc->stats_harvest_count < STATS_HARVEST_INTERVAL)
351                return;
352
353        sc->stats_harvest_count = 0;
354        ifp = sc->ifp;
355
356        if_inc_counter(ifp, IFCOUNTER_IPACKETS, READ4(sc, RXFRAMECOUNT_GB));
357        if_inc_counter(ifp, IFCOUNTER_IMCASTS, READ4(sc, RXMULTICASTFRAMES_G));
358        if_inc_counter(ifp, IFCOUNTER_IERRORS,
359            READ4(sc, RXOVERSIZE_G) + READ4(sc, RXUNDERSIZE_G) +
360            READ4(sc, RXCRCERROR) + READ4(sc, RXALIGNMENTERROR) +
361            READ4(sc, RXRUNTERROR) + READ4(sc, RXJABBERERROR) +
362            READ4(sc, RXLENGTHERROR));
363
364        if_inc_counter(ifp, IFCOUNTER_OPACKETS, READ4(sc, TXFRAMECOUNT_G));
365        if_inc_counter(ifp, IFCOUNTER_OMCASTS, READ4(sc, TXMULTICASTFRAMES_G));
366        if_inc_counter(ifp, IFCOUNTER_OERRORS,
367            READ4(sc, TXOVERSIZE_G) + READ4(sc, TXEXCESSDEF) +
368            READ4(sc, TXCARRIERERR) + READ4(sc, TXUNDERFLOWERROR));
369
370        if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
371            READ4(sc, TXEXESSCOL) + READ4(sc, TXLATECOL));
372
373        dwc_clear_stats(sc);
374}
375
376static void
377dwc_tick(void *arg)
378{
379        struct dwc_softc *sc;
380        struct ifnet *ifp;
381        int link_was_up;
382
383        sc = arg;
384
385        DWC_ASSERT_LOCKED(sc);
386
387        ifp = sc->ifp;
388
389        if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
390            return;
391
392        /*
393         * Typical tx watchdog.  If this fires it indicates that we enqueued
394         * packets for output and never got a txdone interrupt for them.  Maybe
395         * it's a missed interrupt somehow, just pretend we got one.
396         */
397        if (sc->tx_watchdog_count > 0) {
398                if (--sc->tx_watchdog_count == 0) {
399                        dwc_txfinish_locked(sc);
400                }
401        }
402
403        /* Gather stats from hardware counters. */
404        dwc_harvest_stats(sc);
405
406        /* Check the media status. */
407        link_was_up = sc->link_is_up;
408        mii_tick(sc->mii_softc);
409        if (sc->link_is_up && !link_was_up)
410                dwc_txstart_locked(sc);
411
412        /* Schedule another check one second from now. */
413        callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
414}
415
416static void
417dwc_init_locked(struct dwc_softc *sc)
418{
419        struct ifnet *ifp = sc->ifp;
420        uint32_t reg;
421
422        DWC_ASSERT_LOCKED(sc);
423
424        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
425                return;
426
427        ifp->if_drv_flags |= IFF_DRV_RUNNING;
428
429        dwc_setup_rxfilter(sc);
430
431        /* Initializa DMA and enable transmitters */
432        reg = READ4(sc, OPERATION_MODE);
433        reg |= (MODE_TSF | MODE_OSF | MODE_FUF);
434        reg &= ~(MODE_RSF);
435        reg |= (MODE_RTC_LEV32 << MODE_RTC_SHIFT);
436        WRITE4(sc, OPERATION_MODE, reg);
437
438        WRITE4(sc, INTERRUPT_ENABLE, INT_EN_DEFAULT);
439
440        /* Start DMA */
441        reg = READ4(sc, OPERATION_MODE);
442        reg |= (MODE_ST | MODE_SR);
443        WRITE4(sc, OPERATION_MODE, reg);
444
445        /* Enable transmitters */
446        reg = READ4(sc, MAC_CONFIGURATION);
447        reg |= (CONF_JD | CONF_ACS | CONF_BE);
448        reg |= (CONF_TE | CONF_RE);
449        WRITE4(sc, MAC_CONFIGURATION, reg);
450
451        /*
452         * Call mii_mediachg() which will call back into dwc_miibus_statchg()
453         * to set up the remaining config registers based on current media.
454         */
455        mii_mediachg(sc->mii_softc);
456        callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
457}
458
459static void
460dwc_init(void *if_softc)
461{
462        struct dwc_softc *sc = if_softc;
463
464        DWC_LOCK(sc);
465        dwc_init_locked(sc);
466        DWC_UNLOCK(sc);
467}
468
469inline static uint32_t
470dwc_setup_rxdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr)
471{
472        uint32_t nidx;
473
474        sc->rxdesc_ring[idx].addr = (uint32_t)paddr;
475        nidx = next_rxidx(sc, idx);
476        sc->rxdesc_ring[idx].addr_next = sc->rxdesc_ring_paddr +        \
477            (nidx * sizeof(struct dwc_hwdesc));
478        if (sc->mactype == DWC_GMAC_ALT_DESC)
479                sc->rxdesc_ring[idx].tdes1 = DDESC_CNTL_CHAINED | RX_MAX_PACKET;
480        else
481                sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
482
483        wmb();
484        sc->rxdesc_ring[idx].tdes0 = DDESC_RDES0_OWN;
485        wmb();
486
487        return (nidx);
488}
489
490static int
491dwc_setup_rxbuf(struct dwc_softc *sc, int idx, struct mbuf *m)
492{
493        struct bus_dma_segment seg;
494        int error, nsegs;
495
496        m_adj(m, ETHER_ALIGN);
497
498        error = bus_dmamap_load_mbuf_sg(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
499            m, &seg, &nsegs, 0);
500        if (error != 0) {
501                return (error);
502        }
503
504        KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
505
506        bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
507            BUS_DMASYNC_PREREAD);
508
509        sc->rxbuf_map[idx].mbuf = m;
510        dwc_setup_rxdesc(sc, idx, seg.ds_addr);
511
512        return (0);
513}
514
515static struct mbuf *
516dwc_alloc_mbufcl(struct dwc_softc *sc)
517{
518        struct mbuf *m;
519
520        m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
521        if (m != NULL)
522                m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
523
524        return (m);
525}
526
527static void
528dwc_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
529{
530        struct dwc_softc *sc;
531        struct mii_data *mii;
532
533        sc = ifp->if_softc;
534        mii = sc->mii_softc;
535        DWC_LOCK(sc);
536        mii_pollstat(mii);
537        ifmr->ifm_active = mii->mii_media_active;
538        ifmr->ifm_status = mii->mii_media_status;
539        DWC_UNLOCK(sc);
540}
541
542static int
543dwc_media_change_locked(struct dwc_softc *sc)
544{
545
546        return (mii_mediachg(sc->mii_softc));
547}
548
549static int
550dwc_media_change(struct ifnet * ifp)
551{
552        struct dwc_softc *sc;
553        int error;
554
555        sc = ifp->if_softc;
556
557        DWC_LOCK(sc);
558        error = dwc_media_change_locked(sc);
559        DWC_UNLOCK(sc);
560        return (error);
561}
562
563static const uint8_t nibbletab[] = {
564        /* 0x0 0000 -> 0000 */  0x0,
565        /* 0x1 0001 -> 1000 */  0x8,
566        /* 0x2 0010 -> 0100 */  0x4,
567        /* 0x3 0011 -> 1100 */  0xc,
568        /* 0x4 0100 -> 0010 */  0x2,
569        /* 0x5 0101 -> 1010 */  0xa,
570        /* 0x6 0110 -> 0110 */  0x6,
571        /* 0x7 0111 -> 1110 */  0xe,
572        /* 0x8 1000 -> 0001 */  0x1,
573        /* 0x9 1001 -> 1001 */  0x9,
574        /* 0xa 1010 -> 0101 */  0x5,
575        /* 0xb 1011 -> 1101 */  0xd,
576        /* 0xc 1100 -> 0011 */  0x3,
577        /* 0xd 1101 -> 1011 */  0xb,
578        /* 0xe 1110 -> 0111 */  0x7,
579        /* 0xf 1111 -> 1111 */  0xf, };
580
581static uint8_t
582bitreverse(uint8_t x)
583{
584
585        return (nibbletab[x & 0xf] << 4) | nibbletab[x >> 4];
586}
587
588static void
589dwc_setup_rxfilter(struct dwc_softc *sc)
590{
591        struct ifmultiaddr *ifma;
592        struct ifnet *ifp;
593        uint8_t *eaddr, val;
594        uint32_t crc, ffval, hashbit, hashreg, hi, lo, hash[8];
595        int nhash, i;
596
597        DWC_ASSERT_LOCKED(sc);
598
599        ifp = sc->ifp;
600        nhash = sc->mactype == DWC_GMAC_ALT_DESC ? 2 : 8;
601
602        /*
603         * Set the multicast (group) filter hash.
604         */
605        if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
606                ffval = (FRAME_FILTER_PM);
607                for (i = 0; i < nhash; i++)
608                        hash[i] = ~0;
609        } else {
610                ffval = (FRAME_FILTER_HMC);
611                for (i = 0; i < nhash; i++)
612                        hash[i] = 0;
613                if_maddr_rlock(ifp);
614                TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
615                        if (ifma->ifma_addr->sa_family != AF_LINK)
616                                continue;
617                        crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
618                                ifma->ifma_addr), ETHER_ADDR_LEN);
619
620                        /* Take lower 8 bits and reverse it */
621                        val = bitreverse(~crc & 0xff);
622                        if (sc->mactype == DWC_GMAC_ALT_DESC)
623                                val >>= nhash; /* Only need lower 6 bits */
624                        hashreg = (val >> 5);
625                        hashbit = (val & 31);
626                        hash[hashreg] |= (1 << hashbit);
627                }
628                if_maddr_runlock(ifp);
629        }
630
631        /*
632         * Set the individual address filter hash.
633         */
634        if (ifp->if_flags & IFF_PROMISC)
635                ffval |= (FRAME_FILTER_PR);
636
637        /*
638         * Set the primary address.
639         */
640        eaddr = IF_LLADDR(ifp);
641        lo = eaddr[0] | (eaddr[1] << 8) | (eaddr[2] << 16) |
642            (eaddr[3] << 24);
643        hi = eaddr[4] | (eaddr[5] << 8);
644        WRITE4(sc, MAC_ADDRESS_LOW(0), lo);
645        WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
646        WRITE4(sc, MAC_FRAME_FILTER, ffval);
647        if (sc->mactype == DWC_GMAC_ALT_DESC) {
648                WRITE4(sc, GMAC_MAC_HTLOW, hash[0]);
649                WRITE4(sc, GMAC_MAC_HTHIGH, hash[1]);
650        } else {
651                for (i = 0; i < nhash; i++)
652                        WRITE4(sc, HASH_TABLE_REG(i), hash[i]);
653        }
654}
655
656static int
657dwc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
658{
659        struct dwc_softc *sc;
660        struct mii_data *mii;
661        struct ifreq *ifr;
662        int mask, error;
663
664        sc = ifp->if_softc;
665        ifr = (struct ifreq *)data;
666
667        error = 0;
668        switch (cmd) {
669        case SIOCSIFFLAGS:
670                DWC_LOCK(sc);
671                if (ifp->if_flags & IFF_UP) {
672                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
673                                if ((ifp->if_flags ^ sc->if_flags) &
674                                    (IFF_PROMISC | IFF_ALLMULTI))
675                                        dwc_setup_rxfilter(sc);
676                        } else {
677                                if (!sc->is_detaching)
678                                        dwc_init_locked(sc);
679                        }
680                } else {
681                        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
682                                dwc_stop_locked(sc);
683                }
684                sc->if_flags = ifp->if_flags;
685                DWC_UNLOCK(sc);
686                break;
687        case SIOCADDMULTI:
688        case SIOCDELMULTI:
689                if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
690                        DWC_LOCK(sc);
691                        dwc_setup_rxfilter(sc);
692                        DWC_UNLOCK(sc);
693                }
694                break;
695        case SIOCSIFMEDIA:
696        case SIOCGIFMEDIA:
697                mii = sc->mii_softc;
698                error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
699                break;
700        case SIOCSIFCAP:
701                mask = ifp->if_capenable ^ ifr->ifr_reqcap;
702                if (mask & IFCAP_VLAN_MTU) {
703                        /* No work to do except acknowledge the change took */
704                        ifp->if_capenable ^= IFCAP_VLAN_MTU;
705                }
706                break;
707
708        default:
709                error = ether_ioctl(ifp, cmd, data);
710                break;
711        }
712
713        return (error);
714}
715
716static void
717dwc_txfinish_locked(struct dwc_softc *sc)
718{
719        struct dwc_bufmap *bmap;
720        struct dwc_hwdesc *desc;
721        struct ifnet *ifp;
722
723        DWC_ASSERT_LOCKED(sc);
724
725        ifp = sc->ifp;
726        while (sc->tx_idx_tail != sc->tx_idx_head) {
727                desc = &sc->txdesc_ring[sc->tx_idx_tail];
728                if ((desc->tdes0 & DDESC_TDES0_OWN) != 0)
729                        break;
730                bmap = &sc->txbuf_map[sc->tx_idx_tail];
731                bus_dmamap_sync(sc->txbuf_tag, bmap->map,
732                    BUS_DMASYNC_POSTWRITE);
733                bus_dmamap_unload(sc->txbuf_tag, bmap->map);
734                m_freem(bmap->mbuf);
735                bmap->mbuf = NULL;
736                dwc_setup_txdesc(sc, sc->tx_idx_tail, 0, 0);
737                sc->tx_idx_tail = next_txidx(sc, sc->tx_idx_tail);
738                ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
739        }
740
741        /* If there are no buffers outstanding, muzzle the watchdog. */
742        if (sc->tx_idx_tail == sc->tx_idx_head) {
743                sc->tx_watchdog_count = 0;
744        }
745}
746
747static void
748dwc_rxfinish_locked(struct dwc_softc *sc)
749{
750        struct ifnet *ifp;
751        struct mbuf *m0;
752        struct mbuf *m;
753        int error, idx, len;
754        uint32_t rdes0;
755
756        ifp = sc->ifp;
757
758        for (;;) {
759                idx = sc->rx_idx;
760
761                rdes0 = sc->rxdesc_ring[idx].tdes0;
762                if ((rdes0 & DDESC_RDES0_OWN) != 0)
763                        break;
764
765                bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
766                    BUS_DMASYNC_POSTREAD);
767                bus_dmamap_unload(sc->rxbuf_tag, sc->rxbuf_map[idx].map);
768
769                len = (rdes0 >> DDESC_RDES0_FL_SHIFT) & DDESC_RDES0_FL_MASK;
770                if (len != 0) {
771                        m = sc->rxbuf_map[idx].mbuf;
772                        m->m_pkthdr.rcvif = ifp;
773                        m->m_pkthdr.len = len;
774                        m->m_len = len;
775
776                        /* Remove trailing FCS */
777                        m_adj(m, -ETHER_CRC_LEN);
778
779                        DWC_UNLOCK(sc);
780                        (*ifp->if_input)(ifp, m);
781                        DWC_LOCK(sc);
782                } else {
783                        /* XXX Zero-length packet ? */
784                }
785
786                if ((m0 = dwc_alloc_mbufcl(sc)) != NULL) {
787                        if ((error = dwc_setup_rxbuf(sc, idx, m0)) != 0) {
788                                /*
789                                 * XXX Now what?
790                                 * We've got a hole in the rx ring.
791                                 */
792                        }
793                } else
794                        if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
795
796                sc->rx_idx = next_rxidx(sc, sc->rx_idx);
797        }
798}
799
800static void
801dwc_intr(void *arg)
802{
803        struct dwc_softc *sc;
804        uint32_t reg;
805
806        sc = arg;
807
808        DWC_LOCK(sc);
809
810        reg = READ4(sc, INTERRUPT_STATUS);
811        if (reg)
812                READ4(sc, SGMII_RGMII_SMII_CTRL_STATUS);
813
814        reg = READ4(sc, DMA_STATUS);
815        if (reg & DMA_STATUS_NIS) {
816                if (reg & DMA_STATUS_RI)
817                        dwc_rxfinish_locked(sc);
818
819                if (reg & DMA_STATUS_TI) {
820                        dwc_txfinish_locked(sc);
821                        dwc_txstart_locked(sc);
822                }
823        }
824
825        if (reg & DMA_STATUS_AIS) {
826                if (reg & DMA_STATUS_FBI) {
827                        /* Fatal bus error */
828                        device_printf(sc->dev,
829                            "Ethernet DMA error, restarting controller.\n");
830                        dwc_stop_locked(sc);
831                        dwc_init_locked(sc);
832                }
833        }
834
835        WRITE4(sc, DMA_STATUS, reg & DMA_STATUS_INTR_MASK);
836        DWC_UNLOCK(sc);
837}
838
839static int
840setup_dma(struct dwc_softc *sc)
841{
842        struct mbuf *m;
843        int error;
844        int nidx;
845        int idx;
846
847        /*
848         * Set up TX descriptor ring, descriptors, and dma maps.
849         */
850        error = bus_dma_tag_create(
851            bus_get_dma_tag(sc->dev),   /* Parent tag. */
852            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
853            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
854            BUS_SPACE_MAXADDR,          /* highaddr */
855            NULL, NULL,                 /* filter, filterarg */
856            TX_DESC_SIZE, 1,            /* maxsize, nsegments */
857            TX_DESC_SIZE,               /* maxsegsize */
858            0,                          /* flags */
859            NULL, NULL,                 /* lockfunc, lockarg */
860            &sc->txdesc_tag);
861        if (error != 0) {
862                device_printf(sc->dev,
863                    "could not create TX ring DMA tag.\n");
864                goto out;
865        }
866
867        error = bus_dmamem_alloc(sc->txdesc_tag, (void**)&sc->txdesc_ring,
868            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
869            &sc->txdesc_map);
870        if (error != 0) {
871                device_printf(sc->dev,
872                    "could not allocate TX descriptor ring.\n");
873                goto out;
874        }
875
876        error = bus_dmamap_load(sc->txdesc_tag, sc->txdesc_map,
877            sc->txdesc_ring, TX_DESC_SIZE, dwc_get1paddr,
878            &sc->txdesc_ring_paddr, 0);
879        if (error != 0) {
880                device_printf(sc->dev,
881                    "could not load TX descriptor ring map.\n");
882                goto out;
883        }
884
885        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
886                nidx = next_txidx(sc, idx);
887                sc->txdesc_ring[idx].addr_next = sc->txdesc_ring_paddr +
888                    (nidx * sizeof(struct dwc_hwdesc));
889        }
890
891        error = bus_dma_tag_create(
892            bus_get_dma_tag(sc->dev),   /* Parent tag. */
893            1, 0,                       /* alignment, boundary */
894            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
895            BUS_SPACE_MAXADDR,          /* highaddr */
896            NULL, NULL,                 /* filter, filterarg */
897            MCLBYTES, 1,                /* maxsize, nsegments */
898            MCLBYTES,                   /* maxsegsize */
899            0,                          /* flags */
900            NULL, NULL,                 /* lockfunc, lockarg */
901            &sc->txbuf_tag);
902        if (error != 0) {
903                device_printf(sc->dev,
904                    "could not create TX ring DMA tag.\n");
905                goto out;
906        }
907
908        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
909                error = bus_dmamap_create(sc->txbuf_tag, BUS_DMA_COHERENT,
910                    &sc->txbuf_map[idx].map);
911                if (error != 0) {
912                        device_printf(sc->dev,
913                            "could not create TX buffer DMA map.\n");
914                        goto out;
915                }
916                dwc_setup_txdesc(sc, idx, 0, 0);
917        }
918
919        /*
920         * Set up RX descriptor ring, descriptors, dma maps, and mbufs.
921         */
922        error = bus_dma_tag_create(
923            bus_get_dma_tag(sc->dev),   /* Parent tag. */
924            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
925            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
926            BUS_SPACE_MAXADDR,          /* highaddr */
927            NULL, NULL,                 /* filter, filterarg */
928            RX_DESC_SIZE, 1,            /* maxsize, nsegments */
929            RX_DESC_SIZE,               /* maxsegsize */
930            0,                          /* flags */
931            NULL, NULL,                 /* lockfunc, lockarg */
932            &sc->rxdesc_tag);
933        if (error != 0) {
934                device_printf(sc->dev,
935                    "could not create RX ring DMA tag.\n");
936                goto out;
937        }
938
939        error = bus_dmamem_alloc(sc->rxdesc_tag, (void **)&sc->rxdesc_ring,
940            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
941            &sc->rxdesc_map);
942        if (error != 0) {
943                device_printf(sc->dev,
944                    "could not allocate RX descriptor ring.\n");
945                goto out;
946        }
947
948        error = bus_dmamap_load(sc->rxdesc_tag, sc->rxdesc_map,
949            sc->rxdesc_ring, RX_DESC_SIZE, dwc_get1paddr,
950            &sc->rxdesc_ring_paddr, 0);
951        if (error != 0) {
952                device_printf(sc->dev,
953                    "could not load RX descriptor ring map.\n");
954                goto out;
955        }
956
957        error = bus_dma_tag_create(
958            bus_get_dma_tag(sc->dev),   /* Parent tag. */
959            1, 0,                       /* alignment, boundary */
960            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
961            BUS_SPACE_MAXADDR,          /* highaddr */
962            NULL, NULL,                 /* filter, filterarg */
963            MCLBYTES, 1,                /* maxsize, nsegments */
964            MCLBYTES,                   /* maxsegsize */
965            0,                          /* flags */
966            NULL, NULL,                 /* lockfunc, lockarg */
967            &sc->rxbuf_tag);
968        if (error != 0) {
969                device_printf(sc->dev,
970                    "could not create RX buf DMA tag.\n");
971                goto out;
972        }
973
974        for (idx = 0; idx < RX_DESC_COUNT; idx++) {
975                error = bus_dmamap_create(sc->rxbuf_tag, BUS_DMA_COHERENT,
976                    &sc->rxbuf_map[idx].map);
977                if (error != 0) {
978                        device_printf(sc->dev,
979                            "could not create RX buffer DMA map.\n");
980                        goto out;
981                }
982                if ((m = dwc_alloc_mbufcl(sc)) == NULL) {
983                        device_printf(sc->dev, "Could not alloc mbuf\n");
984                        error = ENOMEM;
985                        goto out;
986                }
987                if ((error = dwc_setup_rxbuf(sc, idx, m)) != 0) {
988                        device_printf(sc->dev,
989                            "could not create new RX buffer.\n");
990                        goto out;
991                }
992        }
993
994out:
995        if (error != 0)
996                return (ENXIO);
997
998        return (0);
999}
1000
1001static int
1002dwc_get_hwaddr(struct dwc_softc *sc, uint8_t *hwaddr)
1003{
1004        uint32_t hi, lo, rnd;
1005
1006        /*
1007         * Try to recover a MAC address from the running hardware. If there's
1008         * something non-zero there, assume the bootloader did the right thing
1009         * and just use it.
1010         *
1011         * Otherwise, set the address to a convenient locally assigned address,
1012         * 'bsd' + random 24 low-order bits.  'b' is 0x62, which has the locally
1013         * assigned bit set, and the broadcast/multicast bit clear.
1014         */
1015        lo = READ4(sc, MAC_ADDRESS_LOW(0));
1016        hi = READ4(sc, MAC_ADDRESS_HIGH(0)) & 0xffff;
1017        if ((lo != 0xffffffff) || (hi != 0xffff)) {
1018                hwaddr[0] = (lo >>  0) & 0xff;
1019                hwaddr[1] = (lo >>  8) & 0xff;
1020                hwaddr[2] = (lo >> 16) & 0xff;
1021                hwaddr[3] = (lo >> 24) & 0xff;
1022                hwaddr[4] = (hi >>  0) & 0xff;
1023                hwaddr[5] = (hi >>  8) & 0xff;
1024        } else {
1025                rnd = arc4random() & 0x00ffffff;
1026                hwaddr[0] = 'b';
1027                hwaddr[1] = 's';
1028                hwaddr[2] = 'd';
1029                hwaddr[3] = rnd >> 16;
1030                hwaddr[4] = rnd >>  8;
1031                hwaddr[5] = rnd >>  0;
1032        }
1033
1034        return (0);
1035}
1036
1037#define GPIO_ACTIVE_LOW 1
1038
1039static int
1040dwc_reset(device_t dev)
1041{
1042#ifndef __rtems__
1043        pcell_t gpio_prop[4];
1044        pcell_t delay_prop[3];
1045        phandle_t node, gpio_node;
1046        device_t gpio;
1047        uint32_t pin, flags;
1048        uint32_t pin_value;
1049
1050        node = ofw_bus_get_node(dev);
1051        if (OF_getencprop(node, "snps,reset-gpio",
1052            gpio_prop, sizeof(gpio_prop)) <= 0)
1053                return (0);
1054
1055        if (OF_getencprop(node, "snps,reset-delays-us",
1056            delay_prop, sizeof(delay_prop)) <= 0) {
1057                device_printf(dev,
1058                    "Wrong property for snps,reset-delays-us");
1059                return (ENXIO);
1060        }
1061
1062        gpio_node = OF_node_from_xref(gpio_prop[0]);
1063        if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) {
1064                device_printf(dev,
1065                    "Can't find gpio controller for phy reset\n");
1066                return (ENXIO);
1067        }
1068
1069        if (GPIO_MAP_GPIOS(gpio, node, gpio_node,
1070            nitems(gpio_prop) - 1,
1071            gpio_prop + 1, &pin, &flags) != 0) {
1072                device_printf(dev, "Can't map gpio for phy reset\n");
1073                return (ENXIO);
1074        }
1075
1076        pin_value = GPIO_PIN_LOW;
1077        if (OF_hasprop(node, "snps,reset-active-low"))
1078                pin_value = GPIO_PIN_HIGH;
1079
1080        if (flags & GPIO_ACTIVE_LOW)
1081                pin_value = !pin_value;
1082
1083        GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
1084        GPIO_PIN_SET(gpio, pin, pin_value);
1085        DELAY(delay_prop[0]);
1086        GPIO_PIN_SET(gpio, pin, !pin_value);
1087        DELAY(delay_prop[1]);
1088        GPIO_PIN_SET(gpio, pin, pin_value);
1089        DELAY(delay_prop[2]);
1090#endif /* __rtems__ */
1091
1092        return (0);
1093}
1094
1095#ifdef EXT_RESOURCES
1096static int
1097dwc_clock_init(device_t dev)
1098{
1099        hwreset_t rst;
1100        clk_t clk;
1101        int error;
1102
1103        /* Enable clock */
1104        if (clk_get_by_ofw_name(dev, 0, "stmmaceth", &clk) == 0) {
1105                error = clk_enable(clk);
1106                if (error != 0) {
1107                        device_printf(dev, "could not enable main clock\n");
1108                        return (error);
1109                }
1110        }
1111
1112        /* De-assert reset */
1113        if (hwreset_get_by_ofw_name(dev, 0, "stmmaceth", &rst) == 0) {
1114                error = hwreset_deassert(rst);
1115                if (error != 0) {
1116                        device_printf(dev, "could not de-assert reset\n");
1117                        return (error);
1118                }
1119        }
1120
1121        return (0);
1122}
1123#endif
1124
1125static int
1126dwc_probe(device_t dev)
1127{
1128
1129#ifndef __rtems__
1130        if (!ofw_bus_status_okay(dev))
1131                return (ENXIO);
1132
1133        if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
1134                return (ENXIO);
1135#endif /* __rtems__ */
1136
1137        device_set_desc(dev, "Gigabit Ethernet Controller");
1138        return (BUS_PROBE_DEFAULT);
1139}
1140
1141static int
1142dwc_attach(device_t dev)
1143{
1144        uint8_t macaddr[ETHER_ADDR_LEN];
1145        struct dwc_softc *sc;
1146        struct ifnet *ifp;
1147        int error, i;
1148        uint32_t reg;
1149
1150        sc = device_get_softc(dev);
1151        sc->dev = dev;
1152        sc->rx_idx = 0;
1153        sc->txcount = TX_DESC_COUNT;
1154        sc->mii_clk = IF_DWC_MII_CLK(dev);
1155        sc->mactype = IF_DWC_MAC_TYPE(dev);
1156
1157        if (IF_DWC_INIT(dev) != 0)
1158                return (ENXIO);
1159
1160#ifdef EXT_RESOURCES
1161        if (dwc_clock_init(dev) != 0)
1162                return (ENXIO);
1163#endif
1164
1165        if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
1166                device_printf(dev, "could not allocate resources\n");
1167                return (ENXIO);
1168        }
1169
1170        /* Memory interface */
1171        sc->bst = rman_get_bustag(sc->res[0]);
1172        sc->bsh = rman_get_bushandle(sc->res[0]);
1173
1174        /* Read MAC before reset */
1175        if (dwc_get_hwaddr(sc, macaddr)) {
1176                device_printf(sc->dev, "can't get mac\n");
1177                return (ENXIO);
1178        }
1179
1180        /* Reset the PHY if needed */
1181        if (dwc_reset(dev) != 0) {
1182                device_printf(dev, "Can't reset the PHY\n");
1183                return (ENXIO);
1184        }
1185
1186        /* Reset */
1187        reg = READ4(sc, BUS_MODE);
1188        reg |= (BUS_MODE_SWR);
1189        WRITE4(sc, BUS_MODE, reg);
1190
1191        for (i = 0; i < MAC_RESET_TIMEOUT; i++) {
1192                if ((READ4(sc, BUS_MODE) & BUS_MODE_SWR) == 0)
1193                        break;
1194                DELAY(10);
1195        }
1196        if (i >= MAC_RESET_TIMEOUT) {
1197                device_printf(sc->dev, "Can't reset DWC.\n");
1198                return (ENXIO);
1199        }
1200
1201        if (sc->mactype == DWC_GMAC_ALT_DESC) {
1202                reg = BUS_MODE_FIXEDBURST;
1203                reg |= (BUS_MODE_PRIORXTX_41 << BUS_MODE_PRIORXTX_SHIFT);
1204        } else
1205                reg = (BUS_MODE_EIGHTXPBL);
1206        reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
1207        WRITE4(sc, BUS_MODE, reg);
1208
1209        /*
1210         * DMA must be stop while changing descriptor list addresses.
1211         */
1212        reg = READ4(sc, OPERATION_MODE);
1213        reg &= ~(MODE_ST | MODE_SR);
1214        WRITE4(sc, OPERATION_MODE, reg);
1215
1216        if (setup_dma(sc))
1217                return (ENXIO);
1218
1219        /* Setup addresses */
1220        WRITE4(sc, RX_DESCR_LIST_ADDR, sc->rxdesc_ring_paddr);
1221        WRITE4(sc, TX_DESCR_LIST_ADDR, sc->txdesc_ring_paddr);
1222
1223        mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
1224            MTX_NETWORK_LOCK, MTX_DEF);
1225
1226        callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
1227
1228        /* Set up the ethernet interface. */
1229        sc->ifp = ifp = if_alloc(IFT_ETHER);
1230
1231        ifp->if_softc = sc;
1232        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1233        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1234        ifp->if_capabilities = IFCAP_VLAN_MTU;
1235        ifp->if_capenable = ifp->if_capabilities;
1236        ifp->if_start = dwc_txstart;
1237        ifp->if_ioctl = dwc_ioctl;
1238        ifp->if_init = dwc_init;
1239        IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
1240        ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
1241        IFQ_SET_READY(&ifp->if_snd);
1242
1243        /* Attach the mii driver. */
1244        error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
1245            dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
1246            MII_OFFSET_ANY, 0);
1247
1248        if (error != 0) {
1249                device_printf(dev, "PHY attach failed\n");
1250                return (ENXIO);
1251        }
1252        sc->mii_softc = device_get_softc(sc->miibus);
1253
1254        /* Setup interrupt handler. */
1255        error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
1256            NULL, dwc_intr, sc, &sc->intr_cookie);
1257        if (error != 0) {
1258                device_printf(dev, "could not setup interrupt handler.\n");
1259                return (ENXIO);
1260        }
1261
1262        /* All ready to run, attach the ethernet interface. */
1263        ether_ifattach(ifp, macaddr);
1264        sc->is_attached = true;
1265
1266        return (0);
1267}
1268
1269static int
1270dwc_miibus_read_reg(device_t dev, int phy, int reg)
1271{
1272        struct dwc_softc *sc;
1273        uint16_t mii;
1274        size_t cnt;
1275        int rv = 0;
1276
1277        sc = device_get_softc(dev);
1278
1279        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1280            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1281            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1282            | GMII_ADDRESS_GB; /* Busy flag */
1283
1284        WRITE4(sc, GMII_ADDRESS, mii);
1285
1286        for (cnt = 0; cnt < 1000; cnt++) {
1287                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1288                        rv = READ4(sc, GMII_DATA);
1289                        break;
1290                }
1291                DELAY(10);
1292        }
1293
1294        return rv;
1295}
1296
1297static int
1298dwc_miibus_write_reg(device_t dev, int phy, int reg, int val)
1299{
1300        struct dwc_softc *sc;
1301        uint16_t mii;
1302        size_t cnt;
1303
1304        sc = device_get_softc(dev);
1305
1306        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1307            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1308            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1309            | GMII_ADDRESS_GB | GMII_ADDRESS_GW;
1310
1311        WRITE4(sc, GMII_DATA, val);
1312        WRITE4(sc, GMII_ADDRESS, mii);
1313
1314        for (cnt = 0; cnt < 1000; cnt++) {
1315                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1316                        break;
1317                }
1318                DELAY(10);
1319        }
1320
1321        return (0);
1322}
1323
1324static void
1325dwc_miibus_statchg(device_t dev)
1326{
1327        struct dwc_softc *sc;
1328        struct mii_data *mii;
1329        uint32_t reg;
1330
1331        /*
1332         * Called by the MII bus driver when the PHY establishes
1333         * link to set the MAC interface registers.
1334         */
1335
1336        sc = device_get_softc(dev);
1337
1338        DWC_ASSERT_LOCKED(sc);
1339
1340        mii = sc->mii_softc;
1341
1342        if (mii->mii_media_status & IFM_ACTIVE)
1343                sc->link_is_up = true;
1344        else
1345                sc->link_is_up = false;
1346
1347        reg = READ4(sc, MAC_CONFIGURATION);
1348        switch (IFM_SUBTYPE(mii->mii_media_active)) {
1349        case IFM_1000_T:
1350        case IFM_1000_SX:
1351                reg &= ~(CONF_FES | CONF_PS);
1352                break;
1353        case IFM_100_TX:
1354                reg |= (CONF_FES | CONF_PS);
1355                break;
1356        case IFM_10_T:
1357                reg &= ~(CONF_FES);
1358                reg |= (CONF_PS);
1359                break;
1360        case IFM_NONE:
1361                sc->link_is_up = false;
1362                return;
1363        default:
1364                sc->link_is_up = false;
1365                device_printf(dev, "Unsupported media %u\n",
1366                    IFM_SUBTYPE(mii->mii_media_active));
1367                return;
1368        }
1369        if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
1370                reg |= (CONF_DM);
1371        else
1372                reg &= ~(CONF_DM);
1373        WRITE4(sc, MAC_CONFIGURATION, reg);
1374}
1375
1376static device_method_t dwc_methods[] = {
1377        DEVMETHOD(device_probe,         dwc_probe),
1378        DEVMETHOD(device_attach,        dwc_attach),
1379
1380        /* MII Interface */
1381        DEVMETHOD(miibus_readreg,       dwc_miibus_read_reg),
1382        DEVMETHOD(miibus_writereg,      dwc_miibus_write_reg),
1383        DEVMETHOD(miibus_statchg,       dwc_miibus_statchg),
1384
1385        { 0, 0 }
1386};
1387
1388driver_t dwc_driver = {
1389        "dwc",
1390        dwc_methods,
1391        sizeof(struct dwc_softc),
1392};
1393
1394static devclass_t dwc_devclass;
1395
1396DRIVER_MODULE(dwc, simplebus, dwc_driver, dwc_devclass, 0, 0);
1397DRIVER_MODULE(miibus, dwc, miibus_driver, miibus_devclass, 0, 0);
1398
1399MODULE_DEPEND(dwc, ether, 1, 1, 1);
1400MODULE_DEPEND(dwc, miibus, 1, 1, 1);
Note: See TracBrowser for help on using the repository browser.