1/* $NetBSD: dwiic.c,v 1.10 2024/02/09 16:56:23 skrll 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.10 2024/02/09 16:56:23 skrll Exp $");
53
54#include <sys/param.h>
55
56#include <sys/atomic.h>
57#include <sys/bus.h>
58#include <sys/device.h>
59#include <sys/kernel.h>
60#include <sys/systm.h>
61
62#include <dev/ic/dwiic_var.h>
63
64//#define DWIIC_DEBUG
65
66#ifdef DWIIC_DEBUG
67#define DPRINTF(x) printf x
68#else
69#define DPRINTF(x)
70#endif
71
72/* register offsets */
73#define DW_IC_CON		0x0
74#define DW_IC_TAR		0x4
75#define DW_IC_DATA_CMD		0x10
76#define DW_IC_SS_SCL_HCNT	0x14
77#define DW_IC_SS_SCL_LCNT	0x18
78#define DW_IC_FS_SCL_HCNT	0x1c
79#define DW_IC_FS_SCL_LCNT	0x20
80#define DW_IC_INTR_STAT		0x2c
81#define DW_IC_INTR_MASK		0x30
82#define DW_IC_RAW_INTR_STAT	0x34
83#define DW_IC_RX_TL		0x38
84#define DW_IC_TX_TL		0x3c
85#define DW_IC_CLR_INTR		0x40
86#define DW_IC_CLR_RX_UNDER	0x44
87#define DW_IC_CLR_RX_OVER	0x48
88#define DW_IC_CLR_TX_OVER	0x4c
89#define DW_IC_CLR_RD_REQ	0x50
90#define DW_IC_CLR_TX_ABRT	0x54
91#define DW_IC_CLR_RX_DONE	0x58
92#define DW_IC_CLR_ACTIVITY	0x5c
93#define DW_IC_CLR_STOP_DET	0x60
94#define DW_IC_CLR_START_DET	0x64
95#define DW_IC_CLR_GEN_CALL	0x68
96#define DW_IC_ENABLE		0x6c
97#define DW_IC_STATUS		0x70
98#define DW_IC_TXFLR		0x74
99#define DW_IC_RXFLR		0x78
100#define DW_IC_SDA_HOLD		0x7c
101#define DW_IC_TX_ABRT_SOURCE	0x80
102#define DW_IC_ENABLE_STATUS	0x9c
103#define DW_IC_COMP_PARAM_1	0xf4
104#define DW_IC_COMP_VERSION	0xf8
105#define DW_IC_SDA_HOLD_MIN_VERS	0x3131312A
106#define DW_IC_COMP_TYPE		0xfc
107#define DW_IC_COMP_TYPE_VALUE	0x44570140
108
109#define DW_IC_CON_MASTER	0x1
110#define DW_IC_CON_SPEED_STD	0x2
111#define DW_IC_CON_SPEED_FAST	0x4
112#define DW_IC_CON_10BITADDR_MASTER 0x10
113#define DW_IC_CON_RESTART_EN	0x20
114#define DW_IC_CON_SLAVE_DISABLE	0x40
115
116#define DW_IC_DATA_CMD_READ	0x100
117#define DW_IC_DATA_CMD_STOP	0x200
118#define DW_IC_DATA_CMD_RESTART	0x400
119
120#define DW_IC_INTR_RX_UNDER	0x001
121#define DW_IC_INTR_RX_OVER	0x002
122#define DW_IC_INTR_RX_FULL	0x004
123#define DW_IC_INTR_TX_OVER	0x008
124#define DW_IC_INTR_TX_EMPTY	0x010
125#define DW_IC_INTR_RD_REQ	0x020
126#define DW_IC_INTR_TX_ABRT	0x040
127#define DW_IC_INTR_RX_DONE	0x080
128#define DW_IC_INTR_ACTIVITY	0x100
129#define DW_IC_INTR_STOP_DET	0x200
130#define DW_IC_INTR_START_DET	0x400
131#define DW_IC_INTR_GEN_CALL	0x800
132
133#define DW_IC_STATUS_ACTIVITY	0x1
134
135/* hardware abort codes from the DW_IC_TX_ABRT_SOURCE register */
136#define ABRT_7B_ADDR_NOACK	0
137#define ABRT_10ADDR1_NOACK	1
138#define ABRT_10ADDR2_NOACK	2
139#define ABRT_TXDATA_NOACK	3
140#define ABRT_GCALL_NOACK	4
141#define ABRT_GCALL_READ		5
142#define ABRT_SBYTE_ACKDET	7
143#define ABRT_SBYTE_NORSTRT	9
144#define ABRT_10B_RD_NORSTRT	10
145#define ABRT_MASTER_DIS		11
146#define ARB_LOST		12
147
148static int	dwiic_init(struct dwiic_softc *);
149static void	dwiic_enable(struct dwiic_softc *, bool);
150static uint32_t	dwiic_read(struct dwiic_softc *, int);
151static void	dwiic_write(struct dwiic_softc *, int, uint32_t);
152static int	dwiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
153		    size_t, void *, size_t, int);
154
155bool
156dwiic_attach(struct dwiic_softc *sc)
157{
158	if (sc->sc_power != NULL) {
159		if (!sc->sc_power(sc, 1)) {
160			aprint_error_dev(sc->sc_dev, "failed to power up\n");
161			return 0;
162		}
163	}
164
165	/* fetch timing parameters */
166	if (sc->ss_hcnt == 0)
167		sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT);
168	if (sc->ss_lcnt == 0)
169		sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT);
170	if (sc->fs_hcnt == 0)
171		sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT);
172	if (sc->fs_lcnt == 0)
173		sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
174	if (sc->sda_hold_time == 0)
175		sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
176
177	if (dwiic_init(sc)) {
178		aprint_error_dev(sc->sc_dev, "failed initializing\n");
179		return 0;
180	}
181
182	/* leave the controller disabled */
183	dwiic_write(sc, DW_IC_INTR_MASK, 0);
184	dwiic_enable(sc, 0);
185	dwiic_read(sc, DW_IC_CLR_INTR);
186
187	mutex_init(&sc->sc_int_lock, MUTEX_DEFAULT, IPL_VM);
188	cv_init(&sc->sc_int_readwait, "dwiicr");
189	cv_init(&sc->sc_int_writewait, "dwiicw");
190	cv_init(&sc->sc_int_stopwait, "dwiics");
191
192	/* setup and attach iic bus */
193	iic_tag_init(&sc->sc_i2c_tag);
194	sc->sc_i2c_tag.ic_cookie = sc;
195	sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec;
196
197	sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
198
199	/* config_found_ia for "i2cbus" is done in the bus-attachment glue */
200
201	atomic_store_release(&sc->sc_attached, true);
202
203	return 1;
204}
205
206int
207dwiic_detach(device_t self, int flags)
208{
209	struct dwiic_softc *sc = device_private(self);
210
211	dwiic_enable(sc, 0);
212	if (sc->sc_ih != NULL) {
213		intr_disestablish(sc->sc_ih);
214		sc->sc_ih = NULL;
215	}
216
217	return 0;
218}
219
220bool
221dwiic_suspend(device_t self, const pmf_qual_t *qual)
222{
223	struct dwiic_softc *sc = device_private(self);
224
225	/* disable controller */
226	dwiic_enable(sc, 0);
227
228	/* disable interrupts */
229	dwiic_write(sc, DW_IC_INTR_MASK, 0);
230	dwiic_read(sc, DW_IC_CLR_INTR);
231	if (sc->sc_power != NULL) {
232		if (!sc->sc_power(sc, 0)) {
233			device_printf(sc->sc_dev, "failed to power off\n");
234		}
235	}
236	return true;
237}
238
239bool
240dwiic_resume(device_t self, const pmf_qual_t *qual)
241{
242	struct dwiic_softc *sc = device_private(self);
243	if (sc->sc_power != NULL) {
244		if (!sc->sc_power(sc, 1)) {
245			device_printf(sc->sc_dev, "failed to power up\n");
246			return false;
247		}
248	}
249	dwiic_init(sc);
250	return true;
251}
252
253static uint32_t
254dwiic_read(struct dwiic_softc *sc, int offset)
255{
256	u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset);
257
258	DPRINTF(("%s: read at 0x%x = 0x%x\n", device_xname(sc->sc_dev), offset, b));
259
260	return b;
261}
262
263static void
264dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val)
265{
266	bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val);
267
268	DPRINTF(("%s: write at 0x%x: 0x%x\n", device_xname(sc->sc_dev), offset,
269	    val));
270}
271
272static int
273dwiic_init(struct dwiic_softc *sc)
274{
275	uint32_t reg;
276
277	/* make sure we're talking to a device we know */
278	reg = dwiic_read(sc, DW_IC_COMP_TYPE);
279	if (reg != DW_IC_COMP_TYPE_VALUE) {
280		DPRINTF(("%s: invalid component type 0x%x\n",
281		    device_xname(sc->sc_dev), reg));
282		return 1;
283	}
284
285	/* disable the adapter */
286	dwiic_enable(sc, 0);
287
288	/* write standard-mode SCL timing parameters */
289	dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt);
290	dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt);
291
292	/* and fast-mode SCL timing parameters */
293	dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt);
294	dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt);
295
296	/* SDA hold time */
297	reg = dwiic_read(sc, DW_IC_COMP_VERSION);
298	if (reg >= DW_IC_SDA_HOLD_MIN_VERS)
299		dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time);
300
301	/* FIFO threshold levels */
302	sc->tx_fifo_depth = 32;
303	sc->rx_fifo_depth = 32;
304	dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2);
305	dwiic_write(sc, DW_IC_RX_TL, 0);
306
307	/* configure as i2c master with fast speed */
308	sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
309	    DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
310	dwiic_write(sc, DW_IC_CON, sc->master_cfg);
311
312	return 0;
313}
314
315static void
316dwiic_enable(struct dwiic_softc *sc, bool enable)
317{
318	int retries;
319
320	for (retries = 100; retries > 0; retries--) {
321		dwiic_write(sc, DW_IC_ENABLE, enable);
322		if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable)
323			return;
324
325		DELAY(25);
326	}
327
328	device_printf(sc->sc_dev, "failed to %sable\n",
329	    (enable ? "en" : "dis"));
330}
331
332static int
333dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
334    size_t cmdlen, void *buf, size_t len, int flags)
335{
336	struct dwiic_softc *sc = cookie;
337	u_int32_t ic_con, st, cmd, resp;
338	int retries, tx_limit, rx_avail, x, readpos;
339	const uint8_t *bcmd;
340	uint8_t *bdata;
341
342	if (sc->sc_poll)
343		flags |= I2C_F_POLL;
344
345	DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, "
346	    "flags 0x%02x\n", device_xname(sc->sc_dev), __func__, op, addr, cmdlen,
347	    len, flags));
348
349	/* setup transfer */
350	sc->sc_i2c_xfer.op = op;
351	sc->sc_i2c_xfer.buf = buf;
352	sc->sc_i2c_xfer.len = len;
353	sc->sc_i2c_xfer.flags = flags;
354	sc->sc_i2c_xfer.error = 0;
355
356	/* wait for bus to be idle */
357	for (retries = 100; retries > 0; retries--) {
358		st = dwiic_read(sc, DW_IC_STATUS);
359		if (!(st & DW_IC_STATUS_ACTIVITY))
360			break;
361		DELAY(1000);
362	}
363	DPRINTF(("%s: %s: status 0x%x\n", device_xname(sc->sc_dev), __func__, st));
364	if (st & DW_IC_STATUS_ACTIVITY) {
365		return (1);
366	}
367
368	/* disable controller */
369	dwiic_enable(sc, 0);
370
371	/* set slave address */
372	ic_con = dwiic_read(sc, DW_IC_CON);
373	ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
374	dwiic_write(sc, DW_IC_CON, ic_con);
375	dwiic_write(sc, DW_IC_TAR, addr);
376
377	/* disable interrupts */
378	dwiic_write(sc, DW_IC_INTR_MASK, 0);
379	dwiic_read(sc, DW_IC_CLR_INTR);
380
381	/* enable controller */
382	dwiic_enable(sc, 1);
383
384	/* wait until the controller is ready for commands */
385	if (flags & I2C_F_POLL)
386		DELAY(200);
387	else {
388		mutex_enter(&sc->sc_int_lock);
389		dwiic_read(sc, DW_IC_CLR_INTR);
390		dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY);
391
392		if (cv_timedwait(&sc->sc_int_writewait,
393		    &sc->sc_int_lock, hz / 2) != 0)
394			device_printf(sc->sc_dev,
395			    "timed out waiting for tx_empty intr\n");
396		dwiic_write(sc, DW_IC_INTR_MASK, 0);
397		dwiic_read(sc, DW_IC_CLR_INTR);
398		mutex_exit(&sc->sc_int_lock);
399	}
400
401	/* send our command, one byte at a time */
402	if (cmdlen > 0) {
403		bcmd = (const void *)cmdbuf;
404
405		DPRINTF(("%s: %s: sending cmd (len %zu):", device_xname(sc->sc_dev),
406		    __func__, cmdlen));
407		for (x = 0; x < cmdlen; x++)
408			DPRINTF((" %02x", bcmd[x]));
409		DPRINTF(("\n"));
410
411		tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
412		if (cmdlen > tx_limit) {
413			/* TODO */
414			device_printf(sc->sc_dev, "can't write %zu (> %d)\n",
415			    cmdlen, tx_limit);
416			sc->sc_i2c_xfer.error = 1;
417			return (1);
418		}
419
420		for (x = 0; x < cmdlen; x++) {
421			cmd = bcmd[x];
422			/*
423			 * Generate STOP condition if this is the last
424			 * byte of the transfer.
425			 */
426			if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op))
427				cmd |= DW_IC_DATA_CMD_STOP;
428			dwiic_write(sc, DW_IC_DATA_CMD, cmd);
429		}
430	}
431
432	bdata = (void *)buf;
433	x = readpos = 0;
434	tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
435
436	DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n",
437		device_xname(sc->sc_dev), __func__, len, tx_limit));
438
439	while (x < len) {
440		if (I2C_OP_WRITE_P(op))
441			cmd = bdata[x];
442		else
443			cmd = DW_IC_DATA_CMD_READ;
444
445		/*
446		 * Generate RESTART condition if we're reversing
447		 * direction.
448		 */
449		if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op))
450			cmd |= DW_IC_DATA_CMD_RESTART;
451		/*
452		 * Generate STOP condition on the last byte of the
453		 * transfer.
454		 */
455		if (x == (len - 1) && I2C_OP_STOP_P(op))
456			cmd |= DW_IC_DATA_CMD_STOP;
457
458		dwiic_write(sc, DW_IC_DATA_CMD, cmd);
459
460		tx_limit--;
461		x++;
462
463		/*
464		 * As TXFLR fills up, we need to clear it out by reading all
465		 * available data.
466		 */
467		while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) {
468			DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n",
469			    device_xname(sc->sc_dev), __func__, tx_limit, x));
470
471			if (flags & I2C_F_POLL) {
472				for (retries = 100; retries > 0; retries--) {
473					rx_avail = dwiic_read(sc, DW_IC_RXFLR);
474					if (rx_avail > 0)
475						break;
476					DELAY(50);
477				}
478			} else {
479				mutex_enter(&sc->sc_int_lock);
480				dwiic_read(sc, DW_IC_CLR_INTR);
481				dwiic_write(sc, DW_IC_INTR_MASK,
482				    DW_IC_INTR_RX_FULL);
483
484				if (cv_timedwait(&sc->sc_int_readwait,
485				    &sc->sc_int_lock, hz / 2) != 0)
486					device_printf(sc->sc_dev,
487					    "timed out waiting for "
488					    "rx_full intr\n");
489
490				dwiic_write(sc, DW_IC_INTR_MASK, 0);
491				dwiic_read(sc, DW_IC_CLR_INTR);
492				mutex_exit(&sc->sc_int_lock);
493				rx_avail = dwiic_read(sc, DW_IC_RXFLR);
494			}
495
496			if (rx_avail == 0) {
497				device_printf(sc->sc_dev,
498				    "timed out reading remaining %d\n",
499				    (int)(len - 1 - readpos));
500				sc->sc_i2c_xfer.error = 1;
501				return (1);
502			}
503
504			DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n",
505			    device_xname(sc->sc_dev), __func__, rx_avail,
506			    len - readpos));
507
508			while (rx_avail > 0) {
509				resp = dwiic_read(sc, DW_IC_DATA_CMD);
510				if (readpos < len) {
511					bdata[readpos] = resp;
512					readpos++;
513				}
514				rx_avail--;
515			}
516
517			if (readpos >= len)
518				break;
519
520			DPRINTF(("%s: still need to read %d bytes\n",
521			    device_xname(sc->sc_dev), (int)(len - readpos)));
522			tx_limit = sc->tx_fifo_depth -
523			    dwiic_read(sc, DW_IC_TXFLR);
524		}
525	}
526
527	if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) {
528		if (flags & I2C_F_POLL) {
529			/* wait for bus to be idle */
530			for (retries = 100; retries > 0; retries--) {
531				st = dwiic_read(sc, DW_IC_STATUS);
532				if (!(st & DW_IC_STATUS_ACTIVITY))
533					break;
534				DELAY(1000);
535			}
536			if (st & DW_IC_STATUS_ACTIVITY)
537				device_printf(sc->sc_dev, "timed out waiting "
538				    "for bus idle\n");
539		} else {
540			mutex_enter(&sc->sc_int_lock);
541			dwiic_read(sc, DW_IC_CLR_INTR);
542			dwiic_write(sc, DW_IC_INTR_MASK,
543			    DW_IC_INTR_STOP_DET);
544			if (cv_timedwait(&sc->sc_int_stopwait,
545			    &sc->sc_int_lock, hz / 2) != 0)
546				device_printf(sc->sc_dev, "timed out waiting "
547				    "for stop intr\n");
548			dwiic_write(sc, DW_IC_INTR_MASK, 0);
549			dwiic_read(sc, DW_IC_CLR_INTR);
550			mutex_exit(&sc->sc_int_lock);
551		}
552	}
553
554	return 0;
555}
556
557static uint32_t
558dwiic_read_clear_intrbits(struct dwiic_softc *sc)
559{
560       uint32_t stat;
561
562       stat = dwiic_read(sc, DW_IC_INTR_STAT);
563
564       if (stat & DW_IC_INTR_RX_UNDER)
565	       dwiic_read(sc, DW_IC_CLR_RX_UNDER);
566       if (stat & DW_IC_INTR_RX_OVER)
567	       dwiic_read(sc, DW_IC_CLR_RX_OVER);
568       if (stat & DW_IC_INTR_TX_OVER)
569	       dwiic_read(sc, DW_IC_CLR_TX_OVER);
570       if (stat & DW_IC_INTR_RD_REQ)
571	       dwiic_read(sc, DW_IC_CLR_RD_REQ);
572       if (stat & DW_IC_INTR_TX_ABRT)
573	       dwiic_read(sc, DW_IC_CLR_TX_ABRT);
574       if (stat & DW_IC_INTR_RX_DONE)
575	       dwiic_read(sc, DW_IC_CLR_RX_DONE);
576       if (stat & DW_IC_INTR_ACTIVITY)
577	       dwiic_read(sc, DW_IC_CLR_ACTIVITY);
578       if (stat & DW_IC_INTR_STOP_DET)
579	       dwiic_read(sc, DW_IC_CLR_STOP_DET);
580       if (stat & DW_IC_INTR_START_DET)
581	       dwiic_read(sc, DW_IC_CLR_START_DET);
582       if (stat & DW_IC_INTR_GEN_CALL)
583	       dwiic_read(sc, DW_IC_CLR_GEN_CALL);
584
585       return stat;
586}
587
588int
589dwiic_intr(void *arg)
590{
591	struct dwiic_softc *sc = arg;
592	uint32_t en, stat;
593
594	/*
595	 * Give up if attach hasn't succeeded.  If it failed, nothing
596	 * to do here.  If it is still ongoing and simply hasn't yet
597	 * succeeded, interrupts from the device are masked -- so this
598	 * interrupt must be shared with another driver -- and any
599	 * interrupts applicable to us will be delivered once
600	 * interrupts from the device are unmasked in dwiic_i2c_exec.
601	 */
602	if (!atomic_load_acquire(&sc->sc_attached))
603		return 0;
604
605	en = dwiic_read(sc, DW_IC_ENABLE);
606	/* probably for the other controller */
607	if (!en)
608		return 0;
609
610	stat = dwiic_read_clear_intrbits(sc);
611	DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", device_xname(sc->sc_dev),
612	    __func__, en, stat));
613	if (!(stat & ~DW_IC_INTR_ACTIVITY))
614		return 1;
615
616	if (stat & DW_IC_INTR_TX_ABRT)
617		sc->sc_i2c_xfer.error = 1;
618
619	if (sc->sc_i2c_xfer.flags & I2C_F_POLL)
620		DPRINTF(("%s: %s: intr in poll mode?\n", device_xname(sc->sc_dev),
621		    __func__));
622	else {
623		mutex_enter(&sc->sc_int_lock);
624		if (stat & DW_IC_INTR_RX_FULL) {
625			dwiic_write(sc, DW_IC_INTR_MASK, 0);
626			DPRINTF(("%s: %s: waking up reader\n",
627			    device_xname(sc->sc_dev), __func__));
628			cv_signal(&sc->sc_int_readwait);
629		}
630		if (stat & DW_IC_INTR_TX_EMPTY) {
631			dwiic_write(sc, DW_IC_INTR_MASK, 0);
632			DPRINTF(("%s: %s: waking up writer\n",
633			    device_xname(sc->sc_dev), __func__));
634			cv_signal(&sc->sc_int_writewait);
635		}
636		if (stat & DW_IC_INTR_STOP_DET) {
637			dwiic_write(sc, DW_IC_INTR_MASK, 0);
638			DPRINTF(("%s: %s: waking up stopper\n",
639			    device_xname(sc->sc_dev), __func__));
640			cv_signal(&sc->sc_int_stopwait);
641		}
642		mutex_exit(&sc->sc_int_lock);
643	}
644
645	return 1;
646}
647