1 /* $NetBSD: ebus_mainbus.c,v 1.12 2013/12/16 20:17:35 palle Exp $ */ 2 /* $OpenBSD: ebus_mainbus.c,v 1.7 2010/11/11 17:58:23 miod Exp $ */ 3 4 /* 5 * Copyright (c) 2007 Mark Kettenis 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: ebus_mainbus.c,v 1.12 2013/12/16 20:17:35 palle Exp $"); 22 23 #ifdef DEBUG 24 #define EDB_PROM 0x01 25 #define EDB_CHILD 0x02 26 #define EDB_INTRMAP 0x04 27 #define EDB_BUSMAP 0x08 28 #define EDB_BUSDMA 0x10 29 #define EDB_INTR 0x20 30 extern int ebus_debug; 31 #define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0) 32 #else 33 #define DPRINTF(l, s) 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/conf.h> 38 #include <sys/device.h> 39 #include <sys/errno.h> 40 #include <sys/extent.h> 41 #include <sys/malloc.h> 42 #include <sys/systm.h> 43 #include <sys/time.h> 44 45 #define _SPARC_BUS_DMA_PRIVATE 46 #include <sys/bus.h> 47 #include <machine/autoconf.h> 48 #include <machine/openfirm.h> 49 50 #include <dev/pci/pcivar.h> 51 52 #include <sparc64/dev/iommureg.h> 53 #include <sparc64/dev/iommuvar.h> 54 #include <sparc64/dev/pyrovar.h> 55 #include <dev/ebus/ebusreg.h> 56 #include <dev/ebus/ebusvar.h> 57 #include <sparc64/dev/ebusvar.h> 58 59 int ebus_mainbus_match(device_t, cfdata_t, void *); 60 void ebus_mainbus_attach(device_t, device_t, void *); 61 62 CFATTACH_DECL_NEW(ebus_mainbus, sizeof(struct ebus_softc), 63 ebus_mainbus_match, ebus_mainbus_attach, NULL, NULL); 64 65 static int ebus_mainbus_bus_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 66 vaddr_t, bus_space_handle_t *); 67 static void *ebus_mainbus_intr_establish(bus_space_tag_t, int, int, 68 int (*)(void *), void *, void (*)(void)); 69 static bus_space_tag_t ebus_mainbus_alloc_bus_tag(struct ebus_softc *, 70 bus_space_tag_t, int); 71 #ifdef SUN4V 72 #if 0 73 XXX 74 static void ebus_mainbus_intr_ack(struct intrhand *); 75 #endif 76 #endif 77 int 78 ebus_mainbus_match(device_t parent, cfdata_t cf, void *aux) 79 { 80 struct mainbus_attach_args *ma = aux; 81 82 if (strcmp(ma->ma_name, "ebus") == 0) 83 return (1); 84 return (0); 85 } 86 87 void 88 ebus_mainbus_attach(device_t parent, device_t self, void *aux) 89 { 90 struct ebus_softc *sc = device_private(self); 91 struct mainbus_attach_args *ma = aux; 92 struct ebus_attach_args eba; 93 struct ebus_interrupt_map_mask *immp; 94 int node, nmapmask, error; 95 struct pyro_softc *psc; 96 int i; 97 98 sc->sc_dev = self; 99 sc->sc_node = node = ma->ma_node; 100 sc->sc_ign = INTIGN((ma->ma_upaid) << INTMAP_IGN_SHIFT); 101 102 if (CPU_ISSUN4U) { 103 printf(": ign %x", sc->sc_ign); 104 /* XXX */ 105 extern struct cfdriver pyro_cd; 106 107 for (i = 0; i < pyro_cd.cd_ndevs; i++) { 108 device_t dt = pyro_cd.cd_devs[i]; 109 psc = device_private(dt); 110 if (psc && psc->sc_ign == sc->sc_ign) { 111 sc->sc_bust = psc->sc_bustag; 112 sc->sc_csr = psc->sc_csr; 113 sc->sc_csrh = psc->sc_csrh; 114 break; 115 } 116 } 117 118 if (sc->sc_csr == 0) { 119 printf(": can't find matching host bridge leaf\n"); 120 return; 121 } 122 } 123 124 printf("\n"); 125 126 sc->sc_memtag = ebus_mainbus_alloc_bus_tag(sc, ma->ma_bustag, 127 PCI_MEMORY_BUS_SPACE); 128 sc->sc_iotag = ebus_mainbus_alloc_bus_tag(sc, ma->ma_bustag, 129 PCI_IO_BUS_SPACE); 130 sc->sc_childbustag = sc->sc_memtag; 131 sc->sc_dmatag = ma->ma_dmatag; 132 133 /* 134 * fill in our softc with information from the prom 135 */ 136 sc->sc_intmap = NULL; 137 sc->sc_range = NULL; 138 error = prom_getprop(node, "interrupt-map", 139 sizeof(struct ebus_interrupt_map), 140 &sc->sc_nintmap, (void **)&sc->sc_intmap); 141 switch (error) { 142 case 0: 143 immp = &sc->sc_intmapmask; 144 nmapmask = 1; 145 error = prom_getprop(node, "interrupt-map-mask", 146 sizeof(struct ebus_interrupt_map_mask), &nmapmask, 147 (void **)&immp); 148 if (error) 149 panic("could not get ebus interrupt-map-mask: error %d", 150 error); 151 if (nmapmask != 1) 152 panic("ebus interrupt-map-mask is broken"); 153 break; 154 case ENOENT: 155 break; 156 default: 157 panic("ebus interrupt-map: error %d", error); 158 break; 159 } 160 161 error = prom_getprop(node, "ranges", sizeof(struct ebus_mainbus_ranges), 162 &sc->sc_nrange, (void **)&sc->sc_range); 163 if (error) 164 panic("ebus ranges: error %d", error); 165 166 /* 167 * now attach all our children 168 */ 169 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 170 for (node = firstchild(node); node; node = nextsibling(node)) { 171 if (ebus_setup_attach_args(sc, node, &eba) != 0) { 172 DPRINTF(EDB_CHILD, 173 ("ebus_mainbus_attach: %s: incomplete\n", 174 prom_getpropstring(node, "name"))); 175 continue; 176 } else { 177 DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n", 178 eba.ea_name)); 179 (void)config_found(self, &eba, ebus_print); 180 } 181 ebus_destroy_attach_args(&eba); 182 } 183 } 184 185 static bus_space_tag_t 186 ebus_mainbus_alloc_bus_tag(struct ebus_softc *sc, 187 bus_space_tag_t parent, 188 int type) 189 { 190 struct sparc_bus_space_tag *bt; 191 192 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 193 if (bt == NULL) 194 panic("could not allocate ebus bus tag"); 195 196 bt->cookie = sc; 197 bt->parent = parent; 198 bt->type = type; 199 bt->sparc_bus_map = ebus_mainbus_bus_map; 200 bt->sparc_bus_mmap = ebus_bus_mmap; 201 bt->sparc_intr_establish = ebus_mainbus_intr_establish; 202 203 return (bt); 204 } 205 206 int 207 ebus_mainbus_bus_map(bus_space_tag_t t, bus_addr_t offset, bus_size_t size, 208 int flags, vaddr_t va, bus_space_handle_t *hp) 209 { 210 struct ebus_softc *sc = t->cookie; 211 struct ebus_mainbus_ranges *range; 212 bus_addr_t hi, lo; 213 int i; 214 #if 0 215 int ss; 216 #endif 217 218 DPRINTF(EDB_BUSMAP, 219 ("\n_ebus_mainbus_bus_map: off %016llx sz %x flags %d", 220 (unsigned long long)offset, (int)size, (int)flags)); 221 222 if (t->parent == 0 || t->parent->sparc_bus_map == 0) { 223 printf("\n_ebus_mainbus_bus_map: invalid parent"); 224 return (EINVAL); 225 } 226 227 t = t->parent; 228 229 hi = offset >> 32UL; 230 lo = offset & 0xffffffff; 231 range = (struct ebus_mainbus_ranges *)sc->sc_range; 232 233 DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo)); 234 for (i = 0; i < sc->sc_nrange; i++) { 235 bus_addr_t addr; 236 237 if (hi != range[i].child_hi) 238 continue; 239 if (lo < range[i].child_lo || 240 (lo + size) > (range[i].child_lo + range[i].size)) 241 continue; 242 243 #if 0 244 /* Isolate address space and find the right tag */ 245 ss = (range[i].phys_hi>>24)&3; 246 switch (ss) { 247 case 1: /* I/O space */ 248 t = sc->sc_iotag; 249 break; 250 case 2: /* Memory space */ 251 t = sc->sc_memtag; 252 break; 253 case 0: /* Config space */ 254 case 3: /* 64-bit Memory space */ 255 default: /* WTF? */ 256 /* We don't handle these */ 257 panic("ebus_mainbus_bus_map: illegal space %x", ss); 258 break; 259 } 260 #endif 261 262 addr = ((bus_addr_t)range[i].phys_hi << 32UL) | 263 range[i].phys_lo; 264 addr += lo; 265 DPRINTF(EDB_BUSMAP, 266 ("\n_ebus_mainbus_bus_map: paddr offset %qx addr %qx\n", 267 (unsigned long long)offset, (unsigned long long)addr)); 268 return (bus_space_map(t, addr, size, flags, hp)); 269 } 270 DPRINTF(EDB_BUSMAP, (": FAILED\n")); 271 return (EINVAL); 272 } 273 274 static void * 275 ebus_mainbus_intr_establish(bus_space_tag_t t, int ihandle, int level, 276 int (*handler)(void *), void *arg, void (*fastvec)(void) /* ignored */) 277 { 278 struct ebus_softc *sc = t->cookie; 279 struct intrhand *ih = NULL; 280 volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL; 281 u_int64_t *imap, *iclr; 282 int ino; 283 284 #ifdef SUN4V 285 #if 0 286 XXX 287 if (CPU_ISSUN4V) { 288 struct upa_reg reg; 289 u_int64_t devhandle, devino = INTINO(ihandle); 290 u_int64_t sysino; 291 int node = -1; 292 int i, err; 293 294 for (i = 0; i < sc->sc_nintmap; i++) { 295 if (sc->sc_intmap[i].cintr == ihandle) { 296 node = sc->sc_intmap[i].cnode; 297 break; 298 } 299 } 300 if (node == -1) 301 return (NULL); 302 303 if (OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg)) 304 return (NULL); 305 devhandle = (reg.ur_paddr >> 32) & 0x0fffffff; 306 307 err = hv_intr_devino_to_sysino(devhandle, devino, &sysino); 308 if (err != H_EOK) 309 return (NULL); 310 311 KASSERT(sysino == INTVEC(sysino)); 312 ih = bus_intr_allocate(t0, handler, arg, sysino, level, 313 NULL, NULL, what); 314 if (ih == NULL) 315 return (NULL); 316 317 intr_establish(ih->ih_pil, ih); 318 ih->ih_ack = ebus_mainbus_intr_ack; 319 320 err = hv_intr_settarget(sysino, cpus->ci_upaid); 321 if (err != H_EOK) 322 return (NULL); 323 324 /* Clear pending interrupts. */ 325 err = hv_intr_setstate(sysino, INTR_IDLE); 326 if (err != H_EOK) 327 return (NULL); 328 329 err = hv_intr_setenabled(sysino, INTR_ENABLED); 330 if (err != H_EOK) 331 return (NULL); 332 333 return (ih); 334 } 335 #endif 336 #endif 337 ihandle |= sc->sc_ign; 338 ino = INTINO(ihandle); 339 340 /* XXX */ 341 imap = (uint64_t *)((uintptr_t)bus_space_vaddr(sc->sc_bustag, sc->sc_csrh) + 0x1000); 342 iclr = (uint64_t *)((uintptr_t)bus_space_vaddr(sc->sc_bustag, sc->sc_csrh) + 0x1400); 343 intrmapptr = &imap[ino]; 344 intrclrptr = &iclr[ino]; 345 ino |= INTVEC(ihandle); 346 347 ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT); 348 if (ih == NULL) 349 return (NULL); 350 351 /* Register the map and clear intr registers */ 352 ih->ih_map = intrmapptr; 353 ih->ih_clr = intrclrptr; 354 355 ih->ih_ivec = ihandle; 356 ih->ih_fun = handler; 357 ih->ih_arg = arg; 358 ih->ih_pil = level; 359 ih->ih_number = ino; 360 ih->ih_pending = 0; 361 362 intr_establish(ih->ih_pil, level != IPL_VM, ih); 363 364 if (intrmapptr != NULL) { 365 u_int64_t imapval; 366 367 imapval = *intrmapptr; 368 imapval |= (1LL << 6); 369 imapval |= INTMAP_V; 370 *intrmapptr = imapval; 371 imapval = *intrmapptr; 372 ih->ih_number |= imapval & INTMAP_INR; 373 } 374 375 return (ih); 376 } 377 378 #ifdef SUN4V 379 #if 0 380 XXX 381 static void 382 ebus_mainbus_intr_ack(struct intrhand *ih) 383 { 384 hv_intr_setstate(ih->ih_number, INTR_IDLE); 385 } 386 #endif 387 #endif 388