Thu Jan 19 17:29:23 2012 UTC ()
Enable interrupts (even though they are not yet used).


(matt)
diff -r1.1.2.2 -r1.1.2.3 src/sys/arch/mips/rmi/rmixl_i2c_pci.c

cvs diff -r1.1.2.2 -r1.1.2.3 src/sys/arch/mips/rmi/Attic/rmixl_i2c_pci.c (switch to unified diff)

--- src/sys/arch/mips/rmi/Attic/rmixl_i2c_pci.c 2011/12/27 19:57:18 1.1.2.2
+++ src/sys/arch/mips/rmi/Attic/rmixl_i2c_pci.c 2012/01/19 17:29:23 1.1.2.3
@@ -1,455 +1,450 @@ @@ -1,455 +1,450 @@
1/*- 1/*-
2 * Copyright (c) 2011 The NetBSD Foundation, Inc. 2 * Copyright (c) 2011 The NetBSD Foundation, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to The NetBSD Foundation 5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Matt Thomas of 3am Software Foundry. 6 * by Matt Thomas of 3am Software Foundry.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31 31
32__KERNEL_RCSID(1, "$NetBSD: rmixl_i2c_pci.c,v 1.1.2.2 2011/12/27 19:57:18 matt Exp $"); 32__KERNEL_RCSID(1, "$NetBSD: rmixl_i2c_pci.c,v 1.1.2.3 2012/01/19 17:29:23 matt Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37 37
38#include <dev/pci/pcireg.h> 38#include <dev/pci/pcireg.h>
39#include <dev/pci/pcivar.h> 39#include <dev/pci/pcivar.h>
40#include <dev/pci/pcidevs.h> 40#include <dev/pci/pcidevs.h>
41 41
42#include <mips/rmi/rmixlreg.h> 42#include <mips/rmi/rmixlreg.h>
43#include <mips/rmi/rmixlvar.h> 43#include <mips/rmi/rmixlvar.h>
44 44
45#include <mips/rmi/rmixl_i2creg.h> 45#include <mips/rmi/rmixl_i2creg.h>
46#include <mips/rmi/rmixl_i2cvar.h> 46#include <mips/rmi/rmixl_i2cvar.h>
47 47
48#include "locators.h" 48#include "locators.h"
49 49
50#ifdef DEBUG 50#ifdef DEBUG
51int xli2c_debug = 0; 51int xli2c_debug = 0;
52#define DPRINTF(x, ...) do { if (xli2c_debug) printf(x, ## __VA_ARGS__); } while (0) 52#define DPRINTF(x, ...) do { if (xli2c_debug) printf(x, ## __VA_ARGS__); } while (0)
53#else 53#else
54#define DPRINTF(x) 54#define DPRINTF(x)
55#endif 55#endif
56 56
57static int xli2c_pci_match(device_t, cfdata_t, void *); 57static int xli2c_pci_match(device_t, cfdata_t, void *);
58static void xli2c_pci_attach(device_t, device_t, void *); 58static void xli2c_pci_attach(device_t, device_t, void *);
59 59
60static int xli2c_acquire_bus(void *, int); 60static int xli2c_acquire_bus(void *, int);
61static void xli2c_release_bus(void *, int); 61static void xli2c_release_bus(void *, int);
62static int xli2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 62static int xli2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
63 void *, size_t, int); 63 void *, size_t, int);
64#if 0 64
65static int xli2c_intr(void *); 65static int xli2c_intr(void *);
66#endif 66static int xli2c_wait_for_command(struct xli2c_softc *, uint8_t);
67static int xli2c_wait_for_command(struct xli2c_softc *, uint8_t); 
68 67
69static inline uint8_t 68static inline uint8_t
70xli2c_read_status(struct xli2c_softc *sc) 69xli2c_read_status(struct xli2c_softc *sc)
71{ 70{
72 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_STATUS); 71 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_STATUS);
73} 72}
74 73
75static inline uint8_t 74static inline uint8_t
76xli2c_read_control(struct xli2c_softc *sc) 75xli2c_read_control(struct xli2c_softc *sc)
77{ 76{
78 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_CONTROL); 77 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_CONTROL);
79} 78}
80 79
81static inline uint8_t 80static inline uint8_t
82xli2c_read_data_byte(struct xli2c_softc *sc) 81xli2c_read_data_byte(struct xli2c_softc *sc)
83{ 82{
84 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_RECEIVE); 83 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_RECEIVE);
85} 84}
86 85
87static inline void 86static inline void
88xli2c_write_control(struct xli2c_softc *sc, uint32_t v) 87xli2c_write_control(struct xli2c_softc *sc, uint32_t v)
89{ 88{
90 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_CONTROL, v); 89 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_CONTROL, v);
91} 90}
92 91
93static inline void 92static inline void
94xli2c_write_command(struct xli2c_softc *sc, uint32_t v) 93xli2c_write_command(struct xli2c_softc *sc, uint32_t v)
95{ 94{
96 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_COMMAND, v); 95 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_COMMAND, v);
97} 96}
98 97
99static inline void 98static inline void
100xli2c_write_prescale(struct xli2c_softc *sc, uint16_t v) 99xli2c_write_prescale(struct xli2c_softc *sc, uint16_t v)
101{ 100{
102 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 101 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
103 RMIXLP_I2C_CLOCK_PRESCALE_LOW, (v >> 0) & 0xff); 102 RMIXLP_I2C_CLOCK_PRESCALE_LOW, (v >> 0) & 0xff);
104 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 103 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
105 RMIXLP_I2C_CLOCK_PRESCALE_HIGH, (v >> 8) & 0xff); 104 RMIXLP_I2C_CLOCK_PRESCALE_HIGH, (v >> 8) & 0xff);
106} 105}
107 106
108static inline void 107static inline void
109xli2c_write_data_byte(struct xli2c_softc *sc, uint8_t v) 108xli2c_write_data_byte(struct xli2c_softc *sc, uint8_t v)
110{ 109{
111 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_TRANSMIT, v); 110 bus_space_write_4(sc->sc_bst, sc->sc_bsh, RMIXLP_I2C_TRANSMIT, v);
112} 111}
113 112
114CFATTACH_DECL_NEW(xli2c_pci, sizeof(struct xli2c_softc), 113CFATTACH_DECL_NEW(xli2c_pci, sizeof(struct xli2c_softc),
115 xli2c_pci_match, xli2c_pci_attach, 0, 0); 114 xli2c_pci_match, xli2c_pci_attach, 0, 0);
116 115
117static int 116static int
118xli2c_pci_match(device_t parent, cfdata_t cf, void *aux) 117xli2c_pci_match(device_t parent, cfdata_t cf, void *aux)
119{ 118{
120 struct pci_attach_args * const pa = aux; 119 struct pci_attach_args * const pa = aux;
121 120
122 if (pa->pa_id == PCI_ID_CODE(PCI_VENDOR_NETLOGIC, PCI_PRODUCT_NETLOGIC_XLP_I2C)) 121 if (pa->pa_id == PCI_ID_CODE(PCI_VENDOR_NETLOGIC, PCI_PRODUCT_NETLOGIC_XLP_I2C))
123 return 1; 122 return 1;
124 123
125 return 0; 124 return 0;
126} 125}
127 126
128static void 127static void
129xli2c_pci_attach(device_t parent, device_t self, void *aux) 128xli2c_pci_attach(device_t parent, device_t self, void *aux)
130{ 129{
131 struct rmixl_config * const rcp = &rmixl_configuration; 130 struct rmixl_config * const rcp = &rmixl_configuration;
132 struct pci_attach_args * const pa = aux; 131 struct pci_attach_args * const pa = aux;
133 struct xli2c_softc * const sc = device_private(self); 132 struct xli2c_softc * const sc = device_private(self);
134 struct i2cbus_attach_args iba; 133 struct i2cbus_attach_args iba;
135 134
136 sc->sc_dev = self; 135 sc->sc_dev = self;
137 sc->sc_bst = &rcp->rc_pci_ecfg_eb_memt; 136 sc->sc_bst = &rcp->rc_pci_ecfg_eb_memt;
138 137
139 /* 138 /*
140 * Why isn't this accessible via a BAR? 139 * Why isn't this accessible via a BAR?
141 */ 140 */
142 if (bus_space_subregion(sc->sc_bst, rcp->rc_pci_ecfg_eb_memh, 141 if (bus_space_subregion(sc->sc_bst, rcp->rc_pci_ecfg_eb_memh,
143 pa->pa_tag | 0x100, 0, &sc->sc_bsh)) { 142 pa->pa_tag | 0x100, 0, &sc->sc_bsh)) {
144 aprint_error(": can't map registers\n"); 143 aprint_error(": can't map registers\n");
145 return; 144 return;
146 } 145 }
147 146
148 aprint_normal(": XLP I2C Controller\n"); 147 aprint_normal(": XLP I2C Controller\n");
149 148
150 mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE); 149 mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE);
151 150
152 sc->sc_i2c.ic_acquire_bus = xli2c_acquire_bus, 151 sc->sc_i2c.ic_acquire_bus = xli2c_acquire_bus,
153 sc->sc_i2c.ic_release_bus = xli2c_release_bus, 152 sc->sc_i2c.ic_release_bus = xli2c_release_bus,
154 sc->sc_i2c.ic_exec = xli2c_exec, 153 sc->sc_i2c.ic_exec = xli2c_exec,
155 sc->sc_i2c.ic_cookie = sc; 154 sc->sc_i2c.ic_cookie = sc;
156 155
157 xli2c_write_control(sc, 0); /* reset before changing anything */ 156 xli2c_write_control(sc, 0); /* reset before changing anything */
158 xli2c_write_command(sc, RMIXLP_I2C_COMMAND_IACK); 157 xli2c_write_command(sc, RMIXLP_I2C_COMMAND_IACK);
159 /* MMM MAGIC */ 158 /* MMM MAGIC */
160 xli2c_write_prescale(sc, rmixl_i2c_calc_prescale(133333333, 100000)); 159 xli2c_write_prescale(sc, rmixl_i2c_calc_prescale(133333333, 100000));
161 160
162#if 0 
163 pci_intr_handle_t pcih; 161 pci_intr_handle_t pcih;
164 162
165 pci_intr_map(pa, &pcih); 163 pci_intr_map(pa, &pcih);
166 164
167 if (pci_intr_establish(pa->pa_pc, pcih, IPL_VM, xli2c_intr, sc) == NULL) { 165 if (pci_intr_establish(pa->pa_pc, pcih, IPL_VM, xli2c_intr, sc) == NULL) {
168 aprint_error_dev(self, "failed to establish interrupt\n"); 166 aprint_error_dev(self, "failed to establish interrupt\n");
169 } else { 167 } else {
170 const char * const intrstr = pci_intr_string(pa->pa_pc, pcih); 168 const char * const intrstr = pci_intr_string(pa->pa_pc, pcih);
171 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 169 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
172 } 170 }
173#endif 
174 171
175 memset(&iba, 0, sizeof(iba)); 172 memset(&iba, 0, sizeof(iba));
176 iba.iba_tag = &sc->sc_i2c; 173 iba.iba_tag = &sc->sc_i2c;
177 config_found_ia(self, "i2cbus", &iba, iicbus_print); 174 config_found_ia(self, "i2cbus", &iba, iicbus_print);
178} 175}
179 176
180static int 177static int
181xli2c_acquire_bus(void *v, int flags) 178xli2c_acquire_bus(void *v, int flags)
182{ 179{
183 struct xli2c_softc * const sc = v; 180 struct xli2c_softc * const sc = v;
184 181
185 mutex_enter(&sc->sc_buslock); 182 mutex_enter(&sc->sc_buslock);
186 183
187 /* enable the I2C module */ 184 /* enable the I2C module */
188 xli2c_write_control(sc, RMIXLP_I2C_CONTROL_EN); 185 xli2c_write_control(sc, RMIXLP_I2C_CONTROL_EN);
189 186
190 return 0; 187 return 0;
191} 188}
192 189
193static void 190static void
194xli2c_release_bus(void *v, int flags) 191xli2c_release_bus(void *v, int flags)
195{ 192{
196 struct xli2c_softc * const sc = v; 193 struct xli2c_softc * const sc = v;
197 194
198 /* disable the I2C module */ 195 /* disable the I2C module */
199 xli2c_write_control(sc, 0); 196 xli2c_write_control(sc, 0);
200 197
201 mutex_exit(&sc->sc_buslock); 198 mutex_exit(&sc->sc_buslock);
202} 199}
203 200
204#if 0 
205static int 201static int
206xli2c_intr(void *v) 202xli2c_intr(void *v)
207{ 203{
208 struct xli2c_softc * const sc = v; 204 struct xli2c_softc * const sc = v;
209 205
210 panic("%s(%p) called!", __func__, sc); 206 panic("%s(%p) called!", __func__, sc);
211 207
212 return 0; 208 return 0;
213} 209}
214#endif 
215 210
216/* send a command and busy wait for the byte data transfer to complete */ 211/* send a command and busy wait for the byte data transfer to complete */
217static int 212static int
218xli2c_wait_for_command(struct xli2c_softc *sc, uint8_t command) 213xli2c_wait_for_command(struct xli2c_softc *sc, uint8_t command)
219{ 214{
220 uint32_t status; 215 uint32_t status;
221 int error = 0; 216 int error = 0;
222 u_int timo; 217 u_int timo;
223 218
224 /* 219 /*
225 * Issue the command. 220 * Issue the command.
226 */ 221 */
227 xli2c_write_command(sc, command); 222 xli2c_write_command(sc, command);
228 223
229 for (timo = 1000; --timo; ) { 224 for (timo = 1000; --timo; ) {
230 status = xli2c_read_status(sc); 225 status = xli2c_read_status(sc);
231 if ((status & RMIXLP_I2C_STATUS_TIP) == 0) 226 if ((status & RMIXLP_I2C_STATUS_TIP) == 0)
232 break; 227 break;
233 DELAY(10); 228 DELAY(10);
234 } 229 }
235 230
236 if (timo == 0) { 231 if (timo == 0) {
237 DPRINTF("%s: timeout (status=%#x, command=%#x)\n", 232 DPRINTF("%s: timeout (status=%#x, command=%#x)\n",
238 __func__, status, command); 233 __func__, status, command);
239 error = ETIMEDOUT; 234 error = ETIMEDOUT;
240 } 235 }
241 236
242 /* 237 /*
243 * NO_RX_ACK is only valid when transmitting. 238 * NO_RX_ACK is only valid when transmitting.
244 */ 239 */
245 if ((command & RMIXLP_I2C_COMMAND_WR) 240 if ((command & RMIXLP_I2C_COMMAND_WR)
246 && (status & RMIXLP_I2C_STATUS_NO_RX_ACK)) { 241 && (status & RMIXLP_I2C_STATUS_NO_RX_ACK)) {
247 DPRINTF("%s: missing rx ack (status=%#x, command=%#x): " 242 DPRINTF("%s: missing rx ack (status=%#x, command=%#x): "
248 "spin=%u\n", __func__, status, command, 1000 - timo); 243 "spin=%u\n", __func__, status, command, 1000 - timo);
249 error = EIO; 244 error = EIO;
250 } 245 }
251 return error; 246 return error;
252} 247}
253 248
254int 249int
255xli2c_exec(void *v, i2c_op_t op, i2c_addr_t addr, 250xli2c_exec(void *v, i2c_op_t op, i2c_addr_t addr,
256 const void *cmdbuf, size_t cmdlen, 251 const void *cmdbuf, size_t cmdlen,
257 void *databuf, size_t datalen, 252 void *databuf, size_t datalen,
258 int flags) 253 int flags)
259{ 254{
260 struct xli2c_softc * const sc = v; 255 struct xli2c_softc * const sc = v;
261 uint8_t status; 256 uint8_t status;
262 uint8_t command; 257 uint8_t command;
263 int error; 258 int error;
264 259
265 status = xli2c_read_status(sc); 260 status = xli2c_read_status(sc);
266 command = 0; 261 command = 0;
267 262
268#if 0 263#if 0
269 DPRINTF("%s(%#x,%#x,%p,%zu,%p,%zu,%#x): status=%#x command=%#x\n", 264 DPRINTF("%s(%#x,%#x,%p,%zu,%p,%zu,%#x): status=%#x command=%#x\n",
270 __func__, op, addr, cmdbuf, cmdlen, databuf, datalen, flags, 265 __func__, op, addr, cmdbuf, cmdlen, databuf, datalen, flags,
271 status, command); 266 status, command);
272#endif 267#endif
273 268
274 if ((status & RMIXLP_I2C_STATUS_BUSY) != 0) { 269 if ((status & RMIXLP_I2C_STATUS_BUSY) != 0) {
275 /* wait for bus becoming available */ 270 /* wait for bus becoming available */
276 u_int timo = 100; 271 u_int timo = 100;
277 do { 272 do {
278 DELAY(10); 273 DELAY(10);
279 } while (--timo > 0 274 } while (--timo > 0
280 && ((status = xli2c_read_status(sc)) & RMIXLP_I2C_STATUS_BUSY) != 0); 275 && ((status = xli2c_read_status(sc)) & RMIXLP_I2C_STATUS_BUSY) != 0);
281 276
282 if (timo == 0) { 277 if (timo == 0) {
283 DPRINTF("%s: bus is busy (%#x)\n", __func__, status); 278 DPRINTF("%s: bus is busy (%#x)\n", __func__, status);
284 return ETIMEDOUT; 279 return ETIMEDOUT;
285 } 280 }
286 } 281 }
287 282
288 /* reset interrupt and arbitration-lost flags (all others are RO) */ 283 /* reset interrupt and arbitration-lost flags (all others are RO) */
289 xli2c_write_command(sc, RMIXLP_I2C_COMMAND_IACK); 284 xli2c_write_command(sc, RMIXLP_I2C_COMMAND_IACK);
290 285
291 /* 286 /*
292 * send target address and transfer direction 287 * send target address and transfer direction
293 */ 288 */
294 uint8_t addr_byte = (addr << 1) 289 uint8_t addr_byte = (addr << 1)
295 | (cmdlen == 0 && I2C_OP_READ_P(op) ? 1 : 0); 290 | (cmdlen == 0 && I2C_OP_READ_P(op) ? 1 : 0);
296 xli2c_write_data_byte(sc, addr_byte); 291 xli2c_write_data_byte(sc, addr_byte);
297 292
298 /* 293 /*
299 * Generate start (or restart) condition 294 * Generate start (or restart) condition
300 */ 295 */
301 command = RMIXLP_I2C_COMMAND_WR | RMIXLP_I2C_COMMAND_STA; 296 command = RMIXLP_I2C_COMMAND_WR | RMIXLP_I2C_COMMAND_STA;
302 if (cmdlen == 0 && datalen == 0 && I2C_OP_WRITE_P(op)) { 297 if (cmdlen == 0 && datalen == 0 && I2C_OP_WRITE_P(op)) {
303 /* 298 /*
304 * This would allows a probe of i2c without sending data. 299 * This would allows a probe of i2c without sending data.
305 * You just get back a rxack if the device exists. 300 * You just get back a rxack if the device exists.
306 */ 301 */
307 command |= RMIXLP_I2C_COMMAND_STO; 302 command |= RMIXLP_I2C_COMMAND_STO;
308 } 303 }
309 error = xli2c_wait_for_command(sc, command); 304 error = xli2c_wait_for_command(sc, command);
310 if (error) { 305 if (error) {
311 DPRINTF("%s: error sending address: %d\n", __func__, error); 306 DPRINTF("%s: error sending address: %d\n", __func__, error);
312 if (error == EIO) 307 if (error == EIO)
313 error = ENXIO; 308 error = ENXIO;
314 goto out; 309 goto out;
315 } 310 }
316 311
317 status = xli2c_read_status(sc); 312 status = xli2c_read_status(sc);
318 if (status & RMIXLP_I2C_STATUS_AL) { 313 if (status & RMIXLP_I2C_STATUS_AL) {
319 DPRINTF("%s: lost bus: status=%#x\n", __func__, status); 314 DPRINTF("%s: lost bus: status=%#x\n", __func__, status);
320 315
321 /* 316 /*
322 * Generate start (or restart) condition (e.g. try again). 317 * Generate start (or restart) condition (e.g. try again).
323 */ 318 */
324 error = xli2c_wait_for_command(sc, command); 319 error = xli2c_wait_for_command(sc, command);
325 if (error) { 320 if (error) {
326 DPRINTF("%s: error re-sending address: %d\n", 321 DPRINTF("%s: error re-sending address: %d\n",
327 __func__, error); 322 __func__, error);
328 if (error == EIO) 323 if (error == EIO)
329 error = ENXIO; 324 error = ENXIO;
330 goto out; 325 goto out;
331 } 326 }
332 327
333 status = xli2c_read_status(sc); 328 status = xli2c_read_status(sc);
334 if (status & RMIXLP_I2C_STATUS_AL) { 329 if (status & RMIXLP_I2C_STATUS_AL) {
335 error = EBUSY; 330 error = EBUSY;
336 goto out; 331 goto out;
337 } 332 }
338 DPRINTF("%s: reacquired bus (status=%#x ocmmand=%#x)\n", 333 DPRINTF("%s: reacquired bus (status=%#x ocmmand=%#x)\n",
339 __func__, status, command); 334 __func__, status, command);
340 } 335 }
341 336
342 if (cmdlen > 0) { 337 if (cmdlen > 0) {
343 const uint8_t *cmdptr = cmdbuf; 338 const uint8_t *cmdptr = cmdbuf;
344 command = RMIXLP_I2C_COMMAND_WR; 339 command = RMIXLP_I2C_COMMAND_WR;
345 340
346 for (size_t i = 0; i < cmdlen; i++) { 341 for (size_t i = 0; i < cmdlen; i++) {
347 xli2c_write_data_byte(sc, *cmdptr++); 342 xli2c_write_data_byte(sc, *cmdptr++);
348 343
349 /* 344 /*
350 * If this is the last byte we are sending and we 345 * If this is the last byte we are sending and we
351 * are supposed to send a STOP, add the stop bit now. 346 * are supposed to send a STOP, add the stop bit now.
352 */ 347 */
353 if (i + 1 == cmdlen + datalen 348 if (i + 1 == cmdlen + datalen
354 && I2C_OP_WRITE_P(op) && I2C_OP_STOP_P(op)) 349 && I2C_OP_WRITE_P(op) && I2C_OP_STOP_P(op))
355 command |= RMIXLP_I2C_COMMAND_STO; 350 command |= RMIXLP_I2C_COMMAND_STO;
356 351
357 error = xli2c_wait_for_command(sc, command); 352 error = xli2c_wait_for_command(sc, command);
358 if (error) { 353 if (error) {
359 DPRINTF("%s: error sending cmd byte %zu: %d\n", 354 DPRINTF("%s: error sending cmd byte %zu: %d\n",
360 __func__, i, error); 355 __func__, i, error);
361 goto out; 356 goto out;
362 } 357 }
363 } 358 }
364 359
365 if (I2C_OP_READ_P(op)) { 360 if (I2C_OP_READ_P(op)) {
366 /* send target address and read transfer direction */ 361 /* send target address and read transfer direction */
367 addr_byte |= 1; 362 addr_byte |= 1;
368 xli2c_write_data_byte(sc, addr_byte); 363 xli2c_write_data_byte(sc, addr_byte);
369 364
370 /* 365 /*
371 * Restart for the read direction. 366 * Restart for the read direction.
372 */ 367 */
373 KASSERT(command == RMIXLP_I2C_COMMAND_WR); 368 KASSERT(command == RMIXLP_I2C_COMMAND_WR);
374 command |= RMIXLP_I2C_COMMAND_STA; 369 command |= RMIXLP_I2C_COMMAND_STA;
375 error = xli2c_wait_for_command(sc, command); 370 error = xli2c_wait_for_command(sc, command);
376 if (error) { 371 if (error) {
377 if (error == EIO) 372 if (error == EIO)
378 error = ENXIO; 373 error = ENXIO;
379 goto out; 374 goto out;
380 } 375 }
381 } 376 }
382 } 377 }
383 378
384 if (I2C_OP_READ_P(op)) { 379 if (I2C_OP_READ_P(op)) {
385 KASSERT(command & RMIXLP_I2C_COMMAND_WR); 380 KASSERT(command & RMIXLP_I2C_COMMAND_WR);
386 KASSERT(command & RMIXLP_I2C_COMMAND_STA); 381 KASSERT(command & RMIXLP_I2C_COMMAND_STA);
387 KASSERT((command & RMIXLP_I2C_COMMAND_ACK) == 0); 382 KASSERT((command & RMIXLP_I2C_COMMAND_ACK) == 0);
388 uint8_t *dataptr = databuf; 383 uint8_t *dataptr = databuf;
389 384
390 command = RMIXLP_I2C_COMMAND_RD; 385 command = RMIXLP_I2C_COMMAND_RD;
391 for (size_t i = 0; i < datalen; i++) { 386 for (size_t i = 0; i < datalen; i++) {
392 /* 387 /*
393 * If a master receiver wants to terminate a data 388 * If a master receiver wants to terminate a data
394 * transfer, it must inform the slave transmitter by 389 * transfer, it must inform the slave transmitter by
395 * not acknowledging the last byte of data. 390 * not acknowledging the last byte of data.
396 */ 391 */
397 if (i == datalen - 1) { 392 if (i == datalen - 1) {
398 command |= RMIXLP_I2C_COMMAND_ACK; 393 command |= RMIXLP_I2C_COMMAND_ACK;
399 if (I2C_OP_STOP_P(op)) 394 if (I2C_OP_STOP_P(op))
400 command |= RMIXLP_I2C_COMMAND_STO; 395 command |= RMIXLP_I2C_COMMAND_STO;
401 } 396 }
402 error = xli2c_wait_for_command(sc, command); 397 error = xli2c_wait_for_command(sc, command);
403 if (error) { 398 if (error) {
404 DPRINTF("%s: error reading byte %zu: %d\n", 399 DPRINTF("%s: error reading byte %zu: %d\n",
405 __func__, i, error); 400 __func__, i, error);
406 goto out; 401 goto out;
407 } 402 }
408 *dataptr++ = xli2c_read_data_byte(sc); 403 *dataptr++ = xli2c_read_data_byte(sc);
409 } 404 }
410 if (datalen == 0) { 405 if (datalen == 0) {
411 command |= RMIXLP_I2C_COMMAND_ACK; 406 command |= RMIXLP_I2C_COMMAND_ACK;
412 if (I2C_OP_STOP_P(op)) 407 if (I2C_OP_STOP_P(op))
413 command |= RMIXLP_I2C_COMMAND_STO; 408 command |= RMIXLP_I2C_COMMAND_STO;
414 409
415 error = xli2c_wait_for_command(sc, command); 410 error = xli2c_wait_for_command(sc, command);
416 if (error) { 411 if (error) {
417 DPRINTF("%s: error reading dummy last byte:" 412 DPRINTF("%s: error reading dummy last byte:"
418 "%d\n", __func__, error); 413 "%d\n", __func__, error);
419 goto out; 414 goto out;
420 } 415 }
421 (void) xli2c_read_data_byte(sc); /* dummy read */ 416 (void) xli2c_read_data_byte(sc); /* dummy read */
422 } 417 }
423 } else if (datalen > 0) { 418 } else if (datalen > 0) {
424 const uint8_t *dataptr = databuf; 419 const uint8_t *dataptr = databuf;
425 command = RMIXLP_I2C_COMMAND_WR; 420 command = RMIXLP_I2C_COMMAND_WR;
426 for (size_t i = 0; i < datalen; i++) { 421 for (size_t i = 0; i < datalen; i++) {
427 xli2c_write_data_byte(sc, *dataptr++); 422 xli2c_write_data_byte(sc, *dataptr++);
428 if (i == datalen - 1) 423 if (i == datalen - 1)
429 error = xli2c_wait_for_command(sc, command); 424 error = xli2c_wait_for_command(sc, command);
430 if (error) { 425 if (error) {
431 DPRINTF("%s: error sending data byte %zu:" 426 DPRINTF("%s: error sending data byte %zu:"
432 " %d\n", __func__, i, error); 427 " %d\n", __func__, i, error);
433 goto out; 428 goto out;
434 } 429 }
435 } 430 }
436 } 431 }
437 432
438 out: 433 out:
439 /* 434 /*
440 * If we encountered an error condition or caller wants a STOP, 435 * If we encountered an error condition or caller wants a STOP,
441 * send a STOP. 436 * send a STOP.
442 */ 437 */
443 if (error 438 if (error
444 || (command & RMIXLP_I2C_COMMAND_ACK) 439 || (command & RMIXLP_I2C_COMMAND_ACK)
445 || ((command & RMIXLP_I2C_COMMAND_STA) && I2C_OP_STOP_P(op))) { 440 || ((command & RMIXLP_I2C_COMMAND_STA) && I2C_OP_STOP_P(op))) {
446 command = RMIXLP_I2C_COMMAND_STO; 441 command = RMIXLP_I2C_COMMAND_STO;
447 xli2c_write_command(sc, command); 442 xli2c_write_command(sc, command);
448 DPRINTF("%s: stopping\n", __func__); 443 DPRINTF("%s: stopping\n", __func__);
449 } 444 }
450 445
451 DPRINTF("%s: exit status=%#x command=%#x: %d\n", __func__, 446 DPRINTF("%s: exit status=%#x command=%#x: %d\n", __func__,
452 xli2c_read_status(sc), command, error); 447 xli2c_read_status(sc), command, error);
453 448
454 return error; 449 return error;
455} 450}