1ca2e4ecdSMichael Gmelin /*- 2ca2e4ecdSMichael Gmelin * Copyright (c) 2015 Michael Gmelin <freebsd@grem.de> 3ca2e4ecdSMichael Gmelin * All rights reserved. 4ca2e4ecdSMichael Gmelin * 5ca2e4ecdSMichael Gmelin * Redistribution and use in source and binary forms, with or without 6ca2e4ecdSMichael Gmelin * modification, are permitted provided that the following conditions 7ca2e4ecdSMichael Gmelin * are met: 8ca2e4ecdSMichael Gmelin * 1. Redistributions of source code must retain the above copyright 9ca2e4ecdSMichael Gmelin * notice, this list of conditions and the following disclaimer. 10ca2e4ecdSMichael Gmelin * 2. Redistributions in binary form must reproduce the above copyright 11ca2e4ecdSMichael Gmelin * notice, this list of conditions and the following disclaimer in the 12ca2e4ecdSMichael Gmelin * documentation and/or other materials provided with the distribution. 13ca2e4ecdSMichael Gmelin * 14ca2e4ecdSMichael Gmelin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ca2e4ecdSMichael Gmelin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ca2e4ecdSMichael Gmelin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ca2e4ecdSMichael Gmelin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ca2e4ecdSMichael Gmelin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ca2e4ecdSMichael Gmelin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ca2e4ecdSMichael Gmelin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ca2e4ecdSMichael Gmelin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ca2e4ecdSMichael Gmelin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ca2e4ecdSMichael Gmelin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ca2e4ecdSMichael Gmelin * SUCH DAMAGE. 25ca2e4ecdSMichael Gmelin */ 26ca2e4ecdSMichael Gmelin 27ca2e4ecdSMichael Gmelin #include <sys/cdefs.h> 28ca2e4ecdSMichael Gmelin __FBSDID("$FreeBSD$"); 29ca2e4ecdSMichael Gmelin 30ca2e4ecdSMichael Gmelin /* 31ca2e4ecdSMichael Gmelin * Driver for intersil I2C ISL29018 Digital Ambient Light Sensor and Proximity 32ca2e4ecdSMichael Gmelin * Sensor with Interrupt Function, only tested connected over SMBus (ig4iic). 33ca2e4ecdSMichael Gmelin * 34ca2e4ecdSMichael Gmelin * Datasheet: 35ca2e4ecdSMichael Gmelin * http://www.intersil.com/en/products/optoelectronics/ambient-light-and-proximity-sensors/light-to-digital-sensors/ISL29018.html 36ca2e4ecdSMichael Gmelin * http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29018.pdf 37ca2e4ecdSMichael Gmelin */ 38ca2e4ecdSMichael Gmelin 39ca2e4ecdSMichael Gmelin #include <sys/param.h> 40ca2e4ecdSMichael Gmelin #include <sys/bus.h> 41ca2e4ecdSMichael Gmelin #include <sys/conf.h> 42ca2e4ecdSMichael Gmelin #include <sys/event.h> 43ca2e4ecdSMichael Gmelin #include <sys/fcntl.h> 44ca2e4ecdSMichael Gmelin #include <sys/kernel.h> 45ca2e4ecdSMichael Gmelin #include <sys/lock.h> 46ca2e4ecdSMichael Gmelin #include <sys/lockmgr.h> 47ca2e4ecdSMichael Gmelin #include <sys/malloc.h> 48ca2e4ecdSMichael Gmelin #include <sys/mbuf.h> 49ca2e4ecdSMichael Gmelin #include <sys/module.h> 50ca2e4ecdSMichael Gmelin #include <sys/poll.h> 51ca2e4ecdSMichael Gmelin #include <sys/sx.h> 52ca2e4ecdSMichael Gmelin #include <sys/sysctl.h> 53ca2e4ecdSMichael Gmelin #include <sys/systm.h> 54ca2e4ecdSMichael Gmelin #include <sys/systm.h> 55ca2e4ecdSMichael Gmelin 56*448897d3SAndriy Gapon #include <dev/iicbus/iiconf.h> 57*448897d3SAndriy Gapon #include <dev/iicbus/iicbus.h> 58ca2e4ecdSMichael Gmelin #include <dev/isl/isl.h> 59ca2e4ecdSMichael Gmelin 60*448897d3SAndriy Gapon #include "iicbus_if.h" 61ca2e4ecdSMichael Gmelin #include "bus_if.h" 62ca2e4ecdSMichael Gmelin #include "device_if.h" 63ca2e4ecdSMichael Gmelin 64ca2e4ecdSMichael Gmelin #define ISL_METHOD_ALS 0x10 65ca2e4ecdSMichael Gmelin #define ISL_METHOD_IR 0x11 66ca2e4ecdSMichael Gmelin #define ISL_METHOD_PROX 0x12 67ca2e4ecdSMichael Gmelin #define ISL_METHOD_RESOLUTION 0x13 68ca2e4ecdSMichael Gmelin #define ISL_METHOD_RANGE 0x14 69ca2e4ecdSMichael Gmelin 70ca2e4ecdSMichael Gmelin struct isl_softc { 71ca2e4ecdSMichael Gmelin device_t dev; 72ca2e4ecdSMichael Gmelin struct sx isl_sx; 73ca2e4ecdSMichael Gmelin }; 74ca2e4ecdSMichael Gmelin 75ca2e4ecdSMichael Gmelin /* Returns < 0 on problem. */ 76*448897d3SAndriy Gapon static int isl_read_sensor(device_t dev, uint8_t cmd_mask); 77*448897d3SAndriy Gapon 78*448897d3SAndriy Gapon static int 79*448897d3SAndriy Gapon isl_read_byte(device_t dev, uint8_t reg, uint8_t *val) 80*448897d3SAndriy Gapon { 81*448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 82*448897d3SAndriy Gapon struct iic_msg msgs[] = { 83*448897d3SAndriy Gapon { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 84*448897d3SAndriy Gapon { addr, IIC_M_RD, 1, val }, 85*448897d3SAndriy Gapon }; 86*448897d3SAndriy Gapon 87*448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 88*448897d3SAndriy Gapon } 89*448897d3SAndriy Gapon 90*448897d3SAndriy Gapon static int 91*448897d3SAndriy Gapon isl_write_byte(device_t dev, uint8_t reg, uint8_t val) 92*448897d3SAndriy Gapon { 93*448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 94*448897d3SAndriy Gapon uint8_t bytes[] = { reg, val }; 95*448897d3SAndriy Gapon struct iic_msg msgs[] = { 96*448897d3SAndriy Gapon { addr, IIC_M_WR, nitems(bytes), bytes }, 97*448897d3SAndriy Gapon }; 98*448897d3SAndriy Gapon 99*448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 100*448897d3SAndriy Gapon } 101ca2e4ecdSMichael Gmelin 102ca2e4ecdSMichael Gmelin /* 103ca2e4ecdSMichael Gmelin * Initialize the device 104ca2e4ecdSMichael Gmelin */ 10512e413beSMichael Gmelin static int 106*448897d3SAndriy Gapon init_device(device_t dev, int probe) 107ca2e4ecdSMichael Gmelin { 108ca2e4ecdSMichael Gmelin int error; 109ca2e4ecdSMichael Gmelin 110ca2e4ecdSMichael Gmelin /* 111ca2e4ecdSMichael Gmelin * init procedure: send 0x00 to test ref and cmd reg 1 112ca2e4ecdSMichael Gmelin */ 113*448897d3SAndriy Gapon error = isl_write_byte(dev, REG_TEST, 0); 114ca2e4ecdSMichael Gmelin if (error) 115ca2e4ecdSMichael Gmelin goto done; 116*448897d3SAndriy Gapon error = isl_write_byte(dev, REG_CMD1, 0); 117ca2e4ecdSMichael Gmelin if (error) 118ca2e4ecdSMichael Gmelin goto done; 119ca2e4ecdSMichael Gmelin 120ca2e4ecdSMichael Gmelin pause("islinit", hz/100); 121ca2e4ecdSMichael Gmelin 122ca2e4ecdSMichael Gmelin done: 123*448897d3SAndriy Gapon if (error && !probe) 124ca2e4ecdSMichael Gmelin device_printf(dev, "Unable to initialize\n"); 125ca2e4ecdSMichael Gmelin return (error); 126ca2e4ecdSMichael Gmelin } 127ca2e4ecdSMichael Gmelin 128ca2e4ecdSMichael Gmelin static int isl_probe(device_t); 129ca2e4ecdSMichael Gmelin static int isl_attach(device_t); 130ca2e4ecdSMichael Gmelin static int isl_detach(device_t); 131ca2e4ecdSMichael Gmelin 132ca2e4ecdSMichael Gmelin static int isl_sysctl(SYSCTL_HANDLER_ARGS); 133ca2e4ecdSMichael Gmelin 134ca2e4ecdSMichael Gmelin static devclass_t isl_devclass; 135ca2e4ecdSMichael Gmelin 136ca2e4ecdSMichael Gmelin static device_method_t isl_methods[] = { 137ca2e4ecdSMichael Gmelin /* device interface */ 138ca2e4ecdSMichael Gmelin DEVMETHOD(device_probe, isl_probe), 139ca2e4ecdSMichael Gmelin DEVMETHOD(device_attach, isl_attach), 140ca2e4ecdSMichael Gmelin DEVMETHOD(device_detach, isl_detach), 141ca2e4ecdSMichael Gmelin 142ca2e4ecdSMichael Gmelin DEVMETHOD_END 143ca2e4ecdSMichael Gmelin }; 144ca2e4ecdSMichael Gmelin 145ca2e4ecdSMichael Gmelin static driver_t isl_driver = { 146ca2e4ecdSMichael Gmelin "isl", 147ca2e4ecdSMichael Gmelin isl_methods, 148ca2e4ecdSMichael Gmelin sizeof(struct isl_softc), 149ca2e4ecdSMichael Gmelin }; 150ca2e4ecdSMichael Gmelin 151*448897d3SAndriy Gapon #if 0 152*448897d3SAndriy Gapon static void 153*448897d3SAndriy Gapon isl_identify(driver_t *driver, device_t parent) 154*448897d3SAndriy Gapon { 155*448897d3SAndriy Gapon 156*448897d3SAndriy Gapon if (device_find_child(parent, "asl", -1)) { 157*448897d3SAndriy Gapon if (bootverbose) 158*448897d3SAndriy Gapon printf("asl: device(s) already created\n"); 159*448897d3SAndriy Gapon return; 160*448897d3SAndriy Gapon } 161*448897d3SAndriy Gapon 162*448897d3SAndriy Gapon /* Check if we can communicate to our slave. */ 163*448897d3SAndriy Gapon if (init_device(dev, 0x88, 1) == 0) 164*448897d3SAndriy Gapon BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "isl", -1); 165*448897d3SAndriy Gapon } 166*448897d3SAndriy Gapon #endif 167*448897d3SAndriy Gapon 168ca2e4ecdSMichael Gmelin static int 169ca2e4ecdSMichael Gmelin isl_probe(device_t dev) 170ca2e4ecdSMichael Gmelin { 171*448897d3SAndriy Gapon uint32_t addr = iicbus_get_addr(dev); 172ca2e4ecdSMichael Gmelin 173*448897d3SAndriy Gapon if (addr != 0x88) 174ca2e4ecdSMichael Gmelin return (ENXIO); 175*448897d3SAndriy Gapon if (init_device(dev, 1) != 0) 176ca2e4ecdSMichael Gmelin return (ENXIO); 177ca2e4ecdSMichael Gmelin device_set_desc(dev, "ISL Digital Ambient Light Sensor"); 178ca2e4ecdSMichael Gmelin return (BUS_PROBE_VENDOR); 179ca2e4ecdSMichael Gmelin } 180ca2e4ecdSMichael Gmelin 181ca2e4ecdSMichael Gmelin static int 182ca2e4ecdSMichael Gmelin isl_attach(device_t dev) 183ca2e4ecdSMichael Gmelin { 184ca2e4ecdSMichael Gmelin struct isl_softc *sc; 18512e413beSMichael Gmelin struct sysctl_ctx_list *sysctl_ctx; 18612e413beSMichael Gmelin struct sysctl_oid *sysctl_tree; 187ca2e4ecdSMichael Gmelin int use_als; 188ca2e4ecdSMichael Gmelin int use_ir; 189ca2e4ecdSMichael Gmelin int use_prox; 190ca2e4ecdSMichael Gmelin 191ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 192*448897d3SAndriy Gapon sc->dev = dev; 193ca2e4ecdSMichael Gmelin 194*448897d3SAndriy Gapon if (init_device(dev, 0) != 0) 195ca2e4ecdSMichael Gmelin return (ENXIO); 196ca2e4ecdSMichael Gmelin 197ca2e4ecdSMichael Gmelin sx_init(&sc->isl_sx, "ISL read lock"); 198ca2e4ecdSMichael Gmelin 19912e413beSMichael Gmelin sysctl_ctx = device_get_sysctl_ctx(dev); 20012e413beSMichael Gmelin sysctl_tree = device_get_sysctl_tree(dev); 201ca2e4ecdSMichael Gmelin 202*448897d3SAndriy Gapon use_als = isl_read_sensor(dev, CMD1_MASK_ALS_ONCE) >= 0; 203*448897d3SAndriy Gapon use_ir = isl_read_sensor(dev, CMD1_MASK_IR_ONCE) >= 0; 204*448897d3SAndriy Gapon use_prox = isl_read_sensor(dev, CMD1_MASK_PROX_ONCE) >= 0; 205ca2e4ecdSMichael Gmelin 206ca2e4ecdSMichael Gmelin if (use_als) { 20712e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 20812e413beSMichael Gmelin SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 209ca2e4ecdSMichael Gmelin "als", CTLTYPE_INT | CTLFLAG_RD, 210ca2e4ecdSMichael Gmelin sc, ISL_METHOD_ALS, isl_sysctl, "I", 211ca2e4ecdSMichael Gmelin "Current ALS sensor read-out"); 212ca2e4ecdSMichael Gmelin } 213ca2e4ecdSMichael Gmelin 214ca2e4ecdSMichael Gmelin if (use_ir) { 21512e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 21612e413beSMichael Gmelin SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 217ca2e4ecdSMichael Gmelin "ir", CTLTYPE_INT | CTLFLAG_RD, 218ca2e4ecdSMichael Gmelin sc, ISL_METHOD_IR, isl_sysctl, "I", 219ca2e4ecdSMichael Gmelin "Current IR sensor read-out"); 220ca2e4ecdSMichael Gmelin } 221ca2e4ecdSMichael Gmelin 222ca2e4ecdSMichael Gmelin if (use_prox) { 22312e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 22412e413beSMichael Gmelin SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 225ca2e4ecdSMichael Gmelin "prox", CTLTYPE_INT | CTLFLAG_RD, 226ca2e4ecdSMichael Gmelin sc, ISL_METHOD_PROX, isl_sysctl, "I", 227ca2e4ecdSMichael Gmelin "Current proximity sensor read-out"); 228ca2e4ecdSMichael Gmelin } 229ca2e4ecdSMichael Gmelin 23012e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 23112e413beSMichael Gmelin SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 232ca2e4ecdSMichael Gmelin "resolution", CTLTYPE_INT | CTLFLAG_RD, 233ca2e4ecdSMichael Gmelin sc, ISL_METHOD_RESOLUTION, isl_sysctl, "I", 234ca2e4ecdSMichael Gmelin "Current proximity sensor resolution"); 235ca2e4ecdSMichael Gmelin 23612e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 23712e413beSMichael Gmelin SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 238ca2e4ecdSMichael Gmelin "range", CTLTYPE_INT | CTLFLAG_RD, 239ca2e4ecdSMichael Gmelin sc, ISL_METHOD_RANGE, isl_sysctl, "I", 240ca2e4ecdSMichael Gmelin "Current proximity sensor range"); 241ca2e4ecdSMichael Gmelin 242ca2e4ecdSMichael Gmelin return (0); 243ca2e4ecdSMichael Gmelin } 244ca2e4ecdSMichael Gmelin 245ca2e4ecdSMichael Gmelin static int 246ca2e4ecdSMichael Gmelin isl_detach(device_t dev) 247ca2e4ecdSMichael Gmelin { 248ca2e4ecdSMichael Gmelin struct isl_softc *sc; 249ca2e4ecdSMichael Gmelin 250ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 251ca2e4ecdSMichael Gmelin sx_destroy(&sc->isl_sx); 252ca2e4ecdSMichael Gmelin 253ca2e4ecdSMichael Gmelin return (0); 254ca2e4ecdSMichael Gmelin } 255ca2e4ecdSMichael Gmelin 256ca2e4ecdSMichael Gmelin static int 257ca2e4ecdSMichael Gmelin isl_sysctl(SYSCTL_HANDLER_ARGS) 258ca2e4ecdSMichael Gmelin { 259ca2e4ecdSMichael Gmelin static int resolutions[] = { 16, 12, 8, 4}; 260ca2e4ecdSMichael Gmelin static int ranges[] = { 1000, 4000, 16000, 64000}; 261ca2e4ecdSMichael Gmelin 262ca2e4ecdSMichael Gmelin struct isl_softc *sc; 263ca2e4ecdSMichael Gmelin uint8_t rbyte; 264ca2e4ecdSMichael Gmelin int arg; 265ca2e4ecdSMichael Gmelin int resolution; 266ca2e4ecdSMichael Gmelin int range; 267ca2e4ecdSMichael Gmelin 268ca2e4ecdSMichael Gmelin sc = (struct isl_softc *)oidp->oid_arg1; 269ca2e4ecdSMichael Gmelin arg = -1; 270ca2e4ecdSMichael Gmelin 271ca2e4ecdSMichael Gmelin sx_xlock(&sc->isl_sx); 272*448897d3SAndriy Gapon if (isl_read_byte(sc->dev, REG_CMD2, &rbyte) != 0) { 273ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 274ca2e4ecdSMichael Gmelin return (-1); 275ca2e4ecdSMichael Gmelin } 276ca2e4ecdSMichael Gmelin resolution = resolutions[(rbyte & CMD2_MASK_RESOLUTION) 277ca2e4ecdSMichael Gmelin >> CMD2_SHIFT_RESOLUTION]; 278ca2e4ecdSMichael Gmelin range = ranges[(rbyte & CMD2_MASK_RANGE) >> CMD2_SHIFT_RANGE]; 279ca2e4ecdSMichael Gmelin 280ca2e4ecdSMichael Gmelin switch (oidp->oid_arg2) { 281ca2e4ecdSMichael Gmelin case ISL_METHOD_ALS: 282*448897d3SAndriy Gapon arg = (isl_read_sensor(sc->dev, 283ca2e4ecdSMichael Gmelin CMD1_MASK_ALS_ONCE) * range) >> resolution; 284ca2e4ecdSMichael Gmelin break; 285ca2e4ecdSMichael Gmelin case ISL_METHOD_IR: 286*448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_IR_ONCE); 287ca2e4ecdSMichael Gmelin break; 288ca2e4ecdSMichael Gmelin case ISL_METHOD_PROX: 289*448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_PROX_ONCE); 290ca2e4ecdSMichael Gmelin break; 291ca2e4ecdSMichael Gmelin case ISL_METHOD_RESOLUTION: 292ca2e4ecdSMichael Gmelin arg = (1 << resolution); 293ca2e4ecdSMichael Gmelin break; 294ca2e4ecdSMichael Gmelin case ISL_METHOD_RANGE: 295ca2e4ecdSMichael Gmelin arg = range; 296ca2e4ecdSMichael Gmelin break; 297ca2e4ecdSMichael Gmelin } 298ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 299ca2e4ecdSMichael Gmelin 300ca2e4ecdSMichael Gmelin SYSCTL_OUT(req, &arg, sizeof(arg)); 301ca2e4ecdSMichael Gmelin return (0); 302ca2e4ecdSMichael Gmelin } 303ca2e4ecdSMichael Gmelin 30412e413beSMichael Gmelin static int 305*448897d3SAndriy Gapon isl_read_sensor(device_t dev, uint8_t cmd_mask) 306ca2e4ecdSMichael Gmelin { 307ca2e4ecdSMichael Gmelin uint8_t rbyte; 308ca2e4ecdSMichael Gmelin uint8_t cmd; 309ca2e4ecdSMichael Gmelin int ret; 310ca2e4ecdSMichael Gmelin 311*448897d3SAndriy Gapon if (isl_read_byte(dev, REG_CMD1, &rbyte) != 0) { 312ca2e4ecdSMichael Gmelin device_printf(dev, 313ca2e4ecdSMichael Gmelin "Couldn't read first byte before issuing command %d\n", 314ca2e4ecdSMichael Gmelin cmd_mask); 315ca2e4ecdSMichael Gmelin return (-1); 316ca2e4ecdSMichael Gmelin } 317ca2e4ecdSMichael Gmelin 318ca2e4ecdSMichael Gmelin cmd = (rbyte & 0x1f) | cmd_mask; 319*448897d3SAndriy Gapon if (isl_write_byte(dev, REG_CMD1, cmd) != 0) { 320ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't write command %d\n", cmd_mask); 321ca2e4ecdSMichael Gmelin return (-1); 322ca2e4ecdSMichael Gmelin } 323ca2e4ecdSMichael Gmelin 324ca2e4ecdSMichael Gmelin pause("islconv", hz/10); 325ca2e4ecdSMichael Gmelin 326*448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA1, &rbyte) != 0) { 327ca2e4ecdSMichael Gmelin device_printf(dev, 328ca2e4ecdSMichael Gmelin "Couldn't read first byte after command %d\n", cmd_mask); 329ca2e4ecdSMichael Gmelin return (-1); 330ca2e4ecdSMichael Gmelin } 331ca2e4ecdSMichael Gmelin 332ca2e4ecdSMichael Gmelin ret = rbyte; 333*448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA2, &rbyte) != 0) { 334ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't read second byte after command %d\n", cmd_mask); 335ca2e4ecdSMichael Gmelin return (-1); 336ca2e4ecdSMichael Gmelin } 337ca2e4ecdSMichael Gmelin ret += rbyte << 8; 338ca2e4ecdSMichael Gmelin 339ca2e4ecdSMichael Gmelin return (ret); 340ca2e4ecdSMichael Gmelin } 341ca2e4ecdSMichael Gmelin 342*448897d3SAndriy Gapon DRIVER_MODULE(isl, iicbus, isl_driver, isl_devclass, NULL, NULL); 343*448897d3SAndriy Gapon MODULE_DEPEND(isl, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 344ca2e4ecdSMichael Gmelin MODULE_VERSION(isl, 1); 345