kernel - Add support for haswell I2C, expand smbus API, fix /dev/smb*
[dragonfly.git] / sys / bus / smbus / ichiic / ig4_iic.c
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 retry;
126         int error;
127         int txlvl = -1;
128
129         error = SMB_ETIMEOUT;
130         for (retry = 0; retry < 1000000 / 40; retry += 25) {
131                 v = reg_read(sc, IG4_REG_I2C_STA);
132                 if (v & status) {
133                         error = 0;
134                         break;
135                 }
136
137                 if (status & IG4_STATUS_TX_EMPTY) {
138                         v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK;
139                         if (txlvl != v) {
140                                 txlvl = v;
141                                 retry = 0;
142                         }
143                 }
144
145                 /*tsleep(sc, 0, "i2cwait", 1);*/
146                 DELAY(25);
147         }
148         return error;
149 }
150
151 /*
152  * Set the slave address.  The controller must be disabled when
153  * changing the address.
154  *
155  * This operation does not issue anything to the I2C bus but sets
156  * the target address for when the controller later issues a START.
157  */
158 static
159 void
160 set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op)
161 {
162         uint32_t tar;
163         uint32_t ctl;
164         int use_10bit;
165
166         use_10bit = sc->use_10bit;
167         if (trans_op & SMB_TRANS_7BIT)
168                 use_10bit = 0;
169         if (trans_op & SMB_TRANS_10BIT)
170                 use_10bit = 1;
171
172         if (sc->slave_valid && sc->last_slave == slave &&
173             sc->use_10bit == use_10bit) {
174                 return;
175         }
176         sc->use_10bit = use_10bit;
177
178         /*
179          * Wait for TXFIFO to drain before disabling the controller.
180          *
181          * If a write message has not been completed it's really a
182          * programming error, but for now in that case issue an extra
183          * byte + STOP.
184          *
185          * If a read message has not been completed it's also a programming
186          * error, for now just ignore it.
187          */
188         wait_status(sc, IG4_STATUS_TX_NOTFULL);
189         if (sc->write_started) {
190                 reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP);
191                 sc->write_started = 0;
192         }
193         if (sc->read_started)
194                 sc->read_started = 0;
195         wait_status(sc, IG4_STATUS_TX_EMPTY);
196
197         set_controller(sc, 0);
198         ctl = reg_read(sc, IG4_REG_CTL);
199         ctl &= ~IG4_CTL_10BIT;
200         ctl |= IG4_CTL_RESTARTEN;
201
202         tar = slave;
203         if (sc->use_10bit) {
204                 tar |= IG4_TAR_10BIT;
205                 ctl |= IG4_CTL_10BIT;
206         }
207         reg_write(sc, IG4_REG_CTL, ctl);
208         reg_write(sc, IG4_REG_TAR_ADD, tar);
209         set_controller(sc, IG4_I2C_ENABLE);
210         sc->slave_valid = 1;
211         sc->last_slave = slave;
212 }
213
214 /*
215  * Issue START with byte command, possible count, and a variable length
216  * read or write buffer, then possible turn-around read.  The read also
217  * has a possible count received.
218  *
219  * For SMBUS -
220  *
221  * Quick:               START+ADDR+RD/WR STOP
222  *
223  * Normal:              START+ADDR+WR COMM DATA..DATA STOP
224  *
225  *                      START+ADDR+RD COMM
226  *                      RESTART+ADDR RDATA..RDATA STOP
227  *                      (can also be used for I2C transactions)
228  *
229  * Process Call:        START+ADDR+WR COMM DATAL DATAH
230  *                      RESTART+ADDR+RD RDATAL RDATAH STOP
231  *
232  * Block:               START+ADDR+RD COMM
233  *                      RESTART+ADDR+RD RCOUNT DATA... STOP
234  *
235  *                      START+ADDR+WR COMM
236  *                      RESTART+ADDR+WR WCOUNT DATA... STOP
237  *
238  * For I2C - basically, no *COUNT fields.
239  *
240  * Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically
241  * by the controller at the beginning of a command sequence or on a data
242  * direction turn-around, and we only need to tell it when to issue the STOP.
243  */
244 static int
245 smb_transaction(ig4iic_softc_t *sc, char cmd, int op,
246                 char *wbuf, int wcount, char *rbuf, int rcount, int *actualp)
247 {
248         int error;
249         uint32_t last;
250
251         /*
252          * Issue START or RESTART with next data byte, clear any previous
253          * abort condition that may have been holding the txfifo in reset.
254          */
255         last = IG4_DATA_RESTART;
256         reg_read(sc, IG4_REG_CLR_TX_ABORT);
257         if (actualp)
258                 *actualp = 0;
259
260         /*
261          * Issue command if not told otherwise (smbus).
262          */
263         if ((op & SMB_TRANS_NOCMD) == 0) {
264                 error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
265                 if (error)
266                         goto done;
267                 last |= (u_char)cmd;
268                 if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
269                         last |= IG4_DATA_STOP;
270                 reg_write(sc, IG4_REG_DATA_CMD, last);
271                 last = 0;
272         }
273
274         /*
275          * If writing and not told otherwise, issue the write count (smbus).
276          */
277         if (wcount && (op & SMB_TRANS_NOCNT) == 0) {
278                 error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
279                 if (error)
280                         goto done;
281                 last |= (u_char)cmd;
282                 reg_write(sc, IG4_REG_DATA_CMD, last);
283                 last = 0;
284         }
285
286         /*
287          * Bulk write (i2c)
288          */
289         while (wcount) {
290                 error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
291                 if (error)
292                         goto done;
293                 last |= (u_char)*wbuf;
294                 if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
295                         last |= IG4_DATA_STOP;
296                 reg_write(sc, IG4_REG_DATA_CMD, last);
297                 --wcount;
298                 ++wbuf;
299                 last = 0;
300         }
301
302         /*
303          * Issue reads to xmit FIFO (strange, I know) to tell the controller
304          * to clock in data.  At the moment just issue one read ahead to
305          * pipeline the incoming data.
306          *
307          * NOTE: In the case of NOCMD and wcount == 0 we still issue a
308          *       RESTART here, even if the data direction has not changed
309          *       from the previous CHAINing call.  This we force the RESTART.
310          *       (A new START is issued automatically by the controller in
311          *       the other nominal cases such as a data direction change or
312          *       a previous STOP was issued).
313          *
314          * If this will be the last byte read we must also issue the STOP
315          * at the end of the read.
316          */
317         if (rcount) {
318                 last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD;
319                 if (rcount == 1 &&
320                     (op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) ==
321                     SMB_TRANS_NOCNT) {
322                         last |= IG4_DATA_STOP;
323                 }
324                 reg_write(sc, IG4_REG_DATA_CMD, last);
325                 last = IG4_DATA_COMMAND_RD;
326         }
327
328         /*
329          * Bulk read (i2c) and count field handling (smbus)
330          */
331         while (rcount) {
332                 /*
333                  * Maintain a pipeline by queueing the allowance for the next
334                  * read before waiting for the current read.
335                  */
336                 if (rcount > 1) {
337                         if (op & SMB_TRANS_NOCNT)
338                                 last = (rcount == 2) ? IG4_DATA_STOP : 0;
339                         else
340                                 last = 0;
341                         reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD |
342                                                         last);
343                 }
344                 error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
345                 if (error)
346                         goto done;
347                 last = reg_read(sc, IG4_REG_DATA_CMD);
348
349                 if (op & SMB_TRANS_NOCNT) {
350                         *rbuf = (u_char)last;
351                         ++rbuf;
352                         --rcount;
353                         if (actualp)
354                                 ++*actualp;
355                 } else {
356                         /*
357                          * Handle count field (smbus), which is not part of
358                          * the rcount'ed buffer.  The first read data in a
359                          * bulk transfer is the count.
360                          *
361                          * XXX if rcount is loaded as 0 how do I generate a
362                          *     STOP now without issuing another RD or WR?
363                          */
364                         if (rcount > (u_char)last)
365                                 rcount = (u_char)last;
366                         op |= SMB_TRANS_NOCNT;
367                 }
368         }
369         error = 0;
370 done:
371         /* XXX wait for xmit buffer to become empty */
372         last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
373
374         return error;
375 }
376
377 /*
378  *                              SMBUS API FUNCTIONS
379  *
380  * Called from ig4iic_pci_attach/detach()
381  */
382 int
383 ig4iic_attach(ig4iic_softc_t *sc)
384 {
385         int error;
386         uint32_t v;
387
388         lockmgr(&sc->lk, LK_EXCLUSIVE);
389
390         v = reg_read(sc, IG4_REG_COMP_TYPE);
391         kprintf("type %08x\n", v);
392         v = reg_read(sc, IG4_REG_COMP_PARAM1);
393         kprintf("params %08x\n", v);
394         v = reg_read(sc, IG4_REG_COMP_VER);
395         kprintf("version %08x\n", v);
396         if (v != IG4_COMP_VER) {
397                 error = ENXIO;
398                 goto done;
399         }
400 #if 1
401         v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
402         kprintf("SS_SCL_HCNT %08x\n", v);
403         v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
404         kprintf("SS_SCL_LCNT %08x\n", v);
405         v = reg_read(sc, IG4_REG_FS_SCL_HCNT);
406         kprintf("FS_SCL_HCNT %08x\n", v);
407         v = reg_read(sc, IG4_REG_FS_SCL_LCNT);
408         kprintf("FS_SCL_LCNT %08x\n", v);
409         v = reg_read(sc, IG4_REG_SDA_HOLD);
410         kprintf("HOLD        %08x\n", v);
411
412         v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
413         reg_write(sc, IG4_REG_FS_SCL_HCNT, v);
414         v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
415         reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
416 #endif
417         /*
418          * Program based on a 25000 Hz clock.  This is a bit of a
419          * hack (obviously).  The defaults are 400 and 470 for standard
420          * and 60 and 130 for fast.  The defaults for standard fail
421          * utterly (presumably cause an abort) because the clock time
422          * is ~18.8ms by default.  This brings it down to ~4ms (for now).
423          */
424         reg_write(sc, IG4_REG_SS_SCL_HCNT, 100);
425         reg_write(sc, IG4_REG_SS_SCL_LCNT, 125);
426         reg_write(sc, IG4_REG_FS_SCL_HCNT, 100);
427         reg_write(sc, IG4_REG_FS_SCL_LCNT, 125);
428
429         reg_write(sc, IG4_REG_CTL,
430                   IG4_CTL_MASTER |
431                   IG4_CTL_SLAVE_DISABLE |
432                   IG4_CTL_RESTARTEN |
433                   IG4_CTL_SPEED_STD);
434
435         sc->smb = device_add_child(sc->dev, "smbus", -1);
436         if (sc->smb == NULL) {
437                 device_printf(sc->dev, "smbus driver not found\n");
438                 error = ENXIO;
439                 goto done;
440         }
441
442 #if 0
443         /*
444          * Don't do this, it blows up the PCI config
445          */
446         reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT);
447         reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
448 #endif
449         reg_write(sc, IG4_REG_INTR_MASK, 0);
450         if (set_controller(sc, 0))
451                 device_printf(sc->dev, "controller error during attach-1\n");
452         if (set_controller(sc, IG4_I2C_ENABLE))
453                 device_printf(sc->dev, "controller error during attach-2\n");
454         error = bus_setup_intr(sc->dev, sc->intr_res, 0,
455                                ig4iic_intr, sc, &sc->intr_handle, NULL);
456         if (error) {
457                 device_printf(sc->dev,
458                               "Unable to setup irq: error %d\n", error);
459                 goto done;
460         }
461
462         /* Attach us to the smbus */
463         lockmgr(&sc->lk, LK_RELEASE);
464         error = bus_generic_attach(sc->dev);
465         lockmgr(&sc->lk, LK_EXCLUSIVE);
466         if (error) {
467                 device_printf(sc->dev,
468                               "failed to attach child: error %d\n", error);
469                 goto done;
470         }
471         sc->generic_attached = 1;
472
473 done:
474         lockmgr(&sc->lk, LK_RELEASE);
475         return error;
476 }
477
478 int
479 ig4iic_detach(ig4iic_softc_t *sc)
480 {
481         int error;
482
483         lockmgr(&sc->lk, LK_EXCLUSIVE);
484
485         reg_write(sc, IG4_REG_INTR_MASK, 0);
486         reg_read(sc, IG4_REG_CLR_INTR);
487         set_controller(sc, 0);
488
489         if (sc->generic_attached) {
490                 error = bus_generic_detach(sc->dev);
491                 if (error)
492                         goto done;
493                 sc->generic_attached = 0;
494         }
495         if (sc->smb) {
496                 device_delete_child(sc->dev, sc->smb);
497                 sc->smb = NULL;
498         }
499         if (sc->intr_handle) {
500                 bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
501                 sc->intr_handle = NULL;
502         }
503
504         error = 0;
505 done:
506         lockmgr(&sc->lk, LK_RELEASE);
507         return error;
508 }
509
510 int
511 ig4iic_smb_callback(device_t dev, int index, void *data)
512 {
513         ig4iic_softc_t *sc = device_get_softc(dev);
514         int error;
515
516         lockmgr(&sc->lk, LK_EXCLUSIVE);
517
518         switch (index) {
519         case SMB_REQUEST_BUS:
520                 error = 0;
521                 break;
522         case SMB_RELEASE_BUS:
523                 error = 0;
524                 break;
525         default:
526                 error = SMB_EABORT;
527                 break;
528         }
529
530         lockmgr(&sc->lk, LK_RELEASE);
531
532         return error;
533 }
534
535 /*
536  * Quick command.  i.e. START + cmd + R/W + STOP and no data.  It is
537  * unclear to me how I could implement this with the intel i2c controller
538  * because the controler sends STARTs and STOPs automatically with data.
539  */
540 int
541 ig4iic_smb_quick(device_t dev, u_char slave, int how)
542 {
543         ig4iic_softc_t *sc = device_get_softc(dev);
544         int error;
545
546         lockmgr(&sc->lk, LK_EXCLUSIVE);
547
548         switch (how) {
549         case SMB_QREAD:
550                 error = SMB_ENOTSUPP;
551                 break;
552         case SMB_QWRITE:
553                 error = SMB_ENOTSUPP;
554                 break;
555         default:
556                 error = SMB_ENOTSUPP;
557                 break;
558         }
559         lockmgr(&sc->lk, LK_RELEASE);
560
561         return error;
562 }
563
564 /*
565  * Incremental send byte without stop (?).  It is unclear why the slave
566  * address is specified if this presumably is used in combination with
567  * ig4iic_smb_quick().
568  *
569  * (Also, how would this work anyway?  Issue the last byte with writeb()?)
570  */
571 int
572 ig4iic_smb_sendb(device_t dev, u_char slave, char byte)
573 {
574         ig4iic_softc_t *sc = device_get_softc(dev);
575         uint32_t cmd;
576         int error;
577
578         lockmgr(&sc->lk, LK_EXCLUSIVE);
579
580         set_slave_addr(sc, slave, 0);
581         cmd = byte;
582         if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) {
583                 reg_write(sc, IG4_REG_DATA_CMD, cmd);
584                 error = 0;
585         } else {
586                 error = SMB_ETIMEOUT;
587         }
588
589         lockmgr(&sc->lk, LK_RELEASE);
590         return error;
591 }
592
593 /*
594  * Incremental receive byte without stop (?).  It is unclear why the slave
595  * address is specified if this presumably is used in combination with
596  * ig4iic_smb_quick().
597  */
598 int
599 ig4iic_smb_recvb(device_t dev, u_char slave, char *byte)
600 {
601         ig4iic_softc_t *sc = device_get_softc(dev);
602         int error;
603
604         lockmgr(&sc->lk, LK_EXCLUSIVE);
605
606         set_slave_addr(sc, slave, 0);
607         reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD);
608         if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) {
609                 *byte = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
610                 error = 0;
611         } else {
612                 *byte = 0;
613                 error = SMB_ETIMEOUT;
614         }
615
616         lockmgr(&sc->lk, LK_RELEASE);
617         return error;
618 }
619
620 /*
621  * Write command and single byte in transaction.
622  */
623 int
624 ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
625 {
626         ig4iic_softc_t *sc = device_get_softc(dev);
627         int error;
628
629         lockmgr(&sc->lk, LK_EXCLUSIVE);
630
631         set_slave_addr(sc, slave, 0);
632         error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
633                                 &byte, 1, NULL, 0, NULL);
634
635         lockmgr(&sc->lk, LK_RELEASE);
636         return error;
637 }
638
639 /*
640  * Write command and single word in transaction.
641  */
642 int
643 ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word)
644 {
645         ig4iic_softc_t *sc = device_get_softc(dev);
646         char buf[2];
647         int error;
648
649         lockmgr(&sc->lk, LK_EXCLUSIVE);
650
651         set_slave_addr(sc, slave, 0);
652         buf[0] = word & 0xFF;
653         buf[1] = word >> 8;
654         error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
655                                 buf, 2, NULL, 0, NULL);
656
657         lockmgr(&sc->lk, LK_RELEASE);
658         return error;
659 }
660
661 /*
662  * write command and read single byte in transaction.
663  */
664 int
665 ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
666 {
667         ig4iic_softc_t *sc = device_get_softc(dev);
668         int error;
669
670         lockmgr(&sc->lk, LK_EXCLUSIVE);
671
672         set_slave_addr(sc, slave, 0);
673         error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
674                                 NULL, 0, byte, 1, NULL);
675
676         lockmgr(&sc->lk, LK_RELEASE);
677         return error;
678 }
679
680 /*
681  * write command and read word in transaction.
682  */
683 int
684 ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word)
685 {
686         ig4iic_softc_t *sc = device_get_softc(dev);
687         char buf[2];
688         int error;
689
690         lockmgr(&sc->lk, LK_EXCLUSIVE);
691
692         set_slave_addr(sc, slave, 0);
693         if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
694                                      NULL, 0, buf, 2, NULL)) == 0) {
695                 *word = (u_char)buf[0] | ((u_char)buf[1] << 8);
696         }
697
698         lockmgr(&sc->lk, LK_RELEASE);
699         return error;
700 }
701
702 /*
703  * write command and word and read word in transaction
704  */
705 int
706 ig4iic_smb_pcall(device_t dev, u_char slave, char cmd,
707                  short sdata, short *rdata)
708 {
709         ig4iic_softc_t *sc = device_get_softc(dev);
710         char rbuf[2];
711         char wbuf[2];
712         int error;
713
714         lockmgr(&sc->lk, LK_EXCLUSIVE);
715
716         set_slave_addr(sc, slave, 0);
717         wbuf[0] = sdata & 0xFF;
718         wbuf[1] = sdata >> 8;
719         if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
720                                      wbuf, 2, rbuf, 2, NULL)) == 0) {
721                 *rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8);
722         }
723
724         lockmgr(&sc->lk, LK_RELEASE);
725         return error;
726 }
727
728 int
729 ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd,
730                   u_char wcount, char *buf)
731 {
732         ig4iic_softc_t *sc = device_get_softc(dev);
733         int error;
734
735         lockmgr(&sc->lk, LK_EXCLUSIVE);
736
737         set_slave_addr(sc, slave, 0);
738         error = smb_transaction(sc, cmd, 0,
739                                 buf, wcount, NULL, 0, NULL);
740
741         lockmgr(&sc->lk, LK_RELEASE);
742         return error;
743 }
744
745 int
746 ig4iic_smb_bread(device_t dev, u_char slave, char cmd,
747                  u_char *countp_char, char *buf)
748 {
749         ig4iic_softc_t *sc = device_get_softc(dev);
750         int rcount = *countp_char;
751         int error;
752
753         lockmgr(&sc->lk, LK_EXCLUSIVE);
754
755         set_slave_addr(sc, slave, 0);
756         error = smb_transaction(sc, cmd, 0,
757                                 NULL, 0, buf, rcount, &rcount);
758         *countp_char = rcount;
759
760         lockmgr(&sc->lk, LK_RELEASE);
761         return error;
762 }
763
764 int
765 ig4iic_smb_trans(device_t dev, int slave, char cmd, int op,
766                  char *wbuf, int wcount, char *rbuf, int rcount,
767                  int *actualp)
768 {
769         ig4iic_softc_t *sc = device_get_softc(dev);
770         int error;
771
772         lockmgr(&sc->lk, LK_EXCLUSIVE);
773
774         set_slave_addr(sc, slave, op);
775         error = smb_transaction(sc, cmd, op,
776                                 wbuf, wcount, rbuf, rcount, actualp);
777
778         lockmgr(&sc->lk, LK_RELEASE);
779         return error;
780 }
781
782 /*
783  * Interrupt Operation
784  */
785 static
786 void
787 ig4iic_intr(void *cookie)
788 {
789         ig4iic_softc_t *sc = cookie;
790
791         lockmgr(&sc->lk, LK_EXCLUSIVE);
792         kprintf("I");
793         reg_write(sc, IG4_REG_INTR_MASK, 0);
794         reg_read(sc, IG4_REG_CLR_INTR);
795         lockmgr(&sc->lk, LK_RELEASE);
796 }
797
798 DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL);