]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/mv/a37x0_iic.c
MFV r362254: file 5.39.
[FreeBSD/FreeBSD.git] / sys / arm / mv / a37x0_iic.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018, 2019 Rubicon Communications, LLC (Netgate)
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 AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  * Driver for Armada 37x0 i2c controller.
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/module.h>
40 #include <sys/mutex.h>
41 #include <sys/bus.h>
42 #include <machine/resource.h>
43 #include <machine/bus.h>
44 #include <sys/rman.h>
45 #include <sys/sysctl.h>
46
47 #include <dev/iicbus/iicbus.h>
48 #include <dev/iicbus/iiconf.h>
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51
52 #include <arm/mv/a37x0_iicreg.h>
53
54 #include "iicbus_if.h"
55
56 struct a37x0_iic_softc {
57         boolean_t               sc_fast_mode;
58         bus_space_tag_t         sc_bst;
59         bus_space_handle_t      sc_bsh;
60         device_t                sc_dev;
61         device_t                sc_iicbus;
62         struct mtx              sc_mtx;
63         struct resource         *sc_mem_res;
64         struct resource         *sc_irq_res;
65         void                    *sc_intrhand;
66 };
67
68 #define A37X0_IIC_WRITE(_sc, _off, _val)                        \
69     bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, _off, _val)
70 #define A37X0_IIC_READ(_sc, _off)                               \
71     bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, _off)
72 #define A37X0_IIC_LOCK(_sc)     mtx_lock(&(_sc)->sc_mtx)
73 #define A37X0_IIC_UNLOCK(_sc)   mtx_unlock(&(_sc)->sc_mtx)
74
75 static struct ofw_compat_data compat_data[] = {
76         { "marvell,armada-3700-i2c",    1 },
77         { NULL,                         0 }
78 };
79
80 #undef A37x0_IIC_DEBUG
81
82 static void a37x0_iic_intr(void *);
83 static int a37x0_iic_detach(device_t);
84
85 static void
86 a37x0_iic_rmw(struct a37x0_iic_softc *sc, uint32_t off, uint32_t mask,
87     uint32_t value)
88 {
89         uint32_t reg;
90
91         mtx_assert(&sc->sc_mtx, MA_OWNED);
92         reg = A37X0_IIC_READ(sc, off);
93         reg &= ~mask;
94         reg |= value;
95         A37X0_IIC_WRITE(sc, off, reg);
96 }
97
98 static int
99 a37x0_iic_wait_clear(struct a37x0_iic_softc *sc, uint32_t mask)
100 {
101         int timeout;
102         uint32_t status;
103
104         mtx_assert(&sc->sc_mtx, MA_OWNED);
105         timeout = 1000;
106         do {
107                 DELAY(10);
108                 status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
109                 if (--timeout == 0)
110                         return (0);
111         } while ((status & mask) != 0);
112
113         return (1);
114 }
115
116 static int
117 a37x0_iic_wait_set(struct a37x0_iic_softc *sc, uint32_t mask)
118 {
119         int timeout;
120         uint32_t status;
121
122         mtx_assert(&sc->sc_mtx, MA_OWNED);
123         timeout = 1000;
124         do {
125                 DELAY(10);
126                 status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
127                 if (--timeout == 0)
128                         return (0);
129         } while ((status & mask) != mask);
130
131         return (1);
132 }
133
134 #ifdef A37x0_IIC_DEBUG
135 static void
136 a37x0_iic_regdump(struct a37x0_iic_softc *sc)
137 {
138
139         mtx_assert(&sc->sc_mtx, MA_OWNED);
140         printf("%s: IBMR: %#x\n", __func__, A37X0_IIC_READ(sc, A37X0_IIC_IBMR));
141         printf("%s: ICR: %#x\n", __func__, A37X0_IIC_READ(sc, A37X0_IIC_ICR));
142         printf("%s: ISR: %#x\n", __func__, A37X0_IIC_READ(sc, A37X0_IIC_ISR));
143 }
144 #endif
145
146 static void
147 a37x0_iic_reset(struct a37x0_iic_softc *sc)
148 {
149         uint32_t mode, reg;
150
151         mtx_assert(&sc->sc_mtx, MA_OWNED);
152
153         /* Disable the controller. */
154         reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
155         mode = reg & ICR_MODE_MASK;
156         A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg & ~ICR_IUE);
157         A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg | ICR_UR);
158         DELAY(100);
159         A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg & ~ICR_IUE);
160
161         /* Enable the controller. */
162         reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
163         reg |= mode | ICR_IUE | ICR_GCD | ICR_SCLE;
164         A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg);
165 #ifdef A37x0_IIC_DEBUG
166         a37x0_iic_regdump(sc);
167 #endif
168 }
169
170 static int
171 a37x0_iic_probe(device_t dev)
172 {
173
174         if (!ofw_bus_status_okay(dev))
175                 return (ENXIO);
176
177         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
178                 return (ENXIO);
179
180         device_set_desc(dev, "Marvell Armada 37x0 IIC controller");
181
182         return (BUS_PROBE_DEFAULT);
183 }
184
185 static int
186 a37x0_iic_attach(device_t dev)
187 {
188         int rid;
189         phandle_t node;
190         struct a37x0_iic_softc *sc;
191
192         sc = device_get_softc(dev);
193         sc->sc_dev = dev;
194
195         rid = 0;
196         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
197             RF_ACTIVE);
198         if (!sc->sc_mem_res) {
199                 device_printf(dev, "cannot allocate memory window\n");
200                 return (ENXIO);
201         }
202
203         sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
204         sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
205
206         rid = 0;
207         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
208             RF_ACTIVE | RF_SHAREABLE);
209         if (!sc->sc_irq_res) {
210                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
211                 device_printf(dev, "cannot allocate interrupt\n");
212                 return (ENXIO);
213         }
214
215         /* Hook up our interrupt handler. */
216         if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
217             NULL, a37x0_iic_intr, sc, &sc->sc_intrhand)) {
218                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
219                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
220                 device_printf(dev, "cannot setup the interrupt handler\n");
221                 return (ENXIO);
222         }
223
224         mtx_init(&sc->sc_mtx, "a37x0_iic", NULL, MTX_DEF);
225
226         node = ofw_bus_get_node(dev);
227         if (OF_hasprop(node, "mrvl,i2c-fast-mode"))
228                 sc->sc_fast_mode = true;
229
230         /* Enable the controller. */
231         A37X0_IIC_LOCK(sc);
232         a37x0_iic_reset(sc);
233         A37X0_IIC_UNLOCK(sc);
234
235         sc->sc_iicbus = device_add_child(dev, "iicbus", -1);
236         if (sc->sc_iicbus == NULL) {
237                 a37x0_iic_detach(dev);
238                 return (ENXIO);
239         }
240
241         /* Probe and attach the iicbus. */
242         return (bus_generic_attach(dev));
243 }
244
245 static int
246 a37x0_iic_detach(device_t dev)
247 {
248         struct a37x0_iic_softc *sc;
249
250         bus_generic_detach(dev);
251
252         sc = device_get_softc(dev);
253         if (sc->sc_iicbus != NULL)
254                 device_delete_child(dev, sc->sc_iicbus);
255         mtx_destroy(&sc->sc_mtx);
256         if (sc->sc_intrhand)
257                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
258         if (sc->sc_irq_res)
259                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
260         if (sc->sc_mem_res)
261                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
262
263         return (0);
264 }
265
266 static void
267 a37x0_iic_intr(void *arg)
268 {
269         struct a37x0_iic_softc *sc;
270         uint32_t status;
271
272         /* Not used, the interrupts are not enabled. */
273         sc = (struct a37x0_iic_softc *)arg;
274         A37X0_IIC_LOCK(sc);
275         status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
276 #ifdef A37x0_IIC_DEBUG
277         a37x0_iic_regdump(sc);
278 #endif
279
280         /* Clear pending interrrupts. */
281         A37X0_IIC_WRITE(sc, A37X0_IIC_ISR, status);
282         A37X0_IIC_UNLOCK(sc);
283 }
284
285 static int
286 a37x0_iic_stop(device_t dev)
287 {
288         struct a37x0_iic_softc *sc;
289         uint32_t reg;
290
291         sc = device_get_softc(dev);
292         A37X0_IIC_LOCK(sc);
293         /* Clear the STOP condition. */
294         reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
295         if (reg & (ICR_ACKNAK | ICR_STOP)) {
296                 reg &= ~(ICR_START | ICR_ACKNAK | ICR_STOP);
297                 A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg);
298         }
299         /* Clear interrupts. */
300         reg = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
301         A37X0_IIC_WRITE(sc, A37X0_IIC_ISR, reg);
302         A37X0_IIC_UNLOCK(sc);
303
304         return (IIC_NOERR);
305 }
306
307 static int
308 a37x0_iic_start(device_t dev, u_char slave, int timeout)
309 {
310         int rv;
311         struct a37x0_iic_softc *sc;
312         uint32_t reg, status;
313
314         sc = device_get_softc(dev);
315         A37X0_IIC_LOCK(sc);
316
317         /* Wait for the bus to be free before start a transaction. */
318         if (a37x0_iic_wait_clear(sc, ISR_IBB) == 0) {
319                 A37X0_IIC_UNLOCK(sc);
320                 return (IIC_ETIMEOUT);
321         }
322
323         /* Write the slave address. */
324         A37X0_IIC_WRITE(sc, A37X0_IIC_IDBR, slave);
325
326         /* Send Start condition (with slave address). */
327         reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
328         reg &= ~(ICR_STOP | ICR_ACKNAK);
329         A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg | ICR_START | ICR_TB);
330
331         rv = IIC_NOERR;
332         if (a37x0_iic_wait_set(sc, ISR_ITE) == 0)
333                 rv = IIC_ETIMEOUT;
334         if (rv == IIC_NOERR) {
335                 status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
336                 A37X0_IIC_WRITE(sc, A37X0_IIC_ISR, status | ISR_ITE);
337                 if (a37x0_iic_wait_clear(sc, ISR_ACKNAK) == 0)
338                         rv = IIC_ENOACK;
339         }
340
341         A37X0_IIC_UNLOCK(sc);
342         if (rv != IIC_NOERR)
343                 a37x0_iic_stop(dev);
344
345         return (rv);
346 }
347
348 static int
349 a37x0_iic_bus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
350 {
351         struct a37x0_iic_softc *sc;
352         uint32_t busfreq;
353
354         sc = device_get_softc(dev);
355         A37X0_IIC_LOCK(sc);
356         a37x0_iic_reset(sc);
357         if (sc->sc_iicbus == NULL)
358                 busfreq = 100000;
359         else
360                 busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed);
361         a37x0_iic_rmw(sc, A37X0_IIC_ICR, ICR_MODE_MASK,
362             (busfreq > 100000) ? ICR_FAST_MODE : 0);
363         A37X0_IIC_UNLOCK(sc);
364
365         return (IIC_ENOADDR);
366 }
367
368 static int
369 a37x0_iic_read(device_t dev, char *buf, int len, int *read, int last, int delay)
370 {
371         int rv;
372         struct a37x0_iic_softc *sc;
373         uint32_t reg, status;
374
375         sc = device_get_softc(dev);
376         A37X0_IIC_LOCK(sc);
377         reg = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
378         if ((reg & (ISR_UB | ISR_IBB)) != ISR_UB) {
379                 A37X0_IIC_UNLOCK(sc);
380                 return (IIC_EBUSERR);
381         }
382
383         *read = 0;
384         rv = IIC_NOERR;
385         while (*read < len) {
386                 reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
387                 reg &= ~(ICR_START | ICR_STOP | ICR_ACKNAK);
388                 if (*read == len - 1)
389                         reg |= ICR_ACKNAK | ICR_STOP;
390                 A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg | ICR_TB);
391                 if (a37x0_iic_wait_set(sc, ISR_IRF) == 0) {
392                         rv = IIC_ETIMEOUT;
393                         break;
394                 }
395                 *buf++ = A37X0_IIC_READ(sc, A37X0_IIC_IDBR);
396                 (*read)++;
397                 status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
398                 A37X0_IIC_WRITE(sc, A37X0_IIC_ISR, status | ISR_IRF);
399         }
400         A37X0_IIC_UNLOCK(sc);
401
402         return (rv);
403 }
404
405 static int
406 a37x0_iic_write(device_t dev, const char *buf, int len, int *sent, int timeout)
407 {
408         int rv;
409         struct a37x0_iic_softc *sc;
410         uint32_t reg, status;
411
412         sc = device_get_softc(dev);
413         A37X0_IIC_LOCK(sc);
414         reg = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
415         if ((reg & (ISR_UB | ISR_IBB)) != ISR_UB) {
416                 A37X0_IIC_UNLOCK(sc);
417                 return (IIC_EBUSERR);
418         }
419
420         rv = IIC_NOERR;
421         *sent = 0;
422         while (*sent < len) {
423                 A37X0_IIC_WRITE(sc, A37X0_IIC_IDBR, *buf++);
424                 reg = A37X0_IIC_READ(sc, A37X0_IIC_ICR);
425                 reg &= ~(ICR_START | ICR_STOP | ICR_ACKNAK);
426                 if (*sent == len - 1)
427                         reg |= ICR_STOP;
428                 A37X0_IIC_WRITE(sc, A37X0_IIC_ICR, reg | ICR_TB);
429                 if (a37x0_iic_wait_set(sc, ISR_ITE) == 0) {
430                         rv = IIC_ETIMEOUT;
431                         break;
432                 }
433                 (*sent)++;
434                 status = A37X0_IIC_READ(sc, A37X0_IIC_ISR);
435                 A37X0_IIC_WRITE(sc, A37X0_IIC_ISR, status | ISR_ITE);
436                 if (a37x0_iic_wait_clear(sc, ISR_ACKNAK) == 0) {
437                         rv = IIC_ENOACK;
438                         break;
439                 }
440         }
441         A37X0_IIC_UNLOCK(sc);
442
443         return (rv);
444 }
445
446 static phandle_t
447 a37x0_iic_get_node(device_t bus, device_t dev)
448 {
449
450         return (ofw_bus_get_node(bus));
451 }
452
453 static device_method_t a37x0_iic_methods[] = {
454         /* Device interface */
455         DEVMETHOD(device_probe,         a37x0_iic_probe),
456         DEVMETHOD(device_attach,        a37x0_iic_attach),
457         DEVMETHOD(device_detach,        a37x0_iic_detach),
458
459         /* iicbus interface */
460         DEVMETHOD(iicbus_reset,         a37x0_iic_bus_reset),
461         DEVMETHOD(iicbus_callback,      iicbus_null_callback),
462         DEVMETHOD(iicbus_transfer,      iicbus_transfer_gen),
463         DEVMETHOD(iicbus_repeated_start,        a37x0_iic_start),
464         DEVMETHOD(iicbus_start,         a37x0_iic_start),
465         DEVMETHOD(iicbus_stop,          a37x0_iic_stop),
466         DEVMETHOD(iicbus_read,          a37x0_iic_read),
467         DEVMETHOD(iicbus_write,         a37x0_iic_write),
468
469         /* ofw_bus interface */
470         DEVMETHOD(ofw_bus_get_node,     a37x0_iic_get_node),
471
472         DEVMETHOD_END
473 };
474
475 static devclass_t a37x0_iic_devclass;
476
477 static driver_t a37x0_iic_driver = {
478         "iichb",
479         a37x0_iic_methods,
480         sizeof(struct a37x0_iic_softc),
481 };
482
483 DRIVER_MODULE(iicbus, a37x0_iic, iicbus_driver, iicbus_devclass, 0, 0);
484 DRIVER_MODULE(a37x0_iic, simplebus, a37x0_iic_driver, a37x0_iic_devclass, 0, 0);