1 /* $NetBSD: msiiep.c,v 1.53 2022/01/21 19:14:14 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.53 2022/01/21 19:14:14 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 /* pass on real mainbus_attach_args */ 231 msa.msa_ma = ma; 232 233 /* config timer/counter part of PCIC */ 234 msa.msa_name = "timer"; 235 config_found(self, &msa, NULL, CFARGS_NONE); 236 237 /* config PCI tree */ 238 msa.msa_name = "pcic"; 239 config_found(self, &msa, NULL, CFARGS_NONE); 240 } 241 242 /* ARGSUSED */ 243 void 244 msiiep_cpu_sleep(void) 245 { 246 uint32_t reg; 247 248 if (msiiep_mid == 0) 249 return; 250 reg = *msiiep_mid; 251 *msiiep_mid = (reg & MID_MASK) | MID_STANDBY; 252 } 253 254 255 /* ====================================================================== 256 * 257 * Real ms-IIep PCIC driver. 258 */ 259 260 static int 261 mspcic_match(device_t parent, cfdata_t cf, void *aux) 262 { 263 struct msiiep_attach_args *msa = aux; 264 265 return (strcmp(msa->msa_name, "pcic") == 0); 266 } 267 268 269 static void 270 mspcic_attach(device_t parent, device_t self, void *aux) 271 { 272 struct mspcic_softc *sc = device_private(self); 273 struct msiiep_attach_args *msa = aux; 274 struct mainbus_attach_args *ma = msa->msa_ma; 275 int node = ma->ma_node; 276 char devinfo[256], buf[32], *model; 277 278 struct pcibus_attach_args pba; 279 280 sc->sc_node = node; 281 282 /* copy parent tags */ 283 sc->sc_bustag = ma->ma_bustag; 284 sc->sc_dmatag = ma->ma_dmatag; 285 286 /* print our PCI device info and bus clock frequency */ 287 pci_devinfo(mspcic_read_4(pcic_id), mspcic_read_4(pcic_class), 0, 288 devinfo, sizeof(devinfo)); 289 printf(": %s: clock = %s MHz\n", devinfo, 290 clockfreq(prom_getpropint(node, "clock-frequency", 33333333))); 291 292 mspcic_init_maps(); 293 294 /* 295 * On Espresso, we need to adjust the interrupt mapping on 296 * lines 4-7, as onboard devices and cards in the PCI slots use 297 * those lines. Note, that enabling line 5 (onboard ide) causes 298 * a continuous interrupt stream, so leave that unmapped (0). 299 * Any other device using line 5 can't be used. 300 * Interrupt line wiring for slots is set in pci_machdep.c. 301 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise 302 * we'll lock up when using devices behind a PCI-PCI bridge. 303 */ 304 model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf)); 305 if (model != NULL && !strcmp(model, "SUNW,375-0059")) { 306 mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502); 307 mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000); 308 } 309 310 /* init cookies/parents in our statically allocated tags */ 311 mspcic_io_tag = *sc->sc_bustag; 312 mspcic_io_tag.cookie = &mspcic_io_cookie; 313 mspcic_io_tag.ranges = NULL; 314 mspcic_io_tag.nranges = 0; 315 mspcic_io_tag.sparc_bus_map = mspcic_bus_map; 316 mspcic_io_tag.sparc_bus_mmap = mspcic_bus_mmap; 317 mspcic_io_tag.sparc_intr_establish = mspcic_intr_establish; 318 mspcic_io_tag.parent = sc->sc_bustag; 319 320 mspcic_io_tag.sparc_read_2 = mspcic_bus_read_2; 321 mspcic_io_tag.sparc_read_4 = mspcic_bus_read_4; 322 mspcic_io_tag.sparc_read_8 = mspcic_bus_read_8; 323 mspcic_io_tag.sparc_write_2 = mspcic_bus_write_2; 324 mspcic_io_tag.sparc_write_4 = mspcic_bus_write_4; 325 mspcic_io_tag.sparc_write_8 = mspcic_bus_write_8; 326 327 mspcic_mem_tag = *sc->sc_bustag; 328 mspcic_mem_tag.cookie = &mspcic_mem_cookie; 329 mspcic_mem_tag.ranges = NULL; 330 mspcic_mem_tag.nranges = 0; 331 mspcic_mem_tag.sparc_bus_map = mspcic_bus_map; 332 mspcic_mem_tag.sparc_bus_mmap = mspcic_bus_mmap; 333 mspcic_mem_tag.sparc_intr_establish = mspcic_intr_establish; 334 mspcic_mem_tag.parent = sc->sc_bustag; 335 336 mspcic_mem_tag.sparc_read_2 = mspcic_bus_read_2; 337 mspcic_mem_tag.sparc_read_4 = mspcic_bus_read_4; 338 mspcic_mem_tag.sparc_read_8 = mspcic_bus_read_8; 339 mspcic_mem_tag.sparc_write_2 = mspcic_bus_write_2; 340 mspcic_mem_tag.sparc_write_4 = mspcic_bus_write_4; 341 mspcic_mem_tag.sparc_write_8 = mspcic_bus_write_8; 342 343 mspcic_dma_tag._cookie = sc; 344 mspcic_pc_tag.cookie = sc; 345 346 /* save bus tags in softc */ 347 sc->sc_iot = &mspcic_io_tag; 348 sc->sc_memt = &mspcic_mem_tag; 349 sc->sc_dmat = &mspcic_dma_tag; 350 351 /* 352 * Attach the PCI bus. 353 */ 354 pba.pba_bus = 0; 355 pba.pba_bridgetag = NULL; 356 pba.pba_iot = sc->sc_iot; 357 pba.pba_memt = sc->sc_memt; 358 pba.pba_dmat = sc->sc_dmat; 359 pba.pba_dmat64 = NULL; 360 pba.pba_pc = &mspcic_pc_tag; 361 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 362 363 mspcic_pci_scan(sc->sc_node); 364 365 config_found(self, &pba, mspcic_print, 366 CFARGS(.devhandle = device_handle(self))); 367 } 368 369 370 static int 371 mspcic_print(void *args, const char *busname) 372 { 373 374 if (busname == NULL) 375 return (UNCONF); 376 return (QUIET); 377 } 378 379 380 /* 381 * Get the PIL currently assigned for this interrupt input line. 382 */ 383 int 384 mspcic_assigned_interrupt(int line) 385 { 386 unsigned int intrmap; 387 388 if (line < 0 || line > 7) 389 return (-1); 390 391 if (line < 4) { 392 intrmap = mspcic_read_2(pcic_intr_asgn_sel); 393 } else { 394 intrmap = mspcic_read_2(pcic_intr_asgn_sel_hi); 395 line -= 4; 396 } 397 return ((intrmap >> (line * 4)) & 0xf); 398 } 399 400 401 /* ====================================================================== 402 * 403 * BUS space methods 404 */ 405 406 static inline void 407 mspcic_pci_map_from_reg(struct mspcic_pci_map *m, 408 uint8_t sbar, uint8_t pbar, uint8_t sizemask) 409 { 410 m->sysbase = 0x30000000 | ((sbar & 0x0f) << 24); 411 m->pcibase = pbar << 24; 412 m->size = ~((0xf0 | sizemask) << 24) + 1; 413 } 414 415 416 /* does [al, ar) and [bl, br) overlap? */ 417 #define OVERLAP(al, ar, bl, br) (((al) < (br)) && ((bl) < (ar))) 418 419 /* does map "m" overlap with fixed mapping region? */ 420 #define OVERLAP_FIXED(m) OVERLAP((m)->sysbase, (m)->sysbase + (m)->size, \ 421 0x30000000, 0x31000000) 422 423 /* does map "ma" overlap map "mb" (possibly NULL)? */ 424 #define OVERLAP_MAP(ma, mb) \ 425 ((mb != NULL) && OVERLAP((ma)->sysbase, (ma)->sysbase + (ma)->size, \ 426 (mb)->sysbase, (mb)->sysbase + (mb)->size)) 427 428 /* 429 * Init auxiliary paddr->pci maps. 430 */ 431 static void 432 mspcic_init_maps(void) 433 { 434 struct mspcic_pci_map *m0, *m1, *io; 435 int nmem, nio; 436 437 #ifdef DEBUG 438 printf("mspcic0: SMBAR0 %02x PMBAR0 %02x MSIZE0 %02x\n", 439 mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0), 440 mspcic_read_1(pcic_msize0)); 441 printf("mspcic0: SMBAR1 %02x PMBAR1 %02x MSIZE1 %02x\n", 442 mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1), 443 mspcic_read_1(pcic_msize1)); 444 printf("mspcic0: SIBAR %02x PIBAR %02x IOSIZE %02x\n", 445 mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar), 446 mspcic_read_1(pcic_iosize)); 447 #endif 448 nmem = nio = 1; 449 450 m0 = &mspcic_pci_memmap[nmem]; 451 mspcic_pci_map_from_reg(m0, 452 mspcic_read_1(pcic_smbar0), mspcic_read_1(pcic_pmbar0), 453 mspcic_read_1(pcic_msize0)); 454 if (OVERLAP_FIXED(m0)) 455 m0 = NULL; 456 else 457 ++nmem; 458 459 m1 = &mspcic_pci_memmap[nmem]; 460 mspcic_pci_map_from_reg(m1, 461 mspcic_read_1(pcic_smbar1), mspcic_read_1(pcic_pmbar1), 462 mspcic_read_1(pcic_msize1)); 463 if (OVERLAP_FIXED(m1) || OVERLAP_MAP(m1, m0)) 464 m1 = NULL; 465 else 466 ++nmem; 467 468 io = &mspcic_pci_iomap[nio]; 469 mspcic_pci_map_from_reg(io, 470 mspcic_read_1(pcic_sibar), mspcic_read_1(pcic_pibar), 471 mspcic_read_1(pcic_iosize)); 472 if (OVERLAP_FIXED(io) || OVERLAP_MAP(io, m0) || OVERLAP_MAP(io, m1)) 473 io = NULL; 474 else 475 ++nio; 476 477 mspcic_io_cookie.nmaps = nio; 478 mspcic_mem_cookie.nmaps = nmem; 479 480 #ifdef DEBUG 481 mspcic_pci_map_print(&mspcic_pci_iomap[0], "i/o fixed"); 482 mspcic_pci_map_print(&mspcic_pci_memmap[0], "mem fixed"); 483 if (m0) mspcic_pci_map_print(m0, "mem map0"); 484 if (m1) mspcic_pci_map_print(m1, "mem map1"); 485 if (io) mspcic_pci_map_print(io, "i/0 map"); 486 #endif 487 } 488 489 490 #ifdef DEBUG 491 static void 492 mspcic_pci_map_print(struct mspcic_pci_map *m, const char *msg) 493 { 494 printf("mspcic0: paddr [%08x..%08x] -> pci [%08x..%08x] %s\n", 495 m->sysbase, m->sysbase + m->size - 1, 496 m->pcibase, m->pcibase + m->size - 1, 497 msg); 498 } 499 #endif 500 501 502 static bus_addr_t 503 mspcic_pci_map_find(struct mspcic_pci_map *m, int nmaps, 504 bus_addr_t pciaddr, bus_size_t size) 505 { 506 bus_size_t offset; 507 int i; 508 509 for (i = 0; i < nmaps; ++i, ++m) { 510 offset = pciaddr - m->pcibase; 511 if (offset + size <= m->size) 512 return (m->sysbase + offset); 513 } 514 return (0); 515 } 516 517 518 static int 519 mspcic_bus_map(bus_space_tag_t t, bus_addr_t ba, bus_size_t size, 520 int flags, vaddr_t va, bus_space_handle_t *hp) 521 { 522 struct mspcic_cookie *c = t->cookie; 523 bus_addr_t paddr; 524 525 paddr = mspcic_pci_map_find(c->map, c->nmaps, ba, size); 526 if (paddr == 0) 527 return (EINVAL); 528 return (bus_space_map2(t->parent, paddr, size, flags, va, hp)); 529 } 530 531 532 static paddr_t 533 mspcic_bus_mmap(bus_space_tag_t t, bus_addr_t ba, off_t off, 534 int prot, int flags) 535 { 536 struct mspcic_cookie *c = t->cookie; 537 bus_addr_t paddr; 538 539 /* verify that phys to pci mapping for the target page exists */ 540 paddr = mspcic_pci_map_find(c->map, c->nmaps, ba + off, PAGE_SIZE); 541 if (paddr == 0) 542 return (-1); 543 544 return (bus_space_mmap(t->parent, paddr - off, off, prot, flags)); 545 } 546 547 548 /* 549 * Install an interrupt handler. 550 * 551 * Bus-specific interrupt argument is 'line', an interrupt input line 552 * for ms-IIep. The PIL for each line is programmable via pcic interrupt 553 * assignment select registers (but we use existing assignments). 554 */ 555 static void * 556 mspcic_intr_establish(bus_space_tag_t t, int line, int ipl, 557 int (*handler)(void *), void *arg, 558 void (*fastvec)(void)) 559 { 560 struct intrhand *ih; 561 int pil; 562 563 ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 564 565 /* use pil set-up by prom */ 566 pil = mspcic_assigned_interrupt(line); 567 if (pil == -1) 568 panic("mspcic_intr_establish: line %d", line); 569 570 ih->ih_fun = handler; 571 ih->ih_arg = arg; 572 intr_establish(pil, ipl, ih, fastvec, false); 573 574 return(ih); 575 } 576 577 578 static uint16_t 579 mspcic_bus_read_2(bus_space_tag_t space, bus_space_handle_t handle, 580 bus_size_t offset) 581 { 582 uint16_t val = *(volatile uint16_t *)(handle + offset); 583 584 return le16toh(val); 585 } 586 587 588 static uint32_t 589 mspcic_bus_read_4(bus_space_tag_t space, bus_space_handle_t handle, 590 bus_size_t offset) 591 { 592 uint32_t val = *(volatile uint32_t *)(handle + offset); 593 594 return le32toh(val); 595 } 596 597 598 static uint64_t 599 mspcic_bus_read_8(bus_space_tag_t space, bus_space_handle_t handle, 600 bus_size_t offset) 601 { 602 uint64_t val = *(volatile uint64_t *)(handle + offset); 603 604 return le64toh(val); 605 } 606 607 608 static void 609 mspcic_bus_write_2(bus_space_tag_t space, bus_space_handle_t handle, 610 bus_size_t offset, uint16_t value) 611 { 612 613 (*(volatile uint16_t *)(handle + offset)) = htole16(value); 614 } 615 616 617 static void 618 mspcic_bus_write_4(bus_space_tag_t space, bus_space_handle_t handle, 619 bus_size_t offset, uint32_t value) 620 { 621 622 (*(volatile uint32_t *)(handle + offset)) = htole32(value); 623 } 624 625 626 static void 627 mspcic_bus_write_8(bus_space_tag_t space, bus_space_handle_t handle, 628 bus_size_t offset, uint64_t value) 629 { 630 631 (*(volatile uint64_t *)(handle + offset)) = htole64(value); 632 } 633 634 635 /* ====================================================================== 636 * 637 * DMA methods 638 */ 639 640 static int 641 mspcic_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, 642 void *buf, bus_size_t buflen, 643 struct proc *p, int flags) 644 { 645 pmap_t pmap; 646 paddr_t pa; 647 648 if (p != NULL) 649 pmap = p->p_vmspace->vm_map.pmap; 650 else 651 pmap = pmap_kernel(); 652 653 if (!pmap_extract(pmap, (vaddr_t)buf, &pa)) 654 panic("mspcic_dmamap_load: dma memory not mapped"); 655 656 /* we always use just one segment */ 657 map->dm_nsegs = 1; 658 map->dm_segs[0].ds_addr = pa; 659 map->dm_segs[0].ds_len = buflen; 660 map->dm_mapsize = buflen; 661 662 return (0); 663 } 664 665 static void 666 mspcic_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) 667 { 668 669 /* Mark the mappings as invalid. */ 670 map->dm_mapsize = 0; 671 map->dm_nsegs = 0; 672 } 673 674 675 static int 676 mspcic_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, 677 size_t size, void **kvap, int flags) 678 { 679 struct pglist *mlist; 680 struct vm_page *m; 681 vaddr_t va; 682 int pagesz = PAGE_SIZE; 683 const uvm_flag_t kmflags = 684 (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0; 685 686 if (nsegs != 1) 687 panic("mspcic_dmamem_map: nsegs = %d", nsegs); 688 689 size = round_page(size); 690 691 va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags); 692 if (va == 0) 693 return (ENOMEM); 694 695 segs[0]._ds_va = va; 696 *kvap = (void *)va; 697 698 /* 699 * Map the pages allocated in _bus_dmamem_alloc() 700 * to the kernel virtual address space. 701 */ 702 mlist = segs[0]._ds_mlist; 703 TAILQ_FOREACH(m, mlist, pageq.queue) { 704 paddr_t pa; 705 706 if (size == 0) 707 panic("mspcic_dmamem_map: size botch"); 708 709 pa = VM_PAGE_TO_PHYS(m); 710 pmap_kenter_pa(va, 711 pa | PMAP_NC, VM_PROT_READ | VM_PROT_WRITE, 0); 712 va += pagesz; 713 size -= pagesz; 714 } 715 pmap_update(pmap_kernel()); 716 717 return (0); 718 } 719