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