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/e35e77a07c35
branches: trunk
changeset: 356915:e35e77a07c35
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 e6a6b9d60c6b -r e35e77a07c35 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 e6a6b9d60c6b -r e35e77a07c35 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