1*1633672dSaaron /* $OpenBSD: geodesc.c,v 1.4 2005/11/19 01:59:36 aaron Exp $ */ 24e5cdb34Smarkus 34e5cdb34Smarkus /* 44e5cdb34Smarkus * Copyright (c) 2003 Markus Friedl <markus@openbsd.org> 54e5cdb34Smarkus * 64e5cdb34Smarkus * Permission to use, copy, modify, and distribute this software for any 74e5cdb34Smarkus * purpose with or without fee is hereby granted, provided that the above 84e5cdb34Smarkus * copyright notice and this permission notice appear in all copies. 94e5cdb34Smarkus * 104e5cdb34Smarkus * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 114e5cdb34Smarkus * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 124e5cdb34Smarkus * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 134e5cdb34Smarkus * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 144e5cdb34Smarkus * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 154e5cdb34Smarkus * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 164e5cdb34Smarkus * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 174e5cdb34Smarkus */ 184e5cdb34Smarkus 194e5cdb34Smarkus /* 204e5cdb34Smarkus * Geode SC1100 Information Appliance On a Chip 214e5cdb34Smarkus * http://www.national.com/ds.cgi/SC/SC1100.pdf 224e5cdb34Smarkus */ 234e5cdb34Smarkus 244e5cdb34Smarkus #include <sys/cdefs.h> 254e5cdb34Smarkus #include <sys/param.h> 264e5cdb34Smarkus #include <sys/systm.h> 274e5cdb34Smarkus #include <sys/device.h> 284e5cdb34Smarkus 294e5cdb34Smarkus #include <machine/bus.h> 304e5cdb34Smarkus 314e5cdb34Smarkus #include <dev/pci/pcivar.h> 324e5cdb34Smarkus #include <dev/pci/pcidevs.h> 334e5cdb34Smarkus 344e5cdb34Smarkus #include <arch/i386/pci/geodescreg.h> 354e5cdb34Smarkus 364e5cdb34Smarkus struct geodesc_softc { 374e5cdb34Smarkus struct device sc_dev; 384e5cdb34Smarkus bus_space_tag_t sc_iot; 394e5cdb34Smarkus bus_space_handle_t sc_ioh; 404e5cdb34Smarkus }; 414e5cdb34Smarkus 424e5cdb34Smarkus int geodesc_match(struct device *, void *, void *); 434e5cdb34Smarkus void geodesc_attach(struct device *, struct device *, void *); 444e5cdb34Smarkus int geodesc_wdogctl_cb(void *, int); 454e5cdb34Smarkus 464e5cdb34Smarkus struct cfattach geodesc_ca = { 474e5cdb34Smarkus sizeof(struct geodesc_softc), geodesc_match, geodesc_attach 484e5cdb34Smarkus }; 494e5cdb34Smarkus 504e5cdb34Smarkus struct cfdriver geodesc_cd = { 514e5cdb34Smarkus NULL, "geodesc", DV_DULL 524e5cdb34Smarkus }; 534e5cdb34Smarkus 544e5cdb34Smarkus int 554e5cdb34Smarkus geodesc_match(struct device *parent, void *match, void *aux) 564e5cdb34Smarkus { 574e5cdb34Smarkus struct pci_attach_args *pa = aux; 584e5cdb34Smarkus 594e5cdb34Smarkus if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS && 6004ed797aSkevlo (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_XBUS || 6104ed797aSkevlo PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SCx200_XBUS)) 624e5cdb34Smarkus return (1); 634e5cdb34Smarkus return (0); 644e5cdb34Smarkus } 654e5cdb34Smarkus 664e5cdb34Smarkus #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF" 674e5cdb34Smarkus 684e5cdb34Smarkus void 694e5cdb34Smarkus geodesc_attach(struct device *parent, struct device *self, void *aux) 704e5cdb34Smarkus { 714e5cdb34Smarkus struct geodesc_softc *sc = (void *) self; 724e5cdb34Smarkus struct pci_attach_args *pa = aux; 734e5cdb34Smarkus uint16_t cnfg, cba; 744e5cdb34Smarkus uint8_t sts, rev, iid; 754e5cdb34Smarkus pcireg_t reg; 764e5cdb34Smarkus 774e5cdb34Smarkus reg = pci_conf_read(pa->pa_pc, pa->pa_tag, SC1100_F5_SCRATCHPAD); 784e5cdb34Smarkus sc->sc_iot = pa->pa_iot; 794e5cdb34Smarkus if (bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) { 8021db651eSmickey printf(": unable to map registers at 0x%x\n", reg); 814e5cdb34Smarkus return; 824e5cdb34Smarkus } 834e5cdb34Smarkus cba = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_CBA); 844e5cdb34Smarkus if (cba != reg) { 8521db651eSmickey printf(": cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg); 864e5cdb34Smarkus bus_space_unmap(sc->sc_iot, sc->sc_ioh, 64); 874e5cdb34Smarkus return; 884e5cdb34Smarkus } 894e5cdb34Smarkus sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS); 904e5cdb34Smarkus cnfg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG); 914e5cdb34Smarkus iid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_IID); 924e5cdb34Smarkus rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_REV); 934e5cdb34Smarkus 9421db651eSmickey printf(": iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS); 954e5cdb34Smarkus 964e5cdb34Smarkus /* setup and register watchdog */ 974e5cdb34Smarkus bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, 0); 984e5cdb34Smarkus sts |= WDOVF_CLEAR; 994e5cdb34Smarkus bus_space_write_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS, sts); 100*1633672dSaaron cnfg &= ~WDCNFG_MASK; 1014e5cdb34Smarkus cnfg |= WDTYPE1_RESET|WDPRES_DIV_512; 1024e5cdb34Smarkus bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG, cnfg); 1034e5cdb34Smarkus 1044e5cdb34Smarkus wdog_register(sc, geodesc_wdogctl_cb); 1054e5cdb34Smarkus } 1064e5cdb34Smarkus 1074e5cdb34Smarkus int 1084e5cdb34Smarkus geodesc_wdogctl_cb(void *self, int period) 1094e5cdb34Smarkus { 1104e5cdb34Smarkus struct geodesc_softc *sc = self; 1114e5cdb34Smarkus 1124e5cdb34Smarkus if (period > 0x03ff) 1134e5cdb34Smarkus period = 0x03ff; 1144e5cdb34Smarkus bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, period * 64); 1154e5cdb34Smarkus return (period); 1164e5cdb34Smarkus } 117