ofwpci.c revision 1.6
1/* $NetBSD: ofwpci.c,v 1.6 2008/02/11 17:32:18 garbled Exp $ */ 2 3/*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tim Rightnour 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <sys/cdefs.h> 40__KERNEL_RCSID(0, "$NetBSD: ofwpci.c,v 1.6 2008/02/11 17:32:18 garbled Exp $"); 41 42#include "opt_pci.h" 43 44#include <sys/param.h> 45#include <sys/device.h> 46#include <sys/malloc.h> 47#include <sys/extent.h> 48#include <sys/systm.h> 49 50#include <dev/pci/pcivar.h> 51#include <dev/pci/pciconf.h> 52#include <dev/ofw/openfirm.h> 53#include <dev/ofw/ofw_pci.h> 54 55#include <machine/autoconf.h> 56#include <machine/isa_machdep.h> 57#include <machine/pio.h> 58 59struct ofwpci_softc { 60 struct device sc_dev; 61 struct genppc_pci_chipset sc_pc; 62 struct powerpc_bus_space sc_iot; 63 struct powerpc_bus_space sc_memt; 64}; 65 66static void ofwpci_attach(struct device *, struct device *, void *); 67static int ofwpci_match(struct device *, struct cfdata *, void *); 68 69CFATTACH_DECL(ofwpci, sizeof(struct ofwpci_softc), 70 ofwpci_match, ofwpci_attach, NULL, NULL); 71 72extern struct genppc_pci_chipset *genppc_pct; 73extern struct model_data modeldata; 74 75static void 76ofwpci_get_chipset_tag(pci_chipset_tag_t pc) 77{ 78 pc->pc_conf_v = (void *)pc; 79 80 pc->pc_attach_hook = genppc_pci_ofmethod_attach_hook; 81 pc->pc_bus_maxdevs = genppc_pci_bus_maxdevs; 82 pc->pc_make_tag = genppc_pci_ofmethod_make_tag; 83 pc->pc_conf_read = genppc_pci_ofmethod_conf_read; 84 pc->pc_conf_write = genppc_pci_ofmethod_conf_write; 85 86 pc->pc_intr_v = (void *)pc; 87 88 pc->pc_intr_map = genofw_pci_intr_map; 89 pc->pc_intr_string = genppc_pci_intr_string; 90 pc->pc_intr_evcnt = genppc_pci_intr_evcnt; 91 pc->pc_intr_establish = genppc_pci_intr_establish; 92 pc->pc_intr_disestablish = genppc_pci_intr_disestablish; 93 94 pc->pc_conf_interrupt = genppc_pci_conf_interrupt; 95 pc->pc_decompose_tag = genppc_pci_ofmethod_decompose_tag; 96 pc->pc_conf_hook = genofw_pci_conf_hook; 97 98 pc->pc_addr = 0; 99 pc->pc_data = 0; 100 pc->pc_bus = 0; 101 pc->pc_node = 0; 102 pc->pc_memt = 0; 103 pc->pc_iot = 0; 104 pc->pc_ihandle = 0; 105} 106 107static int 108ofwpci_match(struct device *parent, struct cfdata *cf, void *aux) 109{ 110 struct confargs *ca = aux; 111 char name[32]; 112 113 if (strcmp(ca->ca_name, "pci") != 0) 114 return 0; 115 116 memset(name, 0, sizeof(name)); 117 OF_getprop(ca->ca_node, "device_type", name, sizeof(name)); 118 if (strcmp(name, "pci") != 0) 119 return 0; 120 121 return 1; 122} 123 124static void 125ofwpci_attach(struct device *parent, struct device *self, void *aux) 126{ 127 struct ofwpci_softc *sc = (void *)self; 128 pci_chipset_tag_t pc = &sc->sc_pc; 129 struct confargs *ca = aux; 130 struct pcibus_attach_args pba; 131 struct genppc_pci_chipset_businfo *pbi; 132 int node = ca->ca_node; 133 int i, isprim = 0; 134 uint32_t busrange[2]; 135 char buf[64]; 136#ifdef PCI_NETBSD_CONFIGURE 137 struct extent *ioext, *memext; 138#endif 139 140 aprint_normal("\n"); 141 142 /* PCI bus number */ 143 if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) 144 return; 145 146 /* bus space map the io ranges */ 147 sc->sc_iot.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE; 148 sc->sc_iot.pbs_base = 0x00000000; 149 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, node, &sc->sc_iot, 150 "ofwpci io-space") != 0) 151 panic("Can't init ofwpci io tag"); 152 153 sc->sc_memt.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE; 154 sc->sc_memt.pbs_base = 0x00000000; 155 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, node, &sc->sc_memt, 156 "ofwpci mem-space") != 0) 157 panic("Can't init ofwpci mem tag"); 158 159 aprint_debug("io base=0x%x offset=0x%x limit=0x%x\n", 160 sc->sc_iot.pbs_base, sc->sc_iot.pbs_offset, sc->sc_iot.pbs_limit); 161 162 aprint_debug("mem base=0x%x offset=0x%x limit=0x%x\n", 163 sc->sc_memt.pbs_base, sc->sc_memt.pbs_offset, 164 sc->sc_memt.pbs_limit); 165 166 /* are we the primary pci bus? */ 167 if (of_find_firstchild_byname(OF_finddevice("/"), "pci") == node) { 168 int isa_node; 169 170 isprim++; 171 /* yes we are, now do we have an ISA child? */ 172 isa_node = of_find_firstchild_byname(node, "isa"); 173 if (isa_node != -1) { 174 /* isa == pci */ 175 genppc_isa_io_space_tag = sc->sc_iot; 176 genppc_isa_mem_space_tag = sc->sc_memt; 177 map_isa_ioregs(); 178 init_ofppc_interrupt(); 179 ofppc_init_comcons(isa_node); 180 } 181 } 182 183 ofwpci_get_chipset_tag(pc); 184 185 pc->pc_node = node; 186 i = OF_package_to_path(node, buf, sizeof(buf)-5); 187 if (i <= 0) 188 panic("Can't determine path for pci node %d", node); 189 buf[i] = '\0'; 190 pc->pc_ihandle = OF_open(buf); 191 if (pc->pc_ihandle < 0) 192 panic("Can't open device %s", buf); 193 pc->pc_bus = busrange[0]; 194 pc->pc_iot = &sc->sc_iot; 195 pc->pc_memt = &sc->sc_memt; 196 197 pbi = malloc(sizeof(struct genppc_pci_chipset_businfo), 198 M_DEVBUF, M_NOWAIT); 199 KASSERT(pbi != NULL); 200 pbi->pbi_properties = prop_dictionary_create(); 201 KASSERT(pbi->pbi_properties != NULL); 202 SIMPLEQ_INIT(&pc->pc_pbi); 203 SIMPLEQ_INSERT_TAIL(&pc->pc_pbi, pbi, next); 204 205 genofw_setup_pciintr_map((void *)pc, pbi, pc->pc_node); 206 207#ifdef PCI_NETBSD_CONFIGURE 208 ioext = extent_create("pciio", 209 modeldata.pciiodata[device_unit(self)].start, 210 modeldata.pciiodata[device_unit(self)].limit, 211 M_DEVBUF, NULL, 0, EX_NOWAIT); 212 memext = extent_create("pcimem", sc->sc_memt.pbs_base, 213 sc->sc_memt.pbs_limit-1, M_DEVBUF, NULL, 0, EX_NOWAIT); 214 215 if (pci_configure_bus(pc, ioext, memext, NULL, 0, CACHELINESIZE)) 216 aprint_error("pci_configure_bus() failed\n"); 217 218 extent_destroy(ioext); 219 extent_destroy(memext); 220#endif /* PCI_NETBSD_CONFIGURE */ 221 222 memset(&pba, 0, sizeof(pba)); 223 pba.pba_memt = pc->pc_memt; 224 pba.pba_iot = pc->pc_iot; 225 pba.pba_dmat = &pci_bus_dma_tag; 226 pba.pba_dmat64 = NULL; 227 pba.pba_bus = pc->pc_bus; 228 pba.pba_bridgetag = NULL; 229 pba.pba_pc = pc; 230 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 231 232 config_found_ia(self, "pcibus", &pba, pcibusprint); 233} 234