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