Home | History | Annotate | Line # | Download | only in dev
octeon_asx.c revision 1.1
      1 /*	$NetBSD: octeon_asx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2007 Internet Initiative Japan, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: octeon_asx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
     31 
     32 #include "opt_octeon.h"
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/malloc.h>
     37 #include <mips/cavium/octeonvar.h>
     38 #include <mips/cavium/dev/octeon_asxreg.h>
     39 #include <mips/cavium/dev/octeon_asxvar.h>
     40 
     41 #ifdef OCTEON_ETH_DEBUG
     42 void			octeon_asx_intr_evcnt_attach(struct octeon_asx_softc *);
     43 void			octeon_asx_intr_rml(void *);
     44 #endif
     45 
     46 #ifdef OCTEON_ETH_DEBUG
     47 struct octeon_asx_softc *__octeon_asx_softc;
     48 #endif
     49 
     50 /* XXX */
     51 void
     52 octeon_asx_init(struct octeon_asx_attach_args *aa,
     53     struct octeon_asx_softc **rsc)
     54 {
     55 	struct octeon_asx_softc *sc;
     56 	int status;
     57 
     58 	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
     59 	if (sc == NULL)
     60 		panic("can't allocate memory: %s", __func__);
     61 
     62 	sc->sc_port = aa->aa_port;
     63 	sc->sc_regt = aa->aa_regt;
     64 
     65 	status = bus_space_map(sc->sc_regt, ASX0_BASE, ASX0_SIZE, 0,
     66 	    &sc->sc_regh);
     67 	if (status != 0)
     68 		panic("can't map %s space", "asx register");
     69 
     70 	*rsc = sc;
     71 
     72 #ifdef OCTEON_ETH_DEBUG
     73 	octeon_asx_intr_evcnt_attach(sc);
     74 	if (__octeon_asx_softc == NULL)
     75 		__octeon_asx_softc = sc;
     76 #endif
     77 }
     78 
     79 #define	_ASX_RD8(sc, off) \
     80 	bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
     81 #define	_ASX_WR8(sc, off, v) \
     82 	bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
     83 
     84 static int	octeon_asx_enable_tx(struct octeon_asx_softc *, int);
     85 static int	octeon_asx_enable_rx(struct octeon_asx_softc *, int);
     86 #ifdef OCTEON_ETH_DEBUG
     87 static int	octeon_asx_enable_intr(struct octeon_asx_softc *, int);
     88 #endif
     89 
     90 int
     91 octeon_asx_enable(struct octeon_asx_softc *sc, int enable)
     92 {
     93 
     94 #ifdef OCTEON_ETH_DEBUG
     95 	octeon_asx_enable_intr(sc, enable);
     96 #endif
     97 	octeon_asx_enable_tx(sc, enable);
     98 	octeon_asx_enable_rx(sc, enable);
     99 	return 0;
    100 }
    101 
    102 static int
    103 octeon_asx_enable_tx(struct octeon_asx_softc *sc, int enable)
    104 {
    105 	uint64_t asx_tx_port;
    106 
    107 	asx_tx_port = _ASX_RD8(sc, ASX0_TX_PRT_EN_OFFSET);
    108 	if (enable)
    109 		SET(asx_tx_port, 1 << sc->sc_port);
    110 	else
    111 		CLR(asx_tx_port, 1 << sc->sc_port);
    112 	_ASX_WR8(sc, ASX0_TX_PRT_EN_OFFSET, asx_tx_port);
    113 	return 0;
    114 }
    115 
    116 static int
    117 octeon_asx_enable_rx(struct octeon_asx_softc *sc, int enable)
    118 {
    119 	uint64_t asx_rx_port;
    120 
    121 	asx_rx_port = _ASX_RD8(sc, ASX0_RX_PRT_EN_OFFSET);
    122 	if (enable)
    123 		SET(asx_rx_port, 1 << sc->sc_port);
    124 	else
    125 		CLR(asx_rx_port, 1 << sc->sc_port);
    126 	_ASX_WR8(sc, ASX0_RX_PRT_EN_OFFSET, asx_rx_port);
    127 	return 0;
    128 }
    129 
    130 #if defined(OCTEON_ETH_DEBUG)
    131 int			octeon_asx_intr_rml_verbose;
    132 
    133 static const struct octeon_evcnt_entry octeon_asx_intr_evcnt_entries[] = {
    134 #define	_ENTRY(name, type, parent, descr) \
    135 	OCTEON_EVCNT_ENTRY(struct octeon_asx_softc, name, type, parent, descr)
    136 	_ENTRY(asxrxpsh,	MISC, NULL, "asx tx fifo overflow"),
    137 	_ENTRY(asxtxpop,	MISC, NULL, "asx tx fifo underflow"),
    138 	_ENTRY(asxovrflw,	MISC, NULL, "asx rx fifo overflow"),
    139 #undef	_ENTRY
    140 };
    141 
    142 void
    143 octeon_asx_intr_evcnt_attach(struct octeon_asx_softc *sc)
    144 {
    145 	OCTEON_EVCNT_ATTACH_EVCNTS(sc, octeon_asx_intr_evcnt_entries, "asx0");
    146 }
    147 
    148 void
    149 octeon_asx_intr_rml(void *arg)
    150 {
    151 	struct octeon_asx_softc *sc = __octeon_asx_softc;
    152 	uint64_t reg = 0;
    153 
    154 	reg = octeon_asx_int_summary(sc);
    155 	if (octeon_asx_intr_rml_verbose)
    156 		printf("%s: ASX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
    157 	if (reg & ASX0_INT_REG_TXPSH)
    158 		OCTEON_EVCNT_INC(sc, asxrxpsh);
    159 	if (reg & ASX0_INT_REG_TXPOP)
    160 		OCTEON_EVCNT_INC(sc, asxtxpop);
    161 	if (reg & ASX0_INT_REG_OVRFLW)
    162 		OCTEON_EVCNT_INC(sc, asxovrflw);
    163 }
    164 
    165 static int
    166 octeon_asx_enable_intr(struct octeon_asx_softc *sc, int enable)
    167 {
    168 	uint64_t asx_int_xxx = 0;
    169 
    170 	SET(asx_int_xxx,
    171 	    ASX0_INT_REG_TXPSH |
    172 	    ASX0_INT_REG_TXPOP |
    173 	    ASX0_INT_REG_OVRFLW);
    174 	_ASX_WR8(sc, ASX0_INT_REG_OFFSET, asx_int_xxx);
    175 	_ASX_WR8(sc, ASX0_INT_EN_OFFSET, enable ? asx_int_xxx : 0);
    176 	return 0;
    177 }
    178 #endif
    179 
    180 int
    181 octeon_asx_clk_set(struct octeon_asx_softc *sc, int tx_setting, int rx_setting)
    182 {
    183 	_ASX_WR8(sc, ASX0_TX_CLK_SET0_OFFSET + 8 * sc->sc_port, tx_setting);
    184 	_ASX_WR8(sc, ASX0_RX_CLK_SET0_OFFSET + 8 * sc->sc_port, rx_setting);
    185 	return 0;
    186 }
    187 
    188 #ifdef OCTEON_ETH_DEBUG
    189 uint64_t
    190 octeon_asx_int_summary(struct octeon_asx_softc *sc)
    191 {
    192 	uint64_t summary;
    193 
    194 	summary = _ASX_RD8(sc, ASX0_INT_REG_OFFSET);
    195 	_ASX_WR8(sc, ASX0_INT_REG_OFFSET, summary);
    196 	return summary;
    197 }
    198 
    199 #define	_ENTRY(x)	{ #x, x##_BITS, x##_OFFSET }
    200 
    201 struct octeon_asx_dump_reg_ {
    202 	const char *name;
    203 	const char *format;
    204 	size_t	offset;
    205 };
    206 
    207 void		octeon_asx_dump(void);
    208 
    209 static const struct octeon_asx_dump_reg_ octeon_asx_dump_regs_[] = {
    210 	_ENTRY(ASX0_RX_PRT_EN),
    211 	_ENTRY(ASX0_TX_PRT_EN),
    212 	_ENTRY(ASX0_INT_REG),
    213 	_ENTRY(ASX0_INT_EN),
    214 	_ENTRY(ASX0_RX_CLK_SET0),
    215 	_ENTRY(ASX0_RX_CLK_SET1),
    216 	_ENTRY(ASX0_RX_CLK_SET2),
    217 	_ENTRY(ASX0_PRT_LOOP),
    218 	_ENTRY(ASX0_TX_CLK_SET0),
    219 	_ENTRY(ASX0_TX_CLK_SET1),
    220 	_ENTRY(ASX0_TX_CLK_SET2),
    221 	_ENTRY(ASX0_COMP_BYP),
    222 	_ENTRY(ASX0_TX_HI_WATER000),
    223 	_ENTRY(ASX0_TX_HI_WATER001),
    224 	_ENTRY(ASX0_TX_HI_WATER002),
    225 	_ENTRY(ASX0_GMII_RX_CLK_SET),
    226 	_ENTRY(ASX0_GMII_RX_DAT_SET),
    227 	_ENTRY(ASX0_MII_RX_DAT_SET),
    228 };
    229 
    230 void
    231 octeon_asx_dump(void)
    232 {
    233 	struct octeon_asx_softc *sc = __octeon_asx_softc;
    234 	const struct octeon_asx_dump_reg_ *reg;
    235 	uint64_t tmp;
    236 	char buf[512];
    237 	int i;
    238 
    239 	for (i = 0; i < (int)__arraycount(octeon_asx_dump_regs_); i++) {
    240 		reg = &octeon_asx_dump_regs_[i];
    241 		tmp = _ASX_RD8(sc, reg->offset);
    242 		if (reg->format == NULL)
    243 			snprintf(buf, sizeof(buf), "%016" PRIx64, tmp);
    244 		else
    245 			snprintb(buf, sizeof(buf), reg->format, tmp);
    246 		printf("\t%-24s: %s\n", reg->name, buf);
    247 	}
    248 }
    249 #endif
    250