1 /* $NetBSD: pic_u3_ht.c,v 1.14 2023/01/12 01:19:21 macallan Exp $ */ 2 /*- 3 * Copyright (c) 2013 Phileas Fogg 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: pic_u3_ht.c,v 1.14 2023/01/12 01:19:21 macallan Exp $"); 30 31 #include "opt_openpic.h" 32 #include "opt_interrupt.h" 33 34 #include <sys/param.h> 35 #include <sys/kmem.h> 36 #include <sys/kernel.h> 37 #include <sys/atomic.h> 38 #include <sys/cpu.h> 39 40 #include <machine/pio.h> 41 #include <powerpc/openpic.h> 42 43 #include <dev/ofw/openfirm.h> 44 #include <dev/ofw/ofw_pci.h> 45 #include <dev/pci/pcireg.h> 46 47 #include <machine/autoconf.h> 48 #include <arch/powerpc/pic/picvar.h> 49 50 #ifdef U3_HT_PIC_DEBUG 51 #define DPRINTF aprint_error 52 #else 53 #define DPRINTF if (0) printf 54 #endif 55 56 #define HTAPIC_REQUEST_EOI 0x20 57 #define HTAPIC_TRIGGER_LEVEL 0x02 58 #define HTAPIC_MASK 0x01 59 60 struct u3_ht_irqmap { 61 int im_index; 62 int im_level; 63 volatile uint8_t *im_base; 64 volatile uint8_t *im_apple_base; 65 uint32_t im_data; 66 }; 67 68 struct u3_ht_ops { 69 struct pic_ops pic; 70 71 volatile uint8_t *ht_base; 72 73 struct u3_ht_irqmap ht_irqmap[128]; 74 75 uint32_t (*ht_read)(struct u3_ht_ops *, u_int); 76 void (*ht_write)(struct u3_ht_ops *, u_int, uint32_t); 77 }; 78 79 #define u3_ht_read(ptr,reg) (ptr)->ht_read(ptr, reg) 80 #define u3_ht_write(ptr,reg,val) (ptr)->ht_write(ptr, reg, val) 81 82 static struct u3_ht_ops *setup_u3_ht(uint32_t, uint32_t, int, int); 83 static int setup_u3_ht_workarounds(struct u3_ht_ops *); 84 85 static void u3_ht_enable_irq(struct pic_ops *, int, int); 86 static void u3_ht_disable_irq(struct pic_ops *, int); 87 static int u3_ht_get_irq(struct pic_ops *, int); 88 static void u3_ht_ack_irq(struct pic_ops *, int); 89 static void u3_ht_establish_irq(struct pic_ops *, int, int, int); 90 static void u3_ht_finish_setup(struct pic_ops *); 91 92 static int u3_ht_is_ht_irq(struct u3_ht_ops *, int); 93 static void u3_ht_establish_ht_irq(struct u3_ht_ops *, int, int); 94 static void u3_ht_enable_ht_irq(struct u3_ht_ops *, int); 95 static void u3_ht_disable_ht_irq(struct u3_ht_ops *, int); 96 static void u3_ht_ack_ht_irq(struct u3_ht_ops *, int); 97 98 static void u3_ht_set_priority(struct u3_ht_ops *, int, int); 99 void __u3_ht_set_priority(int, int); 100 static int u3_ht_read_irq(struct u3_ht_ops *, int); 101 static void u3_ht_eoi(struct u3_ht_ops *, int); 102 103 static uint32_t u3_ht_read_be(struct u3_ht_ops *, u_int); 104 static void u3_ht_write_be(struct u3_ht_ops *, u_int, uint32_t); 105 static uint32_t u3_ht_read_le(struct u3_ht_ops *, u_int); 106 static void u3_ht_write_le(struct u3_ht_ops *, u_int, uint32_t); 107 108 static const char *u3_compat[] = { 109 "u3", 110 NULL 111 }; 112 113 const char *pic_compat[] = { 114 "chrp,open-pic", 115 "open-pic", 116 "openpic", 117 NULL 118 }; 119 120 static struct u3_ht_ops *u3ht0 = NULL; 121 int have_u3_ht(void); 122 123 #ifdef MULTIPROCESSOR 124 125 extern struct ipi_ops ipiops; 126 static void u3_ht_send_ipi(cpuid_t, uint32_t); 127 static void u3_ht_establish_ipi(int, int, void *); 128 129 #endif 130 131 int init_u3_ht(void) 132 { 133 int u4, pic, irq = -1; 134 uint32_t reg[2]; 135 uint32_t base, len, tmp; 136 int bigendian; 137 volatile uint8_t *unin_reg; 138 139 u4 = OF_finddevice("/u4"); 140 if (u4 == -1) { 141 #ifdef U3HT_CASCADE 142 u4 = OF_finddevice("/u3"); 143 if (u4 == -1) 144 #endif 145 return FALSE; 146 } 147 148 if (! of_compatible(u4, u3_compat)) 149 return FALSE; 150 151 pic = OF_child(u4); 152 while ((pic != 0) && !of_compatible(pic, pic_compat)) 153 pic = OF_peer(pic); 154 155 if ((pic == -1) || (pic == 0)) 156 return FALSE; 157 158 if (OF_getprop(u4, "reg", reg, sizeof(reg)) != 8) 159 return FALSE; 160 161 base = reg[1]; 162 163 /* Enable and reset PIC */ 164 165 unin_reg = mapiodev(base, PAGE_SIZE, false); 166 KASSERT(unin_reg != NULL); 167 tmp = in32(unin_reg + 0xe0); 168 tmp |= 0x06; 169 out32(unin_reg + 0xe0, tmp); 170 171 bigendian = 0; 172 if (OF_getprop(pic, "big-endian", reg, 4) > -1) 173 bigendian = 1; 174 175 if (OF_getprop(pic, "reg", reg, 8) != 8) 176 return FALSE; 177 178 base = reg[0]; 179 len = reg[1]; 180 181 if (OF_getprop(pic, "interrupts", reg, 8) > 4) { 182 /* this is a cascaded PIC */ 183 irq = reg[0]; 184 aprint_normal("found cascaded U3/U4 HT PIC at %08x, IRQ %d\n", 185 base, irq); 186 } else 187 aprint_normal("found U3/U4 HT PIC at %08x\n", base); 188 189 setup_u3_ht(base, len, bigendian, irq); 190 191 return TRUE; 192 } 193 194 static struct u3_ht_ops * 195 setup_u3_ht(uint32_t addr, uint32_t len, int bigendian, int cirq) 196 { 197 struct u3_ht_ops *u3_ht; 198 struct pic_ops *pic; 199 int irq; 200 uint32_t x; 201 202 u3_ht = kmem_alloc(sizeof(struct u3_ht_ops), KM_SLEEP); 203 bzero(u3_ht, sizeof(struct u3_ht_ops)); 204 pic = &u3_ht->pic; 205 206 u3_ht->ht_base = mapiodev(addr, len, false); 207 KASSERT(u3_ht->ht_base != NULL); 208 209 if (bigendian) { 210 u3_ht->ht_read = u3_ht_read_be; 211 u3_ht->ht_write = u3_ht_write_be; 212 } else { 213 u3_ht->ht_read = u3_ht_read_le; 214 u3_ht->ht_write = u3_ht_write_le; 215 } 216 217 setup_u3_ht_workarounds(u3_ht); 218 219 /* Reset PIC */ 220 221 x = u3_ht_read(u3_ht, OPENPIC_CONFIG); 222 u3_ht_write(u3_ht, OPENPIC_CONFIG, x | OPENPIC_CONFIG_RESET); 223 do { 224 x = u3_ht_read(u3_ht, OPENPIC_CONFIG); 225 } while (x & OPENPIC_CONFIG_RESET); 226 227 x = u3_ht_read(u3_ht, OPENPIC_FEATURE); 228 229 aprint_normal("OpenPIC Version 1.%d: " 230 "Supports %d CPUs and %d interrupt sources.\n", 231 x & 0xff, ((x & 0x1f00) >> 8) + 1, ((x & 0x07ff0000) >> 16) + 1); 232 233 /* up to 128 interrupt sources, plus IPI */ 234 pic->pic_numintrs = IPI_VECTOR + 1; 235 pic->pic_cookie = (void *) addr; 236 pic->pic_enable_irq = u3_ht_enable_irq; 237 pic->pic_reenable_irq = u3_ht_enable_irq; 238 pic->pic_disable_irq = u3_ht_disable_irq; 239 pic->pic_get_irq = u3_ht_get_irq; 240 pic->pic_ack_irq = u3_ht_ack_irq; 241 pic->pic_establish_irq = u3_ht_establish_irq; 242 pic->pic_finish_setup = u3_ht_finish_setup; 243 strcpy(pic->pic_name, "u3_ht"); 244 pic_add(pic); 245 246 u3_ht_set_priority(u3_ht, 0, 15); 247 248 for (irq = 0; irq < 4; irq++) { 249 x = irq; 250 x |= OPENPIC_IMASK; 251 x |= OPENPIC_SENSE_LEVEL; 252 x |= 8 << OPENPIC_PRIORITY_SHIFT; 253 u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x); 254 u3_ht_write(u3_ht, OPENPIC_IDEST(irq), 1 << 0); 255 } 256 for (irq = 4; irq < pic->pic_numintrs; irq++) { 257 x = irq; 258 x |= OPENPIC_IMASK; 259 x |= OPENPIC_SENSE_EDGE; 260 x |= 8 << OPENPIC_PRIORITY_SHIFT; 261 u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x); 262 u3_ht_write(u3_ht, OPENPIC_IDEST(irq), 1 << 0); 263 } 264 265 x = u3_ht_read(u3_ht, OPENPIC_CONFIG); 266 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 267 u3_ht_write(u3_ht, OPENPIC_CONFIG, x); 268 269 u3_ht_write(u3_ht, OPENPIC_SPURIOUS_VECTOR, 0xff); 270 271 u3_ht_set_priority(u3_ht, 0, 0); 272 273 for (irq = 0; irq < pic->pic_numintrs; irq++) { 274 u3_ht_read_irq(u3_ht, 0); 275 u3_ht_eoi(u3_ht, 0); 276 } 277 278 if (cirq > -1) { 279 /* we're subordinate to a normal openpic */ 280 intr_establish_xname(cirq, IST_EDGE, IPL_HIGH, 281 pic_handle_intr, pic, "u3_ht"); 282 } 283 #ifdef MULTIPROCESSOR 284 else { 285 /* only handle IPIs if we're the only openpic */ 286 ipiops.ppc_send_ipi = u3_ht_send_ipi; 287 ipiops.ppc_establish_ipi = u3_ht_establish_ipi; 288 ipiops.ppc_ipi_vector = IPI_VECTOR; 289 290 x = u3_ht_read(u3_ht, OPENPIC_IPI_VECTOR(1)); 291 x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK); 292 x |= (15 << OPENPIC_PRIORITY_SHIFT) | ipiops.ppc_ipi_vector; 293 u3_ht_write(u3_ht, OPENPIC_IPI_VECTOR(1), x); 294 u3ht0 = u3_ht; 295 } 296 #endif /* MULTIPROCESSOR */ 297 298 return u3_ht; 299 } 300 301 static int 302 setup_u3_ht_workarounds(struct u3_ht_ops *u3_ht) 303 { 304 struct u3_ht_irqmap *irqmap = u3_ht->ht_irqmap; 305 int parent, child; 306 uint32_t reg[5], tmp; 307 uint8_t pos; 308 uint16_t cr, ht_cr; 309 int nirq, irq, i; 310 volatile uint8_t *ht_reg, *dev_reg, *base; 311 312 parent = OF_finddevice("/ht"); 313 if (parent == -1) 314 return FALSE; 315 316 if (OF_getprop(parent, "reg", reg, 12) != 12) 317 return FALSE; 318 319 ht_reg = mapiodev(reg[1], reg[2], false); 320 KASSERT(ht_reg != NULL); 321 322 memset(irqmap, 0, sizeof(u3_ht->ht_irqmap)); 323 324 for (child = OF_child(parent); child != 0; child = OF_peer(child)) { 325 if (OF_getprop(child, "reg", reg, 4) != 4) 326 continue; 327 328 dev_reg = ht_reg + (reg[0] & (OFW_PCI_PHYS_HI_DEVICEMASK | 329 OFW_PCI_PHYS_HI_FUNCTIONMASK)); 330 331 tmp = in32rb(dev_reg + PCI_COMMAND_STATUS_REG); 332 if ((tmp & PCI_STATUS_CAPLIST_SUPPORT) == 0) 333 continue; 334 335 for (pos = in8rb(dev_reg + PCI_CAPLISTPTR_REG); 336 pos != 0; pos = in8rb(dev_reg + pos + 0x01)) { 337 cr = in16rb(dev_reg + pos); 338 if (PCI_CAPLIST_CAP(cr) != 0x08) 339 continue; 340 341 ht_cr = in16rb(dev_reg + pos + 0x02); 342 if ((ht_cr & 0xf800) == 0x8000) 343 break; 344 } 345 346 if (pos == 0) 347 continue; 348 349 base = dev_reg + pos; 350 351 out8rb(base + 0x02, 0x01); 352 nirq = in32rb(base + 0x04); 353 nirq = (nirq >> 16) & 0xff; 354 355 DPRINTF("dev %08x nirq %d pos %08x\n", (uint32_t)base, nirq, (uint32_t)pos); 356 DPRINTF("devreg %08x\n", in32rb(dev_reg + PCI_ID_REG)); 357 for (i = 0; i <= nirq; i++) { 358 out8rb(base + 0x02, 0x10 + (i << 1)); 359 tmp = in32rb(base + 0x04); 360 irq = (tmp >> 16) & 0xff; 361 tmp |= HTAPIC_MASK; 362 out32rb(base + 0x04, tmp); 363 364 irqmap[irq].im_index = i; 365 irqmap[irq].im_level = 0; 366 irqmap[irq].im_base = base; 367 368 tmp = in32rb(dev_reg + PCI_ID_REG); 369 if (PCI_VENDOR(tmp) == 0x106b) 370 irqmap[irq].im_apple_base = dev_reg + 0x60; 371 else 372 irqmap[irq].im_apple_base = NULL; 373 374 out8rb(base + 0x02, 0x11 + (i << 1)); 375 irqmap[irq].im_data = in32rb(base + 0x04); 376 irqmap[irq].im_data |= (1 << 31); 377 } 378 } 379 380 return TRUE; 381 } 382 383 static void 384 u3_ht_enable_irq(struct pic_ops *pic, int irq, int type) 385 { 386 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 387 u_int x; 388 389 #ifdef MULTIPROCESSOR 390 if (irq == IPI_VECTOR) return; 391 #endif 392 x = u3_ht_read(u3_ht, OPENPIC_SRC_VECTOR(irq)); 393 x &= ~OPENPIC_IMASK; 394 u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x); 395 396 if (u3_ht_is_ht_irq(u3_ht, irq)) 397 u3_ht_enable_ht_irq(u3_ht, irq); 398 } 399 400 static void 401 u3_ht_disable_irq(struct pic_ops *pic, int irq) 402 { 403 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 404 u_int x; 405 406 #ifdef MULTIPROCESSOR 407 if (irq == IPI_VECTOR) return; 408 #endif 409 x = u3_ht_read(u3_ht, OPENPIC_SRC_VECTOR(irq)); 410 x |= OPENPIC_IMASK; 411 u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x); 412 413 if (u3_ht_is_ht_irq(u3_ht, irq)) 414 u3_ht_disable_ht_irq(u3_ht, irq); 415 } 416 417 static int 418 u3_ht_get_irq(struct pic_ops *pic, int mode) 419 { 420 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 421 422 return u3_ht_read_irq(u3_ht, curcpu()->ci_index); 423 } 424 425 static void 426 u3_ht_ack_irq(struct pic_ops *pic, int irq) 427 { 428 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 429 430 if (u3_ht_is_ht_irq(u3_ht, irq)) 431 u3_ht_ack_ht_irq(u3_ht, irq); 432 433 u3_ht_eoi(u3_ht, curcpu()->ci_index); 434 } 435 436 static void 437 u3_ht_establish_irq(struct pic_ops *pic, int irq, int type, int pri) 438 { 439 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 440 int realpri = uimax(1, uimin(15, pri)); 441 uint32_t x; 442 443 x = irq; 444 x |= OPENPIC_IMASK; 445 446 if (u3_ht_is_ht_irq(u3_ht, irq)) { 447 x |= OPENPIC_SENSE_EDGE; 448 } else { 449 if (type == IST_EDGE_FALLING || type == IST_EDGE_RISING) 450 x |= OPENPIC_SENSE_EDGE; 451 else 452 x |= OPENPIC_SENSE_LEVEL; 453 } 454 455 x |= realpri << OPENPIC_PRIORITY_SHIFT; 456 u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x); 457 458 if (u3_ht_is_ht_irq(u3_ht, irq)) 459 u3_ht_establish_ht_irq(u3_ht, irq, type); 460 461 DPRINTF("%s: setting IRQ %d %d to priority %d %x\n", __func__, irq, 462 type, realpri, x); 463 } 464 465 static void 466 u3_ht_finish_setup(struct pic_ops *pic) 467 { 468 struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic; 469 uint32_t cpumask = 0; 470 int i; 471 472 #ifdef OPENPIC_DISTRIBUTE 473 for (i = 0; i < ncpu; i++) 474 cpumask |= (1 << cpu_info[i].ci_cpuid); 475 #else 476 cpumask = 1; 477 #endif 478 479 for (i = 0; i < pic->pic_numintrs; i++) 480 u3_ht_write(u3_ht, OPENPIC_IDEST(i), cpumask); 481 } 482 483 static int 484 u3_ht_is_ht_irq(struct u3_ht_ops *u3_ht, int irq) 485 { 486 return (irq < 128) && (u3_ht->ht_irqmap[irq].im_base != NULL); 487 } 488 489 static void 490 u3_ht_establish_ht_irq(struct u3_ht_ops *u3_ht, int irq, int type) 491 { 492 struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq]; 493 u_int x; 494 495 out8rb(irqmap->im_base + 0x02, 0x10 + (irqmap->im_index << 1)); 496 497 x = in32rb(irqmap->im_base + 0x04); 498 /* mask interrupt */ 499 out32rb(irqmap->im_base + 0x04, x | HTAPIC_MASK); 500 501 /* mask out EOI and LEVEL bits */ 502 x &= ~(HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI); 503 504 if (type == IST_LEVEL_HIGH || type == IST_LEVEL_LOW) { 505 irqmap->im_level = 1; 506 DPRINTF("level\n"); 507 x |= HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI; 508 } else { 509 irqmap->im_level = 0; 510 } 511 512 out32rb(irqmap->im_base + 0x04, x); 513 } 514 515 static void 516 u3_ht_enable_ht_irq(struct u3_ht_ops *u3_ht, int irq) 517 { 518 struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq]; 519 u_int x; 520 521 out8rb(irqmap->im_base + 0x02, 0x10 + (irqmap->im_index << 1)); 522 x = in32rb(irqmap->im_base + 0x04); 523 x &= ~HTAPIC_MASK; 524 out32rb(irqmap->im_base + 0x04, x); 525 526 u3_ht_ack_ht_irq(u3_ht, irq); 527 } 528 529 static void 530 u3_ht_disable_ht_irq(struct u3_ht_ops *u3_ht, int irq) 531 { 532 struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq]; 533 u_int x; 534 535 out8rb(irqmap->im_base + 0x02, 0x10 + (irqmap->im_index << 1)); 536 x = in32rb(irqmap->im_base + 0x04); 537 x |= HTAPIC_MASK; 538 out32rb(irqmap->im_base + 0x04, x); 539 } 540 541 static void 542 u3_ht_ack_ht_irq(struct u3_ht_ops *u3_ht, int irq) 543 { 544 struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq]; 545 546 if (irqmap->im_level != 0) { 547 if (irqmap->im_apple_base != NULL) { 548 out32rb(irqmap->im_apple_base + ((irqmap->im_index >> 3) & ~0x03), 549 1 << (irqmap->im_index & 0x1f)); 550 } else { 551 out8rb(irqmap->im_base + 0x02, 0x11 + (irqmap->im_index << 1)); 552 out32rb(irqmap->im_base + 0x04, irqmap->im_data); 553 } 554 } 555 } 556 557 static void 558 u3_ht_set_priority(struct u3_ht_ops *u3_ht, int cpu, int pri) 559 { 560 u_int x; 561 562 x = u3_ht_read(u3_ht, OPENPIC_CPU_PRIORITY(cpu)); 563 x &= ~OPENPIC_CPU_PRIORITY_MASK; 564 x |= pri; 565 u3_ht_write(u3_ht, OPENPIC_CPU_PRIORITY(cpu), x); 566 } 567 568 void 569 __u3_ht_set_priority(int cpu, int pri) 570 { 571 if (u3ht0 == NULL) return; 572 573 u3_ht_set_priority(u3ht0, cpu, pri); 574 } 575 576 static int 577 u3_ht_read_irq(struct u3_ht_ops *u3_ht, int cpu) 578 { 579 return u3_ht_read(u3_ht, OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK; 580 } 581 582 static void 583 u3_ht_eoi(struct u3_ht_ops *u3_ht, int cpu) 584 { 585 u3_ht_write(u3_ht, OPENPIC_EOI(cpu), 0); 586 u3_ht_read(u3_ht, OPENPIC_EOI(cpu)); 587 } 588 589 static uint32_t 590 u3_ht_read_be(struct u3_ht_ops *u3_ht, u_int reg) 591 { 592 volatile uint8_t *addr = u3_ht->ht_base + reg; 593 594 return in32(addr); 595 } 596 597 static void 598 u3_ht_write_be(struct u3_ht_ops *u3_ht, u_int reg, uint32_t val) 599 { 600 volatile uint8_t *addr = u3_ht->ht_base + reg; 601 602 out32(addr, val); 603 } 604 605 static uint32_t 606 u3_ht_read_le(struct u3_ht_ops *u3_ht, u_int reg) 607 { 608 volatile uint8_t *addr = u3_ht->ht_base + reg; 609 610 return in32rb(addr); 611 } 612 613 static void 614 u3_ht_write_le(struct u3_ht_ops *u3_ht, u_int reg, uint32_t val) 615 { 616 volatile uint8_t *addr = u3_ht->ht_base + reg; 617 618 out32rb(addr, val); 619 } 620 621 #ifdef MULTIPROCESSOR 622 623 static void 624 u3_ht_send_ipi(cpuid_t target, uint32_t mesg) 625 { 626 struct cpu_info * const ci = curcpu(); 627 uint32_t cpumask = 0; 628 629 switch (target) { 630 case IPI_DST_ALL: 631 case IPI_DST_NOTME: 632 for (u_int i = 0; i < ncpu; i++) { 633 struct cpu_info * const dst_ci = cpu_lookup(i); 634 if (target == IPI_DST_ALL || dst_ci != ci) { 635 cpumask |= 1 << cpu_index(dst_ci); 636 atomic_or_32(&dst_ci->ci_pending_ipis, 637 mesg); 638 } 639 } 640 break; 641 default: { 642 struct cpu_info * const dst_ci = cpu_lookup(target); 643 cpumask = 1 << cpu_index(dst_ci); 644 atomic_or_32(&dst_ci->ci_pending_ipis, mesg); 645 break; 646 } 647 } 648 u3_ht_write(u3ht0, OPENPIC_IPI(cpu_index(ci), 1), cpumask); 649 } 650 651 static void 652 u3_ht_establish_ipi(int type, int level, void *ih_args) 653 { 654 intr_establish_xname(ipiops.ppc_ipi_vector, type, level, ipi_intr, 655 ih_args, "u3_ht ipi"); 656 } 657 658 #endif /*MULTIPROCESSOR*/ 659 660 int 661 have_u3_ht(void) 662 { 663 return (u3ht0 != NULL); 664 } 665