fire_i2c.c revision 1.5 1 1.5 jdc /* $NetBSD: fire_i2c.c,v 1.5 2026/09/25 07:16:27 jdc Exp $ */
2 1.1 jdc
3 1.1 jdc /*-
4 1.1 jdc * Copyright (c) 2026 The NetBSD Foundation, Inc.
5 1.1 jdc * All rights reserved.
6 1.1 jdc *
7 1.1 jdc * This code is derived from software contributed to The NetBSD Foundation
8 1.1 jdc * by Julian Coleman.
9 1.1 jdc *
10 1.1 jdc * Redistribution and use in source and binary forms, with or without
11 1.1 jdc * modification, are permitted provided that the following conditions
12 1.1 jdc * are met:
13 1.1 jdc * 1. Redistributions of source code must retain the above copyright
14 1.1 jdc * notice, this list of conditions and the following disclaimer.
15 1.1 jdc * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jdc * notice, this list of conditions and the following disclaimer in the
17 1.1 jdc * documentation and/or other materials provided with the distribution.
18 1.1 jdc *
19 1.1 jdc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jdc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jdc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jdc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jdc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jdc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jdc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jdc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jdc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jdc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jdc * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jdc */
31 1.1 jdc
32 1.1 jdc #include <sys/cdefs.h>
33 1.5 jdc __KERNEL_RCSID(0, "$NetBSD: fire_i2c.c,v 1.5 2026/09/25 07:16:27 jdc Exp $");
34 1.1 jdc
35 1.1 jdc #include <sys/param.h>
36 1.1 jdc #include <sys/condvar.h>
37 1.1 jdc #include <sys/device.h>
38 1.1 jdc #include <sys/intr.h>
39 1.5 jdc #include <sys/kernel.h>
40 1.1 jdc #include <sys/mutex.h>
41 1.1 jdc
42 1.1 jdc #include <machine/autoconf.h>
43 1.1 jdc #include <machine/openfirm.h>
44 1.1 jdc
45 1.5 jdc #include <dev/pci/pcivar.h>
46 1.5 jdc
47 1.1 jdc #include <dev/i2c/i2cvar.h>
48 1.5 jdc #include <sparc64/dev/fire_i2creg.h>
49 1.5 jdc #include <sparc64/dev/iommureg.h>
50 1.5 jdc #include <sparc64/dev/iommuvar.h>
51 1.5 jdc #include <sparc64/dev/pyrovar.h>
52 1.5 jdc
53 1.5 jdc #include "ioconf.h"
54 1.1 jdc
55 1.1 jdc #define FIREI2C_DEBUG 0
56 1.1 jdc #if FIREI2C_DEBUG > 0
57 1.5 jdc int dlvl = 1; /* Set to 2 for verbose i2c ops output */
58 1.5 jdc #define DPRINTF(n) if (dlvl >= n) printf
59 1.1 jdc #else
60 1.5 jdc #define DPRINTF(n) if (0) printf
61 1.1 jdc #endif
62 1.1 jdc
63 1.5 jdc #define FIREI2C_SCL_FREQ 100000 /* Target i2c clock frequency */
64 1.5 jdc #define FIREI2C_OWN_ADDR 0x08 /* Our i2c slave address */
65 1.1 jdc
66 1.5 jdc /* i2c clocks to match possible system clock frequencies (1/1, 1/2, 1/32) */
67 1.1 jdc #define FIREI2C_CLK_FULL 0
68 1.1 jdc #define FIREI2C_CLK_HALF 1
69 1.1 jdc #define FIREI2C_CLK_TT 2
70 1.1 jdc #define FIREI2C_CLK_LEN 3
71 1.1 jdc
72 1.5 jdc /* i2c operations */
73 1.5 jdc #define FIREI2C_OP_READ 0x01
74 1.5 jdc #define FIREI2C_OP_WRITE 0x02
75 1.5 jdc #define FIREI2C_OP_WR_RD 0x04
76 1.5 jdc
77 1.5 jdc /* i2c stages */
78 1.5 jdc #define FIREI2C_STAGE_IDLE 0x00
79 1.5 jdc #define FIREI2C_STAGE_START 0x01
80 1.5 jdc #define FIREI2C_STAGE_WR_ADDR 0x02
81 1.5 jdc #define FIREI2C_STAGE_RE_ADDR 0x04
82 1.5 jdc #define FIREI2C_STAGE_WRITE 0x08
83 1.5 jdc #define FIREI2C_STAGE_REPSTART 0x10
84 1.5 jdc #define FIREI2C_STAGE_READ 0x20
85 1.5 jdc #define FIREI2C_STAGE_STOP 0x40
86 1.5 jdc
87 1.5 jdc /* mainbus intr map/mask are only used for i2c interrupts, so put them here. */
88 1.5 jdc struct mainbus_interrupt_map {
89 1.5 jdc uint64_t paddr; /* phys addr mask */
90 1.5 jdc uint32_t intr; /* interrupt mask */
91 1.5 jdc int32_t cnode; /* child node */
92 1.5 jdc uint32_t cintr; /* child interrupt */
93 1.5 jdc } __packed;
94 1.5 jdc
95 1.5 jdc struct mainbus_interrupt_map_mask {
96 1.5 jdc uint64_t paddr; /* phys addr mask */
97 1.5 jdc uint32_t intr; /* interrupt */
98 1.5 jdc } __packed;
99 1.5 jdc
100 1.1 jdc struct firei2c_softc {
101 1.1 jdc device_t sc_dev;
102 1.1 jdc bus_space_tag_t sc_bustag;
103 1.1 jdc bus_space_handle_t sc_regh;
104 1.1 jdc int sc_node;
105 1.1 jdc void *sc_inth;
106 1.5 jdc
107 1.5 jdc uint8_t sc_i2c_clks[FIREI2C_CLK_LEN]; /* Clocks for sys bus speeds */
108 1.5 jdc
109 1.1 jdc struct i2c_controller sc_i2c;
110 1.5 jdc
111 1.5 jdc kmutex_t sc_mutex; /* Interrupt mutex ... */
112 1.5 jdc kcondvar_t sc_cv; /* ... and condvar */
113 1.5 jdc
114 1.5 jdc int sc_op; /* Operation to run */
115 1.5 jdc int sc_stage; /* Exec stage */
116 1.5 jdc i2c_addr_t sc_target; /* Saved exec args */
117 1.5 jdc const u_int8_t *sc_cmdbuf; /* ... */
118 1.5 jdc size_t sc_cmdlen; /* ... */
119 1.5 jdc u_int8_t *sc_buf; /* ... */
120 1.5 jdc size_t sc_buflen; /* ... */
121 1.5 jdc int sc_i; /* How far through buf */
122 1.5 jdc int sc_err; /* Error during transaction */
123 1.5 jdc
124 1.1 jdc };
125 1.1 jdc
126 1.1 jdc static int firei2c_match(device_t, cfdata_t, void *);
127 1.1 jdc static void firei2c_attach(device_t, device_t, void *);
128 1.5 jdc static void firei2c_intr_establish(struct firei2c_softc *,
129 1.5 jdc struct mainbus_attach_args *);
130 1.1 jdc static uint8_t firei2c_clock(int);
131 1.1 jdc static int firei2c_stop(struct firei2c_softc *);
132 1.1 jdc static int firei2c_wait(struct firei2c_softc *, int);
133 1.1 jdc int firei2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
134 1.1 jdc size_t, void *, size_t, int);
135 1.1 jdc static int firei2c_write(struct firei2c_softc *, const uint8_t *, size_t,
136 1.5 jdc uint8_t *, size_t, int);
137 1.5 jdc static int firei2c_read(struct firei2c_softc *, uint8_t *, size_t, int);
138 1.1 jdc int firei2c_intr(void *);
139 1.1 jdc static uint8_t firei2c_reg_read(struct firei2c_softc *, bus_size_t);
140 1.1 jdc static void firei2c_reg_write(struct firei2c_softc *, bus_size_t, uint8_t);
141 1.1 jdc
142 1.1 jdc CFATTACH_DECL_NEW(firei2c, sizeof(struct firei2c_softc),
143 1.1 jdc firei2c_match, firei2c_attach, NULL, NULL);
144 1.1 jdc
145 1.1 jdc static int
146 1.1 jdc firei2c_match(device_t parent, cfdata_t cf, void *aux)
147 1.1 jdc {
148 1.1 jdc struct mainbus_attach_args *ma = aux;
149 1.1 jdc char *compat;
150 1.1 jdc
151 1.1 jdc if (strcmp(ma->ma_name, "i2c"))
152 1.1 jdc return 0;
153 1.1 jdc
154 1.1 jdc compat = prom_getpropstring(ma->ma_node, "compatible");
155 1.1 jdc if (!strcmp(compat, "fire-i2c"))
156 1.1 jdc return 1;
157 1.1 jdc
158 1.1 jdc return 0;
159 1.1 jdc }
160 1.1 jdc
161 1.1 jdc static void
162 1.1 jdc firei2c_attach(device_t parent, device_t self, void *aux)
163 1.1 jdc {
164 1.1 jdc struct firei2c_softc *sc = device_private(self);
165 1.1 jdc struct mainbus_attach_args *ma = aux;
166 1.1 jdc int sysclk;
167 1.1 jdc
168 1.1 jdc sc->sc_bustag = ma->ma_bustag;
169 1.1 jdc sc->sc_node = ma->ma_node;
170 1.1 jdc sc->sc_dev = self;
171 1.1 jdc
172 1.1 jdc if (ma->ma_nreg != 1) {
173 1.1 jdc aprint_error(": register count error (%d != 1)\n",
174 1.1 jdc ma->ma_nreg);
175 1.1 jdc return;
176 1.1 jdc }
177 1.1 jdc if (ma->ma_reg[0].ur_len < FIREI2C_SRST) {
178 1.4 nakayama aprint_error(": register length error (%" PRId64 " < %d\n",
179 1.4 nakayama ma->ma_reg[0].ur_len, FIREI2C_SRST);
180 1.1 jdc return;
181 1.1 jdc }
182 1.1 jdc
183 1.1 jdc if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr,
184 1.1 jdc ma->ma_reg[0].ur_len, 0, &sc->sc_regh)) {
185 1.1 jdc aprint_error(": failed to map registers\n");
186 1.1 jdc return;
187 1.1 jdc }
188 1.1 jdc
189 1.1 jdc aprint_normal(": addr %" PRIx64 ": Fire/MI2C i2c controller\n",
190 1.1 jdc ma->ma_reg[0].ur_paddr);
191 1.1 jdc
192 1.5 jdc firei2c_intr_establish(sc, ma);
193 1.5 jdc
194 1.5 jdc /* Calculate clock, software reset, set our address */
195 1.1 jdc sysclk = prom_getpropint(findroot(), "clock-frequency", 0);
196 1.1 jdc sc->sc_i2c_clks[FIREI2C_CLK_FULL] = firei2c_clock(sysclk);
197 1.1 jdc sc->sc_i2c_clks[FIREI2C_CLK_HALF] = firei2c_clock(sysclk / 2);
198 1.1 jdc sc->sc_i2c_clks[FIREI2C_CLK_TT] = firei2c_clock(sysclk / 32);
199 1.1 jdc firei2c_reg_write(sc, FIREI2C_SRST, FIREI2C_SRST_RST);
200 1.1 jdc delay(1000);
201 1.1 jdc firei2c_reg_write(sc, FIREI2C_CCR, sc->sc_i2c_clks[FIREI2C_CLK_FULL]);
202 1.1 jdc firei2c_reg_write(sc, FIREI2C_ADDR,
203 1.1 jdc FIREI2C_OWN_ADDR << FIREI2C_ADDR_SHIFT);
204 1.1 jdc
205 1.1 jdc /* i2c setup */
206 1.1 jdc iic_tag_init(&sc->sc_i2c);
207 1.1 jdc sc->sc_i2c.ic_cookie = sc;
208 1.1 jdc sc->sc_i2c.ic_exec = firei2c_exec;
209 1.1 jdc
210 1.1 jdc /* Synchronisation between exec and intr */
211 1.1 jdc mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
212 1.1 jdc cv_init(&sc->sc_cv, "firei2c");
213 1.5 jdc sc->sc_stage = FIREI2C_STAGE_IDLE;
214 1.1 jdc
215 1.1 jdc iicbus_attach(sc->sc_dev, &sc->sc_i2c);
216 1.1 jdc return;
217 1.1 jdc }
218 1.1 jdc
219 1.1 jdc /*
220 1.5 jdc * Use the mainbus (root) interrupt map/mask to find our interrupt number
221 1.5 jdc * (ino 60 or 61) and pyro leaf.
222 1.5 jdc * Both i2c interrupts must go to the same pyro leaf, but we assume that
223 1.5 jdc * OFW has set up the ino and the leaf mapping for us.
224 1.5 jdc */
225 1.5 jdc #define IMASK_LEN 3
226 1.5 jdc #define IMAP_LEN 10
227 1.5 jdc static void
228 1.5 jdc firei2c_intr_establish(struct firei2c_softc *sc,
229 1.5 jdc struct mainbus_attach_args *ma)
230 1.5 jdc {
231 1.5 jdc struct mainbus_interrupt_map *mb_imap;
232 1.5 jdc struct mainbus_interrupt_map_mask *mb_imask;
233 1.5 jdc struct pyro_softc *psc = NULL;
234 1.5 jdc int64_t paddr;
235 1.5 jdc u_int intr;
236 1.5 jdc int ihandle, root, size, i;
237 1.5 jdc
238 1.5 jdc sc->sc_inth = NULL; /* Default */
239 1.5 jdc ihandle = 0;
240 1.5 jdc
241 1.5 jdc /* Find our mapped interrupt number */
242 1.5 jdc root = findroot();
243 1.5 jdc mb_imask = NULL;
244 1.5 jdc if (prom_getprop(root, "interrupt-map-mask",
245 1.5 jdc sizeof(int32_t), &size, (void **) &mb_imask) ||
246 1.5 jdc size != IMASK_LEN) {
247 1.5 jdc aprint_error(": no interrupt-map-mask\n");
248 1.5 jdc return;
249 1.5 jdc }
250 1.5 jdc
251 1.5 jdc mb_imap = NULL;
252 1.5 jdc if (prom_getprop(root, "interrupt-map",
253 1.5 jdc sizeof(int32_t), &size, (void **) &mb_imap) ||
254 1.5 jdc size != IMAP_LEN) {
255 1.5 jdc aprint_error(": no interrupt-map\n");
256 1.5 jdc return;
257 1.5 jdc }
258 1.5 jdc
259 1.5 jdc intr = ma->ma_interrupts[0] && mb_imask->intr;
260 1.5 jdc DPRINTF(1)("%s: intr %x masked to %x\n",
261 1.5 jdc device_xname(sc->sc_dev), ma->ma_interrupts[0], intr);
262 1.5 jdc paddr = ma->ma_reg[0].ur_paddr & mb_imask->paddr;
263 1.5 jdc DPRINTF(1)("%s: reg 0x%" PRIx64 " masked to 0x%" PRIx64 "\n",
264 1.5 jdc device_xname(sc->sc_dev), ma->ma_reg[0].ur_paddr, paddr);
265 1.5 jdc for (i = 0; i < 2; i++) {
266 1.5 jdc DPRINTF(1)("%s: checking paddr 0x%" PRIx64 ", intr %x\n",
267 1.5 jdc device_xname(sc->sc_dev), mb_imap->paddr, mb_imap->intr);
268 1.5 jdc if (paddr == mb_imap->paddr && intr == mb_imap->intr) {
269 1.5 jdc ihandle = mb_imap->cintr;
270 1.5 jdc DPRINTF(1)("%s: found cintr %d, cnode 0x%x\n",
271 1.5 jdc device_xname(sc->sc_dev), ihandle, mb_imap->cnode);
272 1.5 jdc break;
273 1.5 jdc }
274 1.5 jdc mb_imap++;
275 1.5 jdc }
276 1.5 jdc if (ihandle == 0) {
277 1.5 jdc aprint_error(": failed to match interrupt\n");
278 1.5 jdc return;
279 1.5 jdc }
280 1.5 jdc
281 1.5 jdc /* Find the pyro leaf with the matching cnode ) */
282 1.5 jdc for (i = 0; i < pyro_cd.cd_ndevs; i++) {
283 1.5 jdc device_t dt = device_lookup(&pyro_cd, i);
284 1.5 jdc psc = device_private(dt);
285 1.5 jdc if (psc && psc->sc_node == mb_imap->cnode) {
286 1.5 jdc DPRINTF(1)("%s: matched pyro %d (0x%x)\n",
287 1.5 jdc device_xname(sc->sc_dev), i, psc->sc_node);
288 1.5 jdc ihandle |= psc->sc_ign;
289 1.5 jdc break;
290 1.5 jdc }
291 1.5 jdc }
292 1.5 jdc if (psc == NULL) {
293 1.5 jdc aprint_error(": failed to match pyro leaf\n");
294 1.5 jdc return;
295 1.5 jdc }
296 1.5 jdc
297 1.5 jdc sc->sc_inth = psc->intr_establish_sc(psc,
298 1.5 jdc ihandle, IPL_BIO, firei2c_intr, sc, NULL);
299 1.5 jdc
300 1.5 jdc if (sc->sc_inth != NULL) {
301 1.5 jdc aprint_normal_dev(sc->sc_dev,
302 1.5 jdc "interrupting at ivec %x on pyro%d\n", ihandle, i);
303 1.5 jdc }
304 1.5 jdc
305 1.5 jdc return;
306 1.5 jdc }
307 1.5 jdc
308 1.5 jdc /*
309 1.1 jdc * Sampling frequency: input clock divided by 2^N (N is bits 0:2)
310 1.1 jdc * SCL frequency: sampling frequency divided by (M + 1) * 10 (bits 3:6)
311 1.1 jdc * i2c SCL is max 100kHz, so find the closest frequency at or below that.
312 1.1 jdc *
313 1.1 jdc * If the system (JBus) clock frequency changes, we must change our clock.
314 1.1 jdc * If increasing: after the JBus change, if decreasing: before the change.
315 1.1 jdc * This is to avoid running the i2c clock faster than the specification.
316 1.1 jdc */
317 1.1 jdc static uint8_t
318 1.1 jdc firei2c_clock(int sysclk)
319 1.1 jdc {
320 1.1 jdc int p, f, best_p, best_f;
321 1.1 jdc uint32_t sample, scl;
322 1.1 jdc uint32_t min = FIREI2C_SCL_FREQ;
323 1.1 jdc uint8_t clkval;
324 1.1 jdc
325 1.1 jdc best_p = 0;
326 1.1 jdc best_f = 0;
327 1.1 jdc for (p = 0; p <= FIREI2C_CCR_POW2_MAX; p++) {
328 1.1 jdc if (p)
329 1.1 jdc sample = sysclk / (2 << (p - 1));
330 1.1 jdc else
331 1.1 jdc sample = sysclk;
332 1.1 jdc for (f = 0; f <= FIREI2C_CCR_FACT_MAX; f++) {
333 1.1 jdc scl = sample / ((f + 1) * 10);
334 1.1 jdc if (scl <= FIREI2C_SCL_FREQ) {
335 1.1 jdc if (FIREI2C_SCL_FREQ - scl < min) {
336 1.1 jdc best_p = p;
337 1.1 jdc best_f = f;
338 1.1 jdc min = FIREI2C_SCL_FREQ - scl;
339 1.1 jdc }
340 1.1 jdc break; /* Already at or below SCL_FREQ */
341 1.1 jdc }
342 1.1 jdc }
343 1.1 jdc if (!min) /* Exactly SCL_FREQ */
344 1.1 jdc break;
345 1.1 jdc }
346 1.1 jdc clkval = best_p + (best_f << FIREI2C_CCR_FACT_SHIFT);
347 1.1 jdc return clkval;
348 1.1 jdc }
349 1.1 jdc
350 1.1 jdc /* No interrupts for stop, so wait for idle */
351 1.1 jdc static int
352 1.1 jdc firei2c_stop(struct firei2c_softc *sc)
353 1.1 jdc {
354 1.1 jdc int i;
355 1.1 jdc uint8_t ctrl, val;
356 1.1 jdc
357 1.1 jdc ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_STP;
358 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
359 1.1 jdc for (i = 0; i < 500; i++) {
360 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
361 1.5 jdc if (val == FIREI2C_STAT_IDLE) {
362 1.5 jdc mutex_enter(&sc->sc_mutex);
363 1.5 jdc sc->sc_stage = FIREI2C_STAGE_IDLE;
364 1.5 jdc mutex_exit(&sc->sc_mutex);
365 1.1 jdc return 0;
366 1.5 jdc }
367 1.1 jdc delay(1000);
368 1.1 jdc }
369 1.1 jdc /* Clear the interrupt flag if we timed out */
370 1.1 jdc ctrl = FIREI2C_CTRL_ENAB;
371 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
372 1.5 jdc /* Set the stage to idle, even for timeout */
373 1.5 jdc mutex_enter(&sc->sc_mutex);
374 1.5 jdc sc->sc_stage = FIREI2C_STAGE_IDLE;
375 1.5 jdc mutex_exit(&sc->sc_mutex);
376 1.1 jdc return 1;
377 1.1 jdc }
378 1.1 jdc
379 1.1 jdc
380 1.1 jdc static int
381 1.1 jdc firei2c_wait(struct firei2c_softc *sc, int flags)
382 1.1 jdc {
383 1.1 jdc volatile uint8_t ctrl;
384 1.1 jdc int i;
385 1.1 jdc
386 1.5 jdc for (i = 0; i < 500; i++) {
387 1.5 jdc ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
388 1.5 jdc if (ctrl & FIREI2C_CTRL_IFLG)
389 1.5 jdc return 0;
390 1.5 jdc delay(1000);
391 1.1 jdc }
392 1.5 jdc return 1;
393 1.1 jdc }
394 1.1 jdc
395 1.1 jdc /*
396 1.1 jdc * Flow for a "simple" read/write:
397 1.1 jdc * 1. Send start
398 1.1 jdc * 2. Send addr + R or W
399 1.1 jdc * 3. Receive ACK
400 1.1 jdc * 4. (nothing)
401 1.1 jdc * 5. (nothing)
402 1.1 jdc * 6R. Receive data 6W. Send data
403 1.1 jdc * 7R. Send ACK or NAK 7W. Receive ACK or NAK
404 1.1 jdc * either receive more (6R) or either write more (6W) or
405 1.1 jdc * 8. Send stop
406 1.5 jdc *
407 1.1 jdc * Flow for read/write following a "register" write:
408 1.1 jdc * 1. Send start
409 1.1 jdc * 2. Send addr + W
410 1.1 jdc * 3. Receive ACK
411 1.1 jdc * 4. Send register
412 1.1 jdc * 5R. Send repeat start + addr + R 5W. (nothing to do)
413 1.1 jdc * 6R. Receive data 6W. Send data
414 1.1 jdc * 7R. Send ACK or NAK 7W. Receive ACK or NAK
415 1.1 jdc * either receive more (6R) or either write more (6W) or
416 1.1 jdc * 8. Send stop
417 1.1 jdc *
418 1.1 jdc * After each step, we receive an interrupt notifying us of the result.
419 1.5 jdc * We clear the interrupt flag, check the status, and set up the next step.
420 1.5 jdc * If we're polling, we check the flag in a loop instead.
421 1.1 jdc */
422 1.1 jdc int
423 1.1 jdc firei2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, const void *cmd,
424 1.1 jdc size_t cmdlen, void *vbuf, size_t buflen, int flags)
425 1.1 jdc {
426 1.1 jdc struct firei2c_softc *sc = arg;
427 1.5 jdc const uint8_t *cmdbuf = cmd;
428 1.1 jdc uint8_t *buf = vbuf;
429 1.1 jdc uint8_t ctrl, val, ack, nack;
430 1.5 jdc unsigned deadline, rem;
431 1.1 jdc int err;
432 1.1 jdc
433 1.5 jdc DPRINTF(1)("%s: exec op: %d addr: 0x%x "
434 1.5 jdc "cmdlen: %d buflen: %d flags 0x%x, intr %s, poll %s\n",
435 1.1 jdc device_xname(sc->sc_dev), op, addr,
436 1.5 jdc (int) cmdlen, (int) buflen, flags,
437 1.5 jdc sc->sc_inth == NULL ? "no" : "yes",
438 1.5 jdc flags & I2C_F_POLL ? "yes" : "no");
439 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
440 1.1 jdc if (val != FIREI2C_STAT_IDLE) {
441 1.1 jdc /* Try sending stop */
442 1.5 jdc DPRINTF(1)("%s: not idle, sending stop\n",
443 1.1 jdc device_xname(sc->sc_dev));
444 1.1 jdc err = firei2c_stop(sc);
445 1.1 jdc if (err) {
446 1.1 jdc printf("%s: not idle (0x%02x)\n",
447 1.1 jdc device_xname(sc->sc_dev), val);
448 1.1 jdc return 1;
449 1.1 jdc }
450 1.1 jdc }
451 1.1 jdc
452 1.5 jdc /* Control defaults - bus enabled, interrupts enabled */
453 1.5 jdc ctrl = FIREI2C_CTRL_ENAB;
454 1.5 jdc if (sc->sc_inth != NULL && !(flags & I2C_F_POLL)) {
455 1.5 jdc ctrl |= FIREI2C_CTRL_IEN;
456 1.5 jdc sc->sc_target = addr;
457 1.5 jdc sc->sc_cmdbuf = cmdbuf;
458 1.5 jdc sc->sc_cmdlen = cmdlen;
459 1.5 jdc sc->sc_buf = buf;
460 1.5 jdc sc->sc_buflen = buflen;
461 1.5 jdc sc->sc_i = 0;
462 1.5 jdc sc->sc_err = 0;
463 1.5 jdc if (I2C_OP_READ_P(op))
464 1.5 jdc if (cmdlen > 0)
465 1.5 jdc sc->sc_op = FIREI2C_OP_WR_RD;
466 1.5 jdc else
467 1.5 jdc sc->sc_op = FIREI2C_OP_READ;
468 1.5 jdc else
469 1.5 jdc sc->sc_op = FIREI2C_OP_WRITE;
470 1.5 jdc mutex_enter(&sc->sc_mutex);
471 1.5 jdc sc->sc_stage = FIREI2C_STAGE_START;
472 1.5 jdc mutex_exit(&sc->sc_mutex);
473 1.5 jdc }
474 1.5 jdc
475 1.1 jdc /* Send start */
476 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl | FIREI2C_CTRL_STA);
477 1.5 jdc
478 1.5 jdc /* Interrupt-driven */
479 1.5 jdc if (sc->sc_inth != NULL && !(flags & I2C_F_POLL)) {
480 1.5 jdc /* Wait for the transfer to complete (stop). */
481 1.5 jdc deadline = getticks() +
482 1.5 jdc /*timeout*/ hz / 10 + 10 * (cmdlen + buflen);
483 1.5 jdc mutex_enter(&sc->sc_mutex);
484 1.5 jdc while (sc->sc_stage != FIREI2C_STAGE_STOP) {
485 1.5 jdc rem = deadline - getticks();
486 1.5 jdc if (!rem || rem >= INT_MAX) {
487 1.5 jdc printf("%s: intr timeout\n",
488 1.5 jdc device_xname(sc->sc_dev));
489 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
490 1.5 jdc err = sc->sc_err | 1;
491 1.5 jdc break;
492 1.5 jdc }
493 1.5 jdc cv_timedwait(&sc->sc_cv, &sc->sc_mutex, rem);
494 1.5 jdc }
495 1.5 jdc mutex_exit(&sc->sc_mutex);
496 1.5 jdc err = sc->sc_err;
497 1.5 jdc goto stop;
498 1.5 jdc }
499 1.5 jdc
500 1.5 jdc /*
501 1.5 jdc * If we are writing, write addr, cmd, buf.
502 1.5 jdc * If we are reading, either:
503 1.5 jdc * write addr, cmd, repeat-start, then read addr to buf, or:
504 1.5 jdc * read addr to buf.
505 1.5 jdc * Send stop
506 1.5 jdc */
507 1.1 jdc err = firei2c_wait(sc, flags);
508 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
509 1.1 jdc if (err) {
510 1.1 jdc printf("%s: start timeout 0x%x\n",
511 1.1 jdc device_xname(sc->sc_dev), val);
512 1.1 jdc goto stop;
513 1.1 jdc }
514 1.1 jdc if (val != FIREI2C_STAT_STA) {
515 1.1 jdc printf("%s: start error 0x%x\n",
516 1.1 jdc device_xname(sc->sc_dev), val);
517 1.1 jdc err = 1;
518 1.1 jdc goto stop;
519 1.1 jdc }
520 1.1 jdc
521 1.5 jdc /* Address + r/w in data, then send ctrl */
522 1.5 jdc val = addr << FIREI2C_DATA_SHIFT;
523 1.1 jdc if (I2C_OP_WRITE_P(op) || cmdlen > 0) {
524 1.1 jdc ack = FIREI2C_STAT_AWR_ACK;
525 1.1 jdc nack = FIREI2C_STAT_AWR_NAK;
526 1.1 jdc } else {
527 1.1 jdc val |= 0x01;
528 1.1 jdc ack = FIREI2C_STAT_ARE_ACK;
529 1.1 jdc nack = FIREI2C_STAT_ARE_NAK;
530 1.1 jdc }
531 1.1 jdc firei2c_reg_write(sc, FIREI2C_DATA, val);
532 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
533 1.1 jdc err = firei2c_wait(sc, flags);
534 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
535 1.1 jdc if (err) {
536 1.1 jdc printf("%s: addr timeout 0x%x\n",
537 1.1 jdc device_xname(sc->sc_dev), val);
538 1.1 jdc goto stop;
539 1.1 jdc }
540 1.1 jdc if (val != ack) {
541 1.1 jdc if (val != nack) /* Don't print for NACK */
542 1.1 jdc printf("%s: addr error 0x%x\n",
543 1.1 jdc device_xname(sc->sc_dev), val);
544 1.1 jdc err = 1;
545 1.1 jdc goto stop;
546 1.1 jdc }
547 1.1 jdc
548 1.1 jdc err = 0;
549 1.1 jdc if (I2C_OP_READ_P(op)) {
550 1.1 jdc if (cmdlen > 0) {
551 1.1 jdc /* Write register */
552 1.1 jdc err = firei2c_write(sc, cmd, cmdlen,
553 1.5 jdc NULL, 0, flags);
554 1.1 jdc if (err)
555 1.1 jdc goto stop;
556 1.1 jdc
557 1.1 jdc /* Send repeat start */
558 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL,
559 1.5 jdc ctrl | FIREI2C_CTRL_STA);
560 1.1 jdc err = firei2c_wait(sc, flags);
561 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
562 1.1 jdc if (err) {
563 1.1 jdc printf("%s: repeat start timeout 0x%x\n",
564 1.1 jdc device_xname(sc->sc_dev), val);
565 1.1 jdc goto stop;
566 1.1 jdc }
567 1.1 jdc if (val != FIREI2C_STAT_REPSTA) {
568 1.1 jdc printf("%s: repeat start error 0x%x\n",
569 1.1 jdc device_xname(sc->sc_dev), val);
570 1.1 jdc err = 1;
571 1.1 jdc goto stop;
572 1.1 jdc }
573 1.1 jdc
574 1.5 jdc /* Address + r in data, then send ctrl */
575 1.5 jdc val = addr << FIREI2C_DATA_SHIFT;
576 1.1 jdc val |= 0x01;
577 1.1 jdc ack = FIREI2C_STAT_ARE_ACK;
578 1.1 jdc nack = FIREI2C_STAT_ARE_NAK;
579 1.1 jdc firei2c_reg_write(sc, FIREI2C_DATA, val);
580 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
581 1.1 jdc err = firei2c_wait(sc, flags);
582 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
583 1.1 jdc if (err) {
584 1.1 jdc printf("%s: addr timeout 0x%x\n",
585 1.1 jdc device_xname(sc->sc_dev), val);
586 1.1 jdc goto stop;
587 1.1 jdc }
588 1.1 jdc if (val != ack) {
589 1.1 jdc if (val != nack)
590 1.1 jdc printf("%s: addr error 0x%x\n",
591 1.1 jdc device_xname(sc->sc_dev), val);
592 1.1 jdc err = 1;
593 1.1 jdc goto stop;
594 1.1 jdc }
595 1.1 jdc }
596 1.1 jdc
597 1.1 jdc /* Read data */
598 1.5 jdc err = firei2c_read(sc, buf, buflen, flags);
599 1.1 jdc } else
600 1.1 jdc /* Write data or register + data */
601 1.5 jdc err = firei2c_write(sc, cmd, cmdlen, buf, buflen, flags);
602 1.1 jdc
603 1.1 jdc stop:
604 1.1 jdc err |= firei2c_stop(sc);
605 1.1 jdc
606 1.1 jdc return err;
607 1.1 jdc }
608 1.1 jdc
609 1.1 jdc static int
610 1.1 jdc firei2c_write(struct firei2c_softc *sc, const uint8_t *cmd, size_t cmdlen,
611 1.5 jdc uint8_t *buf, size_t buflen, int flags)
612 1.1 jdc {
613 1.5 jdc uint8_t ctrl, val;
614 1.1 jdc int i, err;
615 1.1 jdc
616 1.5 jdc DPRINTF(2)("%s: write %ld\n",
617 1.5 jdc device_xname(sc->sc_dev), cmdlen + buflen);
618 1.5 jdc ctrl = FIREI2C_CTRL_ENAB;
619 1.1 jdc for (i = 0; i < cmdlen + buflen; i++) {
620 1.5 jdc /* Bytes in data, then send ctrl */
621 1.1 jdc if (i < cmdlen)
622 1.1 jdc val = cmd[i];
623 1.1 jdc else
624 1.1 jdc val = buf[i - cmdlen];
625 1.1 jdc firei2c_reg_write(sc, FIREI2C_DATA, val);
626 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
627 1.1 jdc err = firei2c_wait(sc, flags);
628 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
629 1.1 jdc if (err) {
630 1.1 jdc printf("%s: write timeout 0x%x\n",
631 1.1 jdc device_xname(sc->sc_dev), val);
632 1.1 jdc return 1;
633 1.1 jdc }
634 1.1 jdc if (val != FIREI2C_STAT_DAT_ACK) {
635 1.1 jdc if (val != FIREI2C_STAT_DAT_NAK)
636 1.1 jdc printf("%s: write error 0x%x\n",
637 1.1 jdc device_xname(sc->sc_dev), val);
638 1.1 jdc return 1;
639 1.1 jdc }
640 1.1 jdc
641 1.1 jdc }
642 1.1 jdc return 0;
643 1.1 jdc }
644 1.1 jdc
645 1.1 jdc static int
646 1.5 jdc firei2c_read(struct firei2c_softc *sc, uint8_t *buf, size_t buflen, int flags)
647 1.1 jdc {
648 1.5 jdc uint8_t ctrl, val, ack;
649 1.1 jdc int i, err;
650 1.1 jdc
651 1.5 jdc DPRINTF(2)("%s: read %ld\n", device_xname(sc->sc_dev), buflen);
652 1.1 jdc for (i = 0; i < buflen; i++) {
653 1.1 jdc /* Send ACK on all but last byte */
654 1.1 jdc if (i < buflen - 1) {
655 1.5 jdc ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_AAK;
656 1.1 jdc ack = FIREI2C_STAT_MDAT_ACK;
657 1.1 jdc } else {
658 1.5 jdc ctrl = FIREI2C_CTRL_ENAB;
659 1.1 jdc ack = FIREI2C_STAT_MDAT_NAK;
660 1.1 jdc }
661 1.5 jdc /* Send ctrl, then bytes in data */
662 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
663 1.1 jdc err = firei2c_wait(sc, flags);
664 1.1 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
665 1.1 jdc if (err) {
666 1.1 jdc printf("%s: read timeout 0x%x\n",
667 1.1 jdc device_xname(sc->sc_dev), val);
668 1.1 jdc return 1;
669 1.1 jdc }
670 1.1 jdc if (val != ack) {
671 1.1 jdc printf("%s: read error 0x%x\n",
672 1.1 jdc device_xname(sc->sc_dev), val);
673 1.1 jdc return 1;
674 1.1 jdc }
675 1.1 jdc buf[i] = firei2c_reg_read(sc, FIREI2C_DATA);
676 1.1 jdc }
677 1.1 jdc return 0;
678 1.1 jdc }
679 1.1 jdc
680 1.5 jdc /*
681 1.5 jdc * When we receive an interrupt, check the status versus the step
682 1.5 jdc * and set up the next stage.
683 1.5 jdc * See the comments before firei2c_exec() for the list of steps.
684 1.5 jdc */
685 1.1 jdc int
686 1.1 jdc firei2c_intr(void *arg)
687 1.1 jdc {
688 1.1 jdc struct firei2c_softc *sc = arg;
689 1.5 jdc uint8_t ctrl, val;
690 1.1 jdc
691 1.1 jdc mutex_enter(&sc->sc_mutex);
692 1.1 jdc ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
693 1.1 jdc if (ctrl & FIREI2C_CTRL_IFLG) {
694 1.1 jdc /* Disable interrupts */
695 1.1 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl & ~FIREI2C_CTRL_IEN);
696 1.5 jdc }
697 1.5 jdc
698 1.5 jdc if (sc->sc_stage == FIREI2C_STAGE_IDLE) {
699 1.5 jdc DPRINTF(1)("%s: intr and idle\n", device_xname(sc->sc_dev));
700 1.5 jdc mutex_exit(&sc->sc_mutex);
701 1.5 jdc return 0;
702 1.5 jdc }
703 1.5 jdc
704 1.5 jdc ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_IEN;
705 1.5 jdc val = firei2c_reg_read(sc, FIREI2C_STAT);
706 1.5 jdc
707 1.5 jdc switch (sc->sc_stage) {
708 1.5 jdc case FIREI2C_STAGE_START:
709 1.5 jdc DPRINTF(2)("%s: intr start, op %x\n",
710 1.5 jdc device_xname(sc->sc_dev), sc->sc_op);
711 1.5 jdc if (val != FIREI2C_STAT_STA) {
712 1.5 jdc printf("%s: intr start error 0x%02x\n",
713 1.5 jdc device_xname(sc->sc_dev), val);
714 1.5 jdc sc->sc_err = 1;
715 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
716 1.5 jdc break;
717 1.5 jdc }
718 1.5 jdc
719 1.5 jdc /* Address + r/w in data, then send ctrl */
720 1.5 jdc val = sc->sc_target << FIREI2C_DATA_SHIFT;
721 1.5 jdc if (sc->sc_op == FIREI2C_OP_READ) {
722 1.5 jdc val |= 0x01;
723 1.5 jdc sc->sc_stage = FIREI2C_STAGE_RE_ADDR;
724 1.5 jdc } else
725 1.5 jdc sc->sc_stage = FIREI2C_STAGE_WR_ADDR;
726 1.5 jdc firei2c_reg_write(sc, FIREI2C_DATA, val);
727 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
728 1.5 jdc break;
729 1.5 jdc
730 1.5 jdc case FIREI2C_STAGE_WR_ADDR:
731 1.5 jdc DPRINTF(2)("%s: intr addr(w) 0x%02x = 0x%02x\n",
732 1.5 jdc device_xname(sc->sc_dev), sc->sc_target, val);
733 1.5 jdc if (val != FIREI2C_STAT_AWR_ACK) {
734 1.5 jdc if (val != FIREI2C_STAT_AWR_NAK)
735 1.5 jdc printf("%s: intr addr(w) error 0x%02x\n",
736 1.5 jdc device_xname(sc->sc_dev), val);
737 1.5 jdc sc->sc_err = 1;
738 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
739 1.5 jdc break;
740 1.5 jdc }
741 1.5 jdc
742 1.5 jdc sc->sc_stage = FIREI2C_STAGE_WRITE;
743 1.5 jdc val = FIREI2C_STAT_DAT_ACK; /* For write */
744 1.5 jdc /* Fallthrough */
745 1.5 jdc
746 1.5 jdc case FIREI2C_STAGE_WRITE:
747 1.5 jdc DPRINTF(2)("%s: intr write 0x%02x = 0x%02x\n",
748 1.5 jdc device_xname(sc->sc_dev), sc->sc_target, val);
749 1.5 jdc if (val != FIREI2C_STAT_DAT_ACK) {
750 1.5 jdc if (val != FIREI2C_STAT_DAT_NAK)
751 1.5 jdc printf("%s: intr write error 0x%02x\n",
752 1.5 jdc device_xname(sc->sc_dev), val);
753 1.5 jdc sc->sc_err = 1;
754 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
755 1.5 jdc break;
756 1.5 jdc }
757 1.5 jdc
758 1.5 jdc /* Start the write from cmd */
759 1.5 jdc if (sc->sc_i < sc->sc_cmdlen) {
760 1.5 jdc firei2c_reg_write(sc, FIREI2C_DATA,
761 1.5 jdc sc->sc_cmdbuf[sc->sc_i]);
762 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
763 1.5 jdc sc->sc_i++;
764 1.5 jdc break;
765 1.5 jdc }
766 1.5 jdc
767 1.5 jdc /* If a read OP, switch with repeat start after writing cmd */
768 1.5 jdc if (sc->sc_op == FIREI2C_OP_WR_RD) {
769 1.5 jdc sc->sc_i = 0;
770 1.5 jdc sc->sc_stage = FIREI2C_STAGE_REPSTART;
771 1.5 jdc ctrl |= FIREI2C_CTRL_STA;
772 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
773 1.5 jdc break;
774 1.5 jdc }
775 1.5 jdc
776 1.5 jdc /* If a write OP, continue the write, now from buf */
777 1.5 jdc if (sc->sc_i < sc->sc_cmdlen + sc->sc_buflen) {
778 1.5 jdc firei2c_reg_write(sc, FIREI2C_DATA,
779 1.5 jdc sc->sc_buf[sc->sc_i - sc->sc_cmdlen]);
780 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
781 1.5 jdc sc->sc_i++;
782 1.5 jdc } else {
783 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
784 1.5 jdc }
785 1.5 jdc break;
786 1.5 jdc
787 1.5 jdc case FIREI2C_STAGE_REPSTART:
788 1.5 jdc DPRINTF(2)("%s: intr repstart 0x%02x = 0x%02x\n",
789 1.5 jdc device_xname(sc->sc_dev), sc->sc_target, val);
790 1.5 jdc if (val != FIREI2C_STAT_REPSTA) {
791 1.5 jdc printf("%s: intr repstart error 0x%02x\n",
792 1.5 jdc device_xname(sc->sc_dev), val);
793 1.5 jdc sc->sc_err = 1;
794 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
795 1.5 jdc break;
796 1.5 jdc }
797 1.5 jdc
798 1.5 jdc /* Address + r in data, then send ctrl */
799 1.5 jdc val = (sc->sc_target << FIREI2C_DATA_SHIFT) | 0x01;
800 1.5 jdc sc->sc_stage = FIREI2C_STAGE_RE_ADDR;
801 1.5 jdc firei2c_reg_write(sc, FIREI2C_DATA, val);
802 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
803 1.5 jdc break;
804 1.5 jdc
805 1.5 jdc case FIREI2C_STAGE_RE_ADDR:
806 1.5 jdc DPRINTF(2)("%s: intr addr(r) 0x%02x = 0x%02x\n",
807 1.5 jdc device_xname(sc->sc_dev), sc->sc_target, val);
808 1.5 jdc if (val != FIREI2C_STAT_ARE_ACK) {
809 1.5 jdc if (val != FIREI2C_STAT_ARE_NAK)
810 1.5 jdc printf("%s: intr addr(r) error 0x%02x\n",
811 1.5 jdc device_xname(sc->sc_dev), val);
812 1.5 jdc sc->sc_err = 1;
813 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
814 1.5 jdc break;
815 1.5 jdc }
816 1.5 jdc
817 1.5 jdc sc->sc_stage = FIREI2C_STAGE_READ;
818 1.5 jdc val = FIREI2C_STAT_MDAT_NAK; /* For read */
819 1.5 jdc /* Fallthrough */
820 1.5 jdc
821 1.5 jdc case FIREI2C_STAGE_READ:
822 1.5 jdc DPRINTF(2)("%s: intr read 0x%02x = 0x%02x\n",
823 1.5 jdc device_xname(sc->sc_dev), sc->sc_target, val);
824 1.5 jdc if (sc->sc_i > 0 && sc->sc_i < sc->sc_buflen) {
825 1.5 jdc if (val != FIREI2C_STAT_MDAT_ACK) {
826 1.5 jdc printf("%s: intr read error 0x%02x\n",
827 1.5 jdc device_xname(sc->sc_dev), val);
828 1.5 jdc sc->sc_err = 1;
829 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
830 1.5 jdc break;
831 1.5 jdc }
832 1.5 jdc } else {
833 1.5 jdc if (val != FIREI2C_STAT_MDAT_NAK) {
834 1.5 jdc printf("%s: intr read error 0x%02x\n",
835 1.5 jdc device_xname(sc->sc_dev), val);
836 1.5 jdc sc->sc_err = 1;
837 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
838 1.5 jdc break;
839 1.5 jdc }
840 1.5 jdc }
841 1.5 jdc
842 1.5 jdc /* Data read is 1 cycle behind ctrl */
843 1.5 jdc if (sc->sc_i > 0 && sc->sc_i <= sc->sc_buflen) {
844 1.5 jdc sc->sc_buf[sc->sc_i - 1] =
845 1.5 jdc firei2c_reg_read(sc, FIREI2C_DATA);
846 1.5 jdc }
847 1.5 jdc
848 1.5 jdc if (sc->sc_i == sc->sc_buflen) {
849 1.5 jdc /* Last data was read */
850 1.5 jdc sc->sc_stage = FIREI2C_STAGE_STOP;
851 1.5 jdc } else {
852 1.5 jdc /* Send ACK on all but last byte */
853 1.5 jdc if (sc->sc_i < sc->sc_buflen - 1)
854 1.5 jdc ctrl |= FIREI2C_CTRL_AAK;
855 1.5 jdc firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
856 1.5 jdc sc->sc_i++;
857 1.5 jdc }
858 1.5 jdc break;
859 1.5 jdc }
860 1.5 jdc
861 1.5 jdc if (sc->sc_stage == FIREI2C_STAGE_STOP) {
862 1.5 jdc DPRINTF(2)("%s: intr stop (err=%d)\n",
863 1.5 jdc device_xname(sc->sc_dev), sc->sc_err);
864 1.1 jdc cv_signal(&sc->sc_cv);
865 1.1 jdc }
866 1.5 jdc
867 1.1 jdc mutex_exit(&sc->sc_mutex);
868 1.5 jdc
869 1.5 jdc return 1;
870 1.5 jdc
871 1.1 jdc }
872 1.1 jdc
873 1.1 jdc static uint8_t
874 1.1 jdc firei2c_reg_read(struct firei2c_softc *sc, bus_size_t reg)
875 1.1 jdc {
876 1.1 jdc uint32_t val;
877 1.1 jdc bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
878 1.1 jdc BUS_SPACE_BARRIER_READ);
879 1.1 jdc val = bus_space_read_8(sc->sc_bustag, sc->sc_regh, reg);
880 1.1 jdc return val & 0xff;
881 1.1 jdc }
882 1.1 jdc
883 1.1 jdc static void
884 1.1 jdc firei2c_reg_write(struct firei2c_softc *sc, bus_size_t reg, uint8_t val)
885 1.1 jdc {
886 1.1 jdc bus_space_write_8(sc->sc_bustag, sc->sc_regh, reg, val);
887 1.1 jdc bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
888 1.1 jdc BUS_SPACE_BARRIER_WRITE);
889 1.1 jdc }
890