Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add driver for Allwinner Gigabit Ethernet (EMAC) as...
details: https://anonhg.NetBSD.org/src/rev/60f53e818aab
branches: trunk
changeset: 354847:60f53e818aab
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Jul 01 16:25:15 2017 +0000
description:
Add driver for Allwinner Gigabit Ethernet (EMAC) as found in sun8i and
later family SoCs.
This is a port of my FreeBSD driver which has been confirmed to work on
Allwinner H3, A83T, and A64 SoCs.
diffstat:
sys/arch/arm/sunxi/files.sunxi | 7 +-
sys/arch/arm/sunxi/sun8i_h3_ccu.c | 6 +-
sys/arch/arm/sunxi/sunxi_emac.c | 1435 +++++++++++++++++++++++++++++++++++++
sys/arch/arm/sunxi/sunxi_emac.h | 184 ++++
sys/arch/evbarm/conf/SUNXI | 7 +-
5 files changed, 1633 insertions(+), 6 deletions(-)
diffs (truncated from 1697 to 300 lines):
diff -r 999bc0101329 -r 60f53e818aab sys/arch/arm/sunxi/files.sunxi
--- a/sys/arch/arm/sunxi/files.sunxi Sat Jul 01 15:54:08 2017 +0000
+++ b/sys/arch/arm/sunxi/files.sunxi Sat Jul 01 16:25:15 2017 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.sunxi,v 1.5 2017/06/29 19:38:24 jmcneill Exp $
+# $NetBSD: files.sunxi,v 1.6 2017/07/01 16:25:16 jmcneill Exp $
#
# Configuration info for Allwinner sunxi family SoCs
#
@@ -62,6 +62,11 @@
attach sunxirtc at fdt with sunxi_rtc
file arch/arm/sunxi/sunxi_rtc.c sunxi_rtc
+# EMAC
+device sunxiemac: arp, ether, ifnet, mii
+attach sunxiemac at fdt with sunxi_emac
+file arch/arm/sunxi/sunxi_emac.c sunxi_emac
+
# SOC parameters
defflag opt_soc.h SOC_SUNXI
defflag opt_soc.h SOC_SUN8I: SOC_SUNXI
diff -r 999bc0101329 -r 60f53e818aab sys/arch/arm/sunxi/sun8i_h3_ccu.c
--- a/sys/arch/arm/sunxi/sun8i_h3_ccu.c Sat Jul 01 15:54:08 2017 +0000
+++ b/sys/arch/arm/sunxi/sun8i_h3_ccu.c Sat Jul 01 16:25:15 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sun8i_h3_ccu.c,v 1.4 2017/06/29 17:08:52 jmcneill Exp $ */
+/* $NetBSD: sun8i_h3_ccu.c,v 1.5 2017/07/01 16:25:16 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.4 2017/06/29 17:08:52 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.5 2017/07/01 16:25:16 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -185,6 +185,8 @@
BUS_CLK_GATING_REG0, 9),
SUNXI_CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1",
BUS_CLK_GATING_REG0, 10),
+ SUNXI_CCU_GATE(H3_CLK_BUS_EMAC, "bus-emac", "ahb2",
+ BUS_CLK_GATING_REG0, 17),
SUNXI_CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1",
BUS_CLK_GATING_REG0, 23),
SUNXI_CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1",
diff -r 999bc0101329 -r 60f53e818aab sys/arch/arm/sunxi/sunxi_emac.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sunxi_emac.c Sat Jul 01 16:25:15 2017 +0000
@@ -0,0 +1,1435 @@
+/* $NetBSD: sunxi_emac.c,v 1.1 2017/07/01 16:25:16 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2016-2017 Jared McNeill <jmcneill%invisible.ca@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 ``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 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.
+ */
+
+/*
+ * Allwinner Gigabit Ethernet MAC (EMAC) controller
+ */
+
+#include "opt_net_mpsafe.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.1 2017/07/01 16:25:16 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mutex.h>
+#include <sys/callout.h>
+#include <sys/gpio.h>
+#include <sys/cprng.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#include <net/bpf.h>
+
+#include <dev/mii/miivar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/sunxi/sunxi_emac.h>
+
+#ifdef NET_MPSAFE
+#define EMAC_MPSAFE 1
+#define CALLOUT_FLAGS CALLOUT_MPSAFE
+#define FDT_INTR_FLAGS FDT_INTR_MPSAFE
+#else
+#define CALLOUT_FLAGS 0
+#define FDT_INTR_FLAGS 0
+#endif
+
+#define EMAC_IFNAME "emac%d"
+
+#define ETHER_ALIGN 2
+
+#define EMAC_LOCK(sc) mutex_enter(&(sc)->mtx)
+#define EMAC_UNLOCK(sc) mutex_exit(&(sc)->mtx)
+#define EMAC_ASSERT_LOCKED(sc) KASSERT(mutex_owned(&(sc)->mtx))
+
+#define DESC_ALIGN 8
+#define TX_DESC_COUNT 1024
+#define TX_DESC_SIZE (sizeof(struct sunxi_emac_desc) * TX_DESC_COUNT)
+#define RX_DESC_COUNT 256
+#define RX_DESC_SIZE (sizeof(struct sunxi_emac_desc) * RX_DESC_COUNT)
+
+#define DESC_OFF(n) ((n) * sizeof(struct sunxi_emac_desc))
+#define TX_NEXT(n) (((n) + 1) & (TX_DESC_COUNT - 1))
+#define TX_SKIP(n, o) (((n) + (o)) & (TX_DESC_COUNT - 1))
+#define RX_NEXT(n) (((n) + 1) & (RX_DESC_COUNT - 1))
+
+#define TX_MAX_SEGS 128
+
+#define SOFT_RST_RETRY 1000
+#define MII_BUSY_RETRY 1000
+#define MDIO_FREQ 2500000
+
+#define BURST_LEN_DEFAULT 8
+#define RX_TX_PRI_DEFAULT 0
+#define PAUSE_TIME_DEFAULT 0x400
+#define TX_INTERVAL_DEFAULT 64
+#define RX_BATCH_DEFAULT 64
+
+/* syscon EMAC clock register */
+#define EMAC_CLK_EPHY_ADDR (0x1f << 20) /* H3 */
+#define EMAC_CLK_EPHY_ADDR_SHIFT 20
+#define EMAC_CLK_EPHY_LED_POL (1 << 17) /* H3 */
+#define EMAC_CLK_EPHY_SHUTDOWN (1 << 16) /* H3 */
+#define EMAC_CLK_EPHY_SELECT (1 << 15) /* H3 */
+#define EMAC_CLK_RMII_EN (1 << 13)
+#define EMAC_CLK_ETXDC (0x7 << 10)
+#define EMAC_CLK_ETXDC_SHIFT 10
+#define EMAC_CLK_ERXDC (0x1f << 5)
+#define EMAC_CLK_ERXDC_SHIFT 5
+#define EMAC_CLK_PIT (0x1 << 2)
+#define EMAC_CLK_PIT_MII (0 << 2)
+#define EMAC_CLK_PIT_RGMII (1 << 2)
+#define EMAC_CLK_SRC (0x3 << 0)
+#define EMAC_CLK_SRC_MII (0 << 0)
+#define EMAC_CLK_SRC_EXT_RGMII (1 << 0)
+#define EMAC_CLK_SRC_RGMII (2 << 0)
+
+/* Burst length of RX and TX DMA transfers */
+static int sunxi_emac_burst_len = BURST_LEN_DEFAULT;
+
+/* RX / TX DMA priority. If 1, RX DMA has priority over TX DMA. */
+static int sunxi_emac_rx_tx_pri = RX_TX_PRI_DEFAULT;
+
+/* Pause time field in the transmitted control frame */
+static int sunxi_emac_pause_time = PAUSE_TIME_DEFAULT;
+
+/* Request a TX interrupt every <n> descriptors */
+static int sunxi_emac_tx_interval = TX_INTERVAL_DEFAULT;
+
+/* Maximum number of mbufs to send to if_input */
+static int sunxi_emac_rx_batch = RX_BATCH_DEFAULT;
+
+enum sunxi_emac_type {
+ EMAC_A83T = 1,
+ EMAC_H3,
+};
+
+static const struct of_compat_data compat_data[] = {
+ { "allwinner,sun8i-a83t-emac", EMAC_A83T },
+ { "allwinner,sun8i-h3-emac", EMAC_H3 },
+ { NULL }
+};
+
+struct sunxi_emac_bufmap {
+ bus_dmamap_t map;
+ struct mbuf *mbuf;
+};
+
+struct sunxi_emac_txring {
+ bus_dma_tag_t desc_tag;
+ bus_dmamap_t desc_map;
+ bus_dma_segment_t desc_dmaseg;
+ struct sunxi_emac_desc *desc_ring;
+ bus_addr_t desc_ring_paddr;
+ bus_dma_tag_t buf_tag;
+ struct sunxi_emac_bufmap buf_map[TX_DESC_COUNT];
+ u_int cur, next, queued;
+};
+
+struct sunxi_emac_rxring {
+ bus_dma_tag_t desc_tag;
+ bus_dmamap_t desc_map;
+ bus_dma_segment_t desc_dmaseg;
+ struct sunxi_emac_desc *desc_ring;
+ bus_addr_t desc_ring_paddr;
+ bus_dma_tag_t buf_tag;
+ struct sunxi_emac_bufmap buf_map[RX_DESC_COUNT];
+ u_int cur;
+};
+
+enum {
+ _RES_EMAC,
+ _RES_SYSCON,
+ _RES_NITEMS
+};
+
+struct sunxi_emac_softc {
+ device_t dev;
+ int phandle;
+ enum sunxi_emac_type type;
+ bus_space_tag_t bst;
+ bus_dma_tag_t dmat;
+
+ bus_space_handle_t bsh[_RES_NITEMS];
+ struct clk *clk_ahb;
+ struct clk *clk_ephy;
+ struct fdtbus_reset *rst_ahb;
+ struct fdtbus_reset *rst_ephy;
+ struct fdtbus_regulator *reg_phy;
+ struct fdtbus_gpio_pin *pin_reset;
+
+ kmutex_t mtx;
+ struct ethercom ec;
+ struct mii_data mii;
+ callout_t stat_ch;
+ void *ih;
+ u_int mdc_div_ratio_m;
+
+ struct sunxi_emac_txring tx;
+ struct sunxi_emac_rxring rx;
+};
+
+#define RD4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh[_RES_EMAC], (reg))
+#define WR4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh[_RES_EMAC], (reg), (val))
+
+#define SYSCONRD4(sc, reg) \
+ bus_space_read_4((sc)->bst, (sc)->bsh[_RES_SYSCON], (reg))
+#define SYSCONWR4(sc, reg, val) \
+ bus_space_write_4((sc)->bst, (sc)->bsh[_RES_SYSCON], (reg), (val))
+
+static int
+sunxi_emac_mii_readreg(device_t dev, int phy, int reg)
+{
+ struct sunxi_emac_softc *sc = device_private(dev);
+ int retry, val;
+
+ val = 0;
+
+ WR4(sc, EMAC_MII_CMD,
+ (sc->mdc_div_ratio_m << MDC_DIV_RATIO_M_SHIFT) |
+ (phy << PHY_ADDR_SHIFT) |
+ (reg << PHY_REG_ADDR_SHIFT) |
+ MII_BUSY);
+ for (retry = MII_BUSY_RETRY; retry > 0; retry--) {
+ if ((RD4(sc, EMAC_MII_CMD) & MII_BUSY) == 0) {
+ val = RD4(sc, EMAC_MII_DATA);
+ break;
+ }
+ delay(10);
+ }
+
+ if (retry == 0)
+ device_printf(dev, "phy read timeout, phy=%d reg=%d\n",
+ phy, reg);
+
+ return val;
+}
+
+static void
+sunxi_emac_mii_writereg(device_t dev, int phy, int reg, int val)
+{
+ struct sunxi_emac_softc *sc = device_private(dev);
+ int retry;
+
Home |
Main Index |
Thread Index |
Old Index