Home | History | Annotate | Line # | Download | only in vsa
      1 /*	$NetBSD: tc_vsbus.c,v 1.10 2021/05/08 09:03:30 rin Exp $	*/
      2 /*-
      3  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      4  * All rights reserved.
      5  *
      6  * This code is derived from software contributed to The NetBSD Foundation
      7  * by Matt Thomas <matt (at) 3am-software.com>.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: tc_vsbus.c,v 1.10 2021/05/08 09:03:30 rin Exp $");
     33 
     34 #include <sys/param.h>
     35 #include <sys/bus.h>
     36 #include <sys/cpu.h>
     37 #include <sys/device.h>
     38 
     39 #include <machine/cpu.h>
     40 #include <machine/pte.h>
     41 #include <machine/scb.h>
     42 #include <machine/sid.h>
     43 #include <machine/vsbus.h>
     44 
     45 #include <dev/tc/tcvar.h>
     46 
     47 #define NSLOTS	1
     48 
     49 struct tc_vsbus_softc {
     50 	struct tc_softc sc_tc;
     51 	struct tc_slotdesc sc_slots[NSLOTS];
     52 	struct vax_bus_dma_tag sc_dmatag;
     53 	struct vax_sgmap sc_sgmap;
     54 	struct evcnt sc_ev;
     55 	int (*sc_intr_func)(void *);
     56 	void *sc_intr_arg;
     57 	bus_space_tag_t sc_bst;
     58 	bus_space_handle_t sc_bsh_csr;
     59 	int sc_cvec;
     60 };
     61 
     62 static int tc_vsbus_match(device_t, cfdata_t, void *);
     63 static void tc_vsbus_attach(device_t, device_t, void *);
     64 
     65 static int tc_vsbus_dma_init(device_t);
     66 static bus_dma_tag_t tc_vsbus_get_dma_tag(int);
     67 
     68 static void tc_vsbus_intr(void *);
     69 static void tc_vsbus_intr_establish(device_t, void *, int, int (*)(void *),
     70     void *);
     71 static void tc_vsbus_intr_disestablish(device_t, void *);
     72 static const struct evcnt *tc_vsbus_intr_evcnt(device_t, void *);
     73 
     74 static int vax_tc_bus_space_map(void *, bus_addr_t, bus_size_t, int,
     75     bus_space_handle_t *, int);
     76 static int vax_tc_bus_space_subregion(void *, bus_space_handle_t, bus_size_t,
     77     bus_size_t, bus_space_handle_t *);
     78 static void vax_tc_bus_space_unmap(void *, bus_space_handle_t, bus_size_t, int);
     79 static int vax_tc_bus_space_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t,
     80     bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
     81 static void vax_tc_bus_space_free(void *, bus_space_handle_t, bus_size_t);
     82 static paddr_t vax_tc_bus_space_mmap(void *, bus_addr_t, off_t, int, int);
     83 
     84 CFATTACH_DECL_NEW(tc_vsbus, sizeof(struct tc_vsbus_softc),
     85     tc_vsbus_match, tc_vsbus_attach, 0, 0);
     86 
     87 static bus_dma_tag_t tc_vsbus_dmat;
     88 
     89 struct vax_bus_space vax_tc_bus_space = {
     90 	NULL,
     91 	vax_tc_bus_space_map,
     92 	vax_tc_bus_space_unmap,
     93 	vax_tc_bus_space_subregion,
     94 	vax_tc_bus_space_alloc,
     95 	vax_tc_bus_space_free,
     96 	vax_tc_bus_space_mmap,
     97 };
     98 
     99 /*
    100  * taken from KA46 System Board Specification, KA46-0-DBF, Rev. X.02,
    101  * 10 October 1990
    102  */
    103 #define KA46_BWF0			0x20080014
    104 #define   KA46_BWF0_ADP			__BIT(31)
    105 #define KA46_BWF0_SZ			4
    106 
    107 /*
    108  * taken from KA49 Processor Module Specification V 1.1, 20 August 1992
    109  */
    110 #define KA49_CFG			0x25800000
    111 #define   KA49_CFG_BA			__BIT(0)
    112 #define KA49_CFG_SZ			2
    113 
    114 /*
    115  * taken from Pmariah TURBOchannel Adapter Specification, 29 November 1991
    116  */
    117 #define KA4x_TCA_BASE			0x30000000
    118 #define KA4x_TCA_DIAG_TRIG		(KA4x_TCA_BASE + 0x4000000)
    119 #define KA4x_TCA_MAP_CHK_SEQ		(KA4x_TCA_BASE + 0x4800000)
    120 #define KA4x_TCA_FIFO_DIAG		(KA4x_TCA_BASE + 0x5000000)
    121 #define KA4x_TCA_SGMAP			(KA4x_TCA_BASE + 0x5800000)
    122 #define KA4x_TCA_DIAG_ROM		(KA4x_TCA_BASE + 0x6000000)
    123 #define KA4x_TCA_CSR			(KA4x_TCA_BASE + 0x6800000)
    124 #define   KA4x_TCA_CSR_BLK_SZ		__BITS(0, 2)	/* 0x00007 RW   */
    125 #define   KA4x_TCA_CSR_SPARE		__BIT(3)	/* 0x00008 RW   */
    126 #define   KA4x_TCA_CSR_BAD_PAR		__BITS(4, 7)	/* 0x000f0 RW   */
    127 #define   KA4x_TCA_CSR_RST_TC		__BIT(8)	/* 0x00100 RW   */
    128 #define   KA4x_TCA_CSR_EN_MAP		__BIT(9)	/* 0x00200 RW   */
    129 #define   KA4x_TCA_CSR_INVAL_REF	__BIT(10)	/* 0x00400 RW1C */
    130 #define   KA4x_TCA_CSR_TC_TMO		__BIT(11)	/* 0x00800 RW   */
    131 #define   KA4x_TCA_CSR_EN_TC_IRQ	__BIT(12)	/* 0x01000 RW   */
    132 #define   KA4x_TCA_CSR_TC_IRQ		__BIT(13)	/* 0x02000 R    */
    133 #define   KA4x_TCA_CSR_ERR		__BIT(14)	/* 0x04000 RW1C */
    134 #define   KA4x_TCA_CSR_ALT_CYC_ST	__BIT(15)	/* 0x08000 RW   */
    135 #define   KA4x_TCA_CSR_EN_PAR		__BIT(16)	/* 0x10000 RW   */
    136 #define   KA4x_TCA_CSR_FIFO_EMPTY	__BIT(17)	/* 0x20000 R    */
    137 #define KA4x_TCA_CSR_SZ			4
    138 
    139 static int
    140 tc_vsbus_match(device_t parent, cfdata_t cfdata, void *aux)
    141 {
    142 	struct vsbus_attach_args * const va = aux;
    143 	uint32_t *csr;
    144 	bus_space_tag_t bst = va->va_memt;
    145 	bus_space_handle_t bsh;
    146 	int found, rc;
    147 
    148 	if (va->va_paddr != KA4x_TCA_CSR)
    149 		return 0;
    150 
    151 	/* Bus adaptor present? */
    152 	switch (vax_boardtype) {
    153 	case VAX_BTYP_46:
    154 		if (bus_space_map(bst, KA46_BWF0, KA46_BWF0_SZ, 0, &bsh))
    155 			return 0;
    156 		found = ((bus_space_read_4(bst, bsh, 0) & KA46_BWF0_ADP) != 0);
    157 		bus_space_unmap(bst, bsh, KA46_BWF0_SZ);
    158 		/*
    159 		 * On VS4000/60, although interrupting on a real vector, fool
    160 		 * vsbus interrupt, as no interrupt bit will be set in
    161 		 * vsbus_softc's sc_intreq for TC adaptor.
    162 		 */
    163 		rc = 20;
    164 		break;
    165 	case VAX_BTYP_49:
    166 		if (bus_space_map(bst, KA49_CFG, KA49_CFG_SZ, 0, &bsh))
    167 			return 0;
    168 		found = ((bus_space_read_2(bst, bsh, 0) & KA49_CFG_BA) != 0);
    169 		bus_space_unmap(bst, bsh, KA49_CFG_SZ);
    170 		rc = 10;
    171 		break;
    172 	default:
    173 		return 0;
    174 	}
    175 	if (!found)
    176 		return 0;
    177 
    178 	/* XXX Assume a found bus adaptor is the TC bus adaptor. */
    179 
    180 	/* Force interrupt. */
    181 	csr = (uint32_t *)va->va_addr;
    182 	*csr |= KA4x_TCA_CSR_TC_TMO;
    183 	DELAY(10000);
    184 	*csr &= ~KA4x_TCA_CSR_TC_TMO;
    185 	DELAY(10000);
    186 
    187 	return rc;
    188 }
    189 
    190 #define INIT_SLOTSZ	1
    191 
    192 static void
    193 tc_vsbus_attach(device_t parent, device_t self, void *aux)
    194 {
    195 	struct tcbus_attach_args tba;
    196 	struct vsbus_attach_args * const va = aux;
    197 	struct tc_vsbus_softc * const sc = device_private(self);
    198 	struct tc_rommap *rommap;
    199 	bus_space_tag_t bst = va->va_memt;
    200 	bus_space_handle_t bsh_csr, bsh_slot;
    201 	const bus_size_t slotb = 4194304;
    202 	uint32_t csr;
    203 	int error, slotsz;
    204 
    205 	sc->sc_cvec = va->va_cvec;
    206 
    207 	error = bus_space_map(bst, KA4x_TCA_CSR, KA4x_TCA_CSR_SZ, 0, &bsh_csr);
    208 	if (error) {
    209 		aprint_normal(": failed to map TCA CSR: %d\n", error);
    210 		return;
    211 	}
    212 	sc->sc_bst = bst;
    213 	sc->sc_bsh_csr = bsh_csr;
    214 
    215 	/* Deassert TC option reset and clean up. */
    216 	csr = bus_space_read_4(bst, bsh_csr, 0);
    217 	csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC);
    218 	csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_INVAL_REF;
    219 	bus_space_write_4(bst, bsh_csr, 0, csr);
    220 
    221 	/*
    222 	 * Map initial number of "slots" (4 MB each) to read the option ROM
    223 	 * header.
    224 	 */
    225 	error = bus_space_map(bst, KA4x_TCA_BASE, INIT_SLOTSZ * slotb,
    226 	    BUS_SPACE_MAP_LINEAR, &bsh_slot);
    227 	if (error) {
    228 		aprint_normal(": failed to map TC slot: %d", error);
    229 		goto fail;
    230 	}
    231 	/* Determine number of slots required from option ROM header. */
    232 	slotsz = 0;
    233 	if (tc_checkslot((tc_addr_t)bus_space_vaddr(bst, bsh_slot), NULL,
    234 	    &rommap))
    235 		slotsz = rommap->tcr_ssize.v;
    236 	if (slotsz == 0) {
    237 		/* Invalid option ROM header or no option present. */
    238 		bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb);
    239 		goto fail;
    240 	} else if (slotsz > INIT_SLOTSZ) {
    241 		/* Remap with actual slot size required. */
    242 		bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb);
    243 		error = bus_space_map(bst, KA4x_TCA_BASE, slotsz * slotb,
    244 		    BUS_SPACE_MAP_LINEAR, &bsh_slot);
    245 		if (error) {
    246 			aprint_normal(": failed to map TC slot: %d", error);
    247 			goto fail;
    248 		}
    249 	} else
    250 		slotsz = INIT_SLOTSZ;
    251 
    252 	/* Pass pre-mapped space for TC drivers not bus_space'ified yet. */
    253 	sc->sc_slots[0].tcs_addr = (tc_addr_t)bus_space_vaddr(bst, bsh_slot);
    254 	sc->sc_slots[0].tcs_cookie = sc;
    255 
    256 	tba.tba_busname = "tc";
    257 	/* Tag with custom methods for pre-mapped bus_space. */
    258 	tba.tba_memt = &vax_tc_bus_space;
    259 	tba.tba_speed = TC_SPEED_12_5_MHZ;
    260 	tba.tba_nslots = __arraycount(sc->sc_slots);
    261 	tba.tba_slots = sc->sc_slots;
    262 	tba.tba_nbuiltins = 0;
    263 	tba.tba_intr_evcnt = tc_vsbus_intr_evcnt;
    264 	tba.tba_intr_establish = tc_vsbus_intr_establish;
    265 	tba.tba_intr_disestablish = tc_vsbus_intr_disestablish;
    266 	tba.tba_get_dma_tag = tc_vsbus_get_dma_tag;
    267 
    268 	error = tc_vsbus_dma_init(self);
    269 	if (error) {
    270 		aprint_normal(": failed to init DMA: %d", error);
    271 		bus_space_unmap(bst, bsh_slot, slotsz * slotb);
    272 		goto fail;
    273 	}
    274 
    275 	evcnt_attach_dynamic(&sc->sc_ev, EVCNT_TYPE_INTR, NULL,
    276 	    device_xname(self), "intr");
    277 
    278 	/* Enable SGDMA and option IRQ now. */
    279 	csr = bus_space_read_4(bst, bsh_csr, 0);
    280 	csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC);
    281 	csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_EN_TC_IRQ |
    282 	    KA4x_TCA_CSR_INVAL_REF | KA4x_TCA_CSR_EN_MAP;
    283 	bus_space_write_4(bst, bsh_csr, 0, csr);
    284 
    285 	/* XXX: why not config_found(9)?? */
    286 	tcattach(parent, self, &tba);
    287 
    288 	return;
    289 
    290 fail:
    291 	aprint_normal("\n");
    292 	/* Clear possible timeout bit which asserts TC interrupt. */
    293 	csr = bus_space_read_4(bst, bsh_csr, 0);
    294 	csr &= ~KA4x_TCA_CSR_TC_TMO;
    295 	bus_space_write_4(bst, bsh_csr, 0, csr);
    296 	bus_space_unmap(bst, bsh_csr, KA4x_TCA_CSR_SZ);
    297 }
    298 
    299 static int
    300 tc_vsbus_dma_init(device_t dev)
    301 {
    302 	struct tc_vsbus_softc * const sc = device_private(dev);
    303 	struct pte *pte;
    304 	bus_dma_tag_t dmat = &sc->sc_dmatag;
    305 	bus_space_tag_t bst = sc->sc_bst;
    306 	bus_space_handle_t bsh;
    307 	const bus_size_t ptecnt = 8192;
    308 	const bus_size_t mapsize = ptecnt * sizeof(pte[0]);
    309 	int error;
    310 
    311 	vax_sgmap_dmatag_init(dmat, sc, ptecnt);
    312 
    313 	dmat->_sgmap = &sc->sc_sgmap;
    314 
    315 	error = bus_space_map(bst, KA4x_TCA_SGMAP, mapsize,
    316 	    BUS_SPACE_MAP_LINEAR, &bsh);
    317 	if (error)
    318 		return error;
    319 	bus_space_set_region_4(bst, bsh, 0, 0, ptecnt);
    320 	pte = bus_space_vaddr(bst, bsh);
    321 
    322 	/* Initialize the SGMAP. */
    323 	vax_sgmap_init(dmat, &sc->sc_sgmap, "tc_sgmap", dmat->_wbase,
    324 	    dmat->_wsize, pte, 0);
    325 
    326 	tc_vsbus_dmat = dmat;
    327 
    328 	return 0;
    329 }
    330 
    331 static bus_dma_tag_t
    332 tc_vsbus_get_dma_tag(int slotno)
    333 {
    334 
    335 	return tc_vsbus_dmat;
    336 }
    337 
    338 static void
    339 tc_vsbus_intr(void *arg)
    340 {
    341 	struct tc_vsbus_softc * const sc = arg;
    342 	bus_space_tag_t bst = sc->sc_bst;
    343 	bus_space_handle_t bsh = sc->sc_bsh_csr;
    344 	uint32_t csr;
    345 
    346 	sc->sc_ev.ev_count++;
    347 
    348 	csr = bus_space_read_4(bst, bsh, 0);
    349 	if (__predict_true((csr & KA4x_TCA_CSR_TC_IRQ) == 0))	/* active low */
    350 		sc->sc_intr_func(sc->sc_intr_arg);
    351 
    352 	/* Clear possible timeout bit which asserts TC interrupt. */
    353 	csr = bus_space_read_4(bst, bsh, 0);
    354 	csr &= ~KA4x_TCA_CSR_TC_TMO;
    355 	bus_space_write_4(bst, bsh, 0, csr);
    356 }
    357 
    358 static void
    359 tc_vsbus_intr_establish(device_t dv, void *cookie, int level,
    360     int (*func)(void *), void *arg)
    361 {
    362 	struct tc_vsbus_softc * const sc = cookie;
    363 
    364 	sc->sc_intr_func = func;
    365 	sc->sc_intr_arg = arg;
    366 
    367 	scb_vecalloc(sc->sc_cvec, tc_vsbus_intr, sc, SCB_ISTACK, &sc->sc_ev);
    368 }
    369 
    370 static void
    371 tc_vsbus_intr_disestablish(device_t dv, void *cookie)
    372 {
    373 
    374 	/* Do nothing. */
    375 }
    376 
    377 static const struct evcnt *
    378 tc_vsbus_intr_evcnt(device_t dv, void *cookie)
    379 {
    380 	struct tc_vsbus_softc * const sc = device_private(dv);
    381 
    382 	return &sc->sc_ev;
    383 }
    384 
    385 static int
    386 vax_tc_bus_space_map(void *t, bus_addr_t pa, bus_size_t size, int cacheable,
    387     bus_space_handle_t *bshp, int f2)
    388 {
    389 
    390 	/* bus_space is pre-mapped, so "pa" is a virtual address already. */
    391 	*bshp = pa;
    392 	return 0;
    393 }
    394 
    395 static int
    396 vax_tc_bus_space_subregion(void *t, bus_space_handle_t h, bus_size_t o,
    397     bus_size_t s, bus_space_handle_t *hp)
    398 {
    399 
    400 	*hp = h + o;
    401 	return 0;
    402 }
    403 
    404 static void
    405 vax_tc_bus_space_unmap(void *t, bus_space_handle_t h, bus_size_t size, int f)
    406 {
    407 
    408 	/* Do nothing. */
    409 }
    410 
    411 static int
    412 vax_tc_bus_space_alloc(void *t, bus_addr_t rs, bus_addr_t re, bus_size_t s,
    413     bus_size_t a, bus_size_t b, int f, bus_addr_t *ap, bus_space_handle_t *hp)
    414 {
    415 
    416 	panic("vax_tc_bus_space_alloc not implemented");
    417 }
    418 
    419 static void
    420 vax_tc_bus_space_free(void *t, bus_space_handle_t h, bus_size_t s)
    421 {
    422 
    423 	panic("vax_tc_bus_space_free not implemented");
    424 }
    425 
    426 static paddr_t
    427 vax_tc_bus_space_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags)
    428 {
    429 	bus_addr_t rv;
    430 
    431 	rv = addr + off;
    432 	return btop(rv);
    433 }
    434