xref: /openbsd-src/sys/arch/i386/pci/gscpm.c (revision 24ee467d1e5e812429867003c29e5339cd18bad7)
1*24ee467dScheloha /*	$OpenBSD: gscpm.c,v 1.14 2023/02/04 19:19:36 cheloha Exp $	*/
20fd6afa2Sgrange /*
30fd6afa2Sgrange  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
40fd6afa2Sgrange  *
50fd6afa2Sgrange  * Permission to use, copy, modify, and distribute this software for any
60fd6afa2Sgrange  * purpose with or without fee is hereby granted, provided that the above
70fd6afa2Sgrange  * copyright notice and this permission notice appear in all copies.
80fd6afa2Sgrange  *
90fd6afa2Sgrange  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
100fd6afa2Sgrange  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
110fd6afa2Sgrange  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
120fd6afa2Sgrange  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
130fd6afa2Sgrange  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
140fd6afa2Sgrange  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
150fd6afa2Sgrange  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160fd6afa2Sgrange  */
170fd6afa2Sgrange 
180fd6afa2Sgrange /*
190fd6afa2Sgrange  * National Semiconductor Geode SC1100 SMI/ACPI module.
200fd6afa2Sgrange  */
210fd6afa2Sgrange 
220fd6afa2Sgrange #include <sys/param.h>
230fd6afa2Sgrange #include <sys/systm.h>
240fd6afa2Sgrange #include <sys/device.h>
250fd6afa2Sgrange #include <sys/kernel.h>
260fd6afa2Sgrange #include <sys/timetc.h>
270fd6afa2Sgrange 
280fd6afa2Sgrange #include <machine/bus.h>
290fd6afa2Sgrange 
300fd6afa2Sgrange #include <dev/pci/pcireg.h>
310fd6afa2Sgrange #include <dev/pci/pcivar.h>
32b6edc779Sgrange #include <dev/pci/pcidevs.h>
330fd6afa2Sgrange 
340fd6afa2Sgrange #include <i386/pci/gscpmreg.h>
350fd6afa2Sgrange 
360fd6afa2Sgrange struct gscpm_softc {
370fd6afa2Sgrange 	struct device sc_dev;
380fd6afa2Sgrange 
390fd6afa2Sgrange 	pci_chipset_tag_t sc_pc;
400fd6afa2Sgrange 	pcitag_t sc_tag;
410fd6afa2Sgrange 	bus_space_tag_t sc_iot;
420fd6afa2Sgrange 	bus_space_handle_t sc_acpi_ioh;
430fd6afa2Sgrange };
440fd6afa2Sgrange 
450fd6afa2Sgrange int	gscpm_match(struct device *, void *, void *);
460fd6afa2Sgrange void	gscpm_attach(struct device *, struct device *, void *);
470fd6afa2Sgrange 
4896773847Sdim void	gscpm_setperf(int);
490fd6afa2Sgrange 
500fd6afa2Sgrange u_int	gscpm_get_timecount(struct timecounter *tc);
510fd6afa2Sgrange 
520fd6afa2Sgrange struct timecounter gscpm_timecounter = {
538611d3cdScheloha 	.tc_get_timecount = gscpm_get_timecount,
548611d3cdScheloha 	.tc_counter_mask = 0xffffff,
558611d3cdScheloha 	.tc_frequency = 3579545,
568611d3cdScheloha 	.tc_name = "GSCPM",
578611d3cdScheloha 	.tc_quality = 1000,
588611d3cdScheloha 	.tc_priv = NULL,
598611d3cdScheloha 	.tc_user = 0,
600fd6afa2Sgrange };
610fd6afa2Sgrange 
627769e6a4Smpi const struct cfattach gscpm_ca = {
630fd6afa2Sgrange 	sizeof (struct gscpm_softc),
640fd6afa2Sgrange 	gscpm_match,
650fd6afa2Sgrange 	gscpm_attach
660fd6afa2Sgrange };
670fd6afa2Sgrange 
680fd6afa2Sgrange struct cfdriver gscpm_cd = {
690fd6afa2Sgrange 	NULL, "gscpm", DV_DULL
700fd6afa2Sgrange };
710fd6afa2Sgrange 
720fd6afa2Sgrange #if 0
730fd6afa2Sgrange static void *gscpm_cookie;	/* XXX */
740fd6afa2Sgrange #endif
750fd6afa2Sgrange 
760fd6afa2Sgrange int
gscpm_match(struct device * parent,void * match,void * aux)770fd6afa2Sgrange gscpm_match(struct device *parent, void *match, void *aux)
780fd6afa2Sgrange {
790fd6afa2Sgrange 	struct pci_attach_args *pa = aux;
800fd6afa2Sgrange 
810fd6afa2Sgrange 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS &&
820fd6afa2Sgrange 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_SMI)
830fd6afa2Sgrange 		return (1);
840fd6afa2Sgrange 
850fd6afa2Sgrange 	return (0);
860fd6afa2Sgrange }
870fd6afa2Sgrange 
880fd6afa2Sgrange void
gscpm_attach(struct device * parent,struct device * self,void * aux)890fd6afa2Sgrange gscpm_attach(struct device *parent, struct device *self, void *aux)
900fd6afa2Sgrange {
910fd6afa2Sgrange 	struct gscpm_softc *sc = (struct gscpm_softc *)self;
920fd6afa2Sgrange 	struct pci_attach_args *pa = aux;
930fd6afa2Sgrange 	pcireg_t csr, acpibase;
940fd6afa2Sgrange 
950fd6afa2Sgrange 	sc->sc_pc = pa->pa_pc;
960fd6afa2Sgrange 	sc->sc_tag = pa->pa_tag;
970fd6afa2Sgrange 	sc->sc_iot = pa->pa_iot;
980fd6afa2Sgrange 
990fd6afa2Sgrange 	/* Enable I/O space */
1000fd6afa2Sgrange 	csr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
1010fd6afa2Sgrange 	pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG,
1020fd6afa2Sgrange 	    csr | PCI_COMMAND_IO_ENABLE);
1030fd6afa2Sgrange 
1040fd6afa2Sgrange 	/* Map ACPI registers */
1050fd6afa2Sgrange 	acpibase = pci_conf_read(sc->sc_pc, sc->sc_tag, GSCPM_ACPIBASE);
1063d57c359Sderaadt 	if (PCI_MAPREG_IO_ADDR(acpibase) == 0 ||
1073d57c359Sderaadt 	    bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(acpibase),
1080fd6afa2Sgrange 	    GSCPM_ACPISIZE, 0, &sc->sc_acpi_ioh)) {
1090fd6afa2Sgrange 		printf(": failed to map ACPI registers\n");
1100fd6afa2Sgrange 		return;
1110fd6afa2Sgrange 	}
1120fd6afa2Sgrange 
1130fd6afa2Sgrange 	printf("\n");
1140fd6afa2Sgrange 
1150fd6afa2Sgrange 	/* Hook into the kern_tc */
1160fd6afa2Sgrange 	gscpm_timecounter.tc_priv = sc;
1170fd6afa2Sgrange 	tc_init(&gscpm_timecounter);
1180fd6afa2Sgrange 
1190fd6afa2Sgrange /* XXX: disabled due to unresolved yet hardware errata */
1200fd6afa2Sgrange #if 0
1210fd6afa2Sgrange 	/* Hook into the hw.setperf sysctl */
1220fd6afa2Sgrange 	gscpm_cookie = sc;
1230fd6afa2Sgrange 	cpu_setperf = gscpm_setperf;
1240fd6afa2Sgrange #endif
1250fd6afa2Sgrange 
1260fd6afa2Sgrange }
1270fd6afa2Sgrange 
1280fd6afa2Sgrange u_int
gscpm_get_timecount(struct timecounter * tc)1290fd6afa2Sgrange gscpm_get_timecount(struct timecounter *tc)
1300fd6afa2Sgrange {
1310fd6afa2Sgrange 	struct gscpm_softc *sc = tc->tc_priv;
1320fd6afa2Sgrange 
133b6a7f1efSmickey 	return (bus_space_read_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_PM_TMR));
1340fd6afa2Sgrange }
1350fd6afa2Sgrange 
1360fd6afa2Sgrange #if 0
13796773847Sdim void
1380fd6afa2Sgrange gscpm_setperf(int level)
1390fd6afa2Sgrange {
1400fd6afa2Sgrange 	struct gscpm_softc *sc = gscpm_cookie;
1410fd6afa2Sgrange 	int i;
1420fd6afa2Sgrange 	u_int32_t pctl;
1430fd6afa2Sgrange 
1440fd6afa2Sgrange 	pctl = bus_space_read_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_P_CNT);
1450fd6afa2Sgrange 
1460fd6afa2Sgrange 	if (level == 100) {
14736fd90dcSjsg 		/* 100 is a maximum performance, disable throttling */
1480fd6afa2Sgrange 		pctl &= ~GSCPM_P_CNT_THTEN;
1490fd6afa2Sgrange 	} else {
1500fd6afa2Sgrange 		for (i = 0; i < GSCPM_THT_LEVELS; i++)
1510fd6afa2Sgrange 			if (level >= gscpm_tht[i].level)
1520fd6afa2Sgrange 				break;
1530fd6afa2Sgrange 		pctl = (0xf0 | GSCPM_P_CNT_THTEN |
1540fd6afa2Sgrange 		    GSCPM_P_CNT_CLK(gscpm_tht[i].value));
1550fd6afa2Sgrange 	}
1560fd6afa2Sgrange 
1570fd6afa2Sgrange 	/* Update processor control register */
1580fd6afa2Sgrange 	bus_space_write_4(sc->sc_iot, sc->sc_acpi_ioh, GSCPM_P_CNT, pctl);
1590fd6afa2Sgrange }
1600fd6afa2Sgrange #endif
161