ebus_mainbus.c revision 1.1
11.1Smrg/* $OpenBSD: ebus_mainbus.c,v 1.7 2010/11/11 17:58:23 miod Exp $ */ 21.1Smrg 31.1Smrg/* 41.1Smrg * Copyright (c) 2007 Mark Kettenis 51.1Smrg * 61.1Smrg * Permission to use, copy, modify, and distribute this software for any 71.1Smrg * purpose with or without fee is hereby granted, provided that the above 81.1Smrg * copyright notice and this permission notice appear in all copies. 91.1Smrg * 101.1Smrg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 111.1Smrg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 121.1Smrg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 131.1Smrg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 141.1Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 151.1Smrg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 161.1Smrg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 171.1Smrg */ 181.1Smrg 191.1Smrg#ifdef DEBUG 201.1Smrg#define EDB_PROM 0x01 211.1Smrg#define EDB_CHILD 0x02 221.1Smrg#define EDB_INTRMAP 0x04 231.1Smrg#define EDB_BUSMAP 0x08 241.1Smrg#define EDB_BUSDMA 0x10 251.1Smrg#define EDB_INTR 0x20 261.1Smrgextern int ebus_debug; 271.1Smrg#define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0) 281.1Smrg#else 291.1Smrg#define DPRINTF(l, s) 301.1Smrg#endif 311.1Smrg 321.1Smrg#include <sys/param.h> 331.1Smrg#include <sys/conf.h> 341.1Smrg#include <sys/device.h> 351.1Smrg#include <sys/errno.h> 361.1Smrg#include <sys/extent.h> 371.1Smrg#include <sys/malloc.h> 381.1Smrg#include <sys/systm.h> 391.1Smrg#include <sys/time.h> 401.1Smrg 411.1Smrg#define _SPARC_BUS_DMA_PRIVATE 421.1Smrg#include <machine/bus.h> 431.1Smrg#include <machine/autoconf.h> 441.1Smrg#include <machine/hypervisor.h> 451.1Smrg#include <machine/openfirm.h> 461.1Smrg 471.1Smrg#include <dev/pci/pcivar.h> 481.1Smrg 491.1Smrg#include <sparc64/dev/iommureg.h> 501.1Smrg#include <sparc64/dev/ebusreg.h> 511.1Smrg#include <sparc64/dev/ebusvar.h> 521.1Smrg#include <sparc64/dev/pyrovar.h> 531.1Smrg 541.1Smrgextern struct cfdriver pyro_cd; 551.1Smrg 561.1Smrgint ebus_mainbus_match(struct device *, void *, void *); 571.1Smrgvoid ebus_mainbus_attach(struct device *, struct device *, void *); 581.1Smrg 591.1Smrgstruct cfattach ebus_mainbus_ca = { 601.1Smrg sizeof(struct ebus_softc), ebus_mainbus_match, ebus_mainbus_attach 611.1Smrg}; 621.1Smrg 631.1Smrg 641.1Smrgint ebus_mainbus_bus_map(bus_space_tag_t, bus_space_tag_t, 651.1Smrg bus_addr_t, bus_size_t, int, bus_space_handle_t *); 661.1Smrgvoid *ebus_mainbus_intr_establish(bus_space_tag_t, bus_space_tag_t, 671.1Smrg int, int, int, int (*)(void *), void *, const char *); 681.1Smrgbus_space_tag_t ebus_alloc_bus_tag(struct ebus_softc *, bus_space_tag_t); 691.1Smrgvoid ebus_mainbus_intr_ack(struct intrhand *); 701.1Smrg 711.1Smrgint 721.1Smrgebus_mainbus_match(struct device *parent, void *match, void *aux) 731.1Smrg{ 741.1Smrg struct mainbus_attach_args *ma = aux; 751.1Smrg 761.1Smrg if (strcmp(ma->ma_name, "ebus") == 0) 771.1Smrg return (1); 781.1Smrg return (0); 791.1Smrg} 801.1Smrg 811.1Smrgvoid 821.1Smrgebus_mainbus_attach(struct device *parent, struct device *self, void *aux) 831.1Smrg{ 841.1Smrg struct ebus_softc *sc = (struct ebus_softc *)self; 851.1Smrg struct mainbus_attach_args *ma = aux; 861.1Smrg struct ebus_attach_args eba; 871.1Smrg struct ebus_interrupt_map_mask *immp; 881.1Smrg int node, nmapmask, error; 891.1Smrg struct pyro_softc *psc; 901.1Smrg int i; 911.1Smrg 921.1Smrg sc->sc_node = node = ma->ma_node; 931.1Smrg sc->sc_ign = INTIGN((ma->ma_upaid) << INTMAP_IGN_SHIFT); 941.1Smrg 951.1Smrg if (CPU_ISSUN4U) { 961.1Smrg printf(": ign %x", sc->sc_ign); 971.1Smrg 981.1Smrg for (i = 0; i < pyro_cd.cd_ndevs; i++) { 991.1Smrg psc = pyro_cd.cd_devs[i]; 1001.1Smrg if (psc && psc->sc_ign == sc->sc_ign) { 1011.1Smrg sc->sc_bust = psc->sc_bust; 1021.1Smrg sc->sc_csr = psc->sc_csr; 1031.1Smrg sc->sc_csrh = psc->sc_csrh; 1041.1Smrg break; 1051.1Smrg } 1061.1Smrg } 1071.1Smrg 1081.1Smrg if (sc->sc_csr == 0) { 1091.1Smrg printf(": can't find matching host bridge leaf\n"); 1101.1Smrg return; 1111.1Smrg } 1121.1Smrg } 1131.1Smrg 1141.1Smrg printf("\n"); 1151.1Smrg 1161.1Smrg sc->sc_memtag = ebus_alloc_bus_tag(sc, ma->ma_bustag); 1171.1Smrg sc->sc_iotag = ebus_alloc_bus_tag(sc, ma->ma_bustag); 1181.1Smrg sc->sc_dmatag = ebus_alloc_dma_tag(sc, ma->ma_dmatag); 1191.1Smrg 1201.1Smrg /* 1211.1Smrg * fill in our softc with information from the prom 1221.1Smrg */ 1231.1Smrg sc->sc_intmap = NULL; 1241.1Smrg sc->sc_range = NULL; 1251.1Smrg error = getprop(node, "interrupt-map", 1261.1Smrg sizeof(struct ebus_interrupt_map), 1271.1Smrg &sc->sc_nintmap, (void **)&sc->sc_intmap); 1281.1Smrg switch (error) { 1291.1Smrg case 0: 1301.1Smrg immp = &sc->sc_intmapmask; 1311.1Smrg error = getprop(node, "interrupt-map-mask", 1321.1Smrg sizeof(struct ebus_interrupt_map_mask), &nmapmask, 1331.1Smrg (void **)&immp); 1341.1Smrg if (error) 1351.1Smrg panic("could not get ebus interrupt-map-mask"); 1361.1Smrg if (nmapmask != 1) 1371.1Smrg panic("ebus interrupt-map-mask is broken"); 1381.1Smrg break; 1391.1Smrg case ENOENT: 1401.1Smrg break; 1411.1Smrg default: 1421.1Smrg panic("ebus interrupt-map: error %d", error); 1431.1Smrg break; 1441.1Smrg } 1451.1Smrg 1461.1Smrg error = getprop(node, "ranges", sizeof(struct ebus_mainbus_ranges), 1471.1Smrg &sc->sc_nrange, (void **)&sc->sc_range); 1481.1Smrg if (error) 1491.1Smrg panic("ebus ranges: error %d", error); 1501.1Smrg 1511.1Smrg /* 1521.1Smrg * now attach all our children 1531.1Smrg */ 1541.1Smrg DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 1551.1Smrg for (node = firstchild(node); node; node = nextsibling(node)) { 1561.1Smrg if (ebus_setup_attach_args(sc, node, &eba) != 0) { 1571.1Smrg DPRINTF(EDB_CHILD, 1581.1Smrg ("ebus_mainbus_attach: %s: incomplete\n", 1591.1Smrg getpropstring(node, "name"))); 1601.1Smrg continue; 1611.1Smrg } else { 1621.1Smrg DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n", 1631.1Smrg eba.ea_name)); 1641.1Smrg (void)config_found(self, &eba, ebus_print); 1651.1Smrg } 1661.1Smrg ebus_destroy_attach_args(&eba); 1671.1Smrg } 1681.1Smrg} 1691.1Smrg 1701.1Smrgbus_space_tag_t 1711.1Smrgebus_alloc_bus_tag(struct ebus_softc *sc, bus_space_tag_t parent) 1721.1Smrg{ 1731.1Smrg struct sparc_bus_space_tag *bt; 1741.1Smrg 1751.1Smrg bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 1761.1Smrg if (bt == NULL) 1771.1Smrg panic("could not allocate ebus bus tag"); 1781.1Smrg 1791.1Smrg strlcpy(bt->name, sc->sc_dev.dv_xname, sizeof(bt->name)); 1801.1Smrg bt->cookie = sc; 1811.1Smrg bt->parent = parent; 1821.1Smrg bt->asi = parent->asi; 1831.1Smrg bt->sasi = parent->sasi; 1841.1Smrg bt->sparc_bus_map = ebus_mainbus_bus_map; 1851.1Smrg bt->sparc_intr_establish = ebus_mainbus_intr_establish; 1861.1Smrg 1871.1Smrg return (bt); 1881.1Smrg} 1891.1Smrg 1901.1Smrgint 1911.1Smrgebus_mainbus_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset, 1921.1Smrg bus_size_t size, int flags, bus_space_handle_t *hp) 1931.1Smrg{ 1941.1Smrg struct ebus_softc *sc = t->cookie; 1951.1Smrg struct ebus_mainbus_ranges *range; 1961.1Smrg bus_addr_t hi, lo; 1971.1Smrg int i; 1981.1Smrg 1991.1Smrg DPRINTF(EDB_BUSMAP, 2001.1Smrg ("\n_ebus_mainbus_bus_map: off %016llx sz %x flags %d", 2011.1Smrg (unsigned long long)offset, (int)size, (int)flags)); 2021.1Smrg 2031.1Smrg if (t->parent == 0 || t->parent->sparc_bus_map == 0) { 2041.1Smrg printf("\n_ebus_mainbus_bus_map: invalid parent"); 2051.1Smrg return (EINVAL); 2061.1Smrg } 2071.1Smrg 2081.1Smrg t = t->parent; 2091.1Smrg 2101.1Smrg if (flags & BUS_SPACE_MAP_PROMADDRESS) { 2111.1Smrg return ((*t->sparc_bus_map) 2121.1Smrg (t, t0, offset, size, flags, hp)); 2131.1Smrg } 2141.1Smrg 2151.1Smrg hi = offset >> 32UL; 2161.1Smrg lo = offset & 0xffffffff; 2171.1Smrg range = (struct ebus_mainbus_ranges *)sc->sc_range; 2181.1Smrg 2191.1Smrg DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo)); 2201.1Smrg for (i = 0; i < sc->sc_nrange; i++) { 2211.1Smrg bus_addr_t addr; 2221.1Smrg 2231.1Smrg if (hi != range[i].child_hi) 2241.1Smrg continue; 2251.1Smrg if (lo < range[i].child_lo || 2261.1Smrg (lo + size) > (range[i].child_lo + range[i].size)) 2271.1Smrg continue; 2281.1Smrg 2291.1Smrg addr = ((bus_addr_t)range[i].phys_hi << 32UL) | 2301.1Smrg range[i].phys_lo; 2311.1Smrg addr += lo; 2321.1Smrg DPRINTF(EDB_BUSMAP, 2331.1Smrg ("\n_ebus_mainbus_bus_map: paddr offset %qx addr %qx\n", 2341.1Smrg (unsigned long long)offset, (unsigned long long)addr)); 2351.1Smrg return ((*t->sparc_bus_map)(t, t0, addr, size, flags, hp)); 2361.1Smrg } 2371.1Smrg DPRINTF(EDB_BUSMAP, (": FAILED\n")); 2381.1Smrg return (EINVAL); 2391.1Smrg} 2401.1Smrg 2411.1Smrgvoid * 2421.1Smrgebus_mainbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, 2431.1Smrg int level, int flags, int (*handler)(void *), void *arg, const char *what) 2441.1Smrg{ 2451.1Smrg struct ebus_softc *sc = t->cookie; 2461.1Smrg struct intrhand *ih = NULL; 2471.1Smrg volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL; 2481.1Smrg int ino; 2491.1Smrg 2501.1Smrg#ifdef SUN4V 2511.1Smrg if (CPU_ISSUN4V) { 2521.1Smrg struct upa_reg reg; 2531.1Smrg u_int64_t devhandle, devino = INTINO(ihandle); 2541.1Smrg u_int64_t sysino; 2551.1Smrg int node = -1; 2561.1Smrg int i, err; 2571.1Smrg 2581.1Smrg for (i = 0; i < sc->sc_nintmap; i++) { 2591.1Smrg if (sc->sc_intmap[i].cintr == ihandle) { 2601.1Smrg node = sc->sc_intmap[i].cnode; 2611.1Smrg break; 2621.1Smrg } 2631.1Smrg } 2641.1Smrg if (node == -1) 2651.1Smrg return (NULL); 2661.1Smrg 2671.1Smrg if (OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg)) 2681.1Smrg return (NULL); 2691.1Smrg devhandle = (reg.ur_paddr >> 32) & 0x0fffffff; 2701.1Smrg 2711.1Smrg err = hv_intr_devino_to_sysino(devhandle, devino, &sysino); 2721.1Smrg if (err != H_EOK) 2731.1Smrg return (NULL); 2741.1Smrg 2751.1Smrg KASSERT(sysino == INTVEC(sysino)); 2761.1Smrg ih = bus_intr_allocate(t0, handler, arg, sysino, level, 2771.1Smrg NULL, NULL, what); 2781.1Smrg if (ih == NULL) 2791.1Smrg return (NULL); 2801.1Smrg 2811.1Smrg intr_establish(ih->ih_pil, ih); 2821.1Smrg ih->ih_ack = ebus_mainbus_intr_ack; 2831.1Smrg 2841.1Smrg err = hv_intr_settarget(sysino, cpus->ci_upaid); 2851.1Smrg if (err != H_EOK) 2861.1Smrg return (NULL); 2871.1Smrg 2881.1Smrg /* Clear pending interrupts. */ 2891.1Smrg err = hv_intr_setstate(sysino, INTR_IDLE); 2901.1Smrg if (err != H_EOK) 2911.1Smrg return (NULL); 2921.1Smrg 2931.1Smrg err = hv_intr_setenabled(sysino, INTR_ENABLED); 2941.1Smrg if (err != H_EOK) 2951.1Smrg return (NULL); 2961.1Smrg 2971.1Smrg return (ih); 2981.1Smrg } 2991.1Smrg#endif 3001.1Smrg 3011.1Smrg ihandle |= sc->sc_ign; 3021.1Smrg ino = INTINO(ihandle); 3031.1Smrg 3041.1Smrg if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) { 3051.1Smrg u_int64_t *imap, *iclr; 3061.1Smrg 3071.1Smrg /* XXX */ 3081.1Smrg imap = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1000; 3091.1Smrg iclr = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1400; 3101.1Smrg intrmapptr = &imap[ino]; 3111.1Smrg intrclrptr = &iclr[ino]; 3121.1Smrg ino |= INTVEC(ihandle); 3131.1Smrg } 3141.1Smrg 3151.1Smrg ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr, 3161.1Smrg intrclrptr, what); 3171.1Smrg if (ih == NULL) 3181.1Smrg return (NULL); 3191.1Smrg 3201.1Smrg intr_establish(ih->ih_pil, ih); 3211.1Smrg 3221.1Smrg if (intrmapptr != NULL) { 3231.1Smrg u_int64_t intrmap; 3241.1Smrg 3251.1Smrg intrmap = *intrmapptr; 3261.1Smrg intrmap |= (1LL << 6); 3271.1Smrg intrmap |= INTMAP_V; 3281.1Smrg *intrmapptr = intrmap; 3291.1Smrg intrmap = *intrmapptr; 3301.1Smrg ih->ih_number |= intrmap & INTMAP_INR; 3311.1Smrg } 3321.1Smrg 3331.1Smrg return (ih); 3341.1Smrg} 3351.1Smrg 3361.1Smrg#ifdef SUN4V 3371.1Smrg 3381.1Smrgvoid 3391.1Smrgebus_mainbus_intr_ack(struct intrhand *ih) 3401.1Smrg{ 3411.1Smrg hv_intr_setstate(ih->ih_number, INTR_IDLE); 3421.1Smrg} 3431.1Smrg 3441.1Smrg#endif 345