1 /* $NetBSD: piixpm.c,v 1.30 2009/11/03 12:51:56 pgoyette Exp $ */
2 /* $OpenBSD: piixpm.c,v 1.20 2006/02/27 08:25:02 grange Exp $ */
5 * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Intel PIIX and compatible Power Management controller driver.
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.30 2009/11/03 12:51:56 pgoyette Exp $");
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/device.h>
30 #include <sys/kernel.h>
31 #include <sys/rwlock.h>
36 #include <dev/pci/pcidevs.h>
37 #include <dev/pci/pcireg.h>
38 #include <dev/pci/pcivar.h>
40 #include <dev/pci/piixpmreg.h>
42 #include <dev/i2c/i2cvar.h>
44 #include <dev/ic/acpipmtimer.h>
47 #define DPRINTF(x) printf x
52 #define PIIXPM_DELAY 200
53 #define PIIXPM_TIMEOUT 1
58 bus_space_tag_t sc_smb_iot
;
59 bus_space_handle_t sc_smb_ioh
;
63 bus_space_tag_t sc_pm_iot
;
64 bus_space_handle_t sc_pm_ioh
;
66 pci_chipset_tag_t sc_pc
;
69 struct i2c_controller sc_i2c_tag
;
70 krwlock_t sc_i2c_rwlock
;
79 pcireg_t sc_devact
[2];
82 static int piixpm_match(device_t
, cfdata_t
, void *);
83 static void piixpm_attach(device_t
, device_t
, void *);
85 static bool piixpm_suspend(device_t
, pmf_qual_t
);
86 static bool piixpm_resume(device_t
, pmf_qual_t
);
88 static int piixpm_i2c_acquire_bus(void *, int);
89 static void piixpm_i2c_release_bus(void *, int);
90 static int piixpm_i2c_exec(void *, i2c_op_t
, i2c_addr_t
, const void *,
91 size_t, void *, size_t, int);
93 static int piixpm_intr(void *);
95 CFATTACH_DECL_NEW(piixpm
, sizeof(struct piixpm_softc
),
96 piixpm_match
, piixpm_attach
, NULL
, NULL
);
99 piixpm_match(device_t parent
, cfdata_t match
, void *aux
)
101 struct pci_attach_args
*pa
;
103 pa
= (struct pci_attach_args
*)aux
;
104 switch (PCI_VENDOR(pa
->pa_id
)) {
105 case PCI_VENDOR_INTEL
:
106 switch (PCI_PRODUCT(pa
->pa_id
)) {
107 case PCI_PRODUCT_INTEL_82371AB_PMC
:
108 case PCI_PRODUCT_INTEL_82440MX_PMC
:
113 switch (PCI_PRODUCT(pa
->pa_id
)) {
114 case PCI_PRODUCT_ATI_SB200_SMB
:
115 case PCI_PRODUCT_ATI_SB300_SMB
:
116 case PCI_PRODUCT_ATI_SB400_SMB
:
117 case PCI_PRODUCT_ATI_SB600_SMB
: /* matches SB600/SB700/SB800 */
121 case PCI_VENDOR_SERVERWORKS
:
122 switch (PCI_PRODUCT(pa
->pa_id
)) {
123 case PCI_PRODUCT_SERVERWORKS_OSB4
:
124 case PCI_PRODUCT_SERVERWORKS_CSB5
:
125 case PCI_PRODUCT_SERVERWORKS_CSB6
:
126 case PCI_PRODUCT_SERVERWORKS_HT1000SB
:
135 piixpm_attach(device_t parent
, device_t self
, void *aux
)
137 struct piixpm_softc
*sc
= device_private(self
);
138 struct pci_attach_args
*pa
= aux
;
139 struct i2cbus_attach_args iba
;
142 pci_intr_handle_t ih
;
144 const char *intrstr
= NULL
;
147 sc
->sc_pc
= pa
->pa_pc
;
148 sc
->sc_pcitag
= pa
->pa_tag
;
153 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
154 aprint_normal_dev(self
, "%s (rev. 0x%02x)\n", devinfo
,
155 PCI_REVISION(pa
->pa_class
));
157 if (!pmf_device_register(self
, piixpm_suspend
, piixpm_resume
))
158 aprint_error_dev(self
, "couldn't establish power handler\n");
160 /* Read configuration */
161 conf
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PIIX_SMB_HOSTC
);
162 DPRINTF(("%s: conf 0x%x\n", device_xname(self
), conf
));
164 if ((PCI_VENDOR(pa
->pa_id
) != PCI_VENDOR_INTEL
) ||
165 (PCI_PRODUCT(pa
->pa_id
) != PCI_PRODUCT_INTEL_82371AB_PMC
))
166 goto nopowermanagement
;
168 /* check whether I/O access to PM regs is enabled */
169 pmmisc
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PIIX_PMREGMISC
);
171 goto nopowermanagement
;
173 sc
->sc_pm_iot
= pa
->pa_iot
;
175 base
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PIIX_PM_BASE
);
176 if (bus_space_map(sc
->sc_pm_iot
, PCI_MAPREG_IO_ADDR(base
),
177 PIIX_PM_SIZE
, 0, &sc
->sc_pm_ioh
)) {
178 aprint_error_dev(self
, "can't map power management I/O space\n");
179 goto nopowermanagement
;
183 * Revision 0 and 1 are PIIX4, 2 is PIIX4E, 3 is PIIX4M.
184 * PIIX4 and PIIX4E have a bug in the timer latch, see Errata #20
185 * in the "Specification update" (document #297738).
187 acpipmtimer_attach(self
, sc
->sc_pm_iot
, sc
->sc_pm_ioh
,
189 (PCI_REVISION(pa
->pa_class
) < 3) ? ACPIPMT_BADLATCH
: 0 );
192 if ((conf
& PIIX_SMB_HOSTC_HSTEN
) == 0) {
193 aprint_normal_dev(self
, "SMBus disabled\n");
198 sc
->sc_smb_iot
= pa
->pa_iot
;
199 base
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PIIX_SMB_BASE
) & 0xffff;
200 if (bus_space_map(sc
->sc_smb_iot
, PCI_MAPREG_IO_ADDR(base
),
201 PIIX_SMB_SIZE
, 0, &sc
->sc_smb_ioh
)) {
202 aprint_error_dev(self
, "can't map smbus I/O space\n");
207 aprint_normal_dev(self
, "");
208 if ((conf
& PIIX_SMB_HOSTC_INTMASK
) == PIIX_SMB_HOSTC_SMI
) {
210 aprint_normal("interrupting at SMI, ");
211 } else if ((conf
& PIIX_SMB_HOSTC_INTMASK
) == PIIX_SMB_HOSTC_IRQ
) {
212 /* Install interrupt handler */
213 if (pci_intr_map(pa
, &ih
) == 0) {
214 intrstr
= pci_intr_string(pa
->pa_pc
, ih
);
215 sc
->sc_smb_ih
= pci_intr_establish(pa
->pa_pc
, ih
, IPL_BIO
,
217 if (sc
->sc_smb_ih
!= NULL
) {
218 aprint_normal("interrupting at %s", intrstr
);
224 aprint_normal("polling");
229 rw_init(&sc
->sc_i2c_rwlock
);
230 sc
->sc_i2c_tag
.ic_cookie
= sc
;
231 sc
->sc_i2c_tag
.ic_acquire_bus
= piixpm_i2c_acquire_bus
;
232 sc
->sc_i2c_tag
.ic_release_bus
= piixpm_i2c_release_bus
;
233 sc
->sc_i2c_tag
.ic_exec
= piixpm_i2c_exec
;
235 memset(&iba
, 0, sizeof(iba
));
236 iba
.iba_type
= I2C_TYPE_SMBUS
;
237 iba
.iba_tag
= &sc
->sc_i2c_tag
;
238 config_found_ia(self
, "i2cbus", &iba
, iicbus_print
);
244 piixpm_suspend(device_t dv
, pmf_qual_t qual
)
246 struct piixpm_softc
*sc
= device_private(dv
);
248 sc
->sc_devact
[0] = pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
,
250 sc
->sc_devact
[1] = pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
,
257 piixpm_resume(device_t dv
, pmf_qual_t qual
)
259 struct piixpm_softc
*sc
= device_private(dv
);
261 pci_conf_write(sc
->sc_pc
, sc
->sc_pcitag
, PIIX_DEVACTA
,
263 pci_conf_write(sc
->sc_pc
, sc
->sc_pcitag
, PIIX_DEVACTB
,
270 piixpm_i2c_acquire_bus(void *cookie
, int flags
)
272 struct piixpm_softc
*sc
= cookie
;
274 if (cold
|| sc
->sc_poll
|| (flags
& I2C_F_POLL
))
277 rw_enter(&sc
->sc_i2c_rwlock
, RW_WRITER
);
282 piixpm_i2c_release_bus(void *cookie
, int flags
)
284 struct piixpm_softc
*sc
= cookie
;
286 if (cold
|| sc
->sc_poll
|| (flags
& I2C_F_POLL
))
289 rw_exit(&sc
->sc_i2c_rwlock
);
293 piixpm_i2c_exec(void *cookie
, i2c_op_t op
, i2c_addr_t addr
,
294 const void *cmdbuf
, size_t cmdlen
, void *buf
, size_t len
, int flags
)
296 struct piixpm_softc
*sc
= cookie
;
298 u_int8_t ctl
= 0, st
;
301 DPRINTF(("%s: exec: op %d, addr 0x%x, cmdlen %d, len %d, flags 0x%x\n",
302 device_xname(sc
->sc_dev
), op
, addr
, cmdlen
, len
, flags
));
304 /* Wait for bus to be idle */
305 for (retries
= 100; retries
> 0; retries
--) {
306 st
= bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
308 if (!(st
& PIIX_SMB_HS_BUSY
))
312 DPRINTF(("%s: exec: st 0x%d\n", device_xname(sc
->sc_dev
), st
& 0xff));
313 if (st
& PIIX_SMB_HS_BUSY
)
316 if (cold
|| sc
->sc_poll
)
319 if (!I2C_OP_STOP_P(op
) || cmdlen
> 1 || len
> 2)
323 sc
->sc_i2c_xfer
.op
= op
;
324 sc
->sc_i2c_xfer
.buf
= buf
;
325 sc
->sc_i2c_xfer
.len
= len
;
326 sc
->sc_i2c_xfer
.flags
= flags
;
327 sc
->sc_i2c_xfer
.error
= 0;
329 /* Set slave address and transfer direction */
330 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_TXSLVA
,
331 PIIX_SMB_TXSLVA_ADDR(addr
) |
332 (I2C_OP_READ_P(op
) ? PIIX_SMB_TXSLVA_READ
: 0));
336 /* Set command byte */
337 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
338 PIIX_SMB_HCMD
, b
[0]);
340 if (I2C_OP_WRITE_P(op
)) {
344 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
347 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
351 /* Set SMBus command */
354 ctl
= PIIX_SMB_HC_CMD_QUICK
;
356 ctl
= PIIX_SMB_HC_CMD_BYTE
;
358 ctl
= PIIX_SMB_HC_CMD_BDATA
;
360 ctl
= PIIX_SMB_HC_CMD_WDATA
;
362 if ((flags
& I2C_F_POLL
) == 0)
363 ctl
|= PIIX_SMB_HC_INTREN
;
365 /* Start transaction */
366 ctl
|= PIIX_SMB_HC_START
;
367 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HC
, ctl
);
369 if (flags
& I2C_F_POLL
) {
370 /* Poll for completion */
372 for (retries
= 1000; retries
> 0; retries
--) {
373 st
= bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
375 if ((st
& PIIX_SMB_HS_BUSY
) == 0)
379 if (st
& PIIX_SMB_HS_BUSY
)
383 /* Wait for interrupt */
384 if (tsleep(sc
, PRIBIO
, "iicexec", PIIXPM_TIMEOUT
* hz
))
388 if (sc
->sc_i2c_xfer
.error
)
395 * Transfer timeout. Kill the transaction and clear status bits.
397 aprint_error_dev(sc
->sc_dev
, "timeout, status 0x%x\n", st
);
398 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HC
,
401 st
= bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HS
);
402 if ((st
& PIIX_SMB_HS_FAILED
) == 0)
403 aprint_error_dev(sc
->sc_dev
, "transaction abort failed, status 0x%x\n", st
);
404 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HS
, st
);
409 piixpm_intr(void *arg
)
411 struct piixpm_softc
*sc
= arg
;
417 st
= bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HS
);
418 if ((st
& PIIX_SMB_HS_BUSY
) != 0 || (st
& (PIIX_SMB_HS_INTR
|
419 PIIX_SMB_HS_DEVERR
| PIIX_SMB_HS_BUSERR
|
420 PIIX_SMB_HS_FAILED
)) == 0)
421 /* Interrupt was not for us */
424 DPRINTF(("%s: intr st 0x%d\n", device_xname(sc
->sc_dev
), st
& 0xff));
426 /* Clear status bits */
427 bus_space_write_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
, PIIX_SMB_HS
, st
);
429 /* Check for errors */
430 if (st
& (PIIX_SMB_HS_DEVERR
| PIIX_SMB_HS_BUSERR
|
431 PIIX_SMB_HS_FAILED
)) {
432 sc
->sc_i2c_xfer
.error
= 1;
436 if (st
& PIIX_SMB_HS_INTR
) {
437 if (I2C_OP_WRITE_P(sc
->sc_i2c_xfer
.op
))
441 b
= sc
->sc_i2c_xfer
.buf
;
442 len
= sc
->sc_i2c_xfer
.len
;
444 b
[0] = bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
447 b
[1] = bus_space_read_1(sc
->sc_smb_iot
, sc
->sc_smb_ioh
,
452 if ((sc
->sc_i2c_xfer
.flags
& I2C_F_POLL
) == 0)