xref: /netbsd-src/sys/arch/sparc/sparc/msiiep.c (revision 90d7b449b611b9e411624cf344e9ff5914fd701e)
1 /*	$NetBSD: msiiep.c,v 1.53 2022/01/21 19:14:14 thorpej Exp $ */
2 
3 /*
4  * Copyright (c) 2001 Valeriy E. Ushakov
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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1.53 2022/01/21 19:14:14 thorpej Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/kmem.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 
38 #include <uvm/uvm.h>
39 
40 #define _SPARC_BUS_DMA_PRIVATE
41 #include <sys/bus.h>
42 #include <machine/autoconf.h>
43 #include <machine/promlib.h>
44 
45 #include <dev/pci/pcireg.h>
46 #include <dev/pci/pcidevs.h>
47 #include <dev/pci/pcivar.h>
48 
49 #include <sparc/sparc/msiiepreg.h>
50 #include <sparc/sparc/msiiepvar.h>
51 #include <sparc/sparc/pci_fixup.h>
52 
53 /*
54  * Autoconfiguration.
55  *
56  * Normally, sparc autoconfiguration is driven by PROM device tree,
57  * however PROMs in ms-IIep machines usually don't have nodes for
58  * various important registers that are part of ms-IIep PCI controller.
59  * We work around by inserting a dummy device that acts as a parent
60  * for device drivers that deal with various functions of PCIC.  The
61  * other option is to hack mainbus_attach() to treat ms-IIep specially,
62  * but I'd rather insulate the rest of the source from ms-IIep quirks.
63  */
64 
65 /*
66  * "Stub" ms-IIep parent that knows how to attach various functions.
67  */
68 static int	msiiep_match(device_t, cfdata_t, void *);
69 static void	msiiep_attach(device_t, device_t, void *);
70 
71 CFATTACH_DECL_NEW(msiiep, 0, msiiep_match, msiiep_attach, NULL, NULL);
72 
73 
74 /* sleep in idle spin */
75 static void	msiiep_cpu_sleep(void);
76 volatile uint32_t *msiiep_mid = NULL;
77 
78 
79 /*
80  * The real thing.
81  */
82 static int	mspcic_match(device_t, cfdata_t, void *);
83 static void	mspcic_attach(device_t, device_t, void *);
84 static int	mspcic_print(void *, const char *);
85 
86 CFATTACH_DECL_NEW(mspcic, sizeof(struct mspcic_softc),
87     mspcic_match, mspcic_attach, NULL, NULL);
88 
89 
90 /**
91  * Only one PCI controller per MS-IIep and only one MS-IIep per system
92  * so don't bother with malloc'ing our tags.
93  */
94 
95 /*
96  * PCI chipset tag
97  */
98 static struct sparc_pci_chipset mspcic_pc_tag = { NULL };
99 
100 
101 /* fixed i/o and one set of i/o cycle translation registers */
102 struct mspcic_pci_map mspcic_pci_iomap[IOMAP_SIZE] = {
103 	{ 0x30000000, 0x0, 0x00010000 }		/* fixed i/o (decoded bits) */
104 };
105 
106 /* fixed mem and two sets of mem cycle translation registers */
107 struct mspcic_pci_map mspcic_pci_memmap[MEMMAP_SIZE] = {
108 	{ 0x30100000, 0x00100000, 0x00f00000 }	/* fixed mem (pass through) */
109 };
110 
111 struct mspcic_cookie {
112 	struct mspcic_pci_map *map;
113 	int nmaps;
114 };
115 
116 static struct mspcic_cookie mspcic_io_cookie = { mspcic_pci_iomap, 0 };
117 static struct mspcic_cookie mspcic_mem_cookie = { mspcic_pci_memmap, 0 };
118 
119 
120 static void		mspcic_init_maps(void);
121 static void		mspcic_pci_map_from_reg(struct mspcic_pci_map *,
122 						uint8_t, uint8_t, uint8_t);
123 static bus_addr_t	mspcic_pci_map_find(struct mspcic_pci_map *, int,
124 					    bus_addr_t, bus_size_t);
125 #ifdef DEBUG
126 static void	mspcic_pci_map_print(struct mspcic_pci_map *, const char *);
127 #endif
128 
129 
130 static int	mspcic_bus_map(bus_space_tag_t, bus_addr_t, bus_size_t,
131 			       int, vaddr_t, bus_space_handle_t *);
132 static paddr_t	mspcic_bus_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
133 static void	*mspcic_intr_establish(bus_space_tag_t, int, int,
134 				       int (*)(void *), void *, void (*)(void));
135 
136 /* bus space methods that do byteswapping */
137 static uint16_t	mspcic_bus_read_2(bus_space_tag_t, bus_space_handle_t,
138 				  bus_size_t);
139 static uint32_t	mspcic_bus_read_4(bus_space_tag_t, bus_space_handle_t,
140 				  bus_size_t);
141 static uint64_t	mspcic_bus_read_8(bus_space_tag_t, bus_space_handle_t,
142 				  bus_size_t);
143 static void	mspcic_bus_write_2(bus_space_tag_t, bus_space_handle_t,
144 				   bus_size_t, uint16_t);
145 static void	mspcic_bus_write_4(bus_space_tag_t, bus_space_handle_t,
146 				   bus_size_t, uint32_t);
147 static void	mspcic_bus_write_8(bus_space_tag_t, bus_space_handle_t,
148 				   bus_size_t, uint64_t);
149 
150 static struct sparc_bus_space_tag mspcic_io_tag;
151 static struct sparc_bus_space_tag mspcic_mem_tag;
152 
153 
154 /*
155  * DMA tag
156  */
157 static int	mspcic_dmamap_load(bus_dma_tag_t, bus_dmamap_t,
158 				   void *, bus_size_t, struct proc *, int);
159 static void	mspcic_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
160 static int	mspcic_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
161 				  int, size_t, void **, int);
162 
163 static struct sparc_bus_dma_tag mspcic_dma_tag = {
164 	NULL,			/* _cookie */
165 
166 	_bus_dmamap_create,
167 	_bus_dmamap_destroy,
168 	mspcic_dmamap_load,
169 	_bus_dmamap_load_mbuf,
170 	_bus_dmamap_load_uio,
171 	_bus_dmamap_load_raw,
172 	mspcic_dmamap_unload,
173 	_bus_dmamap_sync,
174 
175 	_bus_dmamem_alloc,
176 	_bus_dmamem_free,
177 	mspcic_dmamem_map,
178 	_bus_dmamem_unmap,
179 	_bus_dmamem_mmap
180 };
181 
182 
183 static int
msiiep_match(device_t parent,cfdata_t cf,void * aux)184 msiiep_match(device_t parent, cfdata_t cf, void *aux)
185 {
186 	struct mainbus_attach_args *ma = aux;
187 	pcireg_t id;
188 
189 	/* match by PROM name */
190 	if (strcmp(ma->ma_name, "pci") != 0)
191 		return (0);
192 
193 	/*
194 	 * Verify that PCIC was successfully mapped by bootstrap code.
195 	 * Since PCIC contains all the registers vital to the kernel,
196 	 * bootstrap code maps them at a fixed va, MSIIEP_PCIC_VA
197 	 */
198 	id = mspcic_read_4(pcic_id);
199 	if (PCI_VENDOR(id) != PCI_VENDOR_SUN
200 	    && PCI_PRODUCT(id) != PCI_PRODUCT_SUN_MS_IIep)
201 		panic("msiiep_match: id %08x", id);
202 
203 	return (1);
204 }
205 
206 
207 static void
msiiep_attach(device_t parent,device_t self,void * aux)208 msiiep_attach(device_t parent, device_t self, void *aux)
209 {
210 	struct mainbus_attach_args *ma = aux;
211 	struct msiiep_attach_args msa;
212 	bus_space_handle_t hmid;
213 	struct cpu_info *cur;
214 
215 	aprint_normal("\n");
216 
217 	if (bus_space_map(ma->ma_bustag, MSIIEP_MID_PA, 4, 0, &hmid) == 0) {
218 #ifdef DIAGNOSTICS
219 		uint32_t mid;
220 
221 		mid = bus_space_read_4(ma->ma_bustag, hmid, 0);
222 		printf("MID: %08x\n", mid);
223 #endif
224 		msiiep_mid = (volatile uint32_t *)bus_space_vaddr(ma->ma_bustag,
225 		    hmid);
226 		cur = curcpu();
227 		cur->idlespin = msiiep_cpu_sleep;
228 	}
229 
230 	/* pass on real mainbus_attach_args */
231 	msa.msa_ma = ma;
232 
233 	/* config timer/counter part of PCIC */
234 	msa.msa_name = "timer";
235 	config_found(self, &msa, NULL, CFARGS_NONE);
236 
237 	/* config PCI tree */
238 	msa.msa_name = "pcic";
239 	config_found(self, &msa, NULL, CFARGS_NONE);
240 }
241 
242 /* ARGSUSED */
243 void
msiiep_cpu_sleep(void)244 msiiep_cpu_sleep(void)
245 {
246 	uint32_t reg;
247 
248 	if (msiiep_mid == 0)
249 		return;
250 	reg = *msiiep_mid;
251 	*msiiep_mid = (reg & MID_MASK) | MID_STANDBY;
252 }
253 
254 
255 /* ======================================================================
256  *
257  *		      Real ms-IIep PCIC driver.
258  */
259 
260 static int
mspcic_match(device_t parent,cfdata_t cf,void * aux)261 mspcic_match(device_t parent, cfdata_t cf, void *aux)
262 {
263 	struct msiiep_attach_args *msa = aux;
264 
265 	return (strcmp(msa->msa_name, "pcic") == 0);
266 }
267 
268 
269 static void
mspcic_attach(device_t parent,device_t self,void * aux)270 mspcic_attach(device_t parent, device_t self, void *aux)
271 {
272 	struct mspcic_softc *sc = device_private(self);
273 	struct msiiep_attach_args *msa = aux;
274 	struct mainbus_attach_args *ma = msa->msa_ma;
275 	int node = ma->ma_node;
276 	char devinfo[256], buf[32], *model;
277 
278 	struct pcibus_attach_args pba;
279 
280 	sc->sc_node = node;
281 
282 	/* copy parent tags */
283 	sc->sc_bustag = ma->ma_bustag;
284 	sc->sc_dmatag = ma->ma_dmatag;
285 
286 	/* print our PCI device info and bus clock frequency */
287 	pci_devinfo(mspcic_read_4(pcic_id), mspcic_read_4(pcic_class), 0,
288 		    devinfo, sizeof(devinfo));
289 	printf(": %s: clock = %s MHz\n", devinfo,
290 	       clockfreq(prom_getpropint(node, "clock-frequency", 33333333)));
291 
292 	mspcic_init_maps();
293 
294 	/*
295 	 * On Espresso, we need to adjust the interrupt mapping on
296 	 * lines 4-7, as onboard devices and cards in the PCI slots use
297 	 * those lines.  Note, that enabling line 5 (onboard ide) causes
298 	 * a continuous interrupt stream, so leave that unmapped (0).
299 	 * Any other device using line 5 can't be used.
300 	 * Interrupt line wiring for slots is set in pci_machdep.c.
301 	 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise
302 	 * we'll lock up when using devices behind a PCI-PCI bridge.
303 	 */
304 	model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf));
305 	if (model != NULL && !strcmp(model, "SUNW,375-0059")) {
306 		mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502);
307 		mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000);
308 	}
309 
310 	/* init cookies/parents in our statically allocated tags */
311 	mspcic_io_tag = *sc->sc_bustag;
312 	mspcic_io_tag.cookie = &mspcic_io_cookie;
313 	mspcic_io_tag.ranges = NULL;
314 	mspcic_io_tag.nranges = 0;
315 	mspcic_io_tag.sparc_bus_map = mspcic_bus_map;
316 	mspcic_io_tag.sparc_bus_mmap = mspcic_bus_mmap;
317 	mspcic_io_tag.sparc_intr_establish = mspcic_intr_establish;
318 	mspcic_io_tag.parent = sc->sc_bustag;
319 
320 	mspcic_io_tag.sparc_read_2 = mspcic_bus_read_2;
321 	mspcic_io_tag.sparc_read_4 = mspcic_bus_read_4;
322 	mspcic_io_tag.sparc_read_8 = mspcic_bus_read_8;
323 	mspcic_io_tag.sparc_write_2 = mspcic_bus_write_2;
324 	mspcic_io_tag.sparc_write_4 = mspcic_bus_write_4;
325 	mspcic_io_tag.sparc_write_8 = mspcic_bus_write_8;
326 
327 	mspcic_mem_tag = *sc->sc_bustag;
328 	mspcic_mem_tag.cookie = &mspcic_mem_cookie;
329 	mspcic_mem_tag.ranges = NULL;
330 	mspcic_mem_tag.nranges = 0;
331 	mspcic_mem_tag.sparc_bus_map = mspcic_bus_map;
332 	mspcic_mem_tag.sparc_bus_mmap = mspcic_bus_mmap;
333 	mspcic_mem_tag.sparc_intr_establish = mspcic_intr_establish;
334 	mspcic_mem_tag.parent = sc->sc_bustag;
335 
336 	mspcic_mem_tag.sparc_read_2 = mspcic_bus_read_2;
337 	mspcic_mem_tag.sparc_read_4 = mspcic_bus_read_4;
338 	mspcic_mem_tag.sparc_read_8 = mspcic_bus_read_8;
339 	mspcic_mem_tag.sparc_write_2 = mspcic_bus_write_2;
340 	mspcic_mem_tag.sparc_write_4 = mspcic_bus_write_4;
341 	mspcic_mem_tag.sparc_write_8 = mspcic_bus_write_8;
342 
343 	mspcic_dma_tag._cookie = sc;
344 	mspcic_pc_tag.cookie = sc;
345 
346 	/* save bus tags in softc */
347 	sc->sc_iot = &mspcic_io_tag;
348 	sc->sc_memt = &mspcic_mem_tag;
349 	sc->sc_dmat = &mspcic_dma_tag;
350 
351 	/*
352 	 * Attach the PCI bus.
353 	 */
354 	pba.pba_bus = 0;
355 	pba.pba_bridgetag = NULL;
356 	pba.pba_iot = sc->sc_iot;
357 	pba.pba_memt = sc->sc_memt;
358 	pba.pba_dmat = sc->sc_dmat;
359 	pba.pba_dmat64 = NULL;
360 	pba.pba_pc = &mspcic_pc_tag;
361 	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
362 
363 	mspcic_pci_scan(sc->sc_node);
364 
365 	config_found(self, &pba, mspcic_print,
366 	    CFARGS(.devhandle = device_handle(self)));
367 }
368 
369 
370 static int
mspcic_print(void * args,const char * busname)371 mspcic_print(void *args, const char *busname)
372 {
373 
374 	if (busname == NULL)
375 		return (UNCONF);
376 	return (QUIET);
377 }
378 
379 
380 /*
381  * Get the PIL currently assigned for this interrupt input line.
382  */
383 int
mspcic_assigned_interrupt(int line)384 mspcic_assigned_interrupt(int line)
385 {
386 	unsigned int intrmap;
387 
388 	if (line < 0 || line > 7)
389 		return (-1);
390 
391 	if (line < 4) {
392 		intrmap = mspcic_read_2(pcic_intr_asgn_sel);
393 	} else {
394 		intrmap = mspcic_read_2(pcic_intr_asgn_sel_hi);
395 		line -= 4;
396 	}
397 	return ((intrmap >> (line * 4)) & 0xf);
398 }
399 
400 
401 /* ======================================================================
402  *
403  *			  BUS space methods
404  */
405 
406 static inline void
mspcic_pci_map_from_reg(struct mspcic_pci_map * m,uint8_t sbar,uint8_t pbar,uint8_t sizemask)407 mspcic_pci_map_from_reg(struct mspcic_pci_map *m,
408 			uint8_t sbar, uint8_t pbar, uint8_t sizemask)
409 {
410 	m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24);
411 	m->pcibase = pbar << 24;
412 	m->size = ~((0xf0 | sizemask) << 24) + 1;
413 }
414 
415 
416 /* does [al, ar) and [bl, br) overlap? */
417 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar)))
418 
419 /* does map "m" overlap with fixed mapping region? */
420 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \
421 				0x30000000, 0x31000000)
422 
423 /* does map "ma" overlap map "mb" (possibly NULL)? */
424 #define OVERLAP_MAP(ma, mb) \
425 	((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \
426 				 (mb)->sysbase, (mb)->sysbase + (mb)->size))
427 
428 /*
429  * Init auxiliary paddr->pci maps.
430  */
431 static void
mspcic_init_maps(void)432 mspcic_init_maps(void)
433 {
434 	struct mspcic_pci_map *m0, *m1, *io;
435 	int nmem, nio;
436 
437 #ifdef DEBUG
438 	printf("mspcic0: SMBAR0 %02x  PMBAR0 %02x  MSIZE0 %02x\n",
439 	       mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
440 	       mspcic_read_1(pcic_msize0));
441 	printf("mspcic0: SMBAR1 %02x  PMBAR1 %02x  MSIZE1 %02x\n",
442 	       mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
443 	       mspcic_read_1(pcic_msize1));
444 	printf("mspcic0: SIBAR  %02x  PIBAR  %02x  IOSIZE %02x\n",
445 	       mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
446 	       mspcic_read_1(pcic_iosize));
447 #endif
448 	nmem = nio = 1;
449 
450 	m0 = &mspcic_pci_memmap[nmem];
451 	mspcic_pci_map_from_reg(m0,
452 		mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0),
453 		mspcic_read_1(pcic_msize0));
454 	if (OVERLAP_FIXED(m0))
455 		m0 = NULL;
456 	else
457 		++nmem;
458 
459 	m1 = &mspcic_pci_memmap[nmem];
460 	mspcic_pci_map_from_reg(m1,
461 		mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1),
462 		mspcic_read_1(pcic_msize1));
463 	if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0))
464 		m1 = NULL;
465 	else
466 		++nmem;
467 
468 	io = &mspcic_pci_iomap[nio];
469 	mspcic_pci_map_from_reg(io,
470 		mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar),
471 		mspcic_read_1(pcic_iosize));
472 	if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1))
473 		io = NULL;
474 	else
475 		++nio;
476 
477 	mspcic_io_cookie.nmaps = nio;
478 	mspcic_mem_cookie.nmaps = nmem;
479 
480 #ifdef DEBUG
481 	mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed");
482 	mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed");
483 	if (m0) mspcic_pci_map_print(m0, "mem map0");
484 	if (m1) mspcic_pci_map_print(m1, "mem map1");
485 	if (io) mspcic_pci_map_print(io, "i/0 map");
486 #endif
487 }
488 
489 
490 #ifdef DEBUG
491 static void
mspcic_pci_map_print(struct mspcic_pci_map * m,const char * msg)492 mspcic_pci_map_print(struct mspcic_pci_map *m, const char *msg)
493 {
494 	printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n",
495 	       m->sysbase, m->sysbase + m->size - 1,
496 	       m->pcibase, m->pcibase + m->size - 1,
497 	       msg);
498 }
499 #endif
500 
501 
502 static bus_addr_t
mspcic_pci_map_find(struct mspcic_pci_map * m,int nmaps,bus_addr_t pciaddr,bus_size_t size)503 mspcic_pci_map_find(struct mspcic_pci_map *m, int nmaps,
504 		    bus_addr_t pciaddr, bus_size_t size)
505 {
506 	bus_size_t offset;
507 	int i;
508 
509 	for (i = 0; i < nmaps; ++i, ++m) {
510 		offset = pciaddr - m->pcibase;
511 		if (offset + size <= m->size)
512 			return (m->sysbase + offset);
513 	}
514 	return (0);
515 }
516 
517 
518 static int
mspcic_bus_map(bus_space_tag_t t,bus_addr_t ba,bus_size_t size,int flags,vaddr_t va,bus_space_handle_t * hp)519 mspcic_bus_map(bus_space_tag_t t, bus_addr_t ba, bus_size_t size,
520 	       int flags, vaddr_t va, bus_space_handle_t *hp)
521 {
522 	struct mspcic_cookie *c = t->cookie;
523 	bus_addr_t paddr;
524 
525 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size);
526 	if (paddr == 0)
527 		return (EINVAL);
528 	return (bus_space_map2(t->parent, paddr, size, flags, va, hp));
529 }
530 
531 
532 static paddr_t
mspcic_bus_mmap(bus_space_tag_t t,bus_addr_t ba,off_t off,int prot,int flags)533 mspcic_bus_mmap(bus_space_tag_t t, bus_addr_t ba, off_t off,
534 		int prot, int flags)
535 {
536 	struct mspcic_cookie *c = t->cookie;
537 	bus_addr_t paddr;
538 
539 	/* verify that phys to pci mapping for the target page exists */
540 	paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE);
541 	if (paddr == 0)
542 		return (-1);
543 
544 	return (bus_space_mmap(t->parent, paddr - off, off, prot, flags));
545 }
546 
547 
548 /*
549  * Install an interrupt handler.
550  *
551  * Bus-specific interrupt argument is 'line', an interrupt input line
552  * for ms-IIep.  The PIL for each line is programmable via pcic interrupt
553  * assignment select registers (but we use existing assignments).
554  */
555 static void *
mspcic_intr_establish(bus_space_tag_t t,int line,int ipl,int (* handler)(void *),void * arg,void (* fastvec)(void))556 mspcic_intr_establish(bus_space_tag_t t, int line, int ipl,
557 		      int (*handler)(void *), void *arg,
558 		      void (*fastvec)(void))
559 {
560 	struct intrhand *ih;
561 	int pil;
562 
563 	ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
564 
565 	/* use pil set-up by prom */
566 	pil = mspcic_assigned_interrupt(line);
567 	if (pil == -1)
568 		panic("mspcic_intr_establish: line %d", line);
569 
570 	ih->ih_fun = handler;
571 	ih->ih_arg = arg;
572 	intr_establish(pil, ipl, ih, fastvec, false);
573 
574 	return(ih);
575 }
576 
577 
578 static uint16_t
mspcic_bus_read_2(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset)579 mspcic_bus_read_2(bus_space_tag_t space, bus_space_handle_t handle,
580 		  bus_size_t offset)
581 {
582 	uint16_t val = *(volatile uint16_t *)(handle + offset);
583 
584 	return le16toh(val);
585 }
586 
587 
588 static uint32_t
mspcic_bus_read_4(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset)589 mspcic_bus_read_4(bus_space_tag_t space, bus_space_handle_t handle,
590 		  bus_size_t offset)
591 {
592 	uint32_t val = *(volatile uint32_t *)(handle + offset);
593 
594 	return le32toh(val);
595 }
596 
597 
598 static uint64_t
mspcic_bus_read_8(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset)599 mspcic_bus_read_8(bus_space_tag_t space, bus_space_handle_t handle,
600 		  bus_size_t offset)
601 {
602 	uint64_t val = *(volatile uint64_t *)(handle + offset);
603 
604 	return le64toh(val);
605 }
606 
607 
608 static void
mspcic_bus_write_2(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset,uint16_t value)609 mspcic_bus_write_2(bus_space_tag_t space, bus_space_handle_t handle,
610 		   bus_size_t offset, uint16_t value)
611 {
612 
613 	(*(volatile uint16_t *)(handle + offset)) = htole16(value);
614 }
615 
616 
617 static void
mspcic_bus_write_4(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset,uint32_t value)618 mspcic_bus_write_4(bus_space_tag_t space, bus_space_handle_t handle,
619 		   bus_size_t offset, uint32_t value)
620 {
621 
622 	(*(volatile uint32_t *)(handle + offset)) = htole32(value);
623 }
624 
625 
626 static void
mspcic_bus_write_8(bus_space_tag_t space,bus_space_handle_t handle,bus_size_t offset,uint64_t value)627 mspcic_bus_write_8(bus_space_tag_t space, bus_space_handle_t handle,
628 		   bus_size_t offset, uint64_t value)
629 {
630 
631 	(*(volatile uint64_t *)(handle + offset)) = htole64(value);
632 }
633 
634 
635 /* ======================================================================
636  *
637  *			     DMA methods
638  */
639 
640 static int
mspcic_dmamap_load(bus_dma_tag_t t,bus_dmamap_t map,void * buf,bus_size_t buflen,struct proc * p,int flags)641 mspcic_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map,
642 		   void *buf, bus_size_t buflen,
643 		   struct proc *p, int flags)
644 {
645 	pmap_t pmap;
646 	paddr_t pa;
647 
648 	if (p != NULL)
649 		pmap = p->p_vmspace->vm_map.pmap;
650 	else
651 		pmap = pmap_kernel();
652 
653 	if (!pmap_extract(pmap, (vaddr_t)buf, &pa))
654 		panic("mspcic_dmamap_load: dma memory not mapped");
655 
656 	/* we always use just one segment */
657 	map->dm_nsegs = 1;
658 	map->dm_segs[0].ds_addr = pa;
659 	map->dm_segs[0].ds_len = buflen;
660 	map->dm_mapsize = buflen;
661 
662 	return (0);
663 }
664 
665 static void
mspcic_dmamap_unload(bus_dma_tag_t t,bus_dmamap_t map)666 mspcic_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
667 {
668 
669 	/* Mark the mappings as invalid. */
670 	map->dm_mapsize = 0;
671 	map->dm_nsegs = 0;
672 }
673 
674 
675 static int
mspcic_dmamem_map(bus_dma_tag_t tag,bus_dma_segment_t * segs,int nsegs,size_t size,void ** kvap,int flags)676 mspcic_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
677 		  size_t size, void **kvap, int flags)
678 {
679 	struct pglist *mlist;
680 	struct vm_page *m;
681 	vaddr_t va;
682 	int pagesz = PAGE_SIZE;
683 	const uvm_flag_t kmflags =
684 	    (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0;
685 
686 	if (nsegs != 1)
687 		panic("mspcic_dmamem_map: nsegs = %d", nsegs);
688 
689 	size = round_page(size);
690 
691 	va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags);
692 	if (va == 0)
693 		return (ENOMEM);
694 
695 	segs[0]._ds_va = va;
696 	*kvap = (void *)va;
697 
698 	/*
699 	 * Map the pages allocated in _bus_dmamem_alloc()
700 	 * to the kernel virtual address space.
701 	 */
702 	mlist = segs[0]._ds_mlist;
703 	TAILQ_FOREACH(m, mlist, pageq.queue) {
704 		paddr_t pa;
705 
706 		if (size == 0)
707 			panic("mspcic_dmamem_map: size botch");
708 
709 		pa = VM_PAGE_TO_PHYS(m);
710 		pmap_kenter_pa(va,
711 		    pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE, 0);
712 		va += pagesz;
713 		size -= pagesz;
714 	}
715 	pmap_update(pmap_kernel());
716 
717 	return (0);
718 }
719