isa_machdep.c revision 1.14
1/* $NetBSD: isa_machdep.c,v 1.14 2001/05/06 14:25:16 takemura 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 <dev/hpc/hpciovar.h> 42 43#include <hpcmips/hpcmips/machdep.h> 44#include "opt_vr41xx.h" 45#include <hpcmips/vr/vrcpudef.h> 46#include <hpcmips/vr/vripreg.h> 47#include <hpcmips/vr/vripvar.h> 48 49#include "locators.h" 50 51#define VRISADEBUG 52 53#ifdef VRISADEBUG 54#ifndef VRISADEBUG_CONF 55#define VRISADEBUG_CONF 0 56#endif /* VRISADEBUG_CONF */ 57int vrisa_debug = VRISADEBUG_CONF; 58#define DPRINTF(arg) if (vrisa_debug) printf arg; 59#define DBITDISP32(mask) if (vrisa_debug) bitdisp32(mask); 60#define VPRINTF(arg) if (bootverbose || vrisa_debug) printf arg; 61#else /* VRISADEBUG */ 62#define DPRINTF(arg) 63#define DBITDISP32(mask) 64#define VPRINTF(arg) if (bootverbose) printf arg; 65#endif /* VRISADEBUG */ 66 67/* 68 * intrrupt no. encoding: 69 * 70 * 0x0000000f ISA IRQ# 71 * 0x00ff0000 GPIO port# 72 * 0x01000000 interrupt signal hold/through (1:hold/0:though) 73 * 0x02000000 interrupt detection level (1:low /0:high ) 74 * 0x04000000 interrupt detection trigger (1:edge/0:level ) 75 */ 76#define INTR_IRQ(i) (((i)>> 0) & 0x0f) 77#define INTR_PORT(i) (((i)>>16) & 0xff) 78#define INTR_MODE(i) (((i)>>24) & 0x07) 79#define INTR_NIRQS 16 80 81int vrisabprint __P((void*, const char*)); 82int vrisabmatch __P((struct device*, struct cfdata*, void*)); 83void vrisabattach __P((struct device*, struct device*, void*)); 84 85struct vrisab_softc { 86 struct device sc_dev; 87 hpcio_chip_t sc_hc; 88 int sc_intr_map[INTR_NIRQS]; /* ISA <-> GIU inerrupt line mapping */ 89 struct hpcmips_isa_chipset sc_isa_ic; 90}; 91 92struct cfattach vrisab_ca = { 93 sizeof(struct vrisab_softc), vrisabmatch, vrisabattach 94}; 95 96#ifdef DEBUG_FIND_PCIC 97#include <mips/cpuregs.h> 98#warning DEBUG_FIND_PCIC 99static void __find_pcic __P((void)); 100#endif 101 102#ifdef DEBUG_FIND_COMPORT 103#include <mips/cpuregs.h> 104#include <dev/ic/ns16550reg.h> 105#include <dev/ic/comreg.h> 106#warning DEBUG_FIND_COMPORT 107static void __find_comport __P((void)); 108#endif 109 110 111int 112vrisabmatch(parent, match, aux) 113 struct device *parent; 114 struct cfdata *match; 115 void *aux; 116{ 117 struct hpcio_attach_args *haa = aux; 118 platid_mask_t mask; 119 120 if (strcmp(haa->haa_busname, match->cf_driver->cd_name)) 121 return 0; 122 if (match->cf_loc[HPCIOIFCF_PLATFORM] == HPCIOIFCF_PLATFORM_DEFAULT) 123 return 1; 124 mask = PLATID_DEREF(match->cf_loc[HPCIOIFCF_PLATFORM]); 125 if (platid_match(&platid, &mask)) 126 return 2; 127 return 0; 128} 129 130void 131vrisabattach(parent, self, aux) 132 struct device *parent; 133 struct device *self; 134 void *aux; 135{ 136 struct hpcio_attach_args *haa = aux; 137 struct vrisab_softc *sc = (void*)self; 138 struct isabus_attach_args iba; 139 bus_addr_t offset; 140 int i; 141 142 sc->sc_hc = (*haa->haa_getchip)(haa->haa_sc, VRIP_IOCHIP_VRGIU); 143 sc->sc_isa_ic.ic_sc = sc; 144 145 iba.iba_busname = "isa"; 146 iba.iba_ic = &sc->sc_isa_ic; 147 iba.iba_dmat = 0; /* XXX not yet */ 148 149 /* Allocate ISA memory space */ 150 iba.iba_memt = hpcmips_alloc_bus_space_tag(); 151 strcpy(iba.iba_memt->t_name, "ISA mem"); 152 offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAMEMOFFSET]; 153 iba.iba_memt->t_base = VR_ISA_MEM_BASE + offset; 154 iba.iba_memt->t_size = VR_ISA_MEM_SIZE - offset; 155 hpcmips_init_bus_space_extent(iba.iba_memt); 156 157 /* Allocate ISA port space */ 158 iba.iba_iot = hpcmips_alloc_bus_space_tag(); 159 strcpy(iba.iba_iot->t_name, "ISA port"); 160 /* Platform dependent setting. */ 161 offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAPORTOFFSET]; 162 iba.iba_iot->t_base = VR_ISA_PORT_BASE + offset; 163 iba.iba_iot->t_size = VR_ISA_PORT_SIZE - offset; 164 165 hpcmips_init_bus_space_extent(iba.iba_iot); 166 167#ifdef DEBUG_FIND_PCIC 168#warning DEBUG_FIND_PCIC 169 __find_pcic(); 170#else 171 /* Initialize ISA IRQ <-> GPIO mapping */ 172 for (i = 0; i < INTR_NIRQS; i++) 173 sc->sc_intr_map[i] = -1; 174 printf (":ISA port %#x-%#x mem %#x-%#x\n", 175 iba.iba_iot->t_base, iba.iba_iot->t_base + iba.iba_iot->t_size, 176 iba.iba_memt->t_base, iba.iba_memt->t_base + iba.iba_memt->t_size); 177 config_found(self, &iba, vrisabprint); 178#endif 179 180#ifdef DEBUG_FIND_COMPORT 181#warning DEBUG_FIND_COMPORT 182 __find_comport(); 183#endif 184} 185 186int 187vrisabprint(aux, pnp) 188 void *aux; 189 const char *pnp; 190{ 191 if (pnp) 192 return (QUIET); 193 return (UNCONF); 194} 195 196void 197isa_attach_hook(parent, self, iba) 198 struct device *parent, *self; 199 struct isabus_attach_args *iba; 200{ 201} 202 203const struct evcnt * 204isa_intr_evcnt(isa_chipset_tag_t ic, int irq) 205{ 206 207 /* XXX for now, no evcnt parent reported */ 208 return NULL; 209} 210 211void * 212isa_intr_establish(ic, intr, type, level, ih_fun, ih_arg) 213 isa_chipset_tag_t ic; 214 int intr; 215 int type; /* XXX not yet */ 216 int level; /* XXX not yet */ 217 int (*ih_fun) __P((void*)); 218 void *ih_arg; 219{ 220 struct vrisab_softc *sc = ic->ic_sc; 221 int port, irq, mode; 222 223 static int intr_modes[8] = { 224 HPCIO_INTR_LEVEL_HIGH_THROUGH, 225 HPCIO_INTR_LEVEL_HIGH_HOLD, 226 HPCIO_INTR_LEVEL_LOW_THROUGH, 227 HPCIO_INTR_LEVEL_LOW_HOLD, 228 HPCIO_INTR_EDGE_THROUGH, 229 HPCIO_INTR_EDGE_HOLD, 230 HPCIO_INTR_EDGE_THROUGH, 231 HPCIO_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 -> %s port %d, %s\n", 260 irq, sc->sc_hc->hc_name, port, intr_mode_names[mode])); 261 262 /* Call Vr routine */ 263 return hpcio_intr_establish(sc->sc_hc, port, intr_modes[mode], 264 ih_fun, ih_arg); 265} 266 267void 268isa_intr_disestablish(ic, arg) 269 isa_chipset_tag_t ic; 270 void *arg; 271{ 272 struct vrisab_softc *sc = ic->ic_sc; 273 /* Call Vr routine */ 274 hpcio_intr_disestablish(sc->sc_hc, arg); 275} 276 277int 278isa_intr_alloc(ic, mask, type, irq) 279 isa_chipset_tag_t ic; 280 int mask; 281 int type; 282 int *irq; 283{ 284 /* XXX not coded yet. this is temporary XXX */ 285 DPRINTF(("isa_intr_alloc:")); 286 DBITDISP32(mask); 287 *irq = (ffs(mask) -1); /* XXX */ 288 return 0; 289} 290 291 292#ifdef DEBUG_FIND_PCIC 293#warning DEBUG_FIND_PCIC 294static void 295__find_pcic(void) 296{ 297 int i, j, step, found; 298 u_int32_t addr; 299 u_int8_t reg; 300 int __read_revid (u_int32_t port) 301 { 302 addr = MIPS_PHYS_TO_KSEG1(i + port); 303 printf("%#x\r", i); 304 for (found = 0, j = 0; j < 0x100; j += 0x40) { 305 *((volatile u_int8_t*)addr) = j; 306 reg = *((volatile u_int8_t*)(addr + 1)); 307#ifdef DEBUG_FIND_PCIC_I82365SL_ONLY 308 if (reg == 0x82 || reg == 0x83) { 309#else 310 if ((reg & 0xc0) == 0x80) { 311#endif 312 found++; 313 } 314 } 315 if (found) 316 printf("\nfound %d socket at %#x (base from %#x)\n", found, addr, 317 i + port - VR_ISA_PORT_BASE); 318 }; 319 step = 0x1000000; 320 printf("\nFinding PCIC. Trying ISA port %#x-%#x step %#x\n", 321 VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE, step); 322 for (i = VR_ISA_PORT_BASE; i < VR_ISA_PORT_BASE+VR_ISA_PORT_SIZE; i+= step) { 323 __read_revid (0x3e0); 324 __read_revid (0x3e2); 325 } 326} 327#endif 328 329 330#ifdef DEBUG_FIND_COMPORT 331#warning DEBUG_FIND_COMPORT 332 333static int probe_com __P((u_int32_t)); 334 335static int probe_com( port_addr ) 336 u_int32_t port_addr; 337{ 338 u_int32_t addr; 339 u_int8_t ubtmp1; 340 u_int8_t ubtmp2; 341 342 addr = MIPS_PHYS_TO_KSEG1( port_addr ); 343 344 *((volatile u_int8_t*)(addr + com_cfcr)) = LCR_8BITS; 345 *((volatile u_int8_t*)(addr + com_iir)) = 0; 346 347 ubtmp1 = *((volatile u_int8_t*)(addr + com_cfcr)); 348 ubtmp2 = *((volatile u_int8_t*)(addr + com_iir)); 349 350 if( (ubtmp1 != LCR_8BITS) || ((ubtmp2 & 0x38) != 0) ){ 351 return( 0 ); 352 } 353 354 return( 1 ); 355} 356 357static void 358__find_comport(void) 359{ 360 int found; 361 u_int32_t port; 362 u_int32_t step; 363 364 found = 0; 365 step = 0x08; 366 367 printf("Searching COM port. Trying ISA port %#x-%#x step %#x\n", 368 VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE - 1, step ); 369 370 for( port = VR_ISA_PORT_BASE ; port < (VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE) ; port += step ){ 371 if( probe_com( port ) ){ 372 found++; 373 printf("found %d at %#x\n",found,port); 374 } 375 } 376} 377#endif 378