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