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 i2c_bus *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 = ffs(s->stat & s->mask); 175 if (ret) 176 s->stat ^= 1 << (ret - 1); 177 omap_i2c_interrupts_update(s); 178 return ret; 179 180 case 0x10: /* I2C_SYSS */ 181 return (s->control >> 15) & 1; /* I2C_EN */ 182 183 case 0x14: /* I2C_BUF */ 184 return s->dma; 185 186 case 0x18: /* I2C_CNT */ 187 return s->count_cur; /* DCOUNT */ 188 189 case 0x1c: /* I2C_DATA */ 190 ret = 0; 191 if (s->control & (1 << 14)) { /* BE */ 192 ret |= ((s->fifo >> 0) & 0xff) << 8; 193 ret |= ((s->fifo >> 8) & 0xff) << 0; 194 } else { 195 ret |= ((s->fifo >> 8) & 0xff) << 8; 196 ret |= ((s->fifo >> 0) & 0xff) << 0; 197 } 198 if (s->rxlen == 1) { 199 s->stat |= 1 << 15; /* SBD */ 200 s->rxlen = 0; 201 } else if (s->rxlen > 1) { 202 if (s->rxlen > 2) 203 s->fifo >>= 16; 204 s->rxlen -= 2; 205 } else { 206 /* XXX: remote access (qualifier) error - what's that? */ 207 } 208 if (!s->rxlen) { 209 s->stat &= ~(1 << 3); /* RRDY */ 210 if (((s->control >> 10) & 1) && /* MST */ 211 ((~s->control >> 9) & 1)) { /* TRX */ 212 s->stat |= 1 << 2; /* ARDY */ 213 s->control &= ~(1 << 10); /* MST */ 214 } 215 } 216 s->stat &= ~(1 << 11); /* ROVR */ 217 omap_i2c_fifo_run(s); 218 omap_i2c_interrupts_update(s); 219 return ret; 220 221 case 0x20: /* I2C_SYSC */ 222 return 0; 223 224 case 0x24: /* I2C_CON */ 225 return s->control; 226 227 case 0x28: /* I2C_OA */ 228 return s->addr[0]; 229 230 case 0x2c: /* I2C_SA */ 231 return s->addr[1]; 232 233 case 0x30: /* I2C_PSC */ 234 return s->divider; 235 236 case 0x34: /* I2C_SCLL */ 237 return s->times[0]; 238 239 case 0x38: /* I2C_SCLH */ 240 return s->times[1]; 241 242 case 0x3c: /* I2C_SYSTEST */ 243 if (s->test & (1 << 15)) { /* ST_EN */ 244 s->test ^= 0xa; 245 return s->test; 246 } else 247 return s->test & ~0x300f; 248 } 249 250 OMAP_BAD_REG(addr); 251 return 0; 252 } 253 254 static void omap_i2c_write(void *opaque, hwaddr addr, 255 uint32_t value) 256 { 257 OMAPI2CState *s = opaque; 258 int offset = addr & OMAP_MPUI_REG_MASK; 259 int nack; 260 261 switch (offset) { 262 case 0x00: /* I2C_REV */ 263 case 0x0c: /* I2C_IV */ 264 case 0x10: /* I2C_SYSS */ 265 OMAP_RO_REG(addr); 266 return; 267 268 case 0x04: /* I2C_IE */ 269 s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f); 270 break; 271 272 case 0x08: /* I2C_STAT */ 273 if (s->revision < OMAP2_INTR_REV) { 274 OMAP_RO_REG(addr); 275 return; 276 } 277 278 /* RRDY and XRDY are reset by hardware. (in all versions???) */ 279 s->stat &= ~(value & 0x27); 280 omap_i2c_interrupts_update(s); 281 break; 282 283 case 0x14: /* I2C_BUF */ 284 s->dma = value & 0x8080; 285 if (value & (1 << 15)) /* RDMA_EN */ 286 s->mask &= ~(1 << 3); /* RRDY_IE */ 287 if (value & (1 << 7)) /* XDMA_EN */ 288 s->mask &= ~(1 << 4); /* XRDY_IE */ 289 break; 290 291 case 0x18: /* I2C_CNT */ 292 s->count = value; /* DCOUNT */ 293 break; 294 295 case 0x1c: /* I2C_DATA */ 296 if (s->txlen > 2) { 297 /* XXX: remote access (qualifier) error - what's that? */ 298 break; 299 } 300 s->fifo <<= 16; 301 s->txlen += 2; 302 if (s->control & (1 << 14)) { /* BE */ 303 s->fifo |= ((value >> 8) & 0xff) << 8; 304 s->fifo |= ((value >> 0) & 0xff) << 0; 305 } else { 306 s->fifo |= ((value >> 0) & 0xff) << 8; 307 s->fifo |= ((value >> 8) & 0xff) << 0; 308 } 309 s->stat &= ~(1 << 10); /* XUDF */ 310 if (s->txlen > 2) 311 s->stat &= ~(1 << 4); /* XRDY */ 312 omap_i2c_fifo_run(s); 313 omap_i2c_interrupts_update(s); 314 break; 315 316 case 0x20: /* I2C_SYSC */ 317 if (s->revision < OMAP2_INTR_REV) { 318 OMAP_BAD_REG(addr); 319 return; 320 } 321 322 if (value & 2) { 323 omap_i2c_reset(DEVICE(s)); 324 } 325 break; 326 327 case 0x24: /* I2C_CON */ 328 s->control = value & 0xcf87; 329 if (~value & (1 << 15)) { /* I2C_EN */ 330 if (s->revision < OMAP2_INTR_REV) { 331 omap_i2c_reset(DEVICE(s)); 332 } 333 break; 334 } 335 if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ 336 fprintf(stderr, "%s: I^2C slave mode not supported\n", 337 __FUNCTION__); 338 break; 339 } 340 if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */ 341 fprintf(stderr, "%s: 10-bit addressing mode not supported\n", 342 __FUNCTION__); 343 break; 344 } 345 if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */ 346 nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */ 347 (~value >> 9) & 1); /* TRX */ 348 s->stat |= nack << 1; /* NACK */ 349 s->control &= ~(1 << 0); /* STT */ 350 s->fifo = 0; 351 if (nack) 352 s->control &= ~(1 << 1); /* STP */ 353 else { 354 s->count_cur = s->count; 355 omap_i2c_fifo_run(s); 356 } 357 omap_i2c_interrupts_update(s); 358 } 359 break; 360 361 case 0x28: /* I2C_OA */ 362 s->addr[0] = value & 0x3ff; 363 break; 364 365 case 0x2c: /* I2C_SA */ 366 s->addr[1] = value & 0x3ff; 367 break; 368 369 case 0x30: /* I2C_PSC */ 370 s->divider = value; 371 break; 372 373 case 0x34: /* I2C_SCLL */ 374 s->times[0] = value; 375 break; 376 377 case 0x38: /* I2C_SCLH */ 378 s->times[1] = value; 379 break; 380 381 case 0x3c: /* I2C_SYSTEST */ 382 s->test = value & 0xf80f; 383 if (value & (1 << 11)) /* SBB */ 384 if (s->revision >= OMAP2_INTR_REV) { 385 s->stat |= 0x3f; 386 omap_i2c_interrupts_update(s); 387 } 388 if (value & (1 << 15)) /* ST_EN */ 389 fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__); 390 break; 391 392 default: 393 OMAP_BAD_REG(addr); 394 return; 395 } 396 } 397 398 static void omap_i2c_writeb(void *opaque, hwaddr addr, 399 uint32_t value) 400 { 401 OMAPI2CState *s = opaque; 402 int offset = addr & OMAP_MPUI_REG_MASK; 403 404 switch (offset) { 405 case 0x1c: /* I2C_DATA */ 406 if (s->txlen > 2) { 407 /* XXX: remote access (qualifier) error - what's that? */ 408 break; 409 } 410 s->fifo <<= 8; 411 s->txlen += 1; 412 s->fifo |= value & 0xff; 413 s->stat &= ~(1 << 10); /* XUDF */ 414 if (s->txlen > 2) 415 s->stat &= ~(1 << 4); /* XRDY */ 416 omap_i2c_fifo_run(s); 417 omap_i2c_interrupts_update(s); 418 break; 419 420 default: 421 OMAP_BAD_REG(addr); 422 return; 423 } 424 } 425 426 static const MemoryRegionOps omap_i2c_ops = { 427 .old_mmio = { 428 .read = { 429 omap_badwidth_read16, 430 omap_i2c_read, 431 omap_badwidth_read16, 432 }, 433 .write = { 434 omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */ 435 omap_i2c_write, 436 omap_badwidth_write16, 437 }, 438 }, 439 .endianness = DEVICE_NATIVE_ENDIAN, 440 }; 441 442 static int omap_i2c_init(SysBusDevice *sbd) 443 { 444 DeviceState *dev = DEVICE(sbd); 445 OMAPI2CState *s = OMAP_I2C(dev); 446 447 if (!s->fclk) { 448 hw_error("omap_i2c: fclk not connected\n"); 449 } 450 if (s->revision >= OMAP2_INTR_REV && !s->iclk) { 451 /* Note that OMAP1 doesn't have a separate interface clock */ 452 hw_error("omap_i2c: iclk not connected\n"); 453 } 454 sysbus_init_irq(sbd, &s->irq); 455 sysbus_init_irq(sbd, &s->drq[0]); 456 sysbus_init_irq(sbd, &s->drq[1]); 457 memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c", 458 (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000); 459 sysbus_init_mmio(sbd, &s->iomem); 460 s->bus = i2c_init_bus(dev, NULL); 461 return 0; 462 } 463 464 static Property omap_i2c_properties[] = { 465 DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0), 466 DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk), 467 DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk), 468 DEFINE_PROP_END_OF_LIST(), 469 }; 470 471 static void omap_i2c_class_init(ObjectClass *klass, void *data) 472 { 473 DeviceClass *dc = DEVICE_CLASS(klass); 474 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 475 k->init = omap_i2c_init; 476 dc->props = omap_i2c_properties; 477 dc->reset = omap_i2c_reset; 478 } 479 480 static const TypeInfo omap_i2c_info = { 481 .name = TYPE_OMAP_I2C, 482 .parent = TYPE_SYS_BUS_DEVICE, 483 .instance_size = sizeof(OMAPI2CState), 484 .class_init = omap_i2c_class_init, 485 }; 486 487 static void omap_i2c_register_types(void) 488 { 489 type_register_static(&omap_i2c_info); 490 } 491 492 i2c_bus *omap_i2c_bus(DeviceState *omap_i2c) 493 { 494 OMAPI2CState *s = OMAP_I2C(omap_i2c); 495 return s->bus; 496 } 497 498 type_init(omap_i2c_register_types) 499