1 /*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2025 Poul-Henning Kamp <phk@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 * QualComm GENI I2C controller
28 *
29 * The GENI is actually a multi-protocol serial controller, so a lot of
30 * this can probably be shared if we ever get to those protocols.
31 *
32 * The best open "documentation" of the hardware is the Linux device driver
33 * from which much was learned, and we tip our hat to the authors of it.
34 */
35
36 #include <sys/cdefs.h>
37
38 #include "opt_acpi.h"
39
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/endian.h>
44 #include <sys/time.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/sysctl.h>
48 #include <sys/sx.h>
49 #include <sys/bus.h>
50
51 #include <machine/bus.h>
52 #include <sys/rman.h>
53
54 #include <dev/iicbus/iicbus.h>
55 #include <dev/iicbus/iiconf.h>
56
57 #include <dev/iicbus/controller/qcom/geni_iic_var.h>
58
59 #define GENI_ALL_REGISTERS(THIS_MACRO) \
60 THIS_MACRO(GENI_FORCE_DEFAULT_REG, 0x020) \
61 THIS_MACRO(GENI_OUTPUT_CTRL, 0x024) \
62 THIS_MACRO(GENI_STATUS, 0x040) \
63 THIS_MACRO(GENI_SER_M_CLK_CFG, 0x048) \
64 THIS_MACRO(GENI_SER_S_CLK_CFG, 0x04c) \
65 THIS_MACRO(GENI_IF_DISABLE_RO, 0x064) \
66 THIS_MACRO(GENI_FW_REVISION_RO, 0x068) \
67 THIS_MACRO(GENI_CLK_SEL, 0x07c) \
68 THIS_MACRO(GENI_CFG_SEQ_START, 0x084) \
69 THIS_MACRO(GENI_BYTE_GRANULARITY, 0x254) \
70 THIS_MACRO(GENI_DMA_MODE_EN, 0x258) \
71 THIS_MACRO(GENI_TX_PACKING_CFG0, 0x260) \
72 THIS_MACRO(GENI_TX_PACKING_CFG1, 0x264) \
73 THIS_MACRO(GENI_I2C_TX_TRANS_LEN, 0x26c) \
74 THIS_MACRO(GENI_I2C_RX_TRANS_LEN, 0x270) \
75 THIS_MACRO(GENI_I2C_SCL_COUNTERS, 0x278) \
76 THIS_MACRO(GENI_RX_PACKING_CFG0, 0x284) \
77 THIS_MACRO(GENI_RX_PACKING_CFG1, 0x288) \
78 THIS_MACRO(GENI_M_CMD0, 0x600) \
79 THIS_MACRO(GENI_M_CMD_CTRL_REG, 0x604) \
80 THIS_MACRO(GENI_M_IRQ_STATUS, 0x610) \
81 THIS_MACRO(GENI_M_IRQ_EN, 0x614) \
82 THIS_MACRO(GENI_M_IRQ_CLEAR, 0x618) \
83 THIS_MACRO(GENI_M_IRQ_EN_SET, 0x61c) \
84 THIS_MACRO(GENI_M_IRQ_EN_CLEAR, 0x620) \
85 THIS_MACRO(GENI_S_CMD0, 0x630) \
86 THIS_MACRO(GENI_S_CMD_CTRL_REG, 0x634) \
87 THIS_MACRO(GENI_S_IRQ_STATUS, 0x640) \
88 THIS_MACRO(GENI_S_IRQ_EN, 0x644) \
89 THIS_MACRO(GENI_S_IRQ_CLEAR, 0x648) \
90 THIS_MACRO(GENI_S_IRQ_EN_SET, 0x64c) \
91 THIS_MACRO(GENI_S_IRQ_EN_CLEAR, 0x650) \
92 THIS_MACRO(GENI_TX_FIFOn, 0x700) \
93 THIS_MACRO(GENI_RX_FIFOn, 0x780) \
94 THIS_MACRO(GENI_TX_FIFO_STATUS, 0x800) \
95 THIS_MACRO(GENI_RX_FIFO_STATUS, 0x804) \
96 THIS_MACRO(GENI_TX_WATERMARK_REG, 0x80c) \
97 THIS_MACRO(GENI_RX_WATERMARK_REG, 0x810) \
98 THIS_MACRO(GENI_RX_RFR_WATERMARK_REG, 0x814) \
99 THIS_MACRO(GENI_IOS, 0x908) \
100 THIS_MACRO(GENI_M_GP_LENGTH, 0x910) \
101 THIS_MACRO(GENI_S_GP_LENGTH, 0x914) \
102 THIS_MACRO(GENI_DMA_TX_IRQ_STAT, 0xc40) \
103 THIS_MACRO(GENI_DMA_TX_IRQ_CLR, 0xc44) \
104 THIS_MACRO(GENI_DMA_TX_IRQ_EN, 0xc48) \
105 THIS_MACRO(GENI_DMA_TX_IRQ_EN_CLR, 0xc4c) \
106 THIS_MACRO(GENI_DMA_TX_IRQ_EN_SET, 0xc50) \
107 THIS_MACRO(GENI_DMA_TX_FSM_RST, 0xc58) \
108 THIS_MACRO(GENI_DMA_RX_IRQ_STAT, 0xd40) \
109 THIS_MACRO(GENI_DMA_RX_IRQ_CLR, 0xd44) \
110 THIS_MACRO(GENI_DMA_RX_IRQ_EN, 0xd48) \
111 THIS_MACRO(GENI_DMA_RX_IRQ_EN_CLR, 0xd4c) \
112 THIS_MACRO(GENI_DMA_RX_IRQ_EN_SET, 0xd50) \
113 THIS_MACRO(GENI_DMA_RX_LEN_IN, 0xd54) \
114 THIS_MACRO(GENI_DMA_RX_FSM_RST, 0xd58) \
115 THIS_MACRO(GENI_IRQ_EN, 0xe1c) \
116 THIS_MACRO(GENI_HW_PARAM_0, 0xe24) \
117 THIS_MACRO(GENI_HW_PARAM_1, 0xe28)
118
119 enum geni_registers {
120 #define ITER_MACRO(name, offset) name = offset,
121 GENI_ALL_REGISTERS(ITER_MACRO)
122 #undef ITER_MACRO
123 };
124
125 #define RD(sc, reg) bus_read_4((sc)->regs_res, reg)
126 #define WR(sc, reg, val) bus_write_4((sc)->regs_res, reg, val)
127
128 static void
geni_dump_regs(geniiic_softc_t * sc)129 geni_dump_regs(geniiic_softc_t *sc)
130 {
131 device_printf(sc->dev, "Register Dump\n");
132 #define DUMP_MACRO(name, offset) \
133 device_printf(sc->dev, \
134 " %08x %04x " #name "\n", \
135 RD(sc, offset), offset);
136 GENI_ALL_REGISTERS(DUMP_MACRO)
137 #undef DUMP_MACRO
138 }
139
140 static unsigned geniiic_debug_units = 0;
141
142 static SYSCTL_NODE(_hw, OID_AUTO, geniiic, CTLFLAG_RW, 0, "GENI I2C");
143 SYSCTL_INT(_hw_geniiic, OID_AUTO, debug_units, CTLFLAG_RWTUN,
144 &geniiic_debug_units, 1, "Bitmask of units to debug");
145
146
147 static driver_filter_t geniiic_intr;
148
149 static int
geniiic_intr(void * cookie)150 geniiic_intr(void *cookie)
151 {
152 uint32_t m_status, rx_fifo_status;
153 int retval = FILTER_STRAY;
154 geniiic_softc_t *sc = cookie;
155
156 mtx_lock_spin(&sc->intr_lock);
157 m_status = RD(sc, GENI_M_IRQ_STATUS);
158
159 rx_fifo_status = RD(sc, GENI_RX_FIFO_STATUS);
160 if (sc->rx_buf != NULL && rx_fifo_status & 0x3f) {
161
162 // Number of whole FIFO words, each 4 bytes
163 unsigned gotlen = (((rx_fifo_status & 0x3f) << 2)-1) * 4;
164
165 // Valid bytes in the last FIFO word
166 // (Field is 3 bits, we'll only ever see 0…3)
167 gotlen += (rx_fifo_status >> 28) & 0x7;
168
169 unsigned cnt;
170 for (cnt = 0; cnt < (rx_fifo_status & 0x3f); cnt++) {
171 uint32_t data = RD(sc, GENI_RX_FIFOn);
172 unsigned u;
173 for (u = 0; u < 4 && sc->rx_len && gotlen; u++) {
174 *sc->rx_buf++ = data & 0xff;
175 data >>= 8;
176 sc->rx_len--;
177 gotlen--;
178 }
179 }
180 }
181 if (m_status & (1<<26)) {
182 WR(sc, GENI_M_IRQ_CLEAR, (1<<26));
183 retval = FILTER_HANDLED;
184 }
185
186 if (m_status & (1<<0)) {
187 sc->rx_complete = true;
188 WR(sc, GENI_M_IRQ_EN_CLEAR, (1<<0));
189 WR(sc, GENI_M_IRQ_EN_CLEAR, (1<<26));
190 WR(sc, GENI_M_IRQ_CLEAR, (1<<0));
191 wakeup(sc);
192 retval = FILTER_HANDLED;
193 }
194 sc->cmd_status = m_status;
195
196 if (sc->rx_buf == NULL) {
197 device_printf(sc->dev,
198 "Interrupt m_stat %x rx_fifo_status %x retval %d\n",
199 m_status, rx_fifo_status, retval);
200 WR(sc, GENI_M_IRQ_EN, 0);
201 WR(sc, GENI_M_IRQ_CLEAR, m_status);
202 device_printf(sc->dev,
203 "Interrupt M_IRQ_STATUS 0x%x M_IRQ_EN 0x%x\n",
204 RD(sc, GENI_M_IRQ_STATUS), RD(sc, GENI_M_IRQ_EN));
205 device_printf(sc->dev,
206 "Interrupt S_IRQ_STATUS 0x%x S_IRQ_EN 0x%x\n",
207 RD(sc, GENI_S_IRQ_STATUS), RD(sc, GENI_S_IRQ_EN));
208 device_printf(sc->dev,
209 "Interrupt DMA_TX_IRQ_STAT 0x%x DMA_RX_IRQ_STAT 0x%x\n",
210 RD(sc, GENI_DMA_TX_IRQ_STAT), RD(sc, GENI_DMA_RX_IRQ_STAT));
211 device_printf(sc->dev,
212 "Interrupt DMA_TX_IRQ_EN 0x%x DMA_RX_IRQ_EN 0x%x\n",
213 RD(sc, GENI_DMA_TX_IRQ_EN), RD(sc, GENI_DMA_RX_IRQ_EN));
214 WR(sc, GENI_DMA_TX_IRQ_EN_CLR, RD(sc, GENI_DMA_TX_IRQ_STAT));
215 WR(sc, GENI_DMA_TX_IRQ_CLR, RD(sc, GENI_DMA_TX_IRQ_STAT));
216 WR(sc, GENI_DMA_RX_IRQ_EN_CLR, RD(sc, GENI_DMA_RX_IRQ_STAT));
217 WR(sc, GENI_DMA_RX_IRQ_CLR, RD(sc, GENI_DMA_RX_IRQ_STAT));
218 }
219 mtx_unlock_spin(&sc->intr_lock);
220 return(retval);
221 }
222
223 static int
geniiic_wait_m_ireq(geniiic_softc_t * sc,uint32_t bits)224 geniiic_wait_m_ireq(geniiic_softc_t *sc, uint32_t bits)
225 {
226 uint32_t status;
227 int timeout;
228
229 for (timeout = 0; timeout < 10000; timeout++) {
230 status = RD(sc, GENI_M_IRQ_STATUS);
231 if (status & bits) {
232 return (0);
233 }
234 DELAY(10);
235 }
236 return (IIC_ETIMEOUT);
237 }
238
239 static int
geniiic_read(geniiic_softc_t * sc,uint8_t slave,uint8_t * buf,uint16_t len,bool nonfinal)240 geniiic_read(geniiic_softc_t *sc,
241 uint8_t slave, uint8_t *buf, uint16_t len, bool nonfinal)
242 {
243 uint32_t cmd, istatus;
244
245 istatus = RD(sc, GENI_M_IRQ_STATUS);
246 WR(sc, GENI_M_IRQ_CLEAR, istatus);
247
248 sc->rx_complete = false;
249 sc->rx_fifo = false;
250 sc->rx_buf = buf;
251 sc->rx_len = len;
252 WR(sc, GENI_I2C_RX_TRANS_LEN, len);
253
254 // GENI_M_CMD0_OPCODE_I2C_READ << M_OPCODE_SHFT
255 cmd = (0x2 << 27);
256
257 // GENI_M_CMD0_SLV_ADDR_SHIFT
258 cmd |= slave << 9;
259
260 if (nonfinal) {
261 // GENI_M_CMD0_STOP_STRETCH
262 cmd |= (1<<2);
263 }
264 WR(sc, GENI_RX_WATERMARK_REG, sc->rx_fifo_size - 4);
265
266 // CMD_DONE, RX_FIFO_WATERMARK
267 WR(sc, GENI_M_IRQ_EN, (1<<0) | (1<<26));
268
269 // M_IRQ
270 WR(sc, GENI_IRQ_EN, (1<<2));
271
272 WR(sc, GENI_M_CMD0, cmd);
273
274 mtx_lock_spin(&sc->intr_lock);
275 sc->rx_fifo = false;
276 unsigned msec;
277 for (msec = 0; msec < 100; msec++) {
278 msleep_spin_sbt(sc, &sc->intr_lock,
279 "geniwait", SBT_1MS, SBT_1MS / 10, 0);
280 if (sc->rx_complete)
281 break;
282 }
283 if (msec > sc->worst) {
284 device_printf(sc->dev,
285 "Tworst from %u to %u\n", sc->worst, msec);
286 if (msec != 100)
287 sc->worst = msec;
288 }
289
290 if (!sc->rx_complete) {
291 // S_GENI_CMD_CANCEL
292 WR(sc, GENI_M_CMD_CTRL_REG, (1<<2));
293
294 WR(sc, GENI_IRQ_EN, 0);
295 device_printf(sc->dev,
296 "Incomplete read (residual %x)\n", sc->rx_len);
297 }
298
299 sc->rx_buf = NULL;
300 len = sc->rx_len;
301 sc->rx_len = 0;
302
303 mtx_unlock_spin(&sc->intr_lock);
304
305 #define COMPLAIN(about) \
306 device_printf(sc->dev, \
307 "read " about " slave=0x%x len=0x%x, cmd=0x%x cmd_status=0x%x\n", \
308 slave, len, cmd, sc->cmd_status \
309 )
310
311 if (geniiic_debug_units) {
312 unsigned unit = device_get_unit(sc->dev);
313 if (unit < 32 && geniiic_debug_units & (1<<unit) && len == 0) {
314 COMPLAIN("OK");
315 return(IIC_NOERR);
316 }
317 }
318 if (len == 0)
319 return(IIC_NOERR);
320
321 if (sc->cmd_status & (1<<10)) {
322 COMPLAIN("ESTATUS");
323 return(IIC_ESTATUS);
324 }
325 if (len) {
326 COMPLAIN("EUNDERFLOW");
327 return(IIC_EUNDERFLOW);
328 }
329 COMPLAIN("EBUSERR");
330 return (IIC_EBUSERR);
331 #undef COMPLAIN
332 }
333
334 static int
geniiic_write(geniiic_softc_t * sc,uint8_t slave,uint8_t * buf,uint16_t len,bool nonfinal)335 geniiic_write(geniiic_softc_t *sc,
336 uint8_t slave, uint8_t *buf, uint16_t len, bool nonfinal)
337 {
338 uint32_t status, data, cmd;
339 int timeout, error;
340
341 status = RD(sc, GENI_M_IRQ_STATUS);
342 WR(sc, GENI_M_IRQ_CLEAR, status);
343
344 WR(sc, GENI_I2C_TX_TRANS_LEN, len);
345
346 // GENI_M_CMD0_OPCODE_I2C_WRITE << M_OPCODE_SHFT
347 cmd = (0x1 << 27);
348
349 // GENI_M_CMD0_SLV_ADDR_SHIFT
350 cmd |= slave << 9;
351
352 if (nonfinal) {
353 // GENI_M_CMD0_STOP_STRETCH
354 cmd |= (1<<2);
355 }
356 WR(sc, GENI_M_CMD0, cmd);
357 for(timeout = 0; len > 0 && timeout < 100; timeout++) {
358 status = RD(sc, GENI_TX_FIFO_STATUS);
359 if (status < 16) {
360 data = 0;
361 if (len) { data |= *buf << 0; buf++; len--; }
362 if (len) { data |= *buf << 8; buf++; len--; }
363 if (len) { data |= *buf << 16; buf++; len--; }
364 if (len) { data |= *buf << 24; buf++; len--; }
365 WR(sc, GENI_TX_FIFOn, data);
366 } else {
367 DELAY(10);
368 }
369 }
370
371 // GENI_M_IRQ_CMD_DONE
372 error = geniiic_wait_m_ireq(sc, 1);
373
374 if (len == 0 && error == 0)
375 return(IIC_NOERR);
376 device_printf(sc->dev,
377 "write ERR len=%d, error=%d cmd=0x%x\n", len, error, cmd);
378 return (IIC_EBUSERR);
379 }
380
381 static void
geniiic_dumpmsg(device_t dev,struct iic_msg * msgs,uint32_t nmsgs)382 geniiic_dumpmsg(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
383 {
384 unsigned u;
385
386 device_printf(dev, "transfer:\n");
387 for (u = 0; u < nmsgs; u++) {
388 device_printf(dev,
389 " [%d] slave=0x%x, flags=0x%x len=0x%x buf=%p\n",
390 u, msgs[u].slave, msgs[u].flags, msgs[u].len, msgs[u].buf
391 );
392 }
393 }
394
395 int
geniiic_transfer(device_t dev,struct iic_msg * msgs,uint32_t nmsgs)396 geniiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
397 {
398 geniiic_softc_t *sc = device_get_softc(dev);
399 unsigned u;
400 int error;
401
402 if (sc->nfail > 4) {
403 pause_sbt("geniic_fail", SBT_1S * 5, SBT_1S, 0);
404 return (IIC_ERESOURCE);
405 }
406
407 sx_xlock(&sc->real_bus_lock);
408
409 if (geniiic_debug_units) {
410 unsigned unit = device_get_unit(dev);
411 if (unit < 32 && geniiic_debug_units & (1<<unit)) {
412 geniiic_dumpmsg(dev, msgs, nmsgs);
413 }
414 }
415
416 error = 0;
417 for (u = 0; u < nmsgs; u++) {
418 bool nonfinal =
419 (u < nmsgs - 1) && (msgs[u].flags & IIC_M_NOSTOP);
420 unsigned slave = msgs[u].slave >> 1;
421 if (msgs[u].flags & IIC_M_RD) {
422 error = geniiic_read(sc,
423 slave, msgs[u].buf, msgs[u].len, nonfinal);
424 } else {
425 error = geniiic_write(sc,
426 slave, msgs[u].buf, msgs[u].len, nonfinal);
427 }
428 }
429 if (error) {
430 device_printf(dev, "transfer error %d\n", error);
431 geniiic_dumpmsg(dev, msgs, nmsgs);
432 }
433 if (error) {
434 geniiic_reset(dev, 0, 0, NULL);
435 }
436 if (error)
437 sc->nfail++;
438 else
439 sc->nfail = 0;
440 sx_xunlock(&sc->real_bus_lock);
441 return (error);
442 }
443
444 int
geniiic_reset(device_t dev,u_char speed,u_char addr,u_char * oldaddr)445 geniiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
446 {
447 geniiic_softc_t *sc = device_get_softc(dev);
448 unsigned u;
449
450 device_printf(dev, "reset\n");
451 WR(sc, GENI_M_IRQ_EN, 0);
452 WR(sc, GENI_M_IRQ_CLEAR, ~0);
453 WR(sc, GENI_DMA_TX_IRQ_EN_CLR, ~0);
454 WR(sc, GENI_DMA_TX_IRQ_CLR, ~0);
455 WR(sc, GENI_DMA_RX_IRQ_EN_CLR, ~0);
456 WR(sc, GENI_DMA_RX_IRQ_CLR, ~0);
457
458 // S_GENI_CMD_ABORT
459 WR(sc, GENI_M_CMD_CTRL_REG, (1<<1));
460
461 WR(sc, GENI_DMA_RX_FSM_RST, 1);
462 for (u = 0; u < 1000; u++) {
463 if (RD(sc, GENI_DMA_RX_IRQ_STAT) & 0x8)
464 break;
465 DELAY(10);
466 }
467 if (u > 0)
468 device_printf(dev, "RXRESET time %u\n", u);
469 WR(sc, GENI_DMA_TX_FSM_RST, 1);
470 for (u = 0; u < 1000; u++) {
471 if (RD(sc, GENI_DMA_TX_IRQ_STAT) & 0x8)
472 break;
473 DELAY(10);
474 }
475 if (u > 0)
476 device_printf(dev, "TXRESET time %u\n", u);
477 return (0);
478 }
479
480 int
geniiic_callback(device_t dev,int index,caddr_t data)481 geniiic_callback(device_t dev, int index, caddr_t data)
482 {
483 geniiic_softc_t *sc = device_get_softc(dev);
484 int error = 0;
485
486 return(0);
487 switch (index) {
488 case IIC_REQUEST_BUS:
489 if (sx_try_xlock(&sc->bus_lock) == 0)
490 error = IIC_EBUSBSY;
491 else
492 sc->bus_locked = true;
493 break;
494
495 case IIC_RELEASE_BUS:
496 if (!sc->bus_locked) {
497 device_printf(dev, "Unlocking unlocked bus\n");
498 }
499 sc->bus_locked = false;
500 sx_xunlock(&sc->bus_lock);
501 break;
502
503 default:
504 device_printf(dev, "callback unknown %d\n", index);
505 error = errno2iic(EINVAL);
506 }
507
508 return (error);
509 }
510
511 int
geniiic_attach(geniiic_softc_t * sc)512 geniiic_attach(geniiic_softc_t *sc)
513 {
514 int error = 0;
515
516 if (bootverbose)
517 geni_dump_regs(sc);
518 mtx_init(&sc->intr_lock, "geniiic intr lock", NULL, MTX_SPIN);
519 sx_init(&sc->real_bus_lock, "geniiic real bus lock");
520 sx_init(&sc->bus_lock, "geniiic bus lock");
521
522 sc->rx_fifo_size = (RD(sc, GENI_HW_PARAM_1) >> 16) & 0x3f;
523 device_printf(sc->dev, " RX fifo size= 0x%x\n", sc->rx_fifo_size);
524
525 // We might want to set/check the following registers:
526 // GENI_BYTE_GRANULARITY (0x00000000)
527 // GENI_TX_PACKING_CFG0 (0x0007f8fe)
528 // GENI_TX_PACKING_CFG1 (000ffefe)
529 // GENI_RX_PACKING_CFG0 (0x0007f8fe)
530 // GENI_RX_PACKING_CFG1 (000ffefe)
531
532 sc->iicbus = device_add_child(sc->dev, "iicbus", DEVICE_UNIT_ANY);
533 if (sc->iicbus == NULL) {
534 device_printf(sc->dev, "iicbus driver not found\n");
535 return(ENXIO);
536 }
537
538 error = bus_setup_intr(sc->dev,
539 sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE,
540 geniiic_intr, NULL, sc, &sc->intr_handle);
541 if (error) {
542 device_printf(sc->dev,
543 "Unable to setup irq: error %d\n", error);
544 }
545
546 bus_attach_children(sc->dev);
547 return (error);
548 }
549
550 int
geniiic_detach(geniiic_softc_t * sc)551 geniiic_detach(geniiic_softc_t *sc)
552 {
553 int error = 0;
554
555 error = bus_generic_detach(sc->dev);
556 if (error)
557 return (error);
558
559 WR(sc, GENI_M_IRQ_EN, 0);
560
561 if (sc->intr_handle) {
562 bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
563 }
564
565 sx_xlock(&sc->bus_lock);
566 sx_xlock(&sc->real_bus_lock);
567
568 geniiic_reset(sc->dev, 0, 0, NULL);
569 sc->iicbus = NULL;
570 sc->intr_handle = NULL;
571
572 sx_xunlock(&sc->real_bus_lock);
573 sx_xunlock(&sc->bus_lock);
574
575 sx_destroy(&sc->real_bus_lock);
576 sx_destroy(&sc->bus_lock);
577
578 mtx_destroy(&sc->intr_lock);
579 return (error);
580 }
581
582 int
geniiic_suspend(geniiic_softc_t * sc)583 geniiic_suspend(geniiic_softc_t *sc)
584 {
585 int error;
586
587 device_printf(sc->dev, "suspend method is NO-OP (good luck!)\n");
588
589 error = bus_generic_suspend(sc->dev);
590
591 return (error);
592 }
593
geniiic_resume(geniiic_softc_t * sc)594 int geniiic_resume(geniiic_softc_t *sc)
595 {
596 int error;
597
598 device_printf(sc->dev, "resume method is NO-OP (good luck!)\n");
599
600 error = bus_generic_resume(sc->dev);
601
602 return (error);
603 }
604
605 DRIVER_MODULE(iicbus, geniiic, iicbus_driver, NULL, NULL);
606 DRIVER_MODULE(acpi_iicbus, geniiic, acpi_iicbus_driver, NULL, NULL);
607 MODULE_DEPEND(geniiic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
608 MODULE_VERSION(geniiic, 1);
609