1/*
2 * Copyright 2019, 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/* warning: use of callbacks is NOT tested with this driver */
14
15#include <platsupport/i2c.h>
16#include <platsupport/pmem.h>
17#include <platsupport/plat/i2c.h>
18
19struct omap4_i2c_dev {
20    void *regs;
21    int irq_id;
22    enum i2c_slave_speed speed;
23    enum i2c_mode mode;
24    enum i2c_stat status;
25    uint16_t fifo_threshold;
26    uint8_t *buf;
27    size_t buf_len;
28    size_t buf_pos;
29    bool repeat_start;
30    bool interrupts_enabled;
31    volatile bool busy;
32};
33typedef struct omap4_i2c_dev omap4_i2c_dev_t;
34
35static pmem_region_t pmems[] = {
36    {
37        .type = PMEM_TYPE_DEVICE,
38        .base_addr = AM335X_I2C0_PADDR,
39        .length = PAGE_SIZE_4K
40    },
41    {
42        .type = PMEM_TYPE_DEVICE,
43        .base_addr = AM335X_I2C1_PADDR,
44        .length = PAGE_SIZE_4K
45    },
46    {
47        .type = PMEM_TYPE_DEVICE,
48        .base_addr = AM335X_I2C2_PADDR,
49        .length = PAGE_SIZE_4K
50    }
51};
52
53static ps_irq_t irqs[] = {
54    {
55        .type = PS_INTERRUPT,
56        .irq.number = AM335X_I2C0_IRQ
57    },
58    {
59        .type = PS_INTERRUPT,
60        .irq.number = AM335X_I2C1_IRQ
61    },
62    {
63        .type = PS_INTERRUPT,
64        .irq.number = AM335X_I2C2_IRQ
65    }
66};
67
68static const uint32_t i2c_speed_freqs[] = {
69    [I2C_SLAVE_SPEED_STANDARD] = 100000,
70    [I2C_SLAVE_SPEED_FAST] = 400000
71};
72
73static inline uint16_t omap4_i2c_reg_read(omap4_i2c_dev_t *dev, int addr)
74{
75    return *(volatile uint16_t *)(dev->regs + addr);
76}
77
78static inline void omap4_i2c_reg_write(omap4_i2c_dev_t *dev, int addr, uint16_t val)
79{
80    *(volatile uint16_t *)(dev->regs + addr) = val;
81}
82
83static void omap4_i2c_enable_interrupts(omap4_i2c_dev_t *dev)
84{
85    dev->interrupts_enabled = true;
86    omap4_i2c_reg_write(dev, OMAP4_I2C_IRQENABLE_SET, IRQENABLE_XDR | IRQENABLE_RDR |
87                        IRQENABLE_XRDY | IRQENABLE_RRDY | IRQENABLE_ARDY | IRQENABLE_NACK);
88}
89
90static void omap4_i2c_disable_interrupts(omap4_i2c_dev_t *dev)
91{
92    dev->interrupts_enabled = false;
93    omap4_i2c_reg_write(dev, OMAP4_I2C_IRQENABLE_CLR, IRQENABLE_XDR | IRQENABLE_RDR |
94                        IRQENABLE_XRDY | IRQENABLE_RRDY | IRQENABLE_ARDY | IRQENABLE_NACK);
95}
96
97static void omap4_i2c_wait_for_bb(i2c_bus_t *bus)
98{
99    omap4_i2c_dev_t *dev = bus->priv;
100    while (omap4_i2c_reg_read(dev, OMAP4_I2C_IRQSTATUS_RAW) & IRQSTATUS_BB);
101}
102
103static int omap4_i2c_controller_init(i2c_bus_t *bus)
104{
105    omap4_i2c_dev_t *dev = bus->priv;
106
107    /* set prescaler and SCL timings */
108    int internal_clock;
109    uint16_t scll, sclh;
110    uint16_t prescale;
111
112    /* these values are taken from Table 23-9, OMAP4460 Technical Reference Manual, version AB */
113    switch (dev->speed) {
114    case I2C_SLAVE_SPEED_STANDARD:
115        internal_clock = 4000000;
116        scll = 13;
117        sclh = 15;
118        break;
119    case I2C_SLAVE_SPEED_FAST:
120        internal_clock = 9600000;
121        scll = 7;
122        sclh = 5;
123        break;
124    default:
125        ZF_LOGE("Unsupported I2C speed!");
126        return -1;
127    }
128
129    prescale = AM335X_I2C_SCLK / internal_clock - 1;
130
131    /* disable I2C module for reconfiguration */
132    omap4_i2c_reg_write(dev, OMAP4_I2C_CON, 0);
133
134    /* write clock configuration */
135    omap4_i2c_reg_write(dev, OMAP4_I2C_PSC, prescale);
136    omap4_i2c_reg_write(dev, OMAP4_I2C_SCLL, scll);
137    omap4_i2c_reg_write(dev, OMAP4_I2C_SCLH, sclh);
138
139    /* clamp FIFO depth to maximum possible size */
140    dev->fifo_threshold = MIN(dev->fifo_threshold, AM335X_I2C_MAX_FIFODEPTH);
141    /* configure FIFO */
142    uint16_t buf_reg = ((dev->fifo_threshold - 1) << BUF_RXTRSH_OFFSET) & BUF_RXTRSH_MASK;
143    buf_reg |= (dev->fifo_threshold - 1) & BUF_TXTRSH_MASK;
144    omap4_i2c_reg_write(dev, OMAP4_I2C_BUF, buf_reg);
145
146    /* enable module */
147    omap4_i2c_reg_write(dev, OMAP4_I2C_CON, CON_I2C_EN);
148
149    return 0;
150}
151
152static int omap4_i2c_do_xfer(i2c_slave_t *slave, void *data, size_t size, bool write,
153                             bool repeat_start, i2c_callback_fn cb, void *token)
154{
155    ZF_LOGV("%s %zu bytes from slave 0x%x", write ? "writing" : "reading", size, slave->address);
156    i2c_bus_t *bus = slave->bus;
157    omap4_i2c_dev_t *dev = bus->priv;
158
159    if (dev->busy) {
160        ZF_LOGE("i2c bus is busy ");
161        return -1;
162    }
163
164    if (size == 0) {
165        cb(bus, I2CSTAT_COMPLETE, size, token);
166        return 0;
167    }
168
169    /* skip polling for bus-busy if the device is in repeat-start mode */
170    if (!dev->repeat_start) {
171        omap4_i2c_wait_for_bb(bus);
172    }
173
174    if (slave->max_speed < dev->speed) {
175        uint32_t freq = i2c_set_speed(bus, slave->max_speed);
176        if (freq != i2c_speed_freqs[slave->max_speed]) {
177            ZF_LOGE("failed to set speed");
178            return -1;
179        }
180    }
181
182    omap4_i2c_reg_write(dev, OMAP4_I2C_SA, slave->address);
183
184    if (write) {
185        dev->mode = I2CMODE_TX;
186    } else {
187        dev->mode = I2CMODE_RX;
188    }
189    dev->buf = data;
190    dev->buf_len = size;
191    dev->buf_pos = 0;
192    dev->repeat_start = repeat_start;
193    dev->status = I2CSTAT_COMPLETE;
194
195    omap4_i2c_reg_write(dev, OMAP4_I2C_CNT, size);
196
197    /* clear FIFO */
198    uint16_t buf_reg = omap4_i2c_reg_read(dev, OMAP4_I2C_BUF);
199    buf_reg |= BUF_RXFIFO_CLR | BUF_TXFIFO_CLR;
200    omap4_i2c_reg_write(dev, OMAP4_I2C_BUF, buf_reg);
201
202    uint16_t con_reg = CON_I2C_EN | CON_MST | CON_STT;
203    if (!repeat_start) {
204        con_reg |= CON_STP;
205    }
206    if (write) {
207        con_reg |= CON_TRX;
208    }
209
210    omap4_i2c_reg_write(dev, OMAP4_I2C_CON, con_reg);
211
212    dev->busy = true;
213    if (cb == NULL) {
214        /* synchronous */
215        while (dev->busy) {
216            i2c_handle_irq(bus);
217        }
218        return dev->buf_pos;
219    } else {
220        /* asynchronous */
221        bus->cb = cb;
222        bus->token = token;
223
224        omap4_i2c_enable_interrupts(dev);
225        return size;
226    }
227    return 0;
228}
229
230static int omap4_i2c_slave_read(i2c_slave_t *slave, void *data, size_t size,
231                                bool repeat_start, i2c_callback_fn cb, void *token)
232{
233    return omap4_i2c_do_xfer(slave, data, size, false, repeat_start, cb, token);
234}
235
236static int omap4_i2c_slave_write(i2c_slave_t *slave, const void *data, size_t size,
237                                 bool repeat_start, i2c_callback_fn cb, void *token)
238{
239    return omap4_i2c_do_xfer(slave, (void *) data, size, true, repeat_start, cb, token);
240}
241
242static int omap4_i2c_slave_init(i2c_bus_t *bus, int address, enum i2c_slave_address_size address_size,
243                                enum i2c_slave_speed max_speed, uint32_t i2c_opts, i2c_slave_t *i2c_slave)
244{
245    assert(i2c_slave != NULL);
246
247    if (address_size == I2C_SLAVE_ADDR_7BIT) {
248        address = i2c_extract_address(address);
249    }
250
251    *i2c_slave = (i2c_slave_t) {
252        .address = address,
253        .address_size = address_size,
254        .max_speed = max_speed,
255        .i2c_opts = i2c_opts,
256        .bus = bus,
257
258        .slave_read = &omap4_i2c_slave_read,
259        .slave_write = &omap4_i2c_slave_write
260    };
261
262    return 0;
263}
264
265static long omap4_i2c_set_speed(i2c_bus_t *bus, enum i2c_slave_speed speed)
266{
267    omap4_i2c_dev_t *dev = bus->priv;
268    dev->speed = speed;
269
270    omap4_i2c_wait_for_bb(bus);
271    int err = omap4_i2c_controller_init(bus);
272    if (err) {
273        return err;
274    }
275
276    return i2c_speed_freqs[speed];
277}
278
279static int omap4_i2c_master_stop(i2c_bus_t *bus)
280{
281    omap4_i2c_dev_t *dev = bus->priv;
282
283    uint16_t con_reg = omap4_i2c_reg_read(dev, OMAP4_I2C_CON);
284    con_reg |= CON_STP;
285    omap4_i2c_reg_write(dev, OMAP4_I2C_CON, con_reg);
286
287    omap4_i2c_wait_for_bb(bus);
288
289    omap4_i2c_reg_write(dev, OMAP4_I2C_CON, 0);
290    return 0;
291}
292
293static void omap4_i2c_handle_irq(i2c_bus_t *bus)
294{
295    omap4_i2c_dev_t *dev = bus->priv;
296    size_t bytes = 0;
297
298    uint16_t irq_status = omap4_i2c_reg_read(dev, OMAP4_I2C_IRQSTATUS_RAW);
299    if (dev->interrupts_enabled) {
300        uint16_t irq_enabled = omap4_i2c_reg_read(dev, OMAP4_I2C_IRQENABLE_SET);
301
302        /* mask disabled interrupts */
303        irq_status &= irq_enabled;
304    }
305
306    ZF_LOGV("IRQSTATUS = 0x%x", irq_status);
307
308    if (irq_status & IRQSTATUS_NACK) {
309        /* NACK from slave */
310        ZF_LOGV("NACK");
311        dev->status = I2CSTAT_NACK;
312        omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_NACK);
313    }
314
315    if (irq_status & IRQSTATUS_ARDY) {
316        /* transfer complete */
317        ZF_LOGV("ARDY");
318
319        omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_ARDY | IRQSTATUS_RRDY | IRQSTATUS_XRDY |
320                            IRQSTATUS_RDR | IRQSTATUS_XDR);
321
322        /* run callback */
323        dev->mode = I2CMODE_IDLE;
324        dev->busy = false;
325        if (bus->cb) {
326            bus->cb(bus, dev->status, dev->buf_pos, bus->token);
327            bus->cb = NULL;
328            bus->token = NULL;
329        }
330
331        if (dev->interrupts_enabled) {
332            omap4_i2c_disable_interrupts(dev);
333        }
334
335        return;
336    }
337
338    if (dev->mode == I2CMODE_RX) {
339        if (irq_status & IRQSTATUS_RDR) {
340            /* receive drain */
341            ZF_LOGV("RDR");
342            bytes = dev->buf_len - dev->buf_pos;
343        } else if (irq_status & IRQSTATUS_RRDY) {
344            /* receive ready */
345            ZF_LOGV("RRDY");
346            bytes = MIN(dev->fifo_threshold, dev->buf_len - dev->buf_pos);
347        }
348
349        for (size_t i = 0; i < bytes; i++) {
350            dev->buf[dev->buf_pos] = omap4_i2c_reg_read(dev, OMAP4_I2C_DATA);
351            dev->buf_pos++;
352        }
353
354        if (irq_status & IRQSTATUS_RDR) {
355            omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_RDR);
356        }
357        if (irq_status & IRQSTATUS_RRDY) {
358            omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_RRDY);
359        }
360    }
361
362    if (dev->mode == I2CMODE_TX) {
363        if (irq_status & IRQSTATUS_XDR) {
364            /* transmit drain */
365            ZF_LOGV("XDR");
366            bytes = dev->buf_len - dev->buf_pos;
367        } else if (irq_status & IRQSTATUS_XRDY) {
368            /* transmit ready */
369            ZF_LOGV("XRDY");
370            bytes = MIN(dev->fifo_threshold, dev->buf_len - dev->buf_pos);
371        }
372
373        for (size_t i = 0; i < bytes; i++) {
374            omap4_i2c_reg_write(dev, OMAP4_I2C_DATA, dev->buf[dev->buf_pos]);
375            dev->buf_pos++;
376        }
377
378        if (irq_status & IRQSTATUS_XDR) {
379            omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_XDR);
380        }
381        if (irq_status & IRQSTATUS_XRDY) {
382            omap4_i2c_reg_write(dev, OMAP4_I2C_IRQSTATUS, IRQSTATUS_XRDY);
383        }
384    }
385}
386
387int omap4_i2c_init(void *vaddr, int irq_id, ps_io_ops_t *io_ops, i2c_bus_t *i2c_bus)
388{
389    struct omap4_i2c_dev *dev;
390
391    int error = ps_malloc(&io_ops->malloc_ops, sizeof(omap4_i2c_dev_t), (void **) &dev);
392    if (error) {
393        ZF_LOGE("Failed to allocate device");
394        return -1;
395    }
396
397    *dev = (omap4_i2c_dev_t) {
398        .regs = vaddr,
399        .irq_id = irq_id,
400        .speed = I2C_SLAVE_SPEED_FAST,
401        .fifo_threshold = AM335X_I2C_MAX_FIFODEPTH - 1
402    };
403    *i2c_bus = (i2c_bus_t) {
404        .slave_init = omap4_i2c_slave_init,
405        .set_speed = omap4_i2c_set_speed,
406        .master_stop = omap4_i2c_master_stop,
407        .handle_irq = omap4_i2c_handle_irq,
408        .priv = dev
409    };
410
411    error = omap4_i2c_controller_init(i2c_bus);
412    if (error) {
413        ZF_LOGE("Failed to initialise I2C controller");
414        ps_free(&io_ops->malloc_ops, sizeof(omap4_i2c_dev_t), dev);
415        i2c_bus->priv = NULL;
416        return -1;
417    }
418
419    return 0;
420}
421
422int i2c_init(enum i2c_id id, ps_io_ops_t *io_ops, i2c_bus_t *i2c_bus)
423{
424    void *vaddr;
425    int irq_id;
426
427    assert(io_ops != NULL);
428    assert(i2c_bus != NULL);
429
430    switch (id) {
431    case AM335X_I2C0:
432    case AM335X_I2C1:
433    case AM335X_I2C2:
434        vaddr = ps_pmem_map(io_ops, pmems[id], false, PS_MEM_NORMAL);
435        if (vaddr == NULL) {
436            ZF_LOGE("Failed to map I2C controller %d", id);
437            return -1;
438        }
439
440        irq_id = ps_irq_register(&io_ops->irq_ops, irqs[id], i2c_handle_irq_wrapper, i2c_bus);
441        if (irq_id < 0) {
442            ZF_LOGE("Failed to register IRQ handler for I2C controller %d", id);
443            ps_pmem_unmap(io_ops, pmems[id], vaddr);
444            return -1;
445        }
446
447        break;
448    default:
449        ZF_LOGE("Unknown I2C controller %d", id);
450        return -1;
451    }
452
453    return omap4_i2c_init(vaddr, irq_id, io_ops, i2c_bus);
454}
455