xref: /netbsd-src/sys/dev/pci/ichsmb.c (revision 28fb9d4114714f483a944986436de3756dbf781f)
1 /*	$NetBSD: ichsmb.c,v 1.86 2025/01/18 08:12:13 mrg Exp $	*/
2 /*	$OpenBSD: ichiic.c,v 1.44 2020/10/07 11:23:05 jsg Exp $	*/
3 
4 /*
5  * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org>
6  *
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.
10  *
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.
18  */
19 
20 /*
21  * Intel ICH SMBus controller driver.
22  */
23 
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.86 2025/01/18 08:12:13 mrg Exp $");
26 
27 #include <sys/param.h>
28 #include <sys/device.h>
29 #include <sys/errno.h>
30 #include <sys/kernel.h>
31 #include <sys/mutex.h>
32 #include <sys/condvar.h>
33 #include <sys/module.h>
34 
35 #include <sys/bus.h>
36 
37 #include <dev/pci/pcidevs.h>
38 #include <dev/pci/pcireg.h>
39 #include <dev/pci/pcivar.h>
40 
41 #include <dev/ic/i82801lpcreg.h>
42 
43 #include <dev/i2c/i2cvar.h>
44 
45 #include <x86/pci/tco.h>
46 
47 #ifdef ICHIIC_DEBUG
48 #define DPRINTF(x) printf x
49 #else
50 #define DPRINTF(x)
51 #endif
52 
53 #define ICHIIC_DELAY	100
54 #define ICHIIC_TIMEOUT	1
55 
56 struct ichsmb_softc {
57 	device_t		sc_dev;
58 
59 	bus_space_tag_t		sc_iot;
60 	bus_space_handle_t	sc_ioh;
61 	bus_size_t		sc_size;
62 	pci_chipset_tag_t	sc_pc;
63 	void *			sc_ih;
64 	int			sc_poll;
65 	pci_intr_handle_t	*sc_pihp;
66 
67 	kmutex_t		sc_exec_lock;
68 	kcondvar_t		sc_exec_wait;
69 
70 	struct i2c_controller	sc_i2c_tag;
71 	struct {
72 		i2c_op_t     op;
73 		void *       buf;
74 		size_t       len;
75 		int          flags;
76 		int          error;
77 		bool         done;
78 	}			sc_i2c_xfer;
79 	device_t		sc_i2c_device;
80 
81 	bus_space_tag_t		sc_tcot;
82 	bus_space_handle_t	sc_tcoh;
83 	bus_size_t		sc_tcosz;
84 	bus_space_tag_t		sc_sbregt;
85 	bus_space_handle_t	sc_sbregh;
86 	bus_size_t		sc_sbregsz;
87 	bus_space_tag_t		sc_pmt;
88 	bus_space_handle_t	sc_pmh;
89 	bus_size_t		sc_pmsz;
90 	bool			sc_tco_probed;
91 	device_t		sc_tco_device;
92 };
93 
94 static int	ichsmb_match(device_t, cfdata_t, void *);
95 static void	ichsmb_attach(device_t, device_t, void *);
96 static int	ichsmb_detach(device_t, int);
97 static int	ichsmb_rescan(device_t, const char *, const int *);
98 static void	ichsmb_chdet(device_t, device_t);
99 
100 static void	ichsmb_probe_tco(struct ichsmb_softc *,
101 		    const struct pci_attach_args *);
102 
103 static int	ichsmb_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
104 		    size_t, void *, size_t, int);
105 
106 static int	ichsmb_intr(void *);
107 
108 #include "ioconf.h"
109 
110 CFATTACH_DECL3_NEW(ichsmb, sizeof(struct ichsmb_softc),
111     ichsmb_match, ichsmb_attach, ichsmb_detach, NULL, ichsmb_rescan,
112     ichsmb_chdet, DVF_DETACH_SHUTDOWN);
113 
114 
115 static int
116 ichsmb_match(device_t parent, cfdata_t match, void *aux)
117 {
118 	struct pci_attach_args *pa = aux;
119 
120 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) {
121 		switch (PCI_PRODUCT(pa->pa_id)) {
122 		case PCI_PRODUCT_INTEL_6300ESB_SMB:
123 		case PCI_PRODUCT_INTEL_63XXESB_SMB:
124 		case PCI_PRODUCT_INTEL_82801AA_SMB:
125 		case PCI_PRODUCT_INTEL_82801AB_SMB:
126 		case PCI_PRODUCT_INTEL_82801BA_SMB:
127 		case PCI_PRODUCT_INTEL_82801CA_SMB:
128 		case PCI_PRODUCT_INTEL_82801DB_SMB:
129 		case PCI_PRODUCT_INTEL_82801E_SMB:
130 		case PCI_PRODUCT_INTEL_82801EB_SMB:
131 		case PCI_PRODUCT_INTEL_82801FB_SMB:
132 		case PCI_PRODUCT_INTEL_82801G_SMB:
133 		case PCI_PRODUCT_INTEL_82801H_SMB:
134 		case PCI_PRODUCT_INTEL_82801I_SMB:
135 		case PCI_PRODUCT_INTEL_82801JD_SMB:
136 		case PCI_PRODUCT_INTEL_82801JI_SMB:
137 		case PCI_PRODUCT_INTEL_3400_SMB:
138 		case PCI_PRODUCT_INTEL_6SERIES_SMB:
139 		case PCI_PRODUCT_INTEL_7SERIES_SMB:
140 		case PCI_PRODUCT_INTEL_8SERIES_SMB:
141 		case PCI_PRODUCT_INTEL_9SERIES_SMB:
142 		case PCI_PRODUCT_INTEL_100SERIES_SMB:
143 		case PCI_PRODUCT_INTEL_100SERIES_LP_SMB:
144 		case PCI_PRODUCT_INTEL_2HS_SMB:
145 		case PCI_PRODUCT_INTEL_3HS_SMB:
146 		case PCI_PRODUCT_INTEL_3HS_U_SMB:
147 		case PCI_PRODUCT_INTEL_4HS_H_SMB:
148 		case PCI_PRODUCT_INTEL_4HS_V_SMB:
149 		case PCI_PRODUCT_INTEL_CORE4G_M_SMB:
150 		case PCI_PRODUCT_INTEL_CORE5G_M_SMB:
151 		case PCI_PRODUCT_INTEL_CMTLK_SMB:
152 		case PCI_PRODUCT_INTEL_BAYTRAIL_PCU_SMB:
153 		case PCI_PRODUCT_INTEL_BSW_PCU_SMB:
154 		case PCI_PRODUCT_INTEL_APL_SMB:
155 		case PCI_PRODUCT_INTEL_GLK_SMB:
156 		case PCI_PRODUCT_INTEL_EHL_SMB:
157 		case PCI_PRODUCT_INTEL_JSL_SMB:
158 		case PCI_PRODUCT_INTEL_SNR_SMB_LEGACY:
159 		case PCI_PRODUCT_INTEL_ADL_N_SMB:
160 		case PCI_PRODUCT_INTEL_C600_SMBUS:
161 		case PCI_PRODUCT_INTEL_C600_SMB_0:
162 		case PCI_PRODUCT_INTEL_C600_SMB_1:
163 		case PCI_PRODUCT_INTEL_C600_SMB_2:
164 		case PCI_PRODUCT_INTEL_C610_SMB:
165 		case PCI_PRODUCT_INTEL_C620_SMB:
166 		case PCI_PRODUCT_INTEL_C620_SMB_S:
167 		case PCI_PRODUCT_INTEL_EP80579_SMB:
168 		case PCI_PRODUCT_INTEL_DH89XXCC_SMB:
169 		case PCI_PRODUCT_INTEL_DH89XXCL_SMB:
170 		case PCI_PRODUCT_INTEL_C2000_PCU_SMBUS:
171 		case PCI_PRODUCT_INTEL_C3K_SMBUS_LEGACY:
172 		case PCI_PRODUCT_INTEL_495_YU_SMB:
173 		case PCI_PRODUCT_INTEL_5HS_H_SMB:
174 		case PCI_PRODUCT_INTEL_5HS_LP_SMB:
175 		case PCI_PRODUCT_INTEL_6HS_H_SMB:
176 		case PCI_PRODUCT_INTEL_6HS_LP_SMB:
177 		case PCI_PRODUCT_INTEL_7HS_SMB:
178 		case PCI_PRODUCT_INTEL_SMBUS_MTL:
179 			return 1;
180 		}
181 	}
182 	return 0;
183 }
184 
185 static void
186 ichsmb_attach(device_t parent, device_t self, void *aux)
187 {
188 	struct ichsmb_softc *sc = device_private(self);
189 	struct pci_attach_args *pa = aux;
190 	pcireg_t conf;
191 	const char *intrstr = NULL;
192 	char intrbuf[PCI_INTRSTR_LEN];
193 
194 	sc->sc_dev = self;
195 	sc->sc_pc = pa->pa_pc;
196 
197 	pci_aprint_devinfo(pa, NULL);
198 
199 	mutex_init(&sc->sc_exec_lock, MUTEX_DEFAULT, IPL_BIO);
200 	cv_init(&sc->sc_exec_wait, device_xname(self));
201 
202 	/* Read configuration */
203 	conf = pci_conf_read(pa->pa_pc, pa->pa_tag, SMB_HOSTC);
204 	DPRINTF(("%s: conf 0x%08x\n", device_xname(sc->sc_dev), conf));
205 
206 	if ((conf & SMB_HOSTC_HSTEN) == 0) {
207 		aprint_error_dev(self, "SMBus disabled\n");
208 		goto out;
209 	}
210 
211 	/* Map I/O space */
212 	if (pci_mapreg_map(pa, SMB_BASE, PCI_MAPREG_TYPE_IO, 0,
213 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size)) {
214 		aprint_error_dev(self, "can't map I/O space\n");
215 		goto out;
216 	}
217 
218 	sc->sc_poll = 1;
219 	sc->sc_ih = NULL;
220 	if (conf & SMB_HOSTC_SMIEN) {
221 		/* No PCI IRQ */
222 		aprint_normal_dev(self, "interrupting at SMI\n");
223 	} else {
224 		/* Install interrupt handler */
225 		if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0) == 0) {
226 			intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0],
227 			    intrbuf, sizeof(intrbuf));
228 			pci_intr_setattr(pa->pa_pc, &sc->sc_pihp[0],
229 			    PCI_INTR_MPSAFE, true);
230 			sc->sc_ih = pci_intr_establish_xname(pa->pa_pc,
231 			    sc->sc_pihp[0], IPL_BIO, ichsmb_intr, sc,
232 			    device_xname(sc->sc_dev));
233 			if (sc->sc_ih != NULL) {
234 				aprint_normal_dev(self, "interrupting at %s\n",
235 				    intrstr);
236 				sc->sc_poll = 0;
237 			} else {
238 				pci_intr_release(pa->pa_pc, sc->sc_pihp, 1);
239 				sc->sc_pihp = NULL;
240 			}
241 		}
242 		if (sc->sc_poll)
243 			aprint_normal_dev(self, "polling\n");
244 	}
245 
246 	/* Attach I2C bus */
247 	iic_tag_init(&sc->sc_i2c_tag);
248 	sc->sc_i2c_tag.ic_cookie = sc;
249 	sc->sc_i2c_tag.ic_exec = ichsmb_i2c_exec;
250 
251 	/*
252 	 * Probe to see if there's a TCO hanging here instead of the
253 	 * LPCIB and map it if we can.
254 	 */
255 	ichsmb_probe_tco(sc, pa);
256 
257 	sc->sc_i2c_device = NULL;
258 	ichsmb_rescan(self, NULL, NULL);
259 
260 out:	if (!pmf_device_register(self, NULL, NULL))
261 		aprint_error_dev(self, "couldn't establish power handler\n");
262 }
263 
264 static void
265 ichsmb_probe_tco(struct ichsmb_softc *sc, const struct pci_attach_args *pa)
266 {
267 	const device_t self = sc->sc_dev;
268 	const pci_chipset_tag_t pc = sc->sc_pc;
269 	const pcitag_t p2sb_tag = pci_make_tag(pc,
270 	    /*bus*/0, /*dev*/0x1f, /*fn*/1);
271 	const pcitag_t pmc_tag = pci_make_tag(pc,
272 	    /*bus*/0, /*dev*/0x1f, /*fn*/2);
273 	pcireg_t tcoctl, tcobase, p2sbc, sbreglo, sbreghi;
274 	bus_addr_t sbreg, pmbase;
275 	int error = EIO;
276 
277 	/*
278 	 * Only attempt this on devices where we expect to find a TCO.
279 	 */
280 	switch (PCI_PRODUCT(pa->pa_id)) {
281 	case PCI_PRODUCT_INTEL_100SERIES_LP_SMB:
282 	case PCI_PRODUCT_INTEL_100SERIES_SMB:
283 		break;
284 	default:
285 		goto fail;
286 	}
287 
288 	/*
289 	 * Verify the TCO base address register is enabled.
290 	 */
291 	tcoctl = pci_conf_read(pa->pa_pc, pa->pa_tag, SMB_TCOCTL);
292 	aprint_debug_dev(self, "TCOCTL=0x%"PRIx32"\n", tcoctl);
293 	if ((tcoctl & SMB_TCOCTL_TCO_BASE_EN) == 0) {
294 		aprint_debug_dev(self, "TCO disabled\n");
295 		goto fail;
296 	}
297 
298 	/*
299 	 * Verify the TCO base address register has the I/O space bit
300 	 * set -- otherwise we don't know how to interpret the
301 	 * register.
302 	 */
303 	tcobase = pci_conf_read(pa->pa_pc, pa->pa_tag, SMB_TCOBASE);
304 	aprint_debug_dev(self, "TCOBASE=0x%"PRIx32"\n", tcobase);
305 	if ((tcobase & SMB_TCOBASE_IOS) == 0) {
306 		aprint_error_dev(self, "unrecognized TCO space\n");
307 		goto fail;
308 	}
309 
310 	/*
311 	 * Map the TCO I/O space.
312 	 */
313 	sc->sc_tcot = sc->sc_iot;
314 	error = bus_space_map(sc->sc_tcot, tcobase & SMB_TCOBASE_TCOBA,
315 	    TCO_REGSIZE, 0, &sc->sc_tcoh);
316 	if (error) {
317 		aprint_error_dev(self, "failed to map TCO: %d\n", error);
318 		goto fail;
319 	}
320 	sc->sc_tcosz = TCO_REGSIZE;
321 
322 	/*
323 	 * Clear the Hide Device bit so we can map the SBREG_BAR from
324 	 * the P2SB registers; then restore the Hide Device bit so
325 	 * nobody else gets confused.
326 	 *
327 	 * XXX Hope nobody else is trying to touch the P2SB!
328 	 *
329 	 * XXX Should we have a way to lock PCI bus enumeration,
330 	 * e.g. from concurrent drvctl rescan?
331 	 *
332 	 * XXX pci_mapreg_info doesn't work to get the size, somehow
333 	 * comes out as 4.  Datasheet for 100-series chipset says the
334 	 * size is 16 MB, unconditionally, and the type is memory.
335 	 *
336 	 * XXX The above XXX comment was probably a result of PEBCAK
337 	 * when I tried to use 0xe4 instead of 0xe0 for P2SBC -- should
338 	 * try again with pci_mapreg_info or pci_mapreg_map.
339 	 */
340 	p2sbc = pci_conf_read(pc, p2sb_tag, P2SB_P2SBC);
341 	aprint_debug_dev(self, "P2SBC=0x%x\n", p2sbc);
342 	pci_conf_write(pc, p2sb_tag, P2SB_P2SBC, p2sbc & ~P2SB_P2SBC_HIDE);
343 	aprint_debug_dev(self, "P2SBC=0x%x -> 0x%x\n", p2sbc,
344 	    pci_conf_read(pc, p2sb_tag, P2SB_P2SBC));
345 	sbreglo = pci_conf_read(pc, p2sb_tag, P2SB_SBREG_BAR);
346 	sbreghi = pci_conf_read(pc, p2sb_tag, P2SB_SBREG_BARH);
347 	aprint_debug_dev(self, "SBREG_BAR=0x%08x 0x%08x\n", sbreglo, sbreghi);
348 	pci_conf_write(sc->sc_pc, p2sb_tag, P2SB_P2SBC, p2sbc);
349 
350 	/*
351 	 * Map the sideband registers so we can touch the NO_REBOOT
352 	 * bit.
353 	 */
354 	sbreg = ((uint64_t)sbreghi << 32) | (sbreglo & ~__BITS(0,3));
355 	if (((uint64_t)sbreg >> 32) != sbreghi) {
356 		/* paranoia for 32-bit non-PAE */
357 		aprint_error_dev(self, "can't map 64-bit SBREG\n");
358 		goto fail;
359 	}
360 	sc->sc_sbregt = pa->pa_memt;
361 	error = bus_space_map(sc->sc_sbregt, sbreg + SB_SMBUS_BASE,
362 	    SB_SMBUS_SIZE, 0, &sc->sc_sbregh);
363 	if (error) {
364 		aprint_error_dev(self, "failed to map SMBUS sideband: %d\n",
365 		    error);
366 		goto fail;
367 	}
368 	sc->sc_sbregsz = SB_SMBUS_SIZE;
369 
370 	/*
371 	 * Map the power management configuration controller's I/O
372 	 * space.  Older manual call this PMBASE for power management;
373 	 * newer manuals call it ABASE for ACPI.  The chapters
374 	 * describing the registers say `power management' and I can't
375 	 * find any connection to ACPI (I suppose ACPI firmware logic
376 	 * probably peeks and pokes registers here?) so we say PMBASE
377 	 * here.
378 	 *
379 	 * XXX Hope nobody else is trying to touch it!
380 	 */
381 	pmbase = pci_conf_read(pc, pmc_tag, LPCIB_PCI_PMBASE);
382 	aprint_debug_dev(self, "PMBASE=0x%"PRIxBUSADDR"\n", pmbase);
383 	if ((pmbase & 1) != 1) {	/* I/O space bit? */
384 		aprint_error_dev(self, "unrecognized PMC space\n");
385 		goto fail;
386 	}
387 	sc->sc_pmt = sc->sc_iot;
388 	error = bus_space_map(sc->sc_pmt, PCI_MAPREG_IO_ADDR(pmbase),
389 	    LPCIB_PCI_PM_SIZE, 0, &sc->sc_pmh);
390 	if (error) {
391 		aprint_error_dev(self, "failed to map PMC space: %d\n", error);
392 		goto fail;
393 	}
394 	sc->sc_pmsz = LPCIB_PCI_PM_SIZE;
395 
396 	/* Success! */
397 	sc->sc_tco_probed = true;
398 	return;
399 
400 fail:	if (sc->sc_pmsz) {
401 		bus_space_unmap(sc->sc_pmt, sc->sc_pmh, sc->sc_pmsz);
402 		sc->sc_pmsz = 0;
403 	}
404 	if (sc->sc_sbregsz) {
405 		bus_space_unmap(sc->sc_sbregt, sc->sc_sbregh, sc->sc_sbregsz);
406 		sc->sc_sbregsz = 0;
407 	}
408 	if (sc->sc_tcosz) {
409 		bus_space_unmap(sc->sc_tcot, sc->sc_tcoh, sc->sc_tcosz);
410 		sc->sc_tcosz = 0;
411 	}
412 }
413 
414 static int
415 ichsmb_tco_set_noreboot(device_t tco, bool noreboot)
416 {
417 	device_t self = device_parent(tco);
418 	struct ichsmb_softc *sc = device_private(self);
419 	uint32_t gc, gc1;
420 
421 	KASSERTMSG(tco == sc->sc_tco_device || sc->sc_tco_device == NULL,
422 	    "tco=%p child=%p", tco, sc->sc_tco_device);
423 	KASSERTMSG(device_is_a(self, "ichsmb"), "%s@%s",
424 	    device_xname(tco), device_xname(self));
425 
426 	/*
427 	 * Try to clear the No Reboot bit.
428 	 */
429 	gc = bus_space_read_4(sc->sc_sbregt, sc->sc_sbregh, SB_SMBUS_GC);
430 	if (noreboot)
431 		gc |= SB_SMBUS_GC_NR;
432 	else
433 		gc &= ~SB_SMBUS_GC_NR;
434 	bus_space_write_4(sc->sc_sbregt, sc->sc_sbregh, SB_SMBUS_GC, gc);
435 
436 	/*
437 	 * Check whether we could make it what we want.
438 	 */
439 	gc1 = bus_space_read_4(sc->sc_sbregt, sc->sc_sbregh, SB_SMBUS_GC);
440 	aprint_debug_dev(self, "gc=0x%x -> 0x%x\n", gc, gc1);
441 	if ((gc1 & SB_SMBUS_GC_NR) != (gc & SB_SMBUS_GC_NR))
442 		return ENODEV;
443 	return 0;
444 }
445 
446 static int
447 ichsmb_rescan(device_t self, const char *ifattr, const int *locators)
448 {
449 	struct ichsmb_softc *sc = device_private(self);
450 
451 	if (ifattr_match(ifattr, "i2cbus") && sc->sc_i2c_device == NULL) {
452 		struct i2cbus_attach_args iba;
453 
454 		memset(&iba, 0, sizeof(iba));
455 		iba.iba_tag = &sc->sc_i2c_tag;
456 		sc->sc_i2c_device = config_found(self, &iba, iicbus_print,
457 		    CFARGS(.iattr = "i2cbus"));
458 	}
459 	if (sc->sc_tco_probed &&
460 	    ifattr_match(ifattr, "tcoichbus") &&
461 	    sc->sc_tco_device == NULL) {
462 		struct tco_attach_args ta;
463 
464 		memset(&ta, 0, sizeof(ta));
465 		ta.ta_version = TCO_VERSION_SMBUS;
466 		ta.ta_pmt = sc->sc_pmt;
467 		ta.ta_pmh = sc->sc_pmh;
468 		ta.ta_tcot = sc->sc_tcot;
469 		ta.ta_tcoh = sc->sc_tcoh;
470 		ta.ta_set_noreboot = &ichsmb_tco_set_noreboot;
471 		sc->sc_tco_device = config_found(self, &ta, NULL,
472 		    CFARGS(.iattr = "tcoichbus"));
473 	}
474 
475 	return 0;
476 }
477 
478 static int
479 ichsmb_detach(device_t self, int flags)
480 {
481 	struct ichsmb_softc *sc = device_private(self);
482 	int error;
483 
484 	error = config_detach_children(self, flags);
485 	if (error)
486 		return error;
487 
488 	iic_tag_fini(&sc->sc_i2c_tag);
489 
490 	if (sc->sc_ih) {
491 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
492 		sc->sc_ih = NULL;
493 	}
494 
495 	if (sc->sc_pihp) {
496 		pci_intr_release(sc->sc_pc, sc->sc_pihp, 1);
497 		sc->sc_pihp = NULL;
498 	}
499 
500 	if (sc->sc_pmsz != 0)
501 		bus_space_unmap(sc->sc_pmt, sc->sc_pmh, sc->sc_pmsz);
502 	if (sc->sc_sbregsz != 0)
503 		bus_space_unmap(sc->sc_sbregt, sc->sc_sbregh, sc->sc_sbregsz);
504 	if (sc->sc_tcosz != 0)
505 		bus_space_unmap(sc->sc_tcot, sc->sc_tcoh, sc->sc_tcosz);
506 	if (sc->sc_size != 0)
507 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
508 
509 	mutex_destroy(&sc->sc_exec_lock);
510 	cv_destroy(&sc->sc_exec_wait);
511 
512 	return 0;
513 }
514 
515 static void
516 ichsmb_chdet(device_t self, device_t child)
517 {
518 	struct ichsmb_softc *sc = device_private(self);
519 
520 	if (sc->sc_i2c_device == child)
521 		sc->sc_i2c_device = NULL;
522 	if (sc->sc_tco_device == child)
523 		sc->sc_tco_device = NULL;
524 }
525 
526 static int
527 ichsmb_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
528     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
529 {
530 	struct ichsmb_softc *sc = cookie;
531 	const uint8_t *b;
532 	uint8_t ctl = 0, st;
533 	int retries;
534 	char fbuf[64];
535 
536 	DPRINTF(("%s: exec: op %d, addr 0x%02x, cmdlen %zu, len %zu, "
537 	    "flags 0x%02x\n", device_xname(sc->sc_dev), op, addr, cmdlen,
538 	    len, flags));
539 
540 	mutex_enter(&sc->sc_exec_lock);
541 
542 	/* Clear status bits */
543 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HS,
544 	    SMB_HS_INTR | SMB_HS_DEVERR | SMB_HS_BUSERR | SMB_HS_FAILED);
545 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, SMB_HS, 1,
546 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
547 
548 	/* Wait for bus to be idle */
549 	for (retries = 100; retries > 0; retries--) {
550 		st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SMB_HS);
551 		if (!(st & SMB_HS_BUSY))
552 			break;
553 		DELAY(ICHIIC_DELAY);
554 	}
555 #ifdef ICHIIC_DEBUG
556 	snprintb(fbuf, sizeof(fbuf), SMB_HS_BITS, st);
557 	printf("%s: exec: st %s\n", device_xname(sc->sc_dev), fbuf);
558 #endif
559 	if (st & SMB_HS_BUSY) {
560 		mutex_exit(&sc->sc_exec_lock);
561 		return (EBUSY);
562 	}
563 
564 	if (sc->sc_poll)
565 		flags |= I2C_F_POLL;
566 
567 	if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2 ||
568 	    (cmdlen == 0 && len > 1)) {
569 		mutex_exit(&sc->sc_exec_lock);
570 		return (EINVAL);
571 	}
572 
573 	/* Setup transfer */
574 	sc->sc_i2c_xfer.op = op;
575 	sc->sc_i2c_xfer.buf = buf;
576 	sc->sc_i2c_xfer.len = len;
577 	sc->sc_i2c_xfer.flags = flags;
578 	sc->sc_i2c_xfer.error = 0;
579 	sc->sc_i2c_xfer.done = false;
580 
581 	/* Set slave address and transfer direction */
582 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_TXSLVA,
583 	    SMB_TXSLVA_ADDR(addr) |
584 	    (I2C_OP_READ_P(op) ? SMB_TXSLVA_READ : 0));
585 
586 	b = (const uint8_t *)cmdbuf;
587 	if (cmdlen > 0)
588 		/* Set command byte */
589 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HCMD, b[0]);
590 
591 	if (I2C_OP_WRITE_P(op)) {
592 		/* Write data */
593 		b = buf;
594 		if (cmdlen == 0 && len == 1)
595 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
596 			    SMB_HCMD, b[0]);
597 		else if (len > 0)
598 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
599 			    SMB_HD0, b[0]);
600 		if (len > 1)
601 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
602 			    SMB_HD1, b[1]);
603 	}
604 
605 	/* Set SMBus command */
606 	if (cmdlen == 0) {
607 		if (len == 0)
608 			ctl = SMB_HC_CMD_QUICK;
609 		else
610 			ctl = SMB_HC_CMD_BYTE;
611 	} else if (len == 1)
612 		ctl = SMB_HC_CMD_BDATA;
613 	else if (len == 2)
614 		ctl = SMB_HC_CMD_WDATA;
615 
616 	if ((flags & I2C_F_POLL) == 0)
617 		ctl |= SMB_HC_INTREN;
618 
619 	/* Start transaction */
620 	ctl |= SMB_HC_START;
621 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HC, ctl);
622 
623 	if (flags & I2C_F_POLL) {
624 		/* Poll for completion */
625 		DELAY(ICHIIC_DELAY);
626 		for (retries = 1000; retries > 0; retries--) {
627 			st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SMB_HS);
628 			if ((st & SMB_HS_BUSY) == 0)
629 				break;
630 			DELAY(ICHIIC_DELAY);
631 		}
632 		if (st & SMB_HS_BUSY)
633 			goto timeout;
634 		ichsmb_intr(sc);
635 	} else {
636 		/* Wait for interrupt */
637 		while (! sc->sc_i2c_xfer.done) {
638 			if (cv_timedwait(&sc->sc_exec_wait, &sc->sc_exec_lock,
639 					 ICHIIC_TIMEOUT * hz))
640 				goto timeout;
641 		}
642 	}
643 
644 	int error = sc->sc_i2c_xfer.error;
645 	mutex_exit(&sc->sc_exec_lock);
646 
647 	return (error);
648 
649 timeout:
650 	/*
651 	 * Transfer timeout. Kill the transaction and clear status bits.
652 	 */
653 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HC, SMB_HC_KILL);
654 	DELAY(ICHIIC_DELAY);
655 	st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SMB_HS);
656 	if ((st & SMB_HS_FAILED) == 0) {
657 		snprintb(fbuf, sizeof(fbuf), SMB_HS_BITS, st);
658 		device_printf(sc->sc_dev, "abort failed, status %s\n",
659 		    fbuf);
660 	}
661 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HS, st);
662 	mutex_exit(&sc->sc_exec_lock);
663 	return (ETIMEDOUT);
664 }
665 
666 static int
667 ichsmb_intr(void *arg)
668 {
669 	struct ichsmb_softc *sc = arg;
670 	uint8_t st;
671 	uint8_t *b;
672 	size_t len;
673 #ifdef ICHIIC_DEBUG
674 	char fbuf[64];
675 #endif
676 
677 	/* Read status */
678 	st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SMB_HS);
679 
680 	/* Clear status bits */
681 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SMB_HS, st);
682 
683 	/* XXX Ignore SMBALERT# for now */
684 	if ((st & SMB_HS_BUSY) != 0 ||
685 	    (st & (SMB_HS_INTR | SMB_HS_DEVERR | SMB_HS_BUSERR |
686 		SMB_HS_FAILED | SMB_HS_BDONE)) == 0)
687 		/* Interrupt was not for us */
688 		return (0);
689 
690 #ifdef ICHIIC_DEBUG
691 	snprintb(fbuf, sizeof(fbuf), SMB_HS_BITS, st);
692 	printf("%s: intr st %s\n", device_xname(sc->sc_dev), fbuf);
693 #endif
694 
695 	if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0)
696 		mutex_enter(&sc->sc_exec_lock);
697 
698 	/* Check for errors */
699 	if (st & (SMB_HS_DEVERR | SMB_HS_BUSERR | SMB_HS_FAILED)) {
700 		sc->sc_i2c_xfer.error = EIO;
701 		goto done;
702 	}
703 
704 	if (st & SMB_HS_INTR) {
705 		if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op))
706 			goto done;
707 
708 		/* Read data */
709 		b = sc->sc_i2c_xfer.buf;
710 		len = sc->sc_i2c_xfer.len;
711 		if (len > 0)
712 			b[0] = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
713 			    SMB_HD0);
714 		if (len > 1)
715 			b[1] = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
716 			    SMB_HD1);
717 	}
718 
719 done:
720 	sc->sc_i2c_xfer.done = true;
721 	if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0) {
722 		cv_signal(&sc->sc_exec_wait);
723 		mutex_exit(&sc->sc_exec_lock);
724 	}
725 	return (1);
726 }
727 
728 MODULE(MODULE_CLASS_DRIVER, ichsmb, "pci,iic");
729 
730 #ifdef _MODULE
731 #include "ioconf.c"
732 #endif
733 
734 static int
735 ichsmb_modcmd(modcmd_t cmd, void *opaque)
736 {
737 	int error = 0;
738 
739 	switch (cmd) {
740 	case MODULE_CMD_INIT:
741 #ifdef _MODULE
742 		error = config_init_component(cfdriver_ioconf_ichsmb,
743 		    cfattach_ioconf_ichsmb, cfdata_ioconf_ichsmb);
744 #endif
745 		break;
746 	case MODULE_CMD_FINI:
747 #ifdef _MODULE
748 		error = config_fini_component(cfdriver_ioconf_ichsmb,
749 		    cfattach_ioconf_ichsmb, cfdata_ioconf_ichsmb);
750 #endif
751 		break;
752 	default:
753 #ifdef _MODULE
754 		error = ENOTTY;
755 #endif
756 		break;
757 	}
758 
759 	return error;
760 }
761