1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include <autoconf.h>
14#include <platsupport/gen_config.h>
15
16/* To extend support, provide platform specific i2c.h and gpio.h and delay.c */
17#if defined(CONFIG_PLAT_EXYNOS5) || defined(CONFIG_PLAT_EXYNOS4) || defined(CONFIG_PLAT_IMX6)
18
19#include <platsupport/i2c.h>
20#include <platsupport/delay.h>
21#include "../../services.h"
22
23#define DEFAULT_SPEED 100*1000
24
25static inline struct i2c_bb*
26i2c_bus_get_priv(struct i2c_bus* i2c_bus) {
27    return (struct i2c_bb*)i2c_bus->priv;
28}
29
30static inline void
31_hold(struct i2c_bb* d)
32{
33    ps_udelay(1000000 / d->speed + 1);
34}
35
36static inline void
37pin_l(struct i2c_bb* d, int gpio)
38{
39    gpio_t g;
40    gpio_new(d->gpio_sys, gpio, GPIO_DIR_OUT, &g);
41    gpio_clr(&g);
42}
43
44static inline int
45pin_r(struct i2c_bb* d, int gpio)
46{
47    gpio_t g;
48    gpio_new(d->gpio_sys, gpio, GPIO_DIR_IN, &g);
49    return gpio_get(&g);
50}
51
52static inline void
53pin_h(struct i2c_bb* d, int gpio)
54{
55    pin_r(d, gpio);
56}
57
58static inline int  sda_r (struct i2c_bb* d)
59{
60    return pin_r(d, d->sda);
61}
62static inline void sda_l (struct i2c_bb* d)
63{
64    pin_l(d, d->sda);
65}
66static inline void sda_h (struct i2c_bb* d)
67{
68    pin_h(d, d->sda);
69}
70
71static inline void scl_l (struct i2c_bb* d)
72{
73    pin_l(d, d->scl);
74}
75static inline void scl_h (struct i2c_bb* d)
76{
77    while (!pin_r(d, d->scl));
78}
79
80static inline void
81clk(struct i2c_bb* d)
82{
83    _hold  (d);
84    scl_h  (d);
85    _hold  (d);
86    scl_l  (d);
87}
88
89static inline void
90i2c_bb_start(struct i2c_bb* d)
91{
92    /* init */
93    while (!sda_r(d));
94    _hold  (d);
95    /* Start */
96    sda_l  (d);
97    _hold  (d);
98    scl_l  (d);
99}
100
101static inline void
102i2c_bb_stop(struct i2c_bb* d)
103{
104    sda_l  (d);
105    _hold  (d);
106    scl_h  (d);
107    ps_udelay(1000);
108    while (!sda_r(d));
109    _hold  (d);
110}
111
112static inline void
113i2c_bb_sendbit(struct i2c_bb* d, int bit)
114{
115    /* Setup bit */
116    if (bit) {
117        sda_h (d);
118    } else {
119        sda_l (d);
120    }
121    _hold  (d);
122    /* Raise clock, wait for clock stretching */
123    scl_h  (d);
124    _hold  (d);
125    /* Lower clock */
126    scl_l  (d);
127}
128
129static inline int
130i2c_bb_readbit(struct i2c_bb* d)
131{
132    int bit;
133    /* Release SDA */
134    sda_r  (d);
135    _hold  (d);
136    /* Raise clock, wait for clock stretching */
137    scl_h  (d);
138    /* Data now read to be read */
139    bit = sda_r(d);
140    _hold  (d);
141    scl_l  (d);
142    return bit;
143}
144
145static int
146i2c_bb_sendbyte(struct i2c_bb* d, char b)
147{
148    int i;
149    unsigned char mask = 0x80;
150    for (i = 0; i < 8; i++) {
151        i2c_bb_sendbit(d, !!(b & mask));
152        mask >>= 1;
153    }
154    /* ACK */
155    return i2c_bb_readbit(d);
156}
157
158static int
159i2c_bb_readbyte(struct i2c_bb* d, int send_nak)
160{
161    int i;
162    char data = 0;
163    for (i = 0; i < 8; i++) {
164        data <<= 1;
165        data |= (i2c_bb_readbit(d)) ? 1 : 0;
166    }
167    i2c_bb_sendbit(d, send_nak);
168    return data;
169}
170
171static int
172i2c_bb_read(i2c_bus_t* bus, void* buf, size_t size,
173            UNUSED bool end_with_repeat_start,
174            i2c_callback_fn cb, void* token)
175{
176    assert(!"Not implemented\n");
177    return -1;
178}
179
180static int
181i2c_bb_write(i2c_bus_t* bus, const void* buf, size_t size,
182             UNUSED bool end_with_repeat_start,
183             i2c_callback_fn cb, void* token)
184{
185    assert(!"Not implemented\n");
186    return -1;
187}
188
189static int
190i2c_bb_master_stop(i2c_bus_t* bus)
191{
192    assert(!"Not implemented\n");
193    return -1;
194}
195
196static int
197i2c_bb_start_read(i2c_slave_t *sl,
198                  void* vdata, size_t size,
199                  UNUSED bool end_with_repeat_start,
200                  i2c_callback_fn cb, void* token)
201{
202    struct i2c_bb* d;
203    int nak;
204    int count;
205    char* data = (char*)vdata;
206
207    assert(sl != NULL && sl->bus != NULL);
208
209    d = i2c_bus_get_priv(sl->bus);
210
211    i2c_bb_start(d);
212    nak = i2c_bb_sendbyte(d, sl->address | 1);
213    if (nak) {
214        i2c_bb_stop(d);
215        return -1;
216    }
217
218    for (count = 0; !nak && count < size; count++) {
219        *data++ = i2c_bb_readbyte(d, count + 1 == size);
220    }
221
222    i2c_bb_stop(d);
223    if (cb) {
224        cb(sl->bus, I2CSTAT_COMPLETE, size, token);
225    }
226    return count;
227}
228
229static int
230i2c_bb_start_write(i2c_slave_t *sl,
231                   const void* vdata, size_t size,
232                   UNUSED bool end_with_repeat_start,
233                   i2c_callback_fn cb, void* token)
234{
235    struct i2c_bb* d;
236    int nak;
237    int count;
238    const char* data = (const char*)vdata;
239
240    assert(sl != NULL && sl->bus != NULL);
241
242    d = i2c_bus_get_priv(sl->bus);
243
244    i2c_bb_start(d);
245    nak = i2c_bb_sendbyte(d, sl->address & ~1);
246    if (nak) {
247        return -1;
248    }
249
250    for (count = 0; !nak && count < size; count++) {
251        i2c_bb_sendbyte(d, *data++);
252    }
253
254    i2c_bb_stop(d);
255    if (cb) {
256        cb(sl->bus, I2CSTAT_COMPLETE, size, token);
257    }
258    return count;
259}
260
261static void
262i2c_bb_handle_irq(i2c_bus_t* i2c_bus)
263{
264    struct i2c_bb* d;
265    /* BB is a blocking call, but in case someone tried to poll, we ignore the call */
266    d = i2c_bus_get_priv(i2c_bus);
267    (void)d;
268}
269
270static int
271i2c_bb_set_self_slave_address(i2c_bus_t *i2c_bus, int addr)
272{
273    struct i2c_bb* d;
274    d = i2c_bus_get_priv(i2c_bus);
275    (void)d;
276    assert(!"Not implemented");
277    return -1;
278}
279
280static void
281i2c_bb_register_slave_event_handler(i2c_bus_t *bus,
282                                    i2c_aas_callback_fn aas_cb, void* aas_token)
283{
284    assert(bus != NULL);
285    bus->aas_cb = aas_cb;
286    bus->aas_token = aas_token;
287}
288
289static const uint32_t i2c_speed_freqs[] = {
290    [I2C_SLAVE_SPEED_STANDARD] = 100000,
291    [I2C_SLAVE_SPEED_FAST] = 400000,
292    [I2C_SLAVE_SPEED_FASTPLUS] = 1000000,
293    [I2C_SLAVE_SPEED_HIGHSPEED] = 3400000
294};
295
296static long
297i2c_bb_set_speed(i2c_bus_t* i2c_bus, enum i2c_slave_speed speed)
298{
299    struct i2c_bb* d;
300    d = i2c_bus_get_priv(i2c_bus);
301
302    if (speed < I2C_SLAVE_SPEED_STANDARD || speed > I2C_SLAVE_SPEED_HIGHSPEED) {
303        ZF_LOGE("lib I2C-bitbang: Unsupported speed %d.", speed);
304        return -1;
305    }
306
307    d->speed = i2c_speed_freqs[speed];
308    return speed;
309}
310
311static int
312i2c_bb_slave_init(i2c_bus_t* i2c_bus, int address,
313                  enum i2c_slave_address_size address_size,
314                  enum i2c_slave_speed max_speed,
315                  uint32_t flags,
316                  i2c_slave_t* sl)
317{
318    assert(sl != NULL);
319
320    sl->address = address;
321    sl->address_size = address_size;
322    sl->max_speed = max_speed;
323    sl->i2c_opts = 0;
324    sl->bus = i2c_bus;
325
326    sl->slave_read      = &i2c_bb_start_read;
327    sl->slave_write     = &i2c_bb_start_write;
328
329    return 0;
330}
331
332int
333i2c_bb_init(gpio_sys_t* gpio_sys, gpio_id_t scl, gpio_id_t sda,
334            struct i2c_bb* i2c_bb, struct i2c_bus* i2c)
335{
336    /* Initialise the BB structure */
337    i2c_bb->scl = scl;
338    i2c_bb->sda = sda;
339    i2c_bb->speed = DEFAULT_SPEED;
340    i2c_bb->gpio_sys = gpio_sys;
341    /* Initialise the I2C bus structure */
342    i2c->slave_init  = i2c_bb_slave_init;
343    i2c->read        = i2c_bb_read;
344    i2c->write       = i2c_bb_write;
345    i2c->set_speed   = i2c_bb_set_speed;
346    i2c->set_self_slave_address = i2c_bb_set_self_slave_address;
347    i2c->register_slave_event_handler = i2c_bb_register_slave_event_handler;
348    i2c->master_stop = i2c_bb_master_stop;
349    i2c->handle_irq  = i2c_bb_handle_irq;
350    i2c->priv        = (void*)i2c_bb;
351    /* Done */
352    return 0;
353}
354
355#endif
356