xref: /dragonfly/sys/bus/smbus/ichiic/ig4_iic.c (revision 2513f15e)
1 /*
2  * Copyright (c) 2014 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 /*
35  * Intel 4th generation mobile cpus integrated I2C device, smbus driver.
36  *
37  * See ig4_reg.h for datasheet reference and notes.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/module.h>
44 #include <sys/errno.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/syslog.h>
48 #include <sys/bus.h>
49 
50 #include <sys/rman.h>
51 
52 #include <bus/pci/pcivar.h>
53 #include <bus/pci/pcireg.h>
54 #include <bus/smbus/smbconf.h>
55 
56 #include "smbus_if.h"
57 
58 #include "ig4_reg.h"
59 #include "ig4_var.h"
60 
61 #define TRANS_NORMAL	1
62 #define TRANS_PCALL	2
63 #define TRANS_BLOCK	3
64 
65 static void ig4iic_intr(void *cookie);
66 
67 /*
68  * Low-level inline support functions
69  */
70 static __inline
71 void
72 reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value)
73 {
74 	bus_space_write_4(sc->regs_t, sc->regs_h, reg, value);
75 	bus_space_barrier(sc->regs_t, sc->regs_h, reg, 4,
76 			  BUS_SPACE_BARRIER_WRITE);
77 }
78 
79 static __inline
80 uint32_t
81 reg_read(ig4iic_softc_t *sc, uint32_t reg)
82 {
83 	uint32_t value;
84 
85 	bus_space_barrier(sc->regs_t, sc->regs_h, reg, 4,
86 			  BUS_SPACE_BARRIER_READ);
87 	value = bus_space_read_4(sc->regs_t, sc->regs_h, reg);
88 	return value;
89 }
90 
91 /*
92  * Enable or disable the controller and wait for the controller to acknowledge
93  * the state change.
94  */
95 static
96 int
97 set_controller(ig4iic_softc_t *sc, uint32_t ctl)
98 {
99 	int retry;
100 	int error;
101 	uint32_t v;
102 
103 	reg_write(sc, IG4_REG_I2C_EN, ctl);
104 	error = SMB_ETIMEOUT;
105 
106 	for (retry = 100; retry > 0; --retry) {
107 		v = reg_read(sc, IG4_REG_ENABLE_STATUS);
108 		if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) {
109 			error = 0;
110 			break;
111 		}
112 		tsleep(sc, 0, "i2cslv", 1);
113 	}
114 	return error;
115 }
116 
117 /*
118  * Wait up to 25ms for the requested status using a 25uS polling loop.
119  */
120 static
121 int
122 wait_status(ig4iic_softc_t *sc, uint32_t status)
123 {
124 	uint32_t v;
125 	int error;
126 	int txlvl = -1;
127 	sysclock_t count;
128 	sysclock_t limit;
129 
130 	error = SMB_ETIMEOUT;
131 	count = sys_cputimer->count();
132 	limit = sys_cputimer->freq / 40;
133 
134 	while (sys_cputimer->count() - count <= limit) {
135 		/*
136 		 * Check requested status
137 		 */
138 		v = reg_read(sc, IG4_REG_I2C_STA);
139 		if (v & status) {
140 			error = 0;
141 			break;
142 		}
143 
144 		/*
145 		 * Shim RX_NOTEMPTY of the data was read by the
146 		 * interrupt code.
147 		 */
148 		if (status & IG4_STATUS_RX_NOTEMPTY) {
149 			if (sc->rpos != sc->rnext) {
150 				error = 0;
151 				break;
152 			}
153 		}
154 
155 		/*
156 		 * Shim TX_EMPTY by resetting the retry timer if we
157 		 * see a change in the transmit fifo level.
158 		 */
159 		if (status & IG4_STATUS_TX_EMPTY) {
160 			v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK;
161 			if (txlvl != v) {
162 				txlvl = v;
163 				count = sys_cputimer->count();
164 			}
165 		}
166 
167 		/*
168 		 * The interrupt will wake us up if we are waiting for
169 		 * read data, otherwise poll.
170 		 */
171 		if (status & IG4_STATUS_RX_NOTEMPTY) {
172 			lksleep(sc, &sc->lk, 0, "i2cwait", (hz + 99) / 100);
173 		} else {
174 			DELAY(25);
175 		}
176 	}
177 	return error;
178 }
179 
180 /*
181  * Read I2C data.  The data might have already been read by
182  * the interrupt code, otherwise it is sitting in the data
183  * register.
184  */
185 static
186 uint8_t
187 data_read(ig4iic_softc_t *sc)
188 {
189 	uint8_t c;
190 
191 	if (sc->rpos == sc->rnext) {
192 		c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
193 	} else {
194 		c = sc->rbuf[sc->rpos & IG4_RBUFMASK];
195 		++sc->rpos;
196 	}
197 	return c;
198 }
199 
200 /*
201  * Set the slave address.  The controller must be disabled when
202  * changing the address.
203  *
204  * This operation does not issue anything to the I2C bus but sets
205  * the target address for when the controller later issues a START.
206  */
207 static
208 void
209 set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op)
210 {
211 	uint32_t tar;
212 	uint32_t ctl;
213 	int use_10bit;
214 
215 	use_10bit = sc->use_10bit;
216 	if (trans_op & SMB_TRANS_7BIT)
217 		use_10bit = 0;
218 	if (trans_op & SMB_TRANS_10BIT)
219 		use_10bit = 1;
220 
221 	if (sc->slave_valid && sc->last_slave == slave &&
222 	    sc->use_10bit == use_10bit) {
223 		return;
224 	}
225 	sc->use_10bit = use_10bit;
226 
227 	/*
228 	 * Wait for TXFIFO to drain before disabling the controller.
229 	 *
230 	 * If a write message has not been completed it's really a
231 	 * programming error, but for now in that case issue an extra
232 	 * byte + STOP.
233 	 *
234 	 * If a read message has not been completed it's also a programming
235 	 * error, for now just ignore it.
236 	 */
237 	wait_status(sc, IG4_STATUS_TX_NOTFULL);
238 	if (sc->write_started) {
239 		reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP);
240 		sc->write_started = 0;
241 	}
242 	if (sc->read_started)
243 		sc->read_started = 0;
244 	wait_status(sc, IG4_STATUS_TX_EMPTY);
245 
246 	set_controller(sc, 0);
247 	ctl = reg_read(sc, IG4_REG_CTL);
248 	ctl &= ~IG4_CTL_10BIT;
249 	ctl |= IG4_CTL_RESTARTEN;
250 
251 	tar = slave;
252 	if (sc->use_10bit) {
253 		tar |= IG4_TAR_10BIT;
254 		ctl |= IG4_CTL_10BIT;
255 	}
256 	reg_write(sc, IG4_REG_CTL, ctl);
257 	reg_write(sc, IG4_REG_TAR_ADD, tar);
258 	set_controller(sc, IG4_I2C_ENABLE);
259 	sc->slave_valid = 1;
260 	sc->last_slave = slave;
261 }
262 
263 /*
264  * Issue START with byte command, possible count, and a variable length
265  * read or write buffer, then possible turn-around read.  The read also
266  * has a possible count received.
267  *
268  * For SMBUS -
269  *
270  * Quick:		START+ADDR+RD/WR STOP
271  *
272  * Normal:		START+ADDR+WR COMM DATA..DATA STOP
273  *
274  *			START+ADDR+RD COMM
275  *			RESTART+ADDR RDATA..RDATA STOP
276  *			(can also be used for I2C transactions)
277  *
278  * Process Call:	START+ADDR+WR COMM DATAL DATAH
279  *			RESTART+ADDR+RD RDATAL RDATAH STOP
280  *
281  * Block:		START+ADDR+RD COMM
282  *			RESTART+ADDR+RD RCOUNT DATA... STOP
283  *
284  * 			START+ADDR+WR COMM
285  *			RESTART+ADDR+WR WCOUNT DATA... STOP
286  *
287  * For I2C - basically, no *COUNT fields.
288  *
289  * Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically
290  * by the controller at the beginning of a command sequence or on a data
291  * direction turn-around, and we only need to tell it when to issue the STOP.
292  */
293 static int
294 smb_transaction(ig4iic_softc_t *sc, char cmd, int op,
295 		char *wbuf, int wcount, char *rbuf, int rcount, int *actualp)
296 {
297 	int error;
298 	uint32_t last;
299 
300 	/*
301 	 * Issue START or RESTART with next data byte, clear any previous
302 	 * abort condition that may have been holding the txfifo in reset.
303 	 */
304 	last = IG4_DATA_RESTART;
305 	reg_read(sc, IG4_REG_CLR_TX_ABORT);
306 	if (actualp)
307 		*actualp = 0;
308 
309 	/*
310 	 * Issue command if not told otherwise (smbus).
311 	 */
312 	if ((op & SMB_TRANS_NOCMD) == 0) {
313 		error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
314 		if (error)
315 			goto done;
316 		last |= (u_char)cmd;
317 		if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
318 			last |= IG4_DATA_STOP;
319 		reg_write(sc, IG4_REG_DATA_CMD, last);
320 		last = 0;
321 
322 		/*
323 		 * Clean out any previously received data
324 		 */
325 		sc->rpos = 0;
326 		sc->rnext = 0;
327 	}
328 
329 	/*
330 	 * If writing and not told otherwise, issue the write count (smbus).
331 	 */
332 	if (wcount && (op & SMB_TRANS_NOCNT) == 0) {
333 		error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
334 		if (error)
335 			goto done;
336 		last |= (u_char)cmd;
337 		reg_write(sc, IG4_REG_DATA_CMD, last);
338 		last = 0;
339 	}
340 
341 	/*
342 	 * Bulk write (i2c)
343 	 */
344 	while (wcount) {
345 		error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
346 		if (error)
347 			goto done;
348 		last |= (u_char)*wbuf;
349 		if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
350 			last |= IG4_DATA_STOP;
351 		reg_write(sc, IG4_REG_DATA_CMD, last);
352 		--wcount;
353 		++wbuf;
354 		last = 0;
355 	}
356 
357 	/*
358 	 * Issue reads to xmit FIFO (strange, I know) to tell the controller
359 	 * to clock in data.  At the moment just issue one read ahead to
360 	 * pipeline the incoming data.
361 	 *
362 	 * NOTE: In the case of NOCMD and wcount == 0 we still issue a
363 	 *	 RESTART here, even if the data direction has not changed
364 	 *	 from the previous CHAINing call.  This we force the RESTART.
365 	 *	 (A new START is issued automatically by the controller in
366 	 *	 the other nominal cases such as a data direction change or
367 	 *	 a previous STOP was issued).
368 	 *
369 	 * If this will be the last byte read we must also issue the STOP
370 	 * at the end of the read.
371 	 */
372 	if (rcount) {
373 		last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD;
374 		if (rcount == 1 &&
375 		    (op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) ==
376 		    SMB_TRANS_NOCNT) {
377 			last |= IG4_DATA_STOP;
378 		}
379 		reg_write(sc, IG4_REG_DATA_CMD, last);
380 		last = IG4_DATA_COMMAND_RD;
381 	}
382 
383 	/*
384 	 * Bulk read (i2c) and count field handling (smbus)
385 	 */
386 	while (rcount) {
387 		/*
388 		 * Maintain a pipeline by queueing the allowance for the next
389 		 * read before waiting for the current read.
390 		 */
391 		if (rcount > 1) {
392 			if (op & SMB_TRANS_NOCNT)
393 				last = (rcount == 2) ? IG4_DATA_STOP : 0;
394 			else
395 				last = 0;
396 			reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD |
397 							last);
398 		}
399 		error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
400 		if (error)
401 			goto done;
402 		last = data_read(sc);
403 
404 		if (op & SMB_TRANS_NOCNT) {
405 			*rbuf = (u_char)last;
406 			++rbuf;
407 			--rcount;
408 			if (actualp)
409 				++*actualp;
410 		} else {
411 			/*
412 			 * Handle count field (smbus), which is not part of
413 			 * the rcount'ed buffer.  The first read data in a
414 			 * bulk transfer is the count.
415 			 *
416 			 * XXX if rcount is loaded as 0 how do I generate a
417 			 *     STOP now without issuing another RD or WR?
418 			 */
419 			if (rcount > (u_char)last)
420 				rcount = (u_char)last;
421 			op |= SMB_TRANS_NOCNT;
422 		}
423 	}
424 	error = 0;
425 done:
426 	/* XXX wait for xmit buffer to become empty */
427 	last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
428 
429 	return error;
430 }
431 
432 /*
433  *				SMBUS API FUNCTIONS
434  *
435  * Called from ig4iic_pci_attach/detach()
436  */
437 int
438 ig4iic_attach(ig4iic_softc_t *sc)
439 {
440 	int error;
441 	uint32_t v;
442 
443 	lockmgr(&sc->lk, LK_EXCLUSIVE);
444 
445 	v = reg_read(sc, IG4_REG_COMP_TYPE);
446 	kprintf("type %08x\n", v);
447 	v = reg_read(sc, IG4_REG_COMP_PARAM1);
448 	kprintf("params %08x\n", v);
449 	v = reg_read(sc, IG4_REG_COMP_VER);
450 	kprintf("version %08x\n", v);
451 	if (v != IG4_COMP_VER) {
452 		error = ENXIO;
453 		goto done;
454 	}
455 #if 1
456 	v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
457 	kprintf("SS_SCL_HCNT %08x\n", v);
458 	v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
459 	kprintf("SS_SCL_LCNT %08x\n", v);
460 	v = reg_read(sc, IG4_REG_FS_SCL_HCNT);
461 	kprintf("FS_SCL_HCNT %08x\n", v);
462 	v = reg_read(sc, IG4_REG_FS_SCL_LCNT);
463 	kprintf("FS_SCL_LCNT %08x\n", v);
464 	v = reg_read(sc, IG4_REG_SDA_HOLD);
465 	kprintf("HOLD        %08x\n", v);
466 
467 	v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
468 	reg_write(sc, IG4_REG_FS_SCL_HCNT, v);
469 	v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
470 	reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
471 #endif
472 	/*
473 	 * Program based on a 25000 Hz clock.  This is a bit of a
474 	 * hack (obviously).  The defaults are 400 and 470 for standard
475 	 * and 60 and 130 for fast.  The defaults for standard fail
476 	 * utterly (presumably cause an abort) because the clock time
477 	 * is ~18.8ms by default.  This brings it down to ~4ms (for now).
478 	 */
479 	reg_write(sc, IG4_REG_SS_SCL_HCNT, 100);
480 	reg_write(sc, IG4_REG_SS_SCL_LCNT, 125);
481 	reg_write(sc, IG4_REG_FS_SCL_HCNT, 100);
482 	reg_write(sc, IG4_REG_FS_SCL_LCNT, 125);
483 
484 	/*
485 	 * Use a threshold of 1 so we get interrupted on each character,
486 	 * allowing us to use lksleep() in our poll code.  Not perfect
487 	 * but this is better than using DELAY() for receiving data.
488 	 */
489 	reg_write(sc, IG4_REG_RX_TL, 1);
490 
491 	reg_write(sc, IG4_REG_CTL,
492 		  IG4_CTL_MASTER |
493 		  IG4_CTL_SLAVE_DISABLE |
494 		  IG4_CTL_RESTARTEN |
495 		  IG4_CTL_SPEED_STD);
496 
497 	sc->smb = device_add_child(sc->dev, "smbus", -1);
498 	if (sc->smb == NULL) {
499 		device_printf(sc->dev, "smbus driver not found\n");
500 		error = ENXIO;
501 		goto done;
502 	}
503 
504 #if 0
505 	/*
506 	 * Don't do this, it blows up the PCI config
507 	 */
508 	reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT);
509 	reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
510 #endif
511 
512 	/*
513 	 * Interrupt on STOP detect or receive character ready
514 	 */
515 	reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
516 					 IG4_INTR_RX_FULL);
517 	if (set_controller(sc, 0))
518 		device_printf(sc->dev, "controller error during attach-1\n");
519 	if (set_controller(sc, IG4_I2C_ENABLE))
520 		device_printf(sc->dev, "controller error during attach-2\n");
521 	error = bus_setup_intr(sc->dev, sc->intr_res, 0,
522 			       ig4iic_intr, sc, &sc->intr_handle, NULL);
523 	if (error) {
524 		device_printf(sc->dev,
525 			      "Unable to setup irq: error %d\n", error);
526 		goto done;
527 	}
528 
529 	/* Attach us to the smbus */
530 	lockmgr(&sc->lk, LK_RELEASE);
531 	error = bus_generic_attach(sc->dev);
532 	lockmgr(&sc->lk, LK_EXCLUSIVE);
533 	if (error) {
534 		device_printf(sc->dev,
535 			      "failed to attach child: error %d\n", error);
536 		goto done;
537 	}
538 	sc->generic_attached = 1;
539 
540 done:
541 	lockmgr(&sc->lk, LK_RELEASE);
542 	return error;
543 }
544 
545 int
546 ig4iic_detach(ig4iic_softc_t *sc)
547 {
548 	int error;
549 
550 	lockmgr(&sc->lk, LK_EXCLUSIVE);
551 
552 	reg_write(sc, IG4_REG_INTR_MASK, 0);
553 	reg_read(sc, IG4_REG_CLR_INTR);
554 	set_controller(sc, 0);
555 
556 	if (sc->generic_attached) {
557 		error = bus_generic_detach(sc->dev);
558 		if (error)
559 			goto done;
560 		sc->generic_attached = 0;
561 	}
562 	if (sc->smb) {
563 		device_delete_child(sc->dev, sc->smb);
564 		sc->smb = NULL;
565 	}
566 	if (sc->intr_handle) {
567 		bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
568 		sc->intr_handle = NULL;
569 	}
570 
571 	error = 0;
572 done:
573 	lockmgr(&sc->lk, LK_RELEASE);
574 	return error;
575 }
576 
577 int
578 ig4iic_smb_callback(device_t dev, int index, void *data)
579 {
580 	ig4iic_softc_t *sc = device_get_softc(dev);
581 	int error;
582 
583 	lockmgr(&sc->lk, LK_EXCLUSIVE);
584 
585 	switch (index) {
586 	case SMB_REQUEST_BUS:
587 		error = 0;
588 		break;
589 	case SMB_RELEASE_BUS:
590 		error = 0;
591 		break;
592 	default:
593 		error = SMB_EABORT;
594 		break;
595 	}
596 
597 	lockmgr(&sc->lk, LK_RELEASE);
598 
599 	return error;
600 }
601 
602 /*
603  * Quick command.  i.e. START + cmd + R/W + STOP and no data.  It is
604  * unclear to me how I could implement this with the intel i2c controller
605  * because the controler sends STARTs and STOPs automatically with data.
606  */
607 int
608 ig4iic_smb_quick(device_t dev, u_char slave, int how)
609 {
610 	ig4iic_softc_t *sc = device_get_softc(dev);
611 	int error;
612 
613 	lockmgr(&sc->lk, LK_EXCLUSIVE);
614 
615 	switch (how) {
616 	case SMB_QREAD:
617 		error = SMB_ENOTSUPP;
618 		break;
619 	case SMB_QWRITE:
620 		error = SMB_ENOTSUPP;
621 		break;
622 	default:
623 		error = SMB_ENOTSUPP;
624 		break;
625 	}
626 	lockmgr(&sc->lk, LK_RELEASE);
627 
628 	return error;
629 }
630 
631 /*
632  * Incremental send byte without stop (?).  It is unclear why the slave
633  * address is specified if this presumably is used in combination with
634  * ig4iic_smb_quick().
635  *
636  * (Also, how would this work anyway?  Issue the last byte with writeb()?)
637  */
638 int
639 ig4iic_smb_sendb(device_t dev, u_char slave, char byte)
640 {
641 	ig4iic_softc_t *sc = device_get_softc(dev);
642 	uint32_t cmd;
643 	int error;
644 
645 	lockmgr(&sc->lk, LK_EXCLUSIVE);
646 
647 	set_slave_addr(sc, slave, 0);
648 	cmd = byte;
649 	if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) {
650 		reg_write(sc, IG4_REG_DATA_CMD, cmd);
651 		error = 0;
652 	} else {
653 		error = SMB_ETIMEOUT;
654 	}
655 
656 	lockmgr(&sc->lk, LK_RELEASE);
657 	return error;
658 }
659 
660 /*
661  * Incremental receive byte without stop (?).  It is unclear why the slave
662  * address is specified if this presumably is used in combination with
663  * ig4iic_smb_quick().
664  */
665 int
666 ig4iic_smb_recvb(device_t dev, u_char slave, char *byte)
667 {
668 	ig4iic_softc_t *sc = device_get_softc(dev);
669 	int error;
670 
671 	lockmgr(&sc->lk, LK_EXCLUSIVE);
672 
673 	set_slave_addr(sc, slave, 0);
674 	reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD);
675 	if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) {
676 		*byte = data_read(sc);
677 		error = 0;
678 	} else {
679 		*byte = 0;
680 		error = SMB_ETIMEOUT;
681 	}
682 
683 	lockmgr(&sc->lk, LK_RELEASE);
684 	return error;
685 }
686 
687 /*
688  * Write command and single byte in transaction.
689  */
690 int
691 ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
692 {
693 	ig4iic_softc_t *sc = device_get_softc(dev);
694 	int error;
695 
696 	lockmgr(&sc->lk, LK_EXCLUSIVE);
697 
698 	set_slave_addr(sc, slave, 0);
699 	error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
700 				&byte, 1, NULL, 0, NULL);
701 
702 	lockmgr(&sc->lk, LK_RELEASE);
703 	return error;
704 }
705 
706 /*
707  * Write command and single word in transaction.
708  */
709 int
710 ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word)
711 {
712 	ig4iic_softc_t *sc = device_get_softc(dev);
713 	char buf[2];
714 	int error;
715 
716 	lockmgr(&sc->lk, LK_EXCLUSIVE);
717 
718 	set_slave_addr(sc, slave, 0);
719 	buf[0] = word & 0xFF;
720 	buf[1] = word >> 8;
721 	error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
722 				buf, 2, NULL, 0, NULL);
723 
724 	lockmgr(&sc->lk, LK_RELEASE);
725 	return error;
726 }
727 
728 /*
729  * write command and read single byte in transaction.
730  */
731 int
732 ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
733 {
734 	ig4iic_softc_t *sc = device_get_softc(dev);
735 	int error;
736 
737 	lockmgr(&sc->lk, LK_EXCLUSIVE);
738 
739 	set_slave_addr(sc, slave, 0);
740 	error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
741 				NULL, 0, byte, 1, NULL);
742 
743 	lockmgr(&sc->lk, LK_RELEASE);
744 	return error;
745 }
746 
747 /*
748  * write command and read word in transaction.
749  */
750 int
751 ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word)
752 {
753 	ig4iic_softc_t *sc = device_get_softc(dev);
754 	char buf[2];
755 	int error;
756 
757 	lockmgr(&sc->lk, LK_EXCLUSIVE);
758 
759 	set_slave_addr(sc, slave, 0);
760 	if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
761 				     NULL, 0, buf, 2, NULL)) == 0) {
762 		*word = (u_char)buf[0] | ((u_char)buf[1] << 8);
763 	}
764 
765 	lockmgr(&sc->lk, LK_RELEASE);
766 	return error;
767 }
768 
769 /*
770  * write command and word and read word in transaction
771  */
772 int
773 ig4iic_smb_pcall(device_t dev, u_char slave, char cmd,
774 		 short sdata, short *rdata)
775 {
776 	ig4iic_softc_t *sc = device_get_softc(dev);
777 	char rbuf[2];
778 	char wbuf[2];
779 	int error;
780 
781 	lockmgr(&sc->lk, LK_EXCLUSIVE);
782 
783 	set_slave_addr(sc, slave, 0);
784 	wbuf[0] = sdata & 0xFF;
785 	wbuf[1] = sdata >> 8;
786 	if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
787 				     wbuf, 2, rbuf, 2, NULL)) == 0) {
788 		*rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8);
789 	}
790 
791 	lockmgr(&sc->lk, LK_RELEASE);
792 	return error;
793 }
794 
795 int
796 ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd,
797 		  u_char wcount, char *buf)
798 {
799 	ig4iic_softc_t *sc = device_get_softc(dev);
800 	int error;
801 
802 	lockmgr(&sc->lk, LK_EXCLUSIVE);
803 
804 	set_slave_addr(sc, slave, 0);
805 	error = smb_transaction(sc, cmd, 0,
806 				buf, wcount, NULL, 0, NULL);
807 
808 	lockmgr(&sc->lk, LK_RELEASE);
809 	return error;
810 }
811 
812 int
813 ig4iic_smb_bread(device_t dev, u_char slave, char cmd,
814 		 u_char *countp_char, char *buf)
815 {
816 	ig4iic_softc_t *sc = device_get_softc(dev);
817 	int rcount = *countp_char;
818 	int error;
819 
820 	lockmgr(&sc->lk, LK_EXCLUSIVE);
821 
822 	set_slave_addr(sc, slave, 0);
823 	error = smb_transaction(sc, cmd, 0,
824 				NULL, 0, buf, rcount, &rcount);
825 	*countp_char = rcount;
826 
827 	lockmgr(&sc->lk, LK_RELEASE);
828 	return error;
829 }
830 
831 int
832 ig4iic_smb_trans(device_t dev, int slave, char cmd, int op,
833 		 char *wbuf, int wcount, char *rbuf, int rcount,
834 		 int *actualp)
835 {
836 	ig4iic_softc_t *sc = device_get_softc(dev);
837 	int error;
838 
839 	lockmgr(&sc->lk, LK_EXCLUSIVE);
840 
841 	set_slave_addr(sc, slave, op);
842 	error = smb_transaction(sc, cmd, op,
843 				wbuf, wcount, rbuf, rcount, actualp);
844 
845 	lockmgr(&sc->lk, LK_RELEASE);
846 	return error;
847 }
848 
849 /*
850  * Interrupt Operation
851  */
852 static
853 void
854 ig4iic_intr(void *cookie)
855 {
856 	ig4iic_softc_t *sc = cookie;
857 	uint32_t status;
858 
859 	lockmgr(&sc->lk, LK_EXCLUSIVE);
860 /*	reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/
861 	status = reg_read(sc, IG4_REG_I2C_STA);
862 	if (status & IG4_STATUS_RX_NOTEMPTY) {
863 		sc->rbuf[sc->rnext & IG4_RBUFMASK] =
864 		    (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
865 		++sc->rnext;
866 	}
867 	reg_read(sc, IG4_REG_CLR_INTR);
868 	wakeup(sc);
869 	lockmgr(&sc->lk, LK_RELEASE);
870 }
871 
872 DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL);
873