1*65ca801bSBALATON Zoltan /* 2*65ca801bSBALATON Zoltan * PPC4xx I2C controller emulation 3*65ca801bSBALATON Zoltan * 4*65ca801bSBALATON Zoltan * Copyright (c) 2007 Jocelyn Mayer 5*65ca801bSBALATON Zoltan * 6*65ca801bSBALATON Zoltan * Permission is hereby granted, free of charge, to any person obtaining a copy 7*65ca801bSBALATON Zoltan * of this software and associated documentation files (the "Software"), to deal 8*65ca801bSBALATON Zoltan * in the Software without restriction, including without limitation the rights 9*65ca801bSBALATON Zoltan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10*65ca801bSBALATON Zoltan * copies of the Software, and to permit persons to whom the Software is 11*65ca801bSBALATON Zoltan * furnished to do so, subject to the following conditions: 12*65ca801bSBALATON Zoltan * 13*65ca801bSBALATON Zoltan * The above copyright notice and this permission notice shall be included in 14*65ca801bSBALATON Zoltan * all copies or substantial portions of the Software. 15*65ca801bSBALATON Zoltan * 16*65ca801bSBALATON Zoltan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*65ca801bSBALATON Zoltan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*65ca801bSBALATON Zoltan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*65ca801bSBALATON Zoltan * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20*65ca801bSBALATON Zoltan * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21*65ca801bSBALATON Zoltan * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22*65ca801bSBALATON Zoltan * THE SOFTWARE. 23*65ca801bSBALATON Zoltan */ 24*65ca801bSBALATON Zoltan 25*65ca801bSBALATON Zoltan #include "qemu/osdep.h" 26*65ca801bSBALATON Zoltan #include "qapi/error.h" 27*65ca801bSBALATON Zoltan #include "qemu-common.h" 28*65ca801bSBALATON Zoltan #include "cpu.h" 29*65ca801bSBALATON Zoltan #include "hw/hw.h" 30*65ca801bSBALATON Zoltan #include "exec/address-spaces.h" 31*65ca801bSBALATON Zoltan #include "hw/ppc/ppc.h" 32*65ca801bSBALATON Zoltan #include "ppc405.h" 33*65ca801bSBALATON Zoltan 34*65ca801bSBALATON Zoltan /*#define DEBUG_I2C*/ 35*65ca801bSBALATON Zoltan 36*65ca801bSBALATON Zoltan typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; 37*65ca801bSBALATON Zoltan struct ppc4xx_i2c_t { 38*65ca801bSBALATON Zoltan qemu_irq irq; 39*65ca801bSBALATON Zoltan MemoryRegion iomem; 40*65ca801bSBALATON Zoltan uint8_t mdata; 41*65ca801bSBALATON Zoltan uint8_t lmadr; 42*65ca801bSBALATON Zoltan uint8_t hmadr; 43*65ca801bSBALATON Zoltan uint8_t cntl; 44*65ca801bSBALATON Zoltan uint8_t mdcntl; 45*65ca801bSBALATON Zoltan uint8_t sts; 46*65ca801bSBALATON Zoltan uint8_t extsts; 47*65ca801bSBALATON Zoltan uint8_t sdata; 48*65ca801bSBALATON Zoltan uint8_t lsadr; 49*65ca801bSBALATON Zoltan uint8_t hsadr; 50*65ca801bSBALATON Zoltan uint8_t clkdiv; 51*65ca801bSBALATON Zoltan uint8_t intrmsk; 52*65ca801bSBALATON Zoltan uint8_t xfrcnt; 53*65ca801bSBALATON Zoltan uint8_t xtcntlss; 54*65ca801bSBALATON Zoltan uint8_t directcntl; 55*65ca801bSBALATON Zoltan }; 56*65ca801bSBALATON Zoltan 57*65ca801bSBALATON Zoltan static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr) 58*65ca801bSBALATON Zoltan { 59*65ca801bSBALATON Zoltan ppc4xx_i2c_t *i2c; 60*65ca801bSBALATON Zoltan uint32_t ret; 61*65ca801bSBALATON Zoltan 62*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 63*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); 64*65ca801bSBALATON Zoltan #endif 65*65ca801bSBALATON Zoltan i2c = opaque; 66*65ca801bSBALATON Zoltan switch (addr) { 67*65ca801bSBALATON Zoltan case 0x00: 68*65ca801bSBALATON Zoltan /*i2c_readbyte(&i2c->mdata);*/ 69*65ca801bSBALATON Zoltan ret = i2c->mdata; 70*65ca801bSBALATON Zoltan break; 71*65ca801bSBALATON Zoltan case 0x02: 72*65ca801bSBALATON Zoltan ret = i2c->sdata; 73*65ca801bSBALATON Zoltan break; 74*65ca801bSBALATON Zoltan case 0x04: 75*65ca801bSBALATON Zoltan ret = i2c->lmadr; 76*65ca801bSBALATON Zoltan break; 77*65ca801bSBALATON Zoltan case 0x05: 78*65ca801bSBALATON Zoltan ret = i2c->hmadr; 79*65ca801bSBALATON Zoltan break; 80*65ca801bSBALATON Zoltan case 0x06: 81*65ca801bSBALATON Zoltan ret = i2c->cntl; 82*65ca801bSBALATON Zoltan break; 83*65ca801bSBALATON Zoltan case 0x07: 84*65ca801bSBALATON Zoltan ret = i2c->mdcntl; 85*65ca801bSBALATON Zoltan break; 86*65ca801bSBALATON Zoltan case 0x08: 87*65ca801bSBALATON Zoltan ret = i2c->sts; 88*65ca801bSBALATON Zoltan break; 89*65ca801bSBALATON Zoltan case 0x09: 90*65ca801bSBALATON Zoltan ret = i2c->extsts; 91*65ca801bSBALATON Zoltan break; 92*65ca801bSBALATON Zoltan case 0x0A: 93*65ca801bSBALATON Zoltan ret = i2c->lsadr; 94*65ca801bSBALATON Zoltan break; 95*65ca801bSBALATON Zoltan case 0x0B: 96*65ca801bSBALATON Zoltan ret = i2c->hsadr; 97*65ca801bSBALATON Zoltan break; 98*65ca801bSBALATON Zoltan case 0x0C: 99*65ca801bSBALATON Zoltan ret = i2c->clkdiv; 100*65ca801bSBALATON Zoltan break; 101*65ca801bSBALATON Zoltan case 0x0D: 102*65ca801bSBALATON Zoltan ret = i2c->intrmsk; 103*65ca801bSBALATON Zoltan break; 104*65ca801bSBALATON Zoltan case 0x0E: 105*65ca801bSBALATON Zoltan ret = i2c->xfrcnt; 106*65ca801bSBALATON Zoltan break; 107*65ca801bSBALATON Zoltan case 0x0F: 108*65ca801bSBALATON Zoltan ret = i2c->xtcntlss; 109*65ca801bSBALATON Zoltan break; 110*65ca801bSBALATON Zoltan case 0x10: 111*65ca801bSBALATON Zoltan ret = i2c->directcntl; 112*65ca801bSBALATON Zoltan break; 113*65ca801bSBALATON Zoltan default: 114*65ca801bSBALATON Zoltan ret = 0x00; 115*65ca801bSBALATON Zoltan break; 116*65ca801bSBALATON Zoltan } 117*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 118*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret); 119*65ca801bSBALATON Zoltan #endif 120*65ca801bSBALATON Zoltan 121*65ca801bSBALATON Zoltan return ret; 122*65ca801bSBALATON Zoltan } 123*65ca801bSBALATON Zoltan 124*65ca801bSBALATON Zoltan static void ppc4xx_i2c_writeb(void *opaque, 125*65ca801bSBALATON Zoltan hwaddr addr, uint32_t value) 126*65ca801bSBALATON Zoltan { 127*65ca801bSBALATON Zoltan ppc4xx_i2c_t *i2c; 128*65ca801bSBALATON Zoltan 129*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 130*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, 131*65ca801bSBALATON Zoltan value); 132*65ca801bSBALATON Zoltan #endif 133*65ca801bSBALATON Zoltan i2c = opaque; 134*65ca801bSBALATON Zoltan switch (addr) { 135*65ca801bSBALATON Zoltan case 0x00: 136*65ca801bSBALATON Zoltan i2c->mdata = value; 137*65ca801bSBALATON Zoltan /*i2c_sendbyte(&i2c->mdata);*/ 138*65ca801bSBALATON Zoltan break; 139*65ca801bSBALATON Zoltan case 0x02: 140*65ca801bSBALATON Zoltan i2c->sdata = value; 141*65ca801bSBALATON Zoltan break; 142*65ca801bSBALATON Zoltan case 0x04: 143*65ca801bSBALATON Zoltan i2c->lmadr = value; 144*65ca801bSBALATON Zoltan break; 145*65ca801bSBALATON Zoltan case 0x05: 146*65ca801bSBALATON Zoltan i2c->hmadr = value; 147*65ca801bSBALATON Zoltan break; 148*65ca801bSBALATON Zoltan case 0x06: 149*65ca801bSBALATON Zoltan i2c->cntl = value; 150*65ca801bSBALATON Zoltan break; 151*65ca801bSBALATON Zoltan case 0x07: 152*65ca801bSBALATON Zoltan i2c->mdcntl = value & 0xDF; 153*65ca801bSBALATON Zoltan break; 154*65ca801bSBALATON Zoltan case 0x08: 155*65ca801bSBALATON Zoltan i2c->sts &= ~(value & 0x0A); 156*65ca801bSBALATON Zoltan break; 157*65ca801bSBALATON Zoltan case 0x09: 158*65ca801bSBALATON Zoltan i2c->extsts &= ~(value & 0x8F); 159*65ca801bSBALATON Zoltan break; 160*65ca801bSBALATON Zoltan case 0x0A: 161*65ca801bSBALATON Zoltan i2c->lsadr = value; 162*65ca801bSBALATON Zoltan break; 163*65ca801bSBALATON Zoltan case 0x0B: 164*65ca801bSBALATON Zoltan i2c->hsadr = value; 165*65ca801bSBALATON Zoltan break; 166*65ca801bSBALATON Zoltan case 0x0C: 167*65ca801bSBALATON Zoltan i2c->clkdiv = value; 168*65ca801bSBALATON Zoltan break; 169*65ca801bSBALATON Zoltan case 0x0D: 170*65ca801bSBALATON Zoltan i2c->intrmsk = value; 171*65ca801bSBALATON Zoltan break; 172*65ca801bSBALATON Zoltan case 0x0E: 173*65ca801bSBALATON Zoltan i2c->xfrcnt = value & 0x77; 174*65ca801bSBALATON Zoltan break; 175*65ca801bSBALATON Zoltan case 0x0F: 176*65ca801bSBALATON Zoltan i2c->xtcntlss = value; 177*65ca801bSBALATON Zoltan break; 178*65ca801bSBALATON Zoltan case 0x10: 179*65ca801bSBALATON Zoltan i2c->directcntl = value & 0x7; 180*65ca801bSBALATON Zoltan break; 181*65ca801bSBALATON Zoltan } 182*65ca801bSBALATON Zoltan } 183*65ca801bSBALATON Zoltan 184*65ca801bSBALATON Zoltan static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr) 185*65ca801bSBALATON Zoltan { 186*65ca801bSBALATON Zoltan uint32_t ret; 187*65ca801bSBALATON Zoltan 188*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 189*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); 190*65ca801bSBALATON Zoltan #endif 191*65ca801bSBALATON Zoltan ret = ppc4xx_i2c_readb(opaque, addr) << 8; 192*65ca801bSBALATON Zoltan ret |= ppc4xx_i2c_readb(opaque, addr + 1); 193*65ca801bSBALATON Zoltan 194*65ca801bSBALATON Zoltan return ret; 195*65ca801bSBALATON Zoltan } 196*65ca801bSBALATON Zoltan 197*65ca801bSBALATON Zoltan static void ppc4xx_i2c_writew(void *opaque, 198*65ca801bSBALATON Zoltan hwaddr addr, uint32_t value) 199*65ca801bSBALATON Zoltan { 200*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 201*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, 202*65ca801bSBALATON Zoltan value); 203*65ca801bSBALATON Zoltan #endif 204*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr, value >> 8); 205*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr + 1, value); 206*65ca801bSBALATON Zoltan } 207*65ca801bSBALATON Zoltan 208*65ca801bSBALATON Zoltan static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr) 209*65ca801bSBALATON Zoltan { 210*65ca801bSBALATON Zoltan uint32_t ret; 211*65ca801bSBALATON Zoltan 212*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 213*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); 214*65ca801bSBALATON Zoltan #endif 215*65ca801bSBALATON Zoltan ret = ppc4xx_i2c_readb(opaque, addr) << 24; 216*65ca801bSBALATON Zoltan ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16; 217*65ca801bSBALATON Zoltan ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8; 218*65ca801bSBALATON Zoltan ret |= ppc4xx_i2c_readb(opaque, addr + 3); 219*65ca801bSBALATON Zoltan 220*65ca801bSBALATON Zoltan return ret; 221*65ca801bSBALATON Zoltan } 222*65ca801bSBALATON Zoltan 223*65ca801bSBALATON Zoltan static void ppc4xx_i2c_writel(void *opaque, 224*65ca801bSBALATON Zoltan hwaddr addr, uint32_t value) 225*65ca801bSBALATON Zoltan { 226*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 227*65ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, 228*65ca801bSBALATON Zoltan value); 229*65ca801bSBALATON Zoltan #endif 230*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr, value >> 24); 231*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16); 232*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8); 233*65ca801bSBALATON Zoltan ppc4xx_i2c_writeb(opaque, addr + 3, value); 234*65ca801bSBALATON Zoltan } 235*65ca801bSBALATON Zoltan 236*65ca801bSBALATON Zoltan static const MemoryRegionOps i2c_ops = { 237*65ca801bSBALATON Zoltan .old_mmio = { 238*65ca801bSBALATON Zoltan .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, }, 239*65ca801bSBALATON Zoltan .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, }, 240*65ca801bSBALATON Zoltan }, 241*65ca801bSBALATON Zoltan .endianness = DEVICE_NATIVE_ENDIAN, 242*65ca801bSBALATON Zoltan }; 243*65ca801bSBALATON Zoltan 244*65ca801bSBALATON Zoltan static void ppc4xx_i2c_reset(void *opaque) 245*65ca801bSBALATON Zoltan { 246*65ca801bSBALATON Zoltan ppc4xx_i2c_t *i2c; 247*65ca801bSBALATON Zoltan 248*65ca801bSBALATON Zoltan i2c = opaque; 249*65ca801bSBALATON Zoltan i2c->mdata = 0x00; 250*65ca801bSBALATON Zoltan i2c->sdata = 0x00; 251*65ca801bSBALATON Zoltan i2c->cntl = 0x00; 252*65ca801bSBALATON Zoltan i2c->mdcntl = 0x00; 253*65ca801bSBALATON Zoltan i2c->sts = 0x00; 254*65ca801bSBALATON Zoltan i2c->extsts = 0x00; 255*65ca801bSBALATON Zoltan i2c->clkdiv = 0x00; 256*65ca801bSBALATON Zoltan i2c->xfrcnt = 0x00; 257*65ca801bSBALATON Zoltan i2c->directcntl = 0x0F; 258*65ca801bSBALATON Zoltan } 259*65ca801bSBALATON Zoltan 260*65ca801bSBALATON Zoltan void ppc405_i2c_init(hwaddr base, qemu_irq irq) 261*65ca801bSBALATON Zoltan { 262*65ca801bSBALATON Zoltan ppc4xx_i2c_t *i2c; 263*65ca801bSBALATON Zoltan 264*65ca801bSBALATON Zoltan i2c = g_malloc0(sizeof(ppc4xx_i2c_t)); 265*65ca801bSBALATON Zoltan i2c->irq = irq; 266*65ca801bSBALATON Zoltan #ifdef DEBUG_I2C 267*65ca801bSBALATON Zoltan printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); 268*65ca801bSBALATON Zoltan #endif 269*65ca801bSBALATON Zoltan memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); 270*65ca801bSBALATON Zoltan memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); 271*65ca801bSBALATON Zoltan qemu_register_reset(ppc4xx_i2c_reset, i2c); 272*65ca801bSBALATON Zoltan } 273