vrc4173bcu.c revision 1.6
1/* $NetBSD: vrc4173bcu.c,v 1.6 2002/01/13 14:18:32 takemura Exp $ */ 2 3/*- 4 * Copyright (c) 2001,2002 Enami Tsugutomo. 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. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/device.h> 32 33#include <machine/bus.h> 34 35#include <dev/pci/pcivar.h> 36#include <dev/pci/pcidevs.h> 37 38#include <machine/platid.h> 39#include <machine/platid_mask.h> 40#include <machine/config_hook.h> 41 42#include <hpcmips/vr/vrc4173bcuvar.h> 43#include <hpcmips/vr/vrc4173icureg.h> 44#include <hpcmips/vr/vrc4173cmureg.h> 45 46#define VRC4173BCU_BADR 0x10 47#ifdef DEBUG 48#define DPRINTF(args) printf args 49#else 50#define DPRINTF(args) 51#endif 52 53#define USE_WINCE_CLKMASK (~0) 54 55static int vrc4173bcu_match(struct device *, struct cfdata *, void *); 56static void vrc4173bcu_attach(struct device *, struct device *, void *); 57static int vrc4173bcu_print(void *, const char *); 58static int vrc4173bcu_intr(void *); 59 60/* 61 * machine dependent info 62 */ 63static struct vrc4173bcu_platdep { 64 platid_mask_t *platidmask; 65 u_int32_t clkmask; 66 int intrmask; 67} platdep_table[] = { 68 { 69 &platid_mask_MACH_VICTOR_INTERLINK_MPC303, 70 USE_WINCE_CLKMASK, /* clock mask */ 71 (1 << VRC4173ICU_USBINTR)| /* intrrupts */ 72 (1 << VRC4173ICU_PCMCIA1INTR)| 73 (1 << VRC4173ICU_PCMCIA2INTR), 74 }, 75 { 76 &platid_mask_MACH_VICTOR_INTERLINK_MPC304, 77 USE_WINCE_CLKMASK, /* clock mask */ 78 (1 << VRC4173ICU_USBINTR)| /* intrrupts */ 79 (1 << VRC4173ICU_PCMCIA1INTR)| 80 (1 << VRC4173ICU_PCMCIA2INTR), 81 }, 82 { 83 &platid_mask_MACH_NEC_MCR_SIGMARION2, 84 USE_WINCE_CLKMASK, /* clock mask */ 85 (1 << VRC4173ICU_USBINTR), /* intrrupts */ 86 }, 87 { 88 &platid_wild, 89 USE_WINCE_CLKMASK, /* XXX */ 90 -1, 91 }, 92}; 93 94struct vrc4173bcu_softc { 95 struct device sc_dev; 96 97 pci_chipset_tag_t sc_pc; 98 bus_space_tag_t sc_iot; 99 bus_space_handle_t sc_ioh; 100 bus_size_t sc_size; 101 102 bus_space_handle_t sc_icuh; /* I/O handle for ICU. */ 103 bus_space_handle_t sc_cmuh; /* I/O handle for CMU. */ 104 void *sc_ih; 105#define VRC4173BCU_NINTRS 16 106 config_call_tag sc_calltags[VRC4173BCU_NINTRS]; 107 int sc_intrmask; 108 109 struct vrc4173bcu_platdep *sc_platdep; 110}; 111 112struct cfattach vrc4173bcu_ca = { 113 sizeof(struct vrc4173bcu_softc), vrc4173bcu_match, vrc4173bcu_attach, 114}; 115 116int 117vrc4173bcu_match(struct device *parent, struct cfdata *match, void *aux) 118{ 119 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 120 121 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NEC && 122 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NEC_VRC4173_BCU) 123 return (1); 124 125 return (0); 126} 127 128void 129vrc4173bcu_attach(struct device *parent, struct device *self, void *aux) 130{ 131 struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)self; 132 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 133 pci_chipset_tag_t pc = pa->pa_pc; 134 pcitag_t tag = pa->pa_tag; 135 pcireg_t csr; 136 char devinfo[256]; 137 u_int16_t reg; 138 pci_intr_handle_t ih; 139 const char *intrstr; 140 int bus, device, function; 141#ifdef DEBUG 142 char buf[80]; 143#endif 144 145 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 146 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); 147 148#if 0 149 printf("%s: ", sc->sc_dev.dv_xname); 150 pci_conf_print(pa->pa_pc, pa->pa_tag, NULL); 151#endif 152 153 csr = pci_conf_read(pc, tag, VRC4173BCU_BADR); 154 DPRINTF(("%s: base addr = 0x%08x\n", sc->sc_dev.dv_xname, csr)); 155 156 sc->sc_platdep = platid_search(&platid, platdep_table, 157 sizeof(platdep_table)/sizeof(*platdep_table), 158 sizeof(*platdep_table)); 159 160 /* Map I/O registers */ 161 if (pci_mapreg_map(pa, VRC4173BCU_BADR, PCI_MAPREG_TYPE_IO, 0, 162 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size)) { 163 printf("%s: can't map mem space\n", sc->sc_dev.dv_xname); 164 return; 165 } 166 167 sc->sc_pc = pc; 168 169 /* Enable the device. */ 170 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 171 DPRINTF(("%s: csr = 0x%08x", sc->sc_dev.dv_xname, csr)); 172 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 173 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); 174 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 175 DPRINTF((" -> 0x%08x\n", csr)); 176 177 csr = pci_conf_read(pc, tag, VRC4173BCU_BADR); 178 DPRINTF(("%s: base addr = %x@0x%08x\n", sc->sc_dev.dv_xname, 179 (int)sc->sc_size, csr)); 180 DPRINTF(("%s: iot = 0x%08x, ioh = 0x%08x\n", sc->sc_dev.dv_xname, 181 (int)sc->sc_iot, (int)sc->sc_ioh)); 182 183 /* 184 * Map I/O space for ICU. 185 */ 186 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 187 VRC4173ICU_IOBASE, VRC4173ICU_IOSIZE, &sc->sc_icuh)) { 188 printf(": can't map ICU i/o space\n"); 189 return; 190 } 191 192 /* 193 * Map I/O space for CMU. 194 */ 195 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 196 VRC4173CMU_IOBASE, VRC4173CMU_IOSIZE, &sc->sc_cmuh)) { 197 printf(": can't map CMU i/o space\n"); 198 return; 199 } 200 201 /* machine dependent setup */ 202 if (sc->sc_platdep->clkmask == USE_WINCE_CLKMASK) { 203 /* XXX, You can nothing! */ 204 reg = bus_space_read_2(sc->sc_iot, sc->sc_cmuh, 205 VRC4173CMU_CLKMSK); 206 printf("%s: default clock mask is %04x\n", 207 sc->sc_dev.dv_xname, reg); 208 } else { 209 /* assert all reset bits */ 210 bus_space_write_2(sc->sc_iot, sc->sc_cmuh, VRC4173CMU_SRST, 211 VRC4173CMU_SRST_AC97 | VRC4173CMU_SRST_USB | 212 VRC4173CMU_SRST_CARD2 | VRC4173CMU_SRST_CARD1); 213 /* set clock mask */ 214 bus_space_write_2(sc->sc_iot, sc->sc_cmuh, 215 VRC4173CMU_CLKMSK, sc->sc_platdep->clkmask); 216 /* clear reset bit */ 217 bus_space_write_2(sc->sc_iot, sc->sc_cmuh, VRC4173CMU_SRST, 0); 218 } 219 220#ifdef DEBUG 221 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1); 222 bitmask_snprintf(reg, 223 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU" 224 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15", 225 buf, sizeof(buf)); 226 printf("%s: SYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf); 227 228 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MKIUINT); 229 bitmask_snprintf(reg, 230 "\20\1SCANINT\2KDATRDY\3KDATLOST\4B3\5B4\6B5\7B6\10B7" 231 "\11B8\12B9\13B10\14B11\15B12\16B13\17B14\20B15", 232 buf, sizeof(buf)); 233 printf("%s: MKIUINT = 0x%s\n", sc->sc_dev.dv_xname, buf); 234 235 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1); 236 bitmask_snprintf(reg, 237 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU" 238 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15", 239 buf, sizeof(buf)); 240 printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf); 241 242#if 1 243 reg = VRC4173ICU_USBINTR | VRC4173ICU_PIUINTR | VRC4173ICU_KIUINTR | 244 VRC4173ICU_DOZEPIUINTR; 245 bus_space_write_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1, reg); 246 247 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1); 248 bitmask_snprintf(reg, 249 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU" 250 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15", 251 buf, sizeof(buf)); 252 printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf); 253#endif 254#endif 255 256 /* 257 * install interrupt handler 258 */ 259 if (pci_intr_map(pa, &ih)) { 260 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 261 return; 262 } 263 intrstr = pci_intr_string(pc, ih); 264 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, vrc4173bcu_intr, sc); 265 if (sc->sc_ih == NULL) { 266 printf("%s: couldn't establish interrupt", 267 sc->sc_dev.dv_xname); 268 if (intrstr != NULL) 269 printf(" at %s", intrstr); 270 printf("\n"); 271 return; 272 } 273 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 274 275 /* 276 * set interrupt mask 277 */ 278 sc->sc_intrmask = sc->sc_platdep->intrmask; 279 bus_space_write_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1, 280 sc->sc_intrmask); 281 282 /* 283 * install pci intr hooks 284 */ 285 memset(sc->sc_calltags, 0, sizeof(sc->sc_calltags)); 286 pci_decompose_tag(pc, pa->pa_intrtag, &bus, &device, &function); 287 /* USB unit */ 288 if (sc->sc_intrmask & (1 << VRC4173ICU_USBINTR)) 289 sc->sc_calltags[VRC4173ICU_USBINTR] = 290 config_connect(CONFIG_HOOK_PCIINTR, 291 CONFIG_HOOK_PCIINTR_ID(bus, device, 2)); 292 /* PC card unit 1 */ 293 if (sc->sc_intrmask & (1 << VRC4173ICU_PCMCIA1INTR)) 294 sc->sc_calltags[VRC4173ICU_USBINTR] = 295 config_connect(CONFIG_HOOK_PCIINTR, 296 CONFIG_HOOK_PCIINTR_ID(bus, 1, 0)); 297 /* PC card unit 2 */ 298 if (sc->sc_intrmask & (1 << VRC4173ICU_PCMCIA2INTR)) 299 sc->sc_calltags[VRC4173ICU_USBINTR] = 300 config_connect(CONFIG_HOOK_PCIINTR, 301 CONFIG_HOOK_PCIINTR_ID(bus, 2, 0)); 302 303 /* 304 * Attach sub units found in vrc4173. XXX. 305 */ 306 config_found(self, "vrc4173cmu", vrc4173bcu_print); 307 config_found(self, "vrc4173giu", vrc4173bcu_print); 308 config_found(self, "vrc4173piu", vrc4173bcu_print); 309 config_found(self, "vrc4173kiu", vrc4173bcu_print); 310 config_found(self, "vrc4173aiu", vrc4173bcu_print); 311 config_found(self, "vrc4173ps2u", vrc4173bcu_print); 312} 313 314int 315vrc4173bcu_print(void *aux, const char *pnp) 316{ 317 const char *name = aux; 318 319 if (pnp) 320 printf("%s at %s", name, pnp); 321 322 return (UNCONF); 323} 324 325int 326vrc4173bcu_intr(void *arg) 327{ 328 struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)arg; 329 u_int16_t reg; 330 int i; 331 332 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1); 333 reg &= sc->sc_intrmask; 334 if (reg == 0) 335 return (0); 336 337#if 0 338 { 339 char buf[80]; 340 bitmask_snprintf(reg, 341 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU" 342 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15", 343 buf, sizeof(buf)); 344 printf("%s: %s\n", sc->sc_dev.dv_xname, buf); 345 } 346#endif 347 for (i = 0; i < VRC4173BCU_NINTRS; i++) 348 if (reg & (1 << i)) 349 config_connected_call(sc->sc_calltags[i], NULL); 350 351 return (1); 352} 353