source: rtems-libbsd/freebsd/sys/arm/ti/cpsw/if_cpsw.c @ 736d651

55-freebsd-126-freebsd-12
Last change on this file since 736d651 was 736d651, checked in by Christian Mauderer <christian.mauderer@…>, on 12/19/18 at 21:53:53

freebsd/if_cpsw: Import.

  • Property mode set to 100644
File size: 77.4 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
7 * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * TI Common Platform Ethernet Switch (CPSW) Driver
34 * Found in TI8148 "DaVinci" and AM335x "Sitara" SoCs.
35 *
36 * This controller is documented in the AM335x Technical Reference
37 * Manual, in the TMS320DM814x DaVinci Digital Video Processors TRM
38 * and in the TMS320C6452 3 Port Switch Ethernet Subsystem TRM.
39 *
40 * It is basically a single Ethernet port (port 0) wired internally to
41 * a 3-port store-and-forward switch connected to two independent
42 * "sliver" controllers (port 1 and port 2).  You can operate the
43 * controller in a variety of different ways by suitably configuring
44 * the slivers and the Address Lookup Engine (ALE) that routes packets
45 * between the ports.
46 *
47 * This code was developed and tested on a BeagleBone with
48 * an AM335x SoC.
49 */
50
51#include <sys/cdefs.h>
52__FBSDID("$FreeBSD$");
53
54#include <rtems/bsd/local/opt_cpsw.h>
55
56#include <sys/param.h>
57#include <sys/bus.h>
58#include <sys/kernel.h>
59#include <sys/lock.h>
60#include <sys/mbuf.h>
61#include <sys/module.h>
62#include <sys/mutex.h>
63#include <sys/rman.h>
64#include <sys/socket.h>
65#include <sys/sockio.h>
66#include <sys/sysctl.h>
67
68#include <machine/bus.h>
69#include <machine/resource.h>
70#include <machine/stdarg.h>
71
72#include <net/ethernet.h>
73#include <net/bpf.h>
74#include <net/if.h>
75#include <net/if_dl.h>
76#include <net/if_media.h>
77#include <net/if_types.h>
78
79#include <arm/ti/ti_scm.h>
80#include <arm/ti/am335x/am335x_scm.h>
81
82#include <dev/mii/mii.h>
83#include <dev/mii/miivar.h>
84
85#include <dev/ofw/ofw_bus.h>
86#include <dev/ofw/ofw_bus_subr.h>
87 
88#ifdef CPSW_ETHERSWITCH
89#include <dev/etherswitch/etherswitch.h>
90#include <rtems/bsd/local/etherswitch_if.h>
91#endif
92
93#include "if_cpswreg.h"
94#include "if_cpswvar.h"
95
96#include <rtems/bsd/local/miibus_if.h>
97
98/* Device probe/attach/detach. */
99static int cpsw_probe(device_t);
100static int cpsw_attach(device_t);
101static int cpsw_detach(device_t);
102static int cpswp_probe(device_t);
103static int cpswp_attach(device_t);
104static int cpswp_detach(device_t);
105
106static phandle_t cpsw_get_node(device_t, device_t);
107
108/* Device Init/shutdown. */
109static int cpsw_shutdown(device_t);
110static void cpswp_init(void *);
111static void cpswp_init_locked(void *);
112static void cpswp_stop_locked(struct cpswp_softc *);
113
114/* Device Suspend/Resume. */
115static int cpsw_suspend(device_t);
116static int cpsw_resume(device_t);
117
118/* Ioctl. */
119static int cpswp_ioctl(struct ifnet *, u_long command, caddr_t data);
120
121static int cpswp_miibus_readreg(device_t, int phy, int reg);
122static int cpswp_miibus_writereg(device_t, int phy, int reg, int value);
123static void cpswp_miibus_statchg(device_t);
124
125/* Send/Receive packets. */
126static void cpsw_intr_rx(void *arg);
127static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
128static void cpsw_rx_enqueue(struct cpsw_softc *);
129static void cpswp_start(struct ifnet *);
130static void cpsw_intr_tx(void *);
131static void cpswp_tx_enqueue(struct cpswp_softc *);
132static int cpsw_tx_dequeue(struct cpsw_softc *);
133
134/* Misc interrupts and watchdog. */
135static void cpsw_intr_rx_thresh(void *);
136static void cpsw_intr_misc(void *);
137static void cpswp_tick(void *);
138static void cpswp_ifmedia_sts(struct ifnet *, struct ifmediareq *);
139static int cpswp_ifmedia_upd(struct ifnet *);
140static void cpsw_tx_watchdog(void *);
141
142/* ALE support */
143static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t, uint32_t *);
144static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t, uint32_t *);
145static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t, int, uint8_t *);
146static void cpsw_ale_dump_table(struct cpsw_softc *);
147static int cpsw_ale_update_vlan_table(struct cpsw_softc *, int, int, int, int,
148        int);
149static int cpswp_ale_update_addresses(struct cpswp_softc *, int);
150
151/* Statistics and sysctls. */
152static void cpsw_add_sysctls(struct cpsw_softc *);
153static void cpsw_stats_collect(struct cpsw_softc *);
154static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
155
156#ifdef CPSW_ETHERSWITCH
157static etherswitch_info_t *cpsw_getinfo(device_t);
158static int cpsw_getport(device_t, etherswitch_port_t *);
159static int cpsw_setport(device_t, etherswitch_port_t *);
160static int cpsw_getconf(device_t, etherswitch_conf_t *);
161static int cpsw_getvgroup(device_t, etherswitch_vlangroup_t *);
162static int cpsw_setvgroup(device_t, etherswitch_vlangroup_t *);
163static int cpsw_readreg(device_t, int);
164static int cpsw_writereg(device_t, int, int);
165static int cpsw_readphy(device_t, int, int);
166static int cpsw_writephy(device_t, int, int, int);
167#endif
168
169/*
170 * Arbitrary limit on number of segments in an mbuf to be transmitted.
171 * Packets with more segments than this will be defragmented before
172 * they are queued.
173 */
174#define CPSW_TXFRAGS            16
175
176/* Shared resources. */
177static device_method_t cpsw_methods[] = {
178        /* Device interface */
179        DEVMETHOD(device_probe,         cpsw_probe),
180        DEVMETHOD(device_attach,        cpsw_attach),
181        DEVMETHOD(device_detach,        cpsw_detach),
182        DEVMETHOD(device_shutdown,      cpsw_shutdown),
183        DEVMETHOD(device_suspend,       cpsw_suspend),
184        DEVMETHOD(device_resume,        cpsw_resume),
185        /* Bus interface */
186        DEVMETHOD(bus_add_child,        device_add_child_ordered),
187        /* OFW methods */
188        DEVMETHOD(ofw_bus_get_node,     cpsw_get_node),
189#ifdef CPSW_ETHERSWITCH
190        /* etherswitch interface */
191        DEVMETHOD(etherswitch_getinfo,  cpsw_getinfo),
192        DEVMETHOD(etherswitch_readreg,  cpsw_readreg),
193        DEVMETHOD(etherswitch_writereg, cpsw_writereg),
194        DEVMETHOD(etherswitch_readphyreg,       cpsw_readphy),
195        DEVMETHOD(etherswitch_writephyreg,      cpsw_writephy),
196        DEVMETHOD(etherswitch_getport,  cpsw_getport),
197        DEVMETHOD(etherswitch_setport,  cpsw_setport),
198        DEVMETHOD(etherswitch_getvgroup,        cpsw_getvgroup),
199        DEVMETHOD(etherswitch_setvgroup,        cpsw_setvgroup),
200        DEVMETHOD(etherswitch_getconf,  cpsw_getconf),
201#endif
202        DEVMETHOD_END
203};
204
205static driver_t cpsw_driver = {
206        "cpswss",
207        cpsw_methods,
208        sizeof(struct cpsw_softc),
209};
210
211static devclass_t cpsw_devclass;
212
213DRIVER_MODULE(cpswss, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
214
215/* Port/Slave resources. */
216static device_method_t cpswp_methods[] = {
217        /* Device interface */
218        DEVMETHOD(device_probe,         cpswp_probe),
219        DEVMETHOD(device_attach,        cpswp_attach),
220        DEVMETHOD(device_detach,        cpswp_detach),
221        /* MII interface */
222        DEVMETHOD(miibus_readreg,       cpswp_miibus_readreg),
223        DEVMETHOD(miibus_writereg,      cpswp_miibus_writereg),
224        DEVMETHOD(miibus_statchg,       cpswp_miibus_statchg),
225        DEVMETHOD_END
226};
227
228static driver_t cpswp_driver = {
229        "cpsw",
230        cpswp_methods,
231        sizeof(struct cpswp_softc),
232};
233
234static devclass_t cpswp_devclass;
235
236#ifdef CPSW_ETHERSWITCH
237DRIVER_MODULE(etherswitch, cpswss, etherswitch_driver, etherswitch_devclass, 0, 0);
238MODULE_DEPEND(cpswss, etherswitch, 1, 1, 1);
239#endif
240
241DRIVER_MODULE(cpsw, cpswss, cpswp_driver, cpswp_devclass, 0, 0);
242DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
243MODULE_DEPEND(cpsw, ether, 1, 1, 1);
244MODULE_DEPEND(cpsw, miibus, 1, 1, 1);
245
246#ifdef CPSW_ETHERSWITCH
247static struct cpsw_vlangroups cpsw_vgroups[CPSW_VLANS];
248#endif
249
250static uint32_t slave_mdio_addr[] = { 0x4a100200, 0x4a100300 };
251
252static struct resource_spec irq_res_spec[] = {
253        { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
254        { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
255        { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE },
256        { SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE },
257        { -1, 0 }
258};
259
260static struct {
261        void (*cb)(void *);
262} cpsw_intr_cb[] = {
263        { cpsw_intr_rx_thresh },
264        { cpsw_intr_rx },
265        { cpsw_intr_tx },
266        { cpsw_intr_misc },
267};
268
269/* Number of entries here must match size of stats
270 * array in struct cpswp_softc. */
271static struct cpsw_stat {
272        int     reg;
273        char *oid;
274} cpsw_stat_sysctls[CPSW_SYSCTL_COUNT] = {
275        {0x00, "GoodRxFrames"},
276        {0x04, "BroadcastRxFrames"},
277        {0x08, "MulticastRxFrames"},
278        {0x0C, "PauseRxFrames"},
279        {0x10, "RxCrcErrors"},
280        {0x14, "RxAlignErrors"},
281        {0x18, "OversizeRxFrames"},
282        {0x1c, "RxJabbers"},
283        {0x20, "ShortRxFrames"},
284        {0x24, "RxFragments"},
285        {0x30, "RxOctets"},
286        {0x34, "GoodTxFrames"},
287        {0x38, "BroadcastTxFrames"},
288        {0x3c, "MulticastTxFrames"},
289        {0x40, "PauseTxFrames"},
290        {0x44, "DeferredTxFrames"},
291        {0x48, "CollisionsTxFrames"},
292        {0x4c, "SingleCollisionTxFrames"},
293        {0x50, "MultipleCollisionTxFrames"},
294        {0x54, "ExcessiveCollisions"},
295        {0x58, "LateCollisions"},
296        {0x5c, "TxUnderrun"},
297        {0x60, "CarrierSenseErrors"},
298        {0x64, "TxOctets"},
299        {0x68, "RxTx64OctetFrames"},
300        {0x6c, "RxTx65to127OctetFrames"},
301        {0x70, "RxTx128to255OctetFrames"},
302        {0x74, "RxTx256to511OctetFrames"},
303        {0x78, "RxTx512to1024OctetFrames"},
304        {0x7c, "RxTx1024upOctetFrames"},
305        {0x80, "NetOctets"},
306        {0x84, "RxStartOfFrameOverruns"},
307        {0x88, "RxMiddleOfFrameOverruns"},
308        {0x8c, "RxDmaOverruns"}
309};
310
311/*
312 * Basic debug support.
313 */
314
315static void
316cpsw_debugf_head(const char *funcname)
317{
318        int t = (int)(time_second % (24 * 60 * 60));
319
320        printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
321}
322
323static void
324cpsw_debugf(const char *fmt, ...)
325{
326        va_list ap;
327
328        va_start(ap, fmt);
329        vprintf(fmt, ap);
330        va_end(ap);
331        printf("\n");
332
333}
334
335#define CPSW_DEBUGF(_sc, a) do {                                        \
336        if ((_sc)->debug) {                                             \
337                cpsw_debugf_head(__func__);                             \
338                cpsw_debugf a;                                          \
339        }                                                               \
340} while (0)
341
342/*
343 * Locking macros
344 */
345#define CPSW_TX_LOCK(sc) do {                                           \
346                mtx_assert(&(sc)->rx.lock, MA_NOTOWNED);                \
347                mtx_lock(&(sc)->tx.lock);                               \
348} while (0)
349
350#define CPSW_TX_UNLOCK(sc)      mtx_unlock(&(sc)->tx.lock)
351#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
352
353#define CPSW_RX_LOCK(sc) do {                                           \
354                mtx_assert(&(sc)->tx.lock, MA_NOTOWNED);                \
355                mtx_lock(&(sc)->rx.lock);                               \
356} while (0)
357
358#define CPSW_RX_UNLOCK(sc)              mtx_unlock(&(sc)->rx.lock)
359#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
360
361#define CPSW_PORT_LOCK(_sc) do {                                        \
362                mtx_assert(&(_sc)->lock, MA_NOTOWNED);                  \
363                mtx_lock(&(_sc)->lock);                                 \
364} while (0)
365
366#define CPSW_PORT_UNLOCK(_sc)   mtx_unlock(&(_sc)->lock)
367#define CPSW_PORT_LOCK_ASSERT(_sc)      mtx_assert(&(_sc)->lock, MA_OWNED)
368
369/*
370 * Read/Write macros
371 */
372#define cpsw_read_4(_sc, _reg)          bus_read_4((_sc)->mem_res, (_reg))
373#define cpsw_write_4(_sc, _reg, _val)                                   \
374        bus_write_4((_sc)->mem_res, (_reg), (_val))
375
376#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
377
378#define cpsw_cpdma_bd_paddr(sc, slot)                                   \
379        BUS_SPACE_PHYSADDR(sc->mem_res, slot->bd_offset)
380#define cpsw_cpdma_read_bd(sc, slot, val)                               \
381        bus_read_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
382#define cpsw_cpdma_write_bd(sc, slot, val)                              \
383        bus_write_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
384#define cpsw_cpdma_write_bd_next(sc, slot, next_slot)                   \
385        cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
386#define cpsw_cpdma_write_bd_flags(sc, slot, val)                        \
387        bus_write_2(sc->mem_res, slot->bd_offset + 14, val)
388#define cpsw_cpdma_read_bd_flags(sc, slot)                              \
389        bus_read_2(sc->mem_res, slot->bd_offset + 14)
390#define cpsw_write_hdp_slot(sc, queue, slot)                            \
391        cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
392#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
393#define cpsw_read_cp(sc, queue)                                         \
394        cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
395#define cpsw_write_cp(sc, queue, val)                                   \
396        cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
397#define cpsw_write_cp_slot(sc, queue, slot)                             \
398        cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
399
400#if 0
401/* XXX temporary function versions for debugging. */
402static void
403cpsw_write_hdp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
404{
405        uint32_t reg = queue->hdp_offset;
406        uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
407        CPSW_DEBUGF(("HDP <=== 0x%08x (was 0x%08x)", v, cpsw_read_4(sc, reg)));
408        cpsw_write_4(sc, reg, v);
409}
410
411static void
412cpsw_write_cp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
413{
414        uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
415        CPSW_DEBUGF(("CP <=== 0x%08x (expecting 0x%08x)", v, cpsw_read_cp(sc, queue)));
416        cpsw_write_cp(sc, queue, v);
417}
418#endif
419
420/*
421 * Expanded dump routines for verbose debugging.
422 */
423static void
424cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
425{
426        static const char *flags[] = {"SOP", "EOP", "Owner", "EOQ",
427            "TDownCmplt", "PassCRC", "Long", "Short", "MacCtl", "Overrun",
428            "PktErr1", "PortEn/PktErr0", "RxVlanEncap", "Port2", "Port1",
429            "Port0"};
430        struct cpsw_cpdma_bd bd;
431        const char *sep;
432        int i;
433
434        cpsw_cpdma_read_bd(sc, slot, &bd);
435        printf("BD Addr : 0x%08x   Next  : 0x%08x\n",
436            cpsw_cpdma_bd_paddr(sc, slot), bd.next);
437        printf("  BufPtr: 0x%08x   BufLen: 0x%08x\n", bd.bufptr, bd.buflen);
438        printf("  BufOff: 0x%08x   PktLen: 0x%08x\n", bd.bufoff, bd.pktlen);
439        printf("  Flags: ");
440        sep = "";
441        for (i = 0; i < 16; ++i) {
442                if (bd.flags & (1 << (15 - i))) {
443                        printf("%s%s", sep, flags[i]);
444                        sep = ",";
445                }
446        }
447        printf("\n");
448        if (slot->mbuf) {
449                printf("  Ether:  %14D\n",
450                    (char *)(slot->mbuf->m_data), " ");
451                printf("  Packet: %16D\n",
452                    (char *)(slot->mbuf->m_data) + 14, " ");
453        }
454}
455
456#define CPSW_DUMP_SLOT(cs, slot) do {                           \
457        IF_DEBUG(sc) {                                          \
458                cpsw_dump_slot(sc, slot);                       \
459        }                                                       \
460} while (0)
461
462static void
463cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
464{
465        struct cpsw_slot *slot;
466        int i = 0;
467        int others = 0;
468
469        STAILQ_FOREACH(slot, q, next) {
470                if (i > CPSW_TXFRAGS)
471                        ++others;
472                else
473                        cpsw_dump_slot(sc, slot);
474                ++i;
475        }
476        if (others)
477                printf(" ... and %d more.\n", others);
478        printf("\n");
479}
480
481#define CPSW_DUMP_QUEUE(sc, q) do {                             \
482        IF_DEBUG(sc) {                                          \
483                cpsw_dump_queue(sc, q);                         \
484        }                                                       \
485} while (0)
486
487static void
488cpsw_init_slots(struct cpsw_softc *sc)
489{
490        struct cpsw_slot *slot;
491        int i;
492
493        STAILQ_INIT(&sc->avail);
494
495        /* Put the slot descriptors onto the global avail list. */
496        for (i = 0; i < nitems(sc->_slots); i++) {
497                slot = &sc->_slots[i];
498                slot->bd_offset = cpsw_cpdma_bd_offset(i);
499                STAILQ_INSERT_TAIL(&sc->avail, slot, next);
500        }
501}
502
503static int
504cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
505{
506        const int max_slots = nitems(sc->_slots);
507        struct cpsw_slot *slot;
508        int i;
509
510        if (requested < 0)
511                requested = max_slots;
512
513        for (i = 0; i < requested; ++i) {
514                slot = STAILQ_FIRST(&sc->avail);
515                if (slot == NULL)
516                        return (0);
517                if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
518                        device_printf(sc->dev, "failed to create dmamap\n");
519                        return (ENOMEM);
520                }
521                STAILQ_REMOVE_HEAD(&sc->avail, next);
522                STAILQ_INSERT_TAIL(&queue->avail, slot, next);
523                ++queue->avail_queue_len;
524                ++queue->queue_slots;
525        }
526        return (0);
527}
528
529static void
530cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
531{
532        int error;
533
534        if (slot->dmamap) {
535                if (slot->mbuf)
536                        bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
537                error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
538                KASSERT(error == 0, ("Mapping still active"));
539                slot->dmamap = NULL;
540        }
541        if (slot->mbuf) {
542                m_freem(slot->mbuf);
543                slot->mbuf = NULL;
544        }
545}
546
547static void
548cpsw_reset(struct cpsw_softc *sc)
549{
550        int i;
551
552        callout_stop(&sc->watchdog.callout);
553
554        /* Reset RMII/RGMII wrapper. */
555        cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
556        while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
557                ;
558
559        /* Disable TX and RX interrupts for all cores. */
560        for (i = 0; i < 3; ++i) {
561                cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
562                cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
563                cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
564                cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
565        }
566
567        /* Reset CPSW subsystem. */
568        cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
569        while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
570                ;
571
572        /* Reset Sliver port 1 and 2 */
573        for (i = 0; i < 2; i++) {
574                /* Reset */
575                cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
576                while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
577                        ;
578        }
579
580        /* Reset DMA controller. */
581        cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
582        while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
583                ;
584
585        /* Disable TX & RX DMA */
586        cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
587        cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
588
589        /* Clear all queues. */
590        for (i = 0; i < 8; i++) {
591                cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
592                cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
593                cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
594                cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
595        }
596
597        /* Clear all interrupt Masks */
598        cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
599        cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
600}
601
602static void
603cpsw_init(struct cpsw_softc *sc)
604{
605        struct cpsw_slot *slot;
606        uint32_t reg;
607
608        /* Disable the interrupt pacing. */
609        reg = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
610        reg &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
611        cpsw_write_4(sc, CPSW_WR_INT_CONTROL, reg);
612
613        /* Clear ALE */
614        cpsw_write_4(sc, CPSW_ALE_CONTROL, CPSW_ALE_CTL_CLEAR_TBL);
615
616        /* Enable ALE */
617        reg = CPSW_ALE_CTL_ENABLE;
618        if (sc->dualemac)
619                reg |= CPSW_ALE_CTL_VLAN_AWARE;
620        cpsw_write_4(sc, CPSW_ALE_CONTROL, reg);
621
622        /* Set Host Port Mapping. */
623        cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
624        cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
625
626        /* Initialize ALE: set host port to forwarding(3). */
627        cpsw_write_4(sc, CPSW_ALE_PORTCTL(0),
628            ALE_PORTCTL_INGRESS | ALE_PORTCTL_FORWARD);
629
630        cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
631
632        /* Enable statistics for ports 0, 1 and 2 */
633        cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
634
635        /* Turn off flow control. */
636        cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
637
638        /* Make IP hdr aligned with 4 */
639        cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
640
641        /* Initialize RX Buffer Descriptors */
642        cpsw_write_4(sc, CPSW_CPDMA_RX_PENDTHRESH(0), 0);
643        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
644
645        /* Enable TX & RX DMA */
646        cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
647        cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
648
649        /* Enable Interrupts for core 0 */
650        cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
651        cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
652        cpsw_write_4(sc, CPSW_WR_C_TX_EN(0), 0xFF);
653        cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x1F);
654
655        /* Enable host Error Interrupt */
656        cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
657
658        /* Enable interrupts for RX and TX on Channel 0 */
659        cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET,
660            CPSW_CPDMA_RX_INT(0) | CPSW_CPDMA_RX_INT_THRESH(0));
661        cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_SET, 1);
662
663        /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
664        /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
665        cpsw_write_4(sc, MDIOCONTROL, MDIOCTL_ENABLE | MDIOCTL_FAULTENB | 0xff);
666
667        /* Select MII in GMII_SEL, Internal Delay mode */
668        //ti_scm_reg_write_4(0x650, 0);
669
670        /* Initialize active queues. */
671        slot = STAILQ_FIRST(&sc->tx.active);
672        if (slot != NULL)
673                cpsw_write_hdp_slot(sc, &sc->tx, slot);
674        slot = STAILQ_FIRST(&sc->rx.active);
675        if (slot != NULL)
676                cpsw_write_hdp_slot(sc, &sc->rx, slot);
677        cpsw_rx_enqueue(sc);
678        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), sc->rx.active_queue_len);
679        cpsw_write_4(sc, CPSW_CPDMA_RX_PENDTHRESH(0), CPSW_TXFRAGS);
680
681        /* Activate network interface. */
682        sc->rx.running = 1;
683        sc->tx.running = 1;
684        sc->watchdog.timer = 0;
685        callout_init(&sc->watchdog.callout, 0);
686        callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
687}
688
689/*
690 *
691 * Device Probe, Attach, Detach.
692 *
693 */
694
695static int
696cpsw_probe(device_t dev)
697{
698
699        if (!ofw_bus_status_okay(dev))
700                return (ENXIO);
701
702        if (!ofw_bus_is_compatible(dev, "ti,cpsw"))
703                return (ENXIO);
704
705        device_set_desc(dev, "3-port Switch Ethernet Subsystem");
706        return (BUS_PROBE_DEFAULT);
707}
708
709static int
710cpsw_intr_attach(struct cpsw_softc *sc)
711{
712        int i;
713
714        for (i = 0; i < CPSW_INTR_COUNT; i++) {
715                if (bus_setup_intr(sc->dev, sc->irq_res[i],
716                    INTR_TYPE_NET | INTR_MPSAFE, NULL,
717                    cpsw_intr_cb[i].cb, sc, &sc->ih_cookie[i]) != 0) {
718                        return (-1);
719                }
720        }
721
722        return (0);
723}
724
725static void
726cpsw_intr_detach(struct cpsw_softc *sc)
727{
728        int i;
729
730        for (i = 0; i < CPSW_INTR_COUNT; i++) {
731                if (sc->ih_cookie[i]) {
732                        bus_teardown_intr(sc->dev, sc->irq_res[i],
733                            sc->ih_cookie[i]);
734                }
735        }
736}
737
738static int
739cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
740{
741        char *name;
742        int len, phy, vlan;
743        pcell_t phy_id[3], vlan_id;
744        phandle_t child;
745        unsigned long mdio_child_addr;
746
747        /* Find any slave with phy_id */
748        phy = -1;
749        vlan = -1;
750        for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) {
751                if (OF_getprop_alloc(child, "name", (void **)&name) < 0)
752                        continue;
753                if (sscanf(name, "slave@%lx", &mdio_child_addr) != 1) {
754                        OF_prop_free(name);
755                        continue;
756                }
757                OF_prop_free(name);
758                if (mdio_child_addr != slave_mdio_addr[port])
759                        continue;
760
761                len = OF_getproplen(child, "phy_id");
762                if (len / sizeof(pcell_t) == 2) {
763                        /* Get phy address from fdt */
764                        if (OF_getencprop(child, "phy_id", phy_id, len) > 0)
765                                phy = phy_id[1];
766                }
767
768                len = OF_getproplen(child, "dual_emac_res_vlan");
769                if (len / sizeof(pcell_t) == 1) {
770                        /* Get phy address from fdt */
771                        if (OF_getencprop(child, "dual_emac_res_vlan",
772                            &vlan_id, len) > 0) {
773                                vlan = vlan_id;
774                        }
775                }
776
777                break;
778        }
779        if (phy == -1)
780                return (ENXIO);
781        sc->port[port].phy = phy;
782        sc->port[port].vlan = vlan;
783
784        return (0);
785}
786
787static int
788cpsw_attach(device_t dev)
789{
790        int error, i;
791        struct cpsw_softc *sc;
792        uint32_t reg;
793
794        sc = device_get_softc(dev);
795        sc->dev = dev;
796        sc->node = ofw_bus_get_node(dev);
797        getbinuptime(&sc->attach_uptime);
798
799        if (OF_getencprop(sc->node, "active_slave", &sc->active_slave,
800            sizeof(sc->active_slave)) <= 0) {
801                sc->active_slave = 0;
802        }
803        if (sc->active_slave > 1)
804                sc->active_slave = 1;
805
806        if (OF_hasprop(sc->node, "dual_emac"))
807                sc->dualemac = 1;
808
809        for (i = 0; i < CPSW_PORTS; i++) {
810                if (!sc->dualemac && i != sc->active_slave)
811                        continue;
812                if (cpsw_get_fdt_data(sc, i) != 0) {
813                        device_printf(dev,
814                            "failed to get PHY address from FDT\n");
815                        return (ENXIO);
816                }
817        }
818
819        /* Initialize mutexes */
820        mtx_init(&sc->tx.lock, device_get_nameunit(dev),
821            "cpsw TX lock", MTX_DEF);
822        mtx_init(&sc->rx.lock, device_get_nameunit(dev),
823            "cpsw RX lock", MTX_DEF);
824
825        /* Allocate IRQ resources */
826        error = bus_alloc_resources(dev, irq_res_spec, sc->irq_res);
827        if (error) {
828                device_printf(dev, "could not allocate IRQ resources\n");
829                cpsw_detach(dev);
830                return (ENXIO);
831        }
832
833        sc->mem_rid = 0;
834        sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
835            &sc->mem_rid, RF_ACTIVE);
836        if (sc->mem_res == NULL) {
837                device_printf(sc->dev, "failed to allocate memory resource\n");
838                cpsw_detach(dev);
839                return (ENXIO);
840        }
841
842        reg = cpsw_read_4(sc, CPSW_SS_IDVER);
843        device_printf(dev, "CPSW SS Version %d.%d (%d)\n", (reg >> 8 & 0x7),
844                reg & 0xFF, (reg >> 11) & 0x1F);
845
846        cpsw_add_sysctls(sc);
847
848        /* Allocate a busdma tag and DMA safe memory for mbufs. */
849        error = bus_dma_tag_create(
850                bus_get_dma_tag(sc->dev),       /* parent */
851                1, 0,                           /* alignment, boundary */
852                BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
853                BUS_SPACE_MAXADDR,              /* highaddr */
854                NULL, NULL,                     /* filtfunc, filtfuncarg */
855                MCLBYTES, CPSW_TXFRAGS,         /* maxsize, nsegments */
856                MCLBYTES, 0,                    /* maxsegsz, flags */
857                NULL, NULL,                     /* lockfunc, lockfuncarg */
858                &sc->mbuf_dtag);                /* dmatag */
859        if (error) {
860                device_printf(dev, "bus_dma_tag_create failed\n");
861                cpsw_detach(dev);
862                return (error);
863        }
864
865        /* Allocate a NULL buffer for padding. */
866        sc->nullpad = malloc(ETHER_MIN_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
867
868        cpsw_init_slots(sc);
869
870        /* Allocate slots to TX and RX queues. */
871        STAILQ_INIT(&sc->rx.avail);
872        STAILQ_INIT(&sc->rx.active);
873        STAILQ_INIT(&sc->tx.avail);
874        STAILQ_INIT(&sc->tx.active);
875        // For now:  128 slots to TX, rest to RX.
876        // XXX TODO: start with 32/64 and grow dynamically based on demand.
877        if (cpsw_add_slots(sc, &sc->tx, 128) ||
878            cpsw_add_slots(sc, &sc->rx, -1)) {
879                device_printf(dev, "failed to allocate dmamaps\n");
880                cpsw_detach(dev);
881                return (ENOMEM);
882        }
883        device_printf(dev, "Initial queue size TX=%d RX=%d\n",
884            sc->tx.queue_slots, sc->rx.queue_slots);
885
886        sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
887        sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
888
889        if (cpsw_intr_attach(sc) == -1) {
890                device_printf(dev, "failed to setup interrupts\n");
891                cpsw_detach(dev);
892                return (ENXIO);
893        }
894
895#ifdef CPSW_ETHERSWITCH
896        for (i = 0; i < CPSW_VLANS; i++)
897                cpsw_vgroups[i].vid = -1;
898#endif
899
900        /* Reset the controller. */
901        cpsw_reset(sc);
902        cpsw_init(sc);
903
904        for (i = 0; i < CPSW_PORTS; i++) {
905                if (!sc->dualemac && i != sc->active_slave)
906                        continue;
907                sc->port[i].dev = device_add_child(dev, "cpsw", i);
908                if (sc->port[i].dev == NULL) {
909                        cpsw_detach(dev);
910                        return (ENXIO);
911                }
912        }
913        bus_generic_probe(dev);
914        bus_generic_attach(dev);
915
916        return (0);
917}
918
919static int
920cpsw_detach(device_t dev)
921{
922        struct cpsw_softc *sc;
923        int error, i;
924
925        bus_generic_detach(dev);
926        sc = device_get_softc(dev);
927
928        for (i = 0; i < CPSW_PORTS; i++) {
929                if (sc->port[i].dev)
930                        device_delete_child(dev, sc->port[i].dev);
931        }
932
933        if (device_is_attached(dev)) {
934                callout_stop(&sc->watchdog.callout);
935                callout_drain(&sc->watchdog.callout);
936        }
937
938        /* Stop and release all interrupts */
939        cpsw_intr_detach(sc);
940
941        /* Free dmamaps and mbufs */
942        for (i = 0; i < nitems(sc->_slots); ++i)
943                cpsw_free_slot(sc, &sc->_slots[i]);
944
945        /* Free null padding buffer. */
946        if (sc->nullpad)
947                free(sc->nullpad, M_DEVBUF);
948
949        /* Free DMA tag */
950        if (sc->mbuf_dtag) {
951                error = bus_dma_tag_destroy(sc->mbuf_dtag);
952                KASSERT(error == 0, ("Unable to destroy DMA tag"));
953        }
954
955        /* Free IO memory handler */
956        if (sc->mem_res != NULL)
957                bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
958        bus_release_resources(dev, irq_res_spec, sc->irq_res);
959
960        /* Destroy mutexes */
961        mtx_destroy(&sc->rx.lock);
962        mtx_destroy(&sc->tx.lock);
963
964        /* Detach the switch device, if present. */
965        error = bus_generic_detach(dev);
966        if (error != 0)
967                return (error);
968       
969        return (device_delete_children(dev));
970}
971
972static phandle_t
973cpsw_get_node(device_t bus, device_t dev)
974{
975
976        /* Share controller node with port device. */
977        return (ofw_bus_get_node(bus));
978}
979
980static int
981cpswp_probe(device_t dev)
982{
983
984        if (device_get_unit(dev) > 1) {
985                device_printf(dev, "Only two ports are supported.\n");
986                return (ENXIO);
987        }
988        device_set_desc(dev, "Ethernet Switch Port");
989
990        return (BUS_PROBE_DEFAULT);
991}
992
993static int
994cpswp_attach(device_t dev)
995{
996        int error;
997        struct ifnet *ifp;
998        struct cpswp_softc *sc;
999        uint32_t reg;
1000        uint8_t mac_addr[ETHER_ADDR_LEN];
1001
1002        sc = device_get_softc(dev);
1003        sc->dev = dev;
1004        sc->pdev = device_get_parent(dev);
1005        sc->swsc = device_get_softc(sc->pdev);
1006        sc->unit = device_get_unit(dev);
1007        sc->phy = sc->swsc->port[sc->unit].phy;
1008        sc->vlan = sc->swsc->port[sc->unit].vlan;
1009        if (sc->swsc->dualemac && sc->vlan == -1)
1010                sc->vlan = sc->unit + 1;
1011
1012        if (sc->unit == 0) {
1013                sc->physel = MDIOUSERPHYSEL0;
1014                sc->phyaccess = MDIOUSERACCESS0;
1015        } else {
1016                sc->physel = MDIOUSERPHYSEL1;
1017                sc->phyaccess = MDIOUSERACCESS1;
1018        }
1019
1020        mtx_init(&sc->lock, device_get_nameunit(dev), "cpsw port lock",
1021            MTX_DEF);
1022
1023        /* Allocate network interface */
1024        ifp = sc->ifp = if_alloc(IFT_ETHER);
1025        if (ifp == NULL) {
1026                cpswp_detach(dev);
1027                return (ENXIO);
1028        }
1029
1030        if_initname(ifp, device_get_name(sc->dev), sc->unit);
1031        ifp->if_softc = sc;
1032        ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
1033        ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN?
1034        ifp->if_capenable = ifp->if_capabilities;
1035
1036        ifp->if_init = cpswp_init;
1037        ifp->if_start = cpswp_start;
1038        ifp->if_ioctl = cpswp_ioctl;
1039
1040        ifp->if_snd.ifq_drv_maxlen = sc->swsc->tx.queue_slots;
1041        IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
1042        IFQ_SET_READY(&ifp->if_snd);
1043
1044        /* Get high part of MAC address from control module (mac_id[0|1]_hi) */
1045        ti_scm_reg_read_4(SCM_MAC_ID0_HI + sc->unit * 8, &reg);
1046        mac_addr[0] = reg & 0xFF;
1047        mac_addr[1] = (reg >>  8) & 0xFF;
1048        mac_addr[2] = (reg >> 16) & 0xFF;
1049        mac_addr[3] = (reg >> 24) & 0xFF;
1050
1051        /* Get low part of MAC address from control module (mac_id[0|1]_lo) */
1052        ti_scm_reg_read_4(SCM_MAC_ID0_LO + sc->unit * 8, &reg);
1053        mac_addr[4] = reg & 0xFF;
1054        mac_addr[5] = (reg >>  8) & 0xFF;
1055
1056        error = mii_attach(dev, &sc->miibus, ifp, cpswp_ifmedia_upd,
1057            cpswp_ifmedia_sts, BMSR_DEFCAPMASK, sc->phy, MII_OFFSET_ANY, 0);
1058        if (error) {
1059                device_printf(dev, "attaching PHYs failed\n");
1060                cpswp_detach(dev);
1061                return (error);
1062        }
1063        sc->mii = device_get_softc(sc->miibus);
1064
1065        /* Select PHY and enable interrupts */
1066        cpsw_write_4(sc->swsc, sc->physel,
1067            MDIO_PHYSEL_LINKINTENB | (sc->phy & 0x1F));
1068
1069        ether_ifattach(sc->ifp, mac_addr);
1070        callout_init(&sc->mii_callout, 0);
1071
1072        return (0);
1073}
1074
1075static int
1076cpswp_detach(device_t dev)
1077{
1078        struct cpswp_softc *sc;
1079
1080        sc = device_get_softc(dev);
1081        CPSW_DEBUGF(sc->swsc, (""));
1082        if (device_is_attached(dev)) {
1083                ether_ifdetach(sc->ifp);
1084                CPSW_PORT_LOCK(sc);
1085                cpswp_stop_locked(sc);
1086                CPSW_PORT_UNLOCK(sc);
1087                callout_drain(&sc->mii_callout);
1088        }
1089
1090        bus_generic_detach(dev);
1091
1092        if_free(sc->ifp);
1093        mtx_destroy(&sc->lock);
1094
1095        return (0);
1096}
1097
1098/*
1099 *
1100 * Init/Shutdown.
1101 *
1102 */
1103
1104static int
1105cpsw_ports_down(struct cpsw_softc *sc)
1106{
1107        struct cpswp_softc *psc;
1108        struct ifnet *ifp1, *ifp2;
1109
1110        if (!sc->dualemac)
1111                return (1);
1112        psc = device_get_softc(sc->port[0].dev);
1113        ifp1 = psc->ifp;
1114        psc = device_get_softc(sc->port[1].dev);
1115        ifp2 = psc->ifp;
1116        if ((ifp1->if_flags & IFF_UP) == 0 && (ifp2->if_flags & IFF_UP) == 0)
1117                return (1);
1118
1119        return (0);
1120}
1121
1122static void
1123cpswp_init(void *arg)
1124{
1125        struct cpswp_softc *sc = arg;
1126
1127        CPSW_DEBUGF(sc->swsc, (""));
1128        CPSW_PORT_LOCK(sc);
1129        cpswp_init_locked(arg);
1130        CPSW_PORT_UNLOCK(sc);
1131}
1132
1133static void
1134cpswp_init_locked(void *arg)
1135{
1136#ifdef CPSW_ETHERSWITCH
1137        int i;
1138#endif
1139        struct cpswp_softc *sc = arg;
1140        struct ifnet *ifp;
1141        uint32_t reg;
1142
1143        CPSW_DEBUGF(sc->swsc, (""));
1144        CPSW_PORT_LOCK_ASSERT(sc);
1145        ifp = sc->ifp;
1146        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1147                return;
1148
1149        getbinuptime(&sc->init_uptime);
1150
1151        if (!sc->swsc->rx.running && !sc->swsc->tx.running) {
1152                /* Reset the controller. */
1153                cpsw_reset(sc->swsc);
1154                cpsw_init(sc->swsc);
1155        }
1156
1157        /* Set Slave Mapping. */
1158        cpsw_write_4(sc->swsc, CPSW_SL_RX_PRI_MAP(sc->unit), 0x76543210);
1159        cpsw_write_4(sc->swsc, CPSW_PORT_P_TX_PRI_MAP(sc->unit + 1),
1160            0x33221100);
1161        cpsw_write_4(sc->swsc, CPSW_SL_RX_MAXLEN(sc->unit), 0x5f2);
1162        /* Enable MAC RX/TX modules. */
1163        /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
1164        /* Huh?  Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
1165        reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
1166        reg |= CPSW_SL_MACTL_GMII_ENABLE;
1167        cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
1168
1169        /* Initialize ALE: set port to forwarding, initialize addrs */
1170        cpsw_write_4(sc->swsc, CPSW_ALE_PORTCTL(sc->unit + 1),
1171            ALE_PORTCTL_INGRESS | ALE_PORTCTL_FORWARD);
1172        cpswp_ale_update_addresses(sc, 1);
1173
1174        if (sc->swsc->dualemac) {
1175                /* Set Port VID. */
1176                cpsw_write_4(sc->swsc, CPSW_PORT_P_VLAN(sc->unit + 1),
1177                    sc->vlan & 0xfff);
1178                cpsw_ale_update_vlan_table(sc->swsc, sc->vlan,
1179                    (1 << (sc->unit + 1)) | (1 << 0), /* Member list */
1180                    (1 << (sc->unit + 1)) | (1 << 0), /* Untagged egress */
1181                    (1 << (sc->unit + 1)) | (1 << 0), 0); /* mcast reg flood */
1182#ifdef CPSW_ETHERSWITCH
1183                for (i = 0; i < CPSW_VLANS; i++) {
1184                        if (cpsw_vgroups[i].vid != -1)
1185                                continue;
1186                        cpsw_vgroups[i].vid = sc->vlan;
1187                        break;
1188                }
1189#endif
1190        }
1191
1192        mii_mediachg(sc->mii);
1193        callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
1194        ifp->if_drv_flags |= IFF_DRV_RUNNING;
1195        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1196}
1197
1198static int
1199cpsw_shutdown(device_t dev)
1200{
1201        struct cpsw_softc *sc;
1202        struct cpswp_softc *psc;
1203        int i;
1204
1205        sc = device_get_softc(dev);
1206        CPSW_DEBUGF(sc, (""));
1207        for (i = 0; i < CPSW_PORTS; i++) {
1208                if (!sc->dualemac && i != sc->active_slave)
1209                        continue;
1210                psc = device_get_softc(sc->port[i].dev);
1211                CPSW_PORT_LOCK(psc);
1212                cpswp_stop_locked(psc);
1213                CPSW_PORT_UNLOCK(psc);
1214        }
1215
1216        return (0);
1217}
1218
1219static void
1220cpsw_rx_teardown(struct cpsw_softc *sc)
1221{
1222        int i = 0;
1223
1224        CPSW_RX_LOCK(sc);
1225        CPSW_DEBUGF(sc, ("starting RX teardown"));
1226        sc->rx.teardown = 1;
1227        cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
1228        CPSW_RX_UNLOCK(sc);
1229        while (sc->rx.running) {
1230                if (++i > 10) {
1231                        device_printf(sc->dev,
1232                            "Unable to cleanly shutdown receiver\n");
1233                        return;
1234                }
1235                DELAY(200);
1236        }
1237        if (!sc->rx.running)
1238                CPSW_DEBUGF(sc, ("finished RX teardown (%d retries)", i));
1239}
1240
1241static void
1242cpsw_tx_teardown(struct cpsw_softc *sc)
1243{
1244        int i = 0;
1245
1246        CPSW_TX_LOCK(sc);
1247        CPSW_DEBUGF(sc, ("starting TX teardown"));
1248        /* Start the TX queue teardown if queue is not empty. */
1249        if (STAILQ_FIRST(&sc->tx.active) != NULL)
1250                cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
1251        else
1252                sc->tx.teardown = 1;
1253        cpsw_tx_dequeue(sc);
1254        while (sc->tx.running && ++i < 10) {
1255                DELAY(200);
1256                cpsw_tx_dequeue(sc);
1257        }
1258        if (sc->tx.running) {
1259                device_printf(sc->dev,
1260                    "Unable to cleanly shutdown transmitter\n");
1261        }
1262        CPSW_DEBUGF(sc,
1263            ("finished TX teardown (%d retries, %d idle buffers)", i,
1264             sc->tx.active_queue_len));
1265        CPSW_TX_UNLOCK(sc);
1266}
1267
1268static void
1269cpswp_stop_locked(struct cpswp_softc *sc)
1270{
1271        struct ifnet *ifp;
1272        uint32_t reg;
1273
1274        ifp = sc->ifp;
1275        CPSW_DEBUGF(sc->swsc, (""));
1276        CPSW_PORT_LOCK_ASSERT(sc);
1277
1278        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1279                return;
1280
1281        /* Disable interface */
1282        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1283        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1284
1285        /* Stop ticker */
1286        callout_stop(&sc->mii_callout);
1287
1288        /* Tear down the RX/TX queues. */
1289        if (cpsw_ports_down(sc->swsc)) {
1290                cpsw_rx_teardown(sc->swsc);
1291                cpsw_tx_teardown(sc->swsc);
1292        }
1293
1294        /* Stop MAC RX/TX modules. */
1295        reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
1296        reg &= ~CPSW_SL_MACTL_GMII_ENABLE;
1297        cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
1298
1299        if (cpsw_ports_down(sc->swsc)) {
1300                /* Capture stats before we reset controller. */
1301                cpsw_stats_collect(sc->swsc);
1302
1303                cpsw_reset(sc->swsc);
1304                cpsw_init(sc->swsc);
1305        }
1306}
1307
1308/*
1309 *  Suspend/Resume.
1310 */
1311
1312static int
1313cpsw_suspend(device_t dev)
1314{
1315        struct cpsw_softc *sc;
1316        struct cpswp_softc *psc;
1317        int i;
1318
1319        sc = device_get_softc(dev);
1320        CPSW_DEBUGF(sc, (""));
1321        for (i = 0; i < CPSW_PORTS; i++) {
1322                if (!sc->dualemac && i != sc->active_slave)
1323                        continue;
1324                psc = device_get_softc(sc->port[i].dev);
1325                CPSW_PORT_LOCK(psc);
1326                cpswp_stop_locked(psc);
1327                CPSW_PORT_UNLOCK(psc);
1328        }
1329
1330        return (0);
1331}
1332
1333static int
1334cpsw_resume(device_t dev)
1335{
1336        struct cpsw_softc *sc;
1337
1338        sc  = device_get_softc(dev);
1339        CPSW_DEBUGF(sc, ("UNIMPLEMENTED"));
1340
1341        return (0);
1342}
1343
1344/*
1345 *
1346 *  IOCTL
1347 *
1348 */
1349
1350static void
1351cpsw_set_promisc(struct cpswp_softc *sc, int set)
1352{
1353        uint32_t reg;
1354
1355        /*
1356         * Enabling promiscuous mode requires ALE_BYPASS to be enabled.
1357         * That disables the ALE forwarding logic and causes every
1358         * packet to be sent only to the host port.  In bypass mode,
1359         * the ALE processes host port transmit packets the same as in
1360         * normal mode.
1361         */
1362        reg = cpsw_read_4(sc->swsc, CPSW_ALE_CONTROL);
1363        reg &= ~CPSW_ALE_CTL_BYPASS;
1364        if (set)
1365                reg |= CPSW_ALE_CTL_BYPASS;
1366        cpsw_write_4(sc->swsc, CPSW_ALE_CONTROL, reg);
1367}
1368
1369static void
1370cpsw_set_allmulti(struct cpswp_softc *sc, int set)
1371{
1372        if (set) {
1373                printf("All-multicast mode unimplemented\n");
1374        }
1375}
1376
1377static int
1378cpswp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1379{
1380        struct cpswp_softc *sc;
1381        struct ifreq *ifr;
1382        int error;
1383        uint32_t changed;
1384
1385        error = 0;
1386        sc = ifp->if_softc;
1387        ifr = (struct ifreq *)data;
1388
1389        switch (command) {
1390        case SIOCSIFCAP:
1391                changed = ifp->if_capenable ^ ifr->ifr_reqcap;
1392                if (changed & IFCAP_HWCSUM) {
1393                        if ((ifr->ifr_reqcap & changed) & IFCAP_HWCSUM)
1394                                ifp->if_capenable |= IFCAP_HWCSUM;
1395                        else
1396                                ifp->if_capenable &= ~IFCAP_HWCSUM;
1397                }
1398                error = 0;
1399                break;
1400        case SIOCSIFFLAGS:
1401                CPSW_PORT_LOCK(sc);
1402                if (ifp->if_flags & IFF_UP) {
1403                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1404                                changed = ifp->if_flags ^ sc->if_flags;
1405                                CPSW_DEBUGF(sc->swsc,
1406                                    ("SIOCSIFFLAGS: UP & RUNNING (changed=0x%x)",
1407                                    changed));
1408                                if (changed & IFF_PROMISC)
1409                                        cpsw_set_promisc(sc,
1410                                            ifp->if_flags & IFF_PROMISC);
1411                                if (changed & IFF_ALLMULTI)
1412                                        cpsw_set_allmulti(sc,
1413                                            ifp->if_flags & IFF_ALLMULTI);
1414                        } else {
1415                                CPSW_DEBUGF(sc->swsc,
1416                                    ("SIOCSIFFLAGS: starting up"));
1417                                cpswp_init_locked(sc);
1418                        }
1419                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1420                        CPSW_DEBUGF(sc->swsc, ("SIOCSIFFLAGS: shutting down"));
1421                        cpswp_stop_locked(sc);
1422                }
1423
1424                sc->if_flags = ifp->if_flags;
1425                CPSW_PORT_UNLOCK(sc);
1426                break;
1427        case SIOCADDMULTI:
1428                cpswp_ale_update_addresses(sc, 0);
1429                break;
1430        case SIOCDELMULTI:
1431                /* Ugh.  DELMULTI doesn't provide the specific address
1432                   being removed, so the best we can do is remove
1433                   everything and rebuild it all. */
1434                cpswp_ale_update_addresses(sc, 1);
1435                break;
1436        case SIOCGIFMEDIA:
1437        case SIOCSIFMEDIA:
1438                error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command);
1439                break;
1440        default:
1441                error = ether_ioctl(ifp, command, data);
1442        }
1443        return (error);
1444}
1445
1446/*
1447 *
1448 * MIIBUS
1449 *
1450 */
1451static int
1452cpswp_miibus_ready(struct cpsw_softc *sc, uint32_t reg)
1453{
1454        uint32_t r, retries = CPSW_MIIBUS_RETRIES;
1455
1456        while (--retries) {
1457                r = cpsw_read_4(sc, reg);
1458                if ((r & MDIO_PHYACCESS_GO) == 0)
1459                        return (1);
1460                DELAY(CPSW_MIIBUS_DELAY);
1461        }
1462
1463        return (0);
1464}
1465
1466static int
1467cpswp_miibus_readreg(device_t dev, int phy, int reg)
1468{
1469        struct cpswp_softc *sc;
1470        uint32_t cmd, r;
1471
1472        sc = device_get_softc(dev);
1473        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1474                device_printf(dev, "MDIO not ready to read\n");
1475                return (0);
1476        }
1477
1478        /* Set GO, reg, phy */
1479        cmd = MDIO_PHYACCESS_GO | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
1480        cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
1481
1482        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1483                device_printf(dev, "MDIO timed out during read\n");
1484                return (0);
1485        }
1486
1487        r = cpsw_read_4(sc->swsc, sc->phyaccess);
1488        if ((r & MDIO_PHYACCESS_ACK) == 0) {
1489                device_printf(dev, "Failed to read from PHY.\n");
1490                r = 0;
1491        }
1492        return (r & 0xFFFF);
1493}
1494
1495static int
1496cpswp_miibus_writereg(device_t dev, int phy, int reg, int value)
1497{
1498        struct cpswp_softc *sc;
1499        uint32_t cmd;
1500
1501        sc = device_get_softc(dev);
1502        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1503                device_printf(dev, "MDIO not ready to write\n");
1504                return (0);
1505        }
1506
1507        /* Set GO, WRITE, reg, phy, and value */
1508        cmd = MDIO_PHYACCESS_GO | MDIO_PHYACCESS_WRITE |
1509            (reg & 0x1F) << 21 | (phy & 0x1F) << 16 | (value & 0xFFFF);
1510        cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
1511
1512        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1513                device_printf(dev, "MDIO timed out during write\n");
1514                return (0);
1515        }
1516
1517        return (0);
1518}
1519
1520static void
1521cpswp_miibus_statchg(device_t dev)
1522{
1523        struct cpswp_softc *sc;
1524        uint32_t mac_control, reg;
1525
1526        sc = device_get_softc(dev);
1527        CPSW_DEBUGF(sc->swsc, (""));
1528
1529        reg = CPSW_SL_MACCONTROL(sc->unit);
1530        mac_control = cpsw_read_4(sc->swsc, reg);
1531        mac_control &= ~(CPSW_SL_MACTL_GIG | CPSW_SL_MACTL_IFCTL_A |
1532            CPSW_SL_MACTL_IFCTL_B | CPSW_SL_MACTL_FULLDUPLEX);
1533
1534        switch(IFM_SUBTYPE(sc->mii->mii_media_active)) {
1535        case IFM_1000_SX:
1536        case IFM_1000_LX:
1537        case IFM_1000_CX:
1538        case IFM_1000_T:
1539                mac_control |= CPSW_SL_MACTL_GIG;
1540                break;
1541
1542        case IFM_100_TX:
1543                mac_control |= CPSW_SL_MACTL_IFCTL_A;
1544                break;
1545        }
1546        if (sc->mii->mii_media_active & IFM_FDX)
1547                mac_control |= CPSW_SL_MACTL_FULLDUPLEX;
1548
1549        cpsw_write_4(sc->swsc, reg, mac_control);
1550}
1551
1552/*
1553 *
1554 * Transmit/Receive Packets.
1555 *
1556 */
1557static void
1558cpsw_intr_rx(void *arg)
1559{
1560        struct cpsw_softc *sc;
1561        struct ifnet *ifp;
1562        struct mbuf *received, *next;
1563
1564        sc = (struct cpsw_softc *)arg;
1565        CPSW_RX_LOCK(sc);
1566        if (sc->rx.teardown) {
1567                sc->rx.running = 0;
1568                sc->rx.teardown = 0;
1569                cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
1570        }
1571        received = cpsw_rx_dequeue(sc);
1572        cpsw_rx_enqueue(sc);
1573        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
1574        CPSW_RX_UNLOCK(sc);
1575
1576        while (received != NULL) {
1577                next = received->m_nextpkt;
1578                received->m_nextpkt = NULL;
1579                ifp = received->m_pkthdr.rcvif;
1580                (*ifp->if_input)(ifp, received);
1581                if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
1582                received = next;
1583        }
1584}
1585
1586static struct mbuf *
1587cpsw_rx_dequeue(struct cpsw_softc *sc)
1588{
1589        int nsegs, port, removed;
1590        struct cpsw_cpdma_bd bd;
1591        struct cpsw_slot *last, *slot;
1592        struct cpswp_softc *psc;
1593        struct mbuf *m, *m0, *mb_head, *mb_tail;
1594        uint16_t m0_flags;
1595
1596        nsegs = 0;
1597        m0 = NULL;
1598        last = NULL;
1599        mb_head = NULL;
1600        mb_tail = NULL;
1601        removed = 0;
1602
1603        /* Pull completed packets off hardware RX queue. */
1604        while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) {
1605                cpsw_cpdma_read_bd(sc, slot, &bd);
1606
1607                /*
1608                 * Stop on packets still in use by hardware, but do not stop
1609                 * on packets with the teardown complete flag, they will be
1610                 * discarded later.
1611                 */
1612                if ((bd.flags & (CPDMA_BD_OWNER | CPDMA_BD_TDOWNCMPLT)) ==
1613                    CPDMA_BD_OWNER)
1614                        break;
1615
1616                last = slot;
1617                ++removed;
1618                STAILQ_REMOVE_HEAD(&sc->rx.active, next);
1619                STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
1620
1621                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
1622                bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
1623
1624                m = slot->mbuf;
1625                slot->mbuf = NULL;
1626
1627                if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
1628                        CPSW_DEBUGF(sc, ("RX teardown is complete"));
1629                        m_freem(m);
1630                        sc->rx.running = 0;
1631                        sc->rx.teardown = 0;
1632                        break;
1633                }
1634
1635                port = (bd.flags & CPDMA_BD_PORT_MASK) - 1;
1636                KASSERT(port >= 0 && port <= 1,
1637                    ("patcket received with invalid port: %d", port));
1638                psc = device_get_softc(sc->port[port].dev);
1639
1640                /* Set up mbuf */
1641                m->m_data += bd.bufoff;
1642                m->m_len = bd.buflen;
1643                if (bd.flags & CPDMA_BD_SOP) {
1644                        m->m_pkthdr.len = bd.pktlen;
1645                        m->m_pkthdr.rcvif = psc->ifp;
1646                        m->m_flags |= M_PKTHDR;
1647                        m0_flags = bd.flags;
1648                        m0 = m;
1649                }
1650                nsegs++;
1651                m->m_next = NULL;
1652                m->m_nextpkt = NULL;
1653                if (bd.flags & CPDMA_BD_EOP && m0 != NULL) {
1654                        if (m0_flags & CPDMA_BD_PASS_CRC)
1655                                m_adj(m0, -ETHER_CRC_LEN);
1656                        m0_flags = 0;
1657                        m0 = NULL;
1658                        if (nsegs > sc->rx.longest_chain)
1659                                sc->rx.longest_chain = nsegs;
1660                        nsegs = 0;
1661                }
1662
1663                if ((psc->ifp->if_capenable & IFCAP_RXCSUM) != 0) {
1664                        /* check for valid CRC by looking into pkt_err[5:4] */
1665                        if ((bd.flags &
1666                            (CPDMA_BD_SOP | CPDMA_BD_PKT_ERR_MASK)) ==
1667                            CPDMA_BD_SOP) {
1668                                m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
1669                                m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
1670                                m->m_pkthdr.csum_data = 0xffff;
1671                        }
1672                }
1673
1674                if (STAILQ_FIRST(&sc->rx.active) != NULL &&
1675                    (bd.flags & (CPDMA_BD_EOP | CPDMA_BD_EOQ)) ==
1676                    (CPDMA_BD_EOP | CPDMA_BD_EOQ)) {
1677                        cpsw_write_hdp_slot(sc, &sc->rx,
1678                            STAILQ_FIRST(&sc->rx.active));
1679                        sc->rx.queue_restart++;
1680                }
1681
1682                /* Add mbuf to packet list to be returned. */
1683                if (mb_tail != NULL && (bd.flags & CPDMA_BD_SOP)) {
1684                        mb_tail->m_nextpkt = m;
1685                } else if (mb_tail != NULL) {
1686                        mb_tail->m_next = m;
1687                } else if (mb_tail == NULL && (bd.flags & CPDMA_BD_SOP) == 0) {
1688                        if (bootverbose)
1689                                printf(
1690                                    "%s: %s: discanding fragment packet w/o header\n",
1691                                    __func__, psc->ifp->if_xname);
1692                        m_freem(m);
1693                        continue;
1694                } else {
1695                        mb_head = m;
1696                }
1697                mb_tail = m;
1698        }
1699
1700        if (removed != 0) {
1701                cpsw_write_cp_slot(sc, &sc->rx, last);
1702                sc->rx.queue_removes += removed;
1703                sc->rx.avail_queue_len += removed;
1704                sc->rx.active_queue_len -= removed;
1705                if (sc->rx.avail_queue_len > sc->rx.max_avail_queue_len)
1706                        sc->rx.max_avail_queue_len = sc->rx.avail_queue_len;
1707                CPSW_DEBUGF(sc, ("Removed %d received packet(s) from RX queue", removed));
1708        }
1709
1710        return (mb_head);
1711}
1712
1713static void
1714cpsw_rx_enqueue(struct cpsw_softc *sc)
1715{
1716        bus_dma_segment_t seg[1];
1717        struct cpsw_cpdma_bd bd;
1718        struct cpsw_slot *first_new_slot, *last_old_slot, *next, *slot;
1719        int error, nsegs, added = 0;
1720
1721        /* Register new mbufs with hardware. */
1722        first_new_slot = NULL;
1723        last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
1724        while ((slot = STAILQ_FIRST(&sc->rx.avail)) != NULL) {
1725                if (first_new_slot == NULL)
1726                        first_new_slot = slot;
1727                if (slot->mbuf == NULL) {
1728                        slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1729                        if (slot->mbuf == NULL) {
1730                                device_printf(sc->dev,
1731                                    "Unable to fill RX queue\n");
1732                                break;
1733                        }
1734                        slot->mbuf->m_len =
1735                            slot->mbuf->m_pkthdr.len =
1736                            slot->mbuf->m_ext.ext_size;
1737                }
1738
1739                error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
1740                    slot->mbuf, seg, &nsegs, BUS_DMA_NOWAIT);
1741
1742                KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
1743                KASSERT(error == 0, ("DMA error (error=%d)", error));
1744                if (error != 0 || nsegs != 1) {
1745                        device_printf(sc->dev,
1746                            "%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
1747                            __func__, nsegs, error);
1748                        bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
1749                        m_freem(slot->mbuf);
1750                        slot->mbuf = NULL;
1751                        break;
1752                }
1753
1754                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_PREREAD);
1755
1756                /* Create and submit new rx descriptor. */
1757                if ((next = STAILQ_NEXT(slot, next)) != NULL)
1758                        bd.next = cpsw_cpdma_bd_paddr(sc, next);
1759                else
1760                        bd.next = 0;
1761                bd.bufptr = seg->ds_addr;
1762                bd.bufoff = 0;
1763                bd.buflen = MCLBYTES - 1;
1764                bd.pktlen = bd.buflen;
1765                bd.flags = CPDMA_BD_OWNER;
1766                cpsw_cpdma_write_bd(sc, slot, &bd);
1767                ++added;
1768
1769                STAILQ_REMOVE_HEAD(&sc->rx.avail, next);
1770                STAILQ_INSERT_TAIL(&sc->rx.active, slot, next);
1771        }
1772
1773        if (added == 0 || first_new_slot == NULL)
1774                return;
1775
1776        CPSW_DEBUGF(sc, ("Adding %d buffers to RX queue", added));
1777
1778        /* Link new entries to hardware RX queue. */
1779        if (last_old_slot == NULL) {
1780                /* Start a fresh queue. */
1781                cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
1782        } else {
1783                /* Add buffers to end of current queue. */
1784                cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
1785        }
1786        sc->rx.queue_adds += added;
1787        sc->rx.avail_queue_len -= added;
1788        sc->rx.active_queue_len += added;
1789        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), added);
1790        if (sc->rx.active_queue_len > sc->rx.max_active_queue_len)
1791                sc->rx.max_active_queue_len = sc->rx.active_queue_len;
1792}
1793
1794static void
1795cpswp_start(struct ifnet *ifp)
1796{
1797        struct cpswp_softc *sc;
1798
1799        sc = ifp->if_softc;
1800        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
1801            sc->swsc->tx.running == 0) {
1802                return;
1803        }
1804        CPSW_TX_LOCK(sc->swsc);
1805        cpswp_tx_enqueue(sc);
1806        cpsw_tx_dequeue(sc->swsc);
1807        CPSW_TX_UNLOCK(sc->swsc);
1808}
1809
1810static void
1811cpsw_intr_tx(void *arg)
1812{
1813        struct cpsw_softc *sc;
1814
1815        sc = (struct cpsw_softc *)arg;
1816        CPSW_TX_LOCK(sc);
1817        if (cpsw_read_4(sc, CPSW_CPDMA_TX_CP(0)) == 0xfffffffc)
1818                cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
1819        cpsw_tx_dequeue(sc);
1820        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
1821        CPSW_TX_UNLOCK(sc);
1822}
1823
1824static void
1825cpswp_tx_enqueue(struct cpswp_softc *sc)
1826{
1827        bus_dma_segment_t segs[CPSW_TXFRAGS];
1828        struct cpsw_cpdma_bd bd;
1829        struct cpsw_slot *first_new_slot, *last, *last_old_slot, *next, *slot;
1830        struct mbuf *m0;
1831        int error, nsegs, seg, added = 0, padlen;
1832
1833        /* Pull pending packets from IF queue and prep them for DMA. */
1834        last = NULL;
1835        first_new_slot = NULL;
1836        last_old_slot = STAILQ_LAST(&sc->swsc->tx.active, cpsw_slot, next);
1837        while ((slot = STAILQ_FIRST(&sc->swsc->tx.avail)) != NULL) {
1838                IF_DEQUEUE(&sc->ifp->if_snd, m0);
1839                if (m0 == NULL)
1840                        break;
1841
1842                slot->mbuf = m0;
1843                padlen = ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len;
1844                if (padlen < 0)
1845                        padlen = 0;
1846                else if (padlen > 0)
1847                        m_append(slot->mbuf, padlen, sc->swsc->nullpad);
1848
1849                /* Create mapping in DMA memory */
1850                error = bus_dmamap_load_mbuf_sg(sc->swsc->mbuf_dtag,
1851                    slot->dmamap, slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
1852                /* If the packet is too fragmented, try to simplify. */
1853                if (error == EFBIG ||
1854                    (error == 0 && nsegs > sc->swsc->tx.avail_queue_len)) {
1855                        bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
1856                        m0 = m_defrag(slot->mbuf, M_NOWAIT);
1857                        if (m0 == NULL) {
1858                                device_printf(sc->dev,
1859                                    "Can't defragment packet; dropping\n");
1860                                m_freem(slot->mbuf);
1861                        } else {
1862                                CPSW_DEBUGF(sc->swsc,
1863                                    ("Requeueing defragmented packet"));
1864                                IF_PREPEND(&sc->ifp->if_snd, m0);
1865                        }
1866                        slot->mbuf = NULL;
1867                        continue;
1868                }
1869                if (error != 0) {
1870                        device_printf(sc->dev,
1871                            "%s: Can't setup DMA (error=%d), dropping packet\n",
1872                            __func__, error);
1873                        bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
1874                        m_freem(slot->mbuf);
1875                        slot->mbuf = NULL;
1876                        break;
1877                }
1878
1879                bus_dmamap_sync(sc->swsc->mbuf_dtag, slot->dmamap,
1880                                BUS_DMASYNC_PREWRITE);
1881
1882                CPSW_DEBUGF(sc->swsc,
1883                    ("Queueing TX packet: %d segments + %d pad bytes",
1884                    nsegs, padlen));
1885
1886                if (first_new_slot == NULL)
1887                        first_new_slot = slot;
1888
1889                /* Link from the previous descriptor. */
1890                if (last != NULL)
1891                        cpsw_cpdma_write_bd_next(sc->swsc, last, slot);
1892
1893                slot->ifp = sc->ifp;
1894
1895                /* If there is only one segment, the for() loop
1896                 * gets skipped and the single buffer gets set up
1897                 * as both SOP and EOP. */
1898                if (nsegs > 1) {
1899                        next = STAILQ_NEXT(slot, next);
1900                        bd.next = cpsw_cpdma_bd_paddr(sc->swsc, next);
1901                } else
1902                        bd.next = 0;
1903                /* Start by setting up the first buffer. */
1904                bd.bufptr = segs[0].ds_addr;
1905                bd.bufoff = 0;
1906                bd.buflen = segs[0].ds_len;
1907                bd.pktlen = m_length(slot->mbuf, NULL);
1908                bd.flags =  CPDMA_BD_SOP | CPDMA_BD_OWNER;
1909                if (sc->swsc->dualemac) {
1910                        bd.flags |= CPDMA_BD_TO_PORT;
1911                        bd.flags |= ((sc->unit + 1) & CPDMA_BD_PORT_MASK);
1912                }
1913                for (seg = 1; seg < nsegs; ++seg) {
1914                        /* Save the previous buffer (which isn't EOP) */
1915                        cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
1916                        STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
1917                        STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
1918                        slot = STAILQ_FIRST(&sc->swsc->tx.avail);
1919
1920                        /* Setup next buffer (which isn't SOP) */
1921                        if (nsegs > seg + 1) {
1922                                next = STAILQ_NEXT(slot, next);
1923                                bd.next = cpsw_cpdma_bd_paddr(sc->swsc, next);
1924                        } else
1925                                bd.next = 0;
1926                        bd.bufptr = segs[seg].ds_addr;
1927                        bd.bufoff = 0;
1928                        bd.buflen = segs[seg].ds_len;
1929                        bd.pktlen = 0;
1930                        bd.flags = CPDMA_BD_OWNER;
1931                }
1932
1933                /* Save the final buffer. */
1934                bd.flags |= CPDMA_BD_EOP;
1935                cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
1936                STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
1937                STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
1938
1939                last = slot;
1940                added += nsegs;
1941                if (nsegs > sc->swsc->tx.longest_chain)
1942                        sc->swsc->tx.longest_chain = nsegs;
1943
1944                BPF_MTAP(sc->ifp, m0);
1945        }
1946
1947        if (first_new_slot == NULL)
1948                return;
1949
1950        /* Attach the list of new buffers to the hardware TX queue. */
1951        if (last_old_slot != NULL &&
1952            (cpsw_cpdma_read_bd_flags(sc->swsc, last_old_slot) &
1953             CPDMA_BD_EOQ) == 0) {
1954                /* Add buffers to end of current queue. */
1955                cpsw_cpdma_write_bd_next(sc->swsc, last_old_slot,
1956                    first_new_slot);
1957        } else {
1958                /* Start a fresh queue. */
1959                cpsw_write_hdp_slot(sc->swsc, &sc->swsc->tx, first_new_slot);
1960        }
1961        sc->swsc->tx.queue_adds += added;
1962        sc->swsc->tx.avail_queue_len -= added;
1963        sc->swsc->tx.active_queue_len += added;
1964        if (sc->swsc->tx.active_queue_len > sc->swsc->tx.max_active_queue_len) {
1965                sc->swsc->tx.max_active_queue_len = sc->swsc->tx.active_queue_len;
1966        }
1967        CPSW_DEBUGF(sc->swsc, ("Queued %d TX packet(s)", added));
1968}
1969
1970static int
1971cpsw_tx_dequeue(struct cpsw_softc *sc)
1972{
1973        struct cpsw_slot *slot, *last_removed_slot = NULL;
1974        struct cpsw_cpdma_bd bd;
1975        uint32_t flags, removed = 0;
1976
1977        /* Pull completed buffers off the hardware TX queue. */
1978        slot = STAILQ_FIRST(&sc->tx.active);
1979        while (slot != NULL) {
1980                flags = cpsw_cpdma_read_bd_flags(sc, slot);
1981
1982                /* TearDown complete is only marked on the SOP for the packet. */
1983                if ((flags & (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) ==
1984                    (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) {
1985                        sc->tx.teardown = 1;
1986                }
1987
1988                if ((flags & (CPDMA_BD_SOP | CPDMA_BD_OWNER)) ==
1989                    (CPDMA_BD_SOP | CPDMA_BD_OWNER) && sc->tx.teardown == 0)
1990                        break; /* Hardware is still using this packet. */
1991
1992                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
1993                bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
1994                m_freem(slot->mbuf);
1995                slot->mbuf = NULL;
1996
1997                if (slot->ifp) {
1998                        if (sc->tx.teardown == 0)
1999                                if_inc_counter(slot->ifp, IFCOUNTER_OPACKETS, 1);
2000                        else
2001                                if_inc_counter(slot->ifp, IFCOUNTER_OQDROPS, 1);
2002                }
2003
2004                /* Dequeue any additional buffers used by this packet. */
2005                while (slot != NULL && slot->mbuf == NULL) {
2006                        STAILQ_REMOVE_HEAD(&sc->tx.active, next);
2007                        STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next);
2008                        ++removed;
2009                        last_removed_slot = slot;
2010                        slot = STAILQ_FIRST(&sc->tx.active);
2011                }
2012
2013                cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot);
2014
2015                /* Restart the TX queue if necessary. */
2016                cpsw_cpdma_read_bd(sc, last_removed_slot, &bd);
2017                if (slot != NULL && bd.next != 0 && (bd.flags &
2018                    (CPDMA_BD_EOP | CPDMA_BD_OWNER | CPDMA_BD_EOQ)) ==
2019                    (CPDMA_BD_EOP | CPDMA_BD_EOQ)) {
2020                        cpsw_write_hdp_slot(sc, &sc->tx, slot);
2021                        sc->tx.queue_restart++;
2022                        break;
2023                }
2024        }
2025
2026        if (removed != 0) {
2027                sc->tx.queue_removes += removed;
2028                sc->tx.active_queue_len -= removed;
2029                sc->tx.avail_queue_len += removed;
2030                if (sc->tx.avail_queue_len > sc->tx.max_avail_queue_len)
2031                        sc->tx.max_avail_queue_len = sc->tx.avail_queue_len;
2032                CPSW_DEBUGF(sc, ("TX removed %d completed packet(s)", removed));
2033        }
2034
2035        if (sc->tx.teardown && STAILQ_EMPTY(&sc->tx.active)) {
2036                CPSW_DEBUGF(sc, ("TX teardown is complete"));
2037                sc->tx.teardown = 0;
2038                sc->tx.running = 0;
2039        }
2040
2041        return (removed);
2042}
2043
2044/*
2045 *
2046 * Miscellaneous interrupts.
2047 *
2048 */
2049
2050static void
2051cpsw_intr_rx_thresh(void *arg)
2052{
2053        struct cpsw_softc *sc;
2054        struct ifnet *ifp;
2055        struct mbuf *received, *next;
2056
2057        sc = (struct cpsw_softc *)arg;
2058        CPSW_RX_LOCK(sc);
2059        received = cpsw_rx_dequeue(sc);
2060        cpsw_rx_enqueue(sc);
2061        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
2062        CPSW_RX_UNLOCK(sc);
2063
2064        while (received != NULL) {
2065                next = received->m_nextpkt;
2066                received->m_nextpkt = NULL;
2067                ifp = received->m_pkthdr.rcvif;
2068                (*ifp->if_input)(ifp, received);
2069                if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2070                received = next;
2071        }
2072}
2073
2074static void
2075cpsw_intr_misc_host_error(struct cpsw_softc *sc)
2076{
2077        uint32_t intstat;
2078        uint32_t dmastat;
2079        int txerr, rxerr, txchan, rxchan;
2080
2081        printf("\n\n");
2082        device_printf(sc->dev,
2083            "HOST ERROR:  PROGRAMMING ERROR DETECTED BY HARDWARE\n");
2084        printf("\n\n");
2085        intstat = cpsw_read_4(sc, CPSW_CPDMA_DMA_INTSTAT_MASKED);
2086        device_printf(sc->dev, "CPSW_CPDMA_DMA_INTSTAT_MASKED=0x%x\n", intstat);
2087        dmastat = cpsw_read_4(sc, CPSW_CPDMA_DMASTATUS);
2088        device_printf(sc->dev, "CPSW_CPDMA_DMASTATUS=0x%x\n", dmastat);
2089
2090        txerr = (dmastat >> 20) & 15;
2091        txchan = (dmastat >> 16) & 7;
2092        rxerr = (dmastat >> 12) & 15;
2093        rxchan = (dmastat >> 8) & 7;
2094
2095        switch (txerr) {
2096        case 0: break;
2097        case 1: printf("SOP error on TX channel %d\n", txchan);
2098                break;
2099        case 2: printf("Ownership bit not set on SOP buffer on TX channel %d\n", txchan);
2100                break;
2101        case 3: printf("Zero Next Buffer but not EOP on TX channel %d\n", txchan);
2102                break;
2103        case 4: printf("Zero Buffer Pointer on TX channel %d\n", txchan);
2104                break;
2105        case 5: printf("Zero Buffer Length on TX channel %d\n", txchan);
2106                break;
2107        case 6: printf("Packet length error on TX channel %d\n", txchan);
2108                break;
2109        default: printf("Unknown error on TX channel %d\n", txchan);
2110                break;
2111        }
2112
2113        if (txerr != 0) {
2114                printf("CPSW_CPDMA_TX%d_HDP=0x%x\n",
2115                    txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(txchan)));
2116                printf("CPSW_CPDMA_TX%d_CP=0x%x\n",
2117                    txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_CP(txchan)));
2118                cpsw_dump_queue(sc, &sc->tx.active);
2119        }
2120
2121        switch (rxerr) {
2122        case 0: break;
2123        case 2: printf("Ownership bit not set on RX channel %d\n", rxchan);
2124                break;
2125        case 4: printf("Zero Buffer Pointer on RX channel %d\n", rxchan);
2126                break;
2127        case 5: printf("Zero Buffer Length on RX channel %d\n", rxchan);
2128                break;
2129        case 6: printf("Buffer offset too big on RX channel %d\n", rxchan);
2130                break;
2131        default: printf("Unknown RX error on RX channel %d\n", rxchan);
2132                break;
2133        }
2134
2135        if (rxerr != 0) {
2136                printf("CPSW_CPDMA_RX%d_HDP=0x%x\n",
2137                    rxchan, cpsw_read_4(sc,CPSW_CPDMA_RX_HDP(rxchan)));
2138                printf("CPSW_CPDMA_RX%d_CP=0x%x\n",
2139                    rxchan, cpsw_read_4(sc, CPSW_CPDMA_RX_CP(rxchan)));
2140                cpsw_dump_queue(sc, &sc->rx.active);
2141        }
2142
2143        printf("\nALE Table\n");
2144        cpsw_ale_dump_table(sc);
2145
2146        // XXX do something useful here??
2147        panic("CPSW HOST ERROR INTERRUPT");
2148
2149        // Suppress this interrupt in the future.
2150        cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_CLEAR, intstat);
2151        printf("XXX HOST ERROR INTERRUPT SUPPRESSED\n");
2152        // The watchdog will probably reset the controller
2153        // in a little while.  It will probably fail again.
2154}
2155
2156static void
2157cpsw_intr_misc(void *arg)
2158{
2159        struct cpsw_softc *sc = arg;
2160        uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
2161
2162        if (stat & CPSW_WR_C_MISC_EVNT_PEND)
2163                CPSW_DEBUGF(sc, ("Time sync event interrupt unimplemented"));
2164        if (stat & CPSW_WR_C_MISC_STAT_PEND)
2165                cpsw_stats_collect(sc);
2166        if (stat & CPSW_WR_C_MISC_HOST_PEND)
2167                cpsw_intr_misc_host_error(sc);
2168        if (stat & CPSW_WR_C_MISC_MDIOLINK) {
2169                cpsw_write_4(sc, MDIOLINKINTMASKED,
2170                    cpsw_read_4(sc, MDIOLINKINTMASKED));
2171        }
2172        if (stat & CPSW_WR_C_MISC_MDIOUSER) {
2173                CPSW_DEBUGF(sc,
2174                    ("MDIO operation completed interrupt unimplemented"));
2175        }
2176        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
2177}
2178
2179/*
2180 *
2181 * Periodic Checks and Watchdog.
2182 *
2183 */
2184
2185static void
2186cpswp_tick(void *msc)
2187{
2188        struct cpswp_softc *sc = msc;
2189
2190        /* Check for media type change */
2191        mii_tick(sc->mii);
2192        if (sc->media_status != sc->mii->mii_media.ifm_media) {
2193                printf("%s: media type changed (ifm_media=%x)\n", __func__,
2194                        sc->mii->mii_media.ifm_media);
2195                cpswp_ifmedia_upd(sc->ifp);
2196        }
2197
2198        /* Schedule another timeout one second from now */
2199        callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
2200}
2201
2202static void
2203cpswp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2204{
2205        struct cpswp_softc *sc;
2206        struct mii_data *mii;
2207
2208        sc = ifp->if_softc;
2209        CPSW_DEBUGF(sc->swsc, (""));
2210        CPSW_PORT_LOCK(sc);
2211
2212        mii = sc->mii;
2213        mii_pollstat(mii);
2214
2215        ifmr->ifm_active = mii->mii_media_active;
2216        ifmr->ifm_status = mii->mii_media_status;
2217        CPSW_PORT_UNLOCK(sc);
2218}
2219
2220static int
2221cpswp_ifmedia_upd(struct ifnet *ifp)
2222{
2223        struct cpswp_softc *sc;
2224
2225        sc = ifp->if_softc;
2226        CPSW_DEBUGF(sc->swsc, (""));
2227        CPSW_PORT_LOCK(sc);
2228        mii_mediachg(sc->mii);
2229        sc->media_status = sc->mii->mii_media.ifm_media;
2230        CPSW_PORT_UNLOCK(sc);
2231
2232        return (0);
2233}
2234
2235static void
2236cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
2237{
2238        struct cpswp_softc *psc;
2239        int i;
2240
2241        cpsw_debugf_head("CPSW watchdog");
2242        device_printf(sc->dev, "watchdog timeout\n");
2243        printf("CPSW_CPDMA_TX%d_HDP=0x%x\n", 0,
2244            cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(0)));
2245        printf("CPSW_CPDMA_TX%d_CP=0x%x\n", 0,
2246            cpsw_read_4(sc, CPSW_CPDMA_TX_CP(0)));
2247        cpsw_dump_queue(sc, &sc->tx.active);
2248        for (i = 0; i < CPSW_PORTS; i++) {
2249                if (!sc->dualemac && i != sc->active_slave)
2250                        continue;
2251                psc = device_get_softc(sc->port[i].dev);
2252                CPSW_PORT_LOCK(psc);
2253                cpswp_stop_locked(psc);
2254                CPSW_PORT_UNLOCK(psc);
2255        }
2256}
2257
2258static void
2259cpsw_tx_watchdog(void *msc)
2260{
2261        struct cpsw_softc *sc;
2262
2263        sc = msc;
2264        CPSW_TX_LOCK(sc);
2265        if (sc->tx.active_queue_len == 0 || !sc->tx.running) {
2266                sc->watchdog.timer = 0; /* Nothing to do. */
2267        } else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
2268                sc->watchdog.timer = 0;  /* Stuff done while we weren't looking. */
2269        } else if (cpsw_tx_dequeue(sc) > 0) {
2270                sc->watchdog.timer = 0;  /* We just did something. */
2271        } else {
2272                /* There was something to do but it didn't get done. */
2273                ++sc->watchdog.timer;
2274                if (sc->watchdog.timer > 5) {
2275                        sc->watchdog.timer = 0;
2276                        ++sc->watchdog.resets;
2277                        cpsw_tx_watchdog_full_reset(sc);
2278                }
2279        }
2280        sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
2281        CPSW_TX_UNLOCK(sc);
2282
2283        /* Schedule another timeout one second from now */
2284        callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
2285}
2286
2287/*
2288 *
2289 * ALE support routines.
2290 *
2291 */
2292
2293static void
2294cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
2295{
2296        cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023);
2297        ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0);
2298        ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1);
2299        ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2);
2300}
2301
2302static void
2303cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
2304{
2305        cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]);
2306        cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]);
2307        cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]);
2308        cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
2309}
2310
2311static void
2312cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
2313{
2314        int i;
2315        uint32_t ale_entry[3];
2316
2317        /* First four entries are link address and broadcast. */
2318        for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
2319                cpsw_ale_read_entry(sc, i, ale_entry);
2320                if ((ALE_TYPE(ale_entry) == ALE_TYPE_ADDR ||
2321                    ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR) &&
2322                    ALE_MCAST(ale_entry)  == 1) { /* MCast link addr */
2323                        ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
2324                        cpsw_ale_write_entry(sc, i, ale_entry);
2325                }
2326        }
2327}
2328
2329static int
2330cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, int vlan,
2331        uint8_t *mac)
2332{
2333        int free_index = -1, matching_index = -1, i;
2334        uint32_t ale_entry[3], ale_type;
2335
2336        /* Find a matching entry or a free entry. */
2337        for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
2338                cpsw_ale_read_entry(sc, i, ale_entry);
2339
2340                /* Entry Type[61:60] is 0 for free entry */
2341                if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
2342                        free_index = i;
2343
2344                if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
2345                    (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
2346                    (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
2347                    (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
2348                    (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
2349                    (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
2350                        matching_index = i;
2351                        break;
2352                }
2353        }
2354
2355        if (matching_index < 0) {
2356                if (free_index < 0)
2357                        return (ENOMEM);
2358                i = free_index;
2359        }
2360
2361        if (vlan != -1)
2362                ale_type = ALE_TYPE_VLAN_ADDR << 28 | vlan << 16;
2363        else
2364                ale_type = ALE_TYPE_ADDR << 28;
2365
2366        /* Set MAC address */
2367        ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
2368        ale_entry[1] = mac[0] << 8 | mac[1];
2369
2370        /* Entry type[61:60] and Mcast fwd state[63:62] is fw(3). */
2371        ale_entry[1] |= ALE_MCAST_FWD | ale_type;
2372
2373        /* Set portmask [68:66] */
2374        ale_entry[2] = (portmap & 7) << 2;
2375
2376        cpsw_ale_write_entry(sc, i, ale_entry);
2377
2378        return 0;
2379}
2380
2381static void
2382cpsw_ale_dump_table(struct cpsw_softc *sc) {
2383        int i;
2384        uint32_t ale_entry[3];
2385        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2386                cpsw_ale_read_entry(sc, i, ale_entry);
2387                switch (ALE_TYPE(ale_entry)) {
2388                case ALE_TYPE_VLAN:
2389                        printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
2390                                ale_entry[1], ale_entry[0]);
2391                        printf("type: %u ", ALE_TYPE(ale_entry));
2392                        printf("vlan: %u ", ALE_VLAN(ale_entry));
2393                        printf("untag: %u ", ALE_VLAN_UNTAG(ale_entry));
2394                        printf("reg flood: %u ", ALE_VLAN_REGFLOOD(ale_entry));
2395                        printf("unreg flood: %u ", ALE_VLAN_UNREGFLOOD(ale_entry));
2396                        printf("members: %u ", ALE_VLAN_MEMBERS(ale_entry));
2397                        printf("\n");
2398                        break;
2399                case ALE_TYPE_ADDR:
2400                case ALE_TYPE_VLAN_ADDR:
2401                        printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
2402                                ale_entry[1], ale_entry[0]);
2403                        printf("type: %u ", ALE_TYPE(ale_entry));
2404                        printf("mac: %02x:%02x:%02x:%02x:%02x:%02x ",
2405                                (ale_entry[1] >> 8) & 0xFF,
2406                                (ale_entry[1] >> 0) & 0xFF,
2407                                (ale_entry[0] >>24) & 0xFF,
2408                                (ale_entry[0] >>16) & 0xFF,
2409                                (ale_entry[0] >> 8) & 0xFF,
2410                                (ale_entry[0] >> 0) & 0xFF);
2411                        printf(ALE_MCAST(ale_entry) ? "mcast " : "ucast ");
2412                        if (ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR)
2413                                printf("vlan: %u ", ALE_VLAN(ale_entry));
2414                        printf("port: %u ", ALE_PORTS(ale_entry));
2415                        printf("\n");
2416                        break;
2417                }
2418        }
2419        printf("\n");
2420}
2421
2422static int
2423cpswp_ale_update_addresses(struct cpswp_softc *sc, int purge)
2424{
2425        uint8_t *mac;
2426        uint32_t ale_entry[3], ale_type, portmask;
2427        struct ifmultiaddr *ifma;
2428
2429        if (sc->swsc->dualemac) {
2430                ale_type = ALE_TYPE_VLAN_ADDR << 28 | sc->vlan << 16;
2431                portmask = 1 << (sc->unit + 1) | 1 << 0;
2432        } else {
2433                ale_type = ALE_TYPE_ADDR << 28;
2434                portmask = 7;
2435        }
2436
2437        /*
2438         * Route incoming packets for our MAC address to Port 0 (host).
2439         * For simplicity, keep this entry at table index 0 for port 1 and
2440         * at index 2 for port 2 in the ALE.
2441         */
2442        if_addr_rlock(sc->ifp);
2443        mac = LLADDR((struct sockaddr_dl *)sc->ifp->if_addr->ifa_addr);
2444        ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
2445        ale_entry[1] = ale_type | mac[0] << 8 | mac[1]; /* addr entry + mac */
2446        ale_entry[2] = 0; /* port = 0 */
2447        cpsw_ale_write_entry(sc->swsc, 0 + 2 * sc->unit, ale_entry);
2448
2449        /* Set outgoing MAC Address for slave port. */
2450        cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_HI(sc->unit + 1),
2451            mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
2452        cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_LO(sc->unit + 1),
2453            mac[5] << 8 | mac[4]);
2454        if_addr_runlock(sc->ifp);
2455
2456        /* Keep the broadcast address at table entry 1 (or 3). */
2457        ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
2458        /* ALE_MCAST_FWD, Addr type, upper 16 bits of Mac */
2459        ale_entry[1] = ALE_MCAST_FWD | ale_type | 0xffff;
2460        ale_entry[2] = portmask << 2;
2461        cpsw_ale_write_entry(sc->swsc, 1 + 2 * sc->unit, ale_entry);
2462
2463        /* SIOCDELMULTI doesn't specify the particular address
2464           being removed, so we have to remove all and rebuild. */
2465        if (purge)
2466                cpsw_ale_remove_all_mc_entries(sc->swsc);
2467
2468        /* Set other multicast addrs desired. */
2469        if_maddr_rlock(sc->ifp);
2470        CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
2471                if (ifma->ifma_addr->sa_family != AF_LINK)
2472                        continue;
2473                cpsw_ale_mc_entry_set(sc->swsc, portmask, sc->vlan,
2474                    LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
2475        }
2476        if_maddr_runlock(sc->ifp);
2477
2478        return (0);
2479}
2480
2481static int
2482cpsw_ale_update_vlan_table(struct cpsw_softc *sc, int vlan, int ports,
2483        int untag, int mcregflood, int mcunregflood)
2484{
2485        int free_index, i, matching_index;
2486        uint32_t ale_entry[3];
2487
2488        free_index = matching_index = -1;
2489        /* Find a matching entry or a free entry. */
2490        for (i = 5; i < CPSW_MAX_ALE_ENTRIES; i++) {
2491                cpsw_ale_read_entry(sc, i, ale_entry);
2492
2493                /* Entry Type[61:60] is 0 for free entry */
2494                if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
2495                        free_index = i;
2496
2497                if (ALE_VLAN(ale_entry) == vlan) {
2498                        matching_index = i;
2499                        break;
2500                }
2501        }
2502
2503        if (matching_index < 0) {
2504                if (free_index < 0)
2505                        return (-1);
2506                i = free_index;
2507        }
2508
2509        ale_entry[0] = (untag & 7) << 24 | (mcregflood & 7) << 16 |
2510            (mcunregflood & 7) << 8 | (ports & 7);
2511        ale_entry[1] = ALE_TYPE_VLAN << 28 | vlan << 16;
2512        ale_entry[2] = 0;
2513        cpsw_ale_write_entry(sc, i, ale_entry);
2514
2515        return (0);
2516}
2517
2518/*
2519 *
2520 * Statistics and Sysctls.
2521 *
2522 */
2523
2524#if 0
2525static void
2526cpsw_stats_dump(struct cpsw_softc *sc)
2527{
2528        int i;
2529        uint32_t r;
2530
2531        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2532                r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
2533                    cpsw_stat_sysctls[i].reg);
2534                CPSW_DEBUGF(sc, ("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
2535                    (intmax_t)sc->shadow_stats[i], r,
2536                    (intmax_t)sc->shadow_stats[i] + r));
2537        }
2538}
2539#endif
2540
2541static void
2542cpsw_stats_collect(struct cpsw_softc *sc)
2543{
2544        int i;
2545        uint32_t r;
2546
2547        CPSW_DEBUGF(sc, ("Controller shadow statistics updated."));
2548
2549        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2550                r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
2551                    cpsw_stat_sysctls[i].reg);
2552                sc->shadow_stats[i] += r;
2553                cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg,
2554                    r);
2555        }
2556}
2557
2558static int
2559cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS)
2560{
2561        struct cpsw_softc *sc;
2562        struct cpsw_stat *stat;
2563        uint64_t result;
2564
2565        sc = (struct cpsw_softc *)arg1;
2566        stat = &cpsw_stat_sysctls[oidp->oid_number];
2567        result = sc->shadow_stats[oidp->oid_number];
2568        result += cpsw_read_4(sc, CPSW_STATS_OFFSET + stat->reg);
2569        return (sysctl_handle_64(oidp, &result, 0, req));
2570}
2571
2572static int
2573cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
2574{
2575        struct cpsw_softc *sc;
2576        struct bintime t;
2577        unsigned result;
2578
2579        sc = (struct cpsw_softc *)arg1;
2580        getbinuptime(&t);
2581        bintime_sub(&t, &sc->attach_uptime);
2582        result = t.sec;
2583        return (sysctl_handle_int(oidp, &result, 0, req));
2584}
2585
2586static int
2587cpsw_intr_coalesce(SYSCTL_HANDLER_ARGS)
2588{
2589        int error;
2590        struct cpsw_softc *sc;
2591        uint32_t ctrl, intr_per_ms;
2592
2593        sc = (struct cpsw_softc *)arg1;
2594        error = sysctl_handle_int(oidp, &sc->coal_us, 0, req);
2595        if (error != 0 || req->newptr == NULL)
2596                return (error);
2597
2598        ctrl = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
2599        ctrl &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
2600        if (sc->coal_us == 0) {
2601                /* Disable the interrupt pace hardware. */
2602                cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
2603                cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), 0);
2604                cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), 0);
2605                return (0);
2606        }
2607
2608        if (sc->coal_us > CPSW_WR_C_IMAX_US_MAX)
2609                sc->coal_us = CPSW_WR_C_IMAX_US_MAX;
2610        if (sc->coal_us < CPSW_WR_C_IMAX_US_MIN)
2611                sc->coal_us = CPSW_WR_C_IMAX_US_MIN;
2612        intr_per_ms = 1000 / sc->coal_us;
2613        /* Just to make sure... */
2614        if (intr_per_ms > CPSW_WR_C_IMAX_MAX)
2615                intr_per_ms = CPSW_WR_C_IMAX_MAX;
2616        if (intr_per_ms < CPSW_WR_C_IMAX_MIN)
2617                intr_per_ms = CPSW_WR_C_IMAX_MIN;
2618
2619        /* Set the prescale to produce 4us pulses from the 125 Mhz clock. */
2620        ctrl |= (125 * 4) & CPSW_WR_INT_PRESCALE_MASK;
2621
2622        /* Enable the interrupt pace hardware. */
2623        cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), intr_per_ms);
2624        cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), intr_per_ms);
2625        ctrl |= CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE;
2626        cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
2627
2628        return (0);
2629}
2630
2631static int
2632cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
2633{
2634        struct cpsw_softc *swsc;
2635        struct cpswp_softc *sc;
2636        struct bintime t;
2637        unsigned result;
2638
2639        swsc = arg1;
2640        sc = device_get_softc(swsc->port[arg2].dev);
2641        if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
2642                getbinuptime(&t);
2643                bintime_sub(&t, &sc->init_uptime);
2644                result = t.sec;
2645        } else
2646                result = 0;
2647        return (sysctl_handle_int(oidp, &result, 0, req));
2648}
2649
2650static void
2651cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
2652        struct cpsw_queue *queue)
2653{
2654        struct sysctl_oid_list *parent;
2655
2656        parent = SYSCTL_CHILDREN(node);
2657        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "totalBuffers",
2658            CTLFLAG_RD, &queue->queue_slots, 0,
2659            "Total buffers currently assigned to this queue");
2660        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "activeBuffers",
2661            CTLFLAG_RD, &queue->active_queue_len, 0,
2662            "Buffers currently registered with hardware controller");
2663        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxActiveBuffers",
2664            CTLFLAG_RD, &queue->max_active_queue_len, 0,
2665            "Max value of activeBuffers since last driver reset");
2666        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "availBuffers",
2667            CTLFLAG_RD, &queue->avail_queue_len, 0,
2668            "Buffers allocated to this queue but not currently "
2669            "registered with hardware controller");
2670        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxAvailBuffers",
2671            CTLFLAG_RD, &queue->max_avail_queue_len, 0,
2672            "Max value of availBuffers since last driver reset");
2673        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalEnqueued",
2674            CTLFLAG_RD, &queue->queue_adds, 0,
2675            "Total buffers added to queue");
2676        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalDequeued",
2677            CTLFLAG_RD, &queue->queue_removes, 0,
2678            "Total buffers removed from queue");
2679        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "queueRestart",
2680            CTLFLAG_RD, &queue->queue_restart, 0,
2681            "Total times the queue has been restarted");
2682        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "longestChain",
2683            CTLFLAG_RD, &queue->longest_chain, 0,
2684            "Max buffers used for a single packet");
2685}
2686
2687static void
2688cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
2689        struct cpsw_softc *sc)
2690{
2691        struct sysctl_oid_list *parent;
2692
2693        parent = SYSCTL_CHILDREN(node);
2694        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "resets",
2695            CTLFLAG_RD, &sc->watchdog.resets, 0,
2696            "Total number of watchdog resets");
2697}
2698
2699static void
2700cpsw_add_sysctls(struct cpsw_softc *sc)
2701{
2702        struct sysctl_ctx_list *ctx;
2703        struct sysctl_oid *stats_node, *queue_node, *node;
2704        struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
2705        struct sysctl_oid_list *ports_parent, *port_parent;
2706        char port[16];
2707        int i;
2708
2709        ctx = device_get_sysctl_ctx(sc->dev);
2710        parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
2711
2712        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "debug",
2713            CTLFLAG_RW, &sc->debug, 0, "Enable switch debug messages");
2714
2715        SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
2716            CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
2717            "Time since driver attach");
2718
2719        SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "intr_coalesce_us",
2720            CTLTYPE_UINT | CTLFLAG_RW, sc, 0, cpsw_intr_coalesce, "IU",
2721            "minimum time between interrupts");
2722
2723        node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "ports",
2724            CTLFLAG_RD, NULL, "CPSW Ports Statistics");
2725        ports_parent = SYSCTL_CHILDREN(node);
2726        for (i = 0; i < CPSW_PORTS; i++) {
2727                if (!sc->dualemac && i != sc->active_slave)
2728                        continue;
2729                port[0] = '0' + i;
2730                port[1] = '\0';
2731                node = SYSCTL_ADD_NODE(ctx, ports_parent, OID_AUTO,
2732                    port, CTLFLAG_RD, NULL, "CPSW Port Statistics");
2733                port_parent = SYSCTL_CHILDREN(node);
2734                SYSCTL_ADD_PROC(ctx, port_parent, OID_AUTO, "uptime",
2735                    CTLTYPE_UINT | CTLFLAG_RD, sc, i,
2736                    cpsw_stat_uptime, "IU", "Seconds since driver init");
2737        }
2738
2739        stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
2740                                     CTLFLAG_RD, NULL, "CPSW Statistics");
2741        stats_parent = SYSCTL_CHILDREN(stats_node);
2742        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2743                SYSCTL_ADD_PROC(ctx, stats_parent, i,
2744                                cpsw_stat_sysctls[i].oid,
2745                                CTLTYPE_U64 | CTLFLAG_RD, sc, 0,
2746                                cpsw_stats_sysctl, "IU",
2747                                cpsw_stat_sysctls[i].oid);
2748        }
2749
2750        queue_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "queue",
2751            CTLFLAG_RD, NULL, "CPSW Queue Statistics");
2752        queue_parent = SYSCTL_CHILDREN(queue_node);
2753
2754        node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "tx",
2755            CTLFLAG_RD, NULL, "TX Queue Statistics");
2756        cpsw_add_queue_sysctls(ctx, node, &sc->tx);
2757
2758        node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "rx",
2759            CTLFLAG_RD, NULL, "RX Queue Statistics");
2760        cpsw_add_queue_sysctls(ctx, node, &sc->rx);
2761
2762        node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "watchdog",
2763            CTLFLAG_RD, NULL, "Watchdog Statistics");
2764        cpsw_add_watchdog_sysctls(ctx, node, sc);
2765}
2766
2767#ifdef CPSW_ETHERSWITCH
2768static etherswitch_info_t etherswitch_info = {
2769        .es_nports =            CPSW_PORTS + 1,
2770        .es_nvlangroups =       CPSW_VLANS,
2771        .es_name =              "TI Common Platform Ethernet Switch (CPSW)",
2772        .es_vlan_caps =         ETHERSWITCH_VLAN_DOT1Q,
2773};
2774
2775static etherswitch_info_t *
2776cpsw_getinfo(device_t dev)
2777{
2778        return (&etherswitch_info);
2779}
2780
2781static int
2782cpsw_getport(device_t dev, etherswitch_port_t *p)
2783{
2784        int err;
2785        struct cpsw_softc *sc;
2786        struct cpswp_softc *psc;
2787        struct ifmediareq *ifmr;
2788        uint32_t reg;
2789
2790        if (p->es_port < 0 || p->es_port > CPSW_PORTS)
2791                return (ENXIO);
2792
2793        err = 0;
2794        sc = device_get_softc(dev);
2795        if (p->es_port == CPSW_CPU_PORT) {
2796                p->es_flags |= ETHERSWITCH_PORT_CPU;
2797                ifmr = &p->es_ifmr;
2798                ifmr->ifm_current = ifmr->ifm_active =
2799                    IFM_ETHER | IFM_1000_T | IFM_FDX;
2800                ifmr->ifm_mask = 0;
2801                ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
2802                ifmr->ifm_count = 0;
2803        } else {
2804                psc = device_get_softc(sc->port[p->es_port - 1].dev);
2805                err = ifmedia_ioctl(psc->ifp, &p->es_ifr,
2806                    &psc->mii->mii_media, SIOCGIFMEDIA);
2807        }
2808        reg = cpsw_read_4(sc, CPSW_PORT_P_VLAN(p->es_port));
2809        p->es_pvid = reg & ETHERSWITCH_VID_MASK;
2810
2811        reg = cpsw_read_4(sc, CPSW_ALE_PORTCTL(p->es_port));
2812        if (reg & ALE_PORTCTL_DROP_UNTAGGED)
2813                p->es_flags |= ETHERSWITCH_PORT_DROPUNTAGGED;
2814        if (reg & ALE_PORTCTL_INGRESS)
2815                p->es_flags |= ETHERSWITCH_PORT_INGRESS;
2816
2817        return (err);
2818}
2819
2820static int
2821cpsw_setport(device_t dev, etherswitch_port_t *p)
2822{
2823        struct cpsw_softc *sc;
2824        struct cpswp_softc *psc;
2825        struct ifmedia *ifm;
2826        uint32_t reg;
2827
2828        if (p->es_port < 0 || p->es_port > CPSW_PORTS)
2829                return (ENXIO);
2830
2831        sc = device_get_softc(dev);
2832        if (p->es_pvid != 0) {
2833                cpsw_write_4(sc, CPSW_PORT_P_VLAN(p->es_port),
2834                    p->es_pvid & ETHERSWITCH_VID_MASK);
2835        }
2836
2837        reg = cpsw_read_4(sc, CPSW_ALE_PORTCTL(p->es_port));
2838        if (p->es_flags & ETHERSWITCH_PORT_DROPUNTAGGED)
2839                reg |= ALE_PORTCTL_DROP_UNTAGGED;
2840        else
2841                reg &= ~ALE_PORTCTL_DROP_UNTAGGED;
2842        if (p->es_flags & ETHERSWITCH_PORT_INGRESS)
2843                reg |= ALE_PORTCTL_INGRESS;
2844        else
2845                reg &= ~ALE_PORTCTL_INGRESS;
2846        cpsw_write_4(sc, CPSW_ALE_PORTCTL(p->es_port), reg);
2847
2848        /* CPU port does not allow media settings. */
2849        if (p->es_port == CPSW_CPU_PORT)
2850                return (0);
2851
2852        psc = device_get_softc(sc->port[p->es_port - 1].dev);
2853        ifm = &psc->mii->mii_media;
2854
2855        return (ifmedia_ioctl(psc->ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
2856}
2857
2858static int
2859cpsw_getconf(device_t dev, etherswitch_conf_t *conf)
2860{
2861
2862        /* Return the VLAN mode. */
2863        conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
2864        conf->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
2865
2866        return (0);
2867}
2868
2869static int
2870cpsw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
2871{
2872        int i, vid;
2873        uint32_t ale_entry[3];
2874        struct cpsw_softc *sc;
2875
2876        sc = device_get_softc(dev);
2877
2878        if (vg->es_vlangroup >= CPSW_VLANS)
2879                return (EINVAL);
2880
2881        vg->es_vid = 0;
2882        vid = cpsw_vgroups[vg->es_vlangroup].vid;
2883        if (vid == -1)
2884                return (0);
2885
2886        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2887                cpsw_ale_read_entry(sc, i, ale_entry);
2888                if (ALE_TYPE(ale_entry) != ALE_TYPE_VLAN)
2889                        continue;
2890                if (vid != ALE_VLAN(ale_entry))
2891                        continue;
2892
2893                vg->es_fid = 0;
2894                vg->es_vid = ALE_VLAN(ale_entry) | ETHERSWITCH_VID_VALID;
2895                vg->es_member_ports = ALE_VLAN_MEMBERS(ale_entry);
2896                vg->es_untagged_ports = ALE_VLAN_UNTAG(ale_entry);
2897        }
2898
2899        return (0);
2900}
2901
2902static void
2903cpsw_remove_vlan(struct cpsw_softc *sc, int vlan)
2904{
2905        int i;
2906        uint32_t ale_entry[3];
2907
2908        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2909                cpsw_ale_read_entry(sc, i, ale_entry);
2910                if (ALE_TYPE(ale_entry) != ALE_TYPE_VLAN)
2911                        continue;
2912                if (vlan != ALE_VLAN(ale_entry))
2913                        continue;
2914                ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
2915                cpsw_ale_write_entry(sc, i, ale_entry);
2916                break;
2917        }
2918}
2919
2920static int
2921cpsw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
2922{
2923        int i;
2924        struct cpsw_softc *sc;
2925
2926        sc = device_get_softc(dev);
2927
2928        for (i = 0; i < CPSW_VLANS; i++) {
2929                /* Is this Vlan ID in use by another vlangroup ? */
2930                if (vg->es_vlangroup != i && cpsw_vgroups[i].vid == vg->es_vid)
2931                        return (EINVAL);
2932        }
2933
2934        if (vg->es_vid == 0) {
2935                if (cpsw_vgroups[vg->es_vlangroup].vid == -1)
2936                        return (0);
2937                cpsw_remove_vlan(sc, cpsw_vgroups[vg->es_vlangroup].vid);
2938                cpsw_vgroups[vg->es_vlangroup].vid = -1;
2939                vg->es_untagged_ports = 0;
2940                vg->es_member_ports = 0;
2941                vg->es_vid = 0;
2942                return (0);
2943        }
2944
2945        vg->es_vid &= ETHERSWITCH_VID_MASK;
2946        vg->es_member_ports &= CPSW_PORTS_MASK;
2947        vg->es_untagged_ports &= CPSW_PORTS_MASK;
2948
2949        if (cpsw_vgroups[vg->es_vlangroup].vid != -1 &&
2950            cpsw_vgroups[vg->es_vlangroup].vid != vg->es_vid)
2951                return (EINVAL);
2952
2953        cpsw_vgroups[vg->es_vlangroup].vid = vg->es_vid;
2954        cpsw_ale_update_vlan_table(sc, vg->es_vid, vg->es_member_ports,
2955            vg->es_untagged_ports, vg->es_member_ports, 0);
2956
2957        return (0);
2958}
2959
2960static int
2961cpsw_readreg(device_t dev, int addr)
2962{
2963
2964        /* Not supported. */
2965        return (0);
2966}
2967
2968static int
2969cpsw_writereg(device_t dev, int addr, int value)
2970{
2971
2972        /* Not supported. */
2973        return (0);
2974}
2975
2976static int
2977cpsw_readphy(device_t dev, int phy, int reg)
2978{
2979
2980        /* Not supported. */
2981        return (0);
2982}
2983
2984static int
2985cpsw_writephy(device_t dev, int phy, int reg, int data)
2986{
2987
2988        /* Not supported. */
2989        return (0);
2990}
2991#endif
Note: See TracBrowser for help on using the repository browser.