1/* $NetBSD: pchb.c,v 1.17 2023/12/20 15:29:06 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.17 2023/12/20 15:29:06 thorpej Exp $"); 34 35#include "pci.h" 36 37#ifdef _KERNEL_OPT 38#include "opt_pci.h" 39#endif 40 41#include <sys/types.h> 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/device.h> 45 46#define _IBM4XX_BUS_DMA_PRIVATE 47 48#include <powerpc/ibm4xx/ibm405gp.h> 49#include <powerpc/ibm4xx/pci_machdep.h> 50#include <powerpc/ibm4xx/dev/plbvar.h> 51 52#include <dev/pci/pcivar.h> 53#include <dev/pci/pcireg.h> 54#include <dev/pci/pcidevs.h> 55#include <dev/pci/pciconf.h> 56 57static int pchbmatch(device_t, cfdata_t, void *); 58static void pchbattach(device_t, device_t, void *); 59static int pchbprint(void *, const char *); 60 61CFATTACH_DECL_NEW(pchb, 0, 62 pchbmatch, pchbattach, NULL, NULL); 63 64static int pcifound = 0; 65 66/* IO window located @ e8000000 and maps to 0-0xffff */ 67static struct powerpc_bus_space pchb_io_tag = { 68 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_IO_TYPE, 69 IBM405GP_PLB_PCI_IO_START, /* offset */ 70 IBM405GP_PCI_PCI_IO_START, /* extent base */ 71 IBM405GP_PCI_PCI_IO_START + 0xffff, /* extent limit */ 72}; 73 74/* PCI memory window is directly mapped */ 75static struct powerpc_bus_space pchb_mem_tag = { 76 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE, 77 0x00000000, /* offset */ 78 IBM405GP_PCI_MEM_START, /* extent base */ 79 IBM405GP_PCI_MEM_START + 0x1fffffff, /* extent limit */ 80}; 81 82 83static int 84pchbmatch(device_t parent, cfdata_t cf, void *aux) 85{ 86 struct plb_attach_args *paa = aux; 87 /* XXX chipset tag unused by walnut, so just pass 0 */ 88 pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag(); 89 pcitag_t tag; 90 int class, id; 91 92 /* match only pchb devices */ 93 if (strcmp(paa->plb_name, cf->cf_name) != 0) 94 return 0; 95 96 ibm4xx_pci_machdep_init(); 97 tag = pci_make_tag(pc, 0, 0, 0); 98 99 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 100 id = pci_conf_read(pc, tag, PCI_ID_REG); 101 102 /* 103 * Match all known PCI host chipsets. 104 */ 105 if (PCI_CLASS(class) == PCI_CLASS_BRIDGE && 106 PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_HOST) { 107 switch (PCI_VENDOR(id)) { 108 case PCI_VENDOR_IBM: 109 switch (PCI_PRODUCT(id)) { 110 case PCI_PRODUCT_IBM_405GP: 111 return (!pcifound); 112 } 113 break; 114 } 115 } 116 return (0); 117} 118 119static void 120pchbattach(device_t parent, device_t self, void *aux) 121{ 122 struct plb_attach_args *paa = aux; 123 struct pcibus_attach_args pba; 124 char devinfo[256]; 125#ifdef PCI_CONFIGURE_VERBOSE 126 extern int pci_conf_debug; 127 128 pci_conf_debug = 1; 129#endif 130 pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag(); 131 pcitag_t tag; 132 int class, id; 133 134 ibm4xx_pci_machdep_init(); 135 tag = pci_make_tag(pc, 0, 0, 0); 136 137 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 138 id = pci_conf_read(pc, tag, PCI_ID_REG); 139 140 aprint_normal("\n"); 141 pcifound++; 142 /* 143 * All we do is print out a description. Eventually, we 144 * might want to add code that does something that's 145 * possibly chipset-specific. 146 */ 147 148 pci_devinfo(id, class, 0, devinfo, sizeof(devinfo)); 149 aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo, 150 PCI_REVISION(class)); 151 152 ibm4xx_pci_machdep_init(); /* Redundant... */ 153 ibm4xx_setup_pci(); 154#ifdef PCI_CONFIGURE_VERBOSE 155 ibm4xx_show_pci_map(); 156#endif 157 158 if (bus_space_init(&pchb_io_tag, "pchbio", NULL, 0)) 159 panic("pchbattach: can't init IO tag"); 160 if (bus_space_init(&pchb_mem_tag, "pchbmem", NULL, 0)) 161 panic("pchbattach: can't init MEM tag"); 162 163#ifdef PCI_NETBSD_CONFIGURE 164 struct pciconf_resources *pcires = pciconf_resource_init(); 165 166 pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, 167 IBM405GP_PCI_PCI_IO_START, 0x10000); 168 pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, 169 IBM405GP_PCI_MEM_START, 0x20000000); 170 171 pci_configure_bus(pc, pcires, 0, 32); 172 pciconf_resource_fini(pcires); 173#endif /* PCI_NETBSD_CONFIGURE */ 174 175#ifdef PCI_CONFIGURE_VERBOSE 176 printf("running config_found PCI\n"); 177#endif 178 /* IO window located @ e8000000 and maps to 0-0xffff */ 179 pba.pba_iot = &pchb_io_tag; 180 /* PCI memory window is directly mapped */ 181 pba.pba_memt = &pchb_mem_tag; 182 pba.pba_dmat = paa->plb_dmat; 183 pba.pba_dmat64 = NULL; 184 pba.pba_pc = pc; 185 pba.pba_bus = 0; 186 pba.pba_bridgetag = NULL; 187 pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY; 188 config_found(self, &pba, pchbprint, CFARGS_NONE); 189} 190 191 192static int 193pchbprint(void *aux, const char *p) 194{ 195 196 if (p == NULL) 197 return (UNCONF); 198 return (QUIET); 199} 200 201#if 0 202static void 203scan_pci_bus(void) 204{ 205 pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag(); 206 pcitag_t tag; 207 int i, x; 208 209 for (i=0;i<32;i++){ 210 tag = pci_make_tag(pc, 0, i, 0); 211 x = pci_conf_read(pc, tag, 0); 212 printf("%d tag=%08x : %08x\n", i, tag, x); 213#if 0 214 if (PCI_VENDOR(x) == PCI_VENDOR_INTEL 215 && PCI_PRODUCT(x) == PCI_PRODUCT_INTEL_80960_RP) { 216 /* Do not configure PCI bus analyzer */ 217 continue; 218 } 219 x = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 220 x |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; 221 pci_conf_write(0, tag, PCI_COMMAND_STATUS_REG, x); 222#endif 223 } 224} 225#endif 226