1 1.30 thorpej /* $NetBSD: tsc.c,v 1.30 2023/12/04 00:32:10 thorpej Exp $ */ 2 1.1 ross 3 1.1 ross /*- 4 1.1 ross * Copyright (c) 1999 by Ross Harvey. All rights reserved. 5 1.1 ross * 6 1.1 ross * Redistribution and use in source and binary forms, with or without 7 1.1 ross * modification, are permitted provided that the following conditions 8 1.1 ross * are met: 9 1.1 ross * 1. Redistributions of source code must retain the above copyright 10 1.1 ross * notice, this list of conditions and the following disclaimer. 11 1.1 ross * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 ross * notice, this list of conditions and the following disclaimer in the 13 1.1 ross * documentation and/or other materials provided with the distribution. 14 1.1 ross * 3. All advertising materials mentioning features or use of this software 15 1.1 ross * must display the following acknowledgement: 16 1.1 ross * This product includes software developed by Ross Harvey. 17 1.1 ross * 4. The name of Ross Harvey may not be used to endorse or promote products 18 1.1 ross * derived from this software without specific prior written permission. 19 1.1 ross * 20 1.1 ross * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS 21 1.1 ross * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 1.1 ross * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE 23 1.1 ross * ARE DISCLAIMED. IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY 24 1.1 ross * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 ross * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 ross * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 ross * SUCH DAMAGE. 31 1.1 ross * 32 1.1 ross */ 33 1.1 ross 34 1.1 ross #include <sys/cdefs.h> 35 1.1 ross 36 1.30 thorpej __KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.30 2023/12/04 00:32:10 thorpej Exp $"); 37 1.1 ross 38 1.1 ross #include <sys/param.h> 39 1.1 ross #include <sys/systm.h> 40 1.1 ross #include <sys/device.h> 41 1.1 ross 42 1.1 ross #include <machine/autoconf.h> 43 1.1 ross #include <machine/rpb.h> 44 1.3 thorpej #include <machine/sysarch.h> 45 1.1 ross 46 1.1 ross #include <dev/isa/isareg.h> 47 1.1 ross #include <dev/isa/isavar.h> 48 1.1 ross #include <dev/pci/pcireg.h> 49 1.1 ross #include <dev/pci/pcivar.h> 50 1.1 ross #include <alpha/pci/tsreg.h> 51 1.1 ross #include <alpha/pci/tsvar.h> 52 1.1 ross 53 1.24 martin #include "tsciic.h" 54 1.24 martin 55 1.1 ross #define tsc() { Generate ctags(1) key. } 56 1.1 ross 57 1.17 jakllsch static int tscmatch(device_t, cfdata_t, void *); 58 1.17 jakllsch static void tscattach(device_t, device_t, void *); 59 1.1 ross 60 1.17 jakllsch CFATTACH_DECL_NEW(tsc, 0, tscmatch, tscattach, NULL, NULL); 61 1.1 ross 62 1.1 ross extern struct cfdriver tsc_cd; 63 1.1 ross 64 1.20 tsutsui struct tsp_config tsp_configuration[4]; 65 1.1 ross 66 1.14 dsl static int tscprint(void *, const char *pnp); 67 1.1 ross 68 1.17 jakllsch static int tspmatch(device_t, cfdata_t, void *); 69 1.17 jakllsch static void tspattach(device_t, device_t, void *); 70 1.1 ross 71 1.17 jakllsch CFATTACH_DECL_NEW(tsp, 0, tspmatch, tspattach, NULL, NULL); 72 1.1 ross 73 1.1 ross extern struct cfdriver tsp_cd; 74 1.1 ross 75 1.14 dsl static int tsp_bus_get_window(int, int, 76 1.14 dsl struct alpha_bus_space_translation *); 77 1.3 thorpej 78 1.23 jdc static int tsciicprint(void *, const char *pnp); 79 1.23 jdc 80 1.23 jdc static int tsciicmatch(device_t, cfdata_t, void *); 81 1.23 jdc static void tsciicattach(device_t, device_t, void *); 82 1.23 jdc 83 1.23 jdc CFATTACH_DECL_NEW(tsciic, sizeof(struct tsciic_softc), tsciicmatch, 84 1.23 jdc tsciicattach, NULL, NULL); 85 1.23 jdc 86 1.24 martin #if NTSCIIC 87 1.23 jdc extern struct cfdriver tsciic_cd; 88 1.24 martin #endif 89 1.23 jdc 90 1.1 ross /* There can be only one */ 91 1.3 thorpej static int tscfound; 92 1.1 ross 93 1.3 thorpej /* Which hose is the display console connected to? */ 94 1.3 thorpej int tsp_console_hose; 95 1.1 ross 96 1.17 jakllsch static int 97 1.17 jakllsch tscmatch(device_t parent, cfdata_t match, void *aux) 98 1.1 ross { 99 1.1 ross struct mainbus_attach_args *ma = aux; 100 1.1 ross 101 1.20 tsutsui switch (cputype) { 102 1.20 tsutsui case ST_DEC_6600: 103 1.20 tsutsui case ST_DEC_TITAN: 104 1.20 tsutsui return strcmp(ma->ma_name, tsc_cd.cd_name) == 0 && !tscfound; 105 1.20 tsutsui default: 106 1.20 tsutsui return 0; 107 1.20 tsutsui } 108 1.1 ross } 109 1.1 ross 110 1.17 jakllsch static void 111 1.17 jakllsch tscattach(device_t parent, device_t self, void * aux) 112 1.1 ross { 113 1.1 ross int i; 114 1.1 ross int nbus; 115 1.17 jakllsch uint64_t csc, aar; 116 1.1 ross struct tsp_attach_args tsp; 117 1.23 jdc struct tsciic_attach_args tsciic; 118 1.1 ross struct mainbus_attach_args *ma = aux; 119 1.20 tsutsui int titan = cputype == ST_DEC_TITAN; 120 1.1 ross 121 1.1 ross tscfound = 1; 122 1.1 ross 123 1.1 ross csc = LDQP(TS_C_CSC); 124 1.1 ross 125 1.1 ross nbus = 1 + (CSC_BC(csc) >= 2); 126 1.20 tsutsui printf(": 2127%c Core Logic Chipset, Cchip rev %d\n" 127 1.1 ross "%s%d: %c Dchips, %d memory bus%s of %d bytes\n", 128 1.20 tsutsui titan ? '4' : '2', (int)MISC_REV(LDQP(TS_C_MISC)), 129 1.1 ross ma->ma_name, ma->ma_slot, "2448"[CSC_BC(csc)], 130 1.1 ross nbus, nbus > 1 ? "es" : "", 16 + 16 * ((csc & CSC_AW) != 0)); 131 1.1 ross printf("%s%d: arrays present: ", ma->ma_name, ma->ma_slot); 132 1.22 tsutsui for (i = 0; i < 4; ++i) { 133 1.1 ross aar = LDQP(TS_C_AAR0 + i * TS_STEP); 134 1.1 ross printf("%s%dMB%s", i ? ", " : "", (8 << AAR_ASIZ(aar)) & ~0xf, 135 1.1 ross aar & AAR_SPLIT ? " (split)" : ""); 136 1.1 ross } 137 1.1 ross printf(", Dchip 0 rev %d\n", (int)LDQP(TS_D_DREV) & 0xf); 138 1.1 ross 139 1.6 thorpej memset(&tsp, 0, sizeof tsp); 140 1.1 ross tsp.tsp_name = "tsp"; 141 1.22 tsutsui tsp.tsp_slot = 0; 142 1.22 tsutsui 143 1.29 thorpej config_found(self, &tsp, tscprint, CFARGS_NONE); 144 1.20 tsutsui if (titan) { 145 1.20 tsutsui tsp.tsp_slot += 2; 146 1.29 thorpej config_found(self, &tsp, tscprint, CFARGS_NONE); 147 1.20 tsutsui } 148 1.1 ross 149 1.20 tsutsui if (csc & CSC_P1P) { 150 1.20 tsutsui tsp.tsp_slot = 1; 151 1.29 thorpej config_found(self, &tsp, tscprint, CFARGS_NONE); 152 1.20 tsutsui if (titan) { 153 1.20 tsutsui tsp.tsp_slot += 2; 154 1.29 thorpej config_found(self, &tsp, tscprint, CFARGS_NONE); 155 1.20 tsutsui } 156 1.1 ross } 157 1.23 jdc 158 1.23 jdc memset(&tsciic, 0, sizeof tsciic); 159 1.23 jdc tsciic.tsciic_name = "tsciic"; 160 1.23 jdc 161 1.29 thorpej config_found(self, &tsciic, tsciicprint, CFARGS_NONE); 162 1.1 ross } 163 1.1 ross 164 1.1 ross static int 165 1.15 dsl tscprint(void *aux, const char *p) 166 1.1 ross { 167 1.21 tsutsui struct tsp_attach_args *tsp = aux; 168 1.1 ross 169 1.22 tsutsui if (p) 170 1.10 thorpej aprint_normal("%s%d at %s", tsp->tsp_name, tsp->tsp_slot, p); 171 1.1 ross return UNCONF; 172 1.1 ross } 173 1.1 ross 174 1.23 jdc static int 175 1.23 jdc tsciicprint(void *aux, const char *p) 176 1.23 jdc { 177 1.23 jdc struct tsciic_attach_args *tsciic = aux; 178 1.23 jdc 179 1.23 jdc if (p) 180 1.23 jdc aprint_normal("%s at %s\n", tsciic->tsciic_name, p); 181 1.23 jdc else 182 1.23 jdc aprint_normal("\n"); 183 1.23 jdc return UNCONF; 184 1.23 jdc } 185 1.23 jdc 186 1.1 ross #define tsp() { Generate ctags(1) key. } 187 1.1 ross 188 1.17 jakllsch static int 189 1.17 jakllsch tspmatch(device_t parent, cfdata_t match, void *aux) 190 1.1 ross { 191 1.1 ross struct tsp_attach_args *t = aux; 192 1.1 ross 193 1.20 tsutsui switch (cputype) { 194 1.20 tsutsui case ST_DEC_6600: 195 1.20 tsutsui case ST_DEC_TITAN: 196 1.20 tsutsui return strcmp(t->tsp_name, tsp_cd.cd_name) == 0; 197 1.20 tsutsui default: 198 1.20 tsutsui return 0; 199 1.20 tsutsui } 200 1.1 ross } 201 1.1 ross 202 1.17 jakllsch static void 203 1.17 jakllsch tspattach(device_t parent, device_t self, void *aux) 204 1.1 ross { 205 1.1 ross struct pcibus_attach_args pba; 206 1.1 ross struct tsp_attach_args *t = aux; 207 1.1 ross struct tsp_config *pcp; 208 1.1 ross 209 1.1 ross printf("\n"); 210 1.30 thorpej pcp = tsp_init(t->tsp_slot); 211 1.5 thorpej 212 1.1 ross tsp_dma_init(pcp); 213 1.22 tsutsui 214 1.5 thorpej /* 215 1.5 thorpej * Do PCI memory initialization that needs to be deferred until 216 1.5 thorpej * malloc is safe. On the Tsunami, we need to do this after 217 1.5 thorpej * DMA is initialized, as well. 218 1.5 thorpej */ 219 1.5 thorpej tsp_bus_mem_init2(&pcp->pc_memt, pcp); 220 1.5 thorpej 221 1.27 thorpej alpha_pci_intr_init(pcp, &pcp->pc_iot, &pcp->pc_memt, &pcp->pc_pc); 222 1.5 thorpej 223 1.1 ross pba.pba_iot = &pcp->pc_iot; 224 1.1 ross pba.pba_memt = &pcp->pc_memt; 225 1.1 ross pba.pba_dmat = 226 1.1 ross alphabus_dma_get_tag(&pcp->pc_dmat_direct, ALPHA_BUS_PCI); 227 1.26 thorpej pba.pba_dmat64 = &pcp->pc_dmat64_direct; 228 1.1 ross pba.pba_pc = &pcp->pc_pc; 229 1.1 ross pba.pba_bus = 0; 230 1.7 thorpej pba.pba_bridgetag = NULL; 231 1.19 dyoung pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 232 1.2 thorpej PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 233 1.29 thorpej config_found(self, &pba, pcibusprint, CFARGS_NONE); 234 1.1 ross } 235 1.1 ross 236 1.1 ross struct tsp_config * 237 1.30 thorpej tsp_init(int n) 238 1.16 dsl /* n: Pchip number */ 239 1.1 ross { 240 1.1 ross struct tsp_config *pcp; 241 1.20 tsutsui int titan = cputype == ST_DEC_TITAN; 242 1.1 ross 243 1.20 tsutsui KASSERT(n >= 0 && n < __arraycount(tsp_configuration)); 244 1.1 ross pcp = &tsp_configuration[n]; 245 1.1 ross pcp->pc_pslot = n; 246 1.1 ross pcp->pc_iobase = TS_Pn(n, 0); 247 1.20 tsutsui pcp->pc_csr = S_PAGE(TS_Pn(n & 1, P_CSRBASE)); 248 1.20 tsutsui if (n & 2) { 249 1.20 tsutsui /* `A' port of PA Chip */ 250 1.20 tsutsui pcp->pc_csr++; 251 1.20 tsutsui } 252 1.20 tsutsui if (titan) { 253 1.20 tsutsui /* same address on G and A ports */ 254 1.20 tsutsui pcp->pc_tlbia = &pcp->pc_csr->port.g.tsp_tlbia.tsg_r; 255 1.20 tsutsui } else { 256 1.20 tsutsui pcp->pc_tlbia = &pcp->pc_csr->port.p.tsp_tlbia.tsg_r; 257 1.20 tsutsui } 258 1.20 tsutsui 259 1.1 ross if (!pcp->pc_initted) { 260 1.1 ross tsp_bus_io_init(&pcp->pc_iot, pcp); 261 1.1 ross tsp_bus_mem_init(&pcp->pc_memt, pcp); 262 1.3 thorpej 263 1.3 thorpej alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_IO] = 1; 264 1.3 thorpej alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_MEM] = 1; 265 1.3 thorpej 266 1.3 thorpej alpha_bus_get_window = tsp_bus_get_window; 267 1.1 ross } 268 1.1 ross tsp_pci_init(&pcp->pc_pc, pcp); 269 1.1 ross pcp->pc_initted = 1; 270 1.1 ross return pcp; 271 1.1 ross } 272 1.1 ross 273 1.1 ross static int 274 1.17 jakllsch tsp_bus_get_window(int type, int window, 275 1.17 jakllsch struct alpha_bus_space_translation *abst) 276 1.3 thorpej { 277 1.3 thorpej struct tsp_config *tsp = &tsp_configuration[tsp_console_hose]; 278 1.3 thorpej bus_space_tag_t st; 279 1.4 thorpej int error; 280 1.3 thorpej 281 1.3 thorpej switch (type) { 282 1.3 thorpej case ALPHA_BUS_TYPE_PCI_IO: 283 1.3 thorpej st = &tsp->pc_iot; 284 1.3 thorpej break; 285 1.3 thorpej 286 1.3 thorpej case ALPHA_BUS_TYPE_PCI_MEM: 287 1.3 thorpej st = &tsp->pc_memt; 288 1.3 thorpej break; 289 1.3 thorpej 290 1.3 thorpej default: 291 1.3 thorpej panic("tsp_bus_get_window"); 292 1.3 thorpej } 293 1.3 thorpej 294 1.4 thorpej error = alpha_bus_space_get_window(st, window, abst); 295 1.4 thorpej if (error) 296 1.22 tsutsui return error; 297 1.4 thorpej 298 1.4 thorpej abst->abst_sys_start = TS_PHYSADDR(abst->abst_sys_start); 299 1.4 thorpej abst->abst_sys_end = TS_PHYSADDR(abst->abst_sys_end); 300 1.4 thorpej 301 1.22 tsutsui return 0; 302 1.1 ross } 303 1.18 hans 304 1.23 jdc #define tsciic() { Generate ctags(1) key. } 305 1.23 jdc 306 1.23 jdc static int 307 1.23 jdc tsciicmatch(device_t parent, cfdata_t match, void *aux) 308 1.23 jdc { 309 1.24 martin #if NTSCIIC 310 1.23 jdc struct tsciic_attach_args *t = aux; 311 1.24 martin #endif 312 1.23 jdc 313 1.23 jdc switch (cputype) { 314 1.23 jdc case ST_DEC_6600: 315 1.23 jdc case ST_DEC_TITAN: 316 1.24 martin #if NTSCIIC 317 1.23 jdc return strcmp(t->tsciic_name, tsciic_cd.cd_name) == 0; 318 1.24 martin #endif 319 1.23 jdc default: 320 1.23 jdc return 0; 321 1.23 jdc } 322 1.23 jdc } 323 1.23 jdc 324 1.23 jdc static void 325 1.23 jdc tsciicattach(device_t parent, device_t self, void *aux) 326 1.23 jdc { 327 1.24 martin #if NTSCIIC 328 1.23 jdc tsciic_init(self); 329 1.24 martin #endif 330 1.23 jdc } 331 1.23 jdc 332 1.18 hans void 333 1.18 hans tsc_print_dir(unsigned int indent, unsigned long dir) 334 1.18 hans { 335 1.18 hans char buf[60]; 336 1.18 hans 337 1.18 hans snprintb(buf, 60, 338 1.18 hans "\177\20" 339 1.18 hans "b\77Internal Cchip asynchronous error\0" 340 1.18 hans "b\76Pchip 0 error\0" 341 1.18 hans "b\75Pchip 1 error\0" 342 1.18 hans "b\74Pchip 2 error\0" 343 1.18 hans "b\73Pchip 3 error\0", 344 1.18 hans dir); 345 1.18 hans IPRINTF(indent, "DIR = %s\n", buf); 346 1.18 hans } 347 1.18 hans 348 1.18 hans void 349 1.18 hans tsc_print_misc(unsigned int indent, unsigned long misc) 350 1.18 hans { 351 1.18 hans unsigned long tmp = MISC_NXM_SRC(misc); 352 1.18 hans 353 1.18 hans if (!MISC_NXM(misc)) 354 1.18 hans return; 355 1.18 hans 356 1.18 hans IPRINTF(indent, "NXM address detected\n"); 357 1.18 hans IPRINTF(indent, "NXM source = %s %lu\n", 358 1.18 hans tmp <= 3 ? "CPU" : "Pchip", tmp <= 3 ? tmp : tmp - 4); 359 1.18 hans } 360