xref: /openbsd-src/sys/arch/riscv64/dev/mpfiic.c (revision 9bf0468d61eef72cbfd1a16669a327f925621c12)
1*9bf0468dSvisa /*	$OpenBSD: mpfiic.c,v 1.1 2022/02/16 13:07:36 visa Exp $	*/
2*9bf0468dSvisa 
3*9bf0468dSvisa /*
4*9bf0468dSvisa  * Copyright (c) 2022 Visa Hankala
5*9bf0468dSvisa  *
6*9bf0468dSvisa  * Permission to use, copy, modify, and distribute this software for any
7*9bf0468dSvisa  * purpose with or without fee is hereby granted, provided that the above
8*9bf0468dSvisa  * copyright notice and this permission notice appear in all copies.
9*9bf0468dSvisa  *
10*9bf0468dSvisa  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*9bf0468dSvisa  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*9bf0468dSvisa  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*9bf0468dSvisa  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*9bf0468dSvisa  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*9bf0468dSvisa  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*9bf0468dSvisa  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*9bf0468dSvisa  */
18*9bf0468dSvisa 
19*9bf0468dSvisa /*
20*9bf0468dSvisa  * Driver for PolarFire SoC MSS I2C controller.
21*9bf0468dSvisa  */
22*9bf0468dSvisa 
23*9bf0468dSvisa #include <sys/param.h>
24*9bf0468dSvisa #include <sys/systm.h>
25*9bf0468dSvisa #include <sys/device.h>
26*9bf0468dSvisa #include <sys/malloc.h>
27*9bf0468dSvisa 
28*9bf0468dSvisa #include <machine/bus.h>
29*9bf0468dSvisa #include <machine/fdt.h>
30*9bf0468dSvisa 
31*9bf0468dSvisa #define _I2C_PRIVATE
32*9bf0468dSvisa #include <dev/i2c/i2cvar.h>
33*9bf0468dSvisa 
34*9bf0468dSvisa #include <dev/ofw/fdt.h>
35*9bf0468dSvisa #include <dev/ofw/openfirm.h>
36*9bf0468dSvisa #include <dev/ofw/ofw_clock.h>
37*9bf0468dSvisa #include <dev/ofw/ofw_misc.h>
38*9bf0468dSvisa 
39*9bf0468dSvisa #define I2C_CTRL		0x0000
40*9bf0468dSvisa #define  I2C_CTRL_CR2			(1 << 7)
41*9bf0468dSvisa #define  I2C_CTRL_ENS1			(1 << 6)
42*9bf0468dSvisa #define  I2C_CTRL_STA			(1 << 5)
43*9bf0468dSvisa #define  I2C_CTRL_STO			(1 << 4)
44*9bf0468dSvisa #define  I2C_CTRL_SI			(1 << 3)
45*9bf0468dSvisa #define  I2C_CTRL_AA			(1 << 2)
46*9bf0468dSvisa #define  I2C_CTRL_CR1			(1 << 1)
47*9bf0468dSvisa #define  I2C_CTRL_CR0			(1 << 0)
48*9bf0468dSvisa #define I2C_STATUS		0x0004
49*9bf0468dSvisa #define I2C_DATA		0x0008
50*9bf0468dSvisa #define I2C_SLAVE0ADR		0x000c
51*9bf0468dSvisa #define I2C_SMBUS		0x0010
52*9bf0468dSvisa #define I2C_FREQ		0x0014
53*9bf0468dSvisa #define I2C_GLITCHREG		0x0018
54*9bf0468dSvisa #define I2C_SLAVE1ADR		0x001c
55*9bf0468dSvisa 
56*9bf0468dSvisa #define I2C_STATUS_START		0x08
57*9bf0468dSvisa #define I2C_STATUS_RESTART		0x10
58*9bf0468dSvisa #define I2C_STATUS_SLAW_ACK		0x18
59*9bf0468dSvisa #define I2C_STATUS_DATAW_ACK		0x28
60*9bf0468dSvisa #define I2C_STATUS_LOSTARB		0x38
61*9bf0468dSvisa #define I2C_STATUS_SLAR_ACK		0x40
62*9bf0468dSvisa #define I2C_STATUS_DATAR_ACK		0x50
63*9bf0468dSvisa #define I2C_STATUS_DATAR_NACK		0x58
64*9bf0468dSvisa #define I2C_STATUS_IDLE			0xf8
65*9bf0468dSvisa 
66*9bf0468dSvisa struct mpfiic_softc {
67*9bf0468dSvisa 	struct device		sc_dev;
68*9bf0468dSvisa 	bus_space_tag_t		sc_iot;
69*9bf0468dSvisa 	bus_space_handle_t	sc_ioh;
70*9bf0468dSvisa 	int			sc_node;
71*9bf0468dSvisa 
72*9bf0468dSvisa 	struct i2c_bus		sc_i2c_bus;
73*9bf0468dSvisa 	struct i2c_controller	sc_i2c_tag;
74*9bf0468dSvisa 	struct rwlock		sc_i2c_lock;
75*9bf0468dSvisa 
76*9bf0468dSvisa 	uint32_t		sc_bus_freq;		/* in Hz */
77*9bf0468dSvisa 	uint8_t			sc_ctrl;
78*9bf0468dSvisa 	uint8_t			sc_start_sent;
79*9bf0468dSvisa };
80*9bf0468dSvisa 
81*9bf0468dSvisa #define HREAD4(sc, reg) \
82*9bf0468dSvisa 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
83*9bf0468dSvisa #define HWRITE4(sc, reg, val) \
84*9bf0468dSvisa 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
85*9bf0468dSvisa 
86*9bf0468dSvisa int	mpfiic_match(struct device *, void *, void*);
87*9bf0468dSvisa void	mpfiic_attach(struct device *, struct device *, void *);
88*9bf0468dSvisa 
89*9bf0468dSvisa int	mpfiic_i2c_acquire_bus(void *, int);
90*9bf0468dSvisa void	mpfiic_i2c_release_bus(void *, int);
91*9bf0468dSvisa int	mpfiic_i2c_send_start(void *, int);
92*9bf0468dSvisa int	mpfiic_i2c_send_stop(void *, int);
93*9bf0468dSvisa int	mpfiic_i2c_initiate_xfer(void *, i2c_addr_t, int);
94*9bf0468dSvisa int	mpfiic_i2c_read_byte(void *, uint8_t *, int);
95*9bf0468dSvisa int	mpfiic_i2c_write_byte(void *, uint8_t, int);
96*9bf0468dSvisa void	mpfiic_i2c_scan(struct device *, struct i2cbus_attach_args *, void *);
97*9bf0468dSvisa 
98*9bf0468dSvisa int	mpfiic_wait(struct mpfiic_softc *, uint8_t);
99*9bf0468dSvisa 
100*9bf0468dSvisa const struct cfattach mpfiic_ca = {
101*9bf0468dSvisa 	sizeof(struct mpfiic_softc), mpfiic_match, mpfiic_attach
102*9bf0468dSvisa };
103*9bf0468dSvisa 
104*9bf0468dSvisa struct cfdriver mpfiic_cd = {
105*9bf0468dSvisa 	NULL, "mpfiic", DV_DULL
106*9bf0468dSvisa };
107*9bf0468dSvisa 
108*9bf0468dSvisa static struct {
109*9bf0468dSvisa 	uint32_t	div;
110*9bf0468dSvisa 	uint32_t	cr;
111*9bf0468dSvisa } mpfiic_clk_divs[] = {
112*9bf0468dSvisa #ifdef notused
113*9bf0468dSvisa 	/* BCLK */
114*9bf0468dSvisa 	{ 8,	I2C_CTRL_CR2 | I2C_CTRL_CR1 | I2C_CTRL_CR0 },
115*9bf0468dSvisa #endif
116*9bf0468dSvisa 	/* PCLK */
117*9bf0468dSvisa 	{ 60,	I2C_CTRL_CR2 | I2C_CTRL_CR1 },
118*9bf0468dSvisa 	{ 120,	I2C_CTRL_CR2 | I2C_CTRL_CR0 },
119*9bf0468dSvisa 	{ 160,	I2C_CTRL_CR1 | I2C_CTRL_CR0 },
120*9bf0468dSvisa 	{ 192,	I2C_CTRL_CR1 },
121*9bf0468dSvisa 	{ 224,	I2C_CTRL_CR0 },
122*9bf0468dSvisa 	{ 256,	0 },
123*9bf0468dSvisa 	{ 960,	I2C_CTRL_CR2 },
124*9bf0468dSvisa };
125*9bf0468dSvisa 
126*9bf0468dSvisa int
mpfiic_match(struct device * parent,void * match,void * aux)127*9bf0468dSvisa mpfiic_match(struct device *parent, void *match, void *aux)
128*9bf0468dSvisa {
129*9bf0468dSvisa 	struct fdt_attach_args *faa = aux;
130*9bf0468dSvisa 
131*9bf0468dSvisa 	if (faa->fa_nreg < 1)
132*9bf0468dSvisa 		return 0;
133*9bf0468dSvisa 	return OF_is_compatible(faa->fa_node, "microchip,mpfs-i2c");
134*9bf0468dSvisa }
135*9bf0468dSvisa 
136*9bf0468dSvisa void
mpfiic_attach(struct device * parent,struct device * self,void * aux)137*9bf0468dSvisa mpfiic_attach(struct device *parent, struct device *self, void *aux)
138*9bf0468dSvisa {
139*9bf0468dSvisa 	struct i2cbus_attach_args iba;
140*9bf0468dSvisa 	struct fdt_attach_args *faa = aux;
141*9bf0468dSvisa 	struct mpfiic_softc *sc = (struct mpfiic_softc *)self;
142*9bf0468dSvisa 	uint32_t i, bus_freq, clock_freq;
143*9bf0468dSvisa 
144*9bf0468dSvisa 	sc->sc_node = faa->fa_node;
145*9bf0468dSvisa 	sc->sc_iot = faa->fa_iot;
146*9bf0468dSvisa 
147*9bf0468dSvisa 	clock_freq = clock_get_frequency(sc->sc_node, NULL);
148*9bf0468dSvisa 	bus_freq = OF_getpropint(sc->sc_node, "clock-frequency", 100000);
149*9bf0468dSvisa 
150*9bf0468dSvisa 	/* Determine clock divider, assumes PCLK. */
151*9bf0468dSvisa 	for (i = 0; i < nitems(mpfiic_clk_divs) - 1; i++) {
152*9bf0468dSvisa 		if (clock_freq / mpfiic_clk_divs[i].div <= bus_freq)
153*9bf0468dSvisa 			break;
154*9bf0468dSvisa 	}
155*9bf0468dSvisa 	sc->sc_bus_freq = clock_freq / mpfiic_clk_divs[i].div;
156*9bf0468dSvisa 	sc->sc_ctrl = mpfiic_clk_divs[i].cr | I2C_CTRL_ENS1;
157*9bf0468dSvisa 
158*9bf0468dSvisa 	if (sc->sc_bus_freq == 0) {
159*9bf0468dSvisa 		printf(": invalid bus frequency\n");
160*9bf0468dSvisa 		return;
161*9bf0468dSvisa 	}
162*9bf0468dSvisa 
163*9bf0468dSvisa 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
164*9bf0468dSvisa 	    0, &sc->sc_ioh) != 0) {
165*9bf0468dSvisa 		printf(": can't map registers\n");
166*9bf0468dSvisa 		return;
167*9bf0468dSvisa 	}
168*9bf0468dSvisa 
169*9bf0468dSvisa 	clock_enable_all(sc->sc_node);
170*9bf0468dSvisa 
171*9bf0468dSvisa 	/* Initialize the device. */
172*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
173*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, 0);
174*9bf0468dSvisa 
175*9bf0468dSvisa 	/* Disable slave address comparison. */
176*9bf0468dSvisa 	HWRITE4(sc, I2C_SLAVE0ADR, 0);
177*9bf0468dSvisa 	HWRITE4(sc, I2C_SLAVE1ADR, 0);
178*9bf0468dSvisa 
179*9bf0468dSvisa 	/* Disable SMBus logic, operate in standard I2C mode. */
180*9bf0468dSvisa 	HWRITE4(sc, I2C_SMBUS, 0);
181*9bf0468dSvisa 
182*9bf0468dSvisa 	printf("\n");
183*9bf0468dSvisa 
184*9bf0468dSvisa 	rw_init(&sc->sc_i2c_lock, "iiclk");
185*9bf0468dSvisa 	sc->sc_i2c_tag.ic_cookie = sc;
186*9bf0468dSvisa 	sc->sc_i2c_tag.ic_acquire_bus = mpfiic_i2c_acquire_bus;
187*9bf0468dSvisa 	sc->sc_i2c_tag.ic_release_bus = mpfiic_i2c_release_bus;
188*9bf0468dSvisa 	sc->sc_i2c_tag.ic_send_start = mpfiic_i2c_send_start;
189*9bf0468dSvisa 	sc->sc_i2c_tag.ic_send_stop = mpfiic_i2c_send_stop;
190*9bf0468dSvisa 	sc->sc_i2c_tag.ic_initiate_xfer = mpfiic_i2c_initiate_xfer;
191*9bf0468dSvisa 	sc->sc_i2c_tag.ic_read_byte = mpfiic_i2c_read_byte;
192*9bf0468dSvisa 	sc->sc_i2c_tag.ic_write_byte = mpfiic_i2c_write_byte;
193*9bf0468dSvisa 
194*9bf0468dSvisa 	memset(&iba, 0, sizeof(iba));
195*9bf0468dSvisa 	iba.iba_name = "iic";
196*9bf0468dSvisa 	iba.iba_tag = &sc->sc_i2c_tag;
197*9bf0468dSvisa 	iba.iba_bus_scan = mpfiic_i2c_scan;
198*9bf0468dSvisa 	iba.iba_bus_scan_arg = &sc->sc_node;
199*9bf0468dSvisa 	config_found(self, &iba, iicbus_print);
200*9bf0468dSvisa 
201*9bf0468dSvisa 	sc->sc_i2c_bus.ib_node = faa->fa_node;
202*9bf0468dSvisa 	sc->sc_i2c_bus.ib_ic = &sc->sc_i2c_tag;
203*9bf0468dSvisa 	i2c_register(&sc->sc_i2c_bus);
204*9bf0468dSvisa }
205*9bf0468dSvisa 
206*9bf0468dSvisa int
mpfiic_i2c_acquire_bus(void * arg,int flags)207*9bf0468dSvisa mpfiic_i2c_acquire_bus(void *arg, int flags)
208*9bf0468dSvisa {
209*9bf0468dSvisa 	struct mpfiic_softc *sc = arg;
210*9bf0468dSvisa 
211*9bf0468dSvisa 	if (cold || (flags & I2C_F_POLL))
212*9bf0468dSvisa 		return 0;
213*9bf0468dSvisa 
214*9bf0468dSvisa 	return rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR);
215*9bf0468dSvisa }
216*9bf0468dSvisa 
217*9bf0468dSvisa void
mpfiic_i2c_release_bus(void * arg,int flags)218*9bf0468dSvisa mpfiic_i2c_release_bus(void *arg, int flags)
219*9bf0468dSvisa {
220*9bf0468dSvisa 	struct mpfiic_softc *sc = arg;
221*9bf0468dSvisa 
222*9bf0468dSvisa 	if (cold || (flags & I2C_F_POLL))
223*9bf0468dSvisa 		return;
224*9bf0468dSvisa 
225*9bf0468dSvisa 	rw_exit(&sc->sc_i2c_lock);
226*9bf0468dSvisa }
227*9bf0468dSvisa 
228*9bf0468dSvisa int
mpfiic_i2c_send_start(void * cookie,int flags)229*9bf0468dSvisa mpfiic_i2c_send_start(void *cookie, int flags)
230*9bf0468dSvisa {
231*9bf0468dSvisa 	struct mpfiic_softc *sc = cookie;
232*9bf0468dSvisa 	int error;
233*9bf0468dSvisa 	uint8_t nstatus;
234*9bf0468dSvisa 
235*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STA);
236*9bf0468dSvisa 
237*9bf0468dSvisa 	if (sc->sc_start_sent)
238*9bf0468dSvisa 		nstatus = I2C_STATUS_RESTART;
239*9bf0468dSvisa 	else
240*9bf0468dSvisa 		nstatus = I2C_STATUS_START;
241*9bf0468dSvisa 	error = mpfiic_wait(sc, nstatus);
242*9bf0468dSvisa 	if (error != 0)
243*9bf0468dSvisa 		return error;
244*9bf0468dSvisa 
245*9bf0468dSvisa 	sc->sc_start_sent = 1;
246*9bf0468dSvisa 
247*9bf0468dSvisa 	return 0;
248*9bf0468dSvisa }
249*9bf0468dSvisa 
250*9bf0468dSvisa int
mpfiic_i2c_send_stop(void * cookie,int flags)251*9bf0468dSvisa mpfiic_i2c_send_stop(void *cookie, int flags)
252*9bf0468dSvisa {
253*9bf0468dSvisa 	struct mpfiic_softc *sc = cookie;
254*9bf0468dSvisa 
255*9bf0468dSvisa 	sc->sc_start_sent = 0;
256*9bf0468dSvisa 
257*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STO);
258*9bf0468dSvisa 
259*9bf0468dSvisa 	/* Let a few bus clock cycles pass. */
260*9bf0468dSvisa 	delay(4 * 1000000 / sc->sc_bus_freq);
261*9bf0468dSvisa 
262*9bf0468dSvisa 	/* Disable the device. This resets the state machine. */
263*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, 0);
264*9bf0468dSvisa 
265*9bf0468dSvisa 	return 0;
266*9bf0468dSvisa }
267*9bf0468dSvisa 
268*9bf0468dSvisa int
mpfiic_i2c_initiate_xfer(void * cookie,i2c_addr_t addr,int flags)269*9bf0468dSvisa mpfiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
270*9bf0468dSvisa {
271*9bf0468dSvisa 	struct mpfiic_softc *sc = cookie;
272*9bf0468dSvisa 	int error;
273*9bf0468dSvisa 	uint8_t mode, nstatus;
274*9bf0468dSvisa 
275*9bf0468dSvisa 	if (addr >= 0x80)
276*9bf0468dSvisa 		return EINVAL;
277*9bf0468dSvisa 
278*9bf0468dSvisa 	error = mpfiic_i2c_send_start(sc, flags);
279*9bf0468dSvisa 	if (error != 0)
280*9bf0468dSvisa 		return error;
281*9bf0468dSvisa 
282*9bf0468dSvisa 	if (flags & I2C_F_READ) {
283*9bf0468dSvisa 		mode = 0x01;
284*9bf0468dSvisa 		nstatus = I2C_STATUS_SLAR_ACK;
285*9bf0468dSvisa 	} else {
286*9bf0468dSvisa 		mode = 0x00;
287*9bf0468dSvisa 		nstatus = I2C_STATUS_SLAW_ACK;
288*9bf0468dSvisa 	}
289*9bf0468dSvisa 
290*9bf0468dSvisa 	HWRITE4(sc, I2C_DATA, (addr << 1) | mode);
291*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
292*9bf0468dSvisa 
293*9bf0468dSvisa 	return mpfiic_wait(sc, nstatus);
294*9bf0468dSvisa }
295*9bf0468dSvisa 
296*9bf0468dSvisa int
mpfiic_i2c_read_byte(void * cookie,uint8_t * datap,int flags)297*9bf0468dSvisa mpfiic_i2c_read_byte(void *cookie, uint8_t *datap, int flags)
298*9bf0468dSvisa {
299*9bf0468dSvisa 	struct mpfiic_softc *sc = cookie;
300*9bf0468dSvisa 	int error;
301*9bf0468dSvisa 	uint8_t ack = 0, nstatus;
302*9bf0468dSvisa 
303*9bf0468dSvisa 	if ((flags & I2C_F_LAST) == 0)
304*9bf0468dSvisa 		ack = I2C_CTRL_AA;
305*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | ack);
306*9bf0468dSvisa 
307*9bf0468dSvisa 	if (flags & I2C_F_LAST)
308*9bf0468dSvisa 		nstatus = I2C_STATUS_DATAR_NACK;
309*9bf0468dSvisa 	else
310*9bf0468dSvisa 		nstatus = I2C_STATUS_DATAR_ACK;
311*9bf0468dSvisa 	error = mpfiic_wait(sc, nstatus);
312*9bf0468dSvisa 	if (error != 0)
313*9bf0468dSvisa 		return error;
314*9bf0468dSvisa 
315*9bf0468dSvisa 	*datap = HREAD4(sc, I2C_DATA);
316*9bf0468dSvisa 
317*9bf0468dSvisa 	if (flags & I2C_F_STOP)
318*9bf0468dSvisa 		error = mpfiic_i2c_send_stop(sc, flags);
319*9bf0468dSvisa 
320*9bf0468dSvisa 	return error;
321*9bf0468dSvisa }
322*9bf0468dSvisa 
323*9bf0468dSvisa int
mpfiic_i2c_write_byte(void * cookie,uint8_t data,int flags)324*9bf0468dSvisa mpfiic_i2c_write_byte(void *cookie, uint8_t data, int flags)
325*9bf0468dSvisa {
326*9bf0468dSvisa 	struct mpfiic_softc *sc = cookie;
327*9bf0468dSvisa 	int error;
328*9bf0468dSvisa 
329*9bf0468dSvisa 	HWRITE4(sc, I2C_DATA, data);
330*9bf0468dSvisa 	HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
331*9bf0468dSvisa 
332*9bf0468dSvisa 	error = mpfiic_wait(sc, I2C_STATUS_DATAW_ACK);
333*9bf0468dSvisa 	if (error != 0)
334*9bf0468dSvisa 		return error;
335*9bf0468dSvisa 
336*9bf0468dSvisa 	if (flags & I2C_F_STOP)
337*9bf0468dSvisa 		error = mpfiic_i2c_send_stop(sc, flags);
338*9bf0468dSvisa 
339*9bf0468dSvisa 	return error;
340*9bf0468dSvisa }
341*9bf0468dSvisa 
342*9bf0468dSvisa void
mpfiic_i2c_scan(struct device * self,struct i2cbus_attach_args * iba,void * arg)343*9bf0468dSvisa mpfiic_i2c_scan(struct device *self, struct i2cbus_attach_args *iba, void *arg)
344*9bf0468dSvisa {
345*9bf0468dSvisa 	struct i2c_attach_args ia;
346*9bf0468dSvisa 	char status[32];
347*9bf0468dSvisa 	char *compat;
348*9bf0468dSvisa 	uint32_t reg[1];
349*9bf0468dSvisa 	int iba_node = *(int *)arg;
350*9bf0468dSvisa 	int len, node;
351*9bf0468dSvisa 
352*9bf0468dSvisa 	for (node = OF_child(iba_node); node != 0; node = OF_peer(node)) {
353*9bf0468dSvisa 		memset(status, 0, sizeof(status));
354*9bf0468dSvisa 		if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
355*9bf0468dSvisa 		    strcmp(status, "disabled") == 0)
356*9bf0468dSvisa 			continue;
357*9bf0468dSvisa 
358*9bf0468dSvisa 		memset(reg, 0, sizeof(reg));
359*9bf0468dSvisa 		if (OF_getprop(node, "reg", &reg, sizeof(reg)) != sizeof(reg))
360*9bf0468dSvisa 			continue;
361*9bf0468dSvisa 
362*9bf0468dSvisa 		len = OF_getproplen(node, "compatible");
363*9bf0468dSvisa 		if (len <= 0)
364*9bf0468dSvisa 			continue;
365*9bf0468dSvisa 
366*9bf0468dSvisa 		compat = malloc(len, M_TEMP, M_WAITOK);
367*9bf0468dSvisa 		OF_getprop(node, "compatible", compat, len);
368*9bf0468dSvisa 
369*9bf0468dSvisa 		memset(&ia, 0, sizeof(ia));
370*9bf0468dSvisa 		ia.ia_tag = iba->iba_tag;
371*9bf0468dSvisa 		ia.ia_addr = bemtoh32(&reg[0]);
372*9bf0468dSvisa 		ia.ia_name = compat;
373*9bf0468dSvisa 		ia.ia_namelen = len;
374*9bf0468dSvisa 		ia.ia_cookie = &node;
375*9bf0468dSvisa 		config_found(self, &ia, iic_print);
376*9bf0468dSvisa 
377*9bf0468dSvisa 		free(compat, M_TEMP, len);
378*9bf0468dSvisa 	}
379*9bf0468dSvisa }
380*9bf0468dSvisa 
381*9bf0468dSvisa int
mpfiic_wait(struct mpfiic_softc * sc,uint8_t nstatus)382*9bf0468dSvisa mpfiic_wait(struct mpfiic_softc *sc, uint8_t nstatus)
383*9bf0468dSvisa {
384*9bf0468dSvisa 	int timeout;
385*9bf0468dSvisa 	uint8_t ctrl, status;
386*9bf0468dSvisa 
387*9bf0468dSvisa 	for (timeout = 100000; timeout > 0; timeout--) {
388*9bf0468dSvisa 		ctrl = HREAD4(sc, I2C_CTRL);
389*9bf0468dSvisa 		if (ctrl & I2C_CTRL_SI)
390*9bf0468dSvisa 			break;
391*9bf0468dSvisa 		delay(1);
392*9bf0468dSvisa 	}
393*9bf0468dSvisa 	if (timeout == 0)
394*9bf0468dSvisa 		return ETIMEDOUT;
395*9bf0468dSvisa 
396*9bf0468dSvisa 	status = HREAD4(sc, I2C_STATUS);
397*9bf0468dSvisa 	if (status != nstatus)
398*9bf0468dSvisa 		return EIO;
399*9bf0468dSvisa 
400*9bf0468dSvisa 	return 0;
401*9bf0468dSvisa }
402