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 56448897d3SAndriy Gapon #include <dev/iicbus/iiconf.h> 57448897d3SAndriy Gapon #include <dev/iicbus/iicbus.h> 58ca2e4ecdSMichael Gmelin #include <dev/isl/isl.h> 59ca2e4ecdSMichael Gmelin 60448897d3SAndriy 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. */ 76448897d3SAndriy Gapon static int isl_read_sensor(device_t dev, uint8_t cmd_mask); 77448897d3SAndriy Gapon 78448897d3SAndriy Gapon static int 79448897d3SAndriy Gapon isl_read_byte(device_t dev, uint8_t reg, uint8_t *val) 80448897d3SAndriy Gapon { 81448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 82448897d3SAndriy Gapon struct iic_msg msgs[] = { 83448897d3SAndriy Gapon { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 84448897d3SAndriy Gapon { addr, IIC_M_RD, 1, val }, 85448897d3SAndriy Gapon }; 86448897d3SAndriy Gapon 87448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 88448897d3SAndriy Gapon } 89448897d3SAndriy Gapon 90448897d3SAndriy Gapon static int 91448897d3SAndriy Gapon isl_write_byte(device_t dev, uint8_t reg, uint8_t val) 92448897d3SAndriy Gapon { 93448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 94448897d3SAndriy Gapon uint8_t bytes[] = { reg, val }; 95448897d3SAndriy Gapon struct iic_msg msgs[] = { 96448897d3SAndriy Gapon { addr, IIC_M_WR, nitems(bytes), bytes }, 97448897d3SAndriy Gapon }; 98448897d3SAndriy Gapon 99448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 100448897d3SAndriy Gapon } 101ca2e4ecdSMichael Gmelin 102ca2e4ecdSMichael Gmelin /* 103ca2e4ecdSMichael Gmelin * Initialize the device 104ca2e4ecdSMichael Gmelin */ 10512e413beSMichael Gmelin static int 106448897d3SAndriy 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 */ 113448897d3SAndriy Gapon error = isl_write_byte(dev, REG_TEST, 0); 114ca2e4ecdSMichael Gmelin if (error) 115ca2e4ecdSMichael Gmelin goto done; 116448897d3SAndriy 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: 123448897d3SAndriy 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 device_method_t isl_methods[] = { 135ca2e4ecdSMichael Gmelin /* device interface */ 136ca2e4ecdSMichael Gmelin DEVMETHOD(device_probe, isl_probe), 137ca2e4ecdSMichael Gmelin DEVMETHOD(device_attach, isl_attach), 138ca2e4ecdSMichael Gmelin DEVMETHOD(device_detach, isl_detach), 139ca2e4ecdSMichael Gmelin 140ca2e4ecdSMichael Gmelin DEVMETHOD_END 141ca2e4ecdSMichael Gmelin }; 142ca2e4ecdSMichael Gmelin 143ca2e4ecdSMichael Gmelin static driver_t isl_driver = { 144ca2e4ecdSMichael Gmelin "isl", 145ca2e4ecdSMichael Gmelin isl_methods, 146ca2e4ecdSMichael Gmelin sizeof(struct isl_softc), 147ca2e4ecdSMichael Gmelin }; 148ca2e4ecdSMichael Gmelin 149448897d3SAndriy Gapon #if 0 150448897d3SAndriy Gapon static void 151448897d3SAndriy Gapon isl_identify(driver_t *driver, device_t parent) 152448897d3SAndriy Gapon { 153448897d3SAndriy Gapon 154448897d3SAndriy Gapon if (device_find_child(parent, "asl", -1)) { 155448897d3SAndriy Gapon if (bootverbose) 156448897d3SAndriy Gapon printf("asl: device(s) already created\n"); 157448897d3SAndriy Gapon return; 158448897d3SAndriy Gapon } 159448897d3SAndriy Gapon 160448897d3SAndriy Gapon /* Check if we can communicate to our slave. */ 161448897d3SAndriy Gapon if (init_device(dev, 0x88, 1) == 0) 162448897d3SAndriy Gapon BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "isl", -1); 163448897d3SAndriy Gapon } 164448897d3SAndriy Gapon #endif 165448897d3SAndriy Gapon 166ca2e4ecdSMichael Gmelin static int 167ca2e4ecdSMichael Gmelin isl_probe(device_t dev) 168ca2e4ecdSMichael Gmelin { 169448897d3SAndriy Gapon uint32_t addr = iicbus_get_addr(dev); 170ca2e4ecdSMichael Gmelin 171448897d3SAndriy Gapon if (addr != 0x88) 172ca2e4ecdSMichael Gmelin return (ENXIO); 173448897d3SAndriy Gapon if (init_device(dev, 1) != 0) 174ca2e4ecdSMichael Gmelin return (ENXIO); 175ca2e4ecdSMichael Gmelin device_set_desc(dev, "ISL Digital Ambient Light Sensor"); 176ca2e4ecdSMichael Gmelin return (BUS_PROBE_VENDOR); 177ca2e4ecdSMichael Gmelin } 178ca2e4ecdSMichael Gmelin 179ca2e4ecdSMichael Gmelin static int 180ca2e4ecdSMichael Gmelin isl_attach(device_t dev) 181ca2e4ecdSMichael Gmelin { 182ca2e4ecdSMichael Gmelin struct isl_softc *sc; 18312e413beSMichael Gmelin struct sysctl_ctx_list *sysctl_ctx; 18412e413beSMichael Gmelin struct sysctl_oid *sysctl_tree; 185ca2e4ecdSMichael Gmelin int use_als; 186ca2e4ecdSMichael Gmelin int use_ir; 187ca2e4ecdSMichael Gmelin int use_prox; 188ca2e4ecdSMichael Gmelin 189ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 190448897d3SAndriy Gapon sc->dev = dev; 191ca2e4ecdSMichael Gmelin 192448897d3SAndriy Gapon if (init_device(dev, 0) != 0) 193ca2e4ecdSMichael Gmelin return (ENXIO); 194ca2e4ecdSMichael Gmelin 195ca2e4ecdSMichael Gmelin sx_init(&sc->isl_sx, "ISL read lock"); 196ca2e4ecdSMichael Gmelin 19712e413beSMichael Gmelin sysctl_ctx = device_get_sysctl_ctx(dev); 19812e413beSMichael Gmelin sysctl_tree = device_get_sysctl_tree(dev); 199ca2e4ecdSMichael Gmelin 200448897d3SAndriy Gapon use_als = isl_read_sensor(dev, CMD1_MASK_ALS_ONCE) >= 0; 201448897d3SAndriy Gapon use_ir = isl_read_sensor(dev, CMD1_MASK_IR_ONCE) >= 0; 202448897d3SAndriy Gapon use_prox = isl_read_sensor(dev, CMD1_MASK_PROX_ONCE) >= 0; 203ca2e4ecdSMichael Gmelin 204ca2e4ecdSMichael Gmelin if (use_als) { 20512e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2067029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "als", 2077029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2087029da5cSPawel Biernacki ISL_METHOD_ALS, isl_sysctl, "I", 209ca2e4ecdSMichael Gmelin "Current ALS sensor read-out"); 210ca2e4ecdSMichael Gmelin } 211ca2e4ecdSMichael Gmelin 212ca2e4ecdSMichael Gmelin if (use_ir) { 21312e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2147029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "ir", 2157029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2167029da5cSPawel Biernacki ISL_METHOD_IR, isl_sysctl, "I", 217ca2e4ecdSMichael Gmelin "Current IR sensor read-out"); 218ca2e4ecdSMichael Gmelin } 219ca2e4ecdSMichael Gmelin 220ca2e4ecdSMichael Gmelin if (use_prox) { 22112e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2227029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "prox", 2237029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2247029da5cSPawel Biernacki ISL_METHOD_PROX, isl_sysctl, "I", 225ca2e4ecdSMichael Gmelin "Current proximity sensor read-out"); 226ca2e4ecdSMichael Gmelin } 227ca2e4ecdSMichael Gmelin 22812e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2297029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "resolution", 2307029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2317029da5cSPawel Biernacki ISL_METHOD_RESOLUTION, isl_sysctl, "I", 232ca2e4ecdSMichael Gmelin "Current proximity sensor resolution"); 233ca2e4ecdSMichael Gmelin 23412e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2357029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "range", 2367029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2377029da5cSPawel Biernacki ISL_METHOD_RANGE, isl_sysctl, "I", 238ca2e4ecdSMichael Gmelin "Current proximity sensor range"); 239ca2e4ecdSMichael Gmelin 240ca2e4ecdSMichael Gmelin return (0); 241ca2e4ecdSMichael Gmelin } 242ca2e4ecdSMichael Gmelin 243ca2e4ecdSMichael Gmelin static int 244ca2e4ecdSMichael Gmelin isl_detach(device_t dev) 245ca2e4ecdSMichael Gmelin { 246ca2e4ecdSMichael Gmelin struct isl_softc *sc; 247ca2e4ecdSMichael Gmelin 248ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 249ca2e4ecdSMichael Gmelin sx_destroy(&sc->isl_sx); 250ca2e4ecdSMichael Gmelin 251ca2e4ecdSMichael Gmelin return (0); 252ca2e4ecdSMichael Gmelin } 253ca2e4ecdSMichael Gmelin 254ca2e4ecdSMichael Gmelin static int 255ca2e4ecdSMichael Gmelin isl_sysctl(SYSCTL_HANDLER_ARGS) 256ca2e4ecdSMichael Gmelin { 257ca2e4ecdSMichael Gmelin static int resolutions[] = { 16, 12, 8, 4}; 258ca2e4ecdSMichael Gmelin static int ranges[] = { 1000, 4000, 16000, 64000}; 259ca2e4ecdSMichael Gmelin 260ca2e4ecdSMichael Gmelin struct isl_softc *sc; 261ca2e4ecdSMichael Gmelin uint8_t rbyte; 262ca2e4ecdSMichael Gmelin int arg; 263ca2e4ecdSMichael Gmelin int resolution; 264ca2e4ecdSMichael Gmelin int range; 265ca2e4ecdSMichael Gmelin 266ca2e4ecdSMichael Gmelin sc = (struct isl_softc *)oidp->oid_arg1; 267ca2e4ecdSMichael Gmelin arg = -1; 268ca2e4ecdSMichael Gmelin 269ca2e4ecdSMichael Gmelin sx_xlock(&sc->isl_sx); 270448897d3SAndriy Gapon if (isl_read_byte(sc->dev, REG_CMD2, &rbyte) != 0) { 271ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 272ca2e4ecdSMichael Gmelin return (-1); 273ca2e4ecdSMichael Gmelin } 274ca2e4ecdSMichael Gmelin resolution = resolutions[(rbyte & CMD2_MASK_RESOLUTION) 275ca2e4ecdSMichael Gmelin >> CMD2_SHIFT_RESOLUTION]; 276ca2e4ecdSMichael Gmelin range = ranges[(rbyte & CMD2_MASK_RANGE) >> CMD2_SHIFT_RANGE]; 277ca2e4ecdSMichael Gmelin 278ca2e4ecdSMichael Gmelin switch (oidp->oid_arg2) { 279ca2e4ecdSMichael Gmelin case ISL_METHOD_ALS: 280448897d3SAndriy Gapon arg = (isl_read_sensor(sc->dev, 281ca2e4ecdSMichael Gmelin CMD1_MASK_ALS_ONCE) * range) >> resolution; 282ca2e4ecdSMichael Gmelin break; 283ca2e4ecdSMichael Gmelin case ISL_METHOD_IR: 284448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_IR_ONCE); 285ca2e4ecdSMichael Gmelin break; 286ca2e4ecdSMichael Gmelin case ISL_METHOD_PROX: 287448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_PROX_ONCE); 288ca2e4ecdSMichael Gmelin break; 289ca2e4ecdSMichael Gmelin case ISL_METHOD_RESOLUTION: 290ca2e4ecdSMichael Gmelin arg = (1 << resolution); 291ca2e4ecdSMichael Gmelin break; 292ca2e4ecdSMichael Gmelin case ISL_METHOD_RANGE: 293ca2e4ecdSMichael Gmelin arg = range; 294ca2e4ecdSMichael Gmelin break; 295ca2e4ecdSMichael Gmelin } 296ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 297ca2e4ecdSMichael Gmelin 298ca2e4ecdSMichael Gmelin SYSCTL_OUT(req, &arg, sizeof(arg)); 299ca2e4ecdSMichael Gmelin return (0); 300ca2e4ecdSMichael Gmelin } 301ca2e4ecdSMichael Gmelin 30212e413beSMichael Gmelin static int 303448897d3SAndriy Gapon isl_read_sensor(device_t dev, uint8_t cmd_mask) 304ca2e4ecdSMichael Gmelin { 305ca2e4ecdSMichael Gmelin uint8_t rbyte; 306ca2e4ecdSMichael Gmelin uint8_t cmd; 307ca2e4ecdSMichael Gmelin int ret; 308ca2e4ecdSMichael Gmelin 309448897d3SAndriy Gapon if (isl_read_byte(dev, REG_CMD1, &rbyte) != 0) { 310ca2e4ecdSMichael Gmelin device_printf(dev, 311ca2e4ecdSMichael Gmelin "Couldn't read first byte before issuing command %d\n", 312ca2e4ecdSMichael Gmelin cmd_mask); 313ca2e4ecdSMichael Gmelin return (-1); 314ca2e4ecdSMichael Gmelin } 315ca2e4ecdSMichael Gmelin 316ca2e4ecdSMichael Gmelin cmd = (rbyte & 0x1f) | cmd_mask; 317448897d3SAndriy Gapon if (isl_write_byte(dev, REG_CMD1, cmd) != 0) { 318ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't write command %d\n", cmd_mask); 319ca2e4ecdSMichael Gmelin return (-1); 320ca2e4ecdSMichael Gmelin } 321ca2e4ecdSMichael Gmelin 322ca2e4ecdSMichael Gmelin pause("islconv", hz/10); 323ca2e4ecdSMichael Gmelin 324448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA1, &rbyte) != 0) { 325ca2e4ecdSMichael Gmelin device_printf(dev, 326ca2e4ecdSMichael Gmelin "Couldn't read first byte after command %d\n", cmd_mask); 327ca2e4ecdSMichael Gmelin return (-1); 328ca2e4ecdSMichael Gmelin } 329ca2e4ecdSMichael Gmelin 330ca2e4ecdSMichael Gmelin ret = rbyte; 331448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA2, &rbyte) != 0) { 332ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't read second byte after command %d\n", cmd_mask); 333ca2e4ecdSMichael Gmelin return (-1); 334ca2e4ecdSMichael Gmelin } 335ca2e4ecdSMichael Gmelin ret += rbyte << 8; 336ca2e4ecdSMichael Gmelin 337ca2e4ecdSMichael Gmelin return (ret); 338ca2e4ecdSMichael Gmelin } 339ca2e4ecdSMichael Gmelin 340*a4f3b83bSJohn Baldwin DRIVER_MODULE(isl, iicbus, isl_driver, NULL, NULL); 341448897d3SAndriy Gapon MODULE_DEPEND(isl, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 342ca2e4ecdSMichael Gmelin MODULE_VERSION(isl, 1); 343