Add alternate descriptors support for if_dwc.

This also adds a newbus interface that allows a SoC to override the
following settings:

 - if_dwc specific SoC initialization;
 - if_dwc descriptor type;
 - if_dwc MII clock.

This seems to be an old version of the hardware descriptors but it is
still in use in a few SoCs (namely Allwinner A20 and Amlogic at least).

Tested on Cubieboard2 and Banana pi.

Tested for regressions on Altera Cyclone by br@ (old version).

Obtained from:	NetBSD
This commit is contained in:
Luiz Otavio O Souza 2015-09-20 14:13:29 +00:00
parent da9a326be3
commit 5df539274f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288023
6 changed files with 219 additions and 70 deletions

View File

@ -15,7 +15,6 @@ arm/altera/socfpga/socfpga_rstmgr.c standard
arm/altera/socfpga/socfpga_mp.c optional smp
arm/altera/socfpga/socfpga_gpio.c optional gpio
dev/dwc/if_dwc.c optional dwc
dev/mii/micphy.c optional micphy
dev/mmc/host/dwmmc.c optional dwmmc

View File

@ -32,5 +32,3 @@ arm/amlogic/aml8726/aml8726_pinctrl.c optional fdt_pinctrl
arm/amlogic/aml8726/uart_dev_aml8726.c optional uart
arm/amlogic/aml8726/aml8726_usb_phy-m3.c optional dwcotg usb gpio
arm/amlogic/aml8726/aml8726_usb_phy-m6.c optional dwcotg usb gpio
dev/dwc/if_dwc.c optional dwc

View File

@ -84,6 +84,8 @@ cddl/dev/dtrace/arm/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}"
cddl/dev/fbt/arm/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}"
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
dev/dwc/if_dwc.c optional dwc
dev/dwc/if_dwc_if.m optional dwc
dev/fb/fb.c optional sc
dev/fdt/fdt_arm_platform.c optional platform fdt
dev/hwpmc/hwpmc_arm.c optional hwpmc

View File

@ -63,11 +63,13 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <dev/dwc/if_dwc.h>
#include <dev/dwc/if_dwcvar.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include "if_dwc_if.h"
#include "miibus_if.h"
#define READ4(_sc, _reg) \
@ -78,7 +80,6 @@ __FBSDID("$FreeBSD$");
#define MAC_RESET_TIMEOUT 100
#define WATCHDOG_TIMEOUT_SECS 5
#define STATS_HARVEST_INTERVAL 2
#define MII_CLK_VAL 2
#define DWC_LOCK(sc) mtx_lock(&(sc)->mtx)
#define DWC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
@ -98,77 +99,34 @@ __FBSDID("$FreeBSD$");
#define DDESC_RDES0_FL_SHIFT 16 /* Frame Length */
#define DDESC_RDES1_CHAINED (1U << 14)
struct dwc_bufmap {
bus_dmamap_t map;
struct mbuf *mbuf;
};
/* Alt descriptor bits. */
#define DDESC_CNTL_TXINT (1U << 31)
#define DDESC_CNTL_TXLAST (1U << 30)
#define DDESC_CNTL_TXFIRST (1U << 29)
#define DDESC_CNTL_TXCRCDIS (1U << 26)
#define DDESC_CNTL_TXRINGEND (1U << 25)
#define DDESC_CNTL_TXCHAIN (1U << 24)
#define DDESC_CNTL_CHAINED (1U << 24)
/*
* A hardware buffer descriptor. Rx and Tx buffers have the same descriptor
* layout, but the bits in the flags field have different meanings.
* layout, but the bits in the fields have different meanings.
*/
struct dwc_hwdesc
{
uint32_t tdes0;
uint32_t tdes1;
uint32_t tdes0; /* status for alt layout */
uint32_t tdes1; /* cntl for alt layout */
uint32_t addr; /* pointer to buffer data */
uint32_t addr_next; /* link to next descriptor */
};
/*
* Driver data and defines.
*/
#define RX_DESC_COUNT 1024
#define RX_DESC_SIZE (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
#define TX_DESC_COUNT 1024
#define TX_DESC_SIZE (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
/*
* The hardware imposes alignment restrictions on various objects involved in
* DMA transfers. These values are expressed in bytes (not bits).
*/
#define DWC_DESC_RING_ALIGN 2048
struct dwc_softc {
struct resource *res[2];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
int mii_clk;
device_t miibus;
struct mii_data * mii_softc;
struct ifnet *ifp;
int if_flags;
struct mtx mtx;
void * intr_cookie;
struct callout dwc_callout;
boolean_t link_is_up;
boolean_t is_attached;
boolean_t is_detaching;
int tx_watchdog_count;
int stats_harvest_count;
/* RX */
bus_dma_tag_t rxdesc_tag;
bus_dmamap_t rxdesc_map;
struct dwc_hwdesc *rxdesc_ring;
bus_addr_t rxdesc_ring_paddr;
bus_dma_tag_t rxbuf_tag;
struct dwc_bufmap rxbuf_map[RX_DESC_COUNT];
uint32_t rx_idx;
/* TX */
bus_dma_tag_t txdesc_tag;
bus_dmamap_t txdesc_map;
struct dwc_hwdesc *txdesc_ring;
bus_addr_t txdesc_ring_paddr;
bus_dma_tag_t txbuf_tag;
struct dwc_bufmap txbuf_map[RX_DESC_COUNT];
uint32_t tx_idx_head;
uint32_t tx_idx_tail;
int txcount;
};
static struct resource_spec dwc_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
@ -217,14 +175,23 @@ dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
flags = 0;
--sc->txcount;
} else {
flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
| DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
if (sc->mactype == DWC_GMAC_ALT_DESC)
flags = DDESC_CNTL_TXCHAIN | DDESC_CNTL_TXFIRST
| DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT;
else
flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
| DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
++sc->txcount;
}
sc->txdesc_ring[idx].addr = (uint32_t)(paddr);
sc->txdesc_ring[idx].tdes0 = flags;
sc->txdesc_ring[idx].tdes1 = len;
if (sc->mactype == DWC_GMAC_ALT_DESC) {
sc->txdesc_ring[idx].tdes0 = 0;
sc->txdesc_ring[idx].tdes1 = flags | len;
} else {
sc->txdesc_ring[idx].tdes0 = flags;
sc->txdesc_ring[idx].tdes1 = len;
}
if (paddr && len) {
wmb();
@ -497,7 +464,10 @@ dwc_setup_rxdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr)
nidx = next_rxidx(sc, idx);
sc->rxdesc_ring[idx].addr_next = sc->rxdesc_ring_paddr + \
(nidx * sizeof(struct dwc_hwdesc));
sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
if (sc->mactype == DWC_GMAC_ALT_DESC)
sc->rxdesc_ring[idx].tdes1 = DDESC_CNTL_CHAINED | RX_MAX_PACKET;
else
sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
wmb();
sc->rxdesc_ring[idx].tdes0 = DDESC_RDES0_OWN;
@ -1065,10 +1035,13 @@ dwc_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
sc->mii_clk = MII_CLK_VAL;
sc->rx_idx = 0;
sc->txcount = TX_DESC_COUNT;
sc->mii_clk = IF_DWC_MII_CLK(dev);
sc->mactype = IF_DWC_MAC_TYPE(dev);
if (IF_DWC_INIT(dev) != 0)
return (ENXIO);
if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
@ -1100,8 +1073,11 @@ dwc_attach(device_t dev)
return (ENXIO);
}
reg = READ4(sc, BUS_MODE);
reg |= (BUS_MODE_EIGHTXPBL);
if (sc->mactype == DWC_GMAC_ALT_DESC) {
reg = BUS_MODE_FIXEDBURST;
reg |= (BUS_MODE_PRIORXTX_41 << BUS_MODE_PRIORXTX_SHIFT);
} else
reg = (BUS_MODE_EIGHTXPBL);
reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
WRITE4(sc, BUS_MODE, reg);
@ -1146,7 +1122,6 @@ dwc_attach(device_t dev)
IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
/* Attach the mii driver. */
error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
@ -1285,7 +1260,7 @@ static device_method_t dwc_methods[] = {
{ 0, 0 }
};
static driver_t dwc_driver = {
driver_t dwc_driver = {
"dwc",
dwc_methods,
sizeof(struct dwc_softc),

76
sys/dev/dwc/if_dwc_if.m Normal file
View File

@ -0,0 +1,76 @@
#-
# Copyright (c) 2015 Luiz Otavio O Souza <loos@FreeBSD.org>
# Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
# 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 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 AUTHOR 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.
#
# $FreeBSD$
#
INTERFACE if_dwc;
#include <dev/dwc/if_dwc.h>
CODE {
static int
if_dwc_default_init(device_t dev)
{
return (0);
}
static int
if_dwc_default_mac_type(device_t dev)
{
return (DWC_GMAC);
}
static int
if_dwc_default_mii_clk(device_t dev)
{
return (GMAC_MII_CLK_25_35M_DIV16);
}
};
HEADER {
};
#
# Initialize the SoC specific registers.
#
METHOD int init {
device_t dev;
} DEFAULT if_dwc_default_init;
#
# Return the DWC MAC type (descriptor type).
#
METHOD int mac_type {
device_t dev;
} DEFAULT if_dwc_default_mac_type;
#
# Return the DWC MII clock for a specific hardware.
#
METHOD int mii_clk {
device_t dev;
} DEFAULT if_dwc_default_mii_clk;

99
sys/dev/dwc/if_dwcvar.h Normal file
View File

@ -0,0 +1,99 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* 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 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 AUTHOR 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.
*
* $FreeBSD$
*/
/*
* Ethernet media access controller (EMAC)
* Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
*
* EMAC is an instance of the Synopsys DesignWare 3504-0
* Universal 10/100/1000 Ethernet MAC (DWC_gmac).
*/
#ifndef __IF_DWCVAR_H__
#define __IF_DWCVAR_H__
/*
* Driver data and defines.
*/
#define RX_MAX_PACKET 0x7ff
#define RX_DESC_COUNT 1024
#define RX_DESC_SIZE (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
#define TX_DESC_COUNT 1024
#define TX_DESC_SIZE (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
struct dwc_bufmap {
bus_dmamap_t map;
struct mbuf *mbuf;
};
struct dwc_softc {
struct resource *res[2];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
int mactype;
int mii_clk;
device_t miibus;
struct mii_data * mii_softc;
struct ifnet *ifp;
int if_flags;
struct mtx mtx;
void * intr_cookie;
struct callout dwc_callout;
boolean_t link_is_up;
boolean_t is_attached;
boolean_t is_detaching;
int tx_watchdog_count;
int stats_harvest_count;
/* RX */
bus_dma_tag_t rxdesc_tag;
bus_dmamap_t rxdesc_map;
struct dwc_hwdesc *rxdesc_ring;
bus_addr_t rxdesc_ring_paddr;
bus_dma_tag_t rxbuf_tag;
struct dwc_bufmap rxbuf_map[RX_DESC_COUNT];
uint32_t rx_idx;
/* TX */
bus_dma_tag_t txdesc_tag;
bus_dmamap_t txdesc_map;
struct dwc_hwdesc *txdesc_ring;
bus_addr_t txdesc_ring_paddr;
bus_dma_tag_t txbuf_tag;
struct dwc_bufmap txbuf_map[RX_DESC_COUNT];
uint32_t tx_idx_head;
uint32_t tx_idx_tail;
int txcount;
};
#endif /* __IF_DWCVAR_H__ */