]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/arm/samsung/exynos/exynos5_i2c.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / arm / samsung / exynos / exynos5_i2c.c
1 /*-
2  * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Samsung Exynos 5 Inter-Integrated Circuit (I2C)
29  * Chapter 13, Exynos 5 Dual User's Manual Public Rev 1.00
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/malloc.h>
41 #include <sys/rman.h>
42 #include <sys/timeet.h>
43 #include <sys/timetc.h>
44
45 #include <dev/iicbus/iiconf.h>
46 #include <dev/iicbus/iicbus.h>
47
48 #include "iicbus_if.h"
49
50 #include <dev/fdt/fdt_common.h>
51 #include <dev/ofw/openfirm.h>
52 #include <dev/ofw/ofw_bus.h>
53 #include <dev/ofw/ofw_bus_subr.h>
54
55 #include <machine/bus.h>
56 #include <machine/fdt.h>
57 #include <machine/cpu.h>
58 #include <machine/intr.h>
59
60 #include <arm/samsung/exynos/exynos5_common.h>
61
62 #define I2CCON          0x00    /* Control register */
63 #define  ACKGEN         (1 << 7) /* Acknowledge Enable */
64 /*
65  * Source Clock of I2C-bus Transmit Clock Prescaler
66  *
67  * 0 = I2CCLK = fPCLK/16
68  * 1 = I2CCLK = fPCLK/512
69  */
70 #define  I2CCLK         (1 << 6)
71 #define  IRQ_EN         (1 << 5)        /* Tx/Rx Interrupt Enable/Disable */
72 #define  IPEND          (1 << 4)        /* Tx/Rx Interrupt Pending Flag */
73 #define  CLKVAL_M       0xf             /* Transmit Clock Prescaler Mask */
74 #define  CLKVAL_S       0
75 #define I2CSTAT         0x04            /* Control/status register */
76 #define  I2CMODE_M      0x3             /* Master/Slave Tx/Rx Mode Select */
77 #define  I2CMODE_S      6
78 #define  I2CMODE_SR     0x0             /* Slave Receive Mode */
79 #define  I2CMODE_ST     0x1             /* Slave Transmit Mode */
80 #define  I2CMODE_MR     0x2             /* Master Receive Mode */
81 #define  I2CMODE_MT     0x3             /* Master Transmit Mode */
82 #define  I2CSTAT_BSY    (1 << 5)        /* Busy Signal Status bit */
83 #define  I2C_START_STOP (1 << 5)        /* Busy Signal Status bit */
84 #define  RXTX_EN        (1 << 4)        /* Data Output Enable/Disable */
85 #define  ARBST          (1 << 3)        /* Arbitration status flag */
86 #define  ADDAS          (1 << 2)        /* Address-as-slave Status Flag */
87 #define  ADDZERO        (1 << 1)        /* Address Zero Status Flag */
88 #define  ACKRECVD       (1 << 0)        /* Last-received Bit Status Flag */
89 #define I2CADD          0x08            /* Address register */
90 #define I2CDS           0x0C            /* Transmit/receive data shift */
91 #define I2CLC           0x10            /* Multi-master line control */
92 #define  FILTER_EN      (1 << 2)        /* Filter Enable bit */
93 #define  SDAOUT_DELAY_M 0x3             /* SDA Line Delay Length */
94 #define  SDAOUT_DELAY_S 0
95
96 #ifdef DEBUG
97 #define DPRINTF(fmt, args...) \
98         printf(fmt, ##args)
99 #else
100 #define DPRINTF(fmt, args...)
101 #endif
102
103 static int i2c_start(device_t, u_char, int);
104 static int i2c_stop(device_t);
105 static int i2c_reset(device_t, u_char, u_char, u_char *);
106 static int i2c_read(device_t, char *, int, int *, int, int);
107 static int i2c_write(device_t, const char *, int, int *, int);
108
109 struct i2c_softc {
110         struct resource         *res[2];
111         bus_space_tag_t         bst;
112         bus_space_handle_t      bsh;
113         device_t                dev;
114         device_t                iicbus;
115         struct mtx              mutex;
116         void                    *ih;
117         int                     intr;
118 };
119
120 static struct resource_spec i2c_spec[] = {
121         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
122         { SYS_RES_IRQ,          0,      RF_ACTIVE },
123         { -1, 0 }
124 };
125
126 static int
127 i2c_probe(device_t dev)
128 {
129
130         if (!ofw_bus_status_okay(dev))
131                 return (ENXIO);
132
133         if (!ofw_bus_is_compatible(dev, "exynos,i2c"))
134                 return (ENXIO);
135
136         device_set_desc(dev, "Samsung Exynos 5 I2C controller");
137         return (BUS_PROBE_DEFAULT);
138 }
139
140 static int
141 clear_ipend(struct i2c_softc *sc)
142 {
143         int reg;
144
145         reg = READ1(sc, I2CCON);
146         reg &= ~(IPEND);
147         WRITE1(sc, I2CCON, reg);
148
149         return (0);
150 }
151
152 static int
153 i2c_attach(device_t dev)
154 {
155         struct i2c_softc *sc;
156         int reg;
157
158         sc = device_get_softc(dev);
159         sc->dev = dev;
160
161         mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
162
163         if (bus_alloc_resources(dev, i2c_spec, sc->res)) {
164                 device_printf(dev, "could not allocate resources\n");
165                 return (ENXIO);
166         }
167
168         /* Memory interface */
169         sc->bst = rman_get_bustag(sc->res[0]);
170         sc->bsh = rman_get_bushandle(sc->res[0]);
171
172         sc->iicbus = device_add_child(dev, "iicbus", -1);
173         if (sc->iicbus == NULL) {
174                 device_printf(dev, "could not add iicbus child");
175                 mtx_destroy(&sc->mutex);
176                 return (ENXIO);
177         }
178
179         WRITE1(sc, I2CSTAT, 0);
180         WRITE1(sc, I2CADD, 0x00);
181
182         /* Mode */
183         reg = (RXTX_EN);
184         reg |= (I2CMODE_MT << I2CMODE_S);
185         WRITE1(sc, I2CSTAT, reg);
186
187         bus_generic_attach(dev);
188
189         return (0);
190 }
191
192 static int
193 wait_for_iif(struct i2c_softc *sc)
194 {
195         int retry;
196         int reg;
197
198         retry = 1000;
199         while (retry --) {
200                 reg = READ1(sc, I2CCON);
201                 if (reg & IPEND) {
202                         return (IIC_NOERR);
203                 }
204                 DELAY(50);
205         }
206
207         return (IIC_ETIMEOUT);
208 }
209
210 static int
211 wait_for_nibb(struct i2c_softc *sc)
212 {
213         int retry;
214
215         retry = 1000;
216         while (retry --) {
217                 if ((READ1(sc, I2CSTAT) & I2CSTAT_BSY) == 0)
218                         return (IIC_NOERR);
219                 DELAY(10);
220         }
221
222         return (IIC_ETIMEOUT);
223 }
224
225 static int
226 is_ack(struct i2c_softc *sc)
227 {
228         int stat;
229
230         stat = READ1(sc, I2CSTAT);
231         if (!(stat & 1)) {
232                 /* ACK received */
233                 return (1);
234         }
235
236         return (0);
237 }
238
239 static int
240 i2c_start(device_t dev, u_char slave, int timeout)
241 {
242         struct i2c_softc *sc;
243         int error;
244         int reg;
245
246         sc = device_get_softc(dev);
247
248         DPRINTF("i2c start\n");
249
250         mtx_lock(&sc->mutex);
251
252 #if 0
253         DPRINTF("I2CCON == 0x%08x\n", READ1(sc, I2CCON));
254         DPRINTF("I2CSTAT == 0x%08x\n", READ1(sc, I2CSTAT));
255 #endif
256
257         if (slave & 1) {
258                 slave &= ~(1);
259                 slave <<= 1;
260                 slave |= 1;
261         } else {
262                 slave <<= 1;
263         }
264
265         error = wait_for_nibb(sc);
266         if (error) {
267                 mtx_unlock(&sc->mutex);
268                 DPRINTF("cant i2c start: IIC_EBUSBSY\n");
269                 return (IIC_EBUSBSY);
270         }
271
272         reg = READ1(sc, I2CCON);
273         reg |= (IRQ_EN | ACKGEN);
274         WRITE1(sc, I2CCON, reg);
275
276         WRITE1(sc, I2CDS, slave);
277         DELAY(50);
278
279         reg = (RXTX_EN);
280         reg |= I2C_START_STOP;
281         reg |= (I2CMODE_MT << I2CMODE_S);
282         WRITE1(sc, I2CSTAT, reg);
283
284         error = wait_for_iif(sc);
285         if (error) {
286                 DPRINTF("cant i2c start: iif error\n");
287
288                 mtx_unlock(&sc->mutex);
289                 return (error);
290         }
291
292         if (!is_ack(sc)) {
293                 DPRINTF("cant i2c start: no ack\n");
294
295                 mtx_unlock(&sc->mutex);
296                 return (IIC_ENOACK);
297         };
298
299         mtx_unlock(&sc->mutex);
300         return (IIC_NOERR);
301 }
302
303 static int
304 i2c_stop(device_t dev)
305 {
306         struct i2c_softc *sc;
307         int reg;
308         int error;
309
310         sc = device_get_softc(dev);
311
312         DPRINTF("i2c stop\n");
313
314         mtx_lock(&sc->mutex);
315
316         reg = READ1(sc, I2CSTAT);
317         int mode = (reg >> I2CMODE_S) & I2CMODE_M;
318
319         reg = (RXTX_EN);
320         reg |= (mode << I2CMODE_S);
321         WRITE1(sc, I2CSTAT, reg);
322
323         clear_ipend(sc);
324
325         error = wait_for_nibb(sc);
326         if (error) {
327                 DPRINTF("cant i2c stop: nibb error\n");
328                 return (error);
329         }
330
331         mtx_unlock(&sc->mutex);
332         return (IIC_NOERR);
333 }
334
335 static int
336 i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
337 {
338         struct i2c_softc *sc;
339
340         sc = device_get_softc(dev);
341
342         DPRINTF("i2c reset\n");
343
344         mtx_lock(&sc->mutex);
345
346         /* TODO */
347
348         mtx_unlock(&sc->mutex);
349
350         return (IIC_NOERR);
351 }
352
353 static int
354 i2c_read(device_t dev, char *buf, int len,
355     int *read, int last, int delay)
356 {
357         struct i2c_softc *sc;
358         int error;
359         int reg;
360         uint8_t d;
361
362         sc = device_get_softc(dev);
363
364         DPRINTF("i2c read\n");
365
366         reg = (RXTX_EN);
367         reg |= (I2CMODE_MR << I2CMODE_S);
368         reg |= I2C_START_STOP;
369         WRITE1(sc, I2CSTAT, reg);
370
371         *read = 0;
372         mtx_lock(&sc->mutex);
373
374         /* dummy read */
375         READ1(sc, I2CDS);
376
377         DPRINTF("Read ");
378         while (*read < len) {
379
380                 /* Do not ack last read */
381                 if (*read == (len - 1)) {
382                         reg = READ1(sc, I2CCON);
383                         reg &= ~(ACKGEN);
384                         WRITE1(sc, I2CCON, reg);
385                 };
386
387                 clear_ipend(sc);
388
389                 error = wait_for_iif(sc);
390                 if (error) {
391                         DPRINTF("cant i2c read: iif error\n");
392                         mtx_unlock(&sc->mutex);
393                         return (error);
394                 }
395
396                 d = READ1(sc, I2CDS);
397                 DPRINTF("0x%02x ", d);
398                 *buf++ = d;
399                 (*read)++;
400         }
401         DPRINTF("\n");
402
403         mtx_unlock(&sc->mutex);
404         return (IIC_NOERR);
405 }
406
407 static int
408 i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
409 {
410         struct i2c_softc *sc;
411         int error;
412
413         sc = device_get_softc(dev);
414
415         DPRINTF("i2c write\n");
416
417         *sent = 0;
418
419         mtx_lock(&sc->mutex);
420
421         DPRINTF("writing ");
422         while (*sent < len) {
423                 uint8_t d = *buf++;
424                 DPRINTF("0x%02x ", d);
425
426                 WRITE1(sc, I2CDS, d);
427                 DELAY(50);
428
429                 clear_ipend(sc);
430
431                 error = wait_for_iif(sc);
432                 if (error) {
433                         DPRINTF("cant i2c write: iif error\n");
434                         mtx_unlock(&sc->mutex);
435                         return (error);
436                 }
437
438                 if (!is_ack(sc)) {
439                         DPRINTF("cant i2c write: no ack\n");
440                         mtx_unlock(&sc->mutex);
441                         return (IIC_ENOACK);
442                 };
443
444                 (*sent)++;
445         }
446         DPRINTF("\n");
447
448         mtx_unlock(&sc->mutex);
449         return (IIC_NOERR);
450 }
451
452 static device_method_t i2c_methods[] = {
453         DEVMETHOD(device_probe,         i2c_probe),
454         DEVMETHOD(device_attach,        i2c_attach),
455
456         DEVMETHOD(iicbus_callback,              iicbus_null_callback),
457         DEVMETHOD(iicbus_start,                 i2c_start),
458         DEVMETHOD(iicbus_stop,                  i2c_stop),
459         DEVMETHOD(iicbus_reset,                 i2c_reset),
460         DEVMETHOD(iicbus_read,                  i2c_read),
461         DEVMETHOD(iicbus_write,                 i2c_write),
462         DEVMETHOD(iicbus_transfer,              iicbus_transfer_gen),
463
464         { 0, 0 }
465 };
466
467 static driver_t i2c_driver = {
468         "i2c",
469         i2c_methods,
470         sizeof(struct i2c_softc),
471 };
472
473 static devclass_t i2c_devclass;
474
475 DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
476 DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);