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