1 /* $NetBSD: gt_mainbus.c,v 1.3 2010/12/17 19:18:49 phx Exp $ */ 2 /* 3 * Copyright (c) 2010 KIYOHARA Takashi 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * 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: gt_mainbus.c,v 1.3 2010/12/17 19:18:49 phx Exp $"); 30 31 #include "opt_pci.h" 32 #include "opt_marvell.h" 33 #include "gtpci.h" 34 #include "pci.h" 35 #include "isa.h" 36 37 #define _POWERPC_BUS_DMA_PRIVATE 38 39 #include <sys/param.h> 40 #include <sys/device.h> 41 #include <sys/errno.h> 42 #include <sys/extent.h> 43 #include <sys/malloc.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/bus.h> 47 #include <machine/isa_machdep.h> 48 #include <machine/pegasosreg.h> 49 50 #include <dev/pci/pcivar.h> 51 #include <dev/pci/pciconf.h> 52 #include <dev/pci/pcidevs.h> 53 54 #include <dev/marvell/gtreg.h> 55 #include <dev/marvell/gtvar.h> 56 #include <dev/marvell/gtpcireg.h> 57 #include <dev/marvell/gtpcivar.h> 58 #include <dev/marvell/marvellvar.h> 59 #include <dev/ofw/openfirm.h> 60 61 62 static int gt_match(device_t, cfdata_t, void *); 63 static void gt_attach(device_t, device_t, void *); 64 65 #if NGTPCI > 0 66 static void gtpci_md_attach_hook(device_t, device_t, 67 struct pcibus_attach_args *); 68 void gtpci_md_conf_interrupt(void *, int, int, int, int, int *); 69 int gtpci_md_conf_hook(void *, int, int, int, pcireg_t); 70 #endif 71 72 CFATTACH_DECL_NEW(gt, sizeof(struct gt_softc), gt_match, gt_attach, NULL, NULL); 73 74 static struct powerpc_bus_space pegasosii_gt_bs_tag = { 75 .pbs_offset = PEGASOS2_GT_REGBASE, 76 .pbs_base = 0x00000000, 77 .pbs_limit = GT_SIZE, 78 }; 79 static char ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)] 80 __attribute__((aligned(8))); 81 82 struct powerpc_bus_dma_tag pegasosii_bus_dma_tag = { 83 0, /* _bounce_thresh */ 84 _bus_dmamap_create, 85 _bus_dmamap_destroy, 86 _bus_dmamap_load, 87 _bus_dmamap_load_mbuf, 88 _bus_dmamap_load_uio, 89 _bus_dmamap_load_raw, 90 _bus_dmamap_unload, 91 _bus_dmamap_sync, 92 _bus_dmamem_alloc, 93 _bus_dmamem_free, 94 _bus_dmamem_map, 95 _bus_dmamem_unmap, 96 _bus_dmamem_mmap, 97 }; 98 99 #if NGTPCI > 0 100 struct powerpc_bus_space 101 gtpci0_io_bs_tag, gtpci0_mem_bs_tag, 102 gtpci1_io_bs_tag, gtpci1_mem_bs_tag; 103 #endif 104 105 struct gtpci_prot gtpci0_prot = { 106 GTPCI_ACBL_RDSIZE_32BYTE | 107 GTPCI_ACBL_RDMBURST_32BYTE | 108 GTPCI_ACBL_PCISWAP_BYTESWAP | 109 GTPCI_ACBL_SNOOP_WB | 110 GTPCI_ACBL_EN, 111 0, 112 }, gtpci1_prot = { 113 GTPCI_ACBL_RDSIZE_128BYTE | 114 GTPCI_ACBL_RDMBURST_32BYTE | 115 GTPCI_ACBL_PCISWAP_BYTESWAP | 116 GTPCI_ACBL_SNOOP_WB | 117 GTPCI_ACBL_EN, 118 0, 119 }; 120 121 122 int 123 gt_match(device_t parent, cfdata_t cf, void *aux) 124 { 125 struct confargs *ca = aux; 126 uint32_t device_id, vendor_id; 127 int node; 128 char name[32]; 129 130 if (strcmp(ca->ca_name, "gt") != 0 || 131 strcmp(model_name, "Pegasos2") != 0) 132 return 0; 133 134 /* Paranoid check... */ 135 for (node = OF_child(OF_finddevice("/")); node; node = OF_peer(node)) { 136 memset(name, 0, sizeof(name)); 137 if (OF_getprop(node, "name", name, sizeof(name)) == -1) 138 continue; 139 if (strcmp(name, "pci") == 0) { 140 for (node = OF_child(node); node; 141 node = OF_peer(node)) { 142 if (OF_getprop(node, "vendor-id", 143 &vendor_id, sizeof(vendor_id)) == -1) 144 continue; 145 if (OF_getprop(node, "device-id", 146 &device_id, sizeof(device_id)) == -1) 147 continue; 148 /* Find a Marvell system controller */ 149 if (vendor_id == PCI_VENDOR_MARVELL && 150 device_id == PCI_PRODUCT_MARVELL_MV64360) 151 return 1; 152 } 153 return 0; 154 } 155 } 156 return 0; 157 } 158 159 /* ARGSUSED */ 160 void 161 gt_attach(device_t parent, device_t self, void *aux) 162 { 163 struct gt_softc *sc = device_private(self); 164 #if NGTPCI > 0 165 uint32_t busrange[2]; 166 int node; 167 extern struct genppc_pci_chipset 168 genppc_gtpci0_chipset, genppc_gtpci1_chipset; 169 #endif 170 171 bus_space_init(&pegasosii_gt_bs_tag, "gt", 172 ex_storage, sizeof(ex_storage)); 173 174 sc->sc_dev = self; 175 sc->sc_addr = 0x00000000; 176 sc->sc_iot = &pegasosii_gt_bs_tag; 177 sc->sc_dmat = &pegasosii_bus_dma_tag; 178 179 if (bus_space_map(sc->sc_iot, sc->sc_addr, GT_SIZE, 0, &sc->sc_ioh) != 180 0) { 181 aprint_error(": registers map failed\n"); 182 return; 183 } 184 185 init_ofppc_interrupt(); 186 187 #if NGTPCI > 0 188 /* bus space map the I/O and Memory ranges of PCI unit 1(PCI bus) */ 189 node = of_find_firstchild_byname(OF_finddevice("/"), "pci"); 190 if (node != -1) { 191 gtpci1_io_bs_tag.pbs_flags = 192 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_IO_TYPE; 193 gtpci1_io_bs_tag.pbs_base = 0x00000000; 194 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, node, 195 >pci1_io_bs_tag, "gtpci 1 io-space") != 0) 196 panic("Can't init gtpci 1 io tag"); 197 gtpci1_mem_bs_tag.pbs_flags = 198 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE; 199 gtpci1_mem_bs_tag.pbs_base = 0x00000000; 200 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, node, 201 >pci1_mem_bs_tag, "gtpci 1 mem-space") != 0) 202 panic("Can't init gtpci 1 mem tag"); 203 204 /* PCI bus number */ 205 if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 206 sizeof(busrange)) { 207 aprint_error(": PCI bus range failed\n"); 208 return; 209 } 210 211 /* Override some functions */ 212 genppc_gtpci1_chipset.pc_attach_hook = gtpci_md_attach_hook; 213 genppc_gtpci1_chipset.pc_intr_map = genofw_pci_intr_map; 214 genppc_gtpci1_chipset.pc_node = node; 215 genppc_gtpci1_chipset.pc_bus = busrange[0]; 216 genppc_gtpci1_chipset.pc_iot = >pci1_io_bs_tag; 217 genppc_gtpci1_chipset.pc_memt = >pci1_mem_bs_tag; 218 219 #if NISA > 0 220 genppc_isa_io_space_tag = gtpci1_io_bs_tag; 221 genppc_isa_mem_space_tag = gtpci1_mem_bs_tag; 222 map_isa_ioregs(); 223 ofppc_init_comcons(of_find_firstchild_byname(node, "isa")); 224 #endif 225 } 226 227 /* bus space map the I/O and Memory ranges of PCI unit 0(AGP bus) */ 228 if (node != -1) 229 node = of_getnode_byname(OF_peer(node), "pci"); 230 if (node != -1 && node != 0) { 231 gtpci0_io_bs_tag.pbs_flags = 232 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_IO_TYPE; 233 gtpci0_io_bs_tag.pbs_base = 0x00000000; 234 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, node, 235 >pci0_io_bs_tag, "gtpci 0 io-space") != 0) 236 panic("Can't init gtpci 0 io tag"); 237 gtpci0_mem_bs_tag.pbs_flags = 238 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE; 239 gtpci0_mem_bs_tag.pbs_base = 0x00000000; 240 if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, node, 241 >pci0_mem_bs_tag, "gtpci 0 mem-space") != 0) 242 panic("Can't init gtpci 0 mem tag"); 243 244 /* PCI bus number */ 245 if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 246 sizeof(busrange)) { 247 aprint_error(": AGP bus range failed\n"); 248 return; 249 } 250 251 genppc_gtpci0_chipset.pc_node = node; 252 genppc_gtpci0_chipset.pc_bus = busrange[0]; 253 genppc_gtpci0_chipset.pc_iot = >pci0_io_bs_tag; 254 genppc_gtpci0_chipset.pc_memt = >pci0_mem_bs_tag; 255 256 /* Enable AGP configuration space access. */ 257 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 258 GT_GPP_Value_Set, PEGASOS2_AGP_CONF_ENABLE); 259 } 260 #endif 261 262 gt_attach_common(sc); 263 } 264 265 266 #if NGTPCI > 0 267 static void 268 gtpci_md_attach_hook(device_t parent, device_t self, 269 struct pcibus_attach_args *pba) 270 { 271 extern struct genppc_pci_chipset genppc_gtpci1_chipset; 272 273 if (device_is_a(parent, "gtpci") && 274 pba->pba_pc == &genppc_gtpci1_chipset) { 275 /* Setup interrupts for PCI bus */ 276 struct genppc_pci_chipset_businfo *pbi; 277 278 pbi = malloc(sizeof(struct genppc_pci_chipset_businfo), 279 M_DEVBUF, M_NOWAIT); 280 KASSERT(pbi != NULL); 281 pbi->pbi_properties = prop_dictionary_create(); 282 KASSERT(pbi->pbi_properties != NULL); 283 SIMPLEQ_INIT(&genppc_gtpci1_chipset.pc_pbi); 284 SIMPLEQ_INSERT_TAIL(&genppc_gtpci1_chipset.pc_pbi, pbi, next); 285 286 genofw_setup_pciintr_map(&genppc_gtpci1_chipset, pbi, 287 genppc_gtpci1_chipset.pc_node); 288 } 289 gtpci_attach_hook(parent, self, pba); 290 } 291 292 /* ARGSUSED */ 293 void 294 gtpci_md_conf_interrupt(void * v, int bus, int dev, int pin, int swiz, 295 int *iline) 296 { 297 298 /* do nothing */ 299 } 300 301 int 302 gtpci_md_conf_hook(void *v, int bus, int dev, int func, pcireg_t id) 303 { 304 struct gtpci_softc *sc = v; 305 306 if (gtpci_conf_hook(sc->sc_pc, bus, dev, func, id) == 0) 307 return 0; 308 return genofw_pci_conf_hook(sc->sc_pc, bus, dev, func, id); 309 } 310 #endif 311 312 313 void * 314 marvell_intr_establish(int irq, int ipl, int (*func)(void *), void *arg) 315 { 316 317 /* pass through */ 318 return intr_establish(irq, IST_LEVEL, ipl, func, arg); 319 } 320