Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sociox Socionext AVE GbE driver for UniPhier So...
details: https://anonhg.NetBSD.org/src/rev/413fc3f6e7ec
branches: trunk
changeset: 970302:413fc3f6e7ec
user: nisimura <nisimura%NetBSD.org@localhost>
date: Fri Mar 20 00:27:58 2020 +0000
description:
Socionext AVE GbE driver for UniPhier SoC family.
diffstat:
sys/arch/arm/sociox/if_ave.c | 1205 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1205 insertions(+), 0 deletions(-)
diffs (truncated from 1209 to 300 lines):
diff -r f07079066fa7 -r 413fc3f6e7ec sys/arch/arm/sociox/if_ave.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sociox/if_ave.c Fri Mar 20 00:27:58 2020 +0000
@@ -0,0 +1,1205 @@
+/* $NetBSD: if_ave.c,v 1.1 2020/03/20 00:27:58 nisimura Exp $ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Tohru Nishimura.
+ *
+ * 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.
+ */
+
+/*
+ * Socionext Uniphier AVE GbE driver
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_ave.c,v 1.1 2020/03/20 00:27:58 nisimura Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/intr.h>
+#include <sys/device.h>
+#include <sys/callout.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/rndsource.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_dl.h>
+#include <net/if_ether.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <net/bpf.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define FDT_INTR_FLAGS (0) /* !MP_SAFE */
+
+#define AVEID 0x000 /* hardware ID */
+#define AVEHWVER 0x004 /* hardware version */
+#define AVEGR 0x008 /* chip global control */
+#define GR_RXRST (1U<<5) /* RxFIFO reset */
+#define GR_PHYRST (1U<<4) /* external PHY reset */
+#define GR_GRST (1U<<0) /* full chip reset */
+#define AVECFG 0x00c /* hw configuration */
+#define CFG_FLE (1U<<31) /* filter function enable */
+#define CFG_CKE (1U<<30) /* checksum enable */
+#define CFG_MII (1U<<27) /* 1: MII/RMII, 0: RGMII */
+#define CFG_IPFCKE (1U<<24) /* IP framgment csum enable */
+#define AVEGIMR 0x100 /* global interrupt mask */
+#define AVEGISR 0x104 /* global interrupt status */
+#define GISR_PHY (1U<<24) /* PHY status change detected */
+#define GISR_TXCI (1U<<16) /* transmission completed */
+#define GISR_RXERR (1U<<8) /* Rx frame error detected */
+#define GISR_RXOVF (1U<<7) /* Rx oveflow detected */
+#define GISR_RXDROP (1U<<6) /* Rx has been dropped */
+#define GISR_RXIT (1U<<5) /* receive itimer notify */
+#define AVETXC 0x200 /* transmit control */
+#define TXC_FCE (1U<<18) /* enable Tx flow control */
+#define TXC_SPD1000 (1U<<17) /* use 1000Mbps */
+#define TXC_SPD100 (1U<<16) /* use 100Mbps */
+#define AVERXC 0x204 /* receive control */
+#define RXC_EN (1U<<30) /* enable receive circuit */
+#define RXC_USEFDX (1U<<22) /* use full-duplex */
+#define RXC_FCE (1U<<21) /* enable Rx flow control */
+#define RXC_AFE (1U<<19) /* use address filter (!promisc) */
+#define RXC_DRPEN (1U<<18) /* drop receiving PAUSE frames */
+/* RXC 15:0 max frame length to accept */
+#define AVEMACL 0x208 /* MAC address lower */
+#define AVEMACH 0x20c /* MAC address upper */
+#define AVEMDIOC 0x214 /* MDIO control */
+#define MDIOC_RD (1U<<3) /* read op */
+#define MDIOC_WR (1U<<2) /* write op */
+#define AVEMDADR 0x218 /* MDIO address -- 13:8 phy id */
+#define AVEMDWRD 0x21c /* MDIO write data - 15:0 */
+#define AVEMDIOS 0x220 /* MDIO status */
+#define MDIOS_BUSY (1U<<0) /* MDIO in progress */
+#define AVEMDRDD 0x224 /* MDIO read data */
+#define AVEDESCC 0x300 /* descriptor control */
+#define DESCC_RD0 (1U<<3) /* activate Rx0 descriptor to run */
+#define DESCC_RSTP (1U<<2) /* pause Rx descriptor */
+#define DESCC_TD (1U<<0) /* activate Tx descriptor to run */
+ /* 31:16 status report to read */
+#define AVETXDES 0x304 /* Tx descriptor control */
+ /* 27:16 Tx descriptor byte count
+ * 11:0 start address offset */
+#define AVERXDES0 0x308 /* Rx0 descriptor control */
+ /* 30:16 Rx descriptor byte count
+ * 14:0 start address offset */
+#define AVEITIRQC 0x34c /* interval IRQ control */
+#define ITIRQC_R0E (1U<<27) /* enable Rx0 interval timer */
+#define INTMVAL (20<<16) /* INTM value */
+ /* 15:0 interval timer count */
+
+#define AVEAFB 0x0800 /* address filter base */
+#define AVEAFMSKB 0x0d00 /* byte mask base */
+#define MSKBYTE0 0xfffffff3f /* zeros in 7:6 */
+#define MSKBYTE1 0x003ffffff /* ones in 25:0 */
+#define genmask0(x) (MSKBYTE0 & (~0U << (32-(x))))
+#define AVEAFMSKV 0x0e00 /* bit mask base */
+#define AVEAFRING 0x0f00 /* entry ring number selector */
+#define AVEAFEN 0x0ffc /* entry enable bit vector */
+
+#ifdef _LP64
+#define AVETDB 0x1000 /* 64bit Tx descriptor storage base */
+#define AVERDB 0x1c00 /* 64bit Rx descriptor storage base */
+#else
+#define AVETDB 0x1000 /* 32bit Tx descriptor storage base */
+#define AVERDB 0x1800 /* 32bit Rx descriptor storage base */
+#endif
+
+/*
+ * descriptor size is 12 bytes when _LP64, 8 bytes otherwise.
+ * 3KB/24KB split or 64bit paddr Tx/Rx descriptor storage.
+ * 2KB/16KB split or 32bit paddr Tx/Rx descriptor storage.
+ */
+struct tdes {
+ uint32_t t0, t1;
+#ifdef _LP64
+ uint32_t t2;
+#endif
+};
+
+struct rdes {
+ uint32_t r0, r1;
+#ifdef _LP64
+ uint32_t r2;
+#endif
+};
+
+#define T0_OWN (1U<<31) /* desc is ready to Tx */
+#define T0_IOC (1U<<29) /* post interrupt on Tx completes */
+#define T0_NOCSUM (1U<<28) /* inhibit checksum operation */
+#define T0_DONEOK (1U<<27) /* status - Tx completed ok */
+#define T0_FS (1U<<26) /* first segment of frame */
+#define T0_LS (1U<<25) /* last segment of frame */
+#define T0_OWC (1U<<21) /* status - out of win. late coll. */
+#define T0_ECOL (1U<<20) /* status - excess collision */
+#define T0_TBS_MASK 0xffff /* T0 segment length 15:0 */
+/* T1 segment address 31:0 */
+/* T2 segment address 63:32 */
+#define R0_OWN (1U<<31) /* desc is empty */
+#define R0_CSUM (1U<<21) /* receive checksum done */
+#define R0_CERR (1U<<20) /* csum found negative */
+#define R0_FL_MASK 0x07ff /* R0 frame length 10:0 */
+/* R1 frame address 31:0 */
+/* R2 frame address 63:32 */
+
+#define AVE_NTXSEGS 16
+#define AVE_TXQUEUELEN 8
+#define AVE_TXQUEUELEN_MASK (AVE_TXQUEUELEN - 1)
+#define AVE_TXQUEUE_GC (AVE_TXQUEUELEN / 4)
+#define AVE_NTXDESC (AVE_TXQUEUELEN * AVE_NTXSEGS)
+#define AVE_NTXDESC_MASK (AVE_NTXDESC - 1)
+#define AVE_NEXTTX(x) (((x) + 1) & AVE_NTXDESC_MASK)
+#define AVE_NEXTTXS(x) (((x) + 1) & AVE_TXQUEUELEN_MASK)
+
+#define AVE_NRXDESC 256
+#define AVE_NRXDESC_MASK (AVE_NRXDESC - 1)
+#define AVE_NEXTRX(x) (((x) + 1) & AVE_NRXDESC_MASK)
+
+#ifdef _LP64
+#define AVE_INIT_RXDESC(sc, x) \
+do { \
+ struct ave_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \
+ struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \
+ struct mbuf *__m = __rxs->rxs_mbuf; \
+ bus_addr_t __paddr =__rxs->rxs_dmamap->dm_segs[0].ds_addr; \
+ __m->m_data = __m->m_ext.ext_buf; \
+ __rxd->r2 = htole32(BUS_ADDR_HI32(__paddr)); \
+ __rxd->r1 = htole32(BUS_ADDR_LO32(__paddr)); \
+ __rxd->r0 = R0_OWN | R0_FL_MASK; \
+} while (/*CONSTCOND*/0)
+#else
+#define AVE_INIT_RXDESC(sc, x) \
+do { \
+ struct ave_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \
+ struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \
+ struct mbuf *__m = __rxs->rxs_mbuf; \
+ bus_addr_t __paddr =__rxs->rxs_dmamap->dm_segs[0].ds_addr; \
+ __m->m_data = __m->m_ext.ext_buf; \
+ __rxd->r1 = htole32(__paddr); \
+ __rxd->r0 = R0_OWN | R0_FL_MASK; \
+} while (/*CONSTCOND*/0)
+#endif
+
+struct ave_txsoft {
+ struct mbuf *txs_mbuf; /* head of our mbuf chain */
+ bus_dmamap_t txs_dmamap; /* our DMA map */
+ int txs_firstdesc; /* first descriptor in packet */
+ int txs_lastdesc; /* last descriptor in packet */
+ int txs_ndesc; /* # of descriptors used */
+};
+
+struct ave_rxsoft {
+ struct mbuf *rxs_mbuf; /* head of our mbuf chain */
+ bus_dmamap_t rxs_dmamap; /* our DMA map */
+};
+
+struct ave_softc {
+ device_t sc_dev; /* generic device information */
+ bus_space_tag_t sc_st; /* bus space tag */
+ bus_space_handle_t sc_sh; /* bus space handle */
+ bus_size_t sc_mapsize; /* csr map size */
+ bus_dma_tag_t sc_dmat; /* bus DMA tag */
+ struct ethercom sc_ethercom; /* Ethernet common data */
+ struct mii_data sc_mii; /* MII */
+ callout_t sc_tick_ch; /* PHY monitor callout */
+ int sc_flowflags; /* 802.3x PAUSE flow control */
+ void *sc_ih; /* interrupt cookie */
+ int sc_phy_id; /* PHY address */
+ uint32_t sc_phymode; /* 1<<27: MII/RMII, 0: RGMII */
+ uint32_t sc_rxc; /* software copy of AVERXC */
+
+ bus_dmamap_t sc_cddmamap; /* control data DMA map */
+#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
+
+ struct tdes *sc_txdescs; /* PTR to tdes [NTXDESC] array */
+ struct rdes *sc_rxdescs; /* PTR to rdes [NRXDESC] array */
+
+ struct ave_txsoft sc_txsoft[AVE_TXQUEUELEN];
+ struct ave_rxsoft sc_rxsoft[AVE_NRXDESC];
+ int sc_txfree; /* number of free Tx descriptors */
+ int sc_txnext; /* next ready Tx descriptor */
+ int sc_txsfree; /* number of free Tx jobs */
+ int sc_txsnext; /* next ready Tx job */
+ int sc_txsdirty; /* dirty Tx jobs */
+ int sc_rxptr; /* next ready Rx descriptor/descsoft */
+ uint32_t sc_t0csum; /* t0 field checksum designation */
+
+ krndsource_t rnd_source; /* random source */
+};
+
+static int ave_fdt_match(device_t, cfdata_t, void *);
+static void ave_fdt_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(ave_fdt, sizeof(struct ave_softc),
+ ave_fdt_match, ave_fdt_attach, NULL, NULL);
+
+static void ave_reset(struct ave_softc *);
+static int ave_init(struct ifnet *);
+static void ave_start(struct ifnet *);
+static void ave_stop(struct ifnet *, int);
+static void ave_watchdog(struct ifnet *);
+static int ave_ioctl(struct ifnet *, u_long, void *);
+static void ave_set_rcvfilt(struct ave_softc *);
+static void ave_write_filt(struct ave_softc *, int, const uint8_t *);
+static int ave_ifmedia_upd(struct ifnet *);
+static void ave_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static void mii_statchg(struct ifnet *);
+static void lnkchg(struct ave_softc *);
+static void phy_tick(void *);
+static int mii_readreg(device_t, int, int, uint16_t *);
+static int mii_writereg(device_t, int, int, uint16_t);
+static int ave_intr(void *);
+static void txreap(struct ave_softc *);
+static void rxintr(struct ave_softc *);
+static int add_rxbuf(struct ave_softc *, int);
+
+#define CSR_READ(sc, off) \
+ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off))
+#define CSR_WRITE(sc, off, val) \
+ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val))
+
+static int
+ave_fdt_match(device_t parent, cfdata_t cf, void *aux)
+{
+ static const char * compatible[] = {
+#ifdef _LP64
+ "socionext,unifier-ld20-ave4",
+#else
+ "socionext,unifier-pro4-ave4",
Home |
Main Index |
Thread Index |
Old Index