1 /* $NetBSD: ichsmb.c,v 1.20 2009/03/18 16:00:19 cegger Exp $ */
2 /* $OpenBSD: ichiic.c,v 1.18 2007/05/03 09:36:26 dlg 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 ICH SMBus controller driver.
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.20 2009/03/18 16:00:19 cegger Exp $");
27 #include <sys/param.h>
28 #include <sys/device.h>
29 #include <sys/errno.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/ic/i82801lpcreg.h>
42 #include <dev/i2c/i2cvar.h>
45 #define DPRINTF(x) printf x
50 #define ICHIIC_DELAY 100
51 #define ICHIIC_TIMEOUT 1
56 bus_space_tag_t sc_iot
;
57 bus_space_handle_t sc_ioh
;
61 struct i2c_controller sc_i2c_tag
;
62 krwlock_t sc_i2c_rwlock
;
72 static int ichsmb_match(device_t
, cfdata_t
, void *);
73 static void ichsmb_attach(device_t
, device_t
, void *);
75 static int ichsmb_i2c_acquire_bus(void *, int);
76 static void ichsmb_i2c_release_bus(void *, int);
77 static int ichsmb_i2c_exec(void *, i2c_op_t
, i2c_addr_t
, const void *,
78 size_t, void *, size_t, int);
80 static int ichsmb_intr(void *);
83 CFATTACH_DECL_NEW(ichsmb
, sizeof(struct ichsmb_softc
),
84 ichsmb_match
, ichsmb_attach
, NULL
, NULL
);
88 ichsmb_match(device_t parent
, cfdata_t match
, void *aux
)
90 struct pci_attach_args
*pa
= aux
;
92 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_INTEL
) {
93 switch (PCI_PRODUCT(pa
->pa_id
)) {
94 case PCI_PRODUCT_INTEL_6300ESB_SMB
:
95 case PCI_PRODUCT_INTEL_63XXESB_SMB
:
96 case PCI_PRODUCT_INTEL_82801AA_SMB
:
97 case PCI_PRODUCT_INTEL_82801AB_SMB
:
98 case PCI_PRODUCT_INTEL_82801BA_SMB
:
99 case PCI_PRODUCT_INTEL_82801CA_SMB
:
100 case PCI_PRODUCT_INTEL_82801DB_SMB
:
101 case PCI_PRODUCT_INTEL_82801E_SMB
:
102 case PCI_PRODUCT_INTEL_82801EB_SMB
:
103 case PCI_PRODUCT_INTEL_82801FB_SMB
:
104 case PCI_PRODUCT_INTEL_82801G_SMB
:
105 case PCI_PRODUCT_INTEL_82801H_SMB
:
106 case PCI_PRODUCT_INTEL_82801I_SMB
:
107 case PCI_PRODUCT_INTEL_ICH10_SMB1
:
108 case PCI_PRODUCT_INTEL_ICH10_SMB2
:
116 ichsmb_attach(device_t parent
, device_t self
, void *aux
)
118 struct ichsmb_softc
*sc
= device_private(self
);
119 struct pci_attach_args
*pa
= aux
;
120 struct i2cbus_attach_args iba
;
123 pci_intr_handle_t ih
;
124 const char *intrstr
= NULL
;
130 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
131 aprint_normal(": %s (rev. 0x%02x)\n", devinfo
,
132 PCI_REVISION(pa
->pa_class
));
134 /* Read configuration */
135 conf
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, LPCIB_SMB_HOSTC
);
136 DPRINTF(("%s: conf 0x%08x\n", device_xname(sc
->sc_dev
), conf
));
138 if ((conf
& LPCIB_SMB_HOSTC_HSTEN
) == 0) {
139 aprint_error_dev(self
, "SMBus disabled\n");
144 if (pci_mapreg_map(pa
, LPCIB_SMB_BASE
, PCI_MAPREG_TYPE_IO
, 0,
145 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, &iosize
)) {
146 aprint_error_dev(self
, "can't map I/O space\n");
151 if (conf
& LPCIB_SMB_HOSTC_SMIEN
) {
153 aprint_normal_dev(self
, "interrupting at SMI\n");
155 /* Install interrupt handler */
156 if (pci_intr_map(pa
, &ih
) == 0) {
157 intrstr
= pci_intr_string(pa
->pa_pc
, ih
);
158 sc
->sc_ih
= pci_intr_establish(pa
->pa_pc
, ih
, IPL_BIO
,
160 if (sc
->sc_ih
!= NULL
) {
161 aprint_normal_dev(self
, "interrupting at %s\n",
167 aprint_normal_dev(self
, "polling\n");
171 rw_init(&sc
->sc_i2c_rwlock
);
172 sc
->sc_i2c_tag
.ic_cookie
= sc
;
173 sc
->sc_i2c_tag
.ic_acquire_bus
= ichsmb_i2c_acquire_bus
;
174 sc
->sc_i2c_tag
.ic_release_bus
= ichsmb_i2c_release_bus
;
175 sc
->sc_i2c_tag
.ic_exec
= ichsmb_i2c_exec
;
177 memset(&iba
, 0, sizeof(iba
));
178 iba
.iba_type
= I2C_TYPE_SMBUS
;
179 iba
.iba_tag
= &sc
->sc_i2c_tag
;
180 config_found(self
, &iba
, iicbus_print
);
182 if (!pmf_device_register(self
, NULL
, NULL
))
183 aprint_error_dev(self
, "couldn't establish power handler\n");
187 ichsmb_i2c_acquire_bus(void *cookie
, int flags
)
189 struct ichsmb_softc
*sc
= cookie
;
191 if (cold
|| sc
->sc_poll
|| (flags
& I2C_F_POLL
))
194 rw_enter(&sc
->sc_i2c_rwlock
, RW_WRITER
);
199 ichsmb_i2c_release_bus(void *cookie
, int flags
)
201 struct ichsmb_softc
*sc
= cookie
;
203 if (cold
|| sc
->sc_poll
|| (flags
& I2C_F_POLL
))
206 rw_exit(&sc
->sc_i2c_rwlock
);
210 ichsmb_i2c_exec(void *cookie
, i2c_op_t op
, i2c_addr_t addr
,
211 const void *cmdbuf
, size_t cmdlen
, void *buf
, size_t len
, int flags
)
213 struct ichsmb_softc
*sc
= cookie
;
219 DPRINTF(("%s: exec: op %d, addr 0x%02x, cmdlen %zu, len %zu, "
220 "flags 0x%02x\n", device_xname(sc
->sc_dev
), op
, addr
, cmdlen
,
223 /* Wait for bus to be idle */
224 for (retries
= 100; retries
> 0; retries
--) {
225 st
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HS
);
226 if (!(st
& LPCIB_SMB_HS_BUSY
))
231 snprintb(fbuf
, sizeof(fbuf
), LPCIB_SMB_HS_BITS
, st
);
232 printf("%s: exec: st 0x%s\n", device_xname(sc
->sc_dev
), fbuf
);
234 if (st
& LPCIB_SMB_HS_BUSY
)
237 if (cold
|| sc
->sc_poll
)
240 if (!I2C_OP_STOP_P(op
) || cmdlen
> 1 || len
> 2)
244 sc
->sc_i2c_xfer
.op
= op
;
245 sc
->sc_i2c_xfer
.buf
= buf
;
246 sc
->sc_i2c_xfer
.len
= len
;
247 sc
->sc_i2c_xfer
.flags
= flags
;
248 sc
->sc_i2c_xfer
.error
= 0;
250 /* Set slave address and transfer direction */
251 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_TXSLVA
,
252 LPCIB_SMB_TXSLVA_ADDR(addr
) |
253 (I2C_OP_READ_P(op
) ? LPCIB_SMB_TXSLVA_READ
: 0));
255 b
= (const uint8_t *)cmdbuf
;
257 /* Set command byte */
258 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HCMD
, b
[0]);
260 if (I2C_OP_WRITE_P(op
)) {
264 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
,
265 LPCIB_SMB_HD0
, b
[0]);
267 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
,
268 LPCIB_SMB_HD1
, b
[1]);
271 /* Set SMBus command */
274 ctl
= LPCIB_SMB_HC_CMD_QUICK
;
276 ctl
= LPCIB_SMB_HC_CMD_BYTE
;
278 ctl
= LPCIB_SMB_HC_CMD_BDATA
;
280 ctl
= LPCIB_SMB_HC_CMD_WDATA
;
282 if ((flags
& I2C_F_POLL
) == 0)
283 ctl
|= LPCIB_SMB_HC_INTREN
;
285 /* Start transaction */
286 ctl
|= LPCIB_SMB_HC_START
;
287 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HC
, ctl
);
289 if (flags
& I2C_F_POLL
) {
290 /* Poll for completion */
292 for (retries
= 1000; retries
> 0; retries
--) {
293 st
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
,
295 if ((st
& LPCIB_SMB_HS_BUSY
) == 0)
299 if (st
& LPCIB_SMB_HS_BUSY
)
303 /* Wait for interrupt */
304 if (tsleep(sc
, PRIBIO
, "iicexec", ICHIIC_TIMEOUT
* hz
))
308 if (sc
->sc_i2c_xfer
.error
)
315 * Transfer timeout. Kill the transaction and clear status bits.
317 snprintb(fbuf
, sizeof(fbuf
), LPCIB_SMB_HS_BITS
, st
);
318 aprint_error_dev(sc
->sc_dev
,
319 "exec: op %d, addr 0x%02x, cmdlen %zd, len %zd, "
320 "flags 0x%02x: timeout, status 0x%s\n",
321 op
, addr
, cmdlen
, len
, flags
, fbuf
);
322 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HC
,
325 st
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HS
);
326 if ((st
& LPCIB_SMB_HS_FAILED
) == 0) {
327 snprintb(fbuf
, sizeof(fbuf
), LPCIB_SMB_HS_BITS
, st
);
328 aprint_error_dev(sc
->sc_dev
, "abort failed, status 0x%s\n",
331 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HS
, st
);
336 ichsmb_intr(void *arg
)
338 struct ichsmb_softc
*sc
= arg
;
347 st
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HS
);
348 if ((st
& LPCIB_SMB_HS_BUSY
) != 0 || (st
& (LPCIB_SMB_HS_INTR
|
349 LPCIB_SMB_HS_DEVERR
| LPCIB_SMB_HS_BUSERR
| LPCIB_SMB_HS_FAILED
|
350 LPCIB_SMB_HS_SMBAL
| LPCIB_SMB_HS_BDONE
)) == 0)
351 /* Interrupt was not for us */
355 snprintb(fbuf
, sizeof(fbuf
), LPCIB_SMB_HS_BITS
, st
);
356 printf("%s: intr st 0x%s\n", device_xname(sc
->sc_dev
), fbuf
);
359 /* Clear status bits */
360 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LPCIB_SMB_HS
, st
);
362 /* Check for errors */
363 if (st
& (LPCIB_SMB_HS_DEVERR
| LPCIB_SMB_HS_BUSERR
| LPCIB_SMB_HS_FAILED
)) {
364 sc
->sc_i2c_xfer
.error
= 1;
368 if (st
& LPCIB_SMB_HS_INTR
) {
369 if (I2C_OP_WRITE_P(sc
->sc_i2c_xfer
.op
))
373 b
= sc
->sc_i2c_xfer
.buf
;
374 len
= sc
->sc_i2c_xfer
.len
;
376 b
[0] = bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
,
379 b
[1] = bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
,
384 if ((sc
->sc_i2c_xfer
.flags
& I2C_F_POLL
) == 0)