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 /* 29ca2e4ecdSMichael Gmelin * Driver for intersil I2C ISL29018 Digital Ambient Light Sensor and Proximity 30ca2e4ecdSMichael Gmelin * Sensor with Interrupt Function, only tested connected over SMBus (ig4iic). 31ca2e4ecdSMichael Gmelin * 32ca2e4ecdSMichael Gmelin * Datasheet: 33ca2e4ecdSMichael Gmelin * http://www.intersil.com/en/products/optoelectronics/ambient-light-and-proximity-sensors/light-to-digital-sensors/ISL29018.html 34ca2e4ecdSMichael Gmelin * http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29018.pdf 35ca2e4ecdSMichael Gmelin */ 36ca2e4ecdSMichael Gmelin 37ca2e4ecdSMichael Gmelin #include <sys/param.h> 38ca2e4ecdSMichael Gmelin #include <sys/bus.h> 39ca2e4ecdSMichael Gmelin #include <sys/conf.h> 40ca2e4ecdSMichael Gmelin #include <sys/event.h> 41ca2e4ecdSMichael Gmelin #include <sys/fcntl.h> 42ca2e4ecdSMichael Gmelin #include <sys/kernel.h> 43ca2e4ecdSMichael Gmelin #include <sys/lock.h> 44ca2e4ecdSMichael Gmelin #include <sys/lockmgr.h> 45ca2e4ecdSMichael Gmelin #include <sys/malloc.h> 46ca2e4ecdSMichael Gmelin #include <sys/mbuf.h> 47ca2e4ecdSMichael Gmelin #include <sys/module.h> 48ca2e4ecdSMichael Gmelin #include <sys/poll.h> 49ca2e4ecdSMichael Gmelin #include <sys/sx.h> 50ca2e4ecdSMichael Gmelin #include <sys/sysctl.h> 51ca2e4ecdSMichael Gmelin #include <sys/systm.h> 52ca2e4ecdSMichael Gmelin #include <sys/systm.h> 53ca2e4ecdSMichael Gmelin 54448897d3SAndriy Gapon #include <dev/iicbus/iiconf.h> 55448897d3SAndriy Gapon #include <dev/iicbus/iicbus.h> 56ca2e4ecdSMichael Gmelin #include <dev/isl/isl.h> 57ca2e4ecdSMichael Gmelin 58448897d3SAndriy Gapon #include "iicbus_if.h" 59ca2e4ecdSMichael Gmelin #include "bus_if.h" 60ca2e4ecdSMichael Gmelin #include "device_if.h" 61ca2e4ecdSMichael Gmelin 62ca2e4ecdSMichael Gmelin #define ISL_METHOD_ALS 0x10 63ca2e4ecdSMichael Gmelin #define ISL_METHOD_IR 0x11 64ca2e4ecdSMichael Gmelin #define ISL_METHOD_PROX 0x12 65ca2e4ecdSMichael Gmelin #define ISL_METHOD_RESOLUTION 0x13 66ca2e4ecdSMichael Gmelin #define ISL_METHOD_RANGE 0x14 67ca2e4ecdSMichael Gmelin 68ca2e4ecdSMichael Gmelin struct isl_softc { 69ca2e4ecdSMichael Gmelin device_t dev; 70ca2e4ecdSMichael Gmelin struct sx isl_sx; 71ca2e4ecdSMichael Gmelin }; 72ca2e4ecdSMichael Gmelin 73ca2e4ecdSMichael Gmelin /* Returns < 0 on problem. */ 74448897d3SAndriy Gapon static int isl_read_sensor(device_t dev, uint8_t cmd_mask); 75448897d3SAndriy Gapon 76448897d3SAndriy Gapon static int 77448897d3SAndriy Gapon isl_read_byte(device_t dev, uint8_t reg, uint8_t *val) 78448897d3SAndriy Gapon { 79448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 80448897d3SAndriy Gapon struct iic_msg msgs[] = { 81448897d3SAndriy Gapon { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 82448897d3SAndriy Gapon { addr, IIC_M_RD, 1, val }, 83448897d3SAndriy Gapon }; 84448897d3SAndriy Gapon 85448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 86448897d3SAndriy Gapon } 87448897d3SAndriy Gapon 88448897d3SAndriy Gapon static int 89448897d3SAndriy Gapon isl_write_byte(device_t dev, uint8_t reg, uint8_t val) 90448897d3SAndriy Gapon { 91448897d3SAndriy Gapon uint16_t addr = iicbus_get_addr(dev); 92448897d3SAndriy Gapon uint8_t bytes[] = { reg, val }; 93448897d3SAndriy Gapon struct iic_msg msgs[] = { 94448897d3SAndriy Gapon { addr, IIC_M_WR, nitems(bytes), bytes }, 95448897d3SAndriy Gapon }; 96448897d3SAndriy Gapon 97448897d3SAndriy Gapon return (iicbus_transfer(dev, msgs, nitems(msgs))); 98448897d3SAndriy Gapon } 99ca2e4ecdSMichael Gmelin 100ca2e4ecdSMichael Gmelin /* 101ca2e4ecdSMichael Gmelin * Initialize the device 102ca2e4ecdSMichael Gmelin */ 10312e413beSMichael Gmelin static int 104448897d3SAndriy Gapon init_device(device_t dev, int probe) 105ca2e4ecdSMichael Gmelin { 106ca2e4ecdSMichael Gmelin int error; 107ca2e4ecdSMichael Gmelin 108ca2e4ecdSMichael Gmelin /* 109ca2e4ecdSMichael Gmelin * init procedure: send 0x00 to test ref and cmd reg 1 110ca2e4ecdSMichael Gmelin */ 111448897d3SAndriy Gapon error = isl_write_byte(dev, REG_TEST, 0); 112ca2e4ecdSMichael Gmelin if (error) 113ca2e4ecdSMichael Gmelin goto done; 114448897d3SAndriy Gapon error = isl_write_byte(dev, REG_CMD1, 0); 115ca2e4ecdSMichael Gmelin if (error) 116ca2e4ecdSMichael Gmelin goto done; 117ca2e4ecdSMichael Gmelin 118ca2e4ecdSMichael Gmelin pause("islinit", hz/100); 119ca2e4ecdSMichael Gmelin 120ca2e4ecdSMichael Gmelin done: 121448897d3SAndriy Gapon if (error && !probe) 122ca2e4ecdSMichael Gmelin device_printf(dev, "Unable to initialize\n"); 123ca2e4ecdSMichael Gmelin return (error); 124ca2e4ecdSMichael Gmelin } 125ca2e4ecdSMichael Gmelin 126ca2e4ecdSMichael Gmelin static int isl_probe(device_t); 127ca2e4ecdSMichael Gmelin static int isl_attach(device_t); 128ca2e4ecdSMichael Gmelin static int isl_detach(device_t); 129ca2e4ecdSMichael Gmelin 130ca2e4ecdSMichael Gmelin static int isl_sysctl(SYSCTL_HANDLER_ARGS); 131ca2e4ecdSMichael Gmelin 132ca2e4ecdSMichael Gmelin static device_method_t isl_methods[] = { 133ca2e4ecdSMichael Gmelin /* device interface */ 134ca2e4ecdSMichael Gmelin DEVMETHOD(device_probe, isl_probe), 135ca2e4ecdSMichael Gmelin DEVMETHOD(device_attach, isl_attach), 136ca2e4ecdSMichael Gmelin DEVMETHOD(device_detach, isl_detach), 137ca2e4ecdSMichael Gmelin 138ca2e4ecdSMichael Gmelin DEVMETHOD_END 139ca2e4ecdSMichael Gmelin }; 140ca2e4ecdSMichael Gmelin 141ca2e4ecdSMichael Gmelin static driver_t isl_driver = { 142ca2e4ecdSMichael Gmelin "isl", 143ca2e4ecdSMichael Gmelin isl_methods, 144ca2e4ecdSMichael Gmelin sizeof(struct isl_softc), 145ca2e4ecdSMichael Gmelin }; 146ca2e4ecdSMichael Gmelin 147448897d3SAndriy Gapon #if 0 148448897d3SAndriy Gapon static void 149448897d3SAndriy Gapon isl_identify(driver_t *driver, device_t parent) 150448897d3SAndriy Gapon { 151448897d3SAndriy Gapon 152448897d3SAndriy Gapon if (device_find_child(parent, "asl", -1)) { 153448897d3SAndriy Gapon if (bootverbose) 154448897d3SAndriy Gapon printf("asl: device(s) already created\n"); 155448897d3SAndriy Gapon return; 156448897d3SAndriy Gapon } 157448897d3SAndriy Gapon 158448897d3SAndriy Gapon /* Check if we can communicate to our slave. */ 159448897d3SAndriy Gapon if (init_device(dev, 0x88, 1) == 0) 160*a05a6804SWarner Losh BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "isl", DEVICE_UNIT_ANY); 161448897d3SAndriy Gapon } 162448897d3SAndriy Gapon #endif 163448897d3SAndriy Gapon 164ca2e4ecdSMichael Gmelin static int 165ca2e4ecdSMichael Gmelin isl_probe(device_t dev) 166ca2e4ecdSMichael Gmelin { 167448897d3SAndriy Gapon uint32_t addr = iicbus_get_addr(dev); 168ca2e4ecdSMichael Gmelin 169448897d3SAndriy Gapon if (addr != 0x88) 170ca2e4ecdSMichael Gmelin return (ENXIO); 171448897d3SAndriy Gapon if (init_device(dev, 1) != 0) 172ca2e4ecdSMichael Gmelin return (ENXIO); 173ca2e4ecdSMichael Gmelin device_set_desc(dev, "ISL Digital Ambient Light Sensor"); 174ca2e4ecdSMichael Gmelin return (BUS_PROBE_VENDOR); 175ca2e4ecdSMichael Gmelin } 176ca2e4ecdSMichael Gmelin 177ca2e4ecdSMichael Gmelin static int 178ca2e4ecdSMichael Gmelin isl_attach(device_t dev) 179ca2e4ecdSMichael Gmelin { 180ca2e4ecdSMichael Gmelin struct isl_softc *sc; 18112e413beSMichael Gmelin struct sysctl_ctx_list *sysctl_ctx; 18212e413beSMichael Gmelin struct sysctl_oid *sysctl_tree; 183ca2e4ecdSMichael Gmelin int use_als; 184ca2e4ecdSMichael Gmelin int use_ir; 185ca2e4ecdSMichael Gmelin int use_prox; 186ca2e4ecdSMichael Gmelin 187ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 188448897d3SAndriy Gapon sc->dev = dev; 189ca2e4ecdSMichael Gmelin 190448897d3SAndriy Gapon if (init_device(dev, 0) != 0) 191ca2e4ecdSMichael Gmelin return (ENXIO); 192ca2e4ecdSMichael Gmelin 193ca2e4ecdSMichael Gmelin sx_init(&sc->isl_sx, "ISL read lock"); 194ca2e4ecdSMichael Gmelin 19512e413beSMichael Gmelin sysctl_ctx = device_get_sysctl_ctx(dev); 19612e413beSMichael Gmelin sysctl_tree = device_get_sysctl_tree(dev); 197ca2e4ecdSMichael Gmelin 198448897d3SAndriy Gapon use_als = isl_read_sensor(dev, CMD1_MASK_ALS_ONCE) >= 0; 199448897d3SAndriy Gapon use_ir = isl_read_sensor(dev, CMD1_MASK_IR_ONCE) >= 0; 200448897d3SAndriy Gapon use_prox = isl_read_sensor(dev, CMD1_MASK_PROX_ONCE) >= 0; 201ca2e4ecdSMichael Gmelin 202ca2e4ecdSMichael Gmelin if (use_als) { 20312e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2047029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "als", 2057029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2067029da5cSPawel Biernacki ISL_METHOD_ALS, isl_sysctl, "I", 207ca2e4ecdSMichael Gmelin "Current ALS sensor read-out"); 208ca2e4ecdSMichael Gmelin } 209ca2e4ecdSMichael Gmelin 210ca2e4ecdSMichael Gmelin if (use_ir) { 21112e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2127029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "ir", 2137029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2147029da5cSPawel Biernacki ISL_METHOD_IR, isl_sysctl, "I", 215ca2e4ecdSMichael Gmelin "Current IR sensor read-out"); 216ca2e4ecdSMichael Gmelin } 217ca2e4ecdSMichael Gmelin 218ca2e4ecdSMichael Gmelin if (use_prox) { 21912e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2207029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "prox", 2217029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2227029da5cSPawel Biernacki ISL_METHOD_PROX, isl_sysctl, "I", 223ca2e4ecdSMichael Gmelin "Current proximity sensor read-out"); 224ca2e4ecdSMichael Gmelin } 225ca2e4ecdSMichael Gmelin 22612e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2277029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "resolution", 2287029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2297029da5cSPawel Biernacki ISL_METHOD_RESOLUTION, isl_sysctl, "I", 230ca2e4ecdSMichael Gmelin "Current proximity sensor resolution"); 231ca2e4ecdSMichael Gmelin 23212e413beSMichael Gmelin SYSCTL_ADD_PROC(sysctl_ctx, 2337029da5cSPawel Biernacki SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "range", 2347029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 2357029da5cSPawel Biernacki ISL_METHOD_RANGE, isl_sysctl, "I", 236ca2e4ecdSMichael Gmelin "Current proximity sensor range"); 237ca2e4ecdSMichael Gmelin 238ca2e4ecdSMichael Gmelin return (0); 239ca2e4ecdSMichael Gmelin } 240ca2e4ecdSMichael Gmelin 241ca2e4ecdSMichael Gmelin static int 242ca2e4ecdSMichael Gmelin isl_detach(device_t dev) 243ca2e4ecdSMichael Gmelin { 244ca2e4ecdSMichael Gmelin struct isl_softc *sc; 245ca2e4ecdSMichael Gmelin 246ca2e4ecdSMichael Gmelin sc = device_get_softc(dev); 247ca2e4ecdSMichael Gmelin sx_destroy(&sc->isl_sx); 248ca2e4ecdSMichael Gmelin 249ca2e4ecdSMichael Gmelin return (0); 250ca2e4ecdSMichael Gmelin } 251ca2e4ecdSMichael Gmelin 252ca2e4ecdSMichael Gmelin static int 253ca2e4ecdSMichael Gmelin isl_sysctl(SYSCTL_HANDLER_ARGS) 254ca2e4ecdSMichael Gmelin { 255ca2e4ecdSMichael Gmelin static int resolutions[] = { 16, 12, 8, 4}; 256ca2e4ecdSMichael Gmelin static int ranges[] = { 1000, 4000, 16000, 64000}; 257ca2e4ecdSMichael Gmelin 258ca2e4ecdSMichael Gmelin struct isl_softc *sc; 259ca2e4ecdSMichael Gmelin uint8_t rbyte; 260ca2e4ecdSMichael Gmelin int arg; 261ca2e4ecdSMichael Gmelin int resolution; 262ca2e4ecdSMichael Gmelin int range; 263ca2e4ecdSMichael Gmelin 264ca2e4ecdSMichael Gmelin sc = (struct isl_softc *)oidp->oid_arg1; 265ca2e4ecdSMichael Gmelin arg = -1; 266ca2e4ecdSMichael Gmelin 267ca2e4ecdSMichael Gmelin sx_xlock(&sc->isl_sx); 268448897d3SAndriy Gapon if (isl_read_byte(sc->dev, REG_CMD2, &rbyte) != 0) { 269ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 270ca2e4ecdSMichael Gmelin return (-1); 271ca2e4ecdSMichael Gmelin } 272ca2e4ecdSMichael Gmelin resolution = resolutions[(rbyte & CMD2_MASK_RESOLUTION) 273ca2e4ecdSMichael Gmelin >> CMD2_SHIFT_RESOLUTION]; 274ca2e4ecdSMichael Gmelin range = ranges[(rbyte & CMD2_MASK_RANGE) >> CMD2_SHIFT_RANGE]; 275ca2e4ecdSMichael Gmelin 276ca2e4ecdSMichael Gmelin switch (oidp->oid_arg2) { 277ca2e4ecdSMichael Gmelin case ISL_METHOD_ALS: 278448897d3SAndriy Gapon arg = (isl_read_sensor(sc->dev, 279ca2e4ecdSMichael Gmelin CMD1_MASK_ALS_ONCE) * range) >> resolution; 280ca2e4ecdSMichael Gmelin break; 281ca2e4ecdSMichael Gmelin case ISL_METHOD_IR: 282448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_IR_ONCE); 283ca2e4ecdSMichael Gmelin break; 284ca2e4ecdSMichael Gmelin case ISL_METHOD_PROX: 285448897d3SAndriy Gapon arg = isl_read_sensor(sc->dev, CMD1_MASK_PROX_ONCE); 286ca2e4ecdSMichael Gmelin break; 287ca2e4ecdSMichael Gmelin case ISL_METHOD_RESOLUTION: 288ca2e4ecdSMichael Gmelin arg = (1 << resolution); 289ca2e4ecdSMichael Gmelin break; 290ca2e4ecdSMichael Gmelin case ISL_METHOD_RANGE: 291ca2e4ecdSMichael Gmelin arg = range; 292ca2e4ecdSMichael Gmelin break; 293ca2e4ecdSMichael Gmelin } 294ca2e4ecdSMichael Gmelin sx_xunlock(&sc->isl_sx); 295ca2e4ecdSMichael Gmelin 296ca2e4ecdSMichael Gmelin SYSCTL_OUT(req, &arg, sizeof(arg)); 297ca2e4ecdSMichael Gmelin return (0); 298ca2e4ecdSMichael Gmelin } 299ca2e4ecdSMichael Gmelin 30012e413beSMichael Gmelin static int 301448897d3SAndriy Gapon isl_read_sensor(device_t dev, uint8_t cmd_mask) 302ca2e4ecdSMichael Gmelin { 303ca2e4ecdSMichael Gmelin uint8_t rbyte; 304ca2e4ecdSMichael Gmelin uint8_t cmd; 305ca2e4ecdSMichael Gmelin int ret; 306ca2e4ecdSMichael Gmelin 307448897d3SAndriy Gapon if (isl_read_byte(dev, REG_CMD1, &rbyte) != 0) { 308ca2e4ecdSMichael Gmelin device_printf(dev, 309ca2e4ecdSMichael Gmelin "Couldn't read first byte before issuing command %d\n", 310ca2e4ecdSMichael Gmelin cmd_mask); 311ca2e4ecdSMichael Gmelin return (-1); 312ca2e4ecdSMichael Gmelin } 313ca2e4ecdSMichael Gmelin 314ca2e4ecdSMichael Gmelin cmd = (rbyte & 0x1f) | cmd_mask; 315448897d3SAndriy Gapon if (isl_write_byte(dev, REG_CMD1, cmd) != 0) { 316ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't write command %d\n", cmd_mask); 317ca2e4ecdSMichael Gmelin return (-1); 318ca2e4ecdSMichael Gmelin } 319ca2e4ecdSMichael Gmelin 320ca2e4ecdSMichael Gmelin pause("islconv", hz/10); 321ca2e4ecdSMichael Gmelin 322448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA1, &rbyte) != 0) { 323ca2e4ecdSMichael Gmelin device_printf(dev, 324ca2e4ecdSMichael Gmelin "Couldn't read first byte after command %d\n", cmd_mask); 325ca2e4ecdSMichael Gmelin return (-1); 326ca2e4ecdSMichael Gmelin } 327ca2e4ecdSMichael Gmelin 328ca2e4ecdSMichael Gmelin ret = rbyte; 329448897d3SAndriy Gapon if (isl_read_byte(dev, REG_DATA2, &rbyte) != 0) { 330ca2e4ecdSMichael Gmelin device_printf(dev, "Couldn't read second byte after command %d\n", cmd_mask); 331ca2e4ecdSMichael Gmelin return (-1); 332ca2e4ecdSMichael Gmelin } 333ca2e4ecdSMichael Gmelin ret += rbyte << 8; 334ca2e4ecdSMichael Gmelin 335ca2e4ecdSMichael Gmelin return (ret); 336ca2e4ecdSMichael Gmelin } 337ca2e4ecdSMichael Gmelin 338a4f3b83bSJohn Baldwin DRIVER_MODULE(isl, iicbus, isl_driver, NULL, NULL); 339448897d3SAndriy Gapon MODULE_DEPEND(isl, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 340ca2e4ecdSMichael Gmelin MODULE_VERSION(isl, 1); 341