cy_pci.c revision 1.12
11.12Sthorpej/* $NetBSD: cy_pci.c,v 1.12 2001/01/20 02:26:39 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.11Sthorpej 121.1Schristos#include <sys/param.h> 131.1Schristos#include <sys/systm.h> 141.1Schristos#include <sys/device.h> 151.1Schristos 161.1Schristos#include <machine/bus.h> 171.1Schristos#include <machine/intr.h> 181.1Schristos 191.1Schristos#include <dev/pci/pcivar.h> 201.1Schristos#include <dev/pci/pcireg.h> 211.1Schristos#include <dev/pci/pcidevs.h> 221.1Schristos 231.1Schristos#include <dev/ic/cd1400reg.h> 241.1Schristos#include <dev/ic/cyreg.h> 251.1Schristos#include <dev/ic/cyvar.h> 261.1Schristos 271.11Sthorpejstruct cy_pci_softc { 281.11Sthorpej struct cy_softc sc_cy; /* real cy softc */ 291.11Sthorpej 301.11Sthorpej bus_space_tag_t sc_iot; /* PLX runtime i/o tag */ 311.11Sthorpej bus_space_handle_t sc_ioh; /* PLX runtime i/o handle */ 321.11Sthorpej}; 331.11Sthorpej 341.11Sthorpejint cy_pci_match(struct device *, struct cfdata *, void *); 351.11Sthorpejvoid cy_pci_attach(struct device *, struct device *, void *); 361.1Schristos 371.1Schristosstruct cfattach cy_pci_ca = { 381.11Sthorpej sizeof(struct cy_pci_softc), cy_pci_match, cy_pci_attach 391.1Schristos}; 401.1Schristos 411.11Sthorpejstatic const struct cy_pci_product { 421.11Sthorpej pci_product_id_t cp_product; /* product ID */ 431.11Sthorpej pcireg_t cp_memtype; /* memory type */ 441.11Sthorpej} cy_pci_products[] = { 451.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_1, 461.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 471.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_1, 481.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 491.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_1, 501.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 511.11Sthorpej 521.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_2, 531.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 541.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_2, 551.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 561.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_2, 571.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 581.1Schristos 591.11Sthorpej { 0, 601.11Sthorpej 0 }, 611.11Sthorpej}; 621.11Sthorpejstatic const int cy_pci_nproducts = 631.11Sthorpej sizeof(cy_pci_products) / sizeof(cy_pci_products[0]); 641.5Scgd 651.11Sthorpejstatic const struct cy_pci_product * 661.11Sthorpejcy_pci_lookup(const struct pci_attach_args *pa) 671.11Sthorpej{ 681.11Sthorpej const struct cy_pci_product *cp; 691.11Sthorpej int i; 701.5Scgd 711.11Sthorpej if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CYCLADES) 721.11Sthorpej return (NULL); 731.1Schristos 741.11Sthorpej for (i = 0; i < cy_pci_nproducts; i++) { 751.11Sthorpej cp = &cy_pci_products[i]; 761.11Sthorpej if (PCI_PRODUCT(pa->pa_id) == cp->cp_product) 771.11Sthorpej return (cp); 781.11Sthorpej } 791.11Sthorpej return (NULL); 801.1Schristos} 811.1Schristos 821.11Sthorpejint 831.11Sthorpejcy_pci_match(struct device *parent, struct cfdata *match, void *aux) 841.1Schristos{ 851.11Sthorpej struct pci_attach_args *pa = aux; 861.1Schristos 871.11Sthorpej return (cy_pci_lookup(pa) != NULL); 881.1Schristos} 891.1Schristos 901.11Sthorpejvoid 911.11Sthorpejcy_pci_attach(struct device *parent, struct device *self, void *aux) 921.1Schristos{ 931.11Sthorpej struct cy_pci_softc *psc = (void *) self; 941.11Sthorpej struct cy_softc *sc = (void *) &psc->sc_cy; 951.11Sthorpej struct pci_attach_args *pa = aux; 961.11Sthorpej pci_intr_handle_t ih; 971.11Sthorpej const struct cy_pci_product *cp; 981.5Scgd const char *intrstr; 991.9Stsubai int plx_ver; 1001.1Schristos 1011.1Schristos sc->sc_bustype = CY_BUSTYPE_PCI; 1021.1Schristos 1031.11Sthorpej cp = cy_pci_lookup(pa); 1041.11Sthorpej if (cp == NULL) 1051.11Sthorpej panic("cy_pci_attach: impossible"); 1061.11Sthorpej 1071.11Sthorpej printf(": Cyclades-Y multiport serial\n"); 1081.11Sthorpej 1091.11Sthorpej if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_IO, 0, 1101.11Sthorpej &psc->sc_iot, &psc->sc_ioh, NULL, NULL) != 0) { 1111.11Sthorpej printf("%s: unable to map PLX registers\n", 1121.11Sthorpej sc->sc_dev.dv_xname); 1131.5Scgd return; 1141.5Scgd } 1151.1Schristos 1161.11Sthorpej if (pci_mapreg_map(pa, 0x18, cp->cp_memtype, 0, 1171.11Sthorpej &sc->sc_memt, &sc->sc_bsh, NULL, NULL) != 0) { 1181.11Sthorpej printf("%s: unable to map device registers\n", 1191.11Sthorpej sc->sc_dev.dv_xname); 1201.11Sthorpej return; 1211.11Sthorpej } 1221.1Schristos 1231.5Scgd if (cy_find(sc) == 0) { 1241.11Sthorpej printf("%s: unable to find CD1400s\n", sc->sc_dev.dv_xname); 1251.5Scgd return; 1261.5Scgd } 1271.5Scgd 1281.11Sthorpej /* 1291.11Sthorpej * XXX Like the Cyclades-Z, we should really check the EEPROM to 1301.11Sthorpej * determine the "poll or interrupt" setting. For now, we always 1311.11Sthorpej * map the interrupt and enable it in the PLX. 1321.11Sthorpej */ 1331.11Sthorpej 1341.11Sthorpej /* Map and establish the interrupt. */ 1351.11Sthorpej if (pci_intr_map(pa, &ih) != 0) { 1361.11Sthorpej printf(": unable to map interrupt\n"); 1371.5Scgd return; 1381.5Scgd } 1391.11Sthorpej intrstr = pci_intr_string(pa->pa_pc, ih); 1401.11Sthorpej sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cy_intr, sc); 1411.5Scgd if (sc->sc_ih == NULL) { 1421.11Sthorpej printf(": unable to establish interrupt"); 1431.5Scgd if (intrstr != NULL) 1441.5Scgd printf(" at %s", intrstr); 1451.5Scgd printf("\n"); 1461.5Scgd return; 1471.5Scgd } 1481.11Sthorpej printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 1491.5Scgd 1501.12Sthorpej cy_attach(sc); 1511.1Schristos 1521.11Sthorpej plx_ver = bus_space_read_1(sc->sc_memt, sc->sc_bsh, CY_PLX_VER) & 0x0f; 1531.9Stsubai 1541.1Schristos /* Enable PCI card interrupts */ 1551.9Stsubai switch (plx_ver) { 1561.9Stsubai case CY_PLX_9050: 1571.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA_9050, 1581.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1591.11Sthorpej CY_PCI_INTENA_9050) | 0x40); 1601.9Stsubai break; 1611.11Sthorpej 1621.9Stsubai case CY_PLX_9060: 1631.9Stsubai case CY_PLX_9080: 1641.9Stsubai default: 1651.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA, 1661.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1671.11Sthorpej CY_PCI_INTENA) | 0x900); 1681.9Stsubai } 1691.1Schristos} 170