Home | History | Annotate | Line # | Download | only in onewire
ds28e17iic.c revision 1.2
      1  1.2  thorpej /*	$NetBSD: ds28e17iic.c,v 1.2 2025/09/15 13:23:03 thorpej Exp $	*/
      2  1.1     brad 
      3  1.1     brad /*
      4  1.1     brad  * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org>
      5  1.1     brad  *
      6  1.1     brad  * Permission to use, copy, modify, and distribute this software for any
      7  1.1     brad  * purpose with or without fee is hereby granted, provided that the above
      8  1.1     brad  * copyright notice and this permission notice appear in all copies.
      9  1.1     brad  *
     10  1.1     brad  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  1.1     brad  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  1.1     brad  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  1.1     brad  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  1.1     brad  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  1.1     brad  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  1.1     brad  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  1.1     brad  */
     18  1.1     brad 
     19  1.1     brad 
     20  1.1     brad /* Driver for the DS28E17 1-Wire to I2C bridge chip */
     21  1.1     brad 
     22  1.1     brad /* https://www.analog.com/en/products/DS28E17.html */
     23  1.1     brad 
     24  1.1     brad #include <sys/cdefs.h>
     25  1.2  thorpej __KERNEL_RCSID(0, "$NetBSD: ds28e17iic.c,v 1.2 2025/09/15 13:23:03 thorpej Exp $");
     26  1.1     brad 
     27  1.1     brad #include <sys/param.h>
     28  1.1     brad #include <sys/systm.h>
     29  1.1     brad #include <sys/device.h>
     30  1.1     brad #include <sys/kernel.h>
     31  1.1     brad #include <sys/proc.h>
     32  1.1     brad #include <sys/module.h>
     33  1.1     brad #include <sys/sysctl.h>
     34  1.1     brad 
     35  1.1     brad #include <dev/onewire/onewiredevs.h>
     36  1.1     brad #include <dev/onewire/onewirereg.h>
     37  1.1     brad #include <dev/onewire/onewirevar.h>
     38  1.1     brad 
     39  1.1     brad #include <dev/i2c/i2cvar.h>
     40  1.1     brad 
     41  1.1     brad #include <dev/onewire/ds28e17iicreg.h>
     42  1.1     brad #include <dev/onewire/ds28e17iicvar.h>
     43  1.1     brad 
     44  1.1     brad static int	ds28e17iic_match(device_t, cfdata_t, void *);
     45  1.1     brad static void	ds28e17iic_attach(device_t, device_t, void *);
     46  1.1     brad static int	ds28e17iic_detach(device_t, int);
     47  1.1     brad static int	ds28e17iic_activate(device_t, enum devact);
     48  1.1     brad static int 	ds28e17iic_verify_sysctl(SYSCTLFN_ARGS);
     49  1.1     brad 
     50  1.1     brad #define DS28E17IIC_DEBUG
     51  1.1     brad #ifdef DS28E17IIC_DEBUG
     52  1.1     brad #define DPRINTF(s, l, x) \
     53  1.1     brad     do { \
     54  1.1     brad 	if (l <= s->sc_ds28e17iicdebug) \
     55  1.1     brad 	    printf x; \
     56  1.1     brad     } while (/*CONSTCOND*/0)
     57  1.1     brad #else
     58  1.1     brad #define DPRINTF(s, l, x)
     59  1.1     brad #endif
     60  1.1     brad 
     61  1.1     brad CFATTACH_DECL_NEW(ds28e17iic, sizeof(struct ds28e17iic_softc),
     62  1.1     brad 	ds28e17iic_match, ds28e17iic_attach, ds28e17iic_detach, ds28e17iic_activate);
     63  1.1     brad 
     64  1.1     brad extern struct cfdriver ds28e17iic_cd;
     65  1.1     brad 
     66  1.1     brad static const struct onewire_matchfam ds28e17iic_fams[] = {
     67  1.1     brad 	{ ONEWIRE_FAMILY_DS28E17 },
     68  1.1     brad };
     69  1.1     brad 
     70  1.1     brad 
     71  1.1     brad #define READY_DELAY(d) if (d > 0) delay(d)
     72  1.1     brad 
     73  1.1     brad /* The chip uses a 16 bit CRC on the 1-Wire bus when doing any I2C transaction.
     74  1.1     brad  * But it has some strangness to it..  the CRC can be made up from a number of
     75  1.1     brad  * parts of the 1-Wire transaction, some of which are only used for some
     76  1.1     brad  * transactions.  Then the result must be inverted and placed in the proper
     77  1.1     brad  * order.
     78  1.1     brad  */
     79  1.1     brad 
     80  1.1     brad static uint16_t
     81  1.1     brad ds28e17iic_crc16_bit(uint16_t icrc)
     82  1.1     brad {
     83  1.1     brad 	for (size_t i = 0; i < 8; i++) {
     84  1.1     brad 		if (icrc & 0x01) {
     85  1.1     brad 			icrc >>= 1;
     86  1.1     brad 			icrc ^= 0xA001;
     87  1.1     brad 		} else {
     88  1.1     brad 			icrc >>= 1;
     89  1.1     brad 		}
     90  1.1     brad 	}
     91  1.1     brad 
     92  1.1     brad 	return(icrc);
     93  1.1     brad }
     94  1.1     brad 
     95  1.1     brad static void
     96  1.1     brad ds28e17iic_crc16(uint8_t crc16[], uint8_t cmd, uint8_t i2c_addr, uint8_t len, uint8_t *data, uint8_t len2)
     97  1.1     brad {
     98  1.1     brad 	uint16_t crc = 0;
     99  1.1     brad 
    100  1.1     brad 	crc ^= cmd;
    101  1.1     brad 	crc = ds28e17iic_crc16_bit(crc);
    102  1.1     brad 
    103  1.1     brad 	/* This is a magic value which means that it should not be considered.
    104  1.1     brad 	 * The address will never be 0xff, but could, in theory, be 0x00, so
    105  1.1     brad 	 * don't use that.
    106  1.1     brad 	 */
    107  1.1     brad 
    108  1.1     brad 	if (i2c_addr != 0xff) {
    109  1.1     brad 		crc ^= i2c_addr;
    110  1.1     brad 		crc = ds28e17iic_crc16_bit(crc);
    111  1.1     brad 	}
    112  1.1     brad 
    113  1.1     brad 	crc ^= len;
    114  1.1     brad 	crc = ds28e17iic_crc16_bit(crc);
    115  1.1     brad 
    116  1.1     brad 	if (data != NULL) {
    117  1.1     brad 		for (size_t j = 0; j < len; j++) {
    118  1.1     brad 			crc ^= data[j];
    119  1.1     brad 			crc = ds28e17iic_crc16_bit(crc);
    120  1.1     brad 		}
    121  1.1     brad 	}
    122  1.1     brad 
    123  1.1     brad 	if (len2 > 0) {
    124  1.1     brad 		crc ^= len2;
    125  1.1     brad 		crc = ds28e17iic_crc16_bit(crc);
    126  1.1     brad 	}
    127  1.1     brad 
    128  1.1     brad 	crc = crc ^ 0xffff;
    129  1.1     brad 
    130  1.1     brad 	crc16[1] = crc >> 8;
    131  1.1     brad 	crc16[0] = crc & 0xff;
    132  1.1     brad }
    133  1.1     brad 
    134  1.1     brad int
    135  1.1     brad ds28e17iic_verify_sysctl(SYSCTLFN_ARGS)
    136  1.1     brad {
    137  1.1     brad 	int error, t;
    138  1.1     brad 	struct sysctlnode node;
    139  1.1     brad 
    140  1.1     brad 	node = *rnode;
    141  1.1     brad 	t = *(int *)rnode->sysctl_data;
    142  1.1     brad 	node.sysctl_data = &t;
    143  1.1     brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    144  1.1     brad 	if (error || newp == NULL)
    145  1.1     brad 		return error;
    146  1.1     brad 
    147  1.1     brad 	if (t < 0)
    148  1.1     brad 		return EINVAL;
    149  1.1     brad 
    150  1.1     brad 	*(int *)rnode->sysctl_data = t;
    151  1.1     brad 
    152  1.1     brad 	return 0;
    153  1.1     brad }
    154  1.1     brad 
    155  1.1     brad /* There isn't much required to acquire or release the I2C bus, but the man
    156  1.1     brad  * pages says these are needed
    157  1.1     brad  */
    158  1.1     brad 
    159  1.1     brad static int
    160  1.1     brad ds28e17iic_acquire_bus(void *v, int flags)
    161  1.1     brad {
    162  1.1     brad 	return(0);
    163  1.1     brad }
    164  1.1     brad 
    165  1.1     brad static void
    166  1.1     brad ds28e17iic_release_bus(void *v, int flags)
    167  1.1     brad {
    168  1.1     brad 	return;
    169  1.1     brad }
    170  1.1     brad 
    171  1.1     brad /* Perform most of a I2C transaction.  Sometimes there there will be
    172  1.1     brad  * more to read from the 1-Wire bus.  That is device command dependent.
    173  1.1     brad  */
    174  1.1     brad 
    175  1.1     brad static int
    176  1.1     brad ds28e17iic_ow_i2c_transaction(struct ds28e17iic_softc *sc, const char *what, uint8_t device_cmd,
    177  1.1     brad     uint8_t i2c_addr, uint8_t len1, uint8_t *buf1, uint8_t len2,
    178  1.1     brad     uint8_t crc16[2], uint8_t *i2c_status)
    179  1.1     brad {
    180  1.1     brad 	int err = 0;
    181  1.1     brad 	int readycount;
    182  1.1     brad 	uint8_t ready;
    183  1.1     brad 
    184  1.1     brad 	if (onewire_reset(sc->sc_onewire) != 0) {
    185  1.1     brad 		err = EIO;
    186  1.1     brad 	} else {
    187  1.1     brad 		ds28e17iic_crc16(crc16,device_cmd,i2c_addr,len1,buf1,len2);
    188  1.1     brad 		onewire_matchrom(sc->sc_onewire, sc->sc_rom);
    189  1.1     brad 		onewire_write_byte(sc->sc_onewire,device_cmd);
    190  1.1     brad 		if (i2c_addr != 0xff)
    191  1.1     brad 			onewire_write_byte(sc->sc_onewire,i2c_addr);
    192  1.1     brad 		onewire_write_byte(sc->sc_onewire,len1);
    193  1.1     brad 		if (buf1 != NULL)
    194  1.1     brad 			onewire_write_block(sc->sc_onewire,buf1,len1);
    195  1.1     brad 		if (len2 > 0)
    196  1.1     brad 			onewire_write_byte(sc->sc_onewire,len2);
    197  1.1     brad 		onewire_write_block(sc->sc_onewire,crc16,2);
    198  1.1     brad 		readycount=0;
    199  1.1     brad 		do {
    200  1.1     brad 			READY_DELAY(sc->sc_readydelay);
    201  1.1     brad 			ready = onewire_read_bit(sc->sc_onewire);
    202  1.1     brad 			readycount++;
    203  1.1     brad 			if (readycount > sc->sc_readycount)
    204  1.1     brad 				err = EAGAIN;
    205  1.1     brad 		} while (ready != 0 && !err);
    206  1.1     brad 		DPRINTF(sc, 3, ("%s: readycount=%d, err=%d\n",
    207  1.1     brad 		    what, readycount, err));
    208  1.1     brad 		*i2c_status = onewire_read_byte(sc->sc_onewire);
    209  1.1     brad 	}
    210  1.1     brad 
    211  1.1     brad 	return(err);
    212  1.1     brad }
    213  1.1     brad 
    214  1.1     brad /* This needs to determine what sort of write is going on.  We will may make use
    215  1.1     brad  * of the fact that the chip can start a write transaction with one command and
    216  1.1     brad  * add data to it with a second command.
    217  1.1     brad  */
    218  1.1     brad 
    219  1.1     brad static int
    220  1.1     brad ds28e17iic_i2c_write(struct ds28e17iic_softc *sc, i2c_op_t op, i2c_addr_t addr,
    221  1.1     brad     const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int flags)
    222  1.1     brad {
    223  1.1     brad 	uint8_t crc16[2];
    224  1.1     brad 	uint8_t dcmd;
    225  1.1     brad 	uint8_t i2c_status;
    226  1.1     brad 	uint8_t i2c_write_status;
    227  1.1     brad 	uint8_t *buf;
    228  1.1     brad 	size_t len;
    229  1.1     brad 	uint8_t maddr;
    230  1.1     brad 	int err = 0;
    231  1.1     brad 
    232  1.1     brad 	if (sc->sc_dying)
    233  1.1     brad 		return(EIO);
    234  1.1     brad 
    235  1.1     brad 	/* It would be possible to support more than 256 bytes in a transfer by
    236  1.1     brad 	 * breaking it up and using the chip's ability to add data to a write,
    237  1.1     brad 	 * but that isn't currently done.
    238  1.1     brad 	 */
    239  1.1     brad 
    240  1.1     brad 	if (cmdbuf != NULL &&
    241  1.1     brad 	    cmdlen > 256)
    242  1.1     brad 		return(ENOTSUP);
    243  1.1     brad 
    244  1.1     brad 	if (databuf != NULL &&
    245  1.1     brad 	    datalen > 256)
    246  1.1     brad 		return(ENOTSUP);
    247  1.1     brad 
    248  1.1     brad 	/* Just null out any attempt to not actually do anything, might save us
    249  1.1     brad 	 * a panic */
    250  1.1     brad 
    251  1.1     brad 	if (cmdbuf == NULL &&
    252  1.1     brad 	    databuf == NULL)
    253  1.1     brad 		return(err);
    254  1.1     brad 
    255  1.1     brad 	maddr = addr << 1;
    256  1.1     brad 
    257  1.1     brad 	onewire_lock(sc->sc_onewire);
    258  1.1     brad 
    259  1.1     brad 	/* Consider two ways to do a basic write.  One is where there is a
    260  1.1     brad 	 * cmdbuf and databuf which can use the chip's ability to add to a
    261  1.1     brad 	 * ongoing transaction and the other case where there is just the
    262  1.1     brad 	 * cmdbuf or the databuf, in which case, just figure out if a stop
    263  1.1     brad 	 * is needed.
    264  1.1     brad 	 */
    265  1.1     brad 
    266  1.1     brad 	if (cmdbuf != NULL &&
    267  1.1     brad 	    databuf != NULL) {
    268  1.1     brad 		/* This chip considers a zero length write an error */
    269  1.1     brad 		if (cmdlen == 0 ||
    270  1.1     brad 		    datalen == 0) {
    271  1.1     brad 			if (sc->sc_reportzerolen)
    272  1.1     brad 				device_printf(sc->sc_dv,"ds28e17iic_i2c_write: ************ called with zero length read: cmdlen: %zu, datalen: %zu ***************\n",
    273  1.1     brad 				    cmdlen, datalen);
    274  1.1     brad 		}
    275  1.1     brad 
    276  1.1     brad 		/* In this case, always start out with a write without stop. */
    277  1.1     brad 
    278  1.1     brad 		err = ds28e17iic_ow_i2c_transaction(sc, "ds28e17iic_i2c_write cmd and data 1",
    279  1.1     brad 		    DS28E17IIC_DC_WD, maddr, cmdlen, __UNCONST(cmdbuf), 0, crc16, &i2c_status);
    280  1.1     brad 		if (! err) {
    281  1.1     brad 			i2c_write_status = onewire_read_byte(sc->sc_onewire);
    282  1.1     brad 			DPRINTF(sc, 2, ("ds28e17iic_i2c_write: both cmd and data 1: i2c_status=%02x, i2c_write_status=%02x\n",
    283  1.1     brad 			    i2c_status, i2c_write_status));
    284  1.1     brad 			if (i2c_status == 0 &&
    285  1.1     brad 			    i2c_write_status == 0) {
    286  1.1     brad 				/* Add data to the transaction and maybe do a stop as well */
    287  1.1     brad 				if (I2C_OP_STOP_P(op))
    288  1.1     brad 					dcmd = DS28E17IIC_DC_WD_ONLY_WITH_STOP;
    289  1.1     brad 				else
    290  1.1     brad 					dcmd = DS28E17IIC_DC_WD_ONLY;
    291  1.1     brad 
    292  1.1     brad 				err = ds28e17iic_ow_i2c_transaction(sc, "ds28e17iic_i2c_write cmd and data 2",
    293  1.1     brad 				    dcmd, 0xff, datalen, databuf, 0, crc16, &i2c_status);
    294  1.1     brad 				if (! err) {
    295  1.1     brad 					i2c_write_status = onewire_read_byte(sc->sc_onewire);
    296  1.1     brad 					DPRINTF(sc, 2, ("ds28e17iic_i2c_write: both cmd and data 2: dcmd=%02x, i2c_status=%02x, i2c_write_status=%02x\n",
    297  1.1     brad 					    dcmd, i2c_status, i2c_write_status));
    298  1.1     brad 					if (i2c_status != 0 ||
    299  1.1     brad 					    i2c_write_status != 0)
    300  1.1     brad 						err = EIO;
    301  1.1     brad 				} else {
    302  1.1     brad 					DPRINTF(sc, 2, ("ds28e17iic_i2c_write: cmd and data 2: err=%d\n", err));
    303  1.1     brad 				}
    304  1.1     brad 			} else {
    305  1.1     brad 				err = EIO;
    306  1.1     brad 			}
    307  1.1     brad 		} else {
    308  1.1     brad 			DPRINTF(sc, 2, ("ds28e17iic_i2c_write: cmd and data 1: err=%d\n", err));
    309  1.1     brad 		}
    310  1.1     brad 	} else {
    311  1.1     brad 		/* Either the cmdbuf or databuf has something, figure out which
    312  1.1     brad 		 * and maybe perform a stop after the write.
    313  1.1     brad 		 */
    314  1.1     brad 		if (cmdbuf != NULL) {
    315  1.1     brad 			buf = __UNCONST(cmdbuf);
    316  1.1     brad 			len = cmdlen;
    317  1.1     brad 		} else {
    318  1.1     brad 			buf = databuf;
    319  1.1     brad 			len = datalen;
    320  1.1     brad 		}
    321  1.1     brad 
    322  1.1     brad 		if (I2C_OP_STOP_P(op))
    323  1.1     brad 			dcmd = DS28E17IIC_DC_WD_WITH_STOP;
    324  1.1     brad 		else
    325  1.1     brad 			dcmd = DS28E17IIC_DC_WD;
    326  1.1     brad 
    327  1.1     brad 		if (len == 0) {
    328  1.1     brad 			if (sc->sc_reportzerolen)
    329  1.1     brad 				device_printf(sc->sc_dv,"ds28e17iic_i2c_write: ************ called with zero length read ***************\n");
    330  1.1     brad 		}
    331  1.1     brad 
    332  1.1     brad 		err = ds28e17iic_ow_i2c_transaction(sc, "ds28e17iic_i2c_write cmd or data",
    333  1.1     brad 		    dcmd, maddr, len, buf, 0, crc16, &i2c_status);
    334  1.1     brad 		if (! err) {
    335  1.1     brad 			i2c_write_status = onewire_read_byte(sc->sc_onewire);
    336  1.1     brad 			DPRINTF(sc, 2, ("ds28e17iic_i2c_write: cmd or data: dcmd=%02x, i2c_status=%02x, i2c_write_status=%02x\n",
    337  1.1     brad 			    dcmd, i2c_status, i2c_write_status));
    338  1.1     brad 			if (i2c_status != 0 ||
    339  1.1     brad 			    i2c_write_status != 0)
    340  1.1     brad 				err = EIO;
    341  1.1     brad 		} else {
    342  1.1     brad 			DPRINTF(sc, 2, ("ds28e17iic_i2c_write: cmd or data: err=%d\n", err));
    343  1.1     brad 		}
    344  1.1     brad 	}
    345  1.1     brad 
    346  1.1     brad 	onewire_unlock(sc->sc_onewire);
    347  1.1     brad 
    348  1.1     brad 	return(err);
    349  1.1     brad }
    350  1.1     brad 
    351  1.1     brad /* This deals with the situation where the desire is just to read from
    352  1.1     brad  * the device.  The chip does not support Read without Stop, so turn
    353  1.1     brad  * that into a Read with Stop and hope for the best.
    354  1.1     brad  */
    355  1.1     brad 
    356  1.1     brad static int
    357  1.1     brad ds28e17iic_i2c_read(struct ds28e17iic_softc *sc, i2c_op_t op, i2c_addr_t addr,
    358  1.1     brad     void *databuf, size_t datalen, int flags)
    359  1.1     brad {
    360  1.1     brad 	uint8_t crc16[2];
    361  1.1     brad 	uint8_t i2c_status;
    362  1.1     brad 	uint8_t maddr;
    363  1.1     brad 	int err = 0;
    364  1.1     brad 
    365  1.1     brad 	if (sc->sc_dying)
    366  1.1     brad 		return(EIO);
    367  1.1     brad 
    368  1.1     brad 	/* It does not appear that it is possible to read more than 256 bytes */
    369  1.1     brad 
    370  1.1     brad 	if (databuf != NULL &&
    371  1.1     brad 	    datalen > 256)
    372  1.1     brad 		return(ENOTSUP);
    373  1.1     brad 
    374  1.1     brad 	/* Just null out the attempt to not really read anything */
    375  1.1     brad 
    376  1.1     brad 	if (databuf == NULL)
    377  1.1     brad 		return(err);
    378  1.1     brad 
    379  1.1     brad 	maddr = (addr << 1) | 0x01;
    380  1.1     brad 
    381  1.1     brad 	onewire_lock(sc->sc_onewire);
    382  1.1     brad 
    383  1.1     brad 	/* Same thing as a write, a zero length read is considered an error */
    384  1.1     brad 
    385  1.1     brad 	if (datalen == 0)
    386  1.1     brad 		if (sc->sc_reportzerolen)
    387  1.1     brad 			device_printf(sc->sc_dv,"ds28e17iic_i2c_read: ************ called with zero length read ***************\n");
    388  1.1     brad 
    389  1.1     brad 	if (!I2C_OP_STOP_P(op) &&
    390  1.1     brad 	    sc->sc_reportreadnostop)
    391  1.1     brad 		device_printf(sc->sc_dv,"ds28e17iic_i2c_read: ************ called with READ without STOP ***************\n");
    392  1.1     brad 
    393  1.1     brad 	err = ds28e17iic_ow_i2c_transaction(sc, "ds28e17iic_i2c_read",
    394  1.1     brad 	    DS28E17IIC_DC_RD_WITH_STOP, maddr, datalen,
    395  1.1     brad 	    NULL, 0, crc16, &i2c_status);
    396  1.1     brad 	if (! err) {
    397  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_i2c_read: i2c_status=%02x\n", i2c_status));
    398  1.1     brad 		if (i2c_status == 0) {
    399  1.1     brad 			onewire_read_block(sc->sc_onewire, databuf, datalen);
    400  1.1     brad 		} else {
    401  1.1     brad 			err = EIO;
    402  1.1     brad 		}
    403  1.1     brad 	} else {
    404  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_i2c_read: err=%d\n", err));
    405  1.1     brad 	}
    406  1.1     brad 
    407  1.1     brad 	onewire_unlock(sc->sc_onewire);
    408  1.1     brad 
    409  1.1     brad 	return(err);
    410  1.1     brad }
    411  1.1     brad 
    412  1.1     brad /* This deals with the situation where the desire is to write something to
    413  1.1     brad  * the device and then read some stuff back.  The chip does not support Read
    414  1.1     brad  * without Stop, so turn that into a Read with Stop and hope for the best.
    415  1.1     brad  */
    416  1.1     brad 
    417  1.1     brad static int
    418  1.1     brad ds28e17iic_i2c_write_read(struct ds28e17iic_softc *sc, i2c_op_t op, i2c_addr_t addr,
    419  1.1     brad     const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int flags)
    420  1.1     brad {
    421  1.1     brad 	uint8_t crc16[2];
    422  1.1     brad 	uint8_t i2c_status;
    423  1.1     brad 	uint8_t i2c_write_status;
    424  1.1     brad 	uint8_t maddr;
    425  1.1     brad 	int err = 0;
    426  1.1     brad 
    427  1.1     brad 	if (sc->sc_dying)
    428  1.1     brad 		return(EIO);
    429  1.1     brad 
    430  1.1     brad 	/* When using the write+read command of the chip, it does not appear to be
    431  1.1     brad 	 * possible to read more than 256 bytes, or write more than 256 bytes in a
    432  1.1     brad 	 * transaction.
    433  1.1     brad 	 */
    434  1.1     brad 
    435  1.1     brad 	if (cmdbuf != NULL &&
    436  1.1     brad 	    cmdlen > 256)
    437  1.1     brad 		return(ENOTSUP);
    438  1.1     brad 
    439  1.1     brad 	if (databuf != NULL &&
    440  1.1     brad 	    datalen > 256)
    441  1.1     brad 		return(ENOTSUP);
    442  1.1     brad 
    443  1.1     brad 	/* Just return if asked to not actually do anything */
    444  1.1     brad 
    445  1.1     brad 	if (cmdbuf == NULL &&
    446  1.1     brad 	    databuf == NULL)
    447  1.1     brad 		return(err);
    448  1.1     brad 
    449  1.1     brad 	maddr = addr << 1;
    450  1.1     brad 
    451  1.1     brad 	/* Same as a single read or write, a zero length anything here is
    452  1.1     brad 	 * considered an error.
    453  1.1     brad 	 */
    454  1.1     brad 
    455  1.1     brad 	if (cmdlen == 0 ||
    456  1.1     brad 	    datalen == 0) {
    457  1.1     brad 		if (sc->sc_reportzerolen)
    458  1.1     brad 			device_printf(sc->sc_dv,"ds28e17iic_i2c_write_read: ************ called with zero length read: cmdlen: %zu, datalen: %zu ***************\n",
    459  1.1     brad 			    cmdlen, datalen);
    460  1.1     brad 	}
    461  1.1     brad 
    462  1.1     brad 	if (!I2C_OP_STOP_P(op) &&
    463  1.1     brad 	    sc->sc_reportreadnostop)
    464  1.1     brad 		device_printf(sc->sc_dv,"ds28e17iic_i2c_write_read: ************ called with READ without STOP ***************\n");
    465  1.1     brad 
    466  1.1     brad 	onewire_lock(sc->sc_onewire);
    467  1.1     brad 
    468  1.1     brad 	err = ds28e17iic_ow_i2c_transaction(sc, "ds28e17iic_i2c_write_read",
    469  1.1     brad 	    DS28E17IIC_DC_WD_RD_WITH_STOP, maddr, cmdlen,
    470  1.1     brad 	    __UNCONST(cmdbuf), datalen, crc16, &i2c_status);
    471  1.1     brad 	if (! err) {
    472  1.1     brad 		/* Like with the normal write, even if the i2c_status is not zero,
    473  1.1     brad 		 * we have to read the write status too.  It will end up being
    474  1.1     brad 		 * the value 0xff. */
    475  1.1     brad 		i2c_write_status = onewire_read_byte(sc->sc_onewire);
    476  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_i2c_write_read: i2c_status=%02x, i2c_write_status=%02x\n",
    477  1.1     brad 		    i2c_status, i2c_write_status));
    478  1.1     brad 		/* However, don't bother trying to read the data block if there was an error */
    479  1.1     brad 		if (i2c_status == 0 &&
    480  1.1     brad 		    i2c_write_status == 0) {
    481  1.1     brad 			onewire_read_block(sc->sc_onewire, databuf, datalen);
    482  1.1     brad 		} else {
    483  1.1     brad 			err = EIO;
    484  1.1     brad 		}
    485  1.1     brad 	} else {
    486  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_i2c_write_read: err=%d\n", err));
    487  1.1     brad 	}
    488  1.1     brad 
    489  1.1     brad 	onewire_unlock(sc->sc_onewire);
    490  1.1     brad 
    491  1.1     brad 	return(err);
    492  1.1     brad }
    493  1.1     brad 
    494  1.1     brad /* This needs to figure out what sort of thing is being sent to the end device.
    495  1.1     brad  * The chip will help out with some of this.
    496  1.1     brad  */
    497  1.1     brad 
    498  1.1     brad static int
    499  1.1     brad ds28e17iic_i2c_exec(void *v, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
    500  1.1     brad     size_t cmdlen, void *databuf, size_t datalen, int flags)
    501  1.1     brad {
    502  1.1     brad 	struct ds28e17iic_softc *sc = v;
    503  1.1     brad 	int err = 0;
    504  1.1     brad 
    505  1.1     brad 	if (sc->sc_dying)
    506  1.1     brad 		return(EIO);
    507  1.1     brad 
    508  1.1     brad 	/* The chip only supports 7 bit addressing */
    509  1.1     brad 
    510  1.1     brad 	if (addr > 0x7f)
    511  1.1     brad 		return (ENOTSUP);
    512  1.1     brad 
    513  1.1     brad 	/* XXX - this driver could support setting the speed for this I2C
    514  1.1     brad 	 * transaction as that information is in the flags, but nothing really
    515  1.1     brad 	 * asks to do that, so just ignore that for now.
    516  1.1     brad 	 *
    517  1.1     brad 	 * If it did support setting speed, do it here.
    518  1.1     brad 	 *
    519  1.1     brad 	 */
    520  1.1     brad 
    521  1.1     brad 	if (I2C_OP_WRITE_P(op)) {
    522  1.1     brad 		/* A write may include the cmdbuf and/or the databuf */
    523  1.1     brad 		err = ds28e17iic_i2c_write(sc, op, addr, cmdbuf, cmdlen, databuf, datalen, flags);
    524  1.1     brad 
    525  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_exec: I2C WRITE: addr=%02x, err=%d\n", addr, err));
    526  1.1     brad 	} else {
    527  1.1     brad 		/* If a read includes a cmdbuf, then this is a write+read operation */
    528  1.1     brad 		if (cmdbuf != NULL)
    529  1.1     brad 			err = ds28e17iic_i2c_write_read(sc, op, addr, cmdbuf, cmdlen, databuf, datalen, flags);
    530  1.1     brad 		else
    531  1.1     brad 			err = ds28e17iic_i2c_read(sc, op, addr, databuf, datalen, flags);
    532  1.1     brad 
    533  1.1     brad 		DPRINTF(sc, 2, ("ds28e17iic_exec: I2C %s addr=%02x, err=%d\n",
    534  1.1     brad 		    cmdbuf != NULL ? "WRITE-READ" : "READ", addr, err));
    535  1.1     brad 	}
    536  1.1     brad 
    537  1.1     brad 	return(err);
    538  1.1     brad }
    539  1.1     brad 
    540  1.1     brad static int
    541  1.1     brad ds28e17iic_sysctl_init(struct ds28e17iic_softc *sc)
    542  1.1     brad {
    543  1.1     brad 	int error;
    544  1.1     brad 	const struct sysctlnode *cnode;
    545  1.1     brad 	int sysctlroot_num;
    546  1.1     brad 
    547  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    548  1.1     brad 	    0, CTLTYPE_NODE, device_xname(sc->sc_dv),
    549  1.1     brad 	    SYSCTL_DESCR("DS28E17IIC controls"), NULL, 0, NULL, 0, CTL_HW,
    550  1.1     brad 	    CTL_CREATE, CTL_EOL)) != 0)
    551  1.1     brad 		return error;
    552  1.1     brad 
    553  1.1     brad 	sysctlroot_num = cnode->sysctl_num;
    554  1.1     brad 
    555  1.1     brad #ifdef DS28E17IIC_DEBUG
    556  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    557  1.1     brad 	    CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
    558  1.1     brad 	    SYSCTL_DESCR("Debug level"), ds28e17iic_verify_sysctl, 0,
    559  1.1     brad 	    &sc->sc_ds28e17iicdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    560  1.1     brad 	    CTL_EOL)) != 0)
    561  1.1     brad 		return error;
    562  1.1     brad #endif
    563  1.1     brad 
    564  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    565  1.1     brad 	    CTLFLAG_READWRITE, CTLTYPE_INT, "readycount",
    566  1.1     brad 	    SYSCTL_DESCR("How many times to wait for the I2C transaction to finish"), ds28e17iic_verify_sysctl, 0,
    567  1.1     brad 	    &sc->sc_readycount, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    568  1.1     brad 	    CTL_EOL)) != 0)
    569  1.1     brad 		return error;
    570  1.1     brad 
    571  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    572  1.1     brad 	    CTLFLAG_READWRITE, CTLTYPE_INT, "readydelay",
    573  1.1     brad 	    SYSCTL_DESCR("Delay in microseconds before checking the I2C transaction"), ds28e17iic_verify_sysctl, 0,
    574  1.1     brad 	    &sc->sc_readydelay, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    575  1.1     brad 	    CTL_EOL)) != 0)
    576  1.1     brad 		return error;
    577  1.1     brad 
    578  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    579  1.1     brad 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "reportreadnostop",
    580  1.1     brad 	    SYSCTL_DESCR("Report that a READ without STOP was attempted by a device"),
    581  1.1     brad 	    NULL, 0, &sc->sc_reportreadnostop, 0, CTL_HW, sysctlroot_num,
    582  1.1     brad 	    CTL_CREATE, CTL_EOL)) != 0)
    583  1.1     brad 		return error;
    584  1.1     brad 
    585  1.1     brad 	if ((error = sysctl_createv(&sc->sc_ds28e17iiclog, 0, NULL, &cnode,
    586  1.1     brad 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "reportzerolen",
    587  1.1     brad 	    SYSCTL_DESCR("Report that an attempt to read or write zero length was attempted"),
    588  1.1     brad 	    NULL, 0, &sc->sc_reportzerolen, 0, CTL_HW, sysctlroot_num,
    589  1.1     brad 	    CTL_CREATE, CTL_EOL)) != 0)
    590  1.1     brad 		return error;
    591  1.1     brad 
    592  1.1     brad 	return 0;
    593  1.1     brad }
    594  1.1     brad 
    595  1.1     brad static int
    596  1.1     brad ds28e17iic_match(device_t parent, cfdata_t match, void *aux)
    597  1.1     brad {
    598  1.1     brad 	return (onewire_matchbyfam(aux, ds28e17iic_fams,
    599  1.1     brad 	    __arraycount(ds28e17iic_fams)));
    600  1.1     brad }
    601  1.1     brad 
    602  1.1     brad static void
    603  1.1     brad ds28e17iic_attach(device_t parent, device_t self, void *aux)
    604  1.1     brad {
    605  1.1     brad 	struct ds28e17iic_softc *sc = device_private(self);
    606  1.1     brad 	struct onewire_attach_args *oa = aux;
    607  1.1     brad 	uint8_t hardware_rev;
    608  1.1     brad 	uint8_t i2c_speed[2];
    609  1.1     brad 	int err = 0;
    610  1.1     brad 
    611  1.1     brad 	aprint_normal("\n");
    612  1.1     brad 
    613  1.1     brad 	sc->sc_dv = self;
    614  1.1     brad 	sc->sc_onewire = oa->oa_onewire;
    615  1.1     brad 	sc->sc_rom = oa->oa_rom;
    616  1.1     brad 	sc->sc_reportreadnostop = true;
    617  1.1     brad 	sc->sc_reportzerolen = true;
    618  1.1     brad 	sc->sc_ds28e17iicdebug = 0;
    619  1.1     brad 	sc->sc_readycount=20;
    620  1.1     brad 	sc->sc_readydelay = 10;
    621  1.1     brad 
    622  1.1     brad 	if ((err = ds28e17iic_sysctl_init(sc)) != 0) {
    623  1.1     brad 		aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", err);
    624  1.1     brad 		return;
    625  1.1     brad 	}
    626  1.1     brad 
    627  1.1     brad 	onewire_lock(sc->sc_onewire);
    628  1.1     brad 
    629  1.1     brad 	if (onewire_reset(sc->sc_onewire) != 0) {
    630  1.1     brad 		aprint_error_dev(sc->sc_dv, "Could not reset the onewire bus for hardware version\n");
    631  1.1     brad 		onewire_unlock(sc->sc_onewire);
    632  1.1     brad 		return;
    633  1.1     brad 	}
    634  1.1     brad 	onewire_matchrom(sc->sc_onewire, sc->sc_rom);
    635  1.1     brad 	onewire_write_byte(sc->sc_onewire, DS28E17IIC_DC_DEV_REVISION);
    636  1.1     brad 	hardware_rev = onewire_read_byte(sc->sc_onewire);
    637  1.1     brad 
    638  1.1     brad 	aprint_normal_dev(sc->sc_dv, "Hardware revision: %d\n",
    639  1.1     brad 	    hardware_rev);
    640  1.1     brad 
    641  1.1     brad 	/* The default for the chip is 400Khz, but some devices may not be able
    642  1.1     brad 	 * to deal with that, so set the speed to 100Khz which is standard I2C
    643  1.1     brad 	 * speed.
    644  1.1     brad 	 */
    645  1.1     brad 
    646  1.1     brad 	if (onewire_reset(sc->sc_onewire) != 0) {
    647  1.1     brad 		aprint_error_dev(sc->sc_dv, "Could not reset the onewire bus to set I2C speed\n");
    648  1.1     brad 		onewire_unlock(sc->sc_onewire);
    649  1.1     brad 		return;
    650  1.1     brad 	}
    651  1.1     brad 	onewire_matchrom(sc->sc_onewire, sc->sc_rom);
    652  1.1     brad 	i2c_speed[0] = DS28E17IIC_DC_WRITE_CONFIG;
    653  1.1     brad 	i2c_speed[1] = DS28E17IIC_SPEED_100KHZ;
    654  1.1     brad 	onewire_write_block(sc->sc_onewire, i2c_speed, 2);
    655  1.1     brad 
    656  1.1     brad 	onewire_unlock(sc->sc_onewire);
    657  1.1     brad 
    658  1.1     brad 	iic_tag_init(&sc->sc_i2c_tag);
    659  1.1     brad 	sc->sc_i2c_tag.ic_cookie = sc;
    660  1.1     brad 	sc->sc_i2c_tag.ic_acquire_bus = ds28e17iic_acquire_bus;
    661  1.1     brad 	sc->sc_i2c_tag.ic_release_bus = ds28e17iic_release_bus;
    662  1.1     brad 	sc->sc_i2c_tag.ic_exec = ds28e17iic_i2c_exec;
    663  1.1     brad 
    664  1.2  thorpej 	sc->sc_i2c_dev = iicbus_attach(self, &sc->sc_i2c_tag);
    665  1.1     brad }
    666  1.1     brad 
    667  1.1     brad static int
    668  1.1     brad ds28e17iic_detach(device_t self, int flags)
    669  1.1     brad {
    670  1.1     brad 	struct ds28e17iic_softc *sc = device_private(self);
    671  1.1     brad 	int err = 0;
    672  1.1     brad 
    673  1.1     brad 	sc->sc_dying = 1;
    674  1.1     brad 
    675  1.1     brad 	err = config_detach_children(self, flags);
    676  1.1     brad 	if (err)
    677  1.1     brad 		return err;
    678  1.1     brad 
    679  1.1     brad 	sysctl_teardown(&sc->sc_ds28e17iiclog);
    680  1.1     brad 
    681  1.1     brad 	return 0;
    682  1.1     brad }
    683  1.1     brad 
    684  1.1     brad static int
    685  1.1     brad ds28e17iic_activate(device_t self, enum devact act)
    686  1.1     brad {
    687  1.1     brad 	struct ds28e17iic_softc *sc = device_private(self);
    688  1.1     brad 
    689  1.1     brad 	switch (act) {
    690  1.1     brad 	case DVACT_DEACTIVATE:
    691  1.1     brad 		sc->sc_dying = 1;
    692  1.1     brad 		return 0;
    693  1.1     brad 	default:
    694  1.1     brad 		return EOPNOTSUPP;
    695  1.1     brad 	}
    696  1.1     brad }
    697  1.1     brad 
    698  1.1     brad 
    699  1.1     brad MODULE(MODULE_CLASS_DRIVER, ds28e17iic, "onewire,iic");
    700  1.1     brad 
    701  1.1     brad #ifdef _MODULE
    702  1.1     brad #include "ioconf.c"
    703  1.1     brad #endif
    704  1.1     brad 
    705  1.1     brad static int
    706  1.1     brad ds28e17iic_modcmd(modcmd_t cmd, void *opaque)
    707  1.1     brad {
    708  1.1     brad 	int error;
    709  1.1     brad 
    710  1.1     brad 	error = 0;
    711  1.1     brad 	switch (cmd) {
    712  1.1     brad 	case MODULE_CMD_INIT:
    713  1.1     brad #ifdef _MODULE
    714  1.1     brad 		error = config_init_component(cfdriver_ioconf_ds28e17iic,
    715  1.1     brad 		    cfattach_ioconf_ds28e17iic, cfdata_ioconf_ds28e17iic);
    716  1.1     brad 		if (error)
    717  1.1     brad 			aprint_error("%s: unable to init component\n",
    718  1.1     brad 			    ds28e17iic_cd.cd_name);
    719  1.1     brad #endif
    720  1.1     brad 		break;
    721  1.1     brad 	case MODULE_CMD_FINI:
    722  1.1     brad #ifdef _MODULE
    723  1.1     brad 		config_fini_component(cfdriver_ioconf_ds28e17iic,
    724  1.1     brad 		    cfattach_ioconf_ds28e17iic, cfdata_ioconf_ds28e17iic);
    725  1.1     brad #endif
    726  1.1     brad 		break;
    727  1.1     brad 	default:
    728  1.1     brad 		error = ENOTTY;
    729  1.1     brad 	}
    730  1.1     brad 	return error;
    731  1.1     brad }
    732