xref: /netbsd-src/sys/dev/ic/dwiic.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* $NetBSD: dwiic.c,v 1.7 2019/12/23 15:28:08 thorpej Exp $ */
2 
3 /* $OpenBSD: dwiic.c,v 1.4 2018/05/23 22:08:00 kettenis Exp $ */
4 
5 /*-
6  * Copyright (c) 2017 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Manuel Bouyer.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * Synopsys DesignWare I2C controller
35  *
36  * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org>
37  *
38  * Permission to use, copy, modify, and/or distribute this software for any
39  * purpose with or without fee is hereby granted, provided that the above
40  * copyright notice and this permission notice appear in all copies.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
43  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
45  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
48  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49  */
50 
51 #include <sys/cdefs.h>
52 __KERNEL_RCSID(0, "$NetBSD: dwiic.c,v 1.7 2019/12/23 15:28:08 thorpej Exp $");
53 
54 #include <sys/param.h>
55 #include <sys/bus.h>
56 #include <sys/device.h>
57 #include <sys/kernel.h>
58 #include <sys/systm.h>
59 
60 #include <dev/ic/dwiic_var.h>
61 
62 //#define DWIIC_DEBUG
63 
64 #ifdef DWIIC_DEBUG
65 #define DPRINTF(x) printf x
66 #else
67 #define DPRINTF(x)
68 #endif
69 
70 /* register offsets */
71 #define DW_IC_CON		0x0
72 #define DW_IC_TAR		0x4
73 #define DW_IC_DATA_CMD		0x10
74 #define DW_IC_SS_SCL_HCNT	0x14
75 #define DW_IC_SS_SCL_LCNT	0x18
76 #define DW_IC_FS_SCL_HCNT	0x1c
77 #define DW_IC_FS_SCL_LCNT	0x20
78 #define DW_IC_INTR_STAT		0x2c
79 #define DW_IC_INTR_MASK		0x30
80 #define DW_IC_RAW_INTR_STAT	0x34
81 #define DW_IC_RX_TL		0x38
82 #define DW_IC_TX_TL		0x3c
83 #define DW_IC_CLR_INTR		0x40
84 #define DW_IC_CLR_RX_UNDER	0x44
85 #define DW_IC_CLR_RX_OVER	0x48
86 #define DW_IC_CLR_TX_OVER	0x4c
87 #define DW_IC_CLR_RD_REQ	0x50
88 #define DW_IC_CLR_TX_ABRT	0x54
89 #define DW_IC_CLR_RX_DONE	0x58
90 #define DW_IC_CLR_ACTIVITY	0x5c
91 #define DW_IC_CLR_STOP_DET	0x60
92 #define DW_IC_CLR_START_DET	0x64
93 #define DW_IC_CLR_GEN_CALL	0x68
94 #define DW_IC_ENABLE		0x6c
95 #define DW_IC_STATUS		0x70
96 #define DW_IC_TXFLR		0x74
97 #define DW_IC_RXFLR		0x78
98 #define DW_IC_SDA_HOLD		0x7c
99 #define DW_IC_TX_ABRT_SOURCE	0x80
100 #define DW_IC_ENABLE_STATUS	0x9c
101 #define DW_IC_COMP_PARAM_1	0xf4
102 #define DW_IC_COMP_VERSION	0xf8
103 #define DW_IC_SDA_HOLD_MIN_VERS	0x3131312A
104 #define DW_IC_COMP_TYPE		0xfc
105 #define DW_IC_COMP_TYPE_VALUE	0x44570140
106 
107 #define DW_IC_CON_MASTER	0x1
108 #define DW_IC_CON_SPEED_STD	0x2
109 #define DW_IC_CON_SPEED_FAST	0x4
110 #define DW_IC_CON_10BITADDR_MASTER 0x10
111 #define DW_IC_CON_RESTART_EN	0x20
112 #define DW_IC_CON_SLAVE_DISABLE	0x40
113 
114 #define DW_IC_DATA_CMD_READ	0x100
115 #define DW_IC_DATA_CMD_STOP	0x200
116 #define DW_IC_DATA_CMD_RESTART	0x400
117 
118 #define DW_IC_INTR_RX_UNDER	0x001
119 #define DW_IC_INTR_RX_OVER	0x002
120 #define DW_IC_INTR_RX_FULL	0x004
121 #define DW_IC_INTR_TX_OVER	0x008
122 #define DW_IC_INTR_TX_EMPTY	0x010
123 #define DW_IC_INTR_RD_REQ	0x020
124 #define DW_IC_INTR_TX_ABRT	0x040
125 #define DW_IC_INTR_RX_DONE	0x080
126 #define DW_IC_INTR_ACTIVITY	0x100
127 #define DW_IC_INTR_STOP_DET	0x200
128 #define DW_IC_INTR_START_DET	0x400
129 #define DW_IC_INTR_GEN_CALL	0x800
130 
131 #define DW_IC_STATUS_ACTIVITY	0x1
132 
133 /* hardware abort codes from the DW_IC_TX_ABRT_SOURCE register */
134 #define ABRT_7B_ADDR_NOACK	0
135 #define ABRT_10ADDR1_NOACK	1
136 #define ABRT_10ADDR2_NOACK	2
137 #define ABRT_TXDATA_NOACK	3
138 #define ABRT_GCALL_NOACK	4
139 #define ABRT_GCALL_READ		5
140 #define ABRT_SBYTE_ACKDET	7
141 #define ABRT_SBYTE_NORSTRT	9
142 #define ABRT_10B_RD_NORSTRT	10
143 #define ABRT_MASTER_DIS		11
144 #define ARB_LOST		12
145 
146 static int	dwiic_init(struct dwiic_softc *);
147 static void	dwiic_enable(struct dwiic_softc *, bool);
148 static uint32_t	dwiic_read(struct dwiic_softc *, int);
149 static void	dwiic_write(struct dwiic_softc *, int, uint32_t);
150 static int	dwiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
151 		    size_t, void *, size_t, int);
152 
153 bool
154 dwiic_attach(struct dwiic_softc *sc)
155 {
156 	if (sc->sc_power != NULL) {
157 		if (!sc->sc_power(sc, 1)) {
158 			aprint_error_dev(sc->sc_dev, "failed to power up\n");
159 			return 0;
160 		}
161 	}
162 
163 	/* fetch timing parameters */
164 	if (sc->ss_hcnt == 0)
165 		sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT);
166 	if (sc->ss_lcnt == 0)
167 		sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT);
168 	if (sc->fs_hcnt == 0)
169 		sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT);
170 	if (sc->fs_lcnt == 0)
171 		sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
172 	if (sc->sda_hold_time == 0)
173 		sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
174 
175 	if (dwiic_init(sc)) {
176 		aprint_error_dev(sc->sc_dev, "failed initializing\n");
177 		return 0;
178 	}
179 
180 	/* leave the controller disabled */
181 	dwiic_write(sc, DW_IC_INTR_MASK, 0);
182 	dwiic_enable(sc, 0);
183 	dwiic_read(sc, DW_IC_CLR_INTR);
184 
185 	mutex_init(&sc->sc_int_lock, MUTEX_DEFAULT, IPL_VM);
186 	cv_init(&sc->sc_int_readwait, "dwiicr");
187 	cv_init(&sc->sc_int_writewait, "dwiicw");
188 	cv_init(&sc->sc_int_stopwait, "dwiics");
189 
190 	/* setup and attach iic bus */
191 	iic_tag_init(&sc->sc_i2c_tag);
192 	sc->sc_i2c_tag.ic_cookie = sc;
193 	sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec;
194 
195 	sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
196 
197 	/* config_found_ia for "i2cbus" is done in the bus-attachment glue */
198 
199 	return 1;
200 }
201 
202 int
203 dwiic_detach(device_t self, int flags)
204 {
205 	struct dwiic_softc *sc = device_private(self);
206 
207 	dwiic_enable(sc, 0);
208 	if (sc->sc_ih != NULL) {
209 		intr_disestablish(sc->sc_ih);
210 		sc->sc_ih = NULL;
211 	}
212 
213 	return 0;
214 }
215 
216 bool
217 dwiic_suspend(device_t self, const pmf_qual_t *qual)
218 {
219 	struct dwiic_softc *sc = device_private(self);
220 
221 	/* disable controller */
222 	dwiic_enable(sc, 0);
223 
224 	/* disable interrupts */
225 	dwiic_write(sc, DW_IC_INTR_MASK, 0);
226 	dwiic_read(sc, DW_IC_CLR_INTR);
227 	if (sc->sc_power != NULL) {
228 		if (!sc->sc_power(sc, 0)) {
229 			device_printf(sc->sc_dev, "failed to power off\n");
230 		}
231 	}
232 	return true;
233 }
234 
235 bool
236 dwiic_resume(device_t self, const pmf_qual_t *qual)
237 {
238 	struct dwiic_softc *sc = device_private(self);
239 	if (sc->sc_power != NULL) {
240 		if (!sc->sc_power(sc, 1)) {
241 			device_printf(sc->sc_dev, "failed to power up\n");
242 			return false;
243 		}
244 	}
245 	dwiic_init(sc);
246 	return true;
247 }
248 
249 static uint32_t
250 dwiic_read(struct dwiic_softc *sc, int offset)
251 {
252 	u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset);
253 
254 	DPRINTF(("%s: read at 0x%x = 0x%x\n", device_xname(sc->sc_dev), offset, b));
255 
256 	return b;
257 }
258 
259 static void
260 dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val)
261 {
262 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val);
263 
264 	DPRINTF(("%s: write at 0x%x: 0x%x\n", device_xname(sc->sc_dev), offset,
265 	    val));
266 }
267 
268 static int
269 dwiic_init(struct dwiic_softc *sc)
270 {
271 	uint32_t reg;
272 
273 	/* make sure we're talking to a device we know */
274 	reg = dwiic_read(sc, DW_IC_COMP_TYPE);
275 	if (reg != DW_IC_COMP_TYPE_VALUE) {
276 		DPRINTF(("%s: invalid component type 0x%x\n",
277 		    device_xname(sc->sc_dev), reg));
278 		return 1;
279 	}
280 
281 	/* disable the adapter */
282 	dwiic_enable(sc, 0);
283 
284 	/* write standard-mode SCL timing parameters */
285 	dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt);
286 	dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt);
287 
288 	/* and fast-mode SCL timing parameters */
289 	dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt);
290 	dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt);
291 
292 	/* SDA hold time */
293 	reg = dwiic_read(sc, DW_IC_COMP_VERSION);
294 	if (reg >= DW_IC_SDA_HOLD_MIN_VERS)
295 		dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time);
296 
297 	/* FIFO threshold levels */
298 	sc->tx_fifo_depth = 32;
299 	sc->rx_fifo_depth = 32;
300 	dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2);
301 	dwiic_write(sc, DW_IC_RX_TL, 0);
302 
303 	/* configure as i2c master with fast speed */
304 	sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
305 	    DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
306 	dwiic_write(sc, DW_IC_CON, sc->master_cfg);
307 
308 	return 0;
309 }
310 
311 static void
312 dwiic_enable(struct dwiic_softc *sc, bool enable)
313 {
314 	int retries;
315 
316 	for (retries = 100; retries > 0; retries--) {
317 		dwiic_write(sc, DW_IC_ENABLE, enable);
318 		if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable)
319 			return;
320 
321 		DELAY(25);
322 	}
323 
324 	device_printf(sc->sc_dev, "failed to %sable\n",
325 	    (enable ? "en" : "dis"));
326 }
327 
328 static int
329 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
330     size_t cmdlen, void *buf, size_t len, int flags)
331 {
332 	struct dwiic_softc *sc = cookie;
333 	u_int32_t ic_con, st, cmd, resp;
334 	int retries, tx_limit, rx_avail, x, readpos;
335 	const uint8_t *bcmd;
336 	uint8_t *bdata;
337 
338 	if (sc->sc_poll)
339 		flags |= I2C_F_POLL;
340 
341 	DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, "
342 	    "flags 0x%02x\n", device_xname(sc->sc_dev), __func__, op, addr, cmdlen,
343 	    len, flags));
344 
345 	/* setup transfer */
346 	sc->sc_i2c_xfer.op = op;
347 	sc->sc_i2c_xfer.buf = buf;
348 	sc->sc_i2c_xfer.len = len;
349 	sc->sc_i2c_xfer.flags = flags;
350 	sc->sc_i2c_xfer.error = 0;
351 
352 	/* wait for bus to be idle */
353 	for (retries = 100; retries > 0; retries--) {
354 		st = dwiic_read(sc, DW_IC_STATUS);
355 		if (!(st & DW_IC_STATUS_ACTIVITY))
356 			break;
357 		DELAY(1000);
358 	}
359 	DPRINTF(("%s: %s: status 0x%x\n", device_xname(sc->sc_dev), __func__, st));
360 	if (st & DW_IC_STATUS_ACTIVITY) {
361 		return (1);
362 	}
363 
364 	/* disable controller */
365 	dwiic_enable(sc, 0);
366 
367 	/* set slave address */
368 	ic_con = dwiic_read(sc, DW_IC_CON);
369 	ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
370 	dwiic_write(sc, DW_IC_CON, ic_con);
371 	dwiic_write(sc, DW_IC_TAR, addr);
372 
373 	/* disable interrupts */
374 	dwiic_write(sc, DW_IC_INTR_MASK, 0);
375 	dwiic_read(sc, DW_IC_CLR_INTR);
376 
377 	/* enable controller */
378 	dwiic_enable(sc, 1);
379 
380 	/* wait until the controller is ready for commands */
381 	if (flags & I2C_F_POLL)
382 		DELAY(200);
383 	else {
384 		mutex_enter(&sc->sc_int_lock);
385 		dwiic_read(sc, DW_IC_CLR_INTR);
386 		dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY);
387 
388 		if (cv_timedwait(&sc->sc_int_writewait,
389 		    &sc->sc_int_lock, hz / 2) != 0)
390 			device_printf(sc->sc_dev,
391 			    "timed out waiting for tx_empty intr\n");
392 		dwiic_write(sc, DW_IC_INTR_MASK, 0);
393 		dwiic_read(sc, DW_IC_CLR_INTR);
394 		mutex_exit(&sc->sc_int_lock);
395 	}
396 
397 	/* send our command, one byte at a time */
398 	if (cmdlen > 0) {
399 		bcmd = (const void *)cmdbuf;
400 
401 		DPRINTF(("%s: %s: sending cmd (len %zu):", device_xname(sc->sc_dev),
402 		    __func__, cmdlen));
403 		for (x = 0; x < cmdlen; x++)
404 			DPRINTF((" %02x", bcmd[x]));
405 		DPRINTF(("\n"));
406 
407 		tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
408 		if (cmdlen > tx_limit) {
409 			/* TODO */
410 			device_printf(sc->sc_dev, "can't write %zu (> %d)\n",
411 			    cmdlen, tx_limit);
412 			sc->sc_i2c_xfer.error = 1;
413 			return (1);
414 		}
415 
416 		for (x = 0; x < cmdlen; x++) {
417 			cmd = bcmd[x];
418 			/*
419 			 * Generate STOP condition if this is the last
420 			 * byte of the transfer.
421 			 */
422 			if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op))
423 				cmd |= DW_IC_DATA_CMD_STOP;
424 			dwiic_write(sc, DW_IC_DATA_CMD, cmd);
425 		}
426 	}
427 
428 	bdata = (void *)buf;
429 	x = readpos = 0;
430 	tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
431 
432 	DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n",
433 		device_xname(sc->sc_dev), __func__, len, tx_limit));
434 
435 	while (x < len) {
436 		if (I2C_OP_WRITE_P(op))
437 			cmd = bdata[x];
438 		else
439 			cmd = DW_IC_DATA_CMD_READ;
440 
441 		/*
442 		 * Generate RESTART condition if we're reversing
443 		 * direction.
444 		 */
445 		if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op))
446 			cmd |= DW_IC_DATA_CMD_RESTART;
447 		/*
448 		 * Generate STOP conditon on the last byte of the
449 		 * transfer.
450 		 */
451 		if (x == (len - 1) && I2C_OP_STOP_P(op))
452 			cmd |= DW_IC_DATA_CMD_STOP;
453 
454 		dwiic_write(sc, DW_IC_DATA_CMD, cmd);
455 
456 		tx_limit--;
457 		x++;
458 
459 		/*
460 		 * As TXFLR fills up, we need to clear it out by reading all
461 		 * available data.
462 		 */
463 		while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) {
464 			DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n",
465 			    device_xname(sc->sc_dev), __func__, tx_limit, x));
466 
467 			if (flags & I2C_F_POLL) {
468 				for (retries = 100; retries > 0; retries--) {
469 					rx_avail = dwiic_read(sc, DW_IC_RXFLR);
470 					if (rx_avail > 0)
471 						break;
472 					DELAY(50);
473 				}
474 			} else {
475 				mutex_enter(&sc->sc_int_lock);
476 				dwiic_read(sc, DW_IC_CLR_INTR);
477 				dwiic_write(sc, DW_IC_INTR_MASK,
478 				    DW_IC_INTR_RX_FULL);
479 
480 				if (cv_timedwait(&sc->sc_int_readwait,
481 				    &sc->sc_int_lock, hz / 2) != 0)
482 					device_printf(sc->sc_dev,
483 					    "timed out waiting for "
484 					    "rx_full intr\n");
485 
486 				dwiic_write(sc, DW_IC_INTR_MASK, 0);
487 				dwiic_read(sc, DW_IC_CLR_INTR);
488 				mutex_exit(&sc->sc_int_lock);
489 				rx_avail = dwiic_read(sc, DW_IC_RXFLR);
490 			}
491 
492 			if (rx_avail == 0) {
493 				device_printf(sc->sc_dev,
494 				    "timed out reading remaining %d\n",
495 				    (int)(len - 1 - readpos));
496 				sc->sc_i2c_xfer.error = 1;
497 				return (1);
498 			}
499 
500 			DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n",
501 			    device_xname(sc->sc_dev), __func__, rx_avail,
502 			    len - readpos));
503 
504 			while (rx_avail > 0) {
505 				resp = dwiic_read(sc, DW_IC_DATA_CMD);
506 				if (readpos < len) {
507 					bdata[readpos] = resp;
508 					readpos++;
509 				}
510 				rx_avail--;
511 			}
512 
513 			if (readpos >= len)
514 				break;
515 
516 			DPRINTF(("%s: still need to read %d bytes\n",
517 			    device_xname(sc->sc_dev), (int)(len - readpos)));
518 			tx_limit = sc->tx_fifo_depth -
519 			    dwiic_read(sc, DW_IC_TXFLR);
520 		}
521 	}
522 
523 	if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) {
524 		if (flags & I2C_F_POLL) {
525 			/* wait for bus to be idle */
526 			for (retries = 100; retries > 0; retries--) {
527 				st = dwiic_read(sc, DW_IC_STATUS);
528 				if (!(st & DW_IC_STATUS_ACTIVITY))
529 					break;
530 				DELAY(1000);
531 			}
532 			if (st & DW_IC_STATUS_ACTIVITY)
533 				device_printf(sc->sc_dev, "timed out waiting "
534 				    "for bus idle\n");
535 		} else {
536 			mutex_enter(&sc->sc_int_lock);
537 			dwiic_read(sc, DW_IC_CLR_INTR);
538 			dwiic_write(sc, DW_IC_INTR_MASK,
539 			    DW_IC_INTR_STOP_DET);
540 			if (cv_timedwait(&sc->sc_int_stopwait,
541 			    &sc->sc_int_lock, hz / 2) != 0)
542 				device_printf(sc->sc_dev, "timed out waiting "
543 				    "for stop intr\n");
544 			dwiic_write(sc, DW_IC_INTR_MASK, 0);
545 			dwiic_read(sc, DW_IC_CLR_INTR);
546 			mutex_exit(&sc->sc_int_lock);
547 		}
548 	}
549 
550 	return 0;
551 }
552 
553 static uint32_t
554 dwiic_read_clear_intrbits(struct dwiic_softc *sc)
555 {
556        uint32_t stat;
557 
558        stat = dwiic_read(sc, DW_IC_INTR_STAT);
559 
560        if (stat & DW_IC_INTR_RX_UNDER)
561 	       dwiic_read(sc, DW_IC_CLR_RX_UNDER);
562        if (stat & DW_IC_INTR_RX_OVER)
563 	       dwiic_read(sc, DW_IC_CLR_RX_OVER);
564        if (stat & DW_IC_INTR_TX_OVER)
565 	       dwiic_read(sc, DW_IC_CLR_TX_OVER);
566        if (stat & DW_IC_INTR_RD_REQ)
567 	       dwiic_read(sc, DW_IC_CLR_RD_REQ);
568        if (stat & DW_IC_INTR_TX_ABRT)
569 	       dwiic_read(sc, DW_IC_CLR_TX_ABRT);
570        if (stat & DW_IC_INTR_RX_DONE)
571 	       dwiic_read(sc, DW_IC_CLR_RX_DONE);
572        if (stat & DW_IC_INTR_ACTIVITY)
573 	       dwiic_read(sc, DW_IC_CLR_ACTIVITY);
574        if (stat & DW_IC_INTR_STOP_DET)
575 	       dwiic_read(sc, DW_IC_CLR_STOP_DET);
576        if (stat & DW_IC_INTR_START_DET)
577 	       dwiic_read(sc, DW_IC_CLR_START_DET);
578        if (stat & DW_IC_INTR_GEN_CALL)
579 	       dwiic_read(sc, DW_IC_CLR_GEN_CALL);
580 
581        return stat;
582 }
583 
584 int
585 dwiic_intr(void *arg)
586 {
587 	struct dwiic_softc *sc = arg;
588 	uint32_t en, stat;
589 
590 	en = dwiic_read(sc, DW_IC_ENABLE);
591 	/* probably for the other controller */
592 	if (!en)
593 		return 0;
594 
595 	stat = dwiic_read_clear_intrbits(sc);
596 	DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", device_xname(sc->sc_dev),
597 	    __func__, en, stat));
598 	if (!(stat & ~DW_IC_INTR_ACTIVITY))
599 		return 1;
600 
601 	if (stat & DW_IC_INTR_TX_ABRT)
602 		sc->sc_i2c_xfer.error = 1;
603 
604 	if (sc->sc_i2c_xfer.flags & I2C_F_POLL)
605 		DPRINTF(("%s: %s: intr in poll mode?\n", device_xname(sc->sc_dev),
606 		    __func__));
607 	else {
608 		mutex_enter(&sc->sc_int_lock);
609 		if (stat & DW_IC_INTR_RX_FULL) {
610 			dwiic_write(sc, DW_IC_INTR_MASK, 0);
611 			DPRINTF(("%s: %s: waking up reader\n",
612 			    device_xname(sc->sc_dev), __func__));
613 			cv_signal(&sc->sc_int_readwait);
614 		}
615 		if (stat & DW_IC_INTR_TX_EMPTY) {
616 			dwiic_write(sc, DW_IC_INTR_MASK, 0);
617 			DPRINTF(("%s: %s: waking up writer\n",
618 			    device_xname(sc->sc_dev), __func__));
619 			cv_signal(&sc->sc_int_writewait);
620 		}
621 		if (stat & DW_IC_INTR_STOP_DET) {
622 			dwiic_write(sc, DW_IC_INTR_MASK, 0);
623 			DPRINTF(("%s: %s: waking up stopper\n",
624 			    device_xname(sc->sc_dev), __func__));
625 			cv_signal(&sc->sc_int_stopwait);
626 		}
627 		mutex_exit(&sc->sc_int_lock);
628 	}
629 
630 	return 1;
631 }
632