1 1.62 hans /* $NetBSD: ichlpcib.c,v 1.62 2024/12/18 18:18:30 hans Exp $ */ 2 1.1 xtraeme 3 1.1 xtraeme /*- 4 1.1 xtraeme * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 1.1 xtraeme * All rights reserved. 6 1.1 xtraeme * 7 1.1 xtraeme * This code is derived from software contributed to The NetBSD Foundation 8 1.1 xtraeme * by Minoura Makoto and Matthew R. Green. 9 1.1 xtraeme * 10 1.1 xtraeme * Redistribution and use in source and binary forms, with or without 11 1.1 xtraeme * modification, are permitted provided that the following conditions 12 1.1 xtraeme * are met: 13 1.1 xtraeme * 1. Redistributions of source code must retain the above copyright 14 1.1 xtraeme * notice, this list of conditions and the following disclaimer. 15 1.1 xtraeme * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 xtraeme * notice, this list of conditions and the following disclaimer in the 17 1.1 xtraeme * documentation and/or other materials provided with the distribution. 18 1.1 xtraeme * 19 1.1 xtraeme * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 xtraeme * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 xtraeme * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 xtraeme * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 xtraeme * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 xtraeme * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 xtraeme * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 xtraeme * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 xtraeme * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 xtraeme * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 xtraeme * POSSIBILITY OF SUCH DAMAGE. 30 1.1 xtraeme */ 31 1.1 xtraeme 32 1.1 xtraeme /* 33 1.1 xtraeme * Intel I/O Controller Hub (ICHn) LPC Interface Bridge driver 34 1.1 xtraeme * 35 1.1 xtraeme * LPC Interface Bridge is basically a pcib (PCI-ISA Bridge), but has 36 1.1 xtraeme * some power management and monitoring functions. 37 1.49 pgoyette * Currently we support the watchdog timer, SpeedStep (on some systems), 38 1.49 pgoyette * the gpio interface, hpet timer, hardware random number generator, 39 1.1 xtraeme * and the power management timer. 40 1.1 xtraeme */ 41 1.1 xtraeme 42 1.1 xtraeme #include <sys/cdefs.h> 43 1.62 hans __KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.62 2024/12/18 18:18:30 hans Exp $"); 44 1.1 xtraeme 45 1.1 xtraeme #include <sys/types.h> 46 1.1 xtraeme #include <sys/param.h> 47 1.1 xtraeme #include <sys/systm.h> 48 1.1 xtraeme #include <sys/device.h> 49 1.1 xtraeme #include <sys/sysctl.h> 50 1.6 jmcneill #include <sys/timetc.h> 51 1.20 jakllsch #include <sys/gpio.h> 52 1.32 dyoung #include <sys/bus.h> 53 1.1 xtraeme 54 1.1 xtraeme #include <dev/pci/pcivar.h> 55 1.1 xtraeme #include <dev/pci/pcireg.h> 56 1.1 xtraeme #include <dev/pci/pcidevs.h> 57 1.1 xtraeme 58 1.20 jakllsch #include <dev/gpio/gpiovar.h> 59 1.1 xtraeme 60 1.6 jmcneill #include <dev/ic/acpipmtimer.h> 61 1.1 xtraeme #include <dev/ic/i82801lpcreg.h> 62 1.31 jruoho #include <dev/ic/i82801lpcvar.h> 63 1.6 jmcneill #include <dev/ic/hpetreg.h> 64 1.6 jmcneill #include <dev/ic/hpetvar.h> 65 1.6 jmcneill 66 1.49 pgoyette #include <arch/x86/pci/tco.h> 67 1.49 pgoyette 68 1.12 martin #include "pcibvar.h" 69 1.20 jakllsch #include "gpio.h" 70 1.25 jakllsch #include "fwhrng.h" 71 1.20 jakllsch 72 1.20 jakllsch #define LPCIB_GPIO_NPINS 64 73 1.1 xtraeme 74 1.1 xtraeme struct lpcib_softc { 75 1.12 martin /* we call pcibattach() which assumes this starts like this: */ 76 1.12 martin struct pcib_softc sc_pcib; 77 1.1 xtraeme 78 1.6 jmcneill struct pci_attach_args sc_pa; 79 1.6 jmcneill int sc_has_rcba; 80 1.6 jmcneill int sc_has_ich5_hpet; 81 1.6 jmcneill 82 1.6 jmcneill /* RCBA */ 83 1.6 jmcneill bus_space_tag_t sc_rcbat; 84 1.6 jmcneill bus_space_handle_t sc_rcbah; 85 1.6 jmcneill pcireg_t sc_rcba_reg; 86 1.6 jmcneill 87 1.49 pgoyette /* Power management variables. */ 88 1.58 riastrad bus_space_tag_t sc_pmt; 89 1.58 riastrad bus_space_handle_t sc_pmh; 90 1.19 dyoung bus_size_t sc_iosize; 91 1.6 jmcneill 92 1.59 riastrad /* TCO variables. */ 93 1.59 riastrad bus_space_tag_t sc_tcot; 94 1.59 riastrad bus_space_handle_t sc_tcoh; 95 1.59 riastrad bus_size_t sc_tcosz; 96 1.59 riastrad 97 1.6 jmcneill /* HPET variables. */ 98 1.6 jmcneill uint32_t sc_hpet_reg; 99 1.6 jmcneill 100 1.20 jakllsch #if NGPIO > 0 101 1.20 jakllsch device_t sc_gpiobus; 102 1.20 jakllsch kmutex_t sc_gpio_mtx; 103 1.20 jakllsch bus_space_tag_t sc_gpio_iot; 104 1.20 jakllsch bus_space_handle_t sc_gpio_ioh; 105 1.20 jakllsch bus_size_t sc_gpio_ios; 106 1.20 jakllsch struct gpio_chipset_tag sc_gpio_gc; 107 1.20 jakllsch gpio_pin_t sc_gpio_pins[LPCIB_GPIO_NPINS]; 108 1.20 jakllsch #endif 109 1.20 jakllsch 110 1.25 jakllsch #if NFWHRNG > 0 111 1.25 jakllsch device_t sc_fwhbus; 112 1.25 jakllsch #endif 113 1.25 jakllsch 114 1.16 joerg /* Speedstep */ 115 1.16 joerg pcireg_t sc_pmcon_orig; 116 1.16 joerg 117 1.1 xtraeme /* Power management */ 118 1.7 drochner pcireg_t sc_pirq[2]; 119 1.6 jmcneill pcireg_t sc_pmcon; 120 1.6 jmcneill pcireg_t sc_fwhsel2; 121 1.19 dyoung 122 1.19 dyoung /* Child devices */ 123 1.49 pgoyette device_t sc_tco; 124 1.19 dyoung device_t sc_hpetbus; 125 1.19 dyoung acpipmtimer_t sc_pmtimer; 126 1.19 dyoung pcireg_t sc_acpi_cntl; 127 1.19 dyoung 128 1.19 dyoung struct sysctllog *sc_log; 129 1.1 xtraeme }; 130 1.1 xtraeme 131 1.9 xtraeme static int lpcibmatch(device_t, cfdata_t, void *); 132 1.9 xtraeme static void lpcibattach(device_t, device_t, void *); 133 1.19 dyoung static int lpcibdetach(device_t, int); 134 1.19 dyoung static void lpcibchilddet(device_t, device_t); 135 1.19 dyoung static int lpcibrescan(device_t, const char *, const int *); 136 1.24 dyoung static bool lpcib_suspend(device_t, const pmf_qual_t *); 137 1.24 dyoung static bool lpcib_resume(device_t, const pmf_qual_t *); 138 1.16 joerg static bool lpcib_shutdown(device_t, int); 139 1.1 xtraeme 140 1.9 xtraeme static void pmtimer_configure(device_t); 141 1.61 riastrad static void pmtimer_unconfigure(device_t, int); 142 1.1 xtraeme 143 1.9 xtraeme static void tcotimer_configure(device_t); 144 1.1 xtraeme 145 1.9 xtraeme static void speedstep_configure(device_t); 146 1.19 dyoung static void speedstep_unconfigure(device_t); 147 1.1 xtraeme static int speedstep_sysctl_helper(SYSCTLFN_ARGS); 148 1.1 xtraeme 149 1.9 xtraeme static void lpcib_hpet_configure(device_t); 150 1.6 jmcneill 151 1.20 jakllsch #if NGPIO > 0 152 1.20 jakllsch static void lpcib_gpio_configure(device_t); 153 1.61 riastrad static void lpcib_gpio_unconfigure(device_t); 154 1.20 jakllsch static int lpcib_gpio_pin_read(void *, int); 155 1.20 jakllsch static void lpcib_gpio_pin_write(void *, int, int); 156 1.20 jakllsch static void lpcib_gpio_pin_ctl(void *, int, int); 157 1.20 jakllsch #endif 158 1.20 jakllsch 159 1.25 jakllsch #if NFWHRNG > 0 160 1.25 jakllsch static void lpcib_fwh_configure(device_t); 161 1.25 jakllsch #endif 162 1.25 jakllsch 163 1.1 xtraeme struct lpcib_softc *speedstep_cookie; /* XXX */ 164 1.1 xtraeme 165 1.19 dyoung CFATTACH_DECL2_NEW(ichlpcib, sizeof(struct lpcib_softc), 166 1.19 dyoung lpcibmatch, lpcibattach, lpcibdetach, NULL, lpcibrescan, lpcibchilddet); 167 1.1 xtraeme 168 1.52 maxv static const struct lpcib_device { 169 1.6 jmcneill pcireg_t vendor, product; 170 1.6 jmcneill int has_rcba; 171 1.6 jmcneill int has_ich5_hpet; 172 1.6 jmcneill } lpcib_devices[] = { 173 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_LPC, 1, 0 }, 174 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3420_LPC, 1, 0 }, 175 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3450_LPC, 1, 0 }, 176 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_LPC, 1, 0 }, 177 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_63XXESB_LPC, 1, 0 }, 178 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_LPC, 0, 0 }, 179 1.27 jakllsch { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_LPC, 0, 0 }, 180 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC, 0, 0 }, 181 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BAM_LPC, 0, 0 }, 182 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_LPC, 0, 0 }, 183 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CAM_LPC, 0, 0 }, 184 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_LPC, 0, 0 }, 185 1.30 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DBM_LPC, 0, 0 }, 186 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801E_LPC, 0, 1 }, 187 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_LPC, 0, 1 }, 188 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_LPC, 1, 0 }, 189 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FBM_LPC, 1, 0 }, 190 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801G_LPC, 1, 0 }, 191 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GBM_LPC, 1, 0 }, 192 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GH_LPC, 1, 0 }, 193 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GHM_LPC, 1, 0 }, 194 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LPC, 1, 0 }, 195 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HEM_LPC, 1, 0 }, 196 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HH_LPC, 1, 0 }, 197 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HO_LPC, 1, 0 }, 198 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HBM_LPC, 1, 0 }, 199 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IB_LPC, 1, 0 }, 200 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IH_LPC, 1, 0 }, 201 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IM_LPC, 1, 0 }, 202 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IO_LPC, 1, 0 }, 203 1.6 jmcneill { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IR_LPC, 1, 0 }, 204 1.17 njoly { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IEM_LPC, 1, 0 }, 205 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JD_LPC, 1, 0 }, 206 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JDO_LPC, 1, 0 }, 207 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JIB_LPC, 1, 0 }, 208 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JIR_LPC, 1, 0 }, 209 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C202_LPC, 1, 0 }, 210 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C204_LPC, 1, 0 }, 211 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C206_LPC, 1, 0 }, 212 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C216_LPC, 1, 0 }, 213 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_NM10_LPC, 1, 0 }, 214 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H55_LPC, 1, 0 }, 215 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H57_LPC, 1, 0 }, 216 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM55_LPC, 1, 0 }, 217 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM57_LPC, 1, 0 }, 218 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_P55_LPC, 1, 0 }, 219 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PM55_LPC, 1, 0 }, 220 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q57_LPC, 1, 0 }, 221 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM57_LPC, 1, 0 }, 222 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QS57_LPC, 1, 0 }, 223 1.36 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B65_LPC, 1, 0 }, 224 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H61_LPC, 1, 0 }, 225 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H67_LPC, 1, 0 }, 226 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM65_LPC, 1, 0 }, 227 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM67_LPC, 1, 0 }, 228 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_P67_LPC, 1, 0 }, 229 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q65_LPC, 1, 0 }, 230 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q67_LPC, 1, 0 }, 231 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM67_LPC, 1, 0 }, 232 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QS67_LPC, 1, 0 }, 233 1.35 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_UM67_LPC, 1, 0 }, 234 1.43 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z68_LPC, 1, 0 }, 235 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B75_LPC, 1, 0 }, 236 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H77_LPC, 1, 0 }, 237 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM70_LPC, 1, 0 }, 238 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM75_LPC, 1, 0 }, 239 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM76_LPC, 1, 0 }, 240 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM77_LPC, 1, 0 }, 241 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_QM77_LPC, 1, 0 }, 242 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_QS77_LPC, 1, 0 }, 243 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_UM77_LPC, 1, 0 }, 244 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_NM70_LPC, 1, 0 }, 245 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q75_LPC, 1, 0 }, 246 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q77_LPC, 1, 0 }, 247 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z75_LPC, 1, 0 }, 248 1.37 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z77_LPC, 1, 0 }, 249 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z87_LPC, 1, 0 }, 250 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z85_LPC, 1, 0 }, 251 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM86_LPC, 1, 0 }, 252 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H87_LPC, 1, 0 }, 253 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM87_LPC, 1, 0 }, 254 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q85_LPC, 1, 0 }, 255 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q87_LPC, 1, 0 }, 256 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM87_LPC, 1, 0 }, 257 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B85_LPC, 1, 0 }, 258 1.47 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H97_LPC, 1, 0 }, 259 1.47 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z97_LPC, 1, 0 }, 260 1.48 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X99_LPC, 1, 0 }, 261 1.48 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X99_LPC_2, 1, 0 }, 262 1.50 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE5G_M_LPC_4, 1, 0 }, 263 1.50 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE5G_M_LPC_7, 1, 0 }, 264 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C222_LPC, 1, 0 }, 265 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C224_LPC, 1, 0 }, 266 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C226_LPC, 1, 0 }, 267 1.39 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H81_LPC, 1, 0 }, 268 1.38 riastrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_LPC, 1, 0 }, 269 1.44 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_DH89XXCC_LPC, 1, 0 }, 270 1.44 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_DH89XXCL_LPC, 1, 0 }, 271 1.62 hans { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BSW_PCU_LPC, 0, 1 }, 272 1.42 msaitoh #if 0 273 1.41 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_1, 1, 0 }, 274 1.41 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_2, 1, 0 }, 275 1.41 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_3, 1, 0 }, 276 1.41 msaitoh { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_4, 1, 0 }, 277 1.42 msaitoh #endif 278 1.14 joerg 279 1.6 jmcneill { 0, 0, 0, 0 }, 280 1.6 jmcneill }; 281 1.6 jmcneill 282 1.1 xtraeme /* 283 1.51 jakllsch * Allow user to enable GPIO functionality if they really need it. The 284 1.51 jakllsch * vast majority of systems with an ICH should not expose GPIO to the 285 1.51 jakllsch * kernel or user. In at least one instance the gpio_resume() handler 286 1.51 jakllsch * on ICH GPIO was found to sabotage S3 suspend/resume. 287 1.51 jakllsch */ 288 1.51 jakllsch int ichlpcib_gpio_disable = 1; 289 1.51 jakllsch 290 1.51 jakllsch /* 291 1.1 xtraeme * Autoconf callbacks. 292 1.1 xtraeme */ 293 1.1 xtraeme static int 294 1.9 xtraeme lpcibmatch(device_t parent, cfdata_t match, void *aux) 295 1.1 xtraeme { 296 1.1 xtraeme struct pci_attach_args *pa = aux; 297 1.52 maxv const struct lpcib_device *lpcib_dev; 298 1.1 xtraeme 299 1.1 xtraeme /* We are ISA bridge, of course */ 300 1.1 xtraeme if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE || 301 1.1 xtraeme PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) 302 1.1 xtraeme return 0; 303 1.1 xtraeme 304 1.6 jmcneill for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) { 305 1.6 jmcneill if (PCI_VENDOR(pa->pa_id) == lpcib_dev->vendor && 306 1.6 jmcneill PCI_PRODUCT(pa->pa_id) == lpcib_dev->product) 307 1.1 xtraeme return 10; 308 1.1 xtraeme } 309 1.1 xtraeme 310 1.1 xtraeme return 0; 311 1.1 xtraeme } 312 1.1 xtraeme 313 1.1 xtraeme static void 314 1.9 xtraeme lpcibattach(device_t parent, device_t self, void *aux) 315 1.1 xtraeme { 316 1.1 xtraeme struct pci_attach_args *pa = aux; 317 1.6 jmcneill struct lpcib_softc *sc = device_private(self); 318 1.52 maxv const struct lpcib_device *lpcib_dev; 319 1.46 msaitoh pcireg_t pmbase; 320 1.1 xtraeme 321 1.6 jmcneill sc->sc_pa = *pa; 322 1.6 jmcneill 323 1.6 jmcneill for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) { 324 1.6 jmcneill if (PCI_VENDOR(pa->pa_id) != lpcib_dev->vendor || 325 1.6 jmcneill PCI_PRODUCT(pa->pa_id) != lpcib_dev->product) 326 1.6 jmcneill continue; 327 1.6 jmcneill sc->sc_has_rcba = lpcib_dev->has_rcba; 328 1.6 jmcneill sc->sc_has_ich5_hpet = lpcib_dev->has_ich5_hpet; 329 1.6 jmcneill break; 330 1.6 jmcneill } 331 1.1 xtraeme 332 1.1 xtraeme pcibattach(parent, self, aux); 333 1.1 xtraeme 334 1.1 xtraeme /* 335 1.1 xtraeme * Part of our I/O registers are used as ACPI PM regs. 336 1.1 xtraeme * Since our ACPI subsystem accesses the I/O space directly so far, 337 1.1 xtraeme * we do not have to bother bus_space I/O map confliction. 338 1.45 msaitoh * 339 1.45 msaitoh * The PMBASE register is alike PCI BAR but not completely compatible 340 1.45 msaitoh * with it. The PMBASE define the base address and the type but 341 1.46 msaitoh * not describe the size. The value of the register may be lower 342 1.46 msaitoh * than LPCIB_PCI_PM_SIZE. It makes impossible to use 343 1.46 msaitoh * pci_mapreg_submap() because the function does range check. 344 1.1 xtraeme */ 345 1.58 riastrad sc->sc_pmt = pa->pa_iot; 346 1.46 msaitoh pmbase = pci_conf_read(pa->pa_pc, pa->pa_tag, LPCIB_PCI_PMBASE); 347 1.58 riastrad if (bus_space_map(sc->sc_pmt, PCI_MAPREG_IO_ADDR(pmbase), 348 1.60 riastrad LPCIB_PCI_PM_SIZE, 0, &sc->sc_pmh) != 0) { 349 1.46 msaitoh aprint_error_dev(self, 350 1.60 riastrad "can't map power management i/o space\n"); 351 1.1 xtraeme return; 352 1.1 xtraeme } 353 1.1 xtraeme 354 1.59 riastrad if (bus_space_subregion(sc->sc_pmt, sc->sc_pmh, PMC_TCO_BASE, 355 1.59 riastrad TCO_REGSIZE, &sc->sc_tcoh)) { 356 1.59 riastrad aprint_error_dev(self, "can't map TCO space\n"); 357 1.59 riastrad } else { 358 1.59 riastrad sc->sc_tcot = sc->sc_pmt; 359 1.59 riastrad } 360 1.59 riastrad 361 1.16 joerg sc->sc_pmcon_orig = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 362 1.16 joerg LPCIB_PCI_GEN_PMCON_1); 363 1.16 joerg 364 1.6 jmcneill /* For ICH6 and later, always enable RCBA */ 365 1.6 jmcneill if (sc->sc_has_rcba) { 366 1.6 jmcneill pcireg_t rcba; 367 1.6 jmcneill 368 1.6 jmcneill sc->sc_rcbat = sc->sc_pa.pa_memt; 369 1.6 jmcneill 370 1.12 martin rcba = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 371 1.60 riastrad LPCIB_RCBA); 372 1.6 jmcneill if ((rcba & LPCIB_RCBA_EN) == 0) { 373 1.40 jakllsch aprint_error_dev(self, "RCBA is not enabled\n"); 374 1.6 jmcneill return; 375 1.6 jmcneill } 376 1.6 jmcneill rcba &= ~LPCIB_RCBA_EN; 377 1.6 jmcneill 378 1.6 jmcneill if (bus_space_map(sc->sc_rcbat, rcba, LPCIB_RCBA_SIZE, 0, 379 1.60 riastrad &sc->sc_rcbah)) { 380 1.40 jakllsch aprint_error_dev(self, "RCBA could not be mapped\n"); 381 1.6 jmcneill return; 382 1.6 jmcneill } 383 1.6 jmcneill } 384 1.6 jmcneill 385 1.1 xtraeme /* Set up the power management timer. */ 386 1.9 xtraeme pmtimer_configure(self); 387 1.1 xtraeme 388 1.1 xtraeme /* Set up the TCO (watchdog). */ 389 1.9 xtraeme tcotimer_configure(self); 390 1.1 xtraeme 391 1.1 xtraeme /* Set up SpeedStep. */ 392 1.9 xtraeme speedstep_configure(self); 393 1.1 xtraeme 394 1.6 jmcneill /* Set up HPET. */ 395 1.9 xtraeme lpcib_hpet_configure(self); 396 1.6 jmcneill 397 1.20 jakllsch #if NGPIO > 0 398 1.20 jakllsch /* Set up GPIO */ 399 1.20 jakllsch lpcib_gpio_configure(self); 400 1.20 jakllsch #endif 401 1.20 jakllsch 402 1.25 jakllsch #if NFWHRNG > 0 403 1.25 jakllsch lpcib_fwh_configure(self); 404 1.25 jakllsch #endif 405 1.25 jakllsch 406 1.6 jmcneill /* Install power handler */ 407 1.16 joerg if (!pmf_device_register1(self, lpcib_suspend, lpcib_resume, 408 1.60 riastrad lpcib_shutdown)) 409 1.6 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 410 1.6 jmcneill } 411 1.6 jmcneill 412 1.19 dyoung static void 413 1.19 dyoung lpcibchilddet(device_t self, device_t child) 414 1.19 dyoung { 415 1.19 dyoung struct lpcib_softc *sc = device_private(self); 416 1.19 dyoung uint32_t val; 417 1.19 dyoung 418 1.25 jakllsch #if NFWHRNG > 0 419 1.25 jakllsch if (sc->sc_fwhbus == child) { 420 1.25 jakllsch sc->sc_fwhbus = NULL; 421 1.25 jakllsch return; 422 1.25 jakllsch } 423 1.25 jakllsch #endif 424 1.21 jakllsch #if NGPIO > 0 425 1.20 jakllsch if (sc->sc_gpiobus == child) { 426 1.20 jakllsch sc->sc_gpiobus = NULL; 427 1.20 jakllsch return; 428 1.20 jakllsch } 429 1.21 jakllsch #endif 430 1.49 pgoyette if (sc->sc_tco == child) { 431 1.49 pgoyette sc->sc_tco = NULL; 432 1.49 pgoyette return; 433 1.49 pgoyette } 434 1.49 pgoyette 435 1.19 dyoung if (sc->sc_hpetbus != child) { 436 1.19 dyoung pcibchilddet(self, child); 437 1.19 dyoung return; 438 1.19 dyoung } 439 1.19 dyoung sc->sc_hpetbus = NULL; 440 1.19 dyoung if (sc->sc_has_ich5_hpet) { 441 1.19 dyoung val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 442 1.19 dyoung LPCIB_PCI_GEN_CNTL); 443 1.19 dyoung switch (val & LPCIB_ICH5_HPTC_WIN_MASK) { 444 1.19 dyoung case LPCIB_ICH5_HPTC_0000: 445 1.19 dyoung case LPCIB_ICH5_HPTC_1000: 446 1.19 dyoung case LPCIB_ICH5_HPTC_2000: 447 1.19 dyoung case LPCIB_ICH5_HPTC_3000: 448 1.19 dyoung break; 449 1.19 dyoung default: 450 1.19 dyoung return; 451 1.19 dyoung } 452 1.19 dyoung val &= ~LPCIB_ICH5_HPTC_EN; 453 1.19 dyoung pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 454 1.19 dyoung LPCIB_PCI_GEN_CNTL, val); 455 1.19 dyoung } else if (sc->sc_has_rcba) { 456 1.19 dyoung val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 457 1.19 dyoung LPCIB_RCBA_HPTC); 458 1.19 dyoung switch (val & LPCIB_RCBA_HPTC_WIN_MASK) { 459 1.19 dyoung case LPCIB_RCBA_HPTC_0000: 460 1.19 dyoung case LPCIB_RCBA_HPTC_1000: 461 1.19 dyoung case LPCIB_RCBA_HPTC_2000: 462 1.19 dyoung case LPCIB_RCBA_HPTC_3000: 463 1.19 dyoung break; 464 1.19 dyoung default: 465 1.19 dyoung return; 466 1.19 dyoung } 467 1.19 dyoung val &= ~LPCIB_RCBA_HPTC_EN; 468 1.19 dyoung bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 469 1.19 dyoung val); 470 1.19 dyoung } 471 1.19 dyoung } 472 1.19 dyoung 473 1.19 dyoung static int 474 1.19 dyoung lpcibrescan(device_t self, const char *ifattr, const int *locators) 475 1.19 dyoung { 476 1.19 dyoung struct lpcib_softc *sc = device_private(self); 477 1.19 dyoung 478 1.60 riastrad if (ifattr_match(ifattr, "tcoichbus") && sc->sc_tco == NULL) 479 1.49 pgoyette tcotimer_configure(self); 480 1.49 pgoyette 481 1.25 jakllsch #if NFWHRNG > 0 482 1.25 jakllsch if (ifattr_match(ifattr, "fwhichbus") && sc->sc_fwhbus == NULL) 483 1.25 jakllsch lpcib_fwh_configure(self); 484 1.25 jakllsch #endif 485 1.25 jakllsch 486 1.19 dyoung if (ifattr_match(ifattr, "hpetichbus") && sc->sc_hpetbus == NULL) 487 1.19 dyoung lpcib_hpet_configure(self); 488 1.19 dyoung 489 1.20 jakllsch #if NGPIO > 0 490 1.20 jakllsch if (ifattr_match(ifattr, "gpiobus") && sc->sc_gpiobus == NULL) 491 1.20 jakllsch lpcib_gpio_configure(self); 492 1.20 jakllsch #endif 493 1.20 jakllsch 494 1.19 dyoung return pcibrescan(self, ifattr, locators); 495 1.19 dyoung } 496 1.19 dyoung 497 1.19 dyoung static int 498 1.19 dyoung lpcibdetach(device_t self, int flags) 499 1.19 dyoung { 500 1.19 dyoung struct lpcib_softc *sc = device_private(self); 501 1.61 riastrad int error; 502 1.61 riastrad 503 1.61 riastrad error = config_detach_children(self, flags); 504 1.61 riastrad if (error) 505 1.61 riastrad return error; 506 1.19 dyoung 507 1.19 dyoung pmf_device_deregister(self); 508 1.19 dyoung 509 1.20 jakllsch #if NGPIO > 0 510 1.61 riastrad lpcib_gpio_unconfigure(self); 511 1.20 jakllsch #endif 512 1.20 jakllsch 513 1.19 dyoung /* Set up SpeedStep. */ 514 1.19 dyoung speedstep_unconfigure(self); 515 1.19 dyoung 516 1.61 riastrad pmtimer_unconfigure(self, flags); 517 1.19 dyoung 518 1.19 dyoung if (sc->sc_has_rcba) 519 1.19 dyoung bus_space_unmap(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_SIZE); 520 1.19 dyoung 521 1.58 riastrad bus_space_unmap(sc->sc_pmt, sc->sc_pmh, sc->sc_iosize); 522 1.19 dyoung 523 1.61 riastrad error = pcibdetach(self, flags); 524 1.61 riastrad KASSERTMSG(error == 0, "error=%d", error); 525 1.61 riastrad 526 1.61 riastrad return 0; 527 1.19 dyoung } 528 1.19 dyoung 529 1.6 jmcneill static bool 530 1.16 joerg lpcib_shutdown(device_t dv, int howto) 531 1.16 joerg { 532 1.16 joerg struct lpcib_softc *sc = device_private(dv); 533 1.16 joerg 534 1.16 joerg pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 535 1.16 joerg LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig); 536 1.16 joerg 537 1.16 joerg return true; 538 1.16 joerg } 539 1.16 joerg 540 1.16 joerg static bool 541 1.24 dyoung lpcib_suspend(device_t dv, const pmf_qual_t *qual) 542 1.6 jmcneill { 543 1.6 jmcneill struct lpcib_softc *sc = device_private(dv); 544 1.12 martin pci_chipset_tag_t pc = sc->sc_pcib.sc_pc; 545 1.12 martin pcitag_t tag = sc->sc_pcib.sc_tag; 546 1.6 jmcneill 547 1.6 jmcneill /* capture PIRQ routing control registers */ 548 1.6 jmcneill sc->sc_pirq[0] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQA_ROUT); 549 1.7 drochner sc->sc_pirq[1] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQE_ROUT); 550 1.6 jmcneill 551 1.6 jmcneill sc->sc_pmcon = pci_conf_read(pc, tag, LPCIB_PCI_GEN_PMCON_1); 552 1.6 jmcneill sc->sc_fwhsel2 = pci_conf_read(pc, tag, LPCIB_PCI_GEN_STA); 553 1.6 jmcneill 554 1.6 jmcneill if (sc->sc_has_rcba) { 555 1.6 jmcneill sc->sc_rcba_reg = pci_conf_read(pc, tag, LPCIB_RCBA); 556 1.6 jmcneill sc->sc_hpet_reg = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 557 1.6 jmcneill LPCIB_RCBA_HPTC); 558 1.6 jmcneill } else if (sc->sc_has_ich5_hpet) { 559 1.6 jmcneill sc->sc_hpet_reg = pci_conf_read(pc, tag, LPCIB_PCI_GEN_CNTL); 560 1.6 jmcneill } 561 1.6 jmcneill 562 1.6 jmcneill return true; 563 1.6 jmcneill } 564 1.6 jmcneill 565 1.6 jmcneill static bool 566 1.24 dyoung lpcib_resume(device_t dv, const pmf_qual_t *qual) 567 1.6 jmcneill { 568 1.6 jmcneill struct lpcib_softc *sc = device_private(dv); 569 1.12 martin pci_chipset_tag_t pc = sc->sc_pcib.sc_pc; 570 1.12 martin pcitag_t tag = sc->sc_pcib.sc_tag; 571 1.6 jmcneill 572 1.6 jmcneill /* restore PIRQ routing control registers */ 573 1.6 jmcneill pci_conf_write(pc, tag, LPCIB_PCI_PIRQA_ROUT, sc->sc_pirq[0]); 574 1.7 drochner pci_conf_write(pc, tag, LPCIB_PCI_PIRQE_ROUT, sc->sc_pirq[1]); 575 1.6 jmcneill 576 1.6 jmcneill pci_conf_write(pc, tag, LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon); 577 1.6 jmcneill pci_conf_write(pc, tag, LPCIB_PCI_GEN_STA, sc->sc_fwhsel2); 578 1.6 jmcneill 579 1.6 jmcneill if (sc->sc_has_rcba) { 580 1.6 jmcneill pci_conf_write(pc, tag, LPCIB_RCBA, sc->sc_rcba_reg); 581 1.6 jmcneill bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 582 1.6 jmcneill sc->sc_hpet_reg); 583 1.6 jmcneill } else if (sc->sc_has_ich5_hpet) { 584 1.6 jmcneill pci_conf_write(pc, tag, LPCIB_PCI_GEN_CNTL, sc->sc_hpet_reg); 585 1.6 jmcneill } 586 1.1 xtraeme 587 1.6 jmcneill return true; 588 1.1 xtraeme } 589 1.1 xtraeme 590 1.1 xtraeme /* 591 1.1 xtraeme * Initialize the power management timer. 592 1.1 xtraeme */ 593 1.1 xtraeme static void 594 1.9 xtraeme pmtimer_configure(device_t self) 595 1.1 xtraeme { 596 1.9 xtraeme struct lpcib_softc *sc = device_private(self); 597 1.1 xtraeme pcireg_t control; 598 1.1 xtraeme 599 1.60 riastrad /* 600 1.1 xtraeme * Check if power management I/O space is enabled and enable the ACPI_EN 601 1.1 xtraeme * bit if it's disabled. 602 1.1 xtraeme */ 603 1.12 martin control = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 604 1.12 martin LPCIB_PCI_ACPI_CNTL); 605 1.19 dyoung sc->sc_acpi_cntl = control; 606 1.1 xtraeme if ((control & LPCIB_PCI_ACPI_CNTL_EN) == 0) { 607 1.1 xtraeme control |= LPCIB_PCI_ACPI_CNTL_EN; 608 1.12 martin pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 609 1.12 martin LPCIB_PCI_ACPI_CNTL, control); 610 1.1 xtraeme } 611 1.1 xtraeme 612 1.1 xtraeme /* Attach our PM timer with the generic acpipmtimer function */ 613 1.58 riastrad sc->sc_pmtimer = acpipmtimer_attach(self, sc->sc_pmt, sc->sc_pmh, 614 1.57 riastrad PMC_PM1_TMR, 0); 615 1.1 xtraeme } 616 1.1 xtraeme 617 1.61 riastrad static void 618 1.19 dyoung pmtimer_unconfigure(device_t self, int flags) 619 1.19 dyoung { 620 1.19 dyoung struct lpcib_softc *sc = device_private(self); 621 1.61 riastrad int error __diagused; 622 1.19 dyoung 623 1.61 riastrad if (sc->sc_pmtimer != NULL) { 624 1.61 riastrad error = acpipmtimer_detach(sc->sc_pmtimer, flags); 625 1.61 riastrad KASSERTMSG(error == 0, "error=%d", error); 626 1.61 riastrad } 627 1.19 dyoung 628 1.19 dyoung pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 629 1.19 dyoung LPCIB_PCI_ACPI_CNTL, sc->sc_acpi_cntl); 630 1.19 dyoung } 631 1.19 dyoung 632 1.1 xtraeme /* 633 1.49 pgoyette * Configure the watchdog timer. 634 1.1 xtraeme */ 635 1.1 xtraeme static void 636 1.9 xtraeme tcotimer_configure(device_t self) 637 1.1 xtraeme { 638 1.9 xtraeme struct lpcib_softc *sc = device_private(self); 639 1.56 riastrad struct tco_attach_args arg; 640 1.1 xtraeme 641 1.55 riastrad if (sc->sc_has_rcba) 642 1.55 riastrad arg.ta_version = TCO_VERSION_RCBA; 643 1.55 riastrad else 644 1.55 riastrad arg.ta_version = TCO_VERSION_PCIB; 645 1.58 riastrad arg.ta_pmt = sc->sc_pmt; 646 1.58 riastrad arg.ta_pmh = sc->sc_pmh; 647 1.49 pgoyette arg.ta_rcbat = sc->sc_rcbat; 648 1.49 pgoyette arg.ta_rcbah = sc->sc_rcbah; 649 1.55 riastrad arg.ta_pcib = &sc->sc_pcib; 650 1.59 riastrad arg.ta_tcot = sc->sc_tcot; 651 1.59 riastrad arg.ta_tcoh = sc->sc_tcoh; 652 1.1 xtraeme 653 1.53 thorpej sc->sc_tco = config_found(self, &arg, NULL, 654 1.54 thorpej CFARGS(.iattr = "tcoichbus")); 655 1.1 xtraeme } 656 1.1 xtraeme 657 1.1 xtraeme 658 1.1 xtraeme /* 659 1.1 xtraeme * Intel ICH SpeedStep support. 660 1.1 xtraeme */ 661 1.1 xtraeme #define SS_READ(sc, reg) \ 662 1.58 riastrad bus_space_read_1((sc)->sc_pmt, (sc)->sc_pmh, (reg)) 663 1.1 xtraeme #define SS_WRITE(sc, reg, val) \ 664 1.58 riastrad bus_space_write_1((sc)->sc_pmt, (sc)->sc_pmh, (reg), (val)) 665 1.1 xtraeme 666 1.1 xtraeme /* 667 1.1 xtraeme * Linux driver says that SpeedStep on older chipsets cause 668 1.1 xtraeme * lockups on Dell Inspiron 8000 and 8100. 669 1.15 mrg * It should also not be enabled on systems with the 82855GM 670 1.15 mrg * Hub, which typically have an EST-enabled CPU. 671 1.1 xtraeme */ 672 1.1 xtraeme static int 673 1.29 dyoung speedstep_bad_hb_check(const struct pci_attach_args *pa) 674 1.1 xtraeme { 675 1.1 xtraeme 676 1.1 xtraeme if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82815_FULL_HUB && 677 1.1 xtraeme PCI_REVISION(pa->pa_class) < 5) 678 1.1 xtraeme return 1; 679 1.1 xtraeme 680 1.15 mrg if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82855GM_MCH) 681 1.15 mrg return 1; 682 1.15 mrg 683 1.1 xtraeme return 0; 684 1.1 xtraeme } 685 1.1 xtraeme 686 1.1 xtraeme static void 687 1.9 xtraeme speedstep_configure(device_t self) 688 1.1 xtraeme { 689 1.9 xtraeme struct lpcib_softc *sc = device_private(self); 690 1.1 xtraeme const struct sysctlnode *node, *ssnode; 691 1.1 xtraeme int rv; 692 1.1 xtraeme 693 1.1 xtraeme /* Supported on ICH2-M, ICH3-M and ICH4-M. */ 694 1.30 msaitoh if (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801DBM_LPC || 695 1.6 jmcneill PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801CAM_LPC || 696 1.6 jmcneill (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801BAM_LPC && 697 1.60 riastrad pci_find_device(&sc->sc_pa, speedstep_bad_hb_check) == 0)) { 698 1.19 dyoung pcireg_t pmcon; 699 1.1 xtraeme 700 1.1 xtraeme /* Enable SpeedStep if it isn't already enabled. */ 701 1.12 martin pmcon = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 702 1.60 riastrad LPCIB_PCI_GEN_PMCON_1); 703 1.1 xtraeme if ((pmcon & LPCIB_PCI_GEN_PMCON_1_SS_EN) == 0) 704 1.12 martin pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 705 1.60 riastrad LPCIB_PCI_GEN_PMCON_1, 706 1.60 riastrad pmcon | LPCIB_PCI_GEN_PMCON_1_SS_EN); 707 1.1 xtraeme 708 1.1 xtraeme /* Put in machdep.speedstep_state (0 for low, 1 for high). */ 709 1.19 dyoung if ((rv = sysctl_createv(&sc->sc_log, 0, NULL, &node, 710 1.1 xtraeme CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 711 1.1 xtraeme NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0) 712 1.1 xtraeme goto err; 713 1.1 xtraeme 714 1.1 xtraeme /* CTLFLAG_ANYWRITE? kernel option like EST? */ 715 1.19 dyoung if ((rv = sysctl_createv(&sc->sc_log, 0, &node, &ssnode, 716 1.1 xtraeme CTLFLAG_READWRITE, CTLTYPE_INT, "speedstep_state", NULL, 717 1.1 xtraeme speedstep_sysctl_helper, 0, NULL, 0, CTL_CREATE, 718 1.1 xtraeme CTL_EOL)) != 0) 719 1.1 xtraeme goto err; 720 1.1 xtraeme 721 1.1 xtraeme /* XXX save the sc for IO tag/handle */ 722 1.1 xtraeme speedstep_cookie = sc; 723 1.9 xtraeme aprint_verbose_dev(self, "SpeedStep enabled\n"); 724 1.1 xtraeme } 725 1.1 xtraeme 726 1.1 xtraeme return; 727 1.1 xtraeme 728 1.1 xtraeme err: 729 1.1 xtraeme aprint_normal("%s: sysctl_createv failed (rv = %d)\n", __func__, rv); 730 1.1 xtraeme } 731 1.1 xtraeme 732 1.19 dyoung static void 733 1.19 dyoung speedstep_unconfigure(device_t self) 734 1.19 dyoung { 735 1.19 dyoung struct lpcib_softc *sc = device_private(self); 736 1.19 dyoung 737 1.19 dyoung sysctl_teardown(&sc->sc_log); 738 1.19 dyoung pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 739 1.19 dyoung LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig); 740 1.19 dyoung 741 1.19 dyoung speedstep_cookie = NULL; 742 1.19 dyoung } 743 1.19 dyoung 744 1.1 xtraeme /* 745 1.1 xtraeme * get/set the SpeedStep state: 0 == low power, 1 == high power. 746 1.1 xtraeme */ 747 1.1 xtraeme static int 748 1.1 xtraeme speedstep_sysctl_helper(SYSCTLFN_ARGS) 749 1.1 xtraeme { 750 1.1 xtraeme struct sysctlnode node; 751 1.1 xtraeme struct lpcib_softc *sc = speedstep_cookie; 752 1.1 xtraeme uint8_t state, state2; 753 1.1 xtraeme int ostate, nstate, s, error = 0; 754 1.1 xtraeme 755 1.1 xtraeme /* 756 1.1 xtraeme * We do the dance with spl's to avoid being at high ipl during 757 1.1 xtraeme * sysctl_lookup() which can both copyin and copyout. 758 1.1 xtraeme */ 759 1.1 xtraeme s = splserial(); 760 1.57 riastrad state = SS_READ(sc, PMC_PM_SS_CNTL); 761 1.1 xtraeme splx(s); 762 1.57 riastrad if ((state & PMC_PM_SS_STATE_LOW) == 0) 763 1.1 xtraeme ostate = 1; 764 1.1 xtraeme else 765 1.1 xtraeme ostate = 0; 766 1.1 xtraeme nstate = ostate; 767 1.1 xtraeme 768 1.1 xtraeme node = *rnode; 769 1.1 xtraeme node.sysctl_data = &nstate; 770 1.1 xtraeme 771 1.1 xtraeme error = sysctl_lookup(SYSCTLFN_CALL(&node)); 772 1.1 xtraeme if (error || newp == NULL) 773 1.1 xtraeme goto out; 774 1.1 xtraeme 775 1.1 xtraeme /* Only two states are available */ 776 1.1 xtraeme if (nstate != 0 && nstate != 1) { 777 1.1 xtraeme error = EINVAL; 778 1.1 xtraeme goto out; 779 1.1 xtraeme } 780 1.1 xtraeme 781 1.1 xtraeme s = splserial(); 782 1.57 riastrad state2 = SS_READ(sc, PMC_PM_SS_CNTL); 783 1.57 riastrad if ((state2 & PMC_PM_SS_STATE_LOW) == 0) 784 1.1 xtraeme ostate = 1; 785 1.1 xtraeme else 786 1.1 xtraeme ostate = 0; 787 1.1 xtraeme 788 1.1 xtraeme if (ostate != nstate) { 789 1.1 xtraeme uint8_t cntl; 790 1.1 xtraeme 791 1.1 xtraeme if (nstate == 0) 792 1.57 riastrad state2 |= PMC_PM_SS_STATE_LOW; 793 1.1 xtraeme else 794 1.57 riastrad state2 &= ~PMC_PM_SS_STATE_LOW; 795 1.1 xtraeme 796 1.1 xtraeme /* 797 1.1 xtraeme * Must disable bus master arbitration during the change. 798 1.1 xtraeme */ 799 1.57 riastrad cntl = SS_READ(sc, PMC_PM_CTRL); 800 1.57 riastrad SS_WRITE(sc, PMC_PM_CTRL, cntl | PMC_PM_SS_CNTL_ARB_DIS); 801 1.57 riastrad SS_WRITE(sc, PMC_PM_SS_CNTL, state2); 802 1.57 riastrad SS_WRITE(sc, PMC_PM_CTRL, cntl); 803 1.1 xtraeme } 804 1.1 xtraeme splx(s); 805 1.1 xtraeme out: 806 1.1 xtraeme return error; 807 1.1 xtraeme } 808 1.6 jmcneill 809 1.6 jmcneill static void 810 1.9 xtraeme lpcib_hpet_configure(device_t self) 811 1.6 jmcneill { 812 1.9 xtraeme struct lpcib_softc *sc = device_private(self); 813 1.31 jruoho struct lpcib_hpet_attach_args arg; 814 1.6 jmcneill uint32_t hpet_reg, val; 815 1.6 jmcneill 816 1.6 jmcneill if (sc->sc_has_ich5_hpet) { 817 1.12 martin val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 818 1.9 xtraeme LPCIB_PCI_GEN_CNTL); 819 1.6 jmcneill switch (val & LPCIB_ICH5_HPTC_WIN_MASK) { 820 1.6 jmcneill case LPCIB_ICH5_HPTC_0000: 821 1.6 jmcneill hpet_reg = LPCIB_ICH5_HPTC_0000_BASE; 822 1.6 jmcneill break; 823 1.6 jmcneill case LPCIB_ICH5_HPTC_1000: 824 1.6 jmcneill hpet_reg = LPCIB_ICH5_HPTC_1000_BASE; 825 1.6 jmcneill break; 826 1.6 jmcneill case LPCIB_ICH5_HPTC_2000: 827 1.6 jmcneill hpet_reg = LPCIB_ICH5_HPTC_2000_BASE; 828 1.6 jmcneill break; 829 1.6 jmcneill case LPCIB_ICH5_HPTC_3000: 830 1.6 jmcneill hpet_reg = LPCIB_ICH5_HPTC_3000_BASE; 831 1.6 jmcneill break; 832 1.6 jmcneill default: 833 1.6 jmcneill return; 834 1.6 jmcneill } 835 1.6 jmcneill val |= sc->sc_hpet_reg | LPCIB_ICH5_HPTC_EN; 836 1.12 martin pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 837 1.9 xtraeme LPCIB_PCI_GEN_CNTL, val); 838 1.6 jmcneill } else if (sc->sc_has_rcba) { 839 1.6 jmcneill val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah, 840 1.6 jmcneill LPCIB_RCBA_HPTC); 841 1.6 jmcneill switch (val & LPCIB_RCBA_HPTC_WIN_MASK) { 842 1.6 jmcneill case LPCIB_RCBA_HPTC_0000: 843 1.6 jmcneill hpet_reg = LPCIB_RCBA_HPTC_0000_BASE; 844 1.6 jmcneill break; 845 1.6 jmcneill case LPCIB_RCBA_HPTC_1000: 846 1.6 jmcneill hpet_reg = LPCIB_RCBA_HPTC_1000_BASE; 847 1.6 jmcneill break; 848 1.6 jmcneill case LPCIB_RCBA_HPTC_2000: 849 1.6 jmcneill hpet_reg = LPCIB_RCBA_HPTC_2000_BASE; 850 1.6 jmcneill break; 851 1.6 jmcneill case LPCIB_RCBA_HPTC_3000: 852 1.6 jmcneill hpet_reg = LPCIB_RCBA_HPTC_3000_BASE; 853 1.6 jmcneill break; 854 1.6 jmcneill default: 855 1.6 jmcneill return; 856 1.6 jmcneill } 857 1.6 jmcneill val |= LPCIB_RCBA_HPTC_EN; 858 1.6 jmcneill bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC, 859 1.6 jmcneill val); 860 1.6 jmcneill } else { 861 1.6 jmcneill /* No HPET here */ 862 1.6 jmcneill return; 863 1.6 jmcneill } 864 1.6 jmcneill 865 1.6 jmcneill arg.hpet_mem_t = sc->sc_pa.pa_memt; 866 1.6 jmcneill arg.hpet_reg = hpet_reg; 867 1.6 jmcneill 868 1.53 thorpej sc->sc_hpetbus = config_found(self, &arg, NULL, 869 1.54 thorpej CFARGS(.iattr = "hpetichbus")); 870 1.19 dyoung } 871 1.19 dyoung 872 1.20 jakllsch #if NGPIO > 0 873 1.20 jakllsch static void 874 1.20 jakllsch lpcib_gpio_configure(device_t self) 875 1.20 jakllsch { 876 1.20 jakllsch struct lpcib_softc *sc = device_private(self); 877 1.20 jakllsch struct gpiobus_attach_args gba; 878 1.20 jakllsch pcireg_t gpio_cntl; 879 1.20 jakllsch uint32_t use, io, bit; 880 1.20 jakllsch int pin, shift, base_reg, cntl_reg, reg; 881 1.45 msaitoh int rv; 882 1.20 jakllsch 883 1.51 jakllsch if (ichlpcib_gpio_disable != 0) 884 1.51 jakllsch return; 885 1.51 jakllsch 886 1.20 jakllsch /* this implies ICH >= 6, and thus different mapreg */ 887 1.20 jakllsch if (sc->sc_has_rcba) { 888 1.20 jakllsch base_reg = LPCIB_PCI_GPIO_BASE_ICH6; 889 1.20 jakllsch cntl_reg = LPCIB_PCI_GPIO_CNTL_ICH6; 890 1.20 jakllsch } else { 891 1.20 jakllsch base_reg = LPCIB_PCI_GPIO_BASE; 892 1.20 jakllsch cntl_reg = LPCIB_PCI_GPIO_CNTL; 893 1.20 jakllsch } 894 1.20 jakllsch 895 1.20 jakllsch gpio_cntl = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 896 1.60 riastrad cntl_reg); 897 1.20 jakllsch 898 1.20 jakllsch /* Is GPIO enabled? */ 899 1.20 jakllsch if ((gpio_cntl & LPCIB_PCI_GPIO_CNTL_EN) == 0) 900 1.20 jakllsch return; 901 1.45 msaitoh /* 902 1.45 msaitoh * The GPIO_BASE register is alike PCI BAR but not completely 903 1.45 msaitoh * compatible with it. The PMBASE define the base address and the type 904 1.46 msaitoh * but not describe the size. The value of the register may be lower 905 1.46 msaitoh * than LPCIB_PCI_GPIO_SIZE. It makes impossible to use 906 1.46 msaitoh * pci_mapreg_submap() because the function does range check. 907 1.45 msaitoh */ 908 1.46 msaitoh sc->sc_gpio_iot = sc->sc_pa.pa_iot; 909 1.46 msaitoh reg = pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag, base_reg); 910 1.46 msaitoh rv = bus_space_map(sc->sc_gpio_iot, PCI_MAPREG_IO_ADDR(reg), 911 1.46 msaitoh LPCIB_PCI_GPIO_SIZE, 0, &sc->sc_gpio_ioh); 912 1.45 msaitoh if (rv != 0) { 913 1.45 msaitoh aprint_error_dev(self, "can't map general purpose i/o space(rv = %d)\n", rv); 914 1.20 jakllsch return; 915 1.20 jakllsch } 916 1.20 jakllsch 917 1.20 jakllsch mutex_init(&sc->sc_gpio_mtx, MUTEX_DEFAULT, IPL_NONE); 918 1.20 jakllsch 919 1.20 jakllsch for (pin = 0; pin < LPCIB_GPIO_NPINS; pin++) { 920 1.20 jakllsch sc->sc_gpio_pins[pin].pin_num = pin; 921 1.20 jakllsch 922 1.20 jakllsch /* Read initial state */ 923 1.20 jakllsch reg = (pin < 32) ? LPCIB_GPIO_GPIO_USE_SEL : LPCIB_GPIO_GPIO_USE_SEL2; 924 1.20 jakllsch use = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 925 1.20 jakllsch reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL; 926 1.20 jakllsch io = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, 4); 927 1.20 jakllsch shift = pin % 32; 928 1.20 jakllsch bit = __BIT(shift); 929 1.20 jakllsch 930 1.20 jakllsch if ((use & bit) != 0) { 931 1.20 jakllsch sc->sc_gpio_pins[pin].pin_caps = 932 1.20 jakllsch GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 933 1.20 jakllsch if (pin < 32) 934 1.20 jakllsch sc->sc_gpio_pins[pin].pin_caps |= 935 1.20 jakllsch GPIO_PIN_PULSATE; 936 1.20 jakllsch if ((io & bit) != 0) 937 1.20 jakllsch sc->sc_gpio_pins[pin].pin_flags = 938 1.20 jakllsch GPIO_PIN_INPUT; 939 1.20 jakllsch else 940 1.20 jakllsch sc->sc_gpio_pins[pin].pin_flags = 941 1.20 jakllsch GPIO_PIN_OUTPUT; 942 1.20 jakllsch } else 943 1.20 jakllsch sc->sc_gpio_pins[pin].pin_caps = 0; 944 1.20 jakllsch 945 1.20 jakllsch if (lpcib_gpio_pin_read(sc, pin) == 0) 946 1.20 jakllsch sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW; 947 1.20 jakllsch else 948 1.20 jakllsch sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH; 949 1.20 jakllsch 950 1.20 jakllsch } 951 1.20 jakllsch 952 1.20 jakllsch /* Create controller tag */ 953 1.20 jakllsch sc->sc_gpio_gc.gp_cookie = sc; 954 1.20 jakllsch sc->sc_gpio_gc.gp_pin_read = lpcib_gpio_pin_read; 955 1.20 jakllsch sc->sc_gpio_gc.gp_pin_write = lpcib_gpio_pin_write; 956 1.20 jakllsch sc->sc_gpio_gc.gp_pin_ctl = lpcib_gpio_pin_ctl; 957 1.20 jakllsch 958 1.20 jakllsch memset(&gba, 0, sizeof(gba)); 959 1.20 jakllsch 960 1.20 jakllsch gba.gba_gc = &sc->sc_gpio_gc; 961 1.20 jakllsch gba.gba_pins = sc->sc_gpio_pins; 962 1.20 jakllsch gba.gba_npins = LPCIB_GPIO_NPINS; 963 1.20 jakllsch 964 1.53 thorpej sc->sc_gpiobus = config_found(self, &gba, gpiobus_print, 965 1.54 thorpej CFARGS(.iattr = "gpiobus")); 966 1.20 jakllsch } 967 1.20 jakllsch 968 1.61 riastrad static void 969 1.61 riastrad lpcib_gpio_unconfigure(device_t self) 970 1.20 jakllsch { 971 1.20 jakllsch struct lpcib_softc *sc = device_private(self); 972 1.20 jakllsch 973 1.20 jakllsch mutex_destroy(&sc->sc_gpio_mtx); 974 1.20 jakllsch 975 1.20 jakllsch bus_space_unmap(sc->sc_gpio_iot, sc->sc_gpio_ioh, sc->sc_gpio_ios); 976 1.20 jakllsch } 977 1.20 jakllsch 978 1.20 jakllsch static int 979 1.20 jakllsch lpcib_gpio_pin_read(void *arg, int pin) 980 1.20 jakllsch { 981 1.20 jakllsch struct lpcib_softc *sc = arg; 982 1.20 jakllsch uint32_t data; 983 1.20 jakllsch int reg, shift; 984 1.60 riastrad 985 1.20 jakllsch reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2; 986 1.20 jakllsch shift = pin % 32; 987 1.20 jakllsch 988 1.20 jakllsch mutex_enter(&sc->sc_gpio_mtx); 989 1.20 jakllsch data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 990 1.20 jakllsch mutex_exit(&sc->sc_gpio_mtx); 991 1.60 riastrad 992 1.20 jakllsch return (__SHIFTOUT(data, __BIT(shift)) ? GPIO_PIN_HIGH : GPIO_PIN_LOW); 993 1.20 jakllsch } 994 1.20 jakllsch 995 1.20 jakllsch static void 996 1.20 jakllsch lpcib_gpio_pin_write(void *arg, int pin, int value) 997 1.20 jakllsch { 998 1.20 jakllsch struct lpcib_softc *sc = arg; 999 1.20 jakllsch uint32_t data; 1000 1.20 jakllsch int reg, shift; 1001 1.20 jakllsch 1002 1.20 jakllsch reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2; 1003 1.20 jakllsch shift = pin % 32; 1004 1.20 jakllsch 1005 1.20 jakllsch mutex_enter(&sc->sc_gpio_mtx); 1006 1.20 jakllsch 1007 1.20 jakllsch data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1008 1.20 jakllsch 1009 1.60 riastrad if (value) 1010 1.20 jakllsch data |= __BIT(shift); 1011 1.20 jakllsch else 1012 1.20 jakllsch data &= ~__BIT(shift); 1013 1.20 jakllsch 1014 1.20 jakllsch bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1015 1.20 jakllsch 1016 1.20 jakllsch mutex_exit(&sc->sc_gpio_mtx); 1017 1.20 jakllsch } 1018 1.20 jakllsch 1019 1.20 jakllsch static void 1020 1.20 jakllsch lpcib_gpio_pin_ctl(void *arg, int pin, int flags) 1021 1.20 jakllsch { 1022 1.20 jakllsch struct lpcib_softc *sc = arg; 1023 1.20 jakllsch uint32_t data; 1024 1.20 jakllsch int reg, shift; 1025 1.20 jakllsch 1026 1.20 jakllsch shift = pin % 32; 1027 1.20 jakllsch reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL2; 1028 1.60 riastrad 1029 1.20 jakllsch mutex_enter(&sc->sc_gpio_mtx); 1030 1.60 riastrad 1031 1.20 jakllsch data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1032 1.60 riastrad 1033 1.20 jakllsch if (flags & GPIO_PIN_OUTPUT) 1034 1.20 jakllsch data &= ~__BIT(shift); 1035 1.20 jakllsch 1036 1.20 jakllsch if (flags & GPIO_PIN_INPUT) 1037 1.20 jakllsch data |= __BIT(shift); 1038 1.20 jakllsch 1039 1.20 jakllsch bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1040 1.20 jakllsch 1041 1.20 jakllsch 1042 1.20 jakllsch if (pin < 32) { 1043 1.20 jakllsch reg = LPCIB_GPIO_GPO_BLINK; 1044 1.20 jakllsch data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); 1045 1.20 jakllsch 1046 1.20 jakllsch if (flags & GPIO_PIN_PULSATE) 1047 1.20 jakllsch data |= __BIT(shift); 1048 1.20 jakllsch else 1049 1.20 jakllsch data &= ~__BIT(shift); 1050 1.20 jakllsch 1051 1.20 jakllsch bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); 1052 1.20 jakllsch } 1053 1.20 jakllsch 1054 1.20 jakllsch mutex_exit(&sc->sc_gpio_mtx); 1055 1.20 jakllsch } 1056 1.20 jakllsch #endif 1057 1.25 jakllsch 1058 1.25 jakllsch #if NFWHRNG > 0 1059 1.25 jakllsch static void 1060 1.25 jakllsch lpcib_fwh_configure(device_t self) 1061 1.25 jakllsch { 1062 1.26 jakllsch struct lpcib_softc *sc; 1063 1.26 jakllsch pcireg_t pr; 1064 1.25 jakllsch 1065 1.26 jakllsch sc = device_private(self); 1066 1.25 jakllsch 1067 1.25 jakllsch if (sc->sc_has_rcba) { 1068 1.25 jakllsch /* 1069 1.25 jakllsch * Very unlikely to find a 82802 on a ICH6 or newer. 1070 1.25 jakllsch * Also the write enable register moved at that point. 1071 1.25 jakllsch */ 1072 1.25 jakllsch return; 1073 1.25 jakllsch } else { 1074 1.25 jakllsch /* Enable FWH write to identify FWH. */ 1075 1.25 jakllsch pr = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 1076 1.26 jakllsch LPCIB_PCI_BIOS_CNTL); 1077 1.25 jakllsch pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 1078 1.26 jakllsch LPCIB_PCI_BIOS_CNTL, pr|LPCIB_PCI_BIOS_CNTL_BWE); 1079 1.25 jakllsch } 1080 1.25 jakllsch 1081 1.53 thorpej sc->sc_fwhbus = config_found(self, NULL, NULL, 1082 1.54 thorpej CFARGS(.iattr = "fwhichbus")); 1083 1.25 jakllsch 1084 1.26 jakllsch /* restore previous write enable setting */ 1085 1.26 jakllsch pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 1086 1.26 jakllsch LPCIB_PCI_BIOS_CNTL, pr); 1087 1.25 jakllsch } 1088 1.25 jakllsch #endif 1089