Home | History | Annotate | Line # | Download | only in i2c
i2c_exec.c revision 1.1
      1 /*	$NetBSD: i2c_exec.c,v 1.1 2003/09/30 00:35:31 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2003 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed for the NetBSD Project by
     20  *      Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/device.h>
     41 #include <sys/event.h>
     42 #include <sys/conf.h>
     43 
     44 #define	_I2C_PRIVATE
     45 #include <dev/i2c/i2cvar.h>
     46 
     47 /*
     48  * iic_exec:
     49  *
     50  *	Simplified I2C client interface engine.
     51  *
     52  *	This and the SMBus routines are the preferred interface for
     53  *	client access to I2C/SMBus, since many automated controllers
     54  *	do not provide access to the low-level primitives of the I2C
     55  *	bus protocol.
     56  */
     57 int
     58 iic_exec(i2c_tag_t tag, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
     59     size_t cmdlen, void *vbuf, size_t buflen, int flags)
     60 {
     61 	const uint8_t *cmd = vcmd;
     62 	uint8_t *buf = vbuf;
     63 	int error;
     64 	size_t len;
     65 
     66 	/*
     67 	 * Defer to the controller if it provides an exec function.  Use
     68 	 * it if it does.
     69 	 */
     70 	if (tag->ic_exec != NULL)
     71 		return ((*tag->ic_exec)(tag->ic_cookie, op, addr, cmd,
     72 					cmdlen, buf, buflen, flags));
     73 
     74 	if ((len = cmdlen) != 0) {
     75 		if ((error = iic_initiate_xfer(tag, addr, flags)) != 0)
     76 			goto bad;
     77 		while (len--) {
     78 			if ((error = iic_write_byte(tag, *cmd++, flags)) != 0)
     79 				goto bad;
     80 		}
     81 	}
     82 
     83 	if (I2C_OP_READ_P(op))
     84 		flags |= I2C_F_READ;
     85 
     86 	len = buflen;
     87 	while (len--) {
     88 		if (len == 0 && I2C_OP_STOP_P(op))
     89 			flags |= I2C_F_STOP;
     90 		if (I2C_OP_READ_P(op)) {
     91 			/* Send REPEATED START. */
     92 			if ((len + 1) == buflen &&
     93 			    (error = iic_initiate_xfer(tag, addr, flags)) != 0)
     94 				goto bad;
     95 			/* NACK on last byte. */
     96 			if (len == 0)
     97 				flags |= I2C_F_LAST;
     98 			if ((error = iic_read_byte(tag, buf++, flags)) != 0)
     99 				goto bad;
    100 		} else  {
    101 			/* Maybe send START. */
    102 			if ((len + 1) == buflen && cmdlen == 0 &&
    103 			    (error = iic_initiate_xfer(tag, addr, flags)) != 0)
    104 				goto bad;
    105 			if ((error == iic_write_byte(tag, *buf++, flags)) != 0)
    106 				goto bad;
    107 		}
    108 	}
    109 
    110 	return (0);
    111  bad:
    112 	iic_send_stop(tag, flags);
    113 	return (error);
    114 }
    115 
    116 /*
    117  * iic_smbus_write_byte:
    118  *
    119  *	Perform an SMBus "write byte" operation.
    120  */
    121 int
    122 iic_smbus_write_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
    123     uint8_t val, int flags)
    124 {
    125 
    126 	return (iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd, 1,
    127 			 &val, 1, flags));
    128 }
    129 
    130 /*
    131  * iic_smbus_read_byte:
    132  *
    133  *	Perform an SMBus "read byte" operation.
    134  */
    135 int
    136 iic_smbus_read_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
    137     uint8_t *valp, int flags)
    138 {
    139 
    140 	return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, &cmd, 1,
    141 			 valp, 1, flags));
    142 }
    143 
    144 /*
    145  * iic_smbus_receive_byte:
    146  *
    147  *	Perform an SMBus "receive byte" operation.
    148  */
    149 int
    150 iic_smbus_receive_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t *valp,
    151     int flags)
    152 {
    153 
    154 	return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0,
    155 			 valp, 1, flags));
    156 }
    157