Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add driver for TI CPSW Ethernet on TI AM335x SoCs.



details:   https://anonhg.NetBSD.org/src/rev/f761b1112285
branches:  trunk
changeset: 783682:f761b1112285
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Thu Jan 03 21:13:26 2013 +0000

description:
Add driver for TI CPSW Ethernet on TI AM335x SoCs.

Portions of this driver are derived from FreeBSD's cpsw(4).

Developed and tested on a BeagleBone.

diffstat:

 sys/arch/arm/omap/files.omap2   |     6 +-
 sys/arch/arm/omap/if_cpsw.c     |  1244 +++++++++++++++++++++++++++++++++++++++
 sys/arch/arm/omap/if_cpswreg.h  |   136 ++++
 sys/arch/evbarm/conf/BEAGLEBONE |     6 +-
 sys/dev/DEVNAMES                |     3 +-
 5 files changed, 1392 insertions(+), 3 deletions(-)

diffs (truncated from 1446 to 300 lines):

diff -r 4513d85e516f -r f761b1112285 sys/arch/arm/omap/files.omap2
--- a/sys/arch/arm/omap/files.omap2     Thu Jan 03 17:12:05 2013 +0000
+++ b/sys/arch/arm/omap/files.omap2     Thu Jan 03 21:13:26 2013 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.omap2,v 1.21 2013/01/01 23:22:44 jmcneill Exp $
+#      $NetBSD: files.omap2,v 1.22 2013/01/03 21:13:26 jakllsch Exp $
 #
 # Configuration info for Texas Instruments OMAP2/OMAP3 CPU support
 # Based on xscale/files.pxa2x0
@@ -129,6 +129,10 @@
 attach omapfb at obio
 file   arch/arm/omap/omapfb.c                  omapfb
 
+device cpsw: ether, ifnet, arp, mii, mii_phy
+attach cpsw at obio
+file   arch/arm/omap/if_cpsw.c                 cpsw
+
 # these bus space methods are not bus-specific ...
 #
 file   arch/arm/omap/omap_nobyteacc_space.c    emifs | gpmc
diff -r 4513d85e516f -r f761b1112285 sys/arch/arm/omap/if_cpsw.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/omap/if_cpsw.c       Thu Jan 03 21:13:26 2013 +0000
@@ -0,0 +1,1244 @@
+/*     $NetBSD: if_cpsw.c,v 1.1 2013/01/03 21:13:26 jakllsch Exp $     */
+
+/*
+ * Copyright (c) 2013 Jonathan A. Kollasch
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion%Freebsd.org@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(1, "$NetBSD: if_cpsw.c,v 1.1 2013/01/03 21:13:26 jakllsch Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/intr.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#include <net/bpf.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arch/arm/omap/omap2_obiovar.h>
+#include <arch/arm/omap/if_cpswreg.h>
+
+#define ETHER_ALIGN (roundup2(ETHER_HDR_LEN, sizeof(uint32_t)) - ETHER_HDR_LEN)
+
+#define CPSW_TXFRAGS   16
+
+#define CPSW_CPPI_RAM_SIZE (0x2000)
+#define CPSW_CPPI_RAM_TXDESCS_SIZE (CPSW_CPPI_RAM_SIZE/2)
+#define CPSW_CPPI_RAM_RXDESCS_SIZE \
+    (CPSW_CPPI_RAM_SIZE - CPSW_CPPI_RAM_TXDESCS_SIZE)
+#define CPSW_CPPI_RAM_TXDESCS_BASE (CPSW_CPPI_RAM_OFFSET + 0x0000)
+#define CPSW_CPPI_RAM_RXDESCS_BASE \
+    (CPSW_CPPI_RAM_OFFSET + CPSW_CPPI_RAM_TXDESCS_SIZE)
+
+#define CPSW_NTXDESCS (CPSW_CPPI_RAM_TXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd))
+#define CPSW_NRXDESCS (CPSW_CPPI_RAM_RXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd))
+
+CTASSERT(powerof2(CPSW_NTXDESCS));
+CTASSERT(powerof2(CPSW_NRXDESCS));
+
+#define CPSW_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
+
+#define TXDESC_NEXT(x) cpsw_txdesc_adjust((x), 1)
+#define TXDESC_PREV(x) cpsw_txdesc_adjust((x), -1)
+
+#define RXDESC_NEXT(x) cpsw_rxdesc_adjust((x), 1)
+#define RXDESC_PREV(x) cpsw_rxdesc_adjust((x), -1)
+
+struct cpsw_ring_data {
+       bus_dmamap_t tx_dm[CPSW_NTXDESCS];
+       struct mbuf *tx_mb[CPSW_NTXDESCS];
+       bus_dmamap_t rx_dm[CPSW_NRXDESCS];
+       struct mbuf *rx_mb[CPSW_NRXDESCS];
+};
+
+struct cpsw_softc {
+       device_t sc_dev;
+       bus_space_tag_t sc_bst;
+       bus_space_handle_t sc_bsh;
+       bus_dma_tag_t sc_bdt;
+       bus_space_handle_t sc_bsh_txdescs;
+       bus_space_handle_t sc_bsh_rxdescs;
+       bus_addr_t sc_txdescs_pa;
+       bus_addr_t sc_rxdescs_pa;
+       struct ethercom sc_ec;
+       struct mii_data sc_mii;
+       callout_t sc_tick_ch;
+       void *sc_ih;
+       struct cpsw_ring_data *sc_rdp;
+       volatile u_int sc_txnext;
+       volatile u_int sc_txhead;
+       volatile u_int sc_rxhead;
+       void *sc_rxthih;
+       void *sc_rxih;
+       void *sc_txih;
+       void *sc_miscih;
+       void *sc_txpad;
+       bus_dmamap_t sc_txpad_dm;
+#define sc_txpad_pa sc_txpad_dm->dm_segs[0].ds_addr
+       uint8_t sc_enaddr[ETHER_ADDR_LEN];
+       volatile bool sc_txrun;
+       volatile bool sc_rxrun;
+       volatile bool sc_txeoq;
+       volatile bool sc_rxeoq;
+};
+
+static int cpsw_match(device_t, cfdata_t, void *);
+static void cpsw_attach(device_t, device_t, void *);
+
+static void cpsw_start(struct ifnet *);
+static int cpsw_ioctl(struct ifnet *, u_long, void *);
+static void cpsw_watchdog(struct ifnet *);
+static int cpsw_init(struct ifnet *);
+static void cpsw_stop(struct ifnet *, int);
+
+static int cpsw_mii_readreg(device_t, int, int);
+static void cpsw_mii_writereg(device_t, int, int, int);
+static void cpsw_mii_statchg(struct ifnet *);
+
+static int cpsw_new_rxbuf(struct cpsw_softc * const, const u_int);
+static void cpsw_tick(void *);
+
+static int cpsw_rxthintr(void *);
+static int cpsw_rxintr(void *);
+static int cpsw_txintr(void *);
+static int cpsw_miscintr(void *);
+
+CFATTACH_DECL_NEW(cpsw, sizeof(struct cpsw_softc),
+    cpsw_match, cpsw_attach, NULL, NULL);
+
+#undef KERNHIST
+#include <sys/kernhist.h>
+KERNHIST_DEFINE(cpswhist);
+
+#ifdef KERNHIST
+#define KERNHIST_CALLED_5(NAME, i, j, k, l) \
+do { \
+       _kernhist_call = atomic_inc_uint_nv(&_kernhist_cnt); \
+       KERNHIST_LOG(NAME, "called! %x %x %x %x", i, j, k, l); \
+} while (/*CONSTCOND*/ 0)
+#else
+#define KERNHIST_CALLED_5(NAME, i, j, k, l)
+#endif
+
+static inline u_int
+cpsw_txdesc_adjust(u_int x, int y)
+{
+       return (((x) + y) & (CPSW_NTXDESCS - 1));
+}
+
+static inline u_int
+cpsw_rxdesc_adjust(u_int x, int y)
+{
+       return (((x) + y) & (CPSW_NRXDESCS - 1));
+}
+
+static inline uint32_t
+cpsw_read_4(struct cpsw_softc * const sc, bus_size_t const offset)
+{
+       return bus_space_read_4(sc->sc_bst, sc->sc_bsh, offset);
+}
+
+static inline void
+cpsw_write_4(struct cpsw_softc * const sc, bus_size_t const offset,
+    uint32_t const value)
+{
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, offset, value);
+}
+
+static inline void
+cpsw_set_txdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n)
+{
+       const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0;
+
+       KERNHIST_FUNC(__func__);
+       KERNHIST_CALLED_5(cpswhist, sc, i, n, 0);
+
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh_txdescs, o, n);
+}
+
+static inline void
+cpsw_set_rxdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n)
+{
+       const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0;
+
+       KERNHIST_FUNC(__func__);
+       KERNHIST_CALLED_5(cpswhist, sc, i, n, 0);
+
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, n);
+}
+
+static inline void
+cpsw_get_txdesc(struct cpsw_softc * const sc, const u_int i,
+    struct cpsw_cpdma_bd * const bdp)
+{
+       const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+       uint32_t * const dp = bdp->word;
+       const bus_size_t c = __arraycount(bdp->word);
+
+       KERNHIST_FUNC(__func__);
+       KERNHIST_CALLED_5(cpswhist, sc, i, bdp, 0);
+
+       bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o, dp, c);
+       KERNHIST_LOG(cpswhist, "%08x %08x %08x %08x\n",
+           dp[0], dp[1], dp[2], dp[3]);
+}
+
+static inline void
+cpsw_set_txdesc(struct cpsw_softc * const sc, const u_int i,
+    struct cpsw_cpdma_bd * const bdp)
+{
+       const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+       uint32_t * const dp = bdp->word;
+       const bus_size_t c = __arraycount(bdp->word);
+
+       KERNHIST_FUNC(__func__);
+       KERNHIST_CALLED_5(cpswhist, sc, i, bdp, 0);
+       KERNHIST_LOG(cpswhist, "%08x %08x %08x %08x\n",
+           dp[0], dp[1], dp[2], dp[3]);
+
+       bus_space_write_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o, dp, c);
+}
+
+static inline void
+cpsw_get_rxdesc(struct cpsw_softc * const sc, const u_int i,
+    struct cpsw_cpdma_bd * const bdp)
+{
+       const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+       uint32_t * const dp = bdp->word;
+       const bus_size_t c = __arraycount(bdp->word);
+
+       KERNHIST_FUNC(__func__);
+       KERNHIST_CALLED_5(cpswhist, sc, i, bdp, 0);
+
+       bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, dp, c);
+
+       KERNHIST_LOG(cpswhist, "%08x %08x %08x %08x\n",
+           dp[0], dp[1], dp[2], dp[3]);
+}
+



Home | Main Index | Thread Index | Old Index