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