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/19ff039b4f92
branches:  trunk
changeset: 746017:19ff039b4f92
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 d0bf9aa6070b -r 19ff039b4f92 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