138774Snsouch/*- 293023Snsouch * Copyright (c) 1998, 2001 Nicolas Souchu 338774Snsouch * All rights reserved. 438774Snsouch * 538774Snsouch * Redistribution and use in source and binary forms, with or without 638774Snsouch * modification, are permitted provided that the following conditions 738774Snsouch * are met: 838774Snsouch * 1. Redistributions of source code must retain the above copyright 938774Snsouch * notice, this list of conditions and the following disclaimer. 1038774Snsouch * 2. Redistributions in binary form must reproduce the above copyright 1138774Snsouch * notice, this list of conditions and the following disclaimer in the 1238774Snsouch * documentation and/or other materials provided with the distribution. 1338774Snsouch * 1438774Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538774Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638774Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738774Snsouch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838774Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938774Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038774Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138774Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238774Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338774Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438774Snsouch * SUCH DAMAGE. 2538774Snsouch */ 2638774Snsouch 27227843Smarius#include <sys/cdefs.h> 28227843Smarius__FBSDID("$FreeBSD: releng/10.3/sys/dev/iicbus/iicsmb.c 294490 2016-01-21 08:32:11Z dumbbell $"); 29227843Smarius 3038774Snsouch/* 3138774Snsouch * I2C to SMB bridge 3240782Snsouch * 3340782Snsouch * Example: 3440782Snsouch * 3540782Snsouch * smb bttv 3640782Snsouch * \ / 3740782Snsouch * smbus 3840782Snsouch * / \ 3940782Snsouch * iicsmb bti2c 4040782Snsouch * | 4140782Snsouch * iicbus 4240782Snsouch * / | \ 4340782Snsouch * iicbb pcf ... 4440782Snsouch * | 4540782Snsouch * lpbb 4638774Snsouch */ 4738774Snsouch 4838774Snsouch#include <sys/param.h> 49179624Sjhb#include <sys/bus.h> 5038774Snsouch#include <sys/kernel.h> 51179624Sjhb#include <sys/lock.h> 52179624Sjhb#include <sys/module.h> 53179624Sjhb#include <sys/mutex.h> 5438774Snsouch#include <sys/systm.h> 5538774Snsouch#include <sys/uio.h> 5638774Snsouch 5738774Snsouch#include <dev/iicbus/iiconf.h> 5838774Snsouch#include <dev/iicbus/iicbus.h> 5938774Snsouch 6038774Snsouch#include <dev/smbus/smbconf.h> 6138774Snsouch 6238774Snsouch#include "iicbus_if.h" 6338774Snsouch#include "smbus_if.h" 6438774Snsouch 6538774Snsouchstruct iicsmb_softc { 6638774Snsouch 6738774Snsouch#define SMB_WAITING_ADDR 0x0 6838774Snsouch#define SMB_WAITING_LOW 0x1 6938774Snsouch#define SMB_WAITING_HIGH 0x2 7038774Snsouch#define SMB_DONE 0x3 7138774Snsouch int state; 7238774Snsouch 7338774Snsouch u_char devaddr; /* slave device address */ 7438774Snsouch 7538774Snsouch char low; /* low byte received first */ 7638774Snsouch char high; /* high byte */ 7738774Snsouch 78181304Sjhb struct mtx lock; 7938774Snsouch device_t smbus; 8038774Snsouch}; 8138774Snsouch 8238774Snsouchstatic int iicsmb_probe(device_t); 8338774Snsouchstatic int iicsmb_attach(device_t); 8493023Snsouchstatic int iicsmb_detach(device_t); 8593023Snsouchstatic void iicsmb_identify(driver_t *driver, device_t parent); 8638774Snsouch 87188461Simpstatic int iicsmb_intr(device_t dev, int event, char *buf); 88162234Sjhbstatic int iicsmb_callback(device_t dev, int index, void *data); 8938774Snsouchstatic int iicsmb_quick(device_t dev, u_char slave, int how); 9038774Snsouchstatic int iicsmb_sendb(device_t dev, u_char slave, char byte); 9138774Snsouchstatic int iicsmb_recvb(device_t dev, u_char slave, char *byte); 9238774Snsouchstatic int iicsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 9338774Snsouchstatic int iicsmb_writew(device_t dev, u_char slave, char cmd, short word); 9438774Snsouchstatic int iicsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 9538774Snsouchstatic int iicsmb_readw(device_t dev, u_char slave, char cmd, short *word); 9638774Snsouchstatic int iicsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 9738774Snsouchstatic int iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 98162234Sjhbstatic int iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); 9938774Snsouch 10038774Snsouchstatic devclass_t iicsmb_devclass; 10138774Snsouch 10238774Snsouchstatic device_method_t iicsmb_methods[] = { 10338774Snsouch /* device interface */ 10493023Snsouch DEVMETHOD(device_identify, iicsmb_identify), 10538774Snsouch DEVMETHOD(device_probe, iicsmb_probe), 10638774Snsouch DEVMETHOD(device_attach, iicsmb_attach), 10793023Snsouch DEVMETHOD(device_detach, iicsmb_detach), 10838774Snsouch 10938774Snsouch /* iicbus interface */ 11038774Snsouch DEVMETHOD(iicbus_intr, iicsmb_intr), 11138774Snsouch 11238774Snsouch /* smbus interface */ 11340782Snsouch DEVMETHOD(smbus_callback, iicsmb_callback), 11438774Snsouch DEVMETHOD(smbus_quick, iicsmb_quick), 11538774Snsouch DEVMETHOD(smbus_sendb, iicsmb_sendb), 11638774Snsouch DEVMETHOD(smbus_recvb, iicsmb_recvb), 11738774Snsouch DEVMETHOD(smbus_writeb, iicsmb_writeb), 11838774Snsouch DEVMETHOD(smbus_writew, iicsmb_writew), 11938774Snsouch DEVMETHOD(smbus_readb, iicsmb_readb), 12038774Snsouch DEVMETHOD(smbus_readw, iicsmb_readw), 12138774Snsouch DEVMETHOD(smbus_pcall, iicsmb_pcall), 12238774Snsouch DEVMETHOD(smbus_bwrite, iicsmb_bwrite), 12338774Snsouch DEVMETHOD(smbus_bread, iicsmb_bread), 124227843Smarius 125227843Smarius DEVMETHOD_END 12638774Snsouch}; 12738774Snsouch 12838774Snsouchstatic driver_t iicsmb_driver = { 12938774Snsouch "iicsmb", 13038774Snsouch iicsmb_methods, 13138774Snsouch sizeof(struct iicsmb_softc), 13238774Snsouch}; 13338774Snsouch 13493023Snsouch#define IICBUS_TIMEOUT 100 /* us */ 13593023Snsouch 13693023Snsouchstatic void 13793023Snsouchiicsmb_identify(driver_t *driver, device_t parent) 13893023Snsouch{ 139181304Sjhb 140181304Sjhb if (device_find_child(parent, "iicsmb", -1) == NULL) 141181304Sjhb BUS_ADD_CHILD(parent, 0, "iicsmb", -1); 14293023Snsouch} 14393023Snsouch 14438774Snsouchstatic int 14538774Snsouchiicsmb_probe(device_t dev) 14638774Snsouch{ 14793023Snsouch device_set_desc(dev, "SMBus over I2C bridge"); 148186833Snwhitehorn return (BUS_PROBE_NOWILDCARD); 14938774Snsouch} 15038774Snsouch 15138774Snsouchstatic int 15238774Snsouchiicsmb_attach(device_t dev) 15338774Snsouch{ 15438774Snsouch struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); 15538774Snsouch 156181304Sjhb mtx_init(&sc->lock, "iicsmb", NULL, MTX_DEF); 157181304Sjhb 15893023Snsouch sc->smbus = device_add_child(dev, "smbus", -1); 15993023Snsouch 16038774Snsouch /* probe and attach the smbus */ 16193023Snsouch bus_generic_attach(dev); 16238774Snsouch 16338774Snsouch return (0); 16438774Snsouch} 16538774Snsouch 16693023Snsouchstatic int 16793023Snsouchiicsmb_detach(device_t dev) 16893023Snsouch{ 16993023Snsouch struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); 170294490Sdumbbell 17193023Snsouch bus_generic_detach(dev); 172294490Sdumbbell device_delete_children(dev); 173181304Sjhb mtx_destroy(&sc->lock); 17493023Snsouch 17593023Snsouch return (0); 17693023Snsouch} 17793023Snsouch 17838774Snsouch/* 17938774Snsouch * iicsmb_intr() 18038774Snsouch * 18138774Snsouch * iicbus interrupt handler 18238774Snsouch */ 183188461Simpstatic int 18438774Snsouchiicsmb_intr(device_t dev, int event, char *buf) 18538774Snsouch{ 18638774Snsouch struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); 18738774Snsouch 188181304Sjhb mtx_lock(&sc->lock); 18938774Snsouch switch (event) { 19038774Snsouch case INTR_GENERAL: 19138774Snsouch case INTR_START: 19238774Snsouch sc->state = SMB_WAITING_ADDR; 19338774Snsouch break; 19438774Snsouch 19538774Snsouch case INTR_STOP: 19638774Snsouch /* call smbus intr handler */ 19738774Snsouch smbus_intr(sc->smbus, sc->devaddr, 19838774Snsouch sc->low, sc->high, SMB_ENOERR); 19938774Snsouch break; 20038774Snsouch 20138774Snsouch case INTR_RECEIVE: 20238774Snsouch switch (sc->state) { 20338774Snsouch case SMB_DONE: 20438774Snsouch /* XXX too much data, discard */ 20587599Sobrien printf("%s: too much data from 0x%x\n", __func__, 20638774Snsouch sc->devaddr & 0xff); 20738774Snsouch goto end; 20838774Snsouch 20938774Snsouch case SMB_WAITING_ADDR: 21038774Snsouch sc->devaddr = (u_char)*buf; 21138774Snsouch sc->state = SMB_WAITING_LOW; 21238774Snsouch break; 21338774Snsouch 21438774Snsouch case SMB_WAITING_LOW: 21538774Snsouch sc->low = *buf; 21638774Snsouch sc->state = SMB_WAITING_HIGH; 21738774Snsouch break; 21838774Snsouch 21938774Snsouch case SMB_WAITING_HIGH: 22038774Snsouch sc->high = *buf; 22138774Snsouch sc->state = SMB_DONE; 22238774Snsouch break; 22338774Snsouch } 22438774Snsouchend: 22538774Snsouch break; 22638774Snsouch 22738774Snsouch case INTR_TRANSMIT: 22838774Snsouch case INTR_NOACK: 22938774Snsouch break; 23038774Snsouch 23138774Snsouch case INTR_ERROR: 23238774Snsouch switch (*buf) { 23338774Snsouch case IIC_EBUSERR: 23438774Snsouch smbus_intr(sc->smbus, sc->devaddr, 0, 0, SMB_EBUSERR); 23538774Snsouch break; 23638774Snsouch 23738774Snsouch default: 23887599Sobrien printf("%s unknown error 0x%x!\n", __func__, 23938774Snsouch (int)*buf); 24038774Snsouch break; 24138774Snsouch } 24238774Snsouch break; 24338774Snsouch 24438774Snsouch default: 24587599Sobrien panic("%s: unknown event (%d)!", __func__, event); 24638774Snsouch } 247181304Sjhb mtx_unlock(&sc->lock); 24838774Snsouch 249188461Simp return (0); 25038774Snsouch} 25138774Snsouch 25238774Snsouchstatic int 253162234Sjhbiicsmb_callback(device_t dev, int index, void *data) 25440782Snsouch{ 25540782Snsouch device_t parent = device_get_parent(dev); 25640782Snsouch int error = 0; 25740782Snsouch int how; 25840782Snsouch 25940782Snsouch switch (index) { 26040782Snsouch case SMB_REQUEST_BUS: 26140782Snsouch /* request underlying iicbus */ 26240782Snsouch how = *(int *)data; 26340782Snsouch error = iicbus_request_bus(parent, dev, how); 26440782Snsouch break; 26540782Snsouch 26640782Snsouch case SMB_RELEASE_BUS: 26740782Snsouch /* release underlying iicbus */ 26840782Snsouch error = iicbus_release_bus(parent, dev); 26940782Snsouch break; 27040782Snsouch 27140782Snsouch default: 27240782Snsouch error = EINVAL; 27340782Snsouch } 27440782Snsouch 27540782Snsouch return (error); 27640782Snsouch} 27740782Snsouch 27840782Snsouchstatic int 27938774Snsouchiicsmb_quick(device_t dev, u_char slave, int how) 28038774Snsouch{ 28138774Snsouch device_t parent = device_get_parent(dev); 28238774Snsouch int error; 28338774Snsouch 28438774Snsouch switch (how) { 28538774Snsouch case SMB_QWRITE: 28693023Snsouch error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT); 28738774Snsouch break; 28838774Snsouch 28938774Snsouch case SMB_QREAD: 29093023Snsouch error = iicbus_start(parent, slave | LSB, IICBUS_TIMEOUT); 29138774Snsouch break; 29238774Snsouch 29338774Snsouch default: 29438774Snsouch error = EINVAL; 29538774Snsouch break; 29638774Snsouch } 29738774Snsouch 29838774Snsouch if (!error) 29938774Snsouch error = iicbus_stop(parent); 300179624Sjhb 30138774Snsouch return (error); 30238774Snsouch} 30338774Snsouch 30438774Snsouchstatic int 30538774Snsouchiicsmb_sendb(device_t dev, u_char slave, char byte) 30638774Snsouch{ 30738774Snsouch device_t parent = device_get_parent(dev); 30838774Snsouch int error, sent; 30938774Snsouch 31093023Snsouch error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT); 31138774Snsouch 31238774Snsouch if (!error) { 31393023Snsouch error = iicbus_write(parent, &byte, 1, &sent, IICBUS_TIMEOUT); 31438774Snsouch 31538774Snsouch iicbus_stop(parent); 31638774Snsouch } 31738774Snsouch 31838774Snsouch return (error); 31938774Snsouch} 32038774Snsouch 32138774Snsouchstatic int 32238774Snsouchiicsmb_recvb(device_t dev, u_char slave, char *byte) 32338774Snsouch{ 32438774Snsouch device_t parent = device_get_parent(dev); 32538774Snsouch int error, read; 32638774Snsouch 32740782Snsouch error = iicbus_start(parent, slave | LSB, 0); 32838774Snsouch 32940782Snsouch if (!error) { 33093023Snsouch error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, IICBUS_TIMEOUT); 33138774Snsouch 33240782Snsouch iicbus_stop(parent); 33340782Snsouch } 33440782Snsouch 33538774Snsouch return (error); 33638774Snsouch} 33738774Snsouch 33838774Snsouchstatic int 33938774Snsouchiicsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 34038774Snsouch{ 34138774Snsouch device_t parent = device_get_parent(dev); 34238774Snsouch int error, sent; 34338774Snsouch 34440782Snsouch error = iicbus_start(parent, slave & ~LSB, 0); 34538774Snsouch 34638774Snsouch if (!error) { 34793023Snsouch if (!(error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 34893023Snsouch error = iicbus_write(parent, &byte, 1, &sent, IICBUS_TIMEOUT); 34938774Snsouch 35038774Snsouch iicbus_stop(parent); 35138774Snsouch } 35238774Snsouch 35338774Snsouch return (error); 35438774Snsouch} 35538774Snsouch 35638774Snsouchstatic int 35738774Snsouchiicsmb_writew(device_t dev, u_char slave, char cmd, short word) 35838774Snsouch{ 35938774Snsouch device_t parent = device_get_parent(dev); 36038774Snsouch int error, sent; 36138774Snsouch 36238774Snsouch char low = (char)(word & 0xff); 36338774Snsouch char high = (char)((word & 0xff00) >> 8); 36438774Snsouch 36540782Snsouch error = iicbus_start(parent, slave & ~LSB, 0); 36638774Snsouch 36738774Snsouch if (!error) { 36893023Snsouch if (!(error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 36993023Snsouch if (!(error = iicbus_write(parent, &low, 1, &sent, IICBUS_TIMEOUT))) 37093023Snsouch error = iicbus_write(parent, &high, 1, &sent, IICBUS_TIMEOUT); 37138774Snsouch 37238774Snsouch iicbus_stop(parent); 37338774Snsouch } 37438774Snsouch 37538774Snsouch return (error); 37638774Snsouch} 37738774Snsouch 37838774Snsouchstatic int 37938774Snsouchiicsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 38038774Snsouch{ 38138774Snsouch device_t parent = device_get_parent(dev); 38238774Snsouch int error, sent, read; 38338774Snsouch 384181304Sjhb if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT))) 38540782Snsouch return (error); 38638774Snsouch 38793023Snsouch if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 38838774Snsouch goto error; 38938774Snsouch 39093023Snsouch if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT))) 39138774Snsouch goto error; 39238774Snsouch 39393023Snsouch if ((error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, IICBUS_TIMEOUT))) 39438774Snsouch goto error; 39538774Snsouch 39638774Snsoucherror: 39740782Snsouch iicbus_stop(parent); 39838774Snsouch return (error); 39938774Snsouch} 40038774Snsouch 40138774Snsouch#define BUF2SHORT(low,high) \ 40238774Snsouch ((short)(((high) & 0xff) << 8) | (short)((low) & 0xff)) 40338774Snsouch 40438774Snsouchstatic int 40538774Snsouchiicsmb_readw(device_t dev, u_char slave, char cmd, short *word) 40638774Snsouch{ 40738774Snsouch device_t parent = device_get_parent(dev); 40838774Snsouch int error, sent, read; 40938774Snsouch char buf[2]; 41038774Snsouch 411181304Sjhb if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT))) 41240782Snsouch return (error); 41338774Snsouch 41493023Snsouch if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 41538774Snsouch goto error; 41638774Snsouch 41793023Snsouch if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT))) 41838774Snsouch goto error; 41938774Snsouch 42093023Snsouch if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, IICBUS_TIMEOUT))) 42138774Snsouch goto error; 42238774Snsouch 42338774Snsouch /* first, receive low, then high byte */ 42438774Snsouch *word = BUF2SHORT(buf[0], buf[1]); 42538774Snsouch 42638774Snsoucherror: 42740782Snsouch iicbus_stop(parent); 42838774Snsouch return (error); 42938774Snsouch} 43038774Snsouch 43138774Snsouchstatic int 43238774Snsouchiicsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 43338774Snsouch{ 43438774Snsouch device_t parent = device_get_parent(dev); 43538774Snsouch int error, sent, read; 43638774Snsouch char buf[2]; 43738774Snsouch 438181304Sjhb if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT))) 43940782Snsouch return (error); 44038774Snsouch 44193023Snsouch if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 44238774Snsouch goto error; 44338774Snsouch 44438774Snsouch /* first, send low, then high byte */ 44538774Snsouch buf[0] = (char)(sdata & 0xff); 44638774Snsouch buf[1] = (char)((sdata & 0xff00) >> 8); 44738774Snsouch 44893023Snsouch if ((error = iicbus_write(parent, buf, 2, &sent, IICBUS_TIMEOUT))) 44938774Snsouch goto error; 45038774Snsouch 45193023Snsouch if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT))) 45238774Snsouch goto error; 45338774Snsouch 45493023Snsouch if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, IICBUS_TIMEOUT))) 45538774Snsouch goto error; 45638774Snsouch 45738774Snsouch /* first, receive low, then high byte */ 45838774Snsouch *rdata = BUF2SHORT(buf[0], buf[1]); 45938774Snsouch 46038774Snsoucherror: 46140782Snsouch iicbus_stop(parent); 46238774Snsouch return (error); 46338774Snsouch} 46438774Snsouch 46538774Snsouchstatic int 46638774Snsouchiicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 46738774Snsouch{ 46838774Snsouch device_t parent = device_get_parent(dev); 46938774Snsouch int error, sent; 47038774Snsouch 47193023Snsouch if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT))) 47238774Snsouch goto error; 47338774Snsouch 47493023Snsouch if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 47538774Snsouch goto error; 47638774Snsouch 47793023Snsouch if ((error = iicbus_write(parent, buf, (int)count, &sent, IICBUS_TIMEOUT))) 47838774Snsouch goto error; 47938774Snsouch 48038774Snsouch if ((error = iicbus_stop(parent))) 48138774Snsouch goto error; 48238774Snsouch 48338774Snsoucherror: 48438774Snsouch return (error); 48538774Snsouch} 48638774Snsouch 48738774Snsouchstatic int 488162234Sjhbiicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 48938774Snsouch{ 49038774Snsouch device_t parent = device_get_parent(dev); 49138774Snsouch int error, sent, read; 49238774Snsouch 493181304Sjhb if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT))) 49440782Snsouch return (error); 49538774Snsouch 49693023Snsouch if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT))) 49738774Snsouch goto error; 49838774Snsouch 49993023Snsouch if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT))) 50038774Snsouch goto error; 50138774Snsouch 502162234Sjhb if ((error = iicbus_read(parent, buf, (int)*count, &read, 50393023Snsouch IIC_LAST_READ, IICBUS_TIMEOUT))) 50438774Snsouch goto error; 505162234Sjhb *count = read; 50638774Snsouch 50738774Snsoucherror: 50840782Snsouch iicbus_stop(parent); 50938774Snsouch return (error); 51038774Snsouch} 51138774Snsouch 51238774SnsouchDRIVER_MODULE(iicsmb, iicbus, iicsmb_driver, iicsmb_devclass, 0, 0); 513162234SjhbDRIVER_MODULE(smbus, iicsmb, smbus_driver, smbus_devclass, 0, 0); 51493023SnsouchMODULE_DEPEND(iicsmb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 51593023SnsouchMODULE_DEPEND(iicsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 51693023SnsouchMODULE_VERSION(iicsmb, 1); 517