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", ®, 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(®[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