omap_i2c.c (15005B)
1/* 2 * TI OMAP on-chip I2C controller. Only "new I2C" mode supported. 3 * 4 * Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include "qemu/osdep.h" 21#include "qemu/log.h" 22#include "qemu/module.h" 23#include "hw/i2c/i2c.h" 24#include "hw/irq.h" 25#include "hw/qdev-properties.h" 26#include "hw/arm/omap.h" 27#include "hw/sysbus.h" 28#include "qemu/error-report.h" 29#include "qapi/error.h" 30 31struct OMAPI2CState { 32 SysBusDevice parent_obj; 33 34 MemoryRegion iomem; 35 qemu_irq irq; 36 qemu_irq drq[2]; 37 I2CBus *bus; 38 39 uint8_t revision; 40 void *iclk; 41 void *fclk; 42 43 uint8_t mask; 44 uint16_t stat; 45 uint16_t dma; 46 uint16_t count; 47 int count_cur; 48 uint32_t fifo; 49 int rxlen; 50 int txlen; 51 uint16_t control; 52 uint16_t addr[2]; 53 uint8_t divider; 54 uint8_t times[2]; 55 uint16_t test; 56}; 57 58#define OMAP2_INTR_REV 0x34 59#define OMAP2_GC_REV 0x34 60 61static void omap_i2c_interrupts_update(OMAPI2CState *s) 62{ 63 qemu_set_irq(s->irq, s->stat & s->mask); 64 if ((s->dma >> 15) & 1) /* RDMA_EN */ 65 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */ 66 if ((s->dma >> 7) & 1) /* XDMA_EN */ 67 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */ 68} 69 70static void omap_i2c_fifo_run(OMAPI2CState *s) 71{ 72 int ack = 1; 73 74 if (!i2c_bus_busy(s->bus)) 75 return; 76 77 if ((s->control >> 2) & 1) { /* RM */ 78 if ((s->control >> 1) & 1) { /* STP */ 79 i2c_end_transfer(s->bus); 80 s->control &= ~(1 << 1); /* STP */ 81 s->count_cur = s->count; 82 s->txlen = 0; 83 } else if ((s->control >> 9) & 1) { /* TRX */ 84 while (ack && s->txlen) 85 ack = (i2c_send(s->bus, 86 (s->fifo >> ((-- s->txlen) << 3)) & 87 0xff) >= 0); 88 s->stat |= 1 << 4; /* XRDY */ 89 } else { 90 while (s->rxlen < 4) 91 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); 92 s->stat |= 1 << 3; /* RRDY */ 93 } 94 } else { 95 if ((s->control >> 9) & 1) { /* TRX */ 96 while (ack && s->count_cur && s->txlen) { 97 ack = (i2c_send(s->bus, 98 (s->fifo >> ((-- s->txlen) << 3)) & 99 0xff) >= 0); 100 s->count_cur --; 101 } 102 if (ack && s->count_cur) 103 s->stat |= 1 << 4; /* XRDY */ 104 else 105 s->stat &= ~(1 << 4); /* XRDY */ 106 if (!s->count_cur) { 107 s->stat |= 1 << 2; /* ARDY */ 108 s->control &= ~(1 << 10); /* MST */ 109 } 110 } else { 111 while (s->count_cur && s->rxlen < 4) { 112 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3); 113 s->count_cur --; 114 } 115 if (s->rxlen) 116 s->stat |= 1 << 3; /* RRDY */ 117 else 118 s->stat &= ~(1 << 3); /* RRDY */ 119 } 120 if (!s->count_cur) { 121 if ((s->control >> 1) & 1) { /* STP */ 122 i2c_end_transfer(s->bus); 123 s->control &= ~(1 << 1); /* STP */ 124 s->count_cur = s->count; 125 s->txlen = 0; 126 } else { 127 s->stat |= 1 << 2; /* ARDY */ 128 s->control &= ~(1 << 10); /* MST */ 129 } 130 } 131 } 132 133 s->stat |= (!ack) << 1; /* NACK */ 134 if (!ack) 135 s->control &= ~(1 << 1); /* STP */ 136} 137 138static void omap_i2c_reset(DeviceState *dev) 139{ 140 OMAPI2CState *s = OMAP_I2C(dev); 141 142 s->mask = 0; 143 s->stat = 0; 144 s->dma = 0; 145 s->count = 0; 146 s->count_cur = 0; 147 s->fifo = 0; 148 s->rxlen = 0; 149 s->txlen = 0; 150 s->control = 0; 151 s->addr[0] = 0; 152 s->addr[1] = 0; 153 s->divider = 0; 154 s->times[0] = 0; 155 s->times[1] = 0; 156 s->test = 0; 157} 158 159static uint32_t omap_i2c_read(void *opaque, hwaddr addr) 160{ 161 OMAPI2CState *s = opaque; 162 int offset = addr & OMAP_MPUI_REG_MASK; 163 uint16_t ret; 164 165 switch (offset) { 166 case 0x00: /* I2C_REV */ 167 return s->revision; /* REV */ 168 169 case 0x04: /* I2C_IE */ 170 return s->mask; 171 172 case 0x08: /* I2C_STAT */ 173 return s->stat | (i2c_bus_busy(s->bus) << 12); 174 175 case 0x0c: /* I2C_IV */ 176 if (s->revision >= OMAP2_INTR_REV) 177 break; 178 ret = ctz32(s->stat & s->mask); 179 if (ret != 32) { 180 s->stat ^= 1 << ret; 181 ret++; 182 } else { 183 ret = 0; 184 } 185 omap_i2c_interrupts_update(s); 186 return ret; 187 188 case 0x10: /* I2C_SYSS */ 189 return (s->control >> 15) & 1; /* I2C_EN */ 190 191 case 0x14: /* I2C_BUF */ 192 return s->dma; 193 194 case 0x18: /* I2C_CNT */ 195 return s->count_cur; /* DCOUNT */ 196 197 case 0x1c: /* I2C_DATA */ 198 ret = 0; 199 if (s->control & (1 << 14)) { /* BE */ 200 ret |= ((s->fifo >> 0) & 0xff) << 8; 201 ret |= ((s->fifo >> 8) & 0xff) << 0; 202 } else { 203 ret |= ((s->fifo >> 8) & 0xff) << 8; 204 ret |= ((s->fifo >> 0) & 0xff) << 0; 205 } 206 if (s->rxlen == 1) { 207 s->stat |= 1 << 15; /* SBD */ 208 s->rxlen = 0; 209 } else if (s->rxlen > 1) { 210 if (s->rxlen > 2) 211 s->fifo >>= 16; 212 s->rxlen -= 2; 213 } else { 214 /* XXX: remote access (qualifier) error - what's that? */ 215 } 216 if (!s->rxlen) { 217 s->stat &= ~(1 << 3); /* RRDY */ 218 if (((s->control >> 10) & 1) && /* MST */ 219 ((~s->control >> 9) & 1)) { /* TRX */ 220 s->stat |= 1 << 2; /* ARDY */ 221 s->control &= ~(1 << 10); /* MST */ 222 } 223 } 224 s->stat &= ~(1 << 11); /* ROVR */ 225 omap_i2c_fifo_run(s); 226 omap_i2c_interrupts_update(s); 227 return ret; 228 229 case 0x20: /* I2C_SYSC */ 230 return 0; 231 232 case 0x24: /* I2C_CON */ 233 return s->control; 234 235 case 0x28: /* I2C_OA */ 236 return s->addr[0]; 237 238 case 0x2c: /* I2C_SA */ 239 return s->addr[1]; 240 241 case 0x30: /* I2C_PSC */ 242 return s->divider; 243 244 case 0x34: /* I2C_SCLL */ 245 return s->times[0]; 246 247 case 0x38: /* I2C_SCLH */ 248 return s->times[1]; 249 250 case 0x3c: /* I2C_SYSTEST */ 251 if (s->test & (1 << 15)) { /* ST_EN */ 252 s->test ^= 0xa; 253 return s->test; 254 } else 255 return s->test & ~0x300f; 256 } 257 258 OMAP_BAD_REG(addr); 259 return 0; 260} 261 262static void omap_i2c_write(void *opaque, hwaddr addr, 263 uint32_t value) 264{ 265 OMAPI2CState *s = opaque; 266 int offset = addr & OMAP_MPUI_REG_MASK; 267 int nack; 268 269 switch (offset) { 270 case 0x00: /* I2C_REV */ 271 case 0x0c: /* I2C_IV */ 272 case 0x10: /* I2C_SYSS */ 273 OMAP_RO_REG(addr); 274 return; 275 276 case 0x04: /* I2C_IE */ 277 s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f); 278 break; 279 280 case 0x08: /* I2C_STAT */ 281 if (s->revision < OMAP2_INTR_REV) { 282 OMAP_RO_REG(addr); 283 return; 284 } 285 286 /* RRDY and XRDY are reset by hardware. (in all versions???) */ 287 s->stat &= ~(value & 0x27); 288 omap_i2c_interrupts_update(s); 289 break; 290 291 case 0x14: /* I2C_BUF */ 292 s->dma = value & 0x8080; 293 if (value & (1 << 15)) /* RDMA_EN */ 294 s->mask &= ~(1 << 3); /* RRDY_IE */ 295 if (value & (1 << 7)) /* XDMA_EN */ 296 s->mask &= ~(1 << 4); /* XRDY_IE */ 297 break; 298 299 case 0x18: /* I2C_CNT */ 300 s->count = value; /* DCOUNT */ 301 break; 302 303 case 0x1c: /* I2C_DATA */ 304 if (s->txlen > 2) { 305 /* XXX: remote access (qualifier) error - what's that? */ 306 break; 307 } 308 s->fifo <<= 16; 309 s->txlen += 2; 310 if (s->control & (1 << 14)) { /* BE */ 311 s->fifo |= ((value >> 8) & 0xff) << 8; 312 s->fifo |= ((value >> 0) & 0xff) << 0; 313 } else { 314 s->fifo |= ((value >> 0) & 0xff) << 8; 315 s->fifo |= ((value >> 8) & 0xff) << 0; 316 } 317 s->stat &= ~(1 << 10); /* XUDF */ 318 if (s->txlen > 2) 319 s->stat &= ~(1 << 4); /* XRDY */ 320 omap_i2c_fifo_run(s); 321 omap_i2c_interrupts_update(s); 322 break; 323 324 case 0x20: /* I2C_SYSC */ 325 if (s->revision < OMAP2_INTR_REV) { 326 OMAP_BAD_REG(addr); 327 return; 328 } 329 330 if (value & 2) { 331 omap_i2c_reset(DEVICE(s)); 332 } 333 break; 334 335 case 0x24: /* I2C_CON */ 336 s->control = value & 0xcf87; 337 if (~value & (1 << 15)) { /* I2C_EN */ 338 if (s->revision < OMAP2_INTR_REV) { 339 omap_i2c_reset(DEVICE(s)); 340 } 341 break; 342 } 343 if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ 344 qemu_log_mask(LOG_UNIMP, "%s: I^2C slave mode not supported\n", 345 __func__); 346 break; 347 } 348 if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */ 349 qemu_log_mask(LOG_UNIMP, 350 "%s: 10-bit addressing mode not supported\n", 351 __func__); 352 break; 353 } 354 if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */ 355 nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */ 356 (~value >> 9) & 1); /* TRX */ 357 s->stat |= nack << 1; /* NACK */ 358 s->control &= ~(1 << 0); /* STT */ 359 s->fifo = 0; 360 if (nack) 361 s->control &= ~(1 << 1); /* STP */ 362 else { 363 s->count_cur = s->count; 364 omap_i2c_fifo_run(s); 365 } 366 omap_i2c_interrupts_update(s); 367 } 368 break; 369 370 case 0x28: /* I2C_OA */ 371 s->addr[0] = value & 0x3ff; 372 break; 373 374 case 0x2c: /* I2C_SA */ 375 s->addr[1] = value & 0x3ff; 376 break; 377 378 case 0x30: /* I2C_PSC */ 379 s->divider = value; 380 break; 381 382 case 0x34: /* I2C_SCLL */ 383 s->times[0] = value; 384 break; 385 386 case 0x38: /* I2C_SCLH */ 387 s->times[1] = value; 388 break; 389 390 case 0x3c: /* I2C_SYSTEST */ 391 s->test = value & 0xf80f; 392 if (value & (1 << 11)) /* SBB */ 393 if (s->revision >= OMAP2_INTR_REV) { 394 s->stat |= 0x3f; 395 omap_i2c_interrupts_update(s); 396 } 397 if (value & (1 << 15)) { /* ST_EN */ 398 qemu_log_mask(LOG_UNIMP, 399 "%s: System Test not supported\n", __func__); 400 } 401 break; 402 403 default: 404 OMAP_BAD_REG(addr); 405 return; 406 } 407} 408 409static void omap_i2c_writeb(void *opaque, hwaddr addr, 410 uint32_t value) 411{ 412 OMAPI2CState *s = opaque; 413 int offset = addr & OMAP_MPUI_REG_MASK; 414 415 switch (offset) { 416 case 0x1c: /* I2C_DATA */ 417 if (s->txlen > 2) { 418 /* XXX: remote access (qualifier) error - what's that? */ 419 break; 420 } 421 s->fifo <<= 8; 422 s->txlen += 1; 423 s->fifo |= value & 0xff; 424 s->stat &= ~(1 << 10); /* XUDF */ 425 if (s->txlen > 2) 426 s->stat &= ~(1 << 4); /* XRDY */ 427 omap_i2c_fifo_run(s); 428 omap_i2c_interrupts_update(s); 429 break; 430 431 default: 432 OMAP_BAD_REG(addr); 433 return; 434 } 435} 436 437static uint64_t omap_i2c_readfn(void *opaque, hwaddr addr, 438 unsigned size) 439{ 440 switch (size) { 441 case 2: 442 return omap_i2c_read(opaque, addr); 443 default: 444 return omap_badwidth_read16(opaque, addr); 445 } 446} 447 448static void omap_i2c_writefn(void *opaque, hwaddr addr, 449 uint64_t value, unsigned size) 450{ 451 switch (size) { 452 case 1: 453 /* Only the last fifo write can be 8 bit. */ 454 omap_i2c_writeb(opaque, addr, value); 455 break; 456 case 2: 457 omap_i2c_write(opaque, addr, value); 458 break; 459 default: 460 omap_badwidth_write16(opaque, addr, value); 461 break; 462 } 463} 464 465static const MemoryRegionOps omap_i2c_ops = { 466 .read = omap_i2c_readfn, 467 .write = omap_i2c_writefn, 468 .valid.min_access_size = 1, 469 .valid.max_access_size = 4, 470 .endianness = DEVICE_NATIVE_ENDIAN, 471}; 472 473static void omap_i2c_init(Object *obj) 474{ 475 DeviceState *dev = DEVICE(obj); 476 OMAPI2CState *s = OMAP_I2C(obj); 477 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 478 479 sysbus_init_irq(sbd, &s->irq); 480 sysbus_init_irq(sbd, &s->drq[0]); 481 sysbus_init_irq(sbd, &s->drq[1]); 482 sysbus_init_mmio(sbd, &s->iomem); 483 s->bus = i2c_init_bus(dev, NULL); 484} 485 486static void omap_i2c_realize(DeviceState *dev, Error **errp) 487{ 488 OMAPI2CState *s = OMAP_I2C(dev); 489 490 memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c", 491 (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000); 492 493 if (!s->fclk) { 494 error_setg(errp, "omap_i2c: fclk not connected"); 495 return; 496 } 497 if (s->revision >= OMAP2_INTR_REV && !s->iclk) { 498 /* Note that OMAP1 doesn't have a separate interface clock */ 499 error_setg(errp, "omap_i2c: iclk not connected"); 500 return; 501 } 502} 503 504void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk) 505{ 506 i2c->iclk = clk; 507} 508 509void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk) 510{ 511 i2c->fclk = clk; 512} 513 514static Property omap_i2c_properties[] = { 515 DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0), 516 DEFINE_PROP_END_OF_LIST(), 517}; 518 519static void omap_i2c_class_init(ObjectClass *klass, void *data) 520{ 521 DeviceClass *dc = DEVICE_CLASS(klass); 522 523 device_class_set_props(dc, omap_i2c_properties); 524 dc->reset = omap_i2c_reset; 525 /* Reason: pointer properties "iclk", "fclk" */ 526 dc->user_creatable = false; 527 dc->realize = omap_i2c_realize; 528} 529 530static const TypeInfo omap_i2c_info = { 531 .name = TYPE_OMAP_I2C, 532 .parent = TYPE_SYS_BUS_DEVICE, 533 .instance_size = sizeof(OMAPI2CState), 534 .instance_init = omap_i2c_init, 535 .class_init = omap_i2c_class_init, 536}; 537 538static void omap_i2c_register_types(void) 539{ 540 type_register_static(&omap_i2c_info); 541} 542 543I2CBus *omap_i2c_bus(DeviceState *omap_i2c) 544{ 545 OMAPI2CState *s = OMAP_I2C(omap_i2c); 546 return s->bus; 547} 548 549type_init(omap_i2c_register_types)