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