1 /* $NetBSD: msiiep.c,v 1.54 2025/10/04 16:11:17 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Valeriy E. Ushakov 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1.54 2025/10/04 16:11:17 thorpej Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/kmem.h> 34 #include <sys/kernel.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 38 #include <uvm/uvm.h> 39 40 #define _SPARC_BUS_DMA_PRIVATE 41 #include <sys/bus.h> 42 #include <machine/autoconf.h> 43 #include <machine/promlib.h> 44 45 #include <dev/pci/pcireg.h> 46 #include <dev/pci/pcidevs.h> 47 #include <dev/pci/pcivar.h> 48 49 #include <sparc/sparc/msiiepreg.h> 50 #include <sparc/sparc/msiiepvar.h> 51 #include <sparc/sparc/pci_fixup.h> 52 53 /* 54 * Autoconfiguration. 55 * 56 * Normally, sparc autoconfiguration is driven by PROM device tree, 57 * however PROMs in ms-IIep machines usually don't have nodes for 58 * various important registers that are part of ms-IIep PCI controller. 59 * We work around by inserting a dummy device that acts as a parent 60 * for device drivers that deal with various functions of PCIC. The 61 * other option is to hack mainbus_attach() to treat ms-IIep specially, 62 * but I'd rather insulate the rest of the source from ms-IIep quirks. 63 */ 64 65 /* 66 * "Stub" ms-IIep parent that knows how to attach various functions. 67 */ 68 static int msiiep_match(device_t, cfdata_t, void *); 69 static void msiiep_attach(device_t, device_t, void *); 70 71 CFATTACH_DECL_NEW(msiiep, 0, msiiep_match, msiiep_attach, NULL, NULL); 72 73 74 /* sleep in idle spin */ 75 static void msiiep_cpu_sleep(void); 76 volatile uint32_t *msiiep_mid = NULL; 77 78 79 /* 80 * The real thing. 81 */ 82 static int mspcic_match(device_t, cfdata_t, void *); 83 static void mspcic_attach(device_t, device_t, void *); 84 static int mspcic_print(void *, const char *); 85 86 CFATTACH_DECL_NEW(mspcic, sizeof(struct mspcic_softc), 87 mspcic_match, mspcic_attach, NULL, NULL); 88 89 90 /** 91 * Only one PCI controller per MS-IIep and only one MS-IIep per system 92 * so don't bother with malloc'ing our tags. 93 */ 94 95 /* 96 * PCI chipset tag 97 */ 98 static struct sparc_pci_chipset mspcic_pc_tag = { NULL }; 99 100 101 /* fixed i/o and one set of i/o cycle translation registers */ 102 struct mspcic_pci_map mspcic_pci_iomap[IOMAP_SIZE] = { 103 { 0x30000000, 0x0, 0x00010000 } /* fixed i/o (decoded bits) */ 104 }; 105 106 /* fixed mem and two sets of mem cycle translation registers */ 107 struct mspcic_pci_map mspcic_pci_memmap[MEMMAP_SIZE] = { 108 { 0x30100000, 0x00100000, 0x00f00000 } /* fixed mem (pass through) */ 109 }; 110 111 struct mspcic_cookie { 112 struct mspcic_pci_map *map; 113 int nmaps; 114 }; 115 116 static struct mspcic_cookie mspcic_io_cookie = { mspcic_pci_iomap, 0 }; 117 static struct mspcic_cookie mspcic_mem_cookie = { mspcic_pci_memmap, 0 }; 118 119 120 static void mspcic_init_maps(void); 121 static void mspcic_pci_map_from_reg(struct mspcic_pci_map *, 122 uint8_t, uint8_t, uint8_t); 123 static bus_addr_t mspcic_pci_map_find(struct mspcic_pci_map *, int, 124 bus_addr_t, bus_size_t); 125 #ifdef DEBUG 126 static void mspcic_pci_map_print(struct mspcic_pci_map *, const char *); 127 #endif 128 129 130 static int mspcic_bus_map(bus_space_tag_t, bus_addr_t, bus_size_t, 131 int, vaddr_t, bus_space_handle_t *); 132 static paddr_t mspcic_bus_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); 133 static void *mspcic_intr_establish(bus_space_tag_t, int, int, 134 int (*)(void *), void *, void (*)(void)); 135 136 /* bus space methods that do byteswapping */ 137 static uint16_t mspcic_bus_read_2(bus_space_tag_t, bus_space_handle_t, 138 bus_size_t); 139 static uint32_t mspcic_bus_read_4(bus_space_tag_t, bus_space_handle_t, 140 bus_size_t); 141 static uint64_t mspcic_bus_read_8(bus_space_tag_t, bus_space_handle_t, 142 bus_size_t); 143 static void mspcic_bus_write_2(bus_space_tag_t, bus_space_handle_t, 144 bus_size_t, uint16_t); 145 static void mspcic_bus_write_4(bus_space_tag_t, bus_space_handle_t, 146 bus_size_t, uint32_t); 147 static void mspcic_bus_write_8(bus_space_tag_t, bus_space_handle_t, 148 bus_size_t, uint64_t); 149 150 static struct sparc_bus_space_tag mspcic_io_tag; 151 static struct sparc_bus_space_tag mspcic_mem_tag; 152 153 154 /* 155 * DMA tag 156 */ 157 static int mspcic_dmamap_load(bus_dma_tag_t, bus_dmamap_t, 158 void *, bus_size_t, struct proc *, int); 159 static void mspcic_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 160 static int mspcic_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, 161 int, size_t, void **, int); 162 163 static struct sparc_bus_dma_tag mspcic_dma_tag = { 164 NULL, /* _cookie */ 165 166 _bus_dmamap_create, 167 _bus_dmamap_destroy, 168 mspcic_dmamap_load, 169 _bus_dmamap_load_mbuf, 170 _bus_dmamap_load_uio, 171 _bus_dmamap_load_raw, 172 mspcic_dmamap_unload, 173 _bus_dmamap_sync, 174 175 _bus_dmamem_alloc, 176 _bus_dmamem_free, 177 mspcic_dmamem_map, 178 _bus_dmamem_unmap, 179 _bus_dmamem_mmap 180 }; 181 182 183 static int 184 msiiep_match(device_t parent, cfdata_t cf, void *aux) 185 { 186 struct mainbus_attach_args *ma = aux; 187 pcireg_t id; 188 189 /* match by PROM name */ 190 if (strcmp(ma->ma_name, "pci") != 0) 191 return (0); 192 193 /* 194 * Verify that PCIC was successfully mapped by bootstrap code. 195 * Since PCIC contains all the registers vital to the kernel, 196 * bootstrap code maps them at a fixed va, MSIIEP_PCIC_VA 197 */ 198 id = mspcic_read_4(pcic_id); 199 if (PCI_VENDOR(id) != PCI_VENDOR_SUN 200 && PCI_PRODUCT(id) != PCI_PRODUCT_SUN_MS_IIep) 201 panic("msiiep_match: id %08x", id); 202 203 return (1); 204 } 205 206 207 static void 208 msiiep_attach(device_t parent, device_t self, void *aux) 209 { 210 struct mainbus_attach_args *ma = aux; 211 struct msiiep_attach_args msa; 212 bus_space_handle_t hmid; 213 struct cpu_info *cur; 214 215 aprint_normal("\n"); 216 217 if (bus_space_map(ma->ma_bustag, MSIIEP_MID_PA, 4, 0, &hmid) == 0) { 218 #ifdef DIAGNOSTICS 219 uint32_t mid; 220 221 mid = bus_space_read_4(ma->ma_bustag, hmid, 0); 222 printf("MID: %08x\n", mid); 223 #endif 224 msiiep_mid = (volatile uint32_t *)bus_space_vaddr(ma->ma_bustag, 225 hmid); 226 cur = curcpu(); 227 cur->idlespin = msiiep_cpu_sleep; 228 } 229 230 devhandle_t selfh = device_handle(self); 231 232 /* pass on real mainbus_attach_args */ 233 msa.msa_ma = ma; 234 KASSERT(prom_devhandle_to_node(selfh) == ma->ma_node); 235 236 /* config timer/counter part of PCIC */ 237 msa.msa_name = "timer"; 238 config_found(self, &msa, NULL, CFARGS_NONE); 239 240 /* config PCI tree */ 241 msa.msa_name = "pcic"; 242 config_found(self, &msa, NULL, 243 CFARGS(.devhandle = selfh)); 244 } 245 246 /* ARGSUSED */ 247 void 248 msiiep_cpu_sleep(void) 249 { 250 uint32_t reg; 251 252 if (msiiep_mid == 0) 253 return; 254 reg = *msiiep_mid; 255 *msiiep_mid = (reg & MID_MASK) | MID_STANDBY; 256 } 257 258 259 /* ====================================================================== 260 * 261 * Real ms-IIep PCIC driver. 262 */ 263 264 static int 265 mspcic_match(device_t parent, cfdata_t cf, void *aux) 266 { 267 struct msiiep_attach_args *msa = aux; 268 269 return (strcmp(msa->msa_name, "pcic") == 0); 270 } 271 272 273 static void 274 mspcic_attach(device_t parent, device_t self, void *aux) 275 { 276 struct mspcic_softc *sc = device_private(self); 277 devhandle_t selfh = device_handle(self); 278 struct msiiep_attach_args *msa = aux; 279 struct mainbus_attach_args *ma = msa->msa_ma; 280 int node = ma->ma_node; 281 char devinfo[256], buf[32], *model; 282 283 struct pcibus_attach_args pba; 284 285 sc->sc_node = node; 286 KASSERT(prom_devhandle_to_node(selfh) == node); 287 288 /* copy parent tags */ 289 sc->sc_bustag = ma->ma_bustag; 290 sc->sc_dmatag = ma->ma_dmatag; 291 292 /* print our PCI device info and bus clock frequency */ 293 pci_devinfo(mspcic_read_4(pcic_id), mspcic_read_4(pcic_class), 0, 294 devinfo, sizeof(devinfo)); 295 printf(": %s: clock = %s MHz\n", devinfo, 296 clockfreq(prom_getpropint(node, "clock-frequency", 33333333))); 297 298 mspcic_init_maps(); 299 300 /* 301 * On Espresso, we need to adjust the interrupt mapping on 302 * lines 4-7, as onboard devices and cards in the PCI slots use 303 * those lines. Note, that enabling line 5 (onboard ide) causes 304 * a continuous interrupt stream, so leave that unmapped (0). 305 * Any other device using line 5 can't be used. 306 * Interrupt line wiring for slots is set in pci_machdep.c. 307 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise 308 * we'll lock up when using devices behind a PCI-PCI bridge. 309 */ 310 model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf)); 311 if (model != NULL && !strcmp(model, "SUNW,375-0059")) { 312 mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502); 313 mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000); 314 } 315 316 /* init cookies/parents in our statically allocated tags */ 317 mspcic_io_tag = *sc->sc_bustag; 318 mspcic_io_tag.cookie = &mspcic_io_cookie; 319 mspcic_io_tag.ranges = NULL; 320 mspcic_io_tag.nranges = 0; 321 mspcic_io_tag.sparc_bus_map = mspcic_bus_map; 322 mspcic_io_tag.sparc_bus_mmap = mspcic_bus_mmap; 323 mspcic_io_tag.sparc_intr_establish = mspcic_intr_establish; 324 mspcic_io_tag.parent = sc->sc_bustag; 325 326 mspcic_io_tag.sparc_read_2 = mspcic_bus_read_2; 327 mspcic_io_tag.sparc_read_4 = mspcic_bus_read_4; 328 mspcic_io_tag.sparc_read_8 = mspcic_bus_read_8; 329 mspcic_io_tag.sparc_write_2 = mspcic_bus_write_2; 330 mspcic_io_tag.sparc_write_4 = mspcic_bus_write_4; 331 mspcic_io_tag.sparc_write_8 = mspcic_bus_write_8; 332 333 mspcic_mem_tag = *sc->sc_bustag; 334 mspcic_mem_tag.cookie = &mspcic_mem_cookie; 335 mspcic_mem_tag.ranges = NULL; 336 mspcic_mem_tag.nranges = 0; 337 mspcic_mem_tag.sparc_bus_map = mspcic_bus_map; 338 mspcic_mem_tag.sparc_bus_mmap = mspcic_bus_mmap; 339 mspcic_mem_tag.sparc_intr_establish = mspcic_intr_establish; 340 mspcic_mem_tag.parent = sc->sc_bustag; 341 342 mspcic_mem_tag.sparc_read_2 = mspcic_bus_read_2; 343 mspcic_mem_tag.sparc_read_4 = mspcic_bus_read_4; 344 mspcic_mem_tag.sparc_read_8 = mspcic_bus_read_8; 345 mspcic_mem_tag.sparc_write_2 = mspcic_bus_write_2; 346 mspcic_mem_tag.sparc_write_4 = mspcic_bus_write_4; 347 mspcic_mem_tag.sparc_write_8 = mspcic_bus_write_8; 348 349 mspcic_dma_tag._cookie = sc; 350 mspcic_pc_tag.cookie = sc; 351 352 /* save bus tags in softc */ 353 sc->sc_iot = &mspcic_io_tag; 354 sc->sc_memt = &mspcic_mem_tag; 355 sc->sc_dmat = &mspcic_dma_tag; 356 357 /* 358 * Attach the PCI bus. 359 */ 360 pba.pba_bus = 0; 361 pba.pba_bridgetag = NULL; 362 pba.pba_iot = sc->sc_iot; 363 pba.pba_memt = sc->sc_memt; 364 pba.pba_dmat = sc->sc_dmat; 365 pba.pba_dmat64 = NULL; 366 pba.pba_pc = &mspcic_pc_tag; 367 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 368 369 mspcic_pci_scan(sc->sc_node); 370 371 config_found(self, &pba, mspcic_print, 372 CFARGS(.devhandle = selfh)); 373 } 374 375 376 static int 377 mspcic_print(void *args, const char *busname) 378 { 379 380 if (busname == NULL) 381 return (UNCONF); 382 return (QUIET); 383 } 384 385 386 /* 387 * Get the PIL currently assigned for this interrupt input line. 388 */ 389 int 390 mspcic_assigned_interrupt(int line) 391 { 392 unsigned int intrmap; 393 394 if (line < 0 || line > 7) 395 return (-1); 396 397 if (line < 4) { 398 intrmap = mspcic_read_2(pcic_intr_asgn_sel); 399 } else { 400 intrmap = mspcic_read_2(pcic_intr_asgn_sel_hi); 401 line -= 4; 402 } 403 return ((intrmap >> (line * 4)) & 0xf); 404 } 405 406 407 /* ====================================================================== 408 * 409 * BUS space methods 410 */ 411 412 static inline void 413 mspcic_pci_map_from_reg(struct mspcic_pci_map *m, 414 uint8_t sbar, uint8_t pbar, uint8_t sizemask) 415 { 416 m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24); 417 m->pcibase = pbar << 24; 418 m->size = ~((0xf0 | sizemask) << 24) + 1; 419 } 420 421 422 /* does [al, ar) and [bl, br) overlap? */ 423 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar))) 424 425 /* does map "m" overlap with fixed mapping region? */ 426 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \ 427 0x30000000, 0x31000000) 428 429 /* does map "ma" overlap map "mb" (possibly NULL)? */ 430 #define OVERLAP_MAP(ma, mb) \ 431 ((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \ 432 (mb)->sysbase, (mb)->sysbase + (mb)->size)) 433 434 /* 435 * Init auxiliary paddr->pci maps. 436 */ 437 static void 438 mspcic_init_maps(void) 439 { 440 struct mspcic_pci_map *m0, *m1, *io; 441 int nmem, nio; 442 443 #ifdef DEBUG 444 printf("mspcic0: SMBAR0 %02x PMBAR0 %02x MSIZE0 %02x\n", 445 mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0), 446 mspcic_read_1(pcic_msize0)); 447 printf("mspcic0: SMBAR1 %02x PMBAR1 %02x MSIZE1 %02x\n", 448 mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1), 449 mspcic_read_1(pcic_msize1)); 450 printf("mspcic0: SIBAR %02x PIBAR %02x IOSIZE %02x\n", 451 mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar), 452 mspcic_read_1(pcic_iosize)); 453 #endif 454 nmem = nio = 1; 455 456 m0 = &mspcic_pci_memmap[nmem]; 457 mspcic_pci_map_from_reg(m0, 458 mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0), 459 mspcic_read_1(pcic_msize0)); 460 if (OVERLAP_FIXED(m0)) 461 m0 = NULL; 462 else 463 ++nmem; 464 465 m1 = &mspcic_pci_memmap[nmem]; 466 mspcic_pci_map_from_reg(m1, 467 mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1), 468 mspcic_read_1(pcic_msize1)); 469 if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0)) 470 m1 = NULL; 471 else 472 ++nmem; 473 474 io = &mspcic_pci_iomap[nio]; 475 mspcic_pci_map_from_reg(io, 476 mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar), 477 mspcic_read_1(pcic_iosize)); 478 if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1)) 479 io = NULL; 480 else 481 ++nio; 482 483 mspcic_io_cookie.nmaps = nio; 484 mspcic_mem_cookie.nmaps = nmem; 485 486 #ifdef DEBUG 487 mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed"); 488 mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed"); 489 if (m0) mspcic_pci_map_print(m0, "mem map0"); 490 if (m1) mspcic_pci_map_print(m1, "mem map1"); 491 if (io) mspcic_pci_map_print(io, "i/0 map"); 492 #endif 493 } 494 495 496 #ifdef DEBUG 497 static void 498 mspcic_pci_map_print(struct mspcic_pci_map *m, const char *msg) 499 { 500 printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n", 501 m->sysbase, m->sysbase + m->size - 1, 502 m->pcibase, m->pcibase + m->size - 1, 503 msg); 504 } 505 #endif 506 507 508 static bus_addr_t 509 mspcic_pci_map_find(struct mspcic_pci_map *m, int nmaps, 510 bus_addr_t pciaddr, bus_size_t size) 511 { 512 bus_size_t offset; 513 int i; 514 515 for (i = 0; i < nmaps; ++i, ++m) { 516 offset = pciaddr - m->pcibase; 517 if (offset + size <= m->size) 518 return (m->sysbase + offset); 519 } 520 return (0); 521 } 522 523 524 static int 525 mspcic_bus_map(bus_space_tag_t t, bus_addr_t ba, bus_size_t size, 526 int flags, vaddr_t va, bus_space_handle_t *hp) 527 { 528 struct mspcic_cookie *c = t->cookie; 529 bus_addr_t paddr; 530 531 paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size); 532 if (paddr == 0) 533 return (EINVAL); 534 return (bus_space_map2(t->parent, paddr, size, flags, va, hp)); 535 } 536 537 538 static paddr_t 539 mspcic_bus_mmap(bus_space_tag_t t, bus_addr_t ba, off_t off, 540 int prot, int flags) 541 { 542 struct mspcic_cookie *c = t->cookie; 543 bus_addr_t paddr; 544 545 /* verify that phys to pci mapping for the target page exists */ 546 paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE); 547 if (paddr == 0) 548 return (-1); 549 550 return (bus_space_mmap(t->parent, paddr - off, off, prot, flags)); 551 } 552 553 554 /* 555 * Install an interrupt handler. 556 * 557 * Bus-specific interrupt argument is 'line', an interrupt input line 558 * for ms-IIep. The PIL for each line is programmable via pcic interrupt 559 * assignment select registers (but we use existing assignments). 560 */ 561 static void * 562 mspcic_intr_establish(bus_space_tag_t t, int line, int ipl, 563 int (*handler)(void *), void *arg, 564 void (*fastvec)(void)) 565 { 566 struct intrhand *ih; 567 int pil; 568 569 ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 570 571 /* use pil set-up by prom */ 572 pil = mspcic_assigned_interrupt(line); 573 if (pil == -1) 574 panic("mspcic_intr_establish: line %d", line); 575 576 ih->ih_fun = handler; 577 ih->ih_arg = arg; 578 intr_establish(pil, ipl, ih, fastvec, false); 579 580 return(ih); 581 } 582 583 584 static uint16_t 585 mspcic_bus_read_2(bus_space_tag_t space, bus_space_handle_t handle, 586 bus_size_t offset) 587 { 588 uint16_t val = *(volatile uint16_t *)(handle + offset); 589 590 return le16toh(val); 591 } 592 593 594 static uint32_t 595 mspcic_bus_read_4(bus_space_tag_t space, bus_space_handle_t handle, 596 bus_size_t offset) 597 { 598 uint32_t val = *(volatile uint32_t *)(handle + offset); 599 600 return le32toh(val); 601 } 602 603 604 static uint64_t 605 mspcic_bus_read_8(bus_space_tag_t space, bus_space_handle_t handle, 606 bus_size_t offset) 607 { 608 uint64_t val = *(volatile uint64_t *)(handle + offset); 609 610 return le64toh(val); 611 } 612 613 614 static void 615 mspcic_bus_write_2(bus_space_tag_t space, bus_space_handle_t handle, 616 bus_size_t offset, uint16_t value) 617 { 618 619 (*(volatile uint16_t *)(handle + offset)) = htole16(value); 620 } 621 622 623 static void 624 mspcic_bus_write_4(bus_space_tag_t space, bus_space_handle_t handle, 625 bus_size_t offset, uint32_t value) 626 { 627 628 (*(volatile uint32_t *)(handle + offset)) = htole32(value); 629 } 630 631 632 static void 633 mspcic_bus_write_8(bus_space_tag_t space, bus_space_handle_t handle, 634 bus_size_t offset, uint64_t value) 635 { 636 637 (*(volatile uint64_t *)(handle + offset)) = htole64(value); 638 } 639 640 641 /* ====================================================================== 642 * 643 * DMA methods 644 */ 645 646 static int 647 mspcic_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, 648 void *buf, bus_size_t buflen, 649 struct proc *p, int flags) 650 { 651 pmap_t pmap; 652 paddr_t pa; 653 654 if (p != NULL) 655 pmap = p->p_vmspace->vm_map.pmap; 656 else 657 pmap = pmap_kernel(); 658 659 if (!pmap_extract(pmap, (vaddr_t)buf, &pa)) 660 panic("mspcic_dmamap_load: dma memory not mapped"); 661 662 /* we always use just one segment */ 663 map->dm_nsegs = 1; 664 map->dm_segs[0].ds_addr = pa; 665 map->dm_segs[0].ds_len = buflen; 666 map->dm_mapsize = buflen; 667 668 return (0); 669 } 670 671 static void 672 mspcic_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) 673 { 674 675 /* Mark the mappings as invalid. */ 676 map->dm_mapsize = 0; 677 map->dm_nsegs = 0; 678 } 679 680 681 static int 682 mspcic_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, 683 size_t size, void **kvap, int flags) 684 { 685 struct pglist *mlist; 686 struct vm_page *m; 687 vaddr_t va; 688 int pagesz = PAGE_SIZE; 689 const uvm_flag_t kmflags = 690 (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0; 691 692 if (nsegs != 1) 693 panic("mspcic_dmamem_map: nsegs = %d", nsegs); 694 695 size = round_page(size); 696 697 va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags); 698 if (va == 0) 699 return (ENOMEM); 700 701 segs[0]._ds_va = va; 702 *kvap = (void *)va; 703 704 /* 705 * Map the pages allocated in _bus_dmamem_alloc() 706 * to the kernel virtual address space. 707 */ 708 mlist = segs[0]._ds_mlist; 709 TAILQ_FOREACH(m, mlist, pageq.queue) { 710 paddr_t pa; 711 712 if (size == 0) 713 panic("mspcic_dmamem_map: size botch"); 714 715 pa = VM_PAGE_TO_PHYS(m); 716 pmap_kenter_pa(va, 717 pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE, 0); 718 va += pagesz; 719 size -= pagesz; 720 } 721 pmap_update(pmap_kernel()); 722 723 return (0); 724 } 725