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