1 /* $NetBSD: mainbus.c,v 1.35 2023/12/20 15:29:07 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Christopher G. Demetriou. 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Christopher G. Demetriou 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.35 2023/12/20 15:29:07 thorpej Exp $"); 35 36 #include "opt_pci.h" 37 #include "pci.h" 38 39 #include <sys/param.h> 40 #include <sys/device.h> 41 #include <sys/systm.h> 42 43 #include <machine/autoconf.h> 44 #include <machine/bootinfo.h> 45 #include <machine/isa_machdep.h> 46 47 #include <powerpc/oea/spr.h> 48 49 #include <dev/pci/pcivar.h> 50 #include <dev/pci/pciconf.h> 51 52 int mainbus_match(device_t, cfdata_t, void *); 53 void mainbus_attach(device_t, device_t, void *); 54 int mainbus_print(void *, const char *); 55 56 CFATTACH_DECL_NEW(mainbus, 0, 57 mainbus_match, mainbus_attach, NULL, NULL); 58 59 struct powerpc_isa_chipset genppc_ict; 60 61 #define PCI_IO_START 0x00001000 62 #define PCI_IO_END 0x0000ffff 63 #define PCI_IO_SIZE ((PCI_IO_END - PCI_IO_START) + 1) 64 65 #define PCI_MEM_START 0x80000000U 66 #define PCI_MEM_END 0x8fffffffU 67 #define PCI_MEM_SIZE ((PCI_MEM_END - PCI_MEM_START) + 1) 68 69 /* 70 * Probe for the mainbus; always succeeds. 71 */ 72 int 73 mainbus_match(device_t parent, cfdata_t match, void *aux) 74 { 75 76 return 1; 77 } 78 79 /* 80 * Attach the mainbus. 81 */ 82 void 83 mainbus_attach(device_t parent, device_t self, void *aux) 84 { 85 struct mainbus_attach_args mba; 86 struct pcibus_attach_args pba; 87 struct btinfo_prodfamily *pfam; 88 89 aprint_naive("\n"); 90 aprint_normal("\n"); 91 92 mba.ma_name = "cpu"; 93 config_found(self, &mba, mainbus_print, 94 CFARGS(.iattr = "mainbus")); 95 96 mba.ma_name = "eumb"; 97 mba.ma_bst = &sandpoint_eumb_space_tag; 98 config_found(self, &mba, mainbus_print, 99 CFARGS(.iattr = "mainbus")); 100 101 pfam = lookup_bootinfo(BTINFO_PRODFAMILY); 102 if (pfam != NULL && strcmp(pfam->name, "nhnas") == 0) { 103 /* attach nhpow(4) for NH230/231 only */ 104 mba.ma_name = "nhpow"; 105 mba.ma_bst = &sandpoint_nhgpio_space_tag; 106 config_found(self, &mba, mainbus_print, 107 CFARGS(.iattr = "mainbus")); 108 } 109 110 mba.ma_name = "cfi"; 111 mba.ma_bst = &sandpoint_flash_space_tag; 112 config_found(self, &mba, mainbus_print, 113 CFARGS(.iattr = "mainbus")); 114 115 /* 116 * XXX Note also that the presence of a PCI bus should 117 * XXX _always_ be checked, and if present the bus should be 118 * XXX 'found'. However, because of the structure of the code, 119 * XXX that's not currently possible. 120 */ 121 #if NPCI > 0 122 #if defined(PCI_NETBSD_CONFIGURE) 123 struct pciconf_resources *pcires = pciconf_resource_init(); 124 125 pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, 126 PCI_IO_START, PCI_IO_SIZE); 127 pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, 128 PCI_MEM_START, PCI_MEM_SIZE); 129 130 pci_configure_bus(0, pcires, 0, 32); 131 132 pciconf_resource_fini(pcires); 133 #endif 134 135 pba.pba_iot = &sandpoint_io_space_tag; 136 pba.pba_memt = &sandpoint_mem_space_tag; 137 pba.pba_dmat = &pci_bus_dma_tag; 138 pba.pba_dmat64 = NULL; 139 pba.pba_bus = 0; 140 pba.pba_pc = 0; 141 pba.pba_bridgetag = NULL; 142 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 143 144 config_found(self, &pba, pcibusprint, 145 CFARGS(.iattr = "pcibus")); 146 #endif 147 } 148 149 static int cpu_match(device_t, cfdata_t, void *); 150 static void cpu_attach(device_t, device_t, void *); 151 152 CFATTACH_DECL_NEW(cpu, 0, cpu_match, cpu_attach, NULL, NULL); 153 154 extern struct cfdriver cpu_cd; 155 156 int 157 cpu_match(device_t parent, cfdata_t cf, void *aux) 158 { 159 struct mainbus_attach_args *mba = aux; 160 161 if (strcmp(mba->ma_name, cpu_cd.cd_name) != 0) 162 return 0; 163 164 if (cpu_info[0].ci_dev != NULL) 165 return 0; 166 167 return 1; 168 } 169 170 void 171 cpu_attach(device_t parent, device_t self, void *aux) 172 { 173 static uint8_t mem_to_cpuclk[] = { 174 25, 30, 45, 20, 20, 00, 10, 30, 175 30, 20, 45, 30, 25, 35, 30, 35, 176 20, 25, 20, 30, 35, 40, 40, 20, 177 30, 25, 40, 30, 30, 25, 35, 00 178 }; 179 extern u_long ticks_per_sec; 180 struct cpu_info *ci; 181 u_int hid1, vers; 182 183 ci = cpu_attach_common(self, 0); 184 if (ci == NULL) 185 return; 186 187 vers = (mfpvr() >> 16) & 0xffff; 188 if (ci->ci_khz == 0 && vers == MPC8245) { 189 /* calculate speed from bus clock and PLL ratio */ 190 asm volatile ("mfspr %0,1009" : "=r"(hid1)); 191 ci->ci_khz = ((uint64_t)ticks_per_sec * 4 * 192 mem_to_cpuclk[hid1 >> 27] + 10) / 10000; 193 aprint_normal_dev(self, "%u.%02u MHz\n", 194 ci->ci_khz / 1000, (ci->ci_khz / 10) % 100); 195 } 196 } 197 198 int 199 mainbus_print(void *aux, const char *pnp) 200 { 201 struct mainbus_attach_args *mba = aux; 202 203 if (pnp) 204 aprint_normal("%s at %s", mba->ma_name, pnp); 205 return UNCONF; 206 } 207