Home | History | Annotate | Line # | Download | only in rmi
      1  1.10    skrll /*	$NetBSD: rmixl_obio.c,v 1.10 2022/09/29 07:00:47 skrll Exp $	*/
      2   1.2     matt 
      3   1.2     matt /*
      4   1.2     matt  * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
      5   1.2     matt  * All rights reserved.
      6   1.2     matt  *
      7   1.2     matt  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8   1.2     matt  *
      9   1.2     matt  * Redistribution and use in source and binary forms, with or without
     10   1.2     matt  * modification, are permitted provided that the following conditions
     11   1.2     matt  * are met:
     12   1.2     matt  * 1. Redistributions of source code must retain the above copyright
     13   1.2     matt  *    notice, this list of conditions and the following disclaimer.
     14   1.2     matt  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.2     matt  *    notice, this list of conditions and the following disclaimer in the
     16   1.2     matt  *    documentation and/or other materials provided with the distribution.
     17   1.2     matt  * 3. All advertising materials mentioning features or use of this software
     18   1.2     matt  *    must display the following acknowledgement:
     19   1.2     matt  *	This product includes software developed for the NetBSD Project by
     20   1.2     matt  *	Wasabi Systems, Inc.
     21   1.2     matt  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22   1.2     matt  *    or promote products derived from this software without specific prior
     23   1.2     matt  *    written permission.
     24   1.2     matt  *
     25   1.2     matt  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26   1.2     matt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27   1.2     matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28   1.2     matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29   1.2     matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30   1.2     matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31   1.2     matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32   1.2     matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33   1.2     matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34   1.2     matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35   1.2     matt  * POSSIBILITY OF SUCH DAMAGE.
     36   1.2     matt  */
     37   1.2     matt 
     38   1.2     matt /*
     39   1.2     matt  * On-board device autoconfiguration support for RMI {XLP, XLR, XLS} chips
     40   1.2     matt  */
     41   1.2     matt 
     42   1.2     matt #include <sys/cdefs.h>
     43  1.10    skrll __KERNEL_RCSID(0, "$NetBSD: rmixl_obio.c,v 1.10 2022/09/29 07:00:47 skrll Exp $");
     44   1.2     matt 
     45   1.2     matt #include "locators.h"
     46   1.2     matt #include "pci.h"
     47   1.5     matt #define _MIPS_BUS_DMA_PRIVATE
     48   1.2     matt 
     49   1.2     matt #include <sys/param.h>
     50   1.5     matt #include <sys/bus.h>
     51   1.2     matt #include <sys/device.h>
     52   1.2     matt #include <sys/extent.h>
     53   1.5     matt #include <sys/systm.h>
     54   1.2     matt 
     55   1.5     matt #include <mips/int_fmtio.h>
     56   1.2     matt 
     57   1.2     matt #include <mips/rmi/rmixlreg.h>
     58   1.2     matt #include <mips/rmi/rmixlvar.h>
     59   1.3     matt #include <mips/rmi/rmixl_intr.h>
     60   1.2     matt #include <mips/rmi/rmixl_obiovar.h>
     61   1.2     matt #include <mips/rmi/rmixl_pcievar.h>
     62   1.2     matt 
     63   1.3     matt #include <evbmips/rmixl/autoconf.h>
     64   1.3     matt 
     65   1.2     matt #ifdef OBIO_DEBUG
     66   1.3     matt int obio_rmixl_debug = OBIO_DEBUG;
     67   1.3     matt # define DPRINTF(x)	do { if (obio_rmixl_debug) printf x ; } while (0)
     68   1.2     matt #else
     69   1.2     matt # define DPRINTF(x)
     70   1.2     matt #endif
     71   1.2     matt 
     72   1.2     matt static int  obio_match(device_t, cfdata_t, void *);
     73   1.2     matt static void obio_attach(device_t, device_t, void *);
     74   1.2     matt static int  obio_print(void *, const char *);
     75   1.2     matt static int  obio_search(device_t, cfdata_t, const int *, void *);
     76   1.2     matt static void obio_bus_init(struct obio_softc *);
     77   1.3     matt static void obio_dma_init_64(bus_dma_tag_t);
     78   1.2     matt static int  rmixl_addr_error_intr(void *);
     79   1.2     matt 
     80   1.2     matt 
     81   1.3     matt CFATTACH_DECL_NEW(obio_rmixl, sizeof(struct obio_softc),
     82   1.2     matt     obio_match, obio_attach, NULL, NULL);
     83   1.2     matt 
     84   1.2     matt int obio_found;
     85   1.2     matt 
     86   1.2     matt static int
     87   1.2     matt obio_match(device_t parent, cfdata_t cf, void *aux)
     88   1.2     matt {
     89   1.3     matt 	struct mainbus_attach_args *aa = aux;
     90   1.3     matt 
     91   1.3     matt 	if (obio_found == 0)
     92   1.3     matt 		if (strncmp(aa->ma_name, cf->cf_name, strlen(cf->cf_name)) == 0)
     93   1.3     matt 			return 1;
     94   1.3     matt 
     95   1.3     matt 	return 0;
     96   1.2     matt }
     97   1.2     matt 
     98   1.2     matt static void
     99   1.2     matt obio_attach(device_t parent, device_t self, void *aux)
    100   1.2     matt {
    101   1.2     matt 	struct obio_softc *sc = device_private(self);
    102   1.2     matt 	bus_addr_t ba;
    103   1.2     matt 
    104   1.2     matt 	obio_found = 1;
    105   1.2     matt 	sc->sc_dev = self;
    106   1.2     matt 
    107   1.2     matt 	ba = (bus_addr_t)rmixl_configuration.rc_io_pbase;
    108   1.2     matt 	KASSERT(ba != 0);
    109   1.2     matt 
    110   1.2     matt 	obio_bus_init(sc);
    111   1.2     matt 
    112   1.2     matt 	aprint_normal(" addr %#"PRIxBUSADDR" size %#"PRIxBUSSIZE"\n",
    113   1.2     matt 		ba, (bus_size_t)RMIXL_IO_DEV_SIZE);
    114   1.2     matt 	aprint_naive("\n");
    115   1.2     matt 
    116   1.2     matt 	/*
    117   1.2     matt 	 * Attach on-board devices as specified in the kernel config file.
    118   1.2     matt 	 */
    119   1.6  thorpej 	config_search(self, NULL,
    120   1.7  thorpej 	    CFARGS(.search = obio_search));
    121   1.2     matt }
    122   1.2     matt 
    123   1.2     matt static int
    124   1.2     matt obio_print(void *aux, const char *pnp)
    125   1.2     matt {
    126   1.2     matt 	struct obio_attach_args *obio = aux;
    127   1.2     matt 
    128   1.2     matt 	if (obio->obio_addr != OBIOCF_ADDR_DEFAULT) {
    129   1.2     matt 		aprint_normal(" addr %#"PRIxBUSADDR, obio->obio_addr);
    130   1.2     matt 		if (obio->obio_size != OBIOCF_SIZE_DEFAULT)
    131   1.2     matt 			aprint_normal("-%#"PRIxBUSADDR,
    132   1.2     matt 				obio->obio_addr + (obio->obio_size - 1));
    133   1.2     matt 	}
    134   1.2     matt 	if (obio->obio_mult != OBIOCF_MULT_DEFAULT)
    135   1.2     matt 		aprint_normal(" mult %d", obio->obio_mult);
    136   1.2     matt 	if (obio->obio_intr != OBIOCF_INTR_DEFAULT)
    137   1.2     matt 		aprint_normal(" intr %d", obio->obio_intr);
    138   1.3     matt 	if (obio->obio_tmsk != OBIOCF_TMSK_DEFAULT)
    139   1.3     matt 		aprint_normal(" tmsk %d", obio->obio_tmsk);
    140   1.2     matt 
    141   1.2     matt 	return (UNCONF);
    142   1.2     matt }
    143   1.2     matt 
    144   1.2     matt static int
    145   1.2     matt obio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
    146   1.2     matt {
    147   1.2     matt 	struct obio_softc *sc = device_private(parent);
    148   1.2     matt 	struct obio_attach_args obio;
    149   1.2     matt 
    150   1.3     matt 	obio.obio_eb_bst = sc->sc_eb_bst;
    151   1.3     matt 	obio.obio_el_bst = sc->sc_el_bst;
    152   1.2     matt 	obio.obio_addr = cf->cf_loc[OBIOCF_ADDR];
    153   1.2     matt 	obio.obio_size = cf->cf_loc[OBIOCF_SIZE];
    154   1.2     matt 	obio.obio_mult = cf->cf_loc[OBIOCF_MULT];
    155   1.2     matt 	obio.obio_intr = cf->cf_loc[OBIOCF_INTR];
    156   1.3     matt 	obio.obio_tmsk = cf->cf_loc[OBIOCF_TMSK];
    157   1.2     matt 	obio.obio_29bit_dmat = sc->sc_29bit_dmat;
    158   1.2     matt 	obio.obio_32bit_dmat = sc->sc_32bit_dmat;
    159   1.2     matt 	obio.obio_64bit_dmat = sc->sc_64bit_dmat;
    160   1.2     matt 
    161   1.6  thorpej 	if (config_probe(parent, cf, &obio))
    162   1.7  thorpej 		config_attach(parent, cf, &obio, obio_print, CFARGS_NONE);
    163   1.2     matt 
    164   1.2     matt 	return 0;
    165   1.2     matt }
    166   1.2     matt 
    167   1.2     matt static void
    168   1.2     matt obio_bus_init(struct obio_softc *sc)
    169   1.2     matt {
    170   1.2     matt 	struct rmixl_config *rcp = &rmixl_configuration;
    171   1.2     matt 	static int done = 0;
    172   1.3     matt 	int error;
    173   1.2     matt 
    174   1.2     matt 	if (done)
    175   1.2     matt 		return;
    176   1.2     matt 	done = 1;
    177   1.2     matt 
    178   1.3     matt 	/* obio (devio) space, Big Endian */
    179   1.3     matt 	if (rcp->rc_obio_eb_memt.bs_cookie == 0)
    180   1.3     matt 		rmixl_obio_eb_bus_mem_init(&rcp->rc_obio_eb_memt, rcp);
    181   1.3     matt 
    182   1.3     matt 	/* obio (devio) space, Little Endian */
    183   1.3     matt 	if (rcp->rc_obio_el_memt.bs_cookie == 0)
    184   1.3     matt 		rmixl_obio_el_bus_mem_init(&rcp->rc_obio_el_memt, rcp);
    185   1.3     matt 
    186   1.3     matt 	/* dma space for all memory, including >= 4GB */
    187   1.3     matt 	if (rcp->rc_dma_tag._cookie == 0)
    188   1.3     matt 		obio_dma_init_64(&rcp->rc_dma_tag);
    189   1.3     matt 	rcp->rc_64bit_dmat = &rcp->rc_dma_tag;
    190   1.3     matt 
    191   1.3     matt 	/* dma space for addr < 4GB */
    192   1.3     matt 	if (rcp->rc_32bit_dmat == NULL) {
    193   1.3     matt 		error = bus_dmatag_subregion(rcp->rc_64bit_dmat,
    194   1.9    skrll 		    0, __MASK(32), &rcp->rc_32bit_dmat, 0);
    195   1.3     matt 		if (error)
    196   1.3     matt 			panic("%s: failed to create 32bit dma tag: %d",
    197   1.3     matt 			    __func__, error);
    198   1.3     matt 	}
    199   1.2     matt 
    200   1.2     matt 	/* dma space for addr < 512MB */
    201   1.3     matt 	if (rcp->rc_29bit_dmat == NULL) {
    202   1.3     matt 		error = bus_dmatag_subregion(rcp->rc_32bit_dmat,
    203   1.9    skrll 		    0, __MASK(29), &rcp->rc_29bit_dmat, 0);
    204   1.3     matt 		if (error)
    205   1.3     matt 			panic("%s: failed to create 29bit dma tag: %d",
    206   1.3     matt 			    __func__, error);
    207   1.3     matt 	}
    208   1.2     matt 
    209   1.2     matt 	sc->sc_base = (bus_addr_t)rcp->rc_io_pbase;
    210   1.2     matt 	sc->sc_size = (bus_size_t)RMIXL_IO_DEV_SIZE;
    211   1.3     matt 	sc->sc_eb_bst = (bus_space_tag_t)&rcp->rc_obio_eb_memt;
    212   1.3     matt 	sc->sc_el_bst = (bus_space_tag_t)&rcp->rc_obio_el_memt;
    213   1.3     matt 	sc->sc_29bit_dmat = rcp->rc_29bit_dmat;
    214   1.3     matt 	sc->sc_32bit_dmat = rcp->rc_32bit_dmat;
    215   1.3     matt 	sc->sc_64bit_dmat = rcp->rc_64bit_dmat;
    216   1.2     matt }
    217   1.2     matt 
    218   1.2     matt static void
    219   1.3     matt obio_dma_init_64(bus_dma_tag_t t)
    220   1.2     matt {
    221   1.2     matt 	t->_cookie = t;
    222   1.2     matt 	t->_wbase = 0;
    223   1.3     matt 	t->_bounce_alloc_lo = 0;
    224   1.3     matt 	t->_bounce_alloc_hi = 0;
    225   1.3     matt 	t->_dmamap_ops = mips_bus_dmamap_ops;
    226   1.3     matt 	t->_dmamem_ops = mips_bus_dmamem_ops;
    227   1.3     matt 	t->_dmatag_ops = mips_bus_dmatag_ops;
    228   1.2     matt }
    229   1.2     matt 
    230   1.2     matt void
    231   1.2     matt rmixl_addr_error_init(void)
    232   1.2     matt {
    233   1.2     matt 	uint32_t r;
    234   1.2     matt 
    235   1.2     matt 	/*
    236   1.2     matt 	 * activate error addr detection on all (configurable) devices
    237   1.2     matt 	 * preserve reserved bit fields
    238   1.2     matt 	 * note some of these bits are read-only (writes are ignored)
    239   1.2     matt 	 */
    240   1.2     matt 	r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DEVICE_MASK);
    241   1.2     matt 	r |= ~(__BITS(19,16) | __BITS(10,9) | __BITS(7,5));
    242   1.2     matt 	RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_DEVICE_MASK, r);
    243   1.2     matt 
    244   1.8    skrll 	/*
    245   1.8    skrll 	 * enable the address error interrupts
    246   1.2     matt 	 * "upgrade" cache and CPU errors to A1
    247   1.2     matt 	 */
    248   1.2     matt #define _ADDR_ERR_DEVSTAT_A1	(__BIT(8) | __BIT(1) | __BIT(0))
    249   1.2     matt #define _ADDR_ERR_RESV		\
    250   1.2     matt 		(__BITS(31,21) | __BITS(15,14) | __BITS(10,9) | __BITS(7,2))
    251   1.2     matt #define _BITERR_INT_EN_RESV	(__BITS(31,8) | __BIT(4))
    252   1.2     matt 
    253   1.2     matt 	r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_EN);
    254   1.2     matt 	r &= _ADDR_ERR_RESV;
    255   1.2     matt 	r |= ~_ADDR_ERR_RESV;
    256   1.2     matt 	RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_EN, r);
    257   1.2     matt 
    258   1.2     matt 	r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_UPG);
    259   1.2     matt 	r &= _ADDR_ERR_RESV;
    260   1.2     matt 	r |= _ADDR_ERR_DEVSTAT_A1;
    261   1.2     matt 	RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_UPG, r);
    262   1.2     matt 
    263   1.2     matt 	/*
    264   1.2     matt 	 * clear the log regs and the dev stat (interrupt status) regs
    265   1.2     matt 	 * "Write any value to bit[0] to clear"
    266   1.2     matt 	 */
    267   1.2     matt 	r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_CLEAR);
    268   1.2     matt 	RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR1_CLEAR, r);
    269   1.2     matt 
    270   1.8    skrll 	/*
    271   1.8    skrll 	 * enable the double bit error interrupts
    272   1.2     matt 	 * (assume reserved bits, which are read-only,  are ignored)
    273   1.2     matt 	 */
    274   1.2     matt 	r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_BITERR_INT_EN);
    275   1.2     matt 	r &= _BITERR_INT_EN_RESV;
    276   1.2     matt 	r |= __BITS(7,5);
    277   1.2     matt 	RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_BITERR_INT_EN, r);
    278   1.2     matt 
    279   1.2     matt 	/*
    280   1.2     matt 	 * establish address error ISR
    281   1.3     matt 	 * XXX assuming "int 16 (bridge_tb)" is our irq
    282   1.3     matt 	 * XXX is true for XLS family only
    283   1.2     matt 	 */
    284   1.3     matt 	if (cpu_rmixls(mips_options.mips_cpu))
    285   1.3     matt 		rmixl_intr_establish(16, 1, IPL_HIGH,
    286   1.3     matt 			RMIXL_TRIG_LEVEL, RMIXL_POLR_HIGH,
    287   1.3     matt 			rmixl_addr_error_intr, NULL, false);
    288   1.2     matt }
    289   1.2     matt 
    290   1.2     matt int
    291   1.2     matt rmixl_addr_error_check(void)
    292   1.2     matt {
    293   1.2     matt 	uint32_t aerr0_devstat;
    294   1.2     matt 	uint32_t aerr0_log1;
    295   1.2     matt 	uint32_t aerr0_log2;
    296   1.2     matt 	uint32_t aerr0_log3;
    297   1.2     matt 	uint32_t aerr1_devstat;
    298   1.2     matt 	uint32_t aerr1_log1;
    299   1.2     matt 	uint32_t aerr1_log2;
    300   1.2     matt 	uint32_t aerr1_log3;
    301   1.2     matt 	uint32_t sbe_counts;
    302   1.2     matt 	uint32_t dbe_counts;
    303   1.2     matt 
    304   1.2     matt 	aerr0_devstat = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_DEVSTAT);
    305   1.2     matt 	aerr0_log1 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG1);
    306   1.2     matt 	aerr0_log2 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG2);
    307   1.2     matt 	aerr0_log3 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG3);
    308   1.2     matt 
    309   1.2     matt 	aerr1_devstat = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_DEVSTAT);
    310   1.2     matt 	aerr1_log1 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG1);
    311   1.2     matt 	aerr1_log2 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG2);
    312   1.2     matt 	aerr1_log3 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG3);
    313   1.2     matt 
    314   1.2     matt 	sbe_counts = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_SBE_COUNTS);
    315   1.2     matt 	dbe_counts = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DBE_COUNTS);
    316   1.2     matt 
    317   1.2     matt 	if (aerr0_log1|aerr0_log2|aerr0_log3
    318   1.2     matt 	   |aerr1_log1|aerr1_log2|aerr1_log3
    319   1.2     matt 	   |dbe_counts) {
    320   1.2     matt 		printf("aerr0: stat %#x, logs: %#x, %#x, %#x\n",
    321   1.2     matt 			aerr0_devstat, aerr0_log1, aerr0_log2, aerr0_log2);
    322   1.2     matt 		printf("aerr1: stat %#x, logs: %#x, %#x, %#x\n",
    323   1.2     matt 			aerr1_devstat, aerr1_log1, aerr1_log2, aerr1_log2);
    324   1.2     matt 		printf("1-bit errors: %#x, 2-bit errors: %#x\n",
    325   1.2     matt 			sbe_counts, dbe_counts);
    326   1.2     matt 		return 1;
    327   1.2     matt 	}
    328   1.2     matt 	return 0;
    329   1.2     matt }
    330   1.2     matt 
    331   1.2     matt static int
    332   1.2     matt rmixl_addr_error_intr(void *arg)
    333   1.2     matt {
    334   1.2     matt 	int err;
    335   1.2     matt 
    336   1.2     matt 	err = rmixl_addr_error_check();
    337   1.2     matt 	if (err != 0) {
    338   1.2     matt #if DDB
    339   1.2     matt 		printf("%s\n", __func__);
    340   1.2     matt 		Debugger();
    341   1.2     matt #endif
    342   1.2     matt 		panic("Address Error");
    343   1.2     matt 	}
    344   1.2     matt 	return 1;
    345   1.2     matt }
    346