cy_pci.c revision 1.18
11.18Sthorpej/* $NetBSD: cy_pci.c,v 1.18 2005/06/28 00:28:41 thorpej Exp $ */ 21.1Schristos 31.1Schristos/* 41.1Schristos * cy_pci.c 51.1Schristos * 61.1Schristos * Driver for Cyclades Cyclom-8/16/32 multiport serial cards 71.1Schristos * (currently not tested with Cyclom-32 cards) 81.1Schristos * 91.1Schristos * Timo Rossi, 1996 101.1Schristos */ 111.13Slukem 121.13Slukem#include <sys/cdefs.h> 131.18Sthorpej__KERNEL_RCSID(0, "$NetBSD: cy_pci.c,v 1.18 2005/06/28 00:28:41 thorpej Exp $"); 141.11Sthorpej 151.1Schristos#include <sys/param.h> 161.1Schristos#include <sys/systm.h> 171.1Schristos#include <sys/device.h> 181.1Schristos 191.1Schristos#include <machine/bus.h> 201.1Schristos#include <machine/intr.h> 211.1Schristos 221.1Schristos#include <dev/pci/pcivar.h> 231.1Schristos#include <dev/pci/pcireg.h> 241.1Schristos#include <dev/pci/pcidevs.h> 251.1Schristos 261.1Schristos#include <dev/ic/cd1400reg.h> 271.1Schristos#include <dev/ic/cyreg.h> 281.1Schristos#include <dev/ic/cyvar.h> 291.1Schristos 301.11Sthorpejstruct cy_pci_softc { 311.11Sthorpej struct cy_softc sc_cy; /* real cy softc */ 321.11Sthorpej 331.11Sthorpej bus_space_tag_t sc_iot; /* PLX runtime i/o tag */ 341.11Sthorpej bus_space_handle_t sc_ioh; /* PLX runtime i/o handle */ 351.11Sthorpej}; 361.11Sthorpej 371.11Sthorpejstatic const struct cy_pci_product { 381.11Sthorpej pci_product_id_t cp_product; /* product ID */ 391.11Sthorpej pcireg_t cp_memtype; /* memory type */ 401.11Sthorpej} cy_pci_products[] = { 411.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_1, 421.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 431.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_1, 441.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 451.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_1, 461.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 471.11Sthorpej 481.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_2, 491.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 501.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_2, 511.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 521.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_2, 531.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 541.1Schristos 551.11Sthorpej { 0, 561.11Sthorpej 0 }, 571.11Sthorpej}; 581.11Sthorpejstatic const int cy_pci_nproducts = 591.11Sthorpej sizeof(cy_pci_products) / sizeof(cy_pci_products[0]); 601.5Scgd 611.11Sthorpejstatic const struct cy_pci_product * 621.11Sthorpejcy_pci_lookup(const struct pci_attach_args *pa) 631.11Sthorpej{ 641.11Sthorpej const struct cy_pci_product *cp; 651.11Sthorpej int i; 661.5Scgd 671.11Sthorpej if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CYCLADES) 681.11Sthorpej return (NULL); 691.1Schristos 701.11Sthorpej for (i = 0; i < cy_pci_nproducts; i++) { 711.11Sthorpej cp = &cy_pci_products[i]; 721.11Sthorpej if (PCI_PRODUCT(pa->pa_id) == cp->cp_product) 731.11Sthorpej return (cp); 741.11Sthorpej } 751.11Sthorpej return (NULL); 761.1Schristos} 771.1Schristos 781.18Sthorpejstatic int 791.11Sthorpejcy_pci_match(struct device *parent, struct cfdata *match, void *aux) 801.1Schristos{ 811.11Sthorpej struct pci_attach_args *pa = aux; 821.1Schristos 831.11Sthorpej return (cy_pci_lookup(pa) != NULL); 841.1Schristos} 851.1Schristos 861.18Sthorpejstatic void 871.11Sthorpejcy_pci_attach(struct device *parent, struct device *self, void *aux) 881.1Schristos{ 891.11Sthorpej struct cy_pci_softc *psc = (void *) self; 901.11Sthorpej struct cy_softc *sc = (void *) &psc->sc_cy; 911.11Sthorpej struct pci_attach_args *pa = aux; 921.11Sthorpej pci_intr_handle_t ih; 931.11Sthorpej const struct cy_pci_product *cp; 941.5Scgd const char *intrstr; 951.9Stsubai int plx_ver; 961.1Schristos 971.17Sthorpej aprint_naive(": Multi-port serial controller\n"); 981.17Sthorpej 991.1Schristos sc->sc_bustype = CY_BUSTYPE_PCI; 1001.1Schristos 1011.11Sthorpej cp = cy_pci_lookup(pa); 1021.11Sthorpej if (cp == NULL) 1031.11Sthorpej panic("cy_pci_attach: impossible"); 1041.11Sthorpej 1051.17Sthorpej aprint_normal(": Cyclades-Y multiport serial\n"); 1061.11Sthorpej 1071.11Sthorpej if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_IO, 0, 1081.11Sthorpej &psc->sc_iot, &psc->sc_ioh, NULL, NULL) != 0) { 1091.17Sthorpej aprint_error("%s: unable to map PLX registers\n", 1101.11Sthorpej sc->sc_dev.dv_xname); 1111.5Scgd return; 1121.5Scgd } 1131.1Schristos 1141.11Sthorpej if (pci_mapreg_map(pa, 0x18, cp->cp_memtype, 0, 1151.11Sthorpej &sc->sc_memt, &sc->sc_bsh, NULL, NULL) != 0) { 1161.17Sthorpej aprint_error("%s: unable to map device registers\n", 1171.11Sthorpej sc->sc_dev.dv_xname); 1181.11Sthorpej return; 1191.11Sthorpej } 1201.1Schristos 1211.5Scgd if (cy_find(sc) == 0) { 1221.17Sthorpej aprint_error("%s: unable to find CD1400s\n", 1231.17Sthorpej sc->sc_dev.dv_xname); 1241.5Scgd return; 1251.5Scgd } 1261.5Scgd 1271.11Sthorpej /* 1281.11Sthorpej * XXX Like the Cyclades-Z, we should really check the EEPROM to 1291.11Sthorpej * determine the "poll or interrupt" setting. For now, we always 1301.11Sthorpej * map the interrupt and enable it in the PLX. 1311.11Sthorpej */ 1321.11Sthorpej 1331.11Sthorpej /* Map and establish the interrupt. */ 1341.11Sthorpej if (pci_intr_map(pa, &ih) != 0) { 1351.17Sthorpej aprint_error(": unable to map interrupt\n"); 1361.5Scgd return; 1371.5Scgd } 1381.11Sthorpej intrstr = pci_intr_string(pa->pa_pc, ih); 1391.11Sthorpej sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cy_intr, sc); 1401.5Scgd if (sc->sc_ih == NULL) { 1411.17Sthorpej aprint_error(": unable to establish interrupt"); 1421.5Scgd if (intrstr != NULL) 1431.17Sthorpej aprint_normal(" at %s", intrstr); 1441.17Sthorpej aprint_normal("\n"); 1451.5Scgd return; 1461.5Scgd } 1471.17Sthorpej aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 1481.5Scgd 1491.12Sthorpej cy_attach(sc); 1501.1Schristos 1511.11Sthorpej plx_ver = bus_space_read_1(sc->sc_memt, sc->sc_bsh, CY_PLX_VER) & 0x0f; 1521.9Stsubai 1531.1Schristos /* Enable PCI card interrupts */ 1541.9Stsubai switch (plx_ver) { 1551.9Stsubai case CY_PLX_9050: 1561.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA_9050, 1571.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1581.11Sthorpej CY_PCI_INTENA_9050) | 0x40); 1591.9Stsubai break; 1601.11Sthorpej 1611.9Stsubai case CY_PLX_9060: 1621.9Stsubai case CY_PLX_9080: 1631.9Stsubai default: 1641.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA, 1651.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1661.11Sthorpej CY_PCI_INTENA) | 0x900); 1671.9Stsubai } 1681.1Schristos} 1691.18Sthorpej 1701.18SthorpejCFATTACH_DECL(cy_pci, sizeof(struct cy_pci_softc), 1711.18Sthorpej cy_pci_match, cy_pci_attach, NULL, NULL); 172