necpb.c revision 1.23
1/* $NetBSD: necpb.c,v 1.23 2006/04/15 09:01:11 tsutsui Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 42 * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by Charles M. Hannum. 55 * 4. The name of the author may not be used to endorse or promote products 56 * derived from this software without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 */ 69 70#include <sys/cdefs.h> 71__KERNEL_RCSID(0, "$NetBSD: necpb.c,v 1.23 2006/04/15 09:01:11 tsutsui Exp $"); 72 73#include <sys/types.h> 74#include <sys/param.h> 75#include <sys/time.h> 76#include <sys/systm.h> 77#include <sys/errno.h> 78#include <sys/device.h> 79#include <sys/malloc.h> 80#include <sys/extent.h> 81 82#include <uvm/uvm_extern.h> 83 84#define _ARC_BUS_DMA_PRIVATE 85#include <machine/bus.h> 86 87#include <machine/pio.h> 88 89#include <machine/autoconf.h> 90#include <machine/cpu.h> 91#include <machine/platform.h> 92 93#include <dev/pci/pcivar.h> 94#include <dev/pci/pcireg.h> 95 96#include <arc/jazz/rd94.h> 97#include <arc/pci/necpbvar.h> 98 99#include "ioconf.h" 100 101int necpbmatch(struct device *, struct cfdata *, void *); 102void necpbattach(struct device *, struct device *, void *); 103 104void necpb_attach_hook(struct device *, struct device *, 105 struct pcibus_attach_args *); 106int necpb_bus_maxdevs(pci_chipset_tag_t, int); 107pcitag_t necpb_make_tag(pci_chipset_tag_t, int, int, int); 108void necpb_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, 109 int *, int *); 110pcireg_t necpb_conf_read(pci_chipset_tag_t, pcitag_t, int); 111void necpb_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); 112int necpb_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 113const char * necpb_intr_string(pci_chipset_tag_t, pci_intr_handle_t); 114void * necpb_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, 115 int, int (*func)(void *), void *); 116void necpb_intr_disestablish(pci_chipset_tag_t, void *); 117 118uint32_t necpb_intr(uint32_t, struct clockframe *); 119 120 121CFATTACH_DECL(necpb, sizeof(struct necpb_softc), 122 necpbmatch, necpbattach, NULL, NULL); 123 124static struct necpb_intrhand *necpb_inttbl[4]; 125 126/* There can be only one. */ 127int necpbfound; 128struct necpb_context necpb_main_context; 129static long necpb_mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(10) / sizeof(long)]; 130static long necpb_io_ex_storage[EXTENT_FIXED_STORAGE_SIZE(10) / sizeof(long)]; 131 132int 133necpbmatch(struct device *parent, struct cfdata *match, void *aux) 134{ 135 struct confargs *ca = aux; 136 137 if (strcmp(ca->ca_name, necpb_cd.cd_name) != 0) 138 return 0; 139 140 if (necpbfound) 141 return 0; 142 143 return 1; 144} 145 146/* 147 * Set up the chipset's function pointers. 148 */ 149void 150necpb_init(struct necpb_context *ncp) 151{ 152 pci_chipset_tag_t pc; 153 pcitag_t tag; 154 pcireg_t csr; 155 156 if (ncp->nc_initialized) 157 return; 158 159 arc_large_bus_space_init(&ncp->nc_memt, "necpcimem", 160 RD94_P_PCI_MEM, 0, RD94_S_PCI_MEM); 161 arc_bus_space_init_extent(&ncp->nc_memt, (caddr_t)necpb_mem_ex_storage, 162 sizeof(necpb_mem_ex_storage)); 163 164 arc_bus_space_init(&ncp->nc_iot, "necpciio", 165 RD94_P_PCI_IO, RD94_V_PCI_IO, 0, RD94_S_PCI_IO); 166 arc_bus_space_init_extent(&ncp->nc_iot, (caddr_t)necpb_io_ex_storage, 167 sizeof(necpb_io_ex_storage)); 168 169 jazz_bus_dma_tag_init(&ncp->nc_dmat); 170 171 pc = &ncp->nc_pc; 172 pc->pc_attach_hook = necpb_attach_hook; 173 pc->pc_bus_maxdevs = necpb_bus_maxdevs; 174 pc->pc_make_tag = necpb_make_tag; 175 pc->pc_decompose_tag = necpb_decompose_tag; 176 pc->pc_conf_read = necpb_conf_read; 177 pc->pc_conf_write = necpb_conf_write; 178 pc->pc_intr_map = necpb_intr_map; 179 pc->pc_intr_string = necpb_intr_string; 180 pc->pc_intr_establish = necpb_intr_establish; 181 pc->pc_intr_disestablish = necpb_intr_disestablish; 182 183 /* 184 * XXX: 185 * NEC's firmware does not configure PCI devices completely. 186 * We need to disable expansion ROM and enable mem/io/busmaster 187 * bits here. 188 */ 189 tag = necpb_make_tag(pc, 0, 3, 0); 190 csr = necpb_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 191 csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 192 PCI_COMMAND_MASTER_ENABLE; 193 necpb_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 194 necpb_conf_write(pc, tag, PCI_MAPREG_ROM, 0); 195 196 tag = necpb_make_tag(pc, 0, 4, 0); 197 csr = necpb_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 198 csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 199 PCI_COMMAND_MASTER_ENABLE; 200 necpb_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 201 necpb_conf_write(pc, tag, PCI_MAPREG_ROM, 0); 202 203 tag = necpb_make_tag(pc, 0, 5, 0); 204 csr = necpb_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 205 csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 206 PCI_COMMAND_MASTER_ENABLE; 207 necpb_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 208 necpb_conf_write(pc, tag, PCI_MAPREG_ROM, 0); 209 210 ncp->nc_initialized = 1; 211} 212 213void 214necpbattach(struct device *parent, struct device *self, void *aux) 215{ 216 struct necpb_softc *sc = (struct necpb_softc *)self; 217 struct pcibus_attach_args pba; 218 pci_chipset_tag_t pc; 219 int i; 220 221 necpbfound = 1; 222 223 printf("\n"); 224 225 sc->sc_ncp = &necpb_main_context; 226 necpb_init(sc->sc_ncp); 227 228 pc = &sc->sc_ncp->nc_pc; 229 230 out32(RD94_SYS_PCI_INTMASK, 0xf); 231 232 for (i = 0; i < 4; i++) 233 necpb_inttbl[i] = NULL; 234 235 (*platform->set_intr)(MIPS_INT_MASK_2, necpb_intr, 3); 236 237 pba.pba_iot = &sc->sc_ncp->nc_iot; 238 pba.pba_memt = &sc->sc_ncp->nc_memt; 239 pba.pba_dmat = &sc->sc_ncp->nc_dmat; 240 pba.pba_dmat64 = NULL; 241 pba.pba_pc = pc; 242 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 243 pba.pba_bus = 0; 244 pba.pba_bridgetag = NULL; 245 246 config_found_ia(self, "pcibus", &pba, pcibusprint); 247} 248 249void 250necpb_attach_hook(struct device *parent, struct device *self, 251 struct pcibus_attach_args *pba) 252{ 253} 254 255int 256necpb_bus_maxdevs(pci_chipset_tag_t pc, int busno) 257{ 258 259 return 32; 260} 261 262pcitag_t 263necpb_make_tag(pci_chipset_tag_t pc, int bus, int device, int function) 264{ 265 pcitag_t tag; 266 267 if (bus >= 256 || device >= 32 || function >= 8) 268 panic("necpb_make_tag: bad request"); 269 270 tag = 0x80000000 | (bus << 16) | (device << 11) | (function << 8); 271 return tag; 272} 273 274void 275necpb_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, 276 int *fp) 277{ 278 279 if (bp != NULL) 280 *bp = (tag >> 16) & 0xff; 281 if (dp != NULL) 282 *dp = (tag >> 11) & 0x1f; 283 if (fp != NULL) 284 *fp = (tag >> 8) & 0x07; 285} 286 287pcireg_t 288necpb_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 289{ 290 pcireg_t data; 291 int s; 292 293 s = splhigh(); 294 out32(RD94_SYS_PCI_CONFADDR, tag | reg); 295 data = in32(RD94_SYS_PCI_CONFDATA); 296 out32(RD94_SYS_PCI_CONFADDR, 0); 297 splx(s); 298 299 return data; 300} 301 302void 303necpb_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 304{ 305 int s; 306 307 s = splhigh(); 308 out32(RD94_SYS_PCI_CONFADDR, tag | reg); 309 out32(RD94_SYS_PCI_CONFDATA, data); 310 out32(RD94_SYS_PCI_CONFADDR, 0); 311 splx(s); 312} 313 314int 315necpb_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 316{ 317 pci_chipset_tag_t pc = pa->pa_pc; 318 pcitag_t intrtag = pa->pa_intrtag; 319 int pin = pa->pa_intrpin; 320 int bus, dev; 321 322 if (pin == 0) { 323 /* No IRQ used. */ 324 *ihp = -1; 325 return 1; 326 } 327 328 if (pin > 4) { 329 printf("necpb_intr_map: bad interrupt pin %d\n", pin); 330 *ihp = -1; 331 return 1; 332 } 333 334 necpb_decompose_tag(pc, intrtag, &bus, &dev, NULL); 335 if (bus != 0) { 336 *ihp = -1; 337 return 1; 338 } 339 340 switch (dev) { 341 case 3: 342 *ihp = (pin + 2) % 4; 343 break; 344 case 4: 345 *ihp = (pin + 1) % 4; 346 break; 347 case 5: 348 *ihp = (pin + 0) % 4; 349 break; 350 default: 351 *ihp = -1; 352 return 1; 353 } 354 355 return 0; 356} 357 358const char * 359necpb_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) 360{ 361 static char str[8]; 362 363 if (ih >= 4) 364 panic("necpb_intr_string: bogus handle %ld", ih); 365 sprintf(str, "int %c", 'A' + (int)ih); 366 return str; 367} 368 369void * 370necpb_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, 371 int (*func)(void *), void *arg) 372{ 373 struct necpb_intrhand *n, *p; 374 uint32_t mask; 375 376 if (ih >= 4) 377 panic("necpb_intr_establish: bogus handle"); 378 379 n = malloc(sizeof(struct necpb_intrhand), M_DEVBUF, M_NOWAIT); 380 if (n == NULL) 381 panic("necpb_intr_establish: can't malloc interrupt handle"); 382 383 n->ih_func = func; 384 n->ih_arg = arg; 385 n->ih_next = NULL; 386 n->ih_intn = ih; 387 strlcpy(n->ih_evname, necpb_intr_string(pc, ih), sizeof(n->ih_evname)); 388 evcnt_attach_dynamic(&n->ih_evcnt, EVCNT_TYPE_INTR, NULL, "necpb", 389 n->ih_evname); 390 391 if (necpb_inttbl[ih] == NULL) { 392 necpb_inttbl[ih] = n; 393 mask = in32(RD94_SYS_PCI_INTMASK); 394 mask |= 1 << ih; 395 out32(RD94_SYS_PCI_INTMASK, mask); 396 } else { 397 p = necpb_inttbl[ih]; 398 while (p->ih_next != NULL) 399 p = p->ih_next; 400 p->ih_next = n; 401 } 402 403 return n; 404} 405 406void 407necpb_intr_disestablish(pci_chipset_tag_t pc, void *cookie) 408{ 409 struct necpb_intrhand *n, *p, *q; 410 uint32_t mask; 411 412 n = cookie; 413 414 q = NULL; 415 p = necpb_inttbl[n->ih_intn]; 416 while (p != n) { 417 if (p == NULL) 418 panic("necpb_intr_disestablish: broken intr table"); 419 q = p; 420 p = p->ih_next; 421 } 422 423 if (q == NULL) { 424 necpb_inttbl[n->ih_intn] = n->ih_next; 425 if (n->ih_next == NULL) { 426 mask = in32(RD94_SYS_PCI_INTMASK); 427 mask &= ~(1 << n->ih_intn); 428 out32(RD94_SYS_PCI_INTMASK, mask); 429 } 430 } else 431 q->ih_next = n->ih_next; 432 433 evcnt_detach(&n->ih_evcnt); 434 435 free(n, M_DEVBUF); 436} 437 438/* 439 * Handle PCI/EISA interrupt. 440 */ 441uint32_t 442necpb_intr(uint32_t mask, struct clockframe *cf) 443{ 444 uint32_t vector, stat; 445 struct necpb_intrhand *p; 446 int i; 447 448 vector = in32(RD94_SYS_INTSTAT2) & 0xffff; 449 450 if (vector == 0x4000) { 451 stat = in32(RD94_SYS_PCI_INTSTAT); 452 stat &= in32(RD94_SYS_PCI_INTMASK); 453 for (i = 0; i < 4; i++) { 454 if (stat & (1 << i)) { 455#if 0 456 printf("pint %d\n", i); 457#endif 458 p = necpb_inttbl[i]; 459 while (p != NULL) { 460 (*p->ih_func)(p->ih_arg); 461 p->ih_evcnt.ev_count++; 462 p = p->ih_next; 463 } 464 } 465 } 466 } else if (vector == 0x8000) { 467 printf("eisa_nmi\n"); 468 } else { 469 printf("eint %d\n", vector & 0xff); 470#if 0 471 eisa_intr(vector & 0xff); 472#endif 473 } 474 475 return ~MIPS_INT_MASK_2; 476} 477