Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/sunxi Add driver for sun4i/sun7i 10/100 Fast Et...



details:   https://anonhg.NetBSD.org/src/rev/30d71b0c2351
branches:  trunk
changeset: 827216:30d71b0c2351
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Oct 20 22:29:15 2017 +0000

description:
Add driver for sun4i/sun7i 10/100 Fast Ethernet controller (EMAC).

diffstat:

 sys/arch/arm/sunxi/files.sunxi  |    9 +-
 sys/arch/arm/sunxi/sun4i_emac.c |  893 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 900 insertions(+), 2 deletions(-)

diffs (truncated from 920 to 300 lines):

diff -r fae49819a936 -r 30d71b0c2351 sys/arch/arm/sunxi/files.sunxi
--- a/sys/arch/arm/sunxi/files.sunxi    Fri Oct 20 21:51:29 2017 +0000
+++ b/sys/arch/arm/sunxi/files.sunxi    Fri Oct 20 22:29:15 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.sunxi,v 1.35 2017/10/11 10:52:54 jmcneill Exp $
+#      $NetBSD: files.sunxi,v 1.36 2017/10/20 22:29:15 jmcneill Exp $
 #
 # Configuration info for Allwinner sunxi family SoCs
 #
@@ -143,7 +143,12 @@
 attach sunxirtc at fdt with sunxi_rtc
 file   arch/arm/sunxi/sunxi_rtc.c              sunxi_rtc
 
-# EMAC
+# EMAC (sun4i/sun7i)
+device sun4iemac: arp, ether, ifnet, mii
+attach sun4iemac at fdt with sun4i_emac
+file   arch/arm/sunxi/sun4i_emac.c             sun4i_emac
+
+# EMAC (sun8i/sun50i)
 device sunxiemac: arp, ether, ifnet, mii
 attach sunxiemac at fdt with sunxi_emac
 file   arch/arm/sunxi/sunxi_emac.c             sunxi_emac
diff -r fae49819a936 -r 30d71b0c2351 sys/arch/arm/sunxi/sun4i_emac.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sun4i_emac.c   Fri Oct 20 22:29:15 2017 +0000
@@ -0,0 +1,893 @@
+/* $NetBSD: sun4i_emac.c,v 1.1 2017/10/20 22:29:15 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2013-2017 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry and Jared McNeill.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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: sun4i_emac.c,v 1.1 2017/10/20 22:29:15 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/ioctl.h>
+#include <sys/mutex.h>
+#include <sys/rndsource.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+#include <dev/mii/miivar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/sunxi/sunxi_sramc.h>
+
+#define        EMAC_IFNAME     "emac%d"
+
+#define        EMAC_CTL_REG            0x00
+#define         EMAC_CTL_RX_EN                 __BIT(2)
+#define         EMAC_CTL_TX_EN                 __BIT(1)
+#define         EMAC_CTL_RST                   __BIT(0)
+#define        EMAC_TX_MODE_REG        0x04
+#define         EMAC_TX_MODE_DMA               __BIT(1)
+#define         EMAC_TX_MODE_ABF_ENA           __BIT(0)
+#define        EMAC_TX_FLOW_REG        0x08
+#define        EMAC_TX_CTL0_REG        0x0c
+#define        EMAC_TX_CTL1_REG        0x10
+#define        EMAC_TX_CTL_REG(n)      (EMAC_TX_CTL0_REG+4*(n))
+#define         EMAC_TX_CTL_START              __BIT(0)
+#define        EMAC_TX_INS_REG         0x14
+#define        EMAC_TX_PL0_REG         0x18
+#define        EMAC_TX_PL1_REG         0x1c
+#define        EMAC_TX_PL_REG(n)       (EMAC_TX_PL0_REG+4*(n))
+#define        EMAC_TX_STA_REG         0x20
+#define        EMAC_TX_IO_DATA0_REG    0x24
+#define        EMAC_TX_IO_DATA1_REG    0x28
+#define        EMAC_TX_IO_DATA_REG(n)  (EMAC_TX_IO_DATA0_REG+4*(n))
+#define        EMAC_TX_TSVL0_REG       0x2c
+#define        EMAC_TX_TSVH0_REG       0x30
+#define        EMAC_TX_TSVL1_REG       0x34
+#define        EMAC_TX_TSVH1_REG       0x38
+#define        EMAC_RX_CTL_REG         0x3c
+#define         EMAC_RX_CTL_SA_IF              __BIT(25)
+#define         EMAC_RX_CTL_SA                 __BIT(24)
+#define         EMAC_RX_CTL_BC0                __BIT(22)
+#define         EMAC_RX_CTL_MHF                __BIT(21)
+#define         EMAC_RX_CTL_MC0                __BIT(20)
+#define         EMAC_RX_CTL_DAF                __BIT(17)
+#define         EMAC_RX_CTL_UCAD               __BIT(16)
+#define         EMAC_RX_CTL_POR                __BIT(8)
+#define         EMAC_RX_CTL_PLE                __BIT(7)
+#define         EMAC_RX_CTL_PCRCE              __BIT(6)
+#define         EMAC_RX_CTL_PCF                __BIT(5)
+#define         EMAC_RX_CTL_PROMISC            __BIT(4)
+#define         EMAC_RX_CTL_FIFO_RESET         __BIT(3)
+#define         EMAC_RX_CTL_DMA                __BIT(2)
+#define         EMAC_RX_CTL_DRQ_MODE           __BIT(1)
+#define         EMAC_RX_CTL_START              __BIT(0)
+#define        EMAC_RX_HASH0_REG       0x40
+#define        EMAC_RX_HASH1_REG       0x44
+#define        EMAC_RX_STA_REG         0x48
+#define         EMAC_RX_STA_PKTOK              __BIT(7)
+#define         EMAC_RX_STA_ALNERR             __BIT(6)
+#define         EMAC_RX_STA_LENERR             __BIT(5)
+#define         EMAC_RX_STA_CRCERR             __BIT(4)
+#define        EMAC_RX_IO_DATA_REG     0x4c
+#define        EMAC_RX_FBC_REG         0x50
+#define        EMAC_INT_CTL_REG        0x54
+#define        EMAC_INT_STA_REG        0x58
+#define         EMAC_INT_RX                    __BIT(8)
+#define         EMAC_INT_TX1                   __BIT(1)
+#define         EMAC_INT_TX0                   __BIT(0)
+#define         EMAC_INT_ENABLE                \
+               (EMAC_INT_RX|EMAC_INT_TX1|EMAC_INT_TX0)
+#define        EMAC_MAC_CTL0_REG       0x5c
+#define         EMAC_MAC_CTL0_SOFT_RESET       __BIT(15)
+#define         EMAC_MAC_CTL0_TFC              __BIT(3)
+#define         EMAC_MAC_CTL0_RFC              __BIT(2)
+#define        EMAC_MAC_CTL1_REG       0x60
+#define         EMAC_MAC_CTL1_ED               __BIT(15)
+#define         EMAC_MAC_CTL1_NB               __BIT(13)
+#define         EMAC_MAC_CTL1_BNB              __BIT(12)
+#define         EMAC_MAC_CTL1_LPE              __BIT(9)
+#define         EMAC_MAC_CTL1_PRE              __BIT(8)
+#define         EMAC_MAC_CTL1_ADP              __BIT(7)
+#define         EMAC_MAC_CTL1_VC               __BIT(6)
+#define         EMAC_MAC_CTL1_PC               __BIT(5)
+#define         EMAC_MAC_CTL1_CRC              __BIT(4)
+#define         EMAC_MAC_CTL1_DCRC             __BIT(3)
+#define         EMAC_MAC_CTL1_HF               __BIT(2)
+#define         EMAC_MAC_CTL1_FLC              __BIT(1)
+#define         EMAC_MAC_CTL1_FD               __BIT(0)
+#define        EMAC_MAC_IPGT_REG       0x64
+#define         EMAC_MAC_IPGT_FD               0x15
+#define        EMAC_MAC_IPGR_REG       0x68
+#define         EMAC_MAC_IPGR_IPG1             __BITS(15,8)
+#define         EMAC_MAC_IPGR_IPG2             __BITS(7,0)
+#define        EMAC_MAC_CLRT_REG       0x6c
+#define         EMAC_MAC_CLRT_CW               __BITS(15,8)
+#define         EMAC_MAC_CLRT_RM               __BITS(7,0)
+#define        EMAC_MAC_MAXF_REG       0x70
+#define        EMAC_MAC_SUPP_REG       0x74
+#define         EMAC_MAC_SUPP_100M             __BIT(8)
+#define        EMAC_MAC_TEST_REG       0x78
+#define        EMAC_MAC_MCFG_REG       0x7c
+#define         EMAC_MAC_MCFG_CLK              __BITS(5,2)
+#define        EMAC_MAC_MCMD_REG       0x80
+#define        EMAC_MAC_MADR_REG       0x84
+#define        EMAC_MAC_MWTD_REG       0x88
+#define        EMAC_MAC_MRDD_REG       0x8c
+#define        EMAC_MAC_MIND_REG       0x90
+#define        EMAC_MAC_SSRR_REG       0x94
+#define        EMAC_MAC_A0_REG         0x98
+#define        EMAC_MAC_A1_REG         0x9c
+#define        EMAC_MAC_A2_REG         0xa0
+
+#define        EMAC_RXHDR_STS                  __BITS(31,16)
+#define        EMAC_RXHDR_LEN                  __BITS(15,0)
+
+#define        EMAC_RX_MAGIC           0x0143414d      /* M A C \001 */
+
+#define        EMAC_TXBUF_SIZE         4096
+
+static int sun4i_emac_match(device_t, cfdata_t, void *);
+static void sun4i_emac_attach(device_t, device_t, void *);
+
+static int sun4i_emac_intr(void *);
+static void sun4i_emac_tick(void *);
+
+static int sun4i_emac_miibus_read_reg(device_t, int, int);
+static void sun4i_emac_miibus_write_reg(device_t, int, int, int);
+static void sun4i_emac_miibus_statchg(struct ifnet *);
+
+static void sun4i_emac_ifstart(struct ifnet *);
+static int sun4i_emac_ifioctl(struct ifnet *, u_long, void *);
+static int sun4i_emac_ifinit(struct ifnet *);
+static void sun4i_emac_ifstop(struct ifnet *, int);
+static void sun4i_emac_ifwatchdog(struct ifnet *);
+
+struct sun4i_emac_softc;
+static void sun4i_emac_rx_hash(struct sun4i_emac_softc *);
+
+struct sun4i_emac_softc {
+       device_t sc_dev;
+       int sc_phandle;
+       bus_space_tag_t sc_bst;
+       bus_space_handle_t sc_bsh;
+       bus_dma_tag_t sc_dmat;
+       struct ethercom sc_ec;
+       struct mii_data sc_mii;
+       krndsource_t sc_rnd_source;     /* random source */
+       kmutex_t sc_intr_lock;
+       uint8_t sc_tx_active;
+       callout_t sc_stat_ch;
+       void *sc_ih;
+       uint32_t sc_txbuf[EMAC_TXBUF_SIZE/4];
+};
+
+static const char * compatible[] = {
+       "allwinner,sun4i-a10-emac",
+       NULL
+};
+
+CFATTACH_DECL_NEW(sun4i_emac, sizeof(struct sun4i_emac_softc),
+       sun4i_emac_match, sun4i_emac_attach, NULL, NULL);
+
+static inline uint32_t
+sun4i_emac_read(struct sun4i_emac_softc *sc, bus_size_t o)
+{
+       return bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
+}
+
+static inline void
+sun4i_emac_write(struct sun4i_emac_softc *sc, bus_size_t o, uint32_t v)
+{
+       return bus_space_write_4(sc->sc_bst, sc->sc_bsh, o, v);
+}
+
+static inline void
+sun4i_emac_clear_set(struct sun4i_emac_softc *sc, bus_size_t o, uint32_t c,
+    uint32_t s)
+{
+       uint32_t v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
+       return bus_space_write_4(sc->sc_bst, sc->sc_bsh, o, (v & ~c) | s);
+}
+
+static int
+sun4i_emac_match(device_t parent, cfdata_t cf, void *aux)
+{
+       struct fdt_attach_args * const faa = aux;
+
+       return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sun4i_emac_attach(device_t parent, device_t self, void *aux)
+{
+       struct sun4i_emac_softc * const sc = device_private(self);
+       struct fdt_attach_args * const faa = aux;
+       struct ifnet * const ifp = &sc->sc_ec.ec_if;
+       struct mii_data * const mii = &sc->sc_mii;
+       const int phandle = faa->faa_phandle;
+       char enaddr[ETHER_ADDR_LEN];
+       const uint8_t *local_addr;
+       char intrstr[128];
+       struct clk *clk;
+       bus_addr_t addr;
+       bus_size_t size;
+       int len;
+
+       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+               aprint_error(": cannot get registers\n");
+               return;
+       }
+
+       if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+               aprint_error(": cannot decode interrupt\n");
+               return;
+       }
+
+       clk = fdtbus_clock_get_index(phandle, 0);
+       if (clk == NULL) {
+               aprint_error(": cannot acquire clock\n");
+               return;
+       }
+       if (clk_enable(clk) != 0) {
+               aprint_error(": cannot enable clock\n");
+               return;
+       }
+
+       if (sunxi_sramc_claim(phandle) != 0) {



Home | Main Index | Thread Index | Old Index