Sat Apr 4 23:13:18 2009 UTC ()
Restore SpeedStep settings on shutdown. Some BIOSes don't like it, if
SpeedStep is enabled and powerdown fails otherwise. Fixes PR kern/40487.


(joerg)
diff -r1.15 -r1.16 src/sys/arch/x86/pci/ichlpcib.c

cvs diff -r1.15 -r1.16 src/sys/arch/x86/pci/ichlpcib.c (expand / switch to unified diff)

--- src/sys/arch/x86/pci/ichlpcib.c 2009/03/03 06:05:28 1.15
+++ src/sys/arch/x86/pci/ichlpcib.c 2009/04/04 23:13:18 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ichlpcib.c,v 1.15 2009/03/03 06:05:28 mrg Exp $ */ 1/* $NetBSD: ichlpcib.c,v 1.16 2009/04/04 23:13:18 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Minoura Makoto and Matthew R. Green. 8 * by Minoura Makoto and Matthew R. Green.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -29,27 +29,27 @@ @@ -29,27 +29,27 @@
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Intel I/O Controller Hub (ICHn) LPC Interface Bridge driver 33 * Intel I/O Controller Hub (ICHn) LPC Interface Bridge driver
34 * 34 *
35 * LPC Interface Bridge is basically a pcib (PCI-ISA Bridge), but has 35 * LPC Interface Bridge is basically a pcib (PCI-ISA Bridge), but has
36 * some power management and monitoring functions. 36 * some power management and monitoring functions.
37 * Currently we support the watchdog timer, SpeedStep (on some systems) 37 * Currently we support the watchdog timer, SpeedStep (on some systems)
38 * and the power management timer. 38 * and the power management timer.
39 */ 39 */
40 40
41#include <sys/cdefs.h> 41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.15 2009/03/03 06:05:28 mrg Exp $"); 42__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.16 2009/04/04 23:13:18 joerg Exp $");
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/device.h> 47#include <sys/device.h>
48#include <sys/sysctl.h> 48#include <sys/sysctl.h>
49#include <sys/timetc.h> 49#include <sys/timetc.h>
50#include <machine/bus.h> 50#include <machine/bus.h>
51 51
52#include <dev/pci/pcivar.h> 52#include <dev/pci/pcivar.h>
53#include <dev/pci/pcireg.h> 53#include <dev/pci/pcireg.h>
54#include <dev/pci/pcidevs.h> 54#include <dev/pci/pcidevs.h>
55 55
@@ -76,36 +76,40 @@ struct lpcib_softc { @@ -76,36 +76,40 @@ struct lpcib_softc {
76 bus_space_handle_t sc_rcbah; 76 bus_space_handle_t sc_rcbah;
77 pcireg_t sc_rcba_reg; 77 pcireg_t sc_rcba_reg;
78 78
79 /* Watchdog variables. */ 79 /* Watchdog variables. */
80 struct sysmon_wdog sc_smw; 80 struct sysmon_wdog sc_smw;
81 bus_space_tag_t sc_iot; 81 bus_space_tag_t sc_iot;
82 bus_space_handle_t sc_ioh; 82 bus_space_handle_t sc_ioh;
83 83
84#if NHPET > 0 84#if NHPET > 0
85 /* HPET variables. */ 85 /* HPET variables. */
86 uint32_t sc_hpet_reg; 86 uint32_t sc_hpet_reg;
87#endif 87#endif
88 88
 89 /* Speedstep */
 90 pcireg_t sc_pmcon_orig;
 91
89 /* Power management */ 92 /* Power management */
90 pcireg_t sc_pirq[2]; 93 pcireg_t sc_pirq[2];
91 pcireg_t sc_pmcon; 94 pcireg_t sc_pmcon;
92 pcireg_t sc_fwhsel2; 95 pcireg_t sc_fwhsel2;
93}; 96};
94 97
95static int lpcibmatch(device_t, cfdata_t, void *); 98static int lpcibmatch(device_t, cfdata_t, void *);
96static void lpcibattach(device_t, device_t, void *); 99static void lpcibattach(device_t, device_t, void *);
97static bool lpcib_suspend(device_t PMF_FN_PROTO); 100static bool lpcib_suspend(device_t PMF_FN_PROTO);
98static bool lpcib_resume(device_t PMF_FN_PROTO); 101static bool lpcib_resume(device_t PMF_FN_PROTO);
 102static bool lpcib_shutdown(device_t, int);
99 103
100static void pmtimer_configure(device_t); 104static void pmtimer_configure(device_t);
101 105
102static void tcotimer_configure(device_t); 106static void tcotimer_configure(device_t);
103static int tcotimer_setmode(struct sysmon_wdog *); 107static int tcotimer_setmode(struct sysmon_wdog *);
104static int tcotimer_tickle(struct sysmon_wdog *); 108static int tcotimer_tickle(struct sysmon_wdog *);
105static void tcotimer_stop(struct lpcib_softc *); 109static void tcotimer_stop(struct lpcib_softc *);
106static void tcotimer_start(struct lpcib_softc *); 110static void tcotimer_start(struct lpcib_softc *);
107static void tcotimer_status_reset(struct lpcib_softc *); 111static void tcotimer_status_reset(struct lpcib_softc *);
108static int tcotimer_disable_noreboot(device_t); 112static int tcotimer_disable_noreboot(device_t);
109 113
110static void speedstep_configure(device_t); 114static void speedstep_configure(device_t);
111static int speedstep_sysctl_helper(SYSCTLFN_ARGS); 115static int speedstep_sysctl_helper(SYSCTLFN_ARGS);
@@ -195,26 +199,29 @@ lpcibattach(device_t parent, device_t se @@ -195,26 +199,29 @@ lpcibattach(device_t parent, device_t se
195 pcibattach(parent, self, aux); 199 pcibattach(parent, self, aux);
196 200
197 /* 201 /*
198 * Part of our I/O registers are used as ACPI PM regs. 202 * Part of our I/O registers are used as ACPI PM regs.
199 * Since our ACPI subsystem accesses the I/O space directly so far, 203 * Since our ACPI subsystem accesses the I/O space directly so far,
200 * we do not have to bother bus_space I/O map confliction. 204 * we do not have to bother bus_space I/O map confliction.
201 */ 205 */
202 if (pci_mapreg_map(pa, LPCIB_PCI_PMBASE, PCI_MAPREG_TYPE_IO, 0, 206 if (pci_mapreg_map(pa, LPCIB_PCI_PMBASE, PCI_MAPREG_TYPE_IO, 0,
203 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { 207 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
204 aprint_error_dev(self, "can't map power management i/o space"); 208 aprint_error_dev(self, "can't map power management i/o space");
205 return; 209 return;
206 } 210 }
207 211
 212 sc->sc_pmcon_orig = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
 213 LPCIB_PCI_GEN_PMCON_1);
 214
208 /* For ICH6 and later, always enable RCBA */ 215 /* For ICH6 and later, always enable RCBA */
209 if (sc->sc_has_rcba) { 216 if (sc->sc_has_rcba) {
210 pcireg_t rcba; 217 pcireg_t rcba;
211 218
212 sc->sc_rcbat = sc->sc_pa.pa_memt; 219 sc->sc_rcbat = sc->sc_pa.pa_memt;
213 220
214 rcba = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 221 rcba = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
215 LPCIB_RCBA); 222 LPCIB_RCBA);
216 if ((rcba & LPCIB_RCBA_EN) == 0) { 223 if ((rcba & LPCIB_RCBA_EN) == 0) {
217 aprint_error_dev(self, "RCBA is not enabled"); 224 aprint_error_dev(self, "RCBA is not enabled");
218 return; 225 return;
219 } 226 }
220 rcba &= ~LPCIB_RCBA_EN; 227 rcba &= ~LPCIB_RCBA_EN;
@@ -231,31 +238,43 @@ lpcibattach(device_t parent, device_t se @@ -231,31 +238,43 @@ lpcibattach(device_t parent, device_t se
231 238
232 /* Set up the TCO (watchdog). */ 239 /* Set up the TCO (watchdog). */
233 tcotimer_configure(self); 240 tcotimer_configure(self);
234 241
235 /* Set up SpeedStep. */ 242 /* Set up SpeedStep. */
236 speedstep_configure(self); 243 speedstep_configure(self);
237 244
238#if NHPET > 0 245#if NHPET > 0
239 /* Set up HPET. */ 246 /* Set up HPET. */
240 lpcib_hpet_configure(self); 247 lpcib_hpet_configure(self);
241#endif 248#endif
242 249
243 /* Install power handler */ 250 /* Install power handler */
244 if (!pmf_device_register(self, lpcib_suspend, lpcib_resume)) 251 if (!pmf_device_register1(self, lpcib_suspend, lpcib_resume,
 252 lpcib_shutdown))
245 aprint_error_dev(self, "couldn't establish power handler\n"); 253 aprint_error_dev(self, "couldn't establish power handler\n");
246} 254}
247 255
248static bool 256static bool
 257lpcib_shutdown(device_t dv, int howto)
 258{
 259 struct lpcib_softc *sc = device_private(dv);
 260
 261 pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
 262 LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig);
 263
 264 return true;
 265}
 266
 267static bool
249lpcib_suspend(device_t dv PMF_FN_ARGS) 268lpcib_suspend(device_t dv PMF_FN_ARGS)
250{ 269{
251 struct lpcib_softc *sc = device_private(dv); 270 struct lpcib_softc *sc = device_private(dv);
252 pci_chipset_tag_t pc = sc->sc_pcib.sc_pc; 271 pci_chipset_tag_t pc = sc->sc_pcib.sc_pc;
253 pcitag_t tag = sc->sc_pcib.sc_tag; 272 pcitag_t tag = sc->sc_pcib.sc_tag;
254 273
255 /* capture PIRQ routing control registers */ 274 /* capture PIRQ routing control registers */
256 sc->sc_pirq[0] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQA_ROUT); 275 sc->sc_pirq[0] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQA_ROUT);
257 sc->sc_pirq[1] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQE_ROUT); 276 sc->sc_pirq[1] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQE_ROUT);
258 277
259 sc->sc_pmcon = pci_conf_read(pc, tag, LPCIB_PCI_GEN_PMCON_1); 278 sc->sc_pmcon = pci_conf_read(pc, tag, LPCIB_PCI_GEN_PMCON_1);
260 sc->sc_fwhsel2 = pci_conf_read(pc, tag, LPCIB_PCI_GEN_STA); 279 sc->sc_fwhsel2 = pci_conf_read(pc, tag, LPCIB_PCI_GEN_STA);
261 280