isa_machdep.c revision 1.12
1/* $NetBSD: isa_machdep.c,v 1.12 2001/04/18 11:07:26 sato Exp $ */ 2 3/* 4 * Copyright (c) 1999, by UCHIYAMA Yasushi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the developer may NOT be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28#include <sys/param.h> 29#include <sys/systm.h> 30#include <sys/device.h> 31#include <sys/reboot.h> 32 33#include <machine/bus.h> 34 35#include <dev/isa/isavar.h> 36#include <dev/isa/isareg.h> 37 38#include <machine/platid.h> 39#include <machine/platid_mask.h> 40 41#include <hpcmips/hpcmips/machdep.h> 42#include "opt_vr41xx.h" 43#include <hpcmips/vr/vrcpudef.h> 44#include <hpcmips/vr/vripreg.h> 45#include <hpcmips/vr/vripvar.h> 46#include <hpcmips/vr/vrgiureg.h> 47 48#include "locators.h" 49 50#define VRISADEBUG 51 52#ifdef VRISADEBUG 53#ifndef VRISADEBUG_CONF 54#define VRISADEBUG_CONF 0 55#endif /* VRISADEBUG_CONF */ 56int vrisa_debug = VRISADEBUG_CONF; 57#define DPRINTF(arg) if (vrisa_debug) printf arg; 58#define DBITDISP32(mask) if (vrisa_debug) bitdisp32(mask); 59#define VPRINTF(arg) if (bootverbose || vrisa_debug) printf arg; 60#else /* VRISADEBUG */ 61#define DPRINTF(arg) 62#define DBITDISP32(mask) 63#define VPRINTF(arg) if (bootverbose) printf arg; 64#endif /* VRISADEBUG */ 65 66int vrisabprint __P((void*, const char*)); 67int vrisabmatch __P((struct device*, struct cfdata*, void*)); 68void vrisabattach __P((struct device*, struct device*, void*)); 69 70struct vrisab_softc { 71 struct device sc_dev; 72 vrgiu_chipset_tag_t sc_gc; 73 vrgiu_function_tag_t sc_gf; 74 int sc_intr_map[MAX_GPIO_INOUT]; /* ISA <-> GIU inerrupt line mapping */ 75 struct hpcmips_isa_chipset sc_isa_ic; 76}; 77 78struct cfattach vrisab_ca = { 79 sizeof(struct vrisab_softc), vrisabmatch, vrisabattach 80}; 81 82#ifdef DEBUG_FIND_PCIC 83#include <mips/cpuregs.h> 84#warning DEBUG_FIND_PCIC 85static void __find_pcic __P((void)); 86#endif 87 88#ifdef DEBUG_FIND_COMPORT 89#include <mips/cpuregs.h> 90#include <dev/ic/ns16550reg.h> 91#include <dev/ic/comreg.h> 92#warning DEBUG_FIND_COMPORT 93static void __find_comport __P((void)); 94#endif 95 96 97int 98vrisabmatch(parent, match, aux) 99 struct device *parent; 100 struct cfdata *match; 101 void *aux; 102{ 103 struct gpbus_attach_args *gpa = aux; 104 platid_mask_t mask; 105 106 if (strcmp(gpa->gpa_busname, match->cf_driver->cd_name)) 107 return 0; 108 if (match->cf_loc[VRISABIFCF_PLATFORM] == VRISABIFCF_PLATFORM_DEFAULT) 109 return 1; 110 mask = PLATID_DEREF(match->cf_loc[VRISABIFCF_PLATFORM]); 111 if (platid_match(&platid, &mask)) 112 return 2; 113 return 0; 114} 115 116void 117vrisabattach(parent, self, aux) 118 struct device *parent; 119 struct device *self; 120 void *aux; 121{ 122 struct gpbus_attach_args *gpa = aux; 123 struct vrgiu_softc *chipset; 124 struct vrisab_softc *sc = (void*)self; 125 struct isabus_attach_args iba; 126 bus_addr_t offset; 127 int i; 128 129 sc->sc_gc = chipset = gpa->gpa_gc; 130 sc->sc_gf = gpa->gpa_gf; 131 sc->sc_isa_ic.ic_sc = sc; 132 133 iba.iba_busname = "isa"; 134 iba.iba_ic = &sc->sc_isa_ic; 135 iba.iba_dmat = 0; /* XXX not yet */ 136 137 /* Allocate ISA memory space */ 138 iba.iba_memt = hpcmips_alloc_bus_space_tag(); 139 strcpy(iba.iba_memt->t_name, "ISA mem"); 140 offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAMEMOFFSET]; 141 iba.iba_memt->t_base = VR_ISA_MEM_BASE + offset; 142 iba.iba_memt->t_size = VR_ISA_MEM_SIZE - offset; 143 hpcmips_init_bus_space_extent(iba.iba_memt); 144 145 /* Allocate ISA port space */ 146 iba.iba_iot = hpcmips_alloc_bus_space_tag(); 147 strcpy(iba.iba_iot->t_name, "ISA port"); 148 /* Platform dependent setting. */ 149 offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAPORTOFFSET]; 150 iba.iba_iot->t_base = VR_ISA_PORT_BASE + offset; 151 iba.iba_iot->t_size = VR_ISA_PORT_SIZE - offset; 152 153 hpcmips_init_bus_space_extent(iba.iba_iot); 154 155#ifdef DEBUG_FIND_PCIC 156#warning DEBUG_FIND_PCIC 157 __find_pcic(); 158#else 159 /* Initialize ISA IRQ <-> GPIO mapping */ 160 for (i = 0; i < MAX_GPIO_INOUT; i++) 161 sc->sc_intr_map[i] = -1; 162 printf (":ISA port %#x-%#x mem %#x-%#x\n", 163 iba.iba_iot->t_base, iba.iba_iot->t_base + iba.iba_iot->t_size, 164 iba.iba_memt->t_base, iba.iba_memt->t_base + iba.iba_memt->t_size); 165 config_found(self, &iba, vrisabprint); 166#endif 167 168#ifdef DEBUG_FIND_COMPORT 169#warning DEBUG_FIND_COMPORT 170 __find_comport(); 171#endif 172} 173 174int 175vrisabprint(aux, pnp) 176 void *aux; 177 const char *pnp; 178{ 179 if (pnp) 180 return (QUIET); 181 return (UNCONF); 182} 183 184void 185isa_attach_hook(parent, self, iba) 186 struct device *parent, *self; 187 struct isabus_attach_args *iba; 188{ 189} 190 191const struct evcnt * 192isa_intr_evcnt(isa_chipset_tag_t ic, int irq) 193{ 194 195 /* XXX for now, no evcnt parent reported */ 196 return NULL; 197} 198 199void * 200isa_intr_establish(ic, intr, type, level, ih_fun, ih_arg) 201 isa_chipset_tag_t ic; 202 int intr; 203 int type; /* XXX not yet */ 204 int level; /* XXX not yet */ 205 int (*ih_fun) __P((void*)); 206 void *ih_arg; 207{ 208 struct vrisab_softc *sc = ic->ic_sc; 209 int port, irq, mode; 210 211 /* 212 * 'intr' encoding: 213 * 214 * 0x0000000f ISA IRQ# 215 * 0x00ff0000 GPIO port# 216 * 0x01000000 interrupt signal hold/through (1:hold/0:though) 217 * 0x02000000 interrupt detection level (1:low /0:high ) 218 * 0x04000000 interrupt detection trigger (1:edge/0:level ) 219 */ 220#define INTR_IRQ(i) (((i)>> 0) & 0x0f) 221#define INTR_PORT(i) (((i)>>16) & 0xff) 222#define INTR_MODE(i) (((i)>>24) & 0x07) 223 static int intr_modes[8] = { 224 VRGIU_INTR_LEVEL_HIGH_THROUGH, 225 VRGIU_INTR_LEVEL_HIGH_HOLD, 226 VRGIU_INTR_LEVEL_LOW_THROUGH, 227 VRGIU_INTR_LEVEL_LOW_HOLD, 228 VRGIU_INTR_EDGE_THROUGH, 229 VRGIU_INTR_EDGE_HOLD, 230 VRGIU_INTR_EDGE_THROUGH, 231 VRGIU_INTR_EDGE_HOLD, 232 }; 233#ifdef VRISADEBUG 234 static char* intr_mode_names[8] = { 235 "level high through", 236 "level high hold", 237 "level low through", 238 "level low hold", 239 "edge through", 240 "edge hold", 241 "edge through", 242 "edge hold", 243 }; 244#endif /* VRISADEBUG */ 245 /* 246 * ISA IRQ <-> GPIO port mapping 247 */ 248 irq = INTR_IRQ(intr); 249 if (sc->sc_intr_map[irq] != -1) { 250 /* already mapped */ 251 intr = sc->sc_intr_map[irq]; 252 } else { 253 /* not mapped yet */ 254 sc->sc_intr_map[irq] = intr; /* Register it */ 255 } 256 mode = INTR_MODE(intr); 257 port = INTR_PORT(intr); 258 259 VPRINTF(("ISA IRQ %d -> GPIO port %d, %s\n", 260 irq, port, intr_mode_names[mode])); 261 262 /* Call Vr routine */ 263 return sc->sc_gf->gf_intr_establish(sc->sc_gc, port, 264 intr_modes[mode], 265 level, ih_fun, ih_arg); 266} 267 268void 269isa_intr_disestablish(ic, arg) 270 isa_chipset_tag_t ic; 271 void *arg; 272{ 273 struct vrisab_softc *sc = ic->ic_sc; 274 /* Call Vr routine */ 275 sc->sc_gf->gf_intr_disestablish(sc->sc_gc, arg); 276} 277 278int 279isa_intr_alloc(ic, mask, type, irq) 280 isa_chipset_tag_t ic; 281 int mask; 282 int type; 283 int *irq; 284{ 285 /* XXX not coded yet. this is temporary XXX */ 286 DPRINTF(("isa_intr_alloc:")); 287 DBITDISP32(mask); 288 *irq = (ffs(mask) -1); /* XXX */ 289 return 0; 290} 291 292 293#ifdef DEBUG_FIND_PCIC 294#warning DEBUG_FIND_PCIC 295static void 296__find_pcic(void) 297{ 298 int i, j, step, found; 299 u_int32_t addr; 300 u_int8_t reg; 301 int __read_revid (u_int32_t port) 302 { 303 addr = MIPS_PHYS_TO_KSEG1(i + port); 304 printf("%#x\r", i); 305 for (found = 0, j = 0; j < 0x100; j += 0x40) { 306 *((volatile u_int8_t*)addr) = j; 307 reg = *((volatile u_int8_t*)(addr + 1)); 308#ifdef DEBUG_FIND_PCIC_I82365SL_ONLY 309 if (reg == 0x82 || reg == 0x83) { 310#else 311 if ((reg & 0xc0) == 0x80) { 312#endif 313 found++; 314 } 315 } 316 if (found) 317 printf("\nfound %d socket at %#x (base from %#x)\n", found, addr, 318 i + port - VR_ISA_PORT_BASE); 319 }; 320 step = 0x1000000; 321 printf("\nFinding PCIC. Trying ISA port %#x-%#x step %#x\n", 322 VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE, step); 323 for (i = VR_ISA_PORT_BASE; i < VR_ISA_PORT_BASE+VR_ISA_PORT_SIZE; i+= step) { 324 __read_revid (0x3e0); 325 __read_revid (0x3e2); 326 } 327} 328#endif 329 330 331#ifdef DEBUG_FIND_COMPORT 332#warning DEBUG_FIND_COMPORT 333 334static int probe_com __P((u_int32_t)); 335 336static int probe_com( port_addr ) 337 u_int32_t port_addr; 338{ 339 u_int32_t addr; 340 u_int8_t ubtmp1; 341 u_int8_t ubtmp2; 342 343 addr = MIPS_PHYS_TO_KSEG1( port_addr ); 344 345 *((volatile u_int8_t*)(addr + com_cfcr)) = LCR_8BITS; 346 *((volatile u_int8_t*)(addr + com_iir)) = 0; 347 348 ubtmp1 = *((volatile u_int8_t*)(addr + com_cfcr)); 349 ubtmp2 = *((volatile u_int8_t*)(addr + com_iir)); 350 351 if( (ubtmp1 != LCR_8BITS) || ((ubtmp2 & 0x38) != 0) ){ 352 return( 0 ); 353 } 354 355 return( 1 ); 356} 357 358static void 359__find_comport(void) 360{ 361 int found; 362 u_int32_t port; 363 u_int32_t step; 364 365 found = 0; 366 step = 0x08; 367 368 printf("Searching COM port. Trying ISA port %#x-%#x step %#x\n", 369 VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE - 1, step ); 370 371 for( port = VR_ISA_PORT_BASE ; port < (VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE) ; port += step ){ 372 if( probe_com( port ) ){ 373 found++; 374 printf("found %d at %#x\n",found,port); 375 } 376 } 377} 378#endif 379