xref: /openbsd/sys/arch/landisk/dev/obio.c (revision 4d6deb19)
1 /*	$OpenBSD: obio.c,v 1.11 2022/05/10 18:04:50 kettenis Exp $	*/
2 /*	$NetBSD: obio.c,v 1.1 2006/09/01 21:26:18 uwe Exp $	*/
3 
4 /*-
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Charles M. Hannum.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 
37 #include <uvm/uvm_extern.h>
38 
39 #include <sh/devreg.h>
40 #include <sh/mmu.h>
41 #include <sh/pmap.h>
42 #include <sh/pte.h>
43 
44 #include <machine/bus.h>
45 #include <machine/cpu.h>
46 #include <machine/intr.h>
47 
48 #include <landisk/dev/obiovar.h>
49 
50 int	obio_match(struct device *, void *, void *);
51 void	obio_attach(struct device *, struct device *, void *);
52 int	obio_print(void *, const char *);
53 int	obio_search(struct device *, void *, void *);
54 
55 const struct cfattach obio_ca = {
56 	sizeof(struct obio_softc), obio_match, obio_attach
57 };
58 
59 struct cfdriver obio_cd = {
60 	0, "obio", DV_DULL
61 };
62 
63 int
obio_match(struct device * parent,void * vcf,void * aux)64 obio_match(struct device *parent, void *vcf, void *aux)
65 {
66 	struct obiobus_attach_args *oba = aux;
67 
68 	if (strcmp(oba->oba_busname, obio_cd.cd_name) != 0)
69 		return (0);
70 
71 	return (1);
72 }
73 
74 void
obio_attach(struct device * parent,struct device * self,void * aux)75 obio_attach(struct device *parent, struct device *self, void *aux)
76 {
77 	struct obio_softc *sc = (struct obio_softc *)self;
78 	struct obiobus_attach_args *oba = aux;
79 
80 	printf("\n");
81 
82 	sc->sc_iot = oba->oba_iot;
83 	sc->sc_memt = oba->oba_memt;
84 
85 	config_search(obio_search, self, NULL);
86 }
87 
88 int
obio_search(struct device * parent,void * vcf,void * aux)89 obio_search(struct device *parent, void *vcf, void *aux)
90 {
91 	struct obio_softc *sc = (struct obio_softc *)parent;
92 	struct cfdata *cf = vcf;
93 	struct obio_attach_args oa;
94 	struct obio_io res_io[1];
95 	struct obio_iomem res_mem[1];
96 	struct obio_irq res_irq[1];
97 
98 	oa.oa_iot = sc->sc_iot;
99 	oa.oa_memt = sc->sc_memt;
100 	oa.oa_nio = oa.oa_niomem = oa.oa_nirq = 0;
101 
102 	if (cf->cf_iobase != IOBASEUNK) {
103 		res_io[0].or_addr = cf->cf_iobase;
104 		res_io[0].or_size = cf->cf_iosize;
105 		oa.oa_io = res_io;
106 		oa.oa_nio = 1;
107 	}
108 
109 	if (cf->cf_maddr != MADDRUNK) {
110 		res_mem[0].or_addr = cf->cf_maddr;
111 		res_mem[0].or_size = cf->cf_msize;
112 		oa.oa_iomem = res_mem;
113 		oa.oa_niomem = 1;
114 	}
115 
116 	if (cf->cf_irq != IRQUNK) {
117 		res_irq[0].or_irq = cf->cf_irq;
118 		oa.oa_irq = res_irq;
119 		oa.oa_nirq = 1;
120 	}
121 
122 	if ((*cf->cf_attach->ca_match)(parent, cf, &oa) == 0)
123 		return (0);
124 
125 	config_attach(parent, cf, &oa, obio_print);
126 	return (1);
127 }
128 
129 int
obio_print(void * args,const char * name)130 obio_print(void *args, const char *name)
131 {
132 	struct obio_attach_args *oa = args;
133 	const char *sep;
134 	int i;
135 
136 	if (oa->oa_nio) {
137 		sep = "";
138 		printf(" port ");
139 		for (i = 0; i < oa->oa_nio; i++) {
140 			if (oa->oa_io[i].or_size == 0)
141 				continue;
142 			printf("%s0x%x", sep, oa->oa_io[i].or_addr);
143 			if (oa->oa_io[i].or_size > 1)
144 				printf("-0x%x", oa->oa_io[i].or_addr +
145 				    oa->oa_io[i].or_size - 1);
146 			sep = ",";
147 		}
148 	}
149 
150 	if (oa->oa_niomem) {
151 		sep = "";
152 		printf(" iomem ");
153 		for (i = 0; i < oa->oa_niomem; i++) {
154 			if (oa->oa_iomem[i].or_size == 0)
155 				continue;
156 			printf("%s0x%x", sep, oa->oa_iomem[i].or_addr);
157 			if (oa->oa_iomem[i].or_size > 1)
158 				printf("-0x%x", oa->oa_iomem[i].or_addr +
159 				    oa->oa_iomem[i].or_size - 1);
160 			sep = ",";
161 		}
162 	}
163 
164 	if (oa->oa_nirq) {
165 		sep = "";
166 		printf(" irq ");
167 		for (i = 0; i < oa->oa_nirq; i++) {
168 			if (oa->oa_irq[i].or_irq == IRQUNK)
169 				continue;
170 			printf("%s%d", sep, oa->oa_irq[i].or_irq);
171 			sep = ",";
172 		}
173 	}
174 
175 	return (UNCONF);
176 }
177 
178 /*
179  * Set up an interrupt handler to start being called.
180  */
181 void *
obio_intr_establish(int irq,int level,int (* ih_fun)(void *),void * ih_arg,const char * ih_name)182 obio_intr_establish(int irq, int level, int (*ih_fun)(void *), void *ih_arg,
183     const char *ih_name)
184 {
185 	return extintr_establish(irq, level, ih_fun, ih_arg, ih_name);
186 }
187 
188 /*
189  * Deregister an interrupt handler.
190  */
191 void
obio_intr_disestablish(void * arg)192 obio_intr_disestablish(void *arg)
193 {
194 	extintr_disestablish(arg);
195 }
196 
197 /*
198  * on-board I/O bus space
199  */
200 #define	OBIO_IOMEM_IO		0	/* space is i/o space */
201 #define	OBIO_IOMEM_MEM		1	/* space is mem space */
202 #define	OBIO_IOMEM_PCMCIA_IO	2	/* PCMCIA IO space */
203 #define	OBIO_IOMEM_PCMCIA_MEM	3	/* PCMCIA Mem space */
204 #define	OBIO_IOMEM_PCMCIA_ATT	4	/* PCMCIA Attr space */
205 #define	OBIO_IOMEM_PCMCIA_8BIT	0x8000	/* PCMCIA BUS 8 BIT WIDTH */
206 #define	OBIO_IOMEM_PCMCIA_IO8 \
207 	    (OBIO_IOMEM_PCMCIA_IO|OBIO_IOMEM_PCMCIA_8BIT)
208 #define	OBIO_IOMEM_PCMCIA_MEM8 \
209 	    (OBIO_IOMEM_PCMCIA_MEM|OBIO_IOMEM_PCMCIA_8BIT)
210 #define	OBIO_IOMEM_PCMCIA_ATT8 \
211 	    (OBIO_IOMEM_PCMCIA_ATT|OBIO_IOMEM_PCMCIA_8BIT)
212 
213 int obio_iomem_map(void *v, bus_addr_t bpa, bus_size_t size, int flags,
214     bus_space_handle_t *bshp);
215 void obio_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size);
216 int obio_iomem_subregion(void *v, bus_space_handle_t bsh,
217     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
218 int obio_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
219     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
220     bus_addr_t *bpap, bus_space_handle_t *bshp);
221 void obio_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size);
222 void *obio_iomem_vaddr(void *v, bus_space_handle_t bsh);
223 
224 int obio_iomem_add_mapping(bus_addr_t, bus_size_t, int,
225     bus_space_handle_t *);
226 
227 int
obio_iomem_add_mapping(bus_addr_t bpa,bus_size_t size,int type,bus_space_handle_t * bshp)228 obio_iomem_add_mapping(bus_addr_t bpa, bus_size_t size, int type,
229     bus_space_handle_t *bshp)
230 {
231 	u_long pa, endpa;
232 	vaddr_t va;
233 	pt_entry_t *pte;
234 	unsigned int m = 0;
235 	int io_type = type & ~OBIO_IOMEM_PCMCIA_8BIT;
236 
237 	pa = trunc_page(bpa);
238 	endpa = round_page(bpa + size);
239 
240 #ifdef DIAGNOSTIC
241 	if (endpa <= pa)
242 		panic("obio_iomem_add_mapping: overflow");
243 #endif
244 
245 	va = (vaddr_t)km_alloc(endpa - pa, &kv_any, &kp_none, &kd_nowait);
246 	if (va == 0)
247 		return (ENOMEM);
248 
249 	*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
250 
251 #define MODE(t, s)							\
252 	((t) & OBIO_IOMEM_PCMCIA_8BIT) ?				\
253 		_PG_PCMCIA_ ## s ## 8 :					\
254 		_PG_PCMCIA_ ## s ## 16
255 	switch (io_type) {
256 	default:
257 		panic("unknown pcmcia space.");
258 		/* NOTREACHED */
259 	case OBIO_IOMEM_PCMCIA_IO:
260 		m = MODE(type, IO);
261 		break;
262 	case OBIO_IOMEM_PCMCIA_MEM:
263 		m = MODE(type, MEM);
264 		break;
265 	case OBIO_IOMEM_PCMCIA_ATT:
266 		m = MODE(type, ATTR);
267 		break;
268 	}
269 #undef MODE
270 
271 	for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
272 		pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE);
273 		pte = __pmap_kpte_lookup(va);
274 		KDASSERT(pte);
275 		*pte |= m;  /* PTEA PCMCIA assistant bit */
276 		sh_tlb_update(0, va, *pte);
277 	}
278 
279 	return (0);
280 }
281 
282 int
obio_iomem_map(void * v,bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)283 obio_iomem_map(void *v, bus_addr_t bpa, bus_size_t size,
284     int flags, bus_space_handle_t *bshp)
285 {
286 	bus_addr_t addr = SH3_PHYS_TO_P2SEG(bpa);
287 	int error;
288 
289 	KASSERT((bpa & SH3_PHYS_MASK) == bpa);
290 
291 	if (bpa < 0x14000000 || bpa >= 0x1c000000) {
292 		/* CS0,1,2,3,4,7 */
293 		*bshp = (bus_space_handle_t)addr;
294 		return (0);
295 	}
296 
297 	/* CS5,6 */
298 	error = obio_iomem_add_mapping(addr, size, (int)(u_long)v, bshp);
299 
300 	return (error);
301 }
302 
303 void
obio_iomem_unmap(void * v,bus_space_handle_t bsh,bus_size_t size)304 obio_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
305 {
306 	u_long va, endva;
307 	bus_addr_t bpa;
308 
309 	if (bsh >= SH3_P2SEG_BASE && bsh <= SH3_P2SEG_END) {
310 		/* maybe CS0,1,2,3,4,7 */
311 		return;
312 	}
313 
314 	/* CS5,6 */
315 	va = trunc_page(bsh);
316 	endva = round_page(bsh + size);
317 
318 #ifdef DIAGNOSTIC
319 	if (endva <= va)
320 		panic("obio_io_unmap: overflow");
321 #endif
322 
323 	pmap_extract(pmap_kernel(), va, &bpa);
324 	bpa += bsh & PGOFSET;
325 
326 	pmap_kremove(va, endva - va);
327 
328 	/*
329 	 * Free the kernel virtual mapping.
330 	 */
331 	km_free((void *)va, endva - va, &kv_any, &kp_none);
332 }
333 
334 int
obio_iomem_subregion(void * v,bus_space_handle_t bsh,bus_size_t offset,bus_size_t size,bus_space_handle_t * nbshp)335 obio_iomem_subregion(void *v, bus_space_handle_t bsh,
336     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
337 {
338 	*nbshp = bsh + offset;
339 
340 	return (0);
341 }
342 
343 int
obio_iomem_alloc(void * v,bus_addr_t rstart,bus_addr_t rend,bus_size_t size,bus_size_t alignment,bus_size_t boundary,int flags,bus_addr_t * bpap,bus_space_handle_t * bshp)344 obio_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
345     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
346     bus_addr_t *bpap, bus_space_handle_t *bshp)
347 {
348 	*bshp = *bpap = rstart;
349 
350 	return (0);
351 }
352 
353 void
obio_iomem_free(void * v,bus_space_handle_t bsh,bus_size_t size)354 obio_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size)
355 {
356 	obio_iomem_unmap(v, bsh, size);
357 }
358 
359 void *
obio_iomem_vaddr(void * v,bus_space_handle_t bsh)360 obio_iomem_vaddr(void *v, bus_space_handle_t bsh)
361 {
362 	return ((void *)bsh);
363 }
364 
365 /*
366  * on-board I/O bus space read/write
367  */
368 uint8_t obio_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset);
369 uint16_t obio_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset);
370 uint32_t obio_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset);
371 void obio_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
372     bus_size_t offset, uint8_t *addr, bus_size_t count);
373 void obio_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
374     bus_size_t offset, uint16_t *addr, bus_size_t count);
375 void obio_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
376     bus_size_t offset, uint32_t *addr, bus_size_t count);
377 void obio_iomem_read_raw_multi_2(void *v, bus_space_handle_t bsh,
378     bus_size_t offset, uint8_t *addr, bus_size_t count);
379 void obio_iomem_read_raw_multi_4(void *v, bus_space_handle_t bsh,
380     bus_size_t offset, uint8_t *addr, bus_size_t count);
381 void obio_iomem_read_region_1(void *v, bus_space_handle_t bsh,
382     bus_size_t offset, uint8_t *addr, bus_size_t count);
383 void obio_iomem_read_region_2(void *v, bus_space_handle_t bsh,
384     bus_size_t offset, uint16_t *addr, bus_size_t count);
385 void obio_iomem_read_region_4(void *v, bus_space_handle_t bsh,
386     bus_size_t offset, uint32_t *addr, bus_size_t count);
387 void obio_iomem_read_raw_region_2(void *v, bus_space_handle_t bsh,
388     bus_size_t offset, uint8_t *addr, bus_size_t count);
389 void obio_iomem_read_raw_region_4(void *v, bus_space_handle_t bsh,
390     bus_size_t offset, uint8_t *addr, bus_size_t count);
391 void obio_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
392     uint8_t value);
393 void obio_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
394     uint16_t value);
395 void obio_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
396     uint32_t value);
397 void obio_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
398     bus_size_t offset, const uint8_t *addr, bus_size_t count);
399 void obio_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
400     bus_size_t offset, const uint16_t *addr, bus_size_t count);
401 void obio_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
402     bus_size_t offset, const uint32_t *addr, bus_size_t count);
403 void obio_iomem_write_raw_multi_2(void *v, bus_space_handle_t bsh,
404     bus_size_t offset, const uint8_t *addr, bus_size_t count);
405 void obio_iomem_write_raw_multi_4(void *v, bus_space_handle_t bsh,
406     bus_size_t offset, const uint8_t *addr, bus_size_t count);
407 void obio_iomem_write_region_1(void *v, bus_space_handle_t bsh,
408     bus_size_t offset, const uint8_t *addr, bus_size_t count);
409 void obio_iomem_write_region_2(void *v, bus_space_handle_t bsh,
410     bus_size_t offset, const uint16_t *addr, bus_size_t count);
411 void obio_iomem_write_region_4(void *v, bus_space_handle_t bsh,
412     bus_size_t offset, const uint32_t *addr, bus_size_t count);
413 void obio_iomem_write_raw_region_2(void *v, bus_space_handle_t bsh,
414     bus_size_t offset, const uint8_t *addr, bus_size_t count);
415 void obio_iomem_write_raw_region_4(void *v, bus_space_handle_t bsh,
416     bus_size_t offset, const uint8_t *addr, bus_size_t count);
417 void obio_iomem_set_multi_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
418     uint8_t val, bus_size_t count);
419 void obio_iomem_set_multi_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
420     uint16_t val, bus_size_t count);
421 void obio_iomem_set_multi_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
422     uint32_t val, bus_size_t count);
423 void obio_iomem_set_region_1(void *v, bus_space_handle_t bsh,
424     bus_size_t offset, uint8_t val, bus_size_t count);
425 void obio_iomem_set_region_2(void *v, bus_space_handle_t bsh,
426     bus_size_t offset, uint16_t val, bus_size_t count);
427 void obio_iomem_set_region_4(void *v, bus_space_handle_t bsh,
428     bus_size_t offset, uint32_t val, bus_size_t count);
429 void obio_iomem_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1,
430     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
431 void obio_iomem_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1,
432     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
433 void obio_iomem_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1,
434     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
435 
436 struct _bus_space obio_bus_io =
437 {
438 	.bs_cookie = (void *)OBIO_IOMEM_PCMCIA_IO,
439 
440 	.bs_map = obio_iomem_map,
441 	.bs_unmap = obio_iomem_unmap,
442 	.bs_subregion = obio_iomem_subregion,
443 
444 	.bs_alloc = obio_iomem_alloc,
445 	.bs_free = obio_iomem_free,
446 
447 	.bs_vaddr = obio_iomem_vaddr,
448 
449 	.bs_r_1 = obio_iomem_read_1,
450 	.bs_r_2 = obio_iomem_read_2,
451 	.bs_r_4 = obio_iomem_read_4,
452 
453 	.bs_rm_1 = obio_iomem_read_multi_1,
454 	.bs_rm_2 = obio_iomem_read_multi_2,
455 	.bs_rm_4 = obio_iomem_read_multi_4,
456 
457 	.bs_rrm_2 = obio_iomem_read_raw_multi_2,
458 	.bs_rrm_4 = obio_iomem_read_raw_multi_4,
459 
460 	.bs_rr_1 = obio_iomem_read_region_1,
461 	.bs_rr_2 = obio_iomem_read_region_2,
462 	.bs_rr_4 = obio_iomem_read_region_4,
463 
464 	.bs_rrr_2 = obio_iomem_read_raw_region_2,
465 	.bs_rrr_4 = obio_iomem_read_raw_region_4,
466 
467 	.bs_w_1 = obio_iomem_write_1,
468 	.bs_w_2 = obio_iomem_write_2,
469 	.bs_w_4 = obio_iomem_write_4,
470 
471 	.bs_wm_1 = obio_iomem_write_multi_1,
472 	.bs_wm_2 = obio_iomem_write_multi_2,
473 	.bs_wm_4 = obio_iomem_write_multi_4,
474 
475 	.bs_wrm_2 = obio_iomem_write_raw_multi_2,
476 	.bs_wrm_4 = obio_iomem_write_raw_multi_4,
477 
478 	.bs_wr_1 = obio_iomem_write_region_1,
479 	.bs_wr_2 = obio_iomem_write_region_2,
480 	.bs_wr_4 = obio_iomem_write_region_4,
481 
482 	.bs_wrr_2 = obio_iomem_write_raw_region_2,
483 	.bs_wrr_4 = obio_iomem_write_raw_region_4,
484 
485 	.bs_sm_1 = obio_iomem_set_multi_1,
486 	.bs_sm_2 = obio_iomem_set_multi_2,
487 	.bs_sm_4 = obio_iomem_set_multi_4,
488 
489 	.bs_sr_1 = obio_iomem_set_region_1,
490 	.bs_sr_2 = obio_iomem_set_region_2,
491 	.bs_sr_4 = obio_iomem_set_region_4,
492 
493 	.bs_c_1 = obio_iomem_copy_1,
494 	.bs_c_2 = obio_iomem_copy_2,
495 	.bs_c_4 = obio_iomem_copy_4,
496 };
497 
498 struct _bus_space obio_bus_mem =
499 {
500 	.bs_cookie = (void *)OBIO_IOMEM_PCMCIA_MEM,
501 
502 	.bs_map = obio_iomem_map,
503 	.bs_unmap = obio_iomem_unmap,
504 	.bs_subregion = obio_iomem_subregion,
505 
506 	.bs_alloc = obio_iomem_alloc,
507 	.bs_free = obio_iomem_free,
508 
509 	.bs_vaddr = obio_iomem_vaddr,
510 
511 	.bs_r_1 = obio_iomem_read_1,
512 	.bs_r_2 = obio_iomem_read_2,
513 	.bs_r_4 = obio_iomem_read_4,
514 
515 	.bs_rm_1 = obio_iomem_read_multi_1,
516 	.bs_rm_2 = obio_iomem_read_multi_2,
517 	.bs_rm_4 = obio_iomem_read_multi_4,
518 
519 	.bs_rrm_2 = obio_iomem_read_raw_multi_2,
520 	.bs_rrm_4 = obio_iomem_read_raw_multi_4,
521 
522 	.bs_rr_1 = obio_iomem_read_region_1,
523 	.bs_rr_2 = obio_iomem_read_region_2,
524 	.bs_rr_4 = obio_iomem_read_region_4,
525 
526 	.bs_rrr_2 = obio_iomem_read_raw_region_2,
527 	.bs_rrr_4 = obio_iomem_read_raw_region_4,
528 
529 	.bs_w_1 = obio_iomem_write_1,
530 	.bs_w_2 = obio_iomem_write_2,
531 	.bs_w_4 = obio_iomem_write_4,
532 
533 	.bs_wm_1 = obio_iomem_write_multi_1,
534 	.bs_wm_2 = obio_iomem_write_multi_2,
535 	.bs_wm_4 = obio_iomem_write_multi_4,
536 
537 	.bs_wrm_2 = obio_iomem_write_raw_multi_2,
538 	.bs_wrm_4 = obio_iomem_write_raw_multi_4,
539 
540 	.bs_wr_1 = obio_iomem_write_region_1,
541 	.bs_wr_2 = obio_iomem_write_region_2,
542 	.bs_wr_4 = obio_iomem_write_region_4,
543 
544 	.bs_wrr_2 = obio_iomem_write_raw_region_2,
545 	.bs_wrr_4 = obio_iomem_write_raw_region_4,
546 
547 	.bs_sm_1 = obio_iomem_set_multi_1,
548 	.bs_sm_2 = obio_iomem_set_multi_2,
549 	.bs_sm_4 = obio_iomem_set_multi_4,
550 
551 	.bs_sr_1 = obio_iomem_set_region_1,
552 	.bs_sr_2 = obio_iomem_set_region_2,
553 	.bs_sr_4 = obio_iomem_set_region_4,
554 
555 	.bs_c_1 = obio_iomem_copy_1,
556 	.bs_c_2 = obio_iomem_copy_2,
557 	.bs_c_4 = obio_iomem_copy_4,
558 };
559 
560 /* read */
561 uint8_t
obio_iomem_read_1(void * v,bus_space_handle_t bsh,bus_size_t offset)562 obio_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset)
563 {
564 	return *(volatile uint8_t *)(bsh + offset);
565 }
566 
567 uint16_t
obio_iomem_read_2(void * v,bus_space_handle_t bsh,bus_size_t offset)568 obio_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset)
569 {
570 	return *(volatile uint16_t *)(bsh + offset);
571 }
572 
573 uint32_t
obio_iomem_read_4(void * v,bus_space_handle_t bsh,bus_size_t offset)574 obio_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset)
575 {
576 	return *(volatile uint32_t *)(bsh + offset);
577 }
578 
579 void
obio_iomem_read_multi_1(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)580 obio_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
581     bus_size_t offset, uint8_t *addr, bus_size_t count)
582 {
583 	volatile uint8_t *p = (void *)(bsh + offset);
584 
585 	while (count--) {
586 		*addr++ = *p;
587 	}
588 }
589 
590 void
obio_iomem_read_multi_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint16_t * addr,bus_size_t count)591 obio_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
592     bus_size_t offset, uint16_t *addr, bus_size_t count)
593 {
594 	volatile uint16_t *p = (void *)(bsh + offset);
595 
596 	while (count--) {
597 		*addr++ = *p;
598 	}
599 }
600 
601 void
obio_iomem_read_multi_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint32_t * addr,bus_size_t count)602 obio_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
603     bus_size_t offset, uint32_t *addr, bus_size_t count)
604 {
605 	volatile uint32_t *p = (void *)(bsh + offset);
606 
607 	while (count--) {
608 		*addr++ = *p;
609 	}
610 }
611 
612 void
obio_iomem_read_raw_multi_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)613 obio_iomem_read_raw_multi_2(void *v, bus_space_handle_t bsh,
614     bus_size_t offset, uint8_t *addr, bus_size_t count)
615 {
616 	volatile uint16_t *p = (void *)(bsh + offset);
617 
618 	count >>= 1;
619 	while (count--) {
620 		*(uint16_t *)addr = *p;
621 		addr += 2;
622 	}
623 }
624 
625 void
obio_iomem_read_raw_multi_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)626 obio_iomem_read_raw_multi_4(void *v, bus_space_handle_t bsh,
627     bus_size_t offset, uint8_t *addr, bus_size_t count)
628 {
629 	volatile uint32_t *p = (void *)(bsh + offset);
630 
631 	count >>= 2;
632 	while (count--) {
633 		*(uint32_t *)addr = *p;
634 		addr += 4;
635 	}
636 }
637 
638 void
obio_iomem_read_region_1(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)639 obio_iomem_read_region_1(void *v, bus_space_handle_t bsh,
640     bus_size_t offset, uint8_t *addr, bus_size_t count)
641 {
642 	volatile uint8_t *p = (void *)(bsh + offset);
643 
644 	while (count--) {
645 		*addr++ = *p++;
646 	}
647 }
648 
649 void
obio_iomem_read_region_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint16_t * addr,bus_size_t count)650 obio_iomem_read_region_2(void *v, bus_space_handle_t bsh,
651     bus_size_t offset, uint16_t *addr, bus_size_t count)
652 {
653 	volatile uint16_t *p = (void *)(bsh + offset);
654 
655 	while (count--) {
656 		*addr++ = *p++;
657 	}
658 }
659 
660 void
obio_iomem_read_region_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint32_t * addr,bus_size_t count)661 obio_iomem_read_region_4(void *v, bus_space_handle_t bsh,
662     bus_size_t offset, uint32_t *addr, bus_size_t count)
663 {
664 	volatile uint32_t *p = (void *)(bsh + offset);
665 
666 	while (count--) {
667 		*addr++ = *p++;
668 	}
669 }
670 
671 void
obio_iomem_read_raw_region_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)672 obio_iomem_read_raw_region_2(void *v, bus_space_handle_t bsh,
673     bus_size_t offset, uint8_t *addr, bus_size_t count)
674 {
675 	volatile uint16_t *p = (void *)(bsh + offset);
676 
677 	count >>= 1;
678 	while (count--) {
679 		*(uint16_t *)addr = *p++;
680 		addr += 2;
681 	}
682 }
683 
684 void
obio_iomem_read_raw_region_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t * addr,bus_size_t count)685 obio_iomem_read_raw_region_4(void *v, bus_space_handle_t bsh,
686     bus_size_t offset, uint8_t *addr, bus_size_t count)
687 {
688 	volatile uint32_t *p = (void *)(bsh + offset);
689 
690 	count >>= 2;
691 	while (count--) {
692 		*(uint32_t *)addr = *p++;
693 		addr += 4;
694 	}
695 }
696 
697 /* write */
698 void
obio_iomem_write_1(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t value)699 obio_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
700     uint8_t value)
701 {
702 	*(volatile uint8_t *)(bsh + offset) = value;
703 }
704 
705 void
obio_iomem_write_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint16_t value)706 obio_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
707     uint16_t value)
708 {
709 	*(volatile uint16_t *)(bsh + offset) = value;
710 }
711 
712 void
obio_iomem_write_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint32_t value)713 obio_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
714     uint32_t value)
715 {
716 	*(volatile uint32_t *)(bsh + offset) = value;
717 }
718 
719 void
obio_iomem_write_multi_1(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)720 obio_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
721     bus_size_t offset, const uint8_t *addr, bus_size_t count)
722 {
723 	volatile uint8_t *p = (void *)(bsh + offset);
724 
725 	while (count--) {
726 		*p = *addr++;
727 	}
728 }
729 
730 void
obio_iomem_write_multi_2(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint16_t * addr,bus_size_t count)731 obio_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
732     bus_size_t offset, const uint16_t *addr, bus_size_t count)
733 {
734 	volatile uint16_t *p = (void *)(bsh + offset);
735 
736 	while (count--) {
737 		*p = *addr++;
738 	}
739 }
740 
741 void
obio_iomem_write_multi_4(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint32_t * addr,bus_size_t count)742 obio_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
743     bus_size_t offset, const uint32_t *addr, bus_size_t count)
744 {
745 	volatile uint32_t *p = (void *)(bsh + offset);
746 
747 	while (count--) {
748 		*p = *addr++;
749 	}
750 }
751 
752 void
obio_iomem_write_raw_multi_2(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)753 obio_iomem_write_raw_multi_2(void *v, bus_space_handle_t bsh,
754     bus_size_t offset, const uint8_t *addr, bus_size_t count)
755 {
756 	volatile uint16_t *p = (void *)(bsh + offset);
757 
758 	count >>= 1;
759 	while (count--) {
760 		*p = *(uint16_t *)addr;
761 		addr += 2;
762 	}
763 }
764 
765 void
obio_iomem_write_raw_multi_4(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)766 obio_iomem_write_raw_multi_4(void *v, bus_space_handle_t bsh,
767     bus_size_t offset, const uint8_t *addr, bus_size_t count)
768 {
769 	volatile uint32_t *p = (void *)(bsh + offset);
770 
771 	count >>= 2;
772 	while (count--) {
773 		*p = *(uint32_t *)addr;
774 		addr += 4;
775 	}
776 }
777 
778 void
obio_iomem_write_region_1(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)779 obio_iomem_write_region_1(void *v, bus_space_handle_t bsh,
780     bus_size_t offset, const uint8_t *addr, bus_size_t count)
781 {
782 	volatile uint8_t *p = (void *)(bsh + offset);
783 
784 	while (count--) {
785 		*p++ = *addr++;
786 	}
787 }
788 
789 void
obio_iomem_write_region_2(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint16_t * addr,bus_size_t count)790 obio_iomem_write_region_2(void *v, bus_space_handle_t bsh,
791     bus_size_t offset, const uint16_t *addr, bus_size_t count)
792 {
793 	volatile uint16_t *p = (void *)(bsh + offset);
794 
795 	while (count--) {
796 		*p++ = *addr++;
797 	}
798 }
799 
800 void
obio_iomem_write_region_4(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint32_t * addr,bus_size_t count)801 obio_iomem_write_region_4(void *v, bus_space_handle_t bsh,
802     bus_size_t offset, const uint32_t *addr, bus_size_t count)
803 {
804 	volatile uint32_t *p = (void *)(bsh + offset);
805 
806 	while (count--) {
807 		*p++ = *addr++;
808 	}
809 }
810 
811 void
obio_iomem_write_raw_region_2(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)812 obio_iomem_write_raw_region_2(void *v, bus_space_handle_t bsh,
813     bus_size_t offset, const uint8_t *addr, bus_size_t count)
814 {
815 	volatile uint16_t *p = (void *)(bsh + offset);
816 
817 	count >>= 1;
818 	while (count--) {
819 		*p++ = *(uint16_t *)addr;
820 		addr += 2;
821 	}
822 }
823 
824 void
obio_iomem_write_raw_region_4(void * v,bus_space_handle_t bsh,bus_size_t offset,const uint8_t * addr,bus_size_t count)825 obio_iomem_write_raw_region_4(void *v, bus_space_handle_t bsh,
826     bus_size_t offset, const uint8_t *addr, bus_size_t count)
827 {
828 	volatile uint32_t *p = (void *)(bsh + offset);
829 
830 	count >>= 2;
831 	while (count--) {
832 		*p++ = *(uint32_t *)addr;
833 		addr += 4;
834 	}
835 }
836 
837 void
obio_iomem_set_multi_1(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t val,bus_size_t count)838 obio_iomem_set_multi_1(void *v, bus_space_handle_t bsh,
839     bus_size_t offset, uint8_t val, bus_size_t count)
840 {
841 	volatile uint8_t *p = (void *)(bsh + offset);
842 
843 	while (count--) {
844 		*p = val;
845 	}
846 }
847 
848 void
obio_iomem_set_multi_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint16_t val,bus_size_t count)849 obio_iomem_set_multi_2(void *v, bus_space_handle_t bsh,
850     bus_size_t offset, uint16_t val, bus_size_t count)
851 {
852 	volatile uint16_t *p = (void *)(bsh + offset);
853 
854 	while (count--) {
855 		*p = val;
856 	}
857 }
858 
859 void
obio_iomem_set_multi_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint32_t val,bus_size_t count)860 obio_iomem_set_multi_4(void *v, bus_space_handle_t bsh,
861     bus_size_t offset, uint32_t val, bus_size_t count)
862 {
863 	volatile uint32_t *p = (void *)(bsh + offset);
864 
865 	while (count--) {
866 		*p = val;
867 	}
868 }
869 
870 void
obio_iomem_set_region_1(void * v,bus_space_handle_t bsh,bus_size_t offset,uint8_t val,bus_size_t count)871 obio_iomem_set_region_1(void *v, bus_space_handle_t bsh,
872     bus_size_t offset, uint8_t val, bus_size_t count)
873 {
874 	volatile uint8_t *addr = (void *)(bsh + offset);
875 
876 	while (count--) {
877 		*addr++ = val;
878 	}
879 }
880 
881 void
obio_iomem_set_region_2(void * v,bus_space_handle_t bsh,bus_size_t offset,uint16_t val,bus_size_t count)882 obio_iomem_set_region_2(void *v, bus_space_handle_t bsh,
883     bus_size_t offset, uint16_t val, bus_size_t count)
884 {
885 	volatile uint16_t *addr = (void *)(bsh + offset);
886 
887 	while (count--) {
888 		*addr++ = val;
889 	}
890 }
891 
892 void
obio_iomem_set_region_4(void * v,bus_space_handle_t bsh,bus_size_t offset,uint32_t val,bus_size_t count)893 obio_iomem_set_region_4(void *v, bus_space_handle_t bsh,
894     bus_size_t offset, uint32_t val, bus_size_t count)
895 {
896 	volatile uint32_t *addr = (void *)(bsh + offset);
897 
898 	while (count--) {
899 		*addr++ = val;
900 	}
901 }
902 
903 void
obio_iomem_copy_1(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t count)904 obio_iomem_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1,
905     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
906 {
907 	volatile uint8_t *addr1 = (void *)(h1 + o1);
908 	volatile uint8_t *addr2 = (void *)(h2 + o2);
909 
910 	if (addr1 >= addr2) {	/* src after dest: copy forward */
911 		while (count--) {
912 			*addr2++ = *addr1++;
913 		}
914 	} else {		/* dest after src: copy backwards */
915 		addr1 += count - 1;
916 		addr2 += count - 1;
917 		while (count--) {
918 			*addr2-- = *addr1--;
919 		}
920 	}
921 }
922 
923 void
obio_iomem_copy_2(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t count)924 obio_iomem_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1,
925     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
926 {
927 	volatile uint16_t *addr1 = (void *)(h1 + o1);
928 	volatile uint16_t *addr2 = (void *)(h2 + o2);
929 
930 	if (addr1 >= addr2) {	/* src after dest: copy forward */
931 		while (count--) {
932 			*addr2++ = *addr1++;
933 		}
934 	} else {		/* dest after src: copy backwards */
935 		addr1 += count - 1;
936 		addr2 += count - 1;
937 		while (count--) {
938 			*addr2-- = *addr1--;
939 		}
940 	}
941 }
942 
943 void
obio_iomem_copy_4(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t count)944 obio_iomem_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1,
945     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
946 {
947 	volatile uint32_t *addr1 = (void *)(h1 + o1);
948 	volatile uint32_t *addr2 = (void *)(h2 + o2);
949 
950 	if (addr1 >= addr2) {	/* src after dest: copy forward */
951 		while (count--) {
952 			*addr2++ = *addr1++;
953 		}
954 	} else {		/* dest after src: copy backwards */
955 		addr1 += count - 1;
956 		addr2 += count - 1;
957 		while (count--) {
958 			*addr2-- = *addr1--;
959 		}
960 	}
961 }
962