bcm2835_bsc.c revision 1.14 1 1.14 thorpej /* $NetBSD: bcm2835_bsc.c,v 1.14 2019/12/22 23:24:56 thorpej Exp $ */
2 1.1 jakllsch
3 1.1 jakllsch /*
4 1.14 thorpej * Copyright (c) 2019 Jason R. Thorpe
5 1.1 jakllsch * Copyright (c) 2012 Jonathan A. Kollasch
6 1.1 jakllsch * All rights reserved.
7 1.1 jakllsch *
8 1.1 jakllsch * Redistribution and use in source and binary forms, with or without
9 1.1 jakllsch * modification, are permitted provided that the following conditions
10 1.1 jakllsch * are met:
11 1.1 jakllsch * 1. Redistributions of source code must retain the above copyright
12 1.1 jakllsch * notice, this list of conditions and the following disclaimer.
13 1.1 jakllsch * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 jakllsch * notice, this list of conditions and the following disclaimer in the
15 1.1 jakllsch * documentation and/or other materials provided with the distribution.
16 1.1 jakllsch *
17 1.1 jakllsch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 1.1 jakllsch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 1.1 jakllsch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 1.1 jakllsch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21 1.1 jakllsch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 1.1 jakllsch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 1.1 jakllsch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 1.1 jakllsch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 1.1 jakllsch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 1.1 jakllsch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 1.1 jakllsch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 jakllsch */
29 1.1 jakllsch
30 1.1 jakllsch #include <sys/cdefs.h>
31 1.14 thorpej __KERNEL_RCSID(0, "$NetBSD: bcm2835_bsc.c,v 1.14 2019/12/22 23:24:56 thorpej Exp $");
32 1.1 jakllsch
33 1.1 jakllsch #include <sys/param.h>
34 1.3 skrll #include <sys/bus.h>
35 1.1 jakllsch #include <sys/device.h>
36 1.8 skrll #include <sys/kernhist.h>
37 1.3 skrll #include <sys/intr.h>
38 1.3 skrll #include <sys/mutex.h>
39 1.1 jakllsch #include <sys/systm.h>
40 1.1 jakllsch
41 1.1 jakllsch #include <dev/i2c/i2cvar.h>
42 1.1 jakllsch
43 1.1 jakllsch #include <arm/broadcom/bcm2835reg.h>
44 1.1 jakllsch #include <arm/broadcom/bcm2835_bscreg.h>
45 1.1 jakllsch
46 1.8 skrll #include <dev/fdt/fdtvar.h>
47 1.1 jakllsch
48 1.14 thorpej typedef enum {
49 1.14 thorpej BSC_EXEC_STATE_IDLE = 0,
50 1.14 thorpej BSC_EXEC_STATE_SEND_ADDR = 1,
51 1.14 thorpej BSC_EXEC_STATE_SEND_CMD = 2,
52 1.14 thorpej BSC_EXEC_STATE_SEND_DATA = 3,
53 1.14 thorpej BSC_EXEC_STATE_RECV_DATA = 4,
54 1.14 thorpej BSC_EXEC_STATE_DONE = 5,
55 1.14 thorpej BSC_EXEC_STATE_ERROR = 6,
56 1.14 thorpej } bsc_exec_state_t;
57 1.14 thorpej
58 1.14 thorpej #define BSC_EXEC_STATE_SENDING(sc) \
59 1.14 thorpej ((sc)->sc_exec_state >= BSC_EXEC_STATE_SEND_ADDR && \
60 1.14 thorpej (sc)->sc_exec_state <= BSC_EXEC_STATE_SEND_DATA)
61 1.14 thorpej
62 1.14 thorpej #define BSC_EXEC_STATE_RECEIVING(sc) \
63 1.14 thorpej ((sc)->sc_exec_state == BSC_EXEC_STATE_RECV_DATA)
64 1.1 jakllsch
65 1.1 jakllsch struct bsciic_softc {
66 1.1 jakllsch device_t sc_dev;
67 1.1 jakllsch bus_space_tag_t sc_iot;
68 1.1 jakllsch bus_space_handle_t sc_ioh;
69 1.1 jakllsch struct i2c_controller sc_i2c;
70 1.1 jakllsch void *sc_inth;
71 1.8 skrll
72 1.8 skrll struct clk *sc_clk;
73 1.8 skrll u_int sc_frequency;
74 1.8 skrll u_int sc_clkrate;
75 1.14 thorpej
76 1.14 thorpej kmutex_t sc_intr_lock;
77 1.14 thorpej kcondvar_t sc_intr_wait;
78 1.14 thorpej
79 1.14 thorpej struct {
80 1.14 thorpej i2c_op_t op;
81 1.14 thorpej i2c_addr_t addr;
82 1.14 thorpej const void *cmdbuf;
83 1.14 thorpej size_t cmdlen;
84 1.14 thorpej void *databuf;
85 1.14 thorpej size_t datalen;
86 1.14 thorpej int flags;
87 1.14 thorpej } sc_exec;
88 1.14 thorpej
89 1.14 thorpej /*
90 1.14 thorpej * Everything below here protected by the i2c controller lock
91 1.14 thorpej * /and/ sc_intr_lock (if we're using interrupts).
92 1.14 thorpej */
93 1.14 thorpej
94 1.14 thorpej bsc_exec_state_t sc_exec_state;
95 1.14 thorpej
96 1.14 thorpej uint8_t *sc_buf;
97 1.14 thorpej size_t sc_bufpos;
98 1.14 thorpej size_t sc_buflen;
99 1.14 thorpej
100 1.14 thorpej uint32_t sc_c_bits;
101 1.14 thorpej bool sc_expecting_interrupt;
102 1.14 thorpej };
103 1.14 thorpej
104 1.14 thorpej static void bsciic_exec_func_idle(struct bsciic_softc * const);
105 1.14 thorpej static void bsciic_exec_func_send_addr(struct bsciic_softc * const);
106 1.14 thorpej static void bsciic_exec_func_send_cmd(struct bsciic_softc * const);
107 1.14 thorpej static void bsciic_exec_func_send_data(struct bsciic_softc * const);
108 1.14 thorpej static void bsciic_exec_func_recv_data(struct bsciic_softc * const);
109 1.14 thorpej static void bsciic_exec_func_done(struct bsciic_softc * const);
110 1.14 thorpej static void bsciic_exec_func_error(struct bsciic_softc * const);
111 1.14 thorpej
112 1.14 thorpej const struct {
113 1.14 thorpej void (*func)(struct bsciic_softc * const);
114 1.14 thorpej uint32_t c_bits;
115 1.14 thorpej uint32_t s_bits;
116 1.14 thorpej } bsciic_exec_state_data[] = {
117 1.14 thorpej [BSC_EXEC_STATE_IDLE] = {
118 1.14 thorpej .func = bsciic_exec_func_idle,
119 1.14 thorpej },
120 1.14 thorpej [BSC_EXEC_STATE_SEND_ADDR] = {
121 1.14 thorpej .func = bsciic_exec_func_send_addr,
122 1.14 thorpej },
123 1.14 thorpej [BSC_EXEC_STATE_SEND_CMD] = {
124 1.14 thorpej .func = bsciic_exec_func_send_cmd,
125 1.14 thorpej .c_bits = BSC_C_INTT,
126 1.14 thorpej .s_bits = BSC_S_TXW,
127 1.14 thorpej },
128 1.14 thorpej [BSC_EXEC_STATE_SEND_DATA] = {
129 1.14 thorpej .func = bsciic_exec_func_send_data,
130 1.14 thorpej .c_bits = BSC_C_INTT,
131 1.14 thorpej .s_bits = BSC_S_TXW,
132 1.14 thorpej },
133 1.14 thorpej [BSC_EXEC_STATE_RECV_DATA] = {
134 1.14 thorpej .func = bsciic_exec_func_recv_data,
135 1.14 thorpej .c_bits = BSC_C_READ | BSC_C_INTR,
136 1.14 thorpej .s_bits = BSC_S_RXR,
137 1.14 thorpej },
138 1.14 thorpej [BSC_EXEC_STATE_DONE] = {
139 1.14 thorpej .func = bsciic_exec_func_done,
140 1.14 thorpej },
141 1.14 thorpej [BSC_EXEC_STATE_ERROR] = {
142 1.14 thorpej .func = bsciic_exec_func_error,
143 1.14 thorpej },
144 1.1 jakllsch };
145 1.1 jakllsch
146 1.1 jakllsch static int bsciic_match(device_t, cfdata_t, void *);
147 1.1 jakllsch static void bsciic_attach(device_t, device_t, void *);
148 1.1 jakllsch
149 1.1 jakllsch static int bsciic_acquire_bus(void *, int);
150 1.1 jakllsch static void bsciic_release_bus(void *, int);
151 1.1 jakllsch static int bsciic_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
152 1.14 thorpej void *, size_t, int);
153 1.14 thorpej
154 1.14 thorpej static int bsciic_intr(void *);
155 1.14 thorpej
156 1.14 thorpej int bsciic_debug = 0;
157 1.1 jakllsch
158 1.1 jakllsch CFATTACH_DECL_NEW(bsciic, sizeof(struct bsciic_softc),
159 1.1 jakllsch bsciic_match, bsciic_attach, NULL, NULL);
160 1.1 jakllsch
161 1.1 jakllsch static int
162 1.1 jakllsch bsciic_match(device_t parent, cfdata_t match, void *aux)
163 1.1 jakllsch {
164 1.8 skrll const char * const compatible[] = { "brcm,bcm2835-i2c", NULL };
165 1.8 skrll struct fdt_attach_args * const faa = aux;
166 1.1 jakllsch
167 1.8 skrll return of_match_compatible(faa->faa_phandle, compatible);
168 1.1 jakllsch }
169 1.1 jakllsch
170 1.1 jakllsch static void
171 1.1 jakllsch bsciic_attach(device_t parent, device_t self, void *aux)
172 1.1 jakllsch {
173 1.1 jakllsch struct bsciic_softc * const sc = device_private(self);
174 1.8 skrll struct fdt_attach_args * const faa = aux;
175 1.8 skrll const int phandle = faa->faa_phandle;
176 1.6 jmcneill prop_dictionary_t prop = device_properties(self);
177 1.6 jmcneill bool disable = false;
178 1.8 skrll
179 1.8 skrll bus_addr_t addr;
180 1.8 skrll bus_size_t size;
181 1.8 skrll
182 1.8 skrll sc->sc_dev = self;
183 1.8 skrll sc->sc_iot = faa->faa_bst;
184 1.1 jakllsch
185 1.8 skrll int error = fdtbus_get_reg(phandle, 0, &addr, &size);
186 1.8 skrll if (error) {
187 1.8 skrll aprint_error(": unable to get device registers\n");
188 1.8 skrll return;
189 1.1 jakllsch }
190 1.1 jakllsch
191 1.6 jmcneill prop_dictionary_get_bool(prop, "disable", &disable);
192 1.6 jmcneill if (disable) {
193 1.6 jmcneill aprint_naive(": disabled\n");
194 1.6 jmcneill aprint_normal(": disabled\n");
195 1.6 jmcneill return;
196 1.6 jmcneill }
197 1.6 jmcneill
198 1.8 skrll /* Enable clock */
199 1.8 skrll sc->sc_clk = fdtbus_clock_get_index(phandle, 0);
200 1.8 skrll if (sc->sc_clk == NULL) {
201 1.8 skrll aprint_error(": couldn't acquire clock\n");
202 1.8 skrll return;
203 1.8 skrll }
204 1.1 jakllsch
205 1.8 skrll if (clk_enable(sc->sc_clk) != 0) {
206 1.8 skrll aprint_error(": failed to enable clock\n");
207 1.8 skrll return;
208 1.8 skrll }
209 1.1 jakllsch
210 1.8 skrll sc->sc_frequency = clk_get_rate(sc->sc_clk);
211 1.1 jakllsch
212 1.8 skrll if (of_getprop_uint32(phandle, "clock-frequency",
213 1.8 skrll &sc->sc_clkrate) != 0) {
214 1.8 skrll sc->sc_clkrate = 100000;
215 1.8 skrll }
216 1.1 jakllsch
217 1.8 skrll if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
218 1.14 thorpej aprint_error(": unable to map device\n");
219 1.1 jakllsch return;
220 1.1 jakllsch }
221 1.1 jakllsch
222 1.8 skrll aprint_naive("\n");
223 1.8 skrll aprint_normal(": Broadcom Serial Controller\n");
224 1.8 skrll
225 1.1 jakllsch /* clear FIFO, disable controller */
226 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_CLEAR_CLEAR);
227 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, BSC_S_CLKT |
228 1.1 jakllsch BSC_S_ERR | BSC_S_DONE);
229 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, 0);
230 1.8 skrll
231 1.8 skrll u_int divider = howmany(sc->sc_frequency, sc->sc_clkrate);
232 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DIV,
233 1.8 skrll __SHIFTIN(divider, BSC_DIV_CDIV));
234 1.1 jakllsch
235 1.14 thorpej mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);
236 1.14 thorpej cv_init(&sc->sc_intr_wait, device_xname(self));
237 1.14 thorpej
238 1.14 thorpej char intrstr[128];
239 1.14 thorpej if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
240 1.14 thorpej aprint_error_dev(sc->sc_dev, "failed to decode interrupt\n");
241 1.14 thorpej return;
242 1.14 thorpej }
243 1.14 thorpej sc->sc_inth = fdtbus_intr_establish(phandle, 0, IPL_VM,
244 1.14 thorpej FDT_INTR_MPSAFE, bsciic_intr, sc);
245 1.14 thorpej if (sc->sc_inth == NULL) {
246 1.14 thorpej aprint_error_dev(sc->sc_dev,
247 1.14 thorpej "failed to establish interrupt %s\n", intrstr);
248 1.14 thorpej return;
249 1.14 thorpej }
250 1.14 thorpej aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
251 1.14 thorpej
252 1.14 thorpej iic_tag_init(&sc->sc_i2c);
253 1.1 jakllsch sc->sc_i2c.ic_cookie = sc;
254 1.1 jakllsch sc->sc_i2c.ic_acquire_bus = bsciic_acquire_bus;
255 1.1 jakllsch sc->sc_i2c.ic_release_bus = bsciic_release_bus;
256 1.1 jakllsch sc->sc_i2c.ic_exec = bsciic_exec;
257 1.1 jakllsch
258 1.13 jmcneill fdtbus_attach_i2cbus(self, phandle, &sc->sc_i2c, iicbus_print);
259 1.1 jakllsch }
260 1.1 jakllsch
261 1.1 jakllsch static int
262 1.1 jakllsch bsciic_acquire_bus(void *v, int flags)
263 1.1 jakllsch {
264 1.1 jakllsch struct bsciic_softc * const sc = v;
265 1.2 ozaki uint32_t s __diagused;
266 1.1 jakllsch
267 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, BSC_S_CLKT |
268 1.1 jakllsch BSC_S_ERR | BSC_S_DONE);
269 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_I2CEN |
270 1.1 jakllsch BSC_C_CLEAR_CLEAR);
271 1.1 jakllsch s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
272 1.1 jakllsch KASSERT((s & BSC_S_TA) == 0);
273 1.1 jakllsch
274 1.1 jakllsch return 0;
275 1.1 jakllsch }
276 1.1 jakllsch
277 1.1 jakllsch static void
278 1.1 jakllsch bsciic_release_bus(void *v, int flags)
279 1.1 jakllsch {
280 1.1 jakllsch struct bsciic_softc * const sc = v;
281 1.1 jakllsch
282 1.1 jakllsch bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_CLEAR_CLEAR);
283 1.14 thorpej }
284 1.1 jakllsch
285 1.14 thorpej static void
286 1.14 thorpej bsciic_exec_lock(struct bsciic_softc * const sc)
287 1.14 thorpej {
288 1.14 thorpej if ((sc->sc_exec.flags & I2C_F_POLL) == 0) {
289 1.14 thorpej mutex_enter(&sc->sc_intr_lock);
290 1.14 thorpej }
291 1.1 jakllsch }
292 1.1 jakllsch
293 1.14 thorpej static void
294 1.14 thorpej bsciic_exec_unlock(struct bsciic_softc * const sc)
295 1.14 thorpej {
296 1.14 thorpej if ((sc->sc_exec.flags & I2C_F_POLL) == 0) {
297 1.14 thorpej mutex_exit(&sc->sc_intr_lock);
298 1.14 thorpej }
299 1.14 thorpej }
300 1.14 thorpej
301 1.14 thorpej static void
302 1.14 thorpej bsciic_txfill(struct bsciic_softc * const sc)
303 1.1 jakllsch {
304 1.14 thorpej uint32_t s;
305 1.1 jakllsch
306 1.14 thorpej while (sc->sc_bufpos != sc->sc_buflen) {
307 1.14 thorpej s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
308 1.14 thorpej if ((s & BSC_S_TXD) == 0)
309 1.14 thorpej break;
310 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_FIFO,
311 1.14 thorpej sc->sc_buf[sc->sc_bufpos++]);
312 1.14 thorpej }
313 1.14 thorpej }
314 1.12 thorpej
315 1.14 thorpej static void
316 1.14 thorpej bsciic_rxdrain(struct bsciic_softc * const sc)
317 1.14 thorpej {
318 1.14 thorpej uint32_t s;
319 1.1 jakllsch
320 1.14 thorpej while (sc->sc_bufpos != sc->sc_buflen) {
321 1.14 thorpej s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
322 1.14 thorpej if ((s & BSC_S_RXD) == 0)
323 1.14 thorpej break;
324 1.14 thorpej sc->sc_buf[sc->sc_bufpos++] =
325 1.14 thorpej (uint8_t)bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_FIFO);
326 1.14 thorpej }
327 1.14 thorpej }
328 1.1 jakllsch
329 1.14 thorpej static bsc_exec_state_t
330 1.14 thorpej bsciic_next_state(struct bsciic_softc * const sc)
331 1.14 thorpej {
332 1.14 thorpej switch (sc->sc_exec_state) {
333 1.14 thorpej case BSC_EXEC_STATE_IDLE:
334 1.14 thorpej if (sc->sc_exec.addr > 0x7f) {
335 1.14 thorpej return BSC_EXEC_STATE_SEND_ADDR;
336 1.14 thorpej }
337 1.14 thorpej /* FALLTHROUGH */
338 1.1 jakllsch
339 1.14 thorpej case BSC_EXEC_STATE_SEND_ADDR:
340 1.14 thorpej if (sc->sc_exec.cmdlen) {
341 1.14 thorpej return BSC_EXEC_STATE_SEND_CMD;
342 1.14 thorpej }
343 1.14 thorpej /* FALLTHROUGH */
344 1.1 jakllsch
345 1.14 thorpej case BSC_EXEC_STATE_SEND_CMD:
346 1.14 thorpej if (sc->sc_exec.datalen == 0) {
347 1.14 thorpej return BSC_EXEC_STATE_DONE;
348 1.1 jakllsch }
349 1.14 thorpej
350 1.14 thorpej if (I2C_OP_READ_P(sc->sc_exec.op)) {
351 1.14 thorpej return BSC_EXEC_STATE_RECV_DATA;
352 1.1 jakllsch }
353 1.14 thorpej
354 1.14 thorpej return BSC_EXEC_STATE_SEND_DATA;
355 1.14 thorpej
356 1.14 thorpej case BSC_EXEC_STATE_SEND_DATA:
357 1.14 thorpej case BSC_EXEC_STATE_RECV_DATA:
358 1.14 thorpej return BSC_EXEC_STATE_DONE;
359 1.14 thorpej
360 1.14 thorpej case BSC_EXEC_STATE_DONE:
361 1.14 thorpej case BSC_EXEC_STATE_ERROR:
362 1.14 thorpej return sc->sc_exec_state;
363 1.14 thorpej }
364 1.14 thorpej
365 1.14 thorpej panic("bsciic_next_state: invalid state: %d", sc->sc_exec_state);
366 1.14 thorpej }
367 1.14 thorpej
368 1.14 thorpej #define BSC_EXEC_PHASE_COMPLETE(sc) \
369 1.14 thorpej ((sc)->sc_exec_state == BSC_EXEC_STATE_ERROR || \
370 1.14 thorpej (sc)->sc_bufpos == (sc)->sc_buflen)
371 1.14 thorpej
372 1.14 thorpej static void
373 1.14 thorpej bsciic_signal(struct bsciic_softc * const sc)
374 1.14 thorpej {
375 1.14 thorpej if ((sc->sc_exec.flags & I2C_F_POLL) == 0) {
376 1.14 thorpej cv_signal(&sc->sc_intr_wait);
377 1.1 jakllsch }
378 1.14 thorpej }
379 1.1 jakllsch
380 1.14 thorpej static void
381 1.14 thorpej bsciic_phase_done(struct bsciic_softc * const sc)
382 1.14 thorpej {
383 1.14 thorpej sc->sc_exec_state = bsciic_next_state(sc);
384 1.14 thorpej (*bsciic_exec_state_data[sc->sc_exec_state].func)(sc);
385 1.14 thorpej }
386 1.14 thorpej
387 1.14 thorpej static void
388 1.14 thorpej bsciic_abort(struct bsciic_softc * const sc)
389 1.14 thorpej {
390 1.14 thorpej sc->sc_exec_state = BSC_EXEC_STATE_ERROR;
391 1.14 thorpej bsciic_phase_done(sc);
392 1.14 thorpej }
393 1.14 thorpej
394 1.14 thorpej static int
395 1.14 thorpej bsciic_intr(void *v)
396 1.14 thorpej {
397 1.14 thorpej struct bsciic_softc * const sc = v;
398 1.14 thorpej uint32_t s;
399 1.14 thorpej
400 1.14 thorpej bsciic_exec_lock(sc);
401 1.14 thorpej
402 1.14 thorpej if ((sc->sc_exec.flags & I2C_F_POLL) == 0 &&
403 1.14 thorpej sc->sc_expecting_interrupt == false) {
404 1.14 thorpej bsciic_exec_unlock(sc);
405 1.14 thorpej return 0;
406 1.14 thorpej }
407 1.1 jakllsch
408 1.1 jakllsch s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
409 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S,
410 1.14 thorpej BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
411 1.14 thorpej
412 1.14 thorpej if (s & (BSC_S_CLKT | BSC_S_ERR)) {
413 1.14 thorpej /*
414 1.14 thorpej * ERR might be a normal "probing for device" sort
415 1.14 thorpej * of thing, so don't complain about that one.
416 1.14 thorpej * Do complain about CLKT, though.
417 1.14 thorpej */
418 1.14 thorpej if ((s & BSC_S_CLKT) ||
419 1.14 thorpej (bsciic_debug && (s & BSC_S_ERR))) {
420 1.14 thorpej device_printf(sc->sc_dev,
421 1.14 thorpej "error s=0x%08x, aborting transfer\n", s);
422 1.14 thorpej }
423 1.14 thorpej bsciic_abort(sc);
424 1.14 thorpej goto out;
425 1.14 thorpej }
426 1.1 jakllsch
427 1.14 thorpej if (BSC_EXEC_STATE_SENDING(sc)) {
428 1.14 thorpej /*
429 1.14 thorpej * When transmitting, we need to wait for one final
430 1.14 thorpej * interrupt after pushing out the last of our data.
431 1.14 thorpej * Catch that case here and go to the next state.
432 1.14 thorpej */
433 1.14 thorpej if (BSC_EXEC_PHASE_COMPLETE(sc)) {
434 1.14 thorpej bsciic_phase_done(sc);
435 1.14 thorpej } else {
436 1.14 thorpej bsciic_txfill(sc);
437 1.14 thorpej }
438 1.14 thorpej } else if (BSC_EXEC_STATE_RECEIVING(sc)) {
439 1.14 thorpej bsciic_rxdrain(sc);
440 1.14 thorpej /*
441 1.14 thorpej * If we've received all of the data, go to the next
442 1.14 thorpej * state now; we might not get another interrupt.
443 1.14 thorpej */
444 1.14 thorpej if (BSC_EXEC_PHASE_COMPLETE(sc)) {
445 1.14 thorpej bsciic_phase_done(sc);
446 1.14 thorpej }
447 1.14 thorpej } else {
448 1.14 thorpej device_printf(sc->sc_dev,
449 1.14 thorpej "unexpected interrupt: state=%d s=0x%08x\n",
450 1.14 thorpej sc->sc_exec_state, s);
451 1.14 thorpej bsciic_abort(sc);
452 1.14 thorpej }
453 1.4 jakllsch
454 1.14 thorpej out:
455 1.14 thorpej bsciic_exec_unlock(sc);
456 1.14 thorpej return (1);
457 1.14 thorpej }
458 1.1 jakllsch
459 1.14 thorpej static void
460 1.14 thorpej bsciic_wait(struct bsciic_softc * const sc, const uint32_t events)
461 1.14 thorpej {
462 1.14 thorpej if ((sc->sc_exec.flags & I2C_F_POLL) == 0) {
463 1.14 thorpej return;
464 1.14 thorpej }
465 1.1 jakllsch
466 1.14 thorpej const uint32_t s_bits =
467 1.14 thorpej events | BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE;
468 1.14 thorpej uint32_t s;
469 1.1 jakllsch
470 1.14 thorpej /* sc_intr_lock is not held in this case. */
471 1.1 jakllsch
472 1.14 thorpej for (;;) {
473 1.1 jakllsch s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
474 1.14 thorpej if (s & s_bits) {
475 1.14 thorpej (void) bsciic_intr(sc);
476 1.14 thorpej }
477 1.14 thorpej if (BSC_EXEC_PHASE_COMPLETE(sc)) {
478 1.14 thorpej bsciic_phase_done(sc);
479 1.1 jakllsch }
480 1.14 thorpej if (sc->sc_exec_state >= BSC_EXEC_STATE_DONE) {
481 1.14 thorpej return;
482 1.1 jakllsch }
483 1.14 thorpej delay(1);
484 1.14 thorpej }
485 1.14 thorpej }
486 1.14 thorpej
487 1.14 thorpej static void
488 1.14 thorpej bsciic_start(struct bsciic_softc * const sc)
489 1.14 thorpej {
490 1.14 thorpej
491 1.14 thorpej sc->sc_c_bits = BSC_C_I2CEN | BSC_C_INTD |
492 1.14 thorpej bsciic_exec_state_data[sc->sc_exec_state].c_bits;
493 1.14 thorpej
494 1.14 thorpej /* Clear the interrupt-enable bits if we're polling. */
495 1.14 thorpej if (sc->sc_exec.flags & I2C_F_POLL) {
496 1.14 thorpej sc->sc_c_bits &= ~(BSC_C_INTD | BSC_C_INTT | BSC_C_INTR);
497 1.14 thorpej }
498 1.14 thorpej
499 1.14 thorpej sc->sc_expecting_interrupt =
500 1.14 thorpej (sc->sc_c_bits & (BSC_C_INTD | BSC_C_INTT | BSC_C_INTR)) ? true
501 1.14 thorpej : false;
502 1.14 thorpej
503 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C,
504 1.14 thorpej sc->sc_c_bits | BSC_C_ST);
505 1.14 thorpej bsciic_wait(sc, bsciic_exec_state_data[sc->sc_exec_state].s_bits);
506 1.14 thorpej }
507 1.14 thorpej
508 1.14 thorpej static void
509 1.14 thorpej bsciic_exec_func_idle(struct bsciic_softc * const sc)
510 1.14 thorpej {
511 1.14 thorpej /* We kick off a transfer by setting the slave address register. */
512 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_A, sc->sc_exec.addr);
513 1.14 thorpej
514 1.14 thorpej /* Immediately transition to the next state. */
515 1.14 thorpej bsciic_phase_done(sc);
516 1.14 thorpej }
517 1.14 thorpej
518 1.14 thorpej static void
519 1.14 thorpej bsciic_exec_func_send_addr(struct bsciic_softc * const sc)
520 1.14 thorpej {
521 1.14 thorpej /* XXX For 10-bit addressing; not implemented yet. */
522 1.14 thorpej panic("bsciic_exec_func_send_addr is not supposed to be called");
523 1.14 thorpej }
524 1.14 thorpej
525 1.14 thorpej static void
526 1.14 thorpej bsciic_exec_func_send_cmd(struct bsciic_softc * const sc)
527 1.14 thorpej {
528 1.14 thorpej sc->sc_buf = __UNCONST(sc->sc_exec.cmdbuf);
529 1.14 thorpej sc->sc_bufpos = 0;
530 1.14 thorpej sc->sc_buflen = sc->sc_exec.cmdlen;
531 1.14 thorpej
532 1.14 thorpej uint32_t dlen = sc->sc_exec.cmdlen;
533 1.14 thorpej if (! I2C_OP_READ_P(sc->sc_exec.op)) {
534 1.14 thorpej dlen += sc->sc_exec.datalen;
535 1.1 jakllsch }
536 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, dlen);
537 1.14 thorpej
538 1.14 thorpej bsciic_start(sc);
539 1.14 thorpej }
540 1.1 jakllsch
541 1.14 thorpej static void
542 1.14 thorpej bsciic_exec_func_send_data(struct bsciic_softc * const sc)
543 1.14 thorpej {
544 1.14 thorpej sc->sc_buf = sc->sc_exec.databuf;
545 1.14 thorpej sc->sc_bufpos = 0;
546 1.14 thorpej sc->sc_buflen = sc->sc_exec.datalen;
547 1.14 thorpej
548 1.14 thorpej if (sc->sc_exec.cmdlen) {
549 1.14 thorpej /*
550 1.14 thorpej * Output has already been started in this case; we just
551 1.14 thorpej * needed to switch buffers.
552 1.14 thorpej */
553 1.14 thorpej bsciic_wait(sc, BSC_S_TXW);
554 1.14 thorpej } else {
555 1.14 thorpej uint32_t dlen = sc->sc_exec.datalen;
556 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, dlen);
557 1.14 thorpej bsciic_start(sc);
558 1.14 thorpej }
559 1.14 thorpej }
560 1.1 jakllsch
561 1.14 thorpej static void
562 1.14 thorpej bsciic_exec_func_recv_data(struct bsciic_softc * const sc)
563 1.14 thorpej {
564 1.14 thorpej sc->sc_buf = sc->sc_exec.databuf;
565 1.14 thorpej sc->sc_bufpos = 0;
566 1.14 thorpej sc->sc_buflen = sc->sc_exec.datalen;
567 1.1 jakllsch
568 1.14 thorpej uint32_t dlen = sc->sc_exec.datalen;
569 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, dlen);
570 1.1 jakllsch
571 1.14 thorpej bsciic_start(sc);
572 1.14 thorpej }
573 1.1 jakllsch
574 1.14 thorpej static void
575 1.14 thorpej bsciic_exec_func_done(struct bsciic_softc * const sc)
576 1.14 thorpej {
577 1.14 thorpej /* We're done! Disable interrupts. */
578 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_I2CEN);
579 1.14 thorpej sc->sc_expecting_interrupt = false;
580 1.14 thorpej bsciic_signal(sc);
581 1.14 thorpej }
582 1.1 jakllsch
583 1.14 thorpej static void
584 1.14 thorpej bsciic_exec_func_error(struct bsciic_softc * const sc)
585 1.14 thorpej {
586 1.14 thorpej /* Clear the FIFO and disable interrupts. */
587 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C,
588 1.14 thorpej BSC_C_I2CEN | BSC_C_CLEAR_CLEAR);
589 1.14 thorpej sc->sc_expecting_interrupt = false;
590 1.14 thorpej bsciic_signal(sc);
591 1.14 thorpej }
592 1.1 jakllsch
593 1.14 thorpej static int
594 1.14 thorpej bsciic_exec(void *v, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
595 1.14 thorpej size_t cmdlen, void *databuf, size_t datalen, int flags)
596 1.14 thorpej {
597 1.14 thorpej struct bsciic_softc * const sc = v;
598 1.1 jakllsch
599 1.14 thorpej /* XXX We don't do 10-bit addressing correctly yet. */
600 1.14 thorpej if (addr > 0x7f)
601 1.14 thorpej return (ENOTSUP);
602 1.1 jakllsch
603 1.14 thorpej /*
604 1.14 thorpej * The I2C middle layer has ensured that the client device has
605 1.14 thorpej * exclusive access to the controller. Copy the parameters
606 1.14 thorpej * and start the state machine that runs through the necessary
607 1.14 thorpej * phases of the request.
608 1.14 thorpej */
609 1.14 thorpej KASSERT(sc->sc_exec_state == BSC_EXEC_STATE_IDLE);
610 1.14 thorpej sc->sc_exec.op = op;
611 1.14 thorpej sc->sc_exec.addr = addr;
612 1.14 thorpej sc->sc_exec.cmdbuf = cmdbuf;
613 1.14 thorpej sc->sc_exec.cmdlen = cmdlen;
614 1.14 thorpej sc->sc_exec.databuf = databuf;
615 1.14 thorpej sc->sc_exec.datalen = datalen;
616 1.14 thorpej sc->sc_exec.flags = flags;
617 1.14 thorpej
618 1.14 thorpej bsciic_exec_lock(sc);
619 1.14 thorpej (*bsciic_exec_state_data[sc->sc_exec_state].func)(sc);
620 1.14 thorpej while (sc->sc_exec_state < BSC_EXEC_STATE_DONE) {
621 1.14 thorpej KASSERT((flags & I2C_F_POLL) == 0);
622 1.14 thorpej cv_wait(&sc->sc_intr_wait, &sc->sc_intr_lock);
623 1.14 thorpej }
624 1.14 thorpej int error = sc->sc_exec_state == BSC_EXEC_STATE_ERROR ? EIO : 0;
625 1.14 thorpej uint32_t s;
626 1.14 thorpej do {
627 1.14 thorpej s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S);
628 1.14 thorpej } while ((s & BSC_S_TA) != 0);
629 1.14 thorpej if (s & (BSC_S_CLKT | BSC_S_ERR)) {
630 1.4 jakllsch error = EIO;
631 1.14 thorpej }
632 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C,
633 1.14 thorpej BSC_C_I2CEN | BSC_C_CLEAR_CLEAR);
634 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S,
635 1.14 thorpej BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
636 1.14 thorpej bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, 0);
637 1.14 thorpej bsciic_exec_unlock(sc);
638 1.14 thorpej
639 1.14 thorpej sc->sc_exec.flags = 0;
640 1.14 thorpej sc->sc_exec_state = BSC_EXEC_STATE_IDLE;
641 1.14 thorpej memset(&sc->sc_exec, 0, sizeof(sc->sc_exec));
642 1.4 jakllsch
643 1.1 jakllsch return error;
644 1.1 jakllsch }
645