xref: /netbsd-src/sys/arch/sh3/dev/shpcic.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: shpcic.c,v 1.21 2021/04/24 23:36:48 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (C) 2005 NONAKA Kimihiro <nonaka@netbsd.org>
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: shpcic.c,v 1.21 2021/04/24 23:36:48 thorpej Exp $");
30 
31 #include "opt_pci.h"
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/device.h>
37 #include <sys/malloc.h>
38 
39 #include <dev/pci/pcireg.h>
40 #include <dev/pci/pcivar.h>
41 #include <dev/pci/pciconf.h>
42 #include <dev/pci/pcidevs.h>
43 
44 #include <sh3/bscreg.h>
45 #include <sh3/cache.h>
46 #include <sh3/exception.h>
47 #include <sh3/pcicreg.h>
48 
49 #include <sys/bus.h>
50 #include <machine/intr.h>
51 #include <machine/pci_machdep.h>
52 
53 
54 #if defined(DEBUG) && !defined(SHPCIC_DEBUG)
55 #define SHPCIC_DEBUG 0
56 #endif
57 #if defined(SHPCIC_DEBUG)
58 int shpcic_debug = SHPCIC_DEBUG + 0;
59 #define	DPRINTF(arg)	if (shpcic_debug) printf arg
60 #else
61 #define	DPRINTF(arg)
62 #endif
63 
64 #define	PCI_MODE1_ENABLE	0x80000000UL
65 
66 
67 static int	shpcic_match(device_t, cfdata_t, void *);
68 static void	shpcic_attach(device_t, device_t, void *);
69 
70 CFATTACH_DECL_NEW(shpcic, 0,
71     shpcic_match, shpcic_attach, NULL, NULL);
72 
73 
74 /* There can be only one. */
75 static int shpcic_found = 0;
76 
77 /* PCIC intr priotiry */
78 static int shpcic_intr_priority[2] = { IPL_BIO, IPL_BIO };
79 
80 
81 static int
82 shpcic_match(device_t parent, cfdata_t cf, void *aux)
83 {
84 	pcireg_t id;
85 
86 	if (shpcic_found)
87 		return (0);
88 
89 	switch (cpu_product) {
90 	case CPU_PRODUCT_7751:
91 	case CPU_PRODUCT_7751R:
92 		break;
93 
94 	default:
95 		return (0);
96 	}
97 
98 
99 	id = _reg_read_4(SH4_PCICONF0);
100 
101 	switch (PCI_VENDOR(id)) {
102 	case PCI_VENDOR_HITACHI:
103 		break;
104 
105 	default:
106 		return (0);
107 	}
108 
109 
110 	switch (PCI_PRODUCT(id)) {
111 	case PCI_PRODUCT_HITACHI_SH7751: /* FALLTHROUGH */
112 	case PCI_PRODUCT_HITACHI_SH7751R:
113 		break;
114 
115 	default:
116 		return (0);
117 	}
118 
119 	if (_reg_read_2(SH4_BCR2) & BCR2_PORTEN)
120 		return (0);
121 
122 	return (1);
123 }
124 
125 static void
126 shpcic_attach(device_t parent, device_t self, void *aux)
127 {
128 	struct pcibus_attach_args pba;
129 	pcireg_t id, class;
130 	char devinfo[256];
131 
132 	shpcic_found = 1;
133 
134 	aprint_naive("\n");
135 
136 	id = _reg_read_4(SH4_PCICONF0);
137 	class = _reg_read_4(SH4_PCICONF2);
138 	pci_devinfo(id, class, 1, devinfo, sizeof(devinfo));
139 	aprint_normal(": %s\n", devinfo);
140 
141 	/* allow PCIC request */
142 	_reg_write_4(SH4_BCR1, _reg_read_4(SH4_BCR1) | BCR1_BREQEN);
143 
144 	/* Initialize PCIC */
145 	_reg_write_4(SH4_PCICR, PCICR_BASE | PCICR_RSTCTL);
146 	delay(10 * 1000);
147 	_reg_write_4(SH4_PCICR, PCICR_BASE);
148 
149 	/* Class: Host-Bridge */
150 	_reg_write_4(SH4_PCICONF2,
151 	    PCI_CLASS_CODE(PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_HOST, 0x00));
152 
153 #if !defined(DONT_INIT_PCIBSC)
154 #if defined(PCIBCR_BCR1_VAL)
155 	_reg_write_4(SH4_PCIBCR1, PCIBCR_BCR1_VAL);
156 #else
157 	_reg_write_4(SH4_PCIBCR1, _reg_read_4(SH4_BCR1) | BCR1_MASTER);
158 #endif
159 #if defined(PCIBCR_BCR2_VAL)
160 	_reg_write_4(SH4_PCIBCR2, PCIBCR_BCR2_VAL);
161 #else
162 	_reg_write_4(SH4_PCIBCR2, _reg_read_2(SH4_BCR2));
163 #endif
164 #if defined(SH4) && defined(SH7751R)
165 	if (cpu_product == CPU_PRODUCT_7751R) {
166 #if defined(PCIBCR_BCR3_VAL)
167 		_reg_write_4(SH4_PCIBCR3, PCIBCR_BCR3_VAL);
168 #else
169 		_reg_write_4(SH4_PCIBCR3, _reg_read_2(SH4_BCR3));
170 #endif
171 	}
172 #endif	/* SH4 && SH7751R && PCIBCR_BCR3_VAL */
173 #if defined(PCIBCR_WCR1_VAL)
174 	_reg_write_4(SH4_PCIWCR1, PCIBCR_WCR1_VAL);
175 #else
176 	_reg_write_4(SH4_PCIWCR1, _reg_read_4(SH4_WCR1));
177 #endif
178 #if defined(PCIBCR_WCR2_VAL)
179 	_reg_write_4(SH4_PCIWCR2, PCIBCR_WCR2_VAL);
180 #else
181 	_reg_write_4(SH4_PCIWCR2, _reg_read_4(SH4_WCR2));
182 #endif
183 #if defined(PCIBCR_WCR3_VAL)
184 	_reg_write_4(SH4_PCIWCR3, PCIBCR_WCR3_VAL);
185 #else
186 	_reg_write_4(SH4_PCIWCR3, _reg_read_4(SH4_WCR3));
187 #endif
188 #if defined(PCIBCR_MCR_VAL)
189 	_reg_write_4(SH4_PCIMCR, PCIBCR_MCR_VAL);
190 #else
191 	_reg_write_4(SH4_PCIMCR, _reg_read_4(SH4_MCR));
192 #endif
193 #endif	/* !DONT_INIT_PCIBSC */
194 
195 	/* set PCI I/O, memory base address */
196 	_reg_write_4(SH4_PCIIOBR, SH4_PCIC_IO);
197 	_reg_write_4(SH4_PCIMBR, SH4_PCIC_MEM);
198 
199 	/* set PCI local address 0 */
200 	_reg_write_4(SH4_PCILSR0, (64 - 1) << 20);
201 	_reg_write_4(SH4_PCILAR0, 0xac000000);
202 	_reg_write_4(SH4_PCICONF5, 0xac000000);
203 
204 	/* set PCI local address 1 */
205 	_reg_write_4(SH4_PCILSR1, (64 - 1) << 20);
206 	_reg_write_4(SH4_PCILAR1, 0xac000000);
207 	_reg_write_4(SH4_PCICONF6, 0x8c000000);
208 
209 	/* Enable I/O, memory, bus-master */
210 	_reg_write_4(SH4_PCICONF1, PCI_COMMAND_IO_ENABLE
211 	                           | PCI_COMMAND_MEM_ENABLE
212 	                           | PCI_COMMAND_MASTER_ENABLE
213 	                           | PCI_COMMAND_STEPPING_ENABLE
214 				   | PCI_STATUS_DEVSEL_MEDIUM);
215 
216 	/* Initialize done. */
217 	_reg_write_4(SH4_PCICR, PCICR_BASE | PCICR_CFINIT);
218 
219 	/* set PCI controller interrupt priority */
220 	intpri_intr_priority(SH4_INTEVT_PCIERR, shpcic_intr_priority[0]);
221 	intpri_intr_priority(SH4_INTEVT_PCISERR, shpcic_intr_priority[1]);
222 
223 	/* PCI bus */
224 #ifdef PCI_NETBSD_CONFIGURE
225 	struct pciconf_resources *pcires = pciconf_resource_init();
226 
227 	pciconf_resource_add(pcires, PCICONF_RESOURCE_IO,
228 	    SH4_PCIC_IO, SH4_PCIC_IO_SIZE);
229 	pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM,
230 	    SH4_PCIC_MEM, SH4_PCIC_MEM_SIZE);
231 
232 	pci_configure_bus(NULL, pcires, 0, sh_cache_line_size);
233 
234 	pciconf_resource_fini(pcires);
235 #endif
236 
237 	/* PCI bus */
238 	memset(&pba, 0, sizeof(pba));
239 	pba.pba_iot = shpcic_get_bus_io_tag();
240 	pba.pba_memt = shpcic_get_bus_mem_tag();
241 	pba.pba_dmat = shpcic_get_bus_dma_tag();
242 	pba.pba_dmat64 = NULL;
243 	pba.pba_pc = NULL;
244 	pba.pba_bus = 0;
245 	pba.pba_bridgetag = NULL;
246 	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
247 	config_found(self, &pba, NULL, CFARG_EOL);
248 }
249 
250 int
251 shpcic_bus_maxdevs(void *v, int busno)
252 {
253 
254 	/*
255 	 * Bus number is irrelevant.  Configuration Mechanism 1 is in
256 	 * use, can have devices 0-32 (i.e. the `normal' range).
257 	 */
258 	return (32);
259 }
260 
261 pcitag_t
262 shpcic_make_tag(void *v, int bus, int device, int function)
263 {
264 	pcitag_t tag;
265 
266 	if (bus >= 256 || device >= 32 || function >= 8)
267 		panic("pci_make_tag: bad request");
268 
269 	tag = PCI_MODE1_ENABLE |
270 		    (bus << 16) | (device << 11) | (function << 8);
271 
272 	return (tag);
273 }
274 
275 void
276 shpcic_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
277 {
278 
279 	if (bp != NULL)
280 		*bp = (tag >> 16) & 0xff;
281 	if (dp != NULL)
282 		*dp = (tag >> 11) & 0x1f;
283 	if (fp != NULL)
284 		*fp = (tag >> 8) & 0x7;
285 }
286 
287 pcireg_t
288 shpcic_conf_read(void *v, pcitag_t tag, int reg)
289 {
290 	pcireg_t data;
291 	int s;
292 
293 	if ((unsigned int)reg >= PCI_CONF_SIZE)
294 		return (pcireg_t) -1;
295 
296 	s = splhigh();
297 	_reg_write_4(SH4_PCIPAR, tag | reg);
298 	data = _reg_read_4(SH4_PCIPDR);
299 	_reg_write_4(SH4_PCIPAR, 0);
300 	splx(s);
301 
302 	return data;
303 }
304 
305 void
306 shpcic_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
307 {
308 	int s;
309 
310 	if ((unsigned int)reg >= PCI_CONF_SIZE)
311 		return;
312 
313 	s = splhigh();
314 	_reg_write_4(SH4_PCIPAR, tag | reg);
315 	_reg_write_4(SH4_PCIPDR, data);
316 	_reg_write_4(SH4_PCIPAR, 0);
317 	splx(s);
318 }
319 
320 int
321 shpcic_set_intr_priority(int intr, int level)
322 {
323 	int evtcode;
324 
325 	if ((intr != 0) && (intr != 1)) {
326 		return (-1);
327 	}
328 	if ((level < IPL_NONE) || (level > IPL_HIGH)) {
329 		return (-1);
330 	}
331 
332 	if (intr == 0) {
333 		evtcode = SH4_INTEVT_PCIERR;
334 	} else {
335 		evtcode = SH4_INTEVT_PCISERR;
336 	}
337 
338 	intpri_intr_priority(evtcode, shpcic_intr_priority[intr]);
339 	shpcic_intr_priority[intr] = level;
340 
341 	return (0);
342 }
343 
344 void *
345 shpcic_intr_establish(int evtcode, int (*ih_func)(void *), void *ih_arg)
346 {
347 	int level;
348 
349 	switch (evtcode) {
350 	case SH4_INTEVT_PCISERR:
351 		level = shpcic_intr_priority[1];
352 		break;
353 
354 	case SH4_INTEVT_PCIDMA3:
355 	case SH4_INTEVT_PCIDMA2:
356 	case SH4_INTEVT_PCIDMA1:
357 	case SH4_INTEVT_PCIDMA0:
358 	case SH4_INTEVT_PCIPWON:
359 	case SH4_INTEVT_PCIPWDWN:
360 	case SH4_INTEVT_PCIERR:
361 		level = shpcic_intr_priority[0];
362 		break;
363 
364 	default:
365 		printf("shpcic_intr_establish: unknown evtcode = 0x%08x\n",
366 		    evtcode);
367 		return NULL;
368 	}
369 
370 	return intc_intr_establish(evtcode, IST_LEVEL, level, ih_func, ih_arg);
371 }
372 
373 void
374 shpcic_intr_disestablish(void *ih)
375 {
376 
377 	intc_intr_disestablish(ih);
378 }
379 
380 /*
381  * shpcic bus space
382  */
383 int
384 shpcic_iomem_map(void *v, bus_addr_t bpa, bus_size_t size,
385     int flags, bus_space_handle_t *bshp)
386 {
387 
388 	*bshp = (bus_space_handle_t)bpa;
389 
390 	return (0);
391 }
392 
393 void
394 shpcic_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
395 {
396 
397 	/* Nothing to do */
398 }
399 
400 int
401 shpcic_iomem_subregion(void *v, bus_space_handle_t bsh,
402     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
403 {
404 
405 	*nbshp = bsh + offset;
406 
407 	return (0);
408 }
409 
410 int
411 shpcic_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
412     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
413     bus_addr_t *bpap, bus_space_handle_t *bshp)
414 {
415 
416 	*bshp = *bpap = rstart;
417 
418 	return (0);
419 }
420 
421 void
422 shpcic_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size)
423 {
424 
425 	/* Nothing to do */
426 }
427 
428 paddr_t
429 shpcic_iomem_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags)
430 {
431 
432 	return (paddr_t)-1;
433 }
434 
435 /*
436  * shpcic bus space io/mem read/write
437  */
438 /* read */
439 static inline uint8_t __shpcic_io_read_1(bus_space_handle_t bsh,
440     bus_size_t offset);
441 static inline uint16_t __shpcic_io_read_2(bus_space_handle_t bsh,
442     bus_size_t offset);
443 static inline uint32_t __shpcic_io_read_4(bus_space_handle_t bsh,
444     bus_size_t offset);
445 static inline uint8_t __shpcic_mem_read_1(bus_space_handle_t bsh,
446     bus_size_t offset);
447 static inline uint16_t __shpcic_mem_read_2(bus_space_handle_t bsh,
448     bus_size_t offset);
449 static inline uint32_t __shpcic_mem_read_4(bus_space_handle_t bsh,
450     bus_size_t offset);
451 
452 static inline uint8_t
453 __shpcic_io_read_1(bus_space_handle_t bsh, bus_size_t offset)
454 {
455 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
456 
457 	return *(volatile uint8_t *)(SH4_PCIC_IO + adr);
458 }
459 
460 static inline uint16_t
461 __shpcic_io_read_2(bus_space_handle_t bsh, bus_size_t offset)
462 {
463 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
464 
465 	return *(volatile uint16_t *)(SH4_PCIC_IO + adr);
466 }
467 
468 static inline uint32_t
469 __shpcic_io_read_4(bus_space_handle_t bsh, bus_size_t offset)
470 {
471 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
472 
473 	return *(volatile uint32_t *)(SH4_PCIC_IO + adr);
474 }
475 
476 static inline uint8_t
477 __shpcic_mem_read_1(bus_space_handle_t bsh, bus_size_t offset)
478 {
479 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
480 
481 	return *(volatile uint8_t *)(SH4_PCIC_MEM + adr);
482 }
483 
484 static inline uint16_t
485 __shpcic_mem_read_2(bus_space_handle_t bsh, bus_size_t offset)
486 {
487 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
488 
489 	return *(volatile uint16_t *)(SH4_PCIC_MEM + adr);
490 }
491 
492 static inline uint32_t
493 __shpcic_mem_read_4(bus_space_handle_t bsh, bus_size_t offset)
494 {
495 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
496 
497 	return *(volatile uint32_t *)(SH4_PCIC_MEM + adr);
498 }
499 
500 /*
501  * read single
502  */
503 uint8_t
504 shpcic_io_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset)
505 {
506 	uint8_t value;
507 
508 	value = __shpcic_io_read_1(bsh, offset);
509 
510 	return value;
511 }
512 
513 uint16_t
514 shpcic_io_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset)
515 {
516 	uint16_t value;
517 
518 	value = __shpcic_io_read_2(bsh, offset);
519 
520 	return value;
521 }
522 
523 uint32_t
524 shpcic_io_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset)
525 {
526 	uint32_t value;
527 
528 	value = __shpcic_io_read_4(bsh, offset);
529 
530 	return value;
531 }
532 
533 uint8_t
534 shpcic_mem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset)
535 {
536 	uint8_t value;
537 
538 	value = __shpcic_mem_read_1(bsh, offset);
539 
540 	return value;
541 }
542 
543 uint16_t
544 shpcic_mem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset)
545 {
546 	uint16_t value;
547 
548 	value = __shpcic_mem_read_2(bsh, offset);
549 
550 	return value;
551 }
552 
553 uint32_t
554 shpcic_mem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset)
555 {
556 	uint32_t value;
557 
558 	value = __shpcic_mem_read_4(bsh, offset);
559 
560 	return value;
561 }
562 
563 /*
564  * read multi
565  */
566 void
567 shpcic_io_read_multi_1(void *v, bus_space_handle_t bsh,
568     bus_size_t offset, uint8_t *addr, bus_size_t count)
569 {
570 
571 	while (count--) {
572 		*addr++ = __shpcic_io_read_1(bsh, offset);
573 	}
574 }
575 
576 void
577 shpcic_io_read_multi_2(void *v, bus_space_handle_t bsh,
578     bus_size_t offset, uint16_t *addr, bus_size_t count)
579 {
580 
581 	while (count--) {
582 		*addr++ = __shpcic_io_read_2(bsh, offset);
583 	}
584 }
585 
586 void
587 shpcic_io_read_multi_4(void *v, bus_space_handle_t bsh,
588     bus_size_t offset, uint32_t *addr, bus_size_t count)
589 {
590 
591 	while (count--) {
592 		*addr++ = __shpcic_io_read_4(bsh, offset);
593 	}
594 }
595 
596 void
597 shpcic_mem_read_multi_1(void *v, bus_space_handle_t bsh,
598     bus_size_t offset, uint8_t *addr, bus_size_t count)
599 {
600 
601 	while (count--) {
602 		*addr++ = __shpcic_mem_read_1(bsh, offset);
603 	}
604 }
605 
606 void
607 shpcic_mem_read_multi_2(void *v, bus_space_handle_t bsh,
608     bus_size_t offset, uint16_t *addr, bus_size_t count)
609 {
610 
611 	while (count--) {
612 		*addr++ = __shpcic_mem_read_2(bsh, offset);
613 	}
614 }
615 
616 void
617 shpcic_mem_read_multi_4(void *v, bus_space_handle_t bsh,
618     bus_size_t offset, uint32_t *addr, bus_size_t count)
619 {
620 
621 	while (count--) {
622 		*addr++ = __shpcic_mem_read_4(bsh, offset);
623 	}
624 }
625 
626 /*
627  *
628  * read region
629  */
630 void
631 shpcic_io_read_region_1(void *v, bus_space_handle_t bsh,
632     bus_size_t offset, uint8_t *addr, bus_size_t count)
633 {
634 
635 	while (count--) {
636 		*addr++ = __shpcic_io_read_1(bsh, offset);
637 		offset += 1;
638 	}
639 }
640 
641 void
642 shpcic_io_read_region_2(void *v, bus_space_handle_t bsh,
643     bus_size_t offset, uint16_t *addr, bus_size_t count)
644 {
645 
646 	while (count--) {
647 		*addr++ = __shpcic_io_read_2(bsh, offset);
648 		offset += 2;
649 	}
650 }
651 
652 void
653 shpcic_io_read_region_4(void *v, bus_space_handle_t bsh,
654     bus_size_t offset, uint32_t *addr, bus_size_t count)
655 {
656 
657 	while (count--) {
658 		*addr++ = __shpcic_io_read_4(bsh, offset);
659 		offset += 4;
660 	}
661 }
662 
663 void
664 shpcic_mem_read_region_1(void *v, bus_space_handle_t bsh,
665     bus_size_t offset, uint8_t *addr, bus_size_t count)
666 {
667 
668 	while (count--) {
669 		*addr++ = __shpcic_mem_read_1(bsh, offset);
670 		offset += 1;
671 	}
672 }
673 
674 void
675 shpcic_mem_read_region_2(void *v, bus_space_handle_t bsh,
676     bus_size_t offset, uint16_t *addr, bus_size_t count)
677 {
678 
679 	while (count--) {
680 		*addr++ = __shpcic_mem_read_2(bsh, offset);
681 		offset += 2;
682 	}
683 }
684 
685 void
686 shpcic_mem_read_region_4(void *v, bus_space_handle_t bsh,
687     bus_size_t offset, uint32_t *addr, bus_size_t count)
688 {
689 
690 	while (count--) {
691 		*addr++ = __shpcic_mem_read_4(bsh, offset);
692 		offset += 4;
693 	}
694 }
695 
696 /* write */
697 static inline void __shpcic_io_write_1(bus_space_handle_t bsh,
698     bus_size_t offset, uint8_t value);
699 static inline void __shpcic_io_write_2(bus_space_handle_t bsh,
700     bus_size_t offset, uint16_t value);
701 static inline void __shpcic_io_write_4(bus_space_handle_t bsh,
702     bus_size_t offset, uint32_t value);
703 static inline void __shpcic_mem_write_1(bus_space_handle_t bsh,
704     bus_size_t offset, uint8_t value);
705 static inline void __shpcic_mem_write_2(bus_space_handle_t bsh,
706     bus_size_t offset, uint16_t value);
707 static inline void __shpcic_mem_write_4(bus_space_handle_t bsh,
708     bus_size_t offset, uint32_t value);
709 
710 static inline void
711 __shpcic_io_write_1(bus_space_handle_t bsh, bus_size_t offset,
712     uint8_t value)
713 {
714 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
715 
716 	*(volatile uint8_t *)(SH4_PCIC_IO + adr) = value;
717 }
718 
719 static inline void
720 __shpcic_io_write_2(bus_space_handle_t bsh, bus_size_t offset,
721     uint16_t value)
722 {
723 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
724 
725 	*(volatile uint16_t *)(SH4_PCIC_IO + adr) = value;
726 }
727 
728 static inline void
729 __shpcic_io_write_4(bus_space_handle_t bsh, bus_size_t offset,
730     uint32_t value)
731 {
732 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK;
733 
734 	*(volatile uint32_t *)(SH4_PCIC_IO + adr) = value;
735 }
736 
737 static inline void
738 __shpcic_mem_write_1(bus_space_handle_t bsh, bus_size_t offset,
739     uint8_t value)
740 {
741 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
742 
743 	*(volatile uint8_t *)(SH4_PCIC_MEM + adr) = value;
744 }
745 
746 static inline void
747 __shpcic_mem_write_2(bus_space_handle_t bsh, bus_size_t offset,
748     uint16_t value)
749 {
750 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
751 
752 	*(volatile uint16_t *)(SH4_PCIC_MEM + adr) = value;
753 }
754 
755 static inline void
756 __shpcic_mem_write_4(bus_space_handle_t bsh, bus_size_t offset,
757     uint32_t value)
758 {
759 	u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK;
760 
761 	*(volatile uint32_t *)(SH4_PCIC_MEM + adr) = value;
762 }
763 
764 /*
765  * write single
766  */
767 void
768 shpcic_io_write_1(void *v, bus_space_handle_t bsh,
769     bus_size_t offset, uint8_t value)
770 {
771 
772 	__shpcic_io_write_1(bsh, offset, value);
773 }
774 
775 void
776 shpcic_io_write_2(void *v, bus_space_handle_t bsh,
777     bus_size_t offset, uint16_t value)
778 {
779 
780 	__shpcic_io_write_2(bsh, offset, value);
781 }
782 
783 void
784 shpcic_io_write_4(void *v, bus_space_handle_t bsh,
785     bus_size_t offset, uint32_t value)
786 {
787 
788 	__shpcic_io_write_4(bsh, offset, value);
789 }
790 
791 void
792 shpcic_mem_write_1(void *v, bus_space_handle_t bsh,
793     bus_size_t offset, uint8_t value)
794 {
795 
796 	__shpcic_mem_write_1(bsh, offset, value);
797 }
798 
799 void
800 shpcic_mem_write_2(void *v, bus_space_handle_t bsh,
801     bus_size_t offset, uint16_t value)
802 {
803 
804 	__shpcic_mem_write_2(bsh, offset, value);
805 }
806 
807 void
808 shpcic_mem_write_4(void *v, bus_space_handle_t bsh,
809     bus_size_t offset, uint32_t value)
810 {
811 
812 	__shpcic_mem_write_4(bsh, offset, value);
813 }
814 
815 /*
816  * write multi
817  */
818 void
819 shpcic_io_write_multi_1(void *v, bus_space_handle_t bsh,
820     bus_size_t offset, const uint8_t *addr, bus_size_t count)
821 {
822 
823 	while (count--) {
824 		__shpcic_io_write_1(bsh, offset, *addr++);
825 	}
826 }
827 
828 void
829 shpcic_io_write_multi_2(void *v, bus_space_handle_t bsh,
830     bus_size_t offset, const uint16_t *addr, bus_size_t count)
831 {
832 
833 	while (count--) {
834 		__shpcic_io_write_2(bsh, offset, *addr++);
835 	}
836 }
837 
838 void
839 shpcic_io_write_multi_4(void *v, bus_space_handle_t bsh,
840     bus_size_t offset, const uint32_t *addr, bus_size_t count)
841 {
842 
843 	while (count--) {
844 		__shpcic_io_write_4(bsh, offset, *addr++);
845 	}
846 }
847 
848 void
849 shpcic_mem_write_multi_1(void *v, bus_space_handle_t bsh,
850     bus_size_t offset, const uint8_t *addr, bus_size_t count)
851 {
852 
853 	while (count--) {
854 		__shpcic_mem_write_1(bsh, offset, *addr++);
855 	}
856 }
857 
858 void
859 shpcic_mem_write_multi_2(void *v, bus_space_handle_t bsh,
860     bus_size_t offset, const uint16_t *addr, bus_size_t count)
861 {
862 
863 	while (count--) {
864 		__shpcic_mem_write_2(bsh, offset, *addr++);
865 	}
866 }
867 
868 void
869 shpcic_mem_write_multi_4(void *v, bus_space_handle_t bsh,
870     bus_size_t offset, const uint32_t *addr, bus_size_t count)
871 {
872 
873 	while (count--) {
874 		__shpcic_mem_write_4(bsh, offset, *addr++);
875 	}
876 }
877 
878 /*
879  * write region
880  */
881 void
882 shpcic_io_write_region_1(void *v, bus_space_handle_t bsh,
883     bus_size_t offset, const uint8_t *addr, bus_size_t count)
884 {
885 
886 	while (count--) {
887 		__shpcic_io_write_1(bsh, offset, *addr++);
888 		offset += 1;
889 	}
890 }
891 
892 void
893 shpcic_io_write_region_2(void *v, bus_space_handle_t bsh,
894     bus_size_t offset, const uint16_t *addr, bus_size_t count)
895 {
896 
897 	while (count--) {
898 		__shpcic_io_write_2(bsh, offset, *addr++);
899 		offset += 2;
900 	}
901 }
902 
903 void
904 shpcic_io_write_region_4(void *v, bus_space_handle_t bsh,
905     bus_size_t offset, const uint32_t *addr, bus_size_t count)
906 {
907 
908 	while (count--) {
909 		__shpcic_io_write_4(bsh, offset, *addr++);
910 		offset += 4;
911 	}
912 }
913 
914 void
915 shpcic_mem_write_region_1(void *v, bus_space_handle_t bsh,
916     bus_size_t offset, const uint8_t *addr, bus_size_t count)
917 {
918 
919 	while (count--) {
920 		__shpcic_mem_write_1(bsh, offset, *addr++);
921 		offset += 1;
922 	}
923 }
924 
925 void
926 shpcic_mem_write_region_2(void *v, bus_space_handle_t bsh,
927     bus_size_t offset, const uint16_t *addr, bus_size_t count)
928 {
929 
930 	while (count--) {
931 		__shpcic_mem_write_2(bsh, offset, *addr++);
932 		offset += 2;
933 	}
934 }
935 
936 void
937 shpcic_mem_write_region_4(void *v, bus_space_handle_t bsh,
938     bus_size_t offset, const uint32_t *addr, bus_size_t count)
939 {
940 
941 	while (count--) {
942 		__shpcic_mem_write_4(bsh, offset, *addr++);
943 		offset += 4;
944 	}
945 }
946 
947 /*
948  * set multi
949  */
950 void
951 shpcic_io_set_multi_1(void *v, bus_space_handle_t bsh,
952     bus_size_t offset, uint8_t value, bus_size_t count)
953 {
954 
955 	while (count--) {
956 		__shpcic_io_write_1(bsh, offset, value);
957 	}
958 }
959 
960 void
961 shpcic_io_set_multi_2(void *v, bus_space_handle_t bsh,
962     bus_size_t offset, uint16_t value, bus_size_t count)
963 {
964 
965 	while (count--) {
966 		__shpcic_io_write_2(bsh, offset, value);
967 	}
968 }
969 
970 void
971 shpcic_io_set_multi_4(void *v, bus_space_handle_t bsh,
972     bus_size_t offset, uint32_t value, bus_size_t count)
973 {
974 
975 	while (count--) {
976 		__shpcic_io_write_4(bsh, offset, value);
977 	}
978 }
979 
980 void
981 shpcic_mem_set_multi_1(void *v, bus_space_handle_t bsh,
982     bus_size_t offset, uint8_t value, bus_size_t count)
983 {
984 
985 	while (count--) {
986 		__shpcic_mem_write_1(bsh, offset, value);
987 	}
988 }
989 
990 void
991 shpcic_mem_set_multi_2(void *v, bus_space_handle_t bsh,
992     bus_size_t offset, uint16_t value, bus_size_t count)
993 {
994 
995 	while (count--) {
996 		__shpcic_mem_write_2(bsh, offset, value);
997 	}
998 }
999 
1000 void
1001 shpcic_mem_set_multi_4(void *v, bus_space_handle_t bsh,
1002     bus_size_t offset, uint32_t value, bus_size_t count)
1003 {
1004 
1005 	while (count--) {
1006 		__shpcic_mem_write_4(bsh, offset, value);
1007 	}
1008 }
1009 
1010 /*
1011  * set region
1012  */
1013 void
1014 shpcic_io_set_region_1(void *v, bus_space_handle_t bsh,
1015     bus_size_t offset, uint8_t value, bus_size_t count)
1016 {
1017 
1018 	while (count--) {
1019 		__shpcic_io_write_1(bsh, offset, value);
1020 		offset += 1;
1021 	}
1022 }
1023 
1024 void
1025 shpcic_io_set_region_2(void *v, bus_space_handle_t bsh,
1026     bus_size_t offset, uint16_t value, bus_size_t count)
1027 {
1028 
1029 	while (count--) {
1030 		__shpcic_io_write_2(bsh, offset, value);
1031 		offset += 2;
1032 	}
1033 }
1034 
1035 void
1036 shpcic_io_set_region_4(void *v, bus_space_handle_t bsh,
1037     bus_size_t offset, uint32_t value, bus_size_t count)
1038 {
1039 
1040 	while (count--) {
1041 		__shpcic_io_write_4(bsh, offset, value);
1042 		offset += 4;
1043 	}
1044 }
1045 
1046 void
1047 shpcic_mem_set_region_1(void *v, bus_space_handle_t bsh,
1048     bus_size_t offset, uint8_t value, bus_size_t count)
1049 {
1050 
1051 	while (count--) {
1052 		__shpcic_mem_write_1(bsh, offset, value);
1053 		offset += 1;
1054 	}
1055 }
1056 
1057 void
1058 shpcic_mem_set_region_2(void *v, bus_space_handle_t bsh,
1059     bus_size_t offset, uint16_t value, bus_size_t count)
1060 {
1061 
1062 	while (count--) {
1063 		__shpcic_mem_write_2(bsh, offset, value);
1064 		offset += 2;
1065 	}
1066 }
1067 
1068 void
1069 shpcic_mem_set_region_4(void *v, bus_space_handle_t bsh,
1070     bus_size_t offset, uint32_t value, bus_size_t count)
1071 {
1072 
1073 	while (count--) {
1074 		__shpcic_mem_write_4(bsh, offset, value);
1075 		offset += 4;
1076 	}
1077 }
1078 
1079 /*
1080  * copy region
1081  */
1082 void
1083 shpcic_io_copy_region_1(void *v, bus_space_handle_t bsh1,
1084     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1085 {
1086 	u_long addr1 = bsh1 + off1;
1087 	u_long addr2 = bsh2 + off2;
1088 	uint8_t value;
1089 
1090 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1091 		while (count--) {
1092 			value = __shpcic_io_read_1(bsh1, off1);
1093 			__shpcic_io_write_1(bsh2, off2, value);
1094 			off1 += 1;
1095 			off2 += 1;
1096 		}
1097 	} else {		/* dest after src: copy backwards */
1098 		off1 += (count - 1) * 1;
1099 		off2 += (count - 1) * 1;
1100 		while (count--) {
1101 			value = __shpcic_io_read_1(bsh1, off1);
1102 			__shpcic_io_write_1(bsh2, off2, value);
1103 			off1 -= 1;
1104 			off2 -= 1;
1105 		}
1106 	}
1107 }
1108 
1109 void
1110 shpcic_io_copy_region_2(void *v, bus_space_handle_t bsh1,
1111     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1112 {
1113 	u_long addr1 = bsh1 + off1;
1114 	u_long addr2 = bsh2 + off2;
1115 	uint16_t value;
1116 
1117 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1118 		while (count--) {
1119 			value = __shpcic_io_read_2(bsh1, off1);
1120 			__shpcic_io_write_2(bsh2, off2, value);
1121 			off1 += 2;
1122 			off2 += 2;
1123 		}
1124 	} else {		/* dest after src: copy backwards */
1125 		off1 += (count - 1) * 2;
1126 		off2 += (count - 1) * 2;
1127 		while (count--) {
1128 			value = __shpcic_io_read_2(bsh1, off1);
1129 			__shpcic_io_write_2(bsh2, off2, value);
1130 			off1 -= 2;
1131 			off2 -= 2;
1132 		}
1133 	}
1134 }
1135 
1136 void
1137 shpcic_io_copy_region_4(void *v, bus_space_handle_t bsh1,
1138     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1139 {
1140 	u_long addr1 = bsh1 + off1;
1141 	u_long addr2 = bsh2 + off2;
1142 	uint32_t value;
1143 
1144 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1145 		while (count--) {
1146 			value = __shpcic_io_read_4(bsh1, off1);
1147 			__shpcic_io_write_4(bsh2, off2, value);
1148 			off1 += 4;
1149 			off2 += 4;
1150 		}
1151 	} else {		/* dest after src: copy backwards */
1152 		off1 += (count - 1) * 4;
1153 		off2 += (count - 1) * 4;
1154 		while (count--) {
1155 			value = __shpcic_io_read_4(bsh1, off1);
1156 			__shpcic_io_write_4(bsh2, off2, value);
1157 			off1 -= 4;
1158 			off2 -= 4;
1159 		}
1160 	}
1161 }
1162 
1163 void
1164 shpcic_mem_copy_region_1(void *v, bus_space_handle_t bsh1,
1165     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1166 {
1167 	u_long addr1 = bsh1 + off1;
1168 	u_long addr2 = bsh2 + off2;
1169 	uint8_t value;
1170 
1171 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1172 		while (count--) {
1173 			value = __shpcic_mem_read_1(bsh1, off1);
1174 			__shpcic_mem_write_1(bsh2, off2, value);
1175 			off1 += 1;
1176 			off2 += 1;
1177 		}
1178 	} else {		/* dest after src: copy backwards */
1179 		off1 += (count - 1) * 1;
1180 		off2 += (count - 1) * 1;
1181 		while (count--) {
1182 			value = __shpcic_mem_read_1(bsh1, off1);
1183 			__shpcic_mem_write_1(bsh2, off2, value);
1184 			off1 -= 1;
1185 			off2 -= 1;
1186 		}
1187 	}
1188 }
1189 
1190 void
1191 shpcic_mem_copy_region_2(void *v, bus_space_handle_t bsh1,
1192     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1193 {
1194 	u_long addr1 = bsh1 + off1;
1195 	u_long addr2 = bsh2 + off2;
1196 	uint16_t value;
1197 
1198 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1199 		while (count--) {
1200 			value = __shpcic_mem_read_2(bsh1, off1);
1201 			__shpcic_mem_write_2(bsh2, off2, value);
1202 			off1 += 2;
1203 			off2 += 2;
1204 		}
1205 	} else {		/* dest after src: copy backwards */
1206 		off1 += (count - 1) * 2;
1207 		off2 += (count - 1) * 2;
1208 		while (count--) {
1209 			value = __shpcic_mem_read_2(bsh1, off1);
1210 			__shpcic_mem_write_2(bsh2, off2, value);
1211 			off1 -= 2;
1212 			off2 -= 2;
1213 		}
1214 	}
1215 }
1216 
1217 void
1218 shpcic_mem_copy_region_4(void *v, bus_space_handle_t bsh1,
1219     bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count)
1220 {
1221 	u_long addr1 = bsh1 + off1;
1222 	u_long addr2 = bsh2 + off2;
1223 	uint32_t value;
1224 
1225 	if (addr1 >= addr2) {	/* src after dest: copy forward */
1226 		while (count--) {
1227 			value = __shpcic_mem_read_4(bsh1, off1);
1228 			__shpcic_mem_write_4(bsh2, off2, value);
1229 			off1 += 4;
1230 			off2 += 4;
1231 		}
1232 	} else {		/* dest after src: copy backwards */
1233 		off1 += (count - 1) * 4;
1234 		off2 += (count - 1) * 4;
1235 		while (count--) {
1236 			value = __shpcic_mem_read_4(bsh1, off1);
1237 			__shpcic_mem_write_4(bsh2, off2, value);
1238 			off1 -= 4;
1239 			off2 -= 4;
1240 		}
1241 	}
1242 }
1243