1 /* $OpenBSD: gscpm.c,v 1.9 2012/08/16 18:42:04 tedu Exp $ */ 2 /* 3 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * National Semiconductor Geode SC1100 SMI/ACPI module. 20 */ 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/device.h> 25 #include <sys/kernel.h> 26 #include <sys/timetc.h> 27 28 #include <machine/bus.h> 29 30 #include <dev/pci/pcireg.h> 31 #include <dev/pci/pcivar.h> 32 #include <dev/pci/pcidevs.h> 33 34 #include <i386/pci/gscpmreg.h> 35 36 struct gscpm_softc { 37 struct device sc_dev; 38 39 pci_chipset_tag_t sc_pc; 40 pcitag_t sc_tag; 41 bus_space_tag_t sc_iot; 42 bus_space_handle_t sc_acpi_ioh; 43 }; 44 45 int gscpm_match(struct device *, void *, void *); 46 void gscpm_attach(struct device *, struct device *, void *); 47 48 void gscpm_setperf(int); 49 50 u_int gscpm_get_timecount(struct timecounter *tc); 51 52 struct timecounter gscpm_timecounter = { 53 gscpm_get_timecount, /* get_timecount */ 54 0, /* no poll_pps */ 55 0xffffff, /* counter_mask */ 56 3579545, /* frequency */ 57 "GSCPM", /* name */ 58 1000 /* quality */ 59 }; 60 61 struct cfattach gscpm_ca = { 62 sizeof (struct gscpm_softc), 63 gscpm_match, 64 gscpm_attach 65 }; 66 67 struct cfdriver gscpm_cd = { 68 NULL, "gscpm", DV_DULL 69 }; 70 71 #if 0 72 static void *gscpm_cookie; /* XXX */ 73 #endif 74 75 int 76 gscpm_match(struct device *parent, void *match, void *aux) 77 { 78 struct pci_attach_args *pa = aux; 79 80 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS && 81 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_SMI) 82 return (1); 83 84 return (0); 85 } 86 87 void 88 gscpm_attach(struct device *parent, struct device *self, void *aux) 89 { 90 struct gscpm_softc *sc = (struct gscpm_softc *)self; 91 struct pci_attach_args *pa = aux; 92 pcireg_t csr, acpibase; 93 94 sc->sc_pc = pa->pa_pc; 95 sc->sc_tag = pa->pa_tag; 96 sc->sc_iot = pa->pa_iot; 97 98 /* Enable I/O space */ 99 csr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG); 100 pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, 101 csr | PCI_COMMAND_IO_ENABLE); 102 103 /* Map ACPI registers */ 104 acpibase = pci_conf_read(sc->sc_pc, sc->sc_tag, GSCPM_ACPIBASE); 105 if (PCI_MAPREG_IO_ADDR(acpibase) == 0 || 106 bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(acpibase), 107 GSCPM_ACPISIZE, 0, &sc->sc_acpi_ioh)) { 108 printf(": failed to map ACPI registers\n"); 109 return; 110 } 111 112 printf("\n"); 113 114 /* Hook into the kern_tc */ 115 gscpm_timecounter.tc_priv = sc; 116 tc_init(&gscpm_timecounter); 117 118 /* XXX: disabled due to unresolved yet hardware errata */ 119 #if 0 120 /* Hook into the hw.setperf sysctl */ 121 gscpm_cookie = sc; 122 cpu_setperf = gscpm_setperf; 123 #endif 124 125 } 126 127 u_int 128 gscpm_get_timecount(struct timecounter *tc) 129 { 130 struct gscpm_softc *sc = tc->tc_priv; 131 132 return (bus_space_read_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_PM_TMR)); 133 } 134 135 #if 0 136 void 137 gscpm_setperf(int level) 138 { 139 struct gscpm_softc *sc = gscpm_cookie; 140 int i; 141 u_int32_t pctl; 142 143 pctl = bus_space_read_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_P_CNT); 144 145 if (level == 100) { 146 /* 100 is a maximum perfomance, disable throttling */ 147 pctl &= ~GSCPM_P_CNT_THTEN; 148 } else { 149 for (i = 0; i < GSCPM_THT_LEVELS; i++) 150 if (level >= gscpm_tht[i].level) 151 break; 152 pctl = (0xf0 | GSCPM_P_CNT_THTEN | 153 GSCPM_P_CNT_CLK(gscpm_tht[i].value)); 154 } 155 156 /* Update processor control register */ 157 bus_space_write_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_P_CNT, pctl); 158 } 159 #endif 160