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