1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdint.h>
6#include <string.h>
7#include <threads.h>
8#include <unistd.h>
9
10#include <bits/limits.h>
11#include <ddk/binding.h>
12#include <ddk/debug.h>
13#include <ddk/device.h>
14#include <ddk/protocol/i2c-impl.h>
15#include <ddk/protocol/platform-bus.h>
16#include <ddk/protocol/platform-defs.h>
17#include <ddk/protocol/platform-device.h>
18#include <hw/reg.h>
19
20#include <zircon/assert.h>
21#include <zircon/types.h>
22
23#define I2C_ERROR_SIGNAL ZX_USER_SIGNAL_0
24#define I2C_TXN_COMPLETE_SIGNAL ZX_USER_SIGNAL_1
25
26#define AML_I2C_CONTROL_REG_START      (uint32_t)(1 << 0)
27#define AML_I2C_CONTROL_REG_ACK_IGNORE (uint32_t)(1 << 1)
28#define AML_I2C_CONTROL_REG_STATUS     (uint32_t)(1 << 2)
29#define AML_I2C_CONTROL_REG_ERR        (uint32_t)(1 << 3)
30
31#define AML_I2C_MAX_TRANSFER 256
32
33typedef volatile struct {
34    uint32_t    control;
35    uint32_t    slave_addr;
36    uint32_t    token_list_0;
37    uint32_t    token_list_1;
38    uint32_t    token_wdata_0;
39    uint32_t    token_wdata_1;
40    uint32_t    token_rdata_0;
41    uint32_t    token_rdata_1;
42} __PACKED aml_i2c_regs_t;
43
44typedef enum {
45    TOKEN_END,
46    TOKEN_START,
47    TOKEN_SLAVE_ADDR_WR,
48    TOKEN_SLAVE_ADDR_RD,
49    TOKEN_DATA,
50    TOKEN_DATA_LAST,
51    TOKEN_STOP
52} aml_i2c_token_t;
53
54typedef struct {
55    zx_handle_t         irq;
56    zx_handle_t         event;
57    io_buffer_t         regs_iobuff;
58    aml_i2c_regs_t*     virt_regs;
59    zx_duration_t       timeout;
60} aml_i2c_dev_t;
61
62typedef struct {
63    platform_device_protocol_t pdev;
64    i2c_impl_protocol_t i2c;
65    zx_device_t* zxdev;
66    aml_i2c_dev_t* i2c_devs;
67    size_t dev_count;
68} aml_i2c_t;
69
70static zx_status_t aml_i2c_set_slave_addr(aml_i2c_dev_t *dev, uint16_t addr) {
71
72    addr &= 0x7f;
73    uint32_t reg = dev->virt_regs->slave_addr;
74    reg = reg & ~0xff;
75    reg = reg | ((addr << 1) & 0xff);
76    dev->virt_regs->slave_addr = reg;
77
78    return ZX_OK;
79}
80
81static int aml_i2c_irq_thread(void *arg) {
82
83    aml_i2c_dev_t *dev = arg;
84    zx_status_t status;
85
86    while (1) {
87        status = zx_interrupt_wait(dev->irq, NULL);
88        if (status != ZX_OK) {
89            zxlogf(ERROR, "i2c: interrupt error\n");
90            continue;
91        }
92        uint32_t reg =  dev->virt_regs->control;
93        if (reg & AML_I2C_CONTROL_REG_ERR) {
94            zx_object_signal(dev->event, 0, I2C_ERROR_SIGNAL);
95            zxlogf(ERROR,"i2c: error on bus\n");
96        } else {
97            zx_object_signal(dev->event, 0, I2C_TXN_COMPLETE_SIGNAL);
98        }
99    }
100    return ZX_OK;
101}
102
103static zx_status_t aml_i2c_dumpstate(aml_i2c_dev_t *dev) {
104
105    printf("control reg      : %08x\n",dev->virt_regs->control);
106    printf("slave addr  reg  : %08x\n",dev->virt_regs->slave_addr);
107    printf("token list0 reg  : %08x\n",dev->virt_regs->token_list_0);
108    printf("token list1 reg  : %08x\n",dev->virt_regs->token_list_1);
109    printf("token wdata0     : %08x\n",dev->virt_regs->token_wdata_0);
110    printf("token wdata1     : %08x\n",dev->virt_regs->token_wdata_1);
111    printf("token rdata0     : %08x\n",dev->virt_regs->token_rdata_0);
112    printf("token rdata1     : %08x\n",dev->virt_regs->token_rdata_1);
113
114    return ZX_OK;
115}
116
117static zx_status_t aml_i2c_start_xfer(aml_i2c_dev_t *dev) {
118    //First have to clear the start bit before setting (RTFM)
119    dev->virt_regs->control &= ~AML_I2C_CONTROL_REG_START;
120    dev->virt_regs->control |= AML_I2C_CONTROL_REG_START;
121    return ZX_OK;
122}
123
124static zx_status_t aml_i2c_wait_event(aml_i2c_dev_t* dev, uint32_t sig_mask) {
125
126    zx_time_t deadline = zx_deadline_after(dev->timeout);
127    uint32_t observed;
128    sig_mask |= I2C_ERROR_SIGNAL;
129    zx_status_t status = zx_object_wait_one(dev->event, sig_mask, deadline, &observed);
130    if (status != ZX_OK) {
131        return status;
132    }
133    zx_object_signal(dev->event,observed,0);
134    if (observed & I2C_ERROR_SIGNAL)
135        return ZX_ERR_TIMED_OUT;
136    return ZX_OK;
137}
138
139static zx_status_t aml_i2c_write(aml_i2c_dev_t *dev, const uint8_t *buff, uint32_t len,
140                                 bool stop) {
141    ZX_DEBUG_ASSERT(len <= AML_I2C_MAX_TRANSFER);
142    uint32_t token_num = 0;
143    uint64_t token_reg = 0;
144
145    token_reg |= (uint64_t)TOKEN_START << (4*(token_num++));
146    token_reg |= (uint64_t)TOKEN_SLAVE_ADDR_WR << (4*(token_num++));
147
148    while (len > 0) {
149        bool is_last_iter = len <= 8;
150        uint32_t tx_size = is_last_iter ? len : 8;
151        for (uint32_t i=0; i < tx_size; i++) {
152            token_reg |= (uint64_t)TOKEN_DATA << (4*(token_num++));
153        }
154
155        if (is_last_iter && stop) {
156            token_reg |= (uint64_t)TOKEN_STOP << (4*(token_num++));
157        }
158
159        dev->virt_regs->token_list_0 = (uint32_t)(token_reg & 0xffffffff);
160        dev->virt_regs->token_list_1 =
161            (uint32_t)((token_reg >> 32) & 0xffffffff);
162
163        uint64_t wdata = 0;
164        for (uint32_t i=0; i < tx_size; i++) {
165            wdata |= (uint64_t)buff[i] << (8*i);
166        }
167
168        dev->virt_regs->token_wdata_0 = (uint32_t)(wdata & 0xffffffff);
169        dev->virt_regs->token_wdata_1 = (uint32_t)((wdata >> 32) & 0xffffffff);
170
171        aml_i2c_start_xfer(dev);
172        //while (dev->virt_regs->control & 0x4) ;;    // wait for idle
173        zx_status_t status = aml_i2c_wait_event(dev, I2C_TXN_COMPLETE_SIGNAL);
174        if (status != ZX_OK) {
175            return status;
176        }
177
178        len -= tx_size;
179        buff += tx_size;
180        token_num = 0;
181        token_reg = 0;
182    }
183
184    return ZX_OK;
185}
186
187static zx_status_t aml_i2c_read(aml_i2c_dev_t *dev, uint8_t *buff, uint32_t len, bool stop) {
188
189    ZX_DEBUG_ASSERT(len <= AML_I2C_MAX_TRANSFER);
190    uint32_t token_num = 0;
191    uint64_t token_reg = 0;
192
193    token_reg |= (uint64_t)TOKEN_START << (4*(token_num++));
194    token_reg |= (uint64_t)TOKEN_SLAVE_ADDR_RD << (4*(token_num++));
195
196    while (len > 0) {
197        bool is_last_iter = len <= 8;
198        uint32_t rx_size = is_last_iter ? len : 8;
199
200        for (uint32_t i=0; i < (rx_size - 1); i++) {
201            token_reg |= (uint64_t)TOKEN_DATA << (4*(token_num++));
202        }
203        if (is_last_iter) {
204            token_reg |= (uint64_t)TOKEN_DATA_LAST << (4*(token_num++));
205            if (stop) {
206                token_reg |= (uint64_t)TOKEN_STOP << (4*(token_num++));
207            }
208        } else {
209            token_reg |= (uint64_t)TOKEN_DATA << (4*(token_num++));
210        }
211
212        dev->virt_regs->token_list_0 = (uint32_t)(token_reg & 0xffffffff);
213        token_reg = token_reg >> 32;
214        dev->virt_regs->token_list_1 = (uint32_t)(token_reg);
215
216        //clear registers to prevent data leaking from last xfer
217        dev->virt_regs->token_rdata_0 = 0;
218        dev->virt_regs->token_rdata_1 = 0;
219
220        aml_i2c_start_xfer(dev);
221
222        zx_status_t status = aml_i2c_wait_event(dev, I2C_TXN_COMPLETE_SIGNAL);
223        if (status != ZX_OK) {
224            return status;
225        }
226
227        //while (dev->virt_regs->control & 0x4) ;;    // wait for idle
228
229        uint64_t rdata;
230        rdata = dev->virt_regs->token_rdata_0;
231        rdata |= (uint64_t)(dev->virt_regs->token_rdata_1) << 32;
232
233        for (uint32_t i=0; i < sizeof(rdata); i++) {
234            buff[i] = (uint8_t)((rdata >> (8*i) & 0xff));
235        }
236
237        len -= rx_size;
238        buff += rx_size;
239        token_num = 0;
240        token_reg = 0;
241    }
242
243    return ZX_OK;
244}
245
246/* create instance of aml_i2c_t and do basic initialization.  There will
247be one of these instances for each of the soc i2c ports.
248*/
249static zx_status_t aml_i2c_dev_init(aml_i2c_t* i2c, unsigned index) {
250    aml_i2c_dev_t* device = &i2c->i2c_devs[index];
251
252    device->timeout = ZX_SEC(1);
253
254    zx_status_t status;
255
256    status = pdev_map_mmio_buffer(&i2c->pdev, index, ZX_CACHE_POLICY_UNCACHED_DEVICE,
257                                  &device->regs_iobuff);
258    if (status != ZX_OK) {
259        zxlogf(ERROR, "aml_i2c_dev_init: pdev_map_mmio_buffer failed %d\n", status);
260        return status;
261    }
262
263    device->virt_regs = (aml_i2c_regs_t*)io_buffer_virt(&device->regs_iobuff);
264
265    status = pdev_map_interrupt(&i2c->pdev, index, &device->irq);
266    if (status != ZX_OK) {
267        return status;
268    }
269
270    status = zx_event_create(0, &device->event);
271    if (status != ZX_OK) {
272        return status;
273    }
274
275    thrd_t irqthrd;
276    thrd_create_with_name(&irqthrd, aml_i2c_irq_thread, device, "i2c_irq_thread");
277
278    return ZX_OK;
279}
280
281static uint32_t aml_i2c_get_bus_count(void* ctx) {
282    aml_i2c_t* i2c = ctx;
283
284    return i2c->dev_count;
285}
286
287static zx_status_t aml_i2c_get_max_transfer_size(void* ctx, uint32_t bus_id, size_t* out_size) {
288    *out_size = AML_I2C_MAX_TRANSFER;
289    return ZX_OK;
290}
291
292static zx_status_t aml_i2c_set_bitrate(void* ctx, uint32_t bus_id, uint32_t bitrate) {
293    // TODO(hollande,voydanoff) implement this
294    return ZX_ERR_NOT_SUPPORTED;
295}
296
297static zx_status_t aml_i2c_transact(void* ctx, uint32_t bus_id, i2c_impl_op_t* rws, size_t count) {
298    size_t i;
299    for (i = 0; i < count; ++i) {
300        if (rws[i].length > AML_I2C_MAX_TRANSFER) {
301            return ZX_ERR_OUT_OF_RANGE;
302        }
303    }
304    aml_i2c_t* i2c = ctx;
305    if (bus_id >= i2c->dev_count) {
306        return ZX_ERR_INVALID_ARGS;
307    }
308    aml_i2c_dev_t *dev = &i2c->i2c_devs[bus_id];
309
310    zx_status_t status = ZX_OK;
311    for (i = 0; i < count; ++i) {
312        status = aml_i2c_set_slave_addr(dev, rws[i].address);
313        if (status != ZX_OK) {
314            return status;
315        }
316        if (rws[i].is_read) {
317            status = aml_i2c_read(dev, rws[i].buf, rws[i].length, rws[i].stop);
318        } else {
319            status = aml_i2c_write(dev, rws[i].buf, rws[i].length, rws[i].stop);
320        }
321        if (status != ZX_OK) {
322            return status; // TODO(andresoportus) release the bus
323        }
324    }
325
326    return status;
327}
328
329static i2c_impl_protocol_ops_t i2c_ops = {
330    .get_bus_count = aml_i2c_get_bus_count,
331    .get_max_transfer_size = aml_i2c_get_max_transfer_size,
332    .set_bitrate = aml_i2c_set_bitrate,
333    .transact = aml_i2c_transact,
334};
335
336static void aml_i2c_release(void* ctx) {
337    aml_i2c_t* i2c = ctx;
338    for (unsigned i = 0; i < i2c->dev_count; i++) {
339        aml_i2c_dev_t* device = &i2c->i2c_devs[i];
340        io_buffer_release(&device->regs_iobuff);
341        zx_handle_close(device->event);
342        zx_handle_close(device->irq);
343    }
344    free(i2c->i2c_devs);
345    free(i2c);
346}
347
348static zx_protocol_device_t i2c_device_proto = {
349    .version = DEVICE_OPS_VERSION,
350    .release = aml_i2c_release,
351};
352
353static zx_status_t aml_i2c_bind(void* ctx, zx_device_t* parent) {
354    zx_status_t status;
355
356    aml_i2c_t* i2c = calloc(1, sizeof(aml_i2c_t));
357    if (!i2c) {
358        return ZX_ERR_NO_MEMORY;
359    }
360
361    if ((status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &i2c->pdev)) != ZX_OK) {
362        zxlogf(ERROR, "aml_i2c_bind: ZX_PROTOCOL_PLATFORM_DEV not available\n");
363        goto fail;
364    }
365
366    platform_bus_protocol_t pbus;
367    if ((status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_BUS, &pbus)) != ZX_OK) {
368        zxlogf(ERROR, "aml_i2c_bind: ZX_PROTOCOL_PLATFORM_BUS not available\n");
369        goto fail;
370    }
371
372    pdev_device_info_t info;
373    status = pdev_get_device_info(&i2c->pdev, &info);
374    if (status != ZX_OK) {
375        zxlogf(ERROR, "aml_i2c_bind: pdev_get_device_info failed\n");
376        goto fail;
377    }
378
379    if (info.mmio_count != info.irq_count) {
380        zxlogf(ERROR, "aml_i2c_bind: mmio_count %u does not matchirq_count %u\n",
381               info.mmio_count, info.irq_count);
382        status = ZX_ERR_INVALID_ARGS;
383        goto fail;
384    }
385    i2c->i2c_devs = calloc(info.mmio_count, sizeof(aml_i2c_dev_t));
386    if (!i2c->i2c_devs) {
387        goto fail;
388    }
389    i2c->dev_count = info.mmio_count;
390
391    for (unsigned i = 0; i < i2c->dev_count; i++) {
392        zx_status_t status = aml_i2c_dev_init(i2c, i);
393        if (status != ZX_OK) {
394            zxlogf(ERROR, "aml_i2c_bind: aml_i2c_dev_init failed: %d\n", status);
395            goto fail;
396        }
397    }
398
399    device_add_args_t args = {
400        .version = DEVICE_ADD_ARGS_VERSION,
401        .name = "aml-i2c",
402        .ctx = i2c,
403        .ops = &i2c_device_proto,
404        .flags = DEVICE_ADD_NON_BINDABLE,
405    };
406
407    status = device_add(parent, &args, &i2c->zxdev);
408    if (status != ZX_OK) {
409        zxlogf(ERROR, "aml_i2c_bind: device_add failed\n");
410        goto fail;
411    }
412
413    i2c->i2c.ops = &i2c_ops;
414    i2c->i2c.ctx = i2c;
415    pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c, NULL, NULL);
416
417    return ZX_OK;
418
419fail:
420    aml_i2c_release(i2c);
421    return status;
422}
423
424static zx_driver_ops_t aml_i2c_driver_ops = {
425    .version = DRIVER_OPS_VERSION,
426    .bind = aml_i2c_bind,
427};
428
429ZIRCON_DRIVER_BEGIN(aml_i2c, aml_i2c_driver_ops, "zircon", "0.1", 4)
430    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV),
431    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
432    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
433    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_I2C),
434ZIRCON_DRIVER_END(aml_i2c)
435