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@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
tc_vsbus_match(device_t parent,cfdata_t cfdata,void * aux)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
tc_vsbus_attach(device_t parent,device_t self,void * aux)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
tc_vsbus_dma_init(device_t dev)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
tc_vsbus_get_dma_tag(int slotno)332 tc_vsbus_get_dma_tag(int slotno)
333 {
334 
335           return tc_vsbus_dmat;
336 }
337 
338 static void
tc_vsbus_intr(void * arg)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
tc_vsbus_intr_establish(device_t dv,void * cookie,int level,int (* func)(void *),void * arg)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
tc_vsbus_intr_disestablish(device_t dv,void * cookie)371 tc_vsbus_intr_disestablish(device_t dv, void *cookie)
372 {
373 
374           /* Do nothing. */
375 }
376 
377 static const struct evcnt *
tc_vsbus_intr_evcnt(device_t dv,void * cookie)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
vax_tc_bus_space_map(void * t,bus_addr_t pa,bus_size_t size,int cacheable,bus_space_handle_t * bshp,int f2)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
vax_tc_bus_space_subregion(void * t,bus_space_handle_t h,bus_size_t o,bus_size_t s,bus_space_handle_t * hp)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
vax_tc_bus_space_unmap(void * t,bus_space_handle_t h,bus_size_t size,int f)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
vax_tc_bus_space_alloc(void * t,bus_addr_t rs,bus_addr_t re,bus_size_t s,bus_size_t a,bus_size_t b,int f,bus_addr_t * ap,bus_space_handle_t * hp)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
vax_tc_bus_space_free(void * t,bus_space_handle_t h,bus_size_t s)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
vax_tc_bus_space_mmap(void * v,bus_addr_t addr,off_t off,int prot,int flags)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