cy_pci.c revision 1.17
11.17Sthorpej/* $NetBSD: cy_pci.c,v 1.17 2003/01/31 00:07: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.17Sthorpej__KERNEL_RCSID(0, "$NetBSD: cy_pci.c,v 1.17 2003/01/31 00:07: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.11Sthorpejint cy_pci_match(struct device *, struct cfdata *, void *); 381.11Sthorpejvoid cy_pci_attach(struct device *, struct device *, void *); 391.1Schristos 401.15SthorpejCFATTACH_DECL(cy_pci, sizeof(struct cy_pci_softc), 411.16Sthorpej cy_pci_match, cy_pci_attach, NULL, NULL); 421.1Schristos 431.11Sthorpejstatic const struct cy_pci_product { 441.11Sthorpej pci_product_id_t cp_product; /* product ID */ 451.11Sthorpej pcireg_t cp_memtype; /* memory type */ 461.11Sthorpej} cy_pci_products[] = { 471.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_1, 481.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 491.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_1, 501.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 511.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_1, 521.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M }, 531.11Sthorpej 541.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOMY_2, 551.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 561.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM4Y_2, 571.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 581.11Sthorpej { PCI_PRODUCT_CYCLADES_CYCLOM8Y_2, 591.11Sthorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT }, 601.1Schristos 611.11Sthorpej { 0, 621.11Sthorpej 0 }, 631.11Sthorpej}; 641.11Sthorpejstatic const int cy_pci_nproducts = 651.11Sthorpej sizeof(cy_pci_products) / sizeof(cy_pci_products[0]); 661.5Scgd 671.11Sthorpejstatic const struct cy_pci_product * 681.11Sthorpejcy_pci_lookup(const struct pci_attach_args *pa) 691.11Sthorpej{ 701.11Sthorpej const struct cy_pci_product *cp; 711.11Sthorpej int i; 721.5Scgd 731.11Sthorpej if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CYCLADES) 741.11Sthorpej return (NULL); 751.1Schristos 761.11Sthorpej for (i = 0; i < cy_pci_nproducts; i++) { 771.11Sthorpej cp = &cy_pci_products[i]; 781.11Sthorpej if (PCI_PRODUCT(pa->pa_id) == cp->cp_product) 791.11Sthorpej return (cp); 801.11Sthorpej } 811.11Sthorpej return (NULL); 821.1Schristos} 831.1Schristos 841.11Sthorpejint 851.11Sthorpejcy_pci_match(struct device *parent, struct cfdata *match, void *aux) 861.1Schristos{ 871.11Sthorpej struct pci_attach_args *pa = aux; 881.1Schristos 891.11Sthorpej return (cy_pci_lookup(pa) != NULL); 901.1Schristos} 911.1Schristos 921.11Sthorpejvoid 931.11Sthorpejcy_pci_attach(struct device *parent, struct device *self, void *aux) 941.1Schristos{ 951.11Sthorpej struct cy_pci_softc *psc = (void *) self; 961.11Sthorpej struct cy_softc *sc = (void *) &psc->sc_cy; 971.11Sthorpej struct pci_attach_args *pa = aux; 981.11Sthorpej pci_intr_handle_t ih; 991.11Sthorpej const struct cy_pci_product *cp; 1001.5Scgd const char *intrstr; 1011.9Stsubai int plx_ver; 1021.1Schristos 1031.17Sthorpej aprint_naive(": Multi-port serial controller\n"); 1041.17Sthorpej 1051.1Schristos sc->sc_bustype = CY_BUSTYPE_PCI; 1061.1Schristos 1071.11Sthorpej cp = cy_pci_lookup(pa); 1081.11Sthorpej if (cp == NULL) 1091.11Sthorpej panic("cy_pci_attach: impossible"); 1101.11Sthorpej 1111.17Sthorpej aprint_normal(": Cyclades-Y multiport serial\n"); 1121.11Sthorpej 1131.11Sthorpej if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_IO, 0, 1141.11Sthorpej &psc->sc_iot, &psc->sc_ioh, NULL, NULL) != 0) { 1151.17Sthorpej aprint_error("%s: unable to map PLX registers\n", 1161.11Sthorpej sc->sc_dev.dv_xname); 1171.5Scgd return; 1181.5Scgd } 1191.1Schristos 1201.11Sthorpej if (pci_mapreg_map(pa, 0x18, cp->cp_memtype, 0, 1211.11Sthorpej &sc->sc_memt, &sc->sc_bsh, NULL, NULL) != 0) { 1221.17Sthorpej aprint_error("%s: unable to map device registers\n", 1231.11Sthorpej sc->sc_dev.dv_xname); 1241.11Sthorpej return; 1251.11Sthorpej } 1261.1Schristos 1271.5Scgd if (cy_find(sc) == 0) { 1281.17Sthorpej aprint_error("%s: unable to find CD1400s\n", 1291.17Sthorpej sc->sc_dev.dv_xname); 1301.5Scgd return; 1311.5Scgd } 1321.5Scgd 1331.11Sthorpej /* 1341.11Sthorpej * XXX Like the Cyclades-Z, we should really check the EEPROM to 1351.11Sthorpej * determine the "poll or interrupt" setting. For now, we always 1361.11Sthorpej * map the interrupt and enable it in the PLX. 1371.11Sthorpej */ 1381.11Sthorpej 1391.11Sthorpej /* Map and establish the interrupt. */ 1401.11Sthorpej if (pci_intr_map(pa, &ih) != 0) { 1411.17Sthorpej aprint_error(": unable to map interrupt\n"); 1421.5Scgd return; 1431.5Scgd } 1441.11Sthorpej intrstr = pci_intr_string(pa->pa_pc, ih); 1451.11Sthorpej sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cy_intr, sc); 1461.5Scgd if (sc->sc_ih == NULL) { 1471.17Sthorpej aprint_error(": unable to establish interrupt"); 1481.5Scgd if (intrstr != NULL) 1491.17Sthorpej aprint_normal(" at %s", intrstr); 1501.17Sthorpej aprint_normal("\n"); 1511.5Scgd return; 1521.5Scgd } 1531.17Sthorpej aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 1541.5Scgd 1551.12Sthorpej cy_attach(sc); 1561.1Schristos 1571.11Sthorpej plx_ver = bus_space_read_1(sc->sc_memt, sc->sc_bsh, CY_PLX_VER) & 0x0f; 1581.9Stsubai 1591.1Schristos /* Enable PCI card interrupts */ 1601.9Stsubai switch (plx_ver) { 1611.9Stsubai case CY_PLX_9050: 1621.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA_9050, 1631.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1641.11Sthorpej CY_PCI_INTENA_9050) | 0x40); 1651.9Stsubai break; 1661.11Sthorpej 1671.9Stsubai case CY_PLX_9060: 1681.9Stsubai case CY_PLX_9080: 1691.9Stsubai default: 1701.11Sthorpej bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA, 1711.11Sthorpej bus_space_read_2(psc->sc_iot, psc->sc_ioh, 1721.11Sthorpej CY_PCI_INTENA) | 0x900); 1731.9Stsubai } 1741.1Schristos} 175