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