elroy.c revision 1.1 1 /* $NetBSD: elroy.c,v 1.1 2014/02/24 07:23:42 skrll Exp $ */
2
3 /* $OpenBSD: elroy.c,v 1.5 2009/03/30 21:24:57 kettenis Exp $ */
4
5 /*
6 * Copyright (c) 2005 Michael Shalayeff
7 * All rights reserved.
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
18 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 /* #include "cardbus.h" */
23
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/device.h>
27 #include <sys/reboot.h>
28 #include <sys/malloc.h>
29 #include <sys/extent.h>
30
31 #include <machine/iomod.h>
32 #include <machine/autoconf.h>
33
34 #include <hppa/dev/cpudevs.h>
35
36 #if NCARDBUS > 0
37 #include <dev/cardbus/rbus.h>
38 #endif
39
40 #include <dev/pci/pcireg.h>
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcidevs.h>
43
44 #include <hppa/dev/elroyreg.h>
45 #include <hppa/dev/elroyvar.h>
46
47 #define ELROY_MEM_CHUNK 0x800000
48 #define ELROY_MEM_WINDOW (2 * ELROY_MEM_CHUNK)
49
50 int elroy_match(device_t, cfdata_t, void *);
51 void elroy_attach(device_t, device_t, void *);
52
53 CFATTACH_DECL_NEW(elroy, sizeof(struct elroy_softc), elroy_match, elroy_attach,
54 NULL, NULL);
55
56 extern struct cfdriver elroy_cd;
57
58 void elroy_write32(volatile uint32_t *, uint32_t);
59 uint32_t elroy_read32(volatile uint32_t *);
60 void elroy_attach_hook(device_t, device_t, struct pcibus_attach_args *);
61 int elroy_maxdevs(void *, int);
62 pcitag_t elroy_make_tag(void *, int, int, int);
63 void elroy_decompose_tag(void *, pcitag_t, int *, int *, int *);
64 pcireg_t elroy_conf_read(void *, pcitag_t, int);
65 void elroy_conf_write(void *, pcitag_t, int, pcireg_t);
66
67 int elroy_iomap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
68 int elroy_memmap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
69 int elroy_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t,
70 bus_space_handle_t *);
71 int elroy_ioalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
72 bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
73 int elroy_memalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
74 bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
75 void elroy_unmap(void *, bus_space_handle_t, bus_size_t);
76 void elroy_free(void *, bus_space_handle_t, bus_size_t);
77 void elroy_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int);
78 void *elroy_alloc_parent(device_t, struct pci_attach_args *, int);
79 void *elroy_vaddr(void *, bus_space_handle_t);
80 paddr_t elroy_mmap(void *, bus_addr_t, off_t, int, int);
81
82 uint8_t elroy_r1(void *, bus_space_handle_t, bus_size_t);
83 uint16_t elroy_r2(void *, bus_space_handle_t, bus_size_t);
84 uint32_t elroy_r4(void *, bus_space_handle_t, bus_size_t);
85 uint64_t elroy_r8(void *, bus_space_handle_t, bus_size_t);
86 void elroy_w1(void *, bus_space_handle_t, bus_size_t, uint8_t);
87 void elroy_w2(void *, bus_space_handle_t, bus_size_t, uint16_t);
88 void elroy_w4(void *, bus_space_handle_t, bus_size_t, uint32_t);
89 void elroy_w8(void *, bus_space_handle_t, bus_size_t, uint64_t);
90
91 void elroy_rm_1(void *, bus_space_handle_t, bus_size_t, uint8_t *,
92 bus_size_t);
93 void elroy_rm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
94 bus_size_t);
95 void elroy_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
96 bus_size_t);
97 void elroy_rm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
98 bus_size_t);
99 void elroy_wm_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *,
100 bus_size_t);
101 void elroy_wm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
102 bus_size_t);
103 void elroy_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
104 bus_size_t);
105 void elroy_wm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
106 bus_size_t);
107 void elroy_sm_1(void *, bus_space_handle_t, bus_size_t, uint8_t,
108 bus_size_t);
109 void elroy_sm_2(void *, bus_space_handle_t, bus_size_t, uint16_t,
110 bus_size_t);
111 void elroy_sm_4(void *, bus_space_handle_t, bus_size_t, uint32_t,
112 bus_size_t);
113 void elroy_sm_8(void *, bus_space_handle_t, bus_size_t, uint64_t,
114 bus_size_t);
115
116 void elroy_rrm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
117 bus_size_t);
118 void elroy_rrm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
119 bus_size_t);
120 void elroy_rrm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
121 bus_size_t);
122 void elroy_wrm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
123 bus_size_t);
124 void elroy_wrm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
125 bus_size_t);
126 void elroy_wrm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
127 bus_size_t);
128 void elroy_rr_1(void *, bus_space_handle_t, bus_size_t, uint8_t *,
129 bus_size_t);
130 void elroy_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
131 bus_size_t);
132 void elroy_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
133 bus_size_t);
134 void elroy_rr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
135 bus_size_t);
136 void elroy_wr_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *,
137 bus_size_t);
138 void elroy_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
139 bus_size_t);
140 void elroy_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
141 bus_size_t);
142 void elroy_wr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
143 bus_size_t);
144
145 void elroy_rrr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
146 bus_size_t);
147 void elroy_rrr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
148 bus_size_t);
149 void elroy_rrr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
150 bus_size_t);
151 void elroy_wrr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
152 bus_size_t);
153 void elroy_wrr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
154 bus_size_t);
155 void elroy_wrr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
156 bus_size_t);
157 void elroy_sr_1(void *, bus_space_handle_t, bus_size_t, uint8_t,
158 bus_size_t);
159 void elroy_sr_2(void *, bus_space_handle_t, bus_size_t, uint16_t,
160 bus_size_t);
161 void elroy_sr_4(void *, bus_space_handle_t, bus_size_t, uint32_t,
162 bus_size_t);
163 void elroy_sr_8(void *, bus_space_handle_t, bus_size_t, uint64_t,
164 bus_size_t);
165 void elroy_cp_1(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
166 bus_size_t, bus_size_t);
167 void elroy_cp_2(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
168 bus_size_t, bus_size_t);
169 void elroy_cp_4(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
170 bus_size_t, bus_size_t);
171 void elroy_cp_8(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
172 bus_size_t, bus_size_t);
173
174 int elroy_dmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t,
175 int, bus_dmamap_t *);
176 void elroy_dmamap_destroy(void *, bus_dmamap_t);
177 int elroy_dmamap_load(void *, bus_dmamap_t, void *, bus_size_t,
178 struct proc *, int);
179 int elroy_dmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int);
180 int elroy_dmamap_load_uio(void *, bus_dmamap_t, struct uio *, int);
181 int elroy_dmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *,
182 int, bus_size_t, int);
183 void elroy_dmamap_unload(void *, bus_dmamap_t);
184 void elroy_dmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t,
185 int);
186 int elroy_dmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t,
187 bus_dma_segment_t *, int, int *, int);
188 void elroy_dmamem_free(void *, bus_dma_segment_t *, int);
189 int elroy_dmamem_map(void *, bus_dma_segment_t *, int, size_t,
190 void **, int);
191 void elroy_dmamem_unmap(void *, void *, size_t);
192 paddr_t elroy_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t,
193 int, int);
194
195 int
196 elroy_match(device_t parent, cfdata_t cf, void *aux)
197 {
198 struct confargs *ca = aux;
199
200 if ((ca->ca_name && !strcmp(ca->ca_name, "lba")) ||
201 (ca->ca_type.iodc_type == HPPA_TYPE_BRIDGE &&
202 ca->ca_type.iodc_sv_model == HPPA_BRIDGE_DINO &&
203 ca->ca_type.iodc_model == 0x78))
204 return (1);
205
206 return (0);
207 }
208
209 void
210 elroy_write32(volatile uint32_t *p, uint32_t v)
211 {
212 *p = v;
213 }
214
215 uint32_t
216 elroy_read32(volatile uint32_t *p)
217 {
218 return *p;
219 }
220
221 void
222 elroy_attach_hook(device_t parent, device_t self,
223 struct pcibus_attach_args *pba)
224 {
225
226 }
227
228 int
229 elroy_maxdevs(void *v, int bus)
230 {
231 return (32);
232 }
233
234 pcitag_t
235 elroy_make_tag(void *v, int bus, int dev, int func)
236 {
237 if (bus > 255 || dev > 31 || func > 7)
238 panic("elroy_make_tag: bad request");
239
240 return ((bus << 16) | (dev << 11) | (func << 8));
241 }
242
243 void
244 elroy_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
245 {
246 *bus = (tag >> 16) & 0xff;
247 *dev = (tag >> 11) & 0x1f;
248 *func= (tag >> 8) & 0x07;
249 }
250
251 pcireg_t
252 elroy_conf_read(void *v, pcitag_t tag, int reg)
253 {
254 struct elroy_softc *sc = v;
255 volatile struct elroy_regs *r = sc->sc_regs;
256 uint32_t arb_mask, err_cfg, control;
257 pcireg_t data;
258
259 /* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */
260 arb_mask = elroy_read32(&r->arb_mask);
261 err_cfg = elroy_read32(&r->err_cfg);
262 control = elroy_read32(&r->control);
263 if (!arb_mask)
264 elroy_write32(&r->arb_mask, htole32(ELROY_ARB_ENABLE));
265 elroy_write32(&r->err_cfg, err_cfg |
266 htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
267 elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
268 ~htole32(ELROY_CONTROL_HF));
269
270 elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
271 (void)elroy_read32(&r->pci_conf_addr);
272 data = elroy_read32(&r->pci_conf_data);
273
274 elroy_write32(&r->control, control |
275 htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
276 elroy_write32(&r->control, control);
277 elroy_write32(&r->err_cfg, err_cfg);
278 if (!arb_mask)
279 elroy_write32(&r->arb_mask, arb_mask);
280
281 data = le32toh(data);
282 /* printf("=0x%08x (@ 0x%08x)\n", data, le32toh(data1)); */
283 return (data);
284 }
285
286 void
287 elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
288 {
289 struct elroy_softc *sc = v;
290 volatile struct elroy_regs *r = sc->sc_regs;
291 uint32_t arb_mask, err_cfg, control;
292
293 /* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */
294 arb_mask = elroy_read32(&r->arb_mask);
295 err_cfg = elroy_read32(&r->err_cfg);
296 control = elroy_read32(&r->control);
297 if (!arb_mask)
298 elroy_write32(&r->arb_mask, htole32(ELROY_ARB_ENABLE));
299 elroy_write32(&r->err_cfg, err_cfg |
300 htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
301 elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
302 ~htole32(ELROY_CONTROL_HF));
303
304 /* fix coalescing config writes errata by interleaving w/ a read */
305 elroy_write32(&r->pci_conf_addr, htole32(tag | PCI_ID_REG));
306 (void)elroy_read32(&r->pci_conf_addr);
307 (void)elroy_read32(&r->pci_conf_data);
308
309 elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
310 (void)elroy_read32(&r->pci_conf_addr);
311 elroy_write32(&r->pci_conf_data, htole32(data));
312 (void)elroy_read32(&r->pci_conf_addr);
313
314 elroy_write32(&r->control, control |
315 htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
316 elroy_write32(&r->control, control);
317 elroy_write32(&r->err_cfg, err_cfg);
318 if (!arb_mask)
319 elroy_write32(&r->arb_mask, arb_mask);
320 }
321
322 int
323 elroy_iomap(void *v, bus_addr_t bpa, bus_size_t size,
324 int flags, bus_space_handle_t *bshp)
325 {
326 struct elroy_softc *sc = v;
327 /* volatile struct elroy_regs *r = sc->sc_regs; */
328 int error;
329
330 if ((error = bus_space_map(sc->sc_bt, bpa + sc->sc_iobase, size,
331 flags, bshp)))
332 return (error);
333
334 return (0);
335 }
336
337 int
338 elroy_memmap(void *v, bus_addr_t bpa, bus_size_t size,
339 int flags, bus_space_handle_t *bshp)
340 {
341 struct elroy_softc *sc = v;
342 /* volatile struct elroy_regs *r = sc->sc_regs; */
343 int error;
344
345 if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp)))
346 return (error);
347
348 return (0);
349 }
350
351 int
352 elroy_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
353 bus_size_t size, bus_space_handle_t *nbshp)
354 {
355 *nbshp = bsh + offset;
356 return (0);
357 }
358
359 int
360 elroy_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
361 bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
362 bus_space_handle_t *bshp)
363 {
364 struct elroy_softc *sc = v;
365 volatile struct elroy_regs *r = sc->sc_regs;
366 bus_addr_t iostart, ioend;
367
368 iostart = r->io_base & ~htole32(ELROY_BASE_RE);
369 ioend = iostart + ~htole32(r->io_mask) + 1;
370 if (rstart < iostart || rend > ioend)
371 panic("elroy_ioalloc: bad region start/end");
372
373 rstart += sc->sc_iobase;
374 rend += sc->sc_iobase;
375 if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
376 align, boundary, flags, addrp, bshp))
377 return (ENOMEM);
378
379 return (0);
380 }
381
382 int
383 elroy_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
384 bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
385 bus_space_handle_t *bshp)
386 {
387 struct elroy_softc *sc = v;
388 /* volatile struct elroy_regs *r = sc->sc_regs; */
389
390 if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
391 align, boundary, flags, addrp, bshp))
392 return (ENOMEM);
393
394 return (0);
395 }
396
397 void
398 elroy_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
399 {
400 struct elroy_softc *sc = v;
401
402 bus_space_free(sc->sc_bt, bsh, size);
403 }
404
405 void
406 elroy_free(void *v, bus_space_handle_t bh, bus_size_t size)
407 {
408 /* should be enough */
409 elroy_unmap(v, bh, size);
410 }
411
412 void
413 elroy_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
414 {
415 struct elroy_softc *sc = v;
416 volatile struct elroy_regs *r = sc->sc_regs;
417
418 sync_caches();
419 if (op & BUS_SPACE_BARRIER_WRITE) {
420 (void)r->pci_id; /* flush write fifo */
421 sync_caches();
422 }
423 }
424
425 #if NCARDBUS > 0
426 void *
427 elroy_alloc_parent(device_t self, struct pci_attach_args *pa, int io)
428 {
429 #if 0 /* TODO */
430
431 struct elroy_softc *sc = pa->pa_pc->_cookie;
432 struct extent *ex;
433 bus_space_tag_t tag;
434 bus_addr_t start;
435 bus_size_t size;
436
437 if (io) {
438 ex = sc->sc_ioex;
439 tag = pa->pa_iot;
440 start = 0xa000;
441 size = 0x1000;
442 } else {
443 if (!sc->sc_memex) {
444 bus_space_handle_t memh;
445 bus_addr_t mem_start;
446
447 if (elroy_memalloc(sc, 0xf0800000, 0xff7fffff,
448 ELROY_MEM_WINDOW, ELROY_MEM_WINDOW, EX_NOBOUNDARY,
449 0, &mem_start, &memh))
450 return (NULL);
451
452 snprintf(sc->sc_memexname, sizeof(sc->sc_memexname),
453 "%s_mem", device_xname(sc->sc_dv));
454 if ((sc->sc_memex = extent_create(sc->sc_memexname,
455 mem_start, mem_start + ELROY_MEM_WINDOW,
456 NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) {
457 extent_destroy(sc->sc_ioex);
458 bus_space_free(sc->sc_bt, memh,
459 ELROY_MEM_WINDOW);
460 return (NULL);
461 }
462 }
463 ex = sc->sc_memex;
464 tag = pa->pa_memt;
465 start = ex->ex_start;
466 size = ELROY_MEM_CHUNK;
467 }
468
469 if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0,
470 EX_NOBOUNDARY, EX_NOWAIT, &start))
471 return (NULL);
472
473 extent_free(ex, start, size, EX_NOWAIT);
474 return rbus_new_root_share(tag, ex, start, size, 0);
475 #else
476 return (NULL);
477 #endif
478 }
479 #endif
480
481 void *
482 elroy_vaddr(void *v, bus_space_handle_t h)
483 {
484 return ((void *)h);
485 }
486
487 paddr_t
488 elroy_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags)
489 {
490
491 return -1;
492 }
493
494 uint8_t
495 elroy_r1(void *v, bus_space_handle_t h, bus_size_t o)
496 {
497 h += o;
498 return *(volatile uint8_t *)h;
499 }
500
501 uint16_t
502 elroy_r2(void *v, bus_space_handle_t h, bus_size_t o)
503 {
504 volatile uint16_t *p;
505
506 h += o;
507 p = (volatile uint16_t *)h;
508 return (le16toh(*p));
509 }
510
511 uint32_t
512 elroy_r4(void *v, bus_space_handle_t h, bus_size_t o)
513 {
514 uint32_t data;
515
516 h += o;
517 data = *(volatile uint32_t *)h;
518 return (le32toh(data));
519 }
520
521 uint64_t
522 elroy_r8(void *v, bus_space_handle_t h, bus_size_t o)
523 {
524 uint64_t data;
525
526 h += o;
527 data = *(volatile uint64_t *)h;
528 return (le64toh(data));
529 }
530
531 void
532 elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv)
533 {
534 h += o;
535 *(volatile uint8_t *)h = vv;
536 }
537
538 void
539 elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv)
540 {
541 volatile uint16_t *p;
542
543 h += o;
544 p = (volatile uint16_t *)h;
545 *p = htole16(vv);
546 }
547
548 void
549 elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv)
550 {
551 h += o;
552 vv = htole32(vv);
553 *(volatile uint32_t *)h = vv;
554 }
555
556 void
557 elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv)
558 {
559 h += o;
560 *(volatile uint64_t *)h = htole64(vv);
561 }
562
563
564 void
565 elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c)
566 {
567 volatile uint8_t *p;
568
569 h += o;
570 p = (volatile uint8_t *)h;
571 while (c--)
572 *a++ = *p;
573 }
574
575 void
576 elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c)
577 {
578 volatile uint16_t *p;
579
580 h += o;
581 p = (volatile uint16_t *)h;
582 while (c--)
583 *a++ = le16toh(*p);
584 }
585
586 void
587 elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c)
588 {
589 volatile uint32_t *p;
590
591 h += o;
592 p = (volatile uint32_t *)h;
593 while (c--)
594 *a++ = le32toh(*p);
595 }
596
597 void
598 elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c)
599 {
600 volatile uint64_t *p;
601
602 h += o;
603 p = (volatile uint64_t *)h;
604 while (c--)
605 *a++ = le64toh(*p);
606 }
607
608 void
609 elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c)
610 {
611 volatile uint8_t *p;
612
613 h += o;
614 p = (volatile uint8_t *)h;
615 while (c--)
616 *p = *a++;
617 }
618
619 void
620 elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c)
621 {
622 volatile uint16_t *p;
623
624 h += o;
625 p = (volatile uint16_t *)h;
626 while (c--)
627 *p = htole16(*a++);
628 }
629
630 void
631 elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c)
632 {
633 volatile uint32_t *p;
634
635 h += o;
636 p = (volatile uint32_t *)h;
637 while (c--)
638 *p = htole32(*a++);
639 }
640
641 void
642 elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c)
643 {
644 volatile uint64_t *p;
645
646 h += o;
647 p = (volatile uint64_t *)h;
648 while (c--)
649 *p = htole64(*a++);
650 }
651
652 void
653 elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv, bus_size_t c)
654 {
655 volatile uint8_t *p;
656
657 h += o;
658 p = (volatile uint8_t *)h;
659 while (c--)
660 *p = vv;
661 }
662
663 void
664 elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c)
665 {
666 volatile uint16_t *p;
667
668 h += o;
669 p = (volatile uint16_t *)h;
670 vv = htole16(vv);
671 while (c--)
672 *p = vv;
673 }
674
675 void
676 elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c)
677 {
678 volatile uint32_t *p;
679
680 h += o;
681 p = (volatile uint32_t *)h;
682 vv = htole32(vv);
683 while (c--)
684 *p = vv;
685 }
686
687 void
688 elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv, bus_size_t c)
689 {
690 volatile uint64_t *p;
691
692 h += o;
693 p = (volatile uint64_t *)h;
694 vv = htole64(vv);
695 while (c--)
696 *p = vv;
697 }
698
699 void
700 elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o,
701 uint16_t *a, bus_size_t c)
702 {
703 volatile uint16_t *p, *q = a;
704
705 h += o;
706 p = (volatile uint16_t *)h;
707 while (c--)
708 *q++ = *p;
709 }
710
711 void
712 elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o,
713 uint32_t *a, bus_size_t c)
714 {
715 volatile uint32_t *p, *q = a;
716
717 h += o;
718 p = (volatile uint32_t *)h;
719 while (c--)
720 *q++ = *p;
721 }
722
723 void
724 elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o,
725 uint64_t *a, bus_size_t c)
726 {
727 volatile uint64_t *p, *q = a;
728
729 h += o;
730 p = (volatile uint64_t *)h;
731 while (c--)
732 *q++ = *p;
733 }
734
735 void
736 elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o,
737 const uint16_t *a, bus_size_t c)
738 {
739 volatile uint16_t *p;
740 const uint16_t *q = a;
741
742 h += o;
743 p = (volatile uint16_t *)h;
744 while (c--)
745 *p = *q++;
746 }
747
748 void
749 elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o,
750 const uint32_t *a, bus_size_t c)
751 {
752 volatile uint32_t *p;
753 const uint32_t *q = a;
754
755 h += o;
756 p = (volatile uint32_t *)h;
757 while (c--)
758 *p = *q++;
759 }
760
761 void
762 elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o,
763 const uint64_t *a, bus_size_t c)
764 {
765 volatile uint64_t *p;
766 const uint64_t *q = a;
767
768 h += o;
769 p = (volatile uint64_t *)h;
770 while (c--)
771 *p = *q++;
772 }
773
774 void
775 elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c)
776 {
777 volatile uint8_t *p;
778
779 h += o;
780 p = (volatile uint8_t *)h;
781 while (c--)
782 *a++ = *p++;
783 }
784
785 void
786 elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c)
787 {
788 volatile uint16_t *p, data;
789
790 h += o;
791 p = (volatile uint16_t *)h;
792 while (c--) {
793 data = *p++;
794 *a++ = le16toh(data);
795 }
796 }
797
798 void
799 elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c)
800 {
801 volatile uint32_t *p, data;
802
803 h += o;
804 p = (volatile uint32_t *)h;
805 while (c--) {
806 data = *p++;
807 *a++ = le32toh(data);
808 }
809 }
810
811 void
812 elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c)
813 {
814 volatile uint64_t *p, data;
815
816 h += o;
817 p = (volatile uint64_t *)h;
818 while (c--) {
819 data = *p++;
820 *a++ = le64toh(data);
821 }
822 }
823
824 void
825 elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c)
826 {
827 volatile uint8_t *p;
828
829 h += o;
830 p = (volatile uint8_t *)h;
831 while (c--)
832 *p++ = *a++;
833 }
834
835 void
836 elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c)
837 {
838 volatile uint16_t *p, data;
839
840 h += o;
841 p = (volatile uint16_t *)h;
842 while (c--) {
843 data = *a++;
844 *p++ = htole16(data);
845 }
846 }
847
848 void
849 elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c)
850 {
851 volatile uint32_t *p, data;
852
853 h += o;
854 p = (volatile uint32_t *)h;
855 while (c--) {
856 data = *a++;
857 *p++ = htole32(data);
858 }
859 }
860
861 void
862 elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c)
863 {
864 volatile uint64_t *p, data;
865
866 h += o;
867 p = (volatile uint64_t *)h;
868 while (c--) {
869 data = *a++;
870 *p++ = htole64(data);
871 }
872 }
873
874 void
875 elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o,
876 uint16_t *a, bus_size_t c)
877 {
878 volatile uint16_t *p, *q = a;
879
880 h += o;
881 p = (volatile uint16_t *)h;
882 while (c--)
883 *q++ = *p++;
884 }
885
886 void
887 elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o,
888 uint32_t *a, bus_size_t c)
889 {
890 volatile uint32_t *p, *q = a;
891
892 h += o;
893 p = (volatile uint32_t *)h;
894 while (c--)
895 *q++ = *p++;
896 }
897
898 void
899 elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o,
900 uint64_t *a, bus_size_t c)
901 {
902 volatile uint64_t *p, *q = a;
903
904 h += o;
905 p = (volatile uint64_t *)h;
906 while (c--)
907 *q++ = *p++;
908 }
909
910 void
911 elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o,
912 const uint16_t *a, bus_size_t c)
913 {
914 volatile uint16_t *p;
915 const uint16_t *q = a;
916
917 h += o;
918 p = (volatile uint16_t *)h;
919 while (c--)
920 *p++ = *q++;
921 }
922
923 void
924 elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o,
925 const uint32_t *a, bus_size_t c)
926 {
927 volatile uint32_t *p;
928 const uint32_t *q = a;
929
930 h += o;
931 p = (volatile uint32_t *)h;
932 while (c--)
933 *p++ = *q++;
934 }
935
936 void
937 elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o,
938 const uint64_t *a, bus_size_t c)
939 {
940 volatile uint64_t *p;
941 const uint64_t *q = a;
942
943 h += o;
944 p = (volatile uint64_t *)h;
945 while (c--)
946 *p++ = *q++;
947 }
948
949 void
950 elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv, bus_size_t c)
951 {
952 volatile uint8_t *p;
953
954 h += o;
955 p = (volatile uint8_t *)h;
956 while (c--)
957 *p++ = vv;
958 }
959
960 void
961 elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c)
962 {
963 volatile uint16_t *p;
964
965 h += o;
966 vv = htole16(vv);
967 p = (volatile uint16_t *)h;
968 while (c--)
969 *p++ = vv;
970 }
971
972 void
973 elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c)
974 {
975 volatile uint32_t *p;
976
977 h += o;
978 vv = htole32(vv);
979 p = (volatile uint32_t *)h;
980 while (c--)
981 *p++ = vv;
982 }
983
984 void
985 elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv, bus_size_t c)
986 {
987 volatile uint64_t *p;
988
989 h += o;
990 vv = htole64(vv);
991 p = (volatile uint64_t *)h;
992 while (c--)
993 *p++ = vv;
994 }
995
996 void
997 elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
998 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
999 {
1000 while (c--)
1001 elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++));
1002 }
1003
1004 void
1005 elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
1006 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1007 {
1008 while (c--) {
1009 elroy_w2(v, h1, o1, elroy_r2(v, h2, o2));
1010 o1 += 2;
1011 o2 += 2;
1012 }
1013 }
1014
1015 void
1016 elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
1017 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1018 {
1019 while (c--) {
1020 elroy_w4(v, h1, o1, elroy_r4(v, h2, o2));
1021 o1 += 4;
1022 o2 += 4;
1023 }
1024 }
1025
1026 void
1027 elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
1028 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1029 {
1030 while (c--) {
1031 elroy_w8(v, h1, o1, elroy_r8(v, h2, o2));
1032 o1 += 8;
1033 o2 += 8;
1034 }
1035 }
1036
1037 const struct hppa_bus_space_tag elroy_iomemt = {
1038 NULL,
1039
1040 NULL, elroy_unmap, elroy_subregion, NULL, elroy_free,
1041 elroy_barrier, elroy_vaddr, elroy_mmap,
1042 elroy_r1, elroy_r2, elroy_r4, elroy_r8,
1043 elroy_w1, elroy_w2, elroy_w4, elroy_w8,
1044 elroy_rm_1, elroy_rm_2, elroy_rm_4, elroy_rm_8,
1045 elroy_wm_1, elroy_wm_2, elroy_wm_4, elroy_wm_8,
1046 elroy_sm_1, elroy_sm_2, elroy_sm_4, elroy_sm_8,
1047 elroy_rrm_2, elroy_rrm_4, elroy_rrm_8,
1048 elroy_wrm_2, elroy_wrm_4, elroy_wrm_8,
1049 elroy_rr_1, elroy_rr_2, elroy_rr_4, elroy_rr_8,
1050 elroy_wr_1, elroy_wr_2, elroy_wr_4, elroy_wr_8,
1051 elroy_rrr_2, elroy_rrr_4, elroy_rrr_8,
1052 elroy_wrr_2, elroy_wrr_4, elroy_wrr_8,
1053 elroy_sr_1, elroy_sr_2, elroy_sr_4, elroy_sr_8,
1054 elroy_cp_1, elroy_cp_2, elroy_cp_4, elroy_cp_8
1055 };
1056
1057 int
1058 elroy_dmamap_create(void *v, bus_size_t size, int nsegments,
1059 bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
1060 {
1061 struct elroy_softc *sc = v;
1062
1063 /* TODO check the addresses, boundary, enable dma */
1064
1065 return (bus_dmamap_create(sc->sc_dmat, size, nsegments,
1066 maxsegsz, boundary, flags, dmamp));
1067 }
1068
1069 void
1070 elroy_dmamap_destroy(void *v, bus_dmamap_t map)
1071 {
1072 struct elroy_softc *sc = v;
1073
1074 bus_dmamap_destroy(sc->sc_dmat, map);
1075 }
1076
1077 int
1078 elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
1079 struct proc *p, int flags)
1080 {
1081 struct elroy_softc *sc = v;
1082
1083 return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags));
1084 }
1085
1086 int
1087 elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
1088 {
1089 struct elroy_softc *sc = v;
1090
1091 return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags));
1092 }
1093
1094 int
1095 elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
1096 {
1097 struct elroy_softc *sc = v;
1098
1099 return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags));
1100 }
1101
1102 int
1103 elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
1104 int nsegs, bus_size_t size, int flags)
1105 {
1106 struct elroy_softc *sc = v;
1107
1108 return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags));
1109 }
1110
1111 void
1112 elroy_dmamap_unload(void *v, bus_dmamap_t map)
1113 {
1114 struct elroy_softc *sc = v;
1115
1116 bus_dmamap_unload(sc->sc_dmat, map);
1117 }
1118
1119 void
1120 elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
1121 bus_size_t len, int ops)
1122 {
1123 struct elroy_softc *sc = v;
1124
1125 bus_dmamap_sync(sc->sc_dmat, map, off, len, ops);
1126 }
1127
1128 int
1129 elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
1130 bus_size_t boundary, bus_dma_segment_t *segs,
1131 int nsegs, int *rsegs, int flags)
1132 {
1133 struct elroy_softc *sc = v;
1134
1135 return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary,
1136 segs, nsegs, rsegs, flags));
1137 }
1138
1139 void
1140 elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
1141 {
1142 struct elroy_softc *sc = v;
1143
1144 bus_dmamem_free(sc->sc_dmat, segs, nsegs);
1145 }
1146
1147 int
1148 elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
1149 void **kvap, int flags)
1150 {
1151 struct elroy_softc *sc = v;
1152
1153 return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags));
1154 }
1155
1156 void
1157 elroy_dmamem_unmap(void *v, void *kva, size_t size)
1158 {
1159 struct elroy_softc *sc = v;
1160
1161 bus_dmamem_unmap(sc->sc_dmat, kva, size);
1162 }
1163
1164 paddr_t
1165 elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
1166 int prot, int flags)
1167 {
1168 struct elroy_softc *sc = v;
1169
1170 return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags));
1171 }
1172
1173 const struct hppa_bus_dma_tag elroy_dmat = {
1174 NULL,
1175 elroy_dmamap_create, elroy_dmamap_destroy,
1176 elroy_dmamap_load, elroy_dmamap_load_mbuf,
1177 elroy_dmamap_load_uio, elroy_dmamap_load_raw,
1178 elroy_dmamap_unload, elroy_dmamap_sync,
1179
1180 elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map,
1181 elroy_dmamem_unmap, elroy_dmamem_mmap
1182 };
1183
1184 const struct hppa_pci_chipset_tag elroy_pc = {
1185 NULL,
1186 elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag,
1187 elroy_conf_read, elroy_conf_write,
1188 apic_intr_map, apic_intr_string,
1189 apic_intr_establish, apic_intr_disestablish,
1190 #if NCARDBUS > 0
1191 elroy_alloc_parent
1192 #else
1193 NULL
1194 #endif
1195 };
1196
1197 void
1198 elroy_attach(device_t parent, device_t self, void *aux)
1199 {
1200 struct elroy_softc *sc = device_private(self);
1201 struct confargs *ca = (struct confargs *)aux;
1202 struct pcibus_attach_args pba;
1203 volatile struct elroy_regs *r;
1204 const char *p = NULL, *q;
1205 int i;
1206
1207 sc->sc_dv = self;
1208 sc->sc_hpa = ca->ca_hpa;
1209 sc->sc_bt = ca->ca_iot;
1210 sc->sc_dmat = ca->ca_dmatag;
1211 if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) {
1212 aprint_error(": can't map space\n");
1213 return;
1214 }
1215
1216 sc->sc_regs = r = bus_space_vaddr(sc->sc_bt, sc->sc_bh);
1217 elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE |
1218 PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE));
1219
1220 elroy_write32(&r->control, elroy_read32(&r->control) &
1221 ~htole32(ELROY_CONTROL_RF));
1222 for (i = 5000; i-- &&
1223 elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10));
1224 if (i < 0) {
1225 char buf[128]; /* XXXNH */
1226
1227 snprintb(buf, sizeof(buf), ELROY_STATUS_BITS,
1228 htole32(r->status));
1229 aprint_error(": reset failed; status %s\n", buf);
1230 return;
1231 }
1232
1233 q = "";
1234 sc->sc_ver = PCI_REVISION(le32toh(elroy_read32(&r->pci_class)));
1235 switch ((ca->ca_type.iodc_model << 4) |
1236 (ca->ca_type.iodc_revision >> 4)) {
1237 case 0x782:
1238 p = "Elroy";
1239 switch (sc->sc_ver) {
1240 default:
1241 q = "+";
1242 case 5: sc->sc_ver = 0x40; break;
1243 case 4: sc->sc_ver = 0x30; break;
1244 case 3: sc->sc_ver = 0x22; break;
1245 case 2: sc->sc_ver = 0x21; break;
1246 case 1: sc->sc_ver = 0x20; break;
1247 case 0: sc->sc_ver = 0x10; break;
1248 }
1249 break;
1250
1251 case 0x783:
1252 p = "Mercury";
1253 break;
1254
1255 case 0x784:
1256 p = "Quicksilver";
1257 break;
1258
1259 default:
1260 p = "Mojo";
1261 break;
1262 }
1263
1264 aprint_normal(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf,
1265 q);
1266 apic_attach(sc);
1267 aprint_normal("\n");
1268
1269 elroy_write32(&r->imask, htole32(0xffffffff << 30));
1270 elroy_write32(&r->ibase, htole32(ELROY_BASE_RE));
1271
1272 /* TODO reserve elroy's pci space ? */
1273
1274 #if 0
1275 printf("lmm %llx/%llx gmm %llx/%llx wlm %llx/%llx wgm %llx/%llx io %llx/%llx eio %llx/%llx\n",
1276 le64toh(r->lmmio_base), le64toh(r->lmmio_mask),
1277 le64toh(r->gmmio_base), le64toh(r->gmmio_mask),
1278 le64toh(r->wlmmio_base), le64toh(r->wlmmio_mask),
1279 le64toh(r->wgmmio_base), le64toh(r->wgmmio_mask),
1280 le64toh(r->io_base), le64toh(r->io_mask),
1281 le64toh(r->eio_base), le64toh(r->eio_mask));
1282 #endif
1283
1284 /* XXX evil hack! */
1285 sc->sc_iobase = 0xfee00000;
1286
1287 sc->sc_iot = elroy_iomemt;
1288 sc->sc_iot.hbt_cookie = sc;
1289 sc->sc_iot.hbt_map = elroy_iomap;
1290 sc->sc_iot.hbt_alloc = elroy_ioalloc;
1291 sc->sc_memt = elroy_iomemt;
1292 sc->sc_memt.hbt_cookie = sc;
1293 sc->sc_memt.hbt_map = elroy_memmap;
1294 sc->sc_memt.hbt_alloc = elroy_memalloc;
1295 sc->sc_pc = elroy_pc;
1296 sc->sc_pc._cookie = sc;
1297 sc->sc_dmatag = elroy_dmat;
1298 sc->sc_dmatag._cookie = sc;
1299
1300 memset(&pba, 0, sizeof(pba));
1301 pba.pba_iot = &sc->sc_iot;
1302 pba.pba_memt = &sc->sc_memt;
1303 pba.pba_dmat = &sc->sc_dmatag;
1304 pba.pba_pc = &sc->sc_pc;
1305 pba.pba_bus = 0; /* (le32toh(elroy_read32(&r->busnum)) & 0xff) >> 4; */
1306 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
1307
1308 config_found_ia(self, "pcibus", &pba, pcibusprint);
1309 }
1310