165ca801bSBALATON Zoltan /* 265ca801bSBALATON Zoltan * PPC4xx I2C controller emulation 365ca801bSBALATON Zoltan * 465ca801bSBALATON Zoltan * Copyright (c) 2007 Jocelyn Mayer 565ca801bSBALATON Zoltan * 665ca801bSBALATON Zoltan * Permission is hereby granted, free of charge, to any person obtaining a copy 765ca801bSBALATON Zoltan * of this software and associated documentation files (the "Software"), to deal 865ca801bSBALATON Zoltan * in the Software without restriction, including without limitation the rights 965ca801bSBALATON Zoltan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1065ca801bSBALATON Zoltan * copies of the Software, and to permit persons to whom the Software is 1165ca801bSBALATON Zoltan * furnished to do so, subject to the following conditions: 1265ca801bSBALATON Zoltan * 1365ca801bSBALATON Zoltan * The above copyright notice and this permission notice shall be included in 1465ca801bSBALATON Zoltan * all copies or substantial portions of the Software. 1565ca801bSBALATON Zoltan * 1665ca801bSBALATON Zoltan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1765ca801bSBALATON Zoltan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1865ca801bSBALATON Zoltan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1965ca801bSBALATON Zoltan * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2065ca801bSBALATON Zoltan * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2165ca801bSBALATON Zoltan * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2265ca801bSBALATON Zoltan * THE SOFTWARE. 2365ca801bSBALATON Zoltan */ 2465ca801bSBALATON Zoltan 2565ca801bSBALATON Zoltan #include "qemu/osdep.h" 2665ca801bSBALATON Zoltan #include "qapi/error.h" 2765ca801bSBALATON Zoltan #include "qemu-common.h" 2865ca801bSBALATON Zoltan #include "cpu.h" 2965ca801bSBALATON Zoltan #include "hw/hw.h" 30*3b09bb0fSBALATON Zoltan #include "hw/i2c/ppc4xx_i2c.h" 3165ca801bSBALATON Zoltan 3265ca801bSBALATON Zoltan /*#define DEBUG_I2C*/ 3365ca801bSBALATON Zoltan 34*3b09bb0fSBALATON Zoltan #define PPC4xx_I2C_MEM_SIZE 0x11 3565ca801bSBALATON Zoltan 36*3b09bb0fSBALATON Zoltan static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size) 3765ca801bSBALATON Zoltan { 38*3b09bb0fSBALATON Zoltan PPC4xxI2CState *i2c = PPC4xx_I2C(opaque); 39*3b09bb0fSBALATON Zoltan uint64_t ret; 4065ca801bSBALATON Zoltan 4165ca801bSBALATON Zoltan #ifdef DEBUG_I2C 4265ca801bSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); 4365ca801bSBALATON Zoltan #endif 4465ca801bSBALATON Zoltan switch (addr) { 4565ca801bSBALATON Zoltan case 0x00: 4665ca801bSBALATON Zoltan /*i2c_readbyte(&i2c->mdata);*/ 4765ca801bSBALATON Zoltan ret = i2c->mdata; 4865ca801bSBALATON Zoltan break; 4965ca801bSBALATON Zoltan case 0x02: 5065ca801bSBALATON Zoltan ret = i2c->sdata; 5165ca801bSBALATON Zoltan break; 5265ca801bSBALATON Zoltan case 0x04: 5365ca801bSBALATON Zoltan ret = i2c->lmadr; 5465ca801bSBALATON Zoltan break; 5565ca801bSBALATON Zoltan case 0x05: 5665ca801bSBALATON Zoltan ret = i2c->hmadr; 5765ca801bSBALATON Zoltan break; 5865ca801bSBALATON Zoltan case 0x06: 5965ca801bSBALATON Zoltan ret = i2c->cntl; 6065ca801bSBALATON Zoltan break; 6165ca801bSBALATON Zoltan case 0x07: 6265ca801bSBALATON Zoltan ret = i2c->mdcntl; 6365ca801bSBALATON Zoltan break; 6465ca801bSBALATON Zoltan case 0x08: 6565ca801bSBALATON Zoltan ret = i2c->sts; 6665ca801bSBALATON Zoltan break; 6765ca801bSBALATON Zoltan case 0x09: 6865ca801bSBALATON Zoltan ret = i2c->extsts; 6965ca801bSBALATON Zoltan break; 7065ca801bSBALATON Zoltan case 0x0A: 7165ca801bSBALATON Zoltan ret = i2c->lsadr; 7265ca801bSBALATON Zoltan break; 7365ca801bSBALATON Zoltan case 0x0B: 7465ca801bSBALATON Zoltan ret = i2c->hsadr; 7565ca801bSBALATON Zoltan break; 7665ca801bSBALATON Zoltan case 0x0C: 7765ca801bSBALATON Zoltan ret = i2c->clkdiv; 7865ca801bSBALATON Zoltan break; 7965ca801bSBALATON Zoltan case 0x0D: 8065ca801bSBALATON Zoltan ret = i2c->intrmsk; 8165ca801bSBALATON Zoltan break; 8265ca801bSBALATON Zoltan case 0x0E: 8365ca801bSBALATON Zoltan ret = i2c->xfrcnt; 8465ca801bSBALATON Zoltan break; 8565ca801bSBALATON Zoltan case 0x0F: 8665ca801bSBALATON Zoltan ret = i2c->xtcntlss; 8765ca801bSBALATON Zoltan break; 8865ca801bSBALATON Zoltan case 0x10: 8965ca801bSBALATON Zoltan ret = i2c->directcntl; 9065ca801bSBALATON Zoltan break; 9165ca801bSBALATON Zoltan default: 9265ca801bSBALATON Zoltan ret = 0x00; 9365ca801bSBALATON Zoltan break; 9465ca801bSBALATON Zoltan } 9565ca801bSBALATON Zoltan #ifdef DEBUG_I2C 96*3b09bb0fSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret); 9765ca801bSBALATON Zoltan #endif 9865ca801bSBALATON Zoltan 9965ca801bSBALATON Zoltan return ret; 10065ca801bSBALATON Zoltan } 10165ca801bSBALATON Zoltan 102*3b09bb0fSBALATON Zoltan static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value, 103*3b09bb0fSBALATON Zoltan unsigned int size) 10465ca801bSBALATON Zoltan { 105*3b09bb0fSBALATON Zoltan PPC4xxI2CState *i2c = opaque; 10665ca801bSBALATON Zoltan #ifdef DEBUG_I2C 107*3b09bb0fSBALATON Zoltan printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", 108*3b09bb0fSBALATON Zoltan __func__, addr, value); 10965ca801bSBALATON Zoltan #endif 11065ca801bSBALATON Zoltan switch (addr) { 11165ca801bSBALATON Zoltan case 0x00: 11265ca801bSBALATON Zoltan i2c->mdata = value; 11365ca801bSBALATON Zoltan /*i2c_sendbyte(&i2c->mdata);*/ 11465ca801bSBALATON Zoltan break; 11565ca801bSBALATON Zoltan case 0x02: 11665ca801bSBALATON Zoltan i2c->sdata = value; 11765ca801bSBALATON Zoltan break; 11865ca801bSBALATON Zoltan case 0x04: 11965ca801bSBALATON Zoltan i2c->lmadr = value; 12065ca801bSBALATON Zoltan break; 12165ca801bSBALATON Zoltan case 0x05: 12265ca801bSBALATON Zoltan i2c->hmadr = value; 12365ca801bSBALATON Zoltan break; 12465ca801bSBALATON Zoltan case 0x06: 12565ca801bSBALATON Zoltan i2c->cntl = value; 12665ca801bSBALATON Zoltan break; 12765ca801bSBALATON Zoltan case 0x07: 12865ca801bSBALATON Zoltan i2c->mdcntl = value & 0xDF; 12965ca801bSBALATON Zoltan break; 13065ca801bSBALATON Zoltan case 0x08: 13165ca801bSBALATON Zoltan i2c->sts &= ~(value & 0x0A); 13265ca801bSBALATON Zoltan break; 13365ca801bSBALATON Zoltan case 0x09: 13465ca801bSBALATON Zoltan i2c->extsts &= ~(value & 0x8F); 13565ca801bSBALATON Zoltan break; 13665ca801bSBALATON Zoltan case 0x0A: 13765ca801bSBALATON Zoltan i2c->lsadr = value; 13865ca801bSBALATON Zoltan break; 13965ca801bSBALATON Zoltan case 0x0B: 14065ca801bSBALATON Zoltan i2c->hsadr = value; 14165ca801bSBALATON Zoltan break; 14265ca801bSBALATON Zoltan case 0x0C: 14365ca801bSBALATON Zoltan i2c->clkdiv = value; 14465ca801bSBALATON Zoltan break; 14565ca801bSBALATON Zoltan case 0x0D: 14665ca801bSBALATON Zoltan i2c->intrmsk = value; 14765ca801bSBALATON Zoltan break; 14865ca801bSBALATON Zoltan case 0x0E: 14965ca801bSBALATON Zoltan i2c->xfrcnt = value & 0x77; 15065ca801bSBALATON Zoltan break; 15165ca801bSBALATON Zoltan case 0x0F: 15265ca801bSBALATON Zoltan i2c->xtcntlss = value; 15365ca801bSBALATON Zoltan break; 15465ca801bSBALATON Zoltan case 0x10: 15565ca801bSBALATON Zoltan i2c->directcntl = value & 0x7; 15665ca801bSBALATON Zoltan break; 15765ca801bSBALATON Zoltan } 15865ca801bSBALATON Zoltan } 15965ca801bSBALATON Zoltan 160*3b09bb0fSBALATON Zoltan static const MemoryRegionOps ppc4xx_i2c_ops = { 161*3b09bb0fSBALATON Zoltan .read = ppc4xx_i2c_readb, 162*3b09bb0fSBALATON Zoltan .write = ppc4xx_i2c_writeb, 163*3b09bb0fSBALATON Zoltan .valid.min_access_size = 1, 164*3b09bb0fSBALATON Zoltan .valid.max_access_size = 4, 165*3b09bb0fSBALATON Zoltan .impl.min_access_size = 1, 166*3b09bb0fSBALATON Zoltan .impl.max_access_size = 1, 16765ca801bSBALATON Zoltan .endianness = DEVICE_NATIVE_ENDIAN, 16865ca801bSBALATON Zoltan }; 16965ca801bSBALATON Zoltan 170*3b09bb0fSBALATON Zoltan static void ppc4xx_i2c_reset(DeviceState *s) 17165ca801bSBALATON Zoltan { 172*3b09bb0fSBALATON Zoltan PPC4xxI2CState *i2c = PPC4xx_I2C(s); 17365ca801bSBALATON Zoltan 17465ca801bSBALATON Zoltan i2c->mdata = 0x00; 17565ca801bSBALATON Zoltan i2c->sdata = 0x00; 17665ca801bSBALATON Zoltan i2c->cntl = 0x00; 17765ca801bSBALATON Zoltan i2c->mdcntl = 0x00; 17865ca801bSBALATON Zoltan i2c->sts = 0x00; 17965ca801bSBALATON Zoltan i2c->extsts = 0x00; 18065ca801bSBALATON Zoltan i2c->clkdiv = 0x00; 18165ca801bSBALATON Zoltan i2c->xfrcnt = 0x00; 18265ca801bSBALATON Zoltan i2c->directcntl = 0x0F; 18365ca801bSBALATON Zoltan } 18465ca801bSBALATON Zoltan 185*3b09bb0fSBALATON Zoltan static void ppc4xx_i2c_init(Object *o) 18665ca801bSBALATON Zoltan { 187*3b09bb0fSBALATON Zoltan PPC4xxI2CState *s = PPC4xx_I2C(o); 18865ca801bSBALATON Zoltan 189*3b09bb0fSBALATON Zoltan memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s, 190*3b09bb0fSBALATON Zoltan TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE); 191*3b09bb0fSBALATON Zoltan sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); 192*3b09bb0fSBALATON Zoltan sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); 193*3b09bb0fSBALATON Zoltan s->bus = i2c_init_bus(DEVICE(s), "i2c"); 19465ca801bSBALATON Zoltan } 195*3b09bb0fSBALATON Zoltan 196*3b09bb0fSBALATON Zoltan static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) 197*3b09bb0fSBALATON Zoltan { 198*3b09bb0fSBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 199*3b09bb0fSBALATON Zoltan 200*3b09bb0fSBALATON Zoltan dc->reset = ppc4xx_i2c_reset; 201*3b09bb0fSBALATON Zoltan } 202*3b09bb0fSBALATON Zoltan 203*3b09bb0fSBALATON Zoltan static const TypeInfo ppc4xx_i2c_type_info = { 204*3b09bb0fSBALATON Zoltan .name = TYPE_PPC4xx_I2C, 205*3b09bb0fSBALATON Zoltan .parent = TYPE_SYS_BUS_DEVICE, 206*3b09bb0fSBALATON Zoltan .instance_size = sizeof(PPC4xxI2CState), 207*3b09bb0fSBALATON Zoltan .instance_init = ppc4xx_i2c_init, 208*3b09bb0fSBALATON Zoltan .class_init = ppc4xx_i2c_class_init, 209*3b09bb0fSBALATON Zoltan }; 210*3b09bb0fSBALATON Zoltan 211*3b09bb0fSBALATON Zoltan static void ppc4xx_i2c_register_types(void) 212*3b09bb0fSBALATON Zoltan { 213*3b09bb0fSBALATON Zoltan type_register_static(&ppc4xx_i2c_type_info); 214*3b09bb0fSBALATON Zoltan } 215*3b09bb0fSBALATON Zoltan 216*3b09bb0fSBALATON Zoltan type_init(ppc4xx_i2c_register_types) 217