1 /* 2 * PPC4xx I2C controller emulation 3 * 4 * Copyright (c) 2007 Jocelyn Mayer 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "qemu-common.h" 28 #include "cpu.h" 29 #include "hw/hw.h" 30 #include "hw/i2c/ppc4xx_i2c.h" 31 32 /*#define DEBUG_I2C*/ 33 34 #define PPC4xx_I2C_MEM_SIZE 0x11 35 36 static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size) 37 { 38 PPC4xxI2CState *i2c = PPC4xx_I2C(opaque); 39 uint64_t ret; 40 41 #ifdef DEBUG_I2C 42 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); 43 #endif 44 switch (addr) { 45 case 0x00: 46 /*i2c_readbyte(&i2c->mdata);*/ 47 ret = i2c->mdata; 48 break; 49 case 0x02: 50 ret = i2c->sdata; 51 break; 52 case 0x04: 53 ret = i2c->lmadr; 54 break; 55 case 0x05: 56 ret = i2c->hmadr; 57 break; 58 case 0x06: 59 ret = i2c->cntl; 60 break; 61 case 0x07: 62 ret = i2c->mdcntl; 63 break; 64 case 0x08: 65 ret = i2c->sts; 66 break; 67 case 0x09: 68 ret = i2c->extsts; 69 break; 70 case 0x0A: 71 ret = i2c->lsadr; 72 break; 73 case 0x0B: 74 ret = i2c->hsadr; 75 break; 76 case 0x0C: 77 ret = i2c->clkdiv; 78 break; 79 case 0x0D: 80 ret = i2c->intrmsk; 81 break; 82 case 0x0E: 83 ret = i2c->xfrcnt; 84 break; 85 case 0x0F: 86 ret = i2c->xtcntlss; 87 break; 88 case 0x10: 89 ret = i2c->directcntl; 90 break; 91 default: 92 ret = 0x00; 93 break; 94 } 95 #ifdef DEBUG_I2C 96 printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret); 97 #endif 98 99 return ret; 100 } 101 102 static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value, 103 unsigned int size) 104 { 105 PPC4xxI2CState *i2c = opaque; 106 #ifdef DEBUG_I2C 107 printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", 108 __func__, addr, value); 109 #endif 110 switch (addr) { 111 case 0x00: 112 i2c->mdata = value; 113 /*i2c_sendbyte(&i2c->mdata);*/ 114 break; 115 case 0x02: 116 i2c->sdata = value; 117 break; 118 case 0x04: 119 i2c->lmadr = value; 120 break; 121 case 0x05: 122 i2c->hmadr = value; 123 break; 124 case 0x06: 125 i2c->cntl = value; 126 break; 127 case 0x07: 128 i2c->mdcntl = value & 0xDF; 129 break; 130 case 0x08: 131 i2c->sts &= ~(value & 0x0A); 132 break; 133 case 0x09: 134 i2c->extsts &= ~(value & 0x8F); 135 break; 136 case 0x0A: 137 i2c->lsadr = value; 138 break; 139 case 0x0B: 140 i2c->hsadr = value; 141 break; 142 case 0x0C: 143 i2c->clkdiv = value; 144 break; 145 case 0x0D: 146 i2c->intrmsk = value; 147 break; 148 case 0x0E: 149 i2c->xfrcnt = value & 0x77; 150 break; 151 case 0x0F: 152 i2c->xtcntlss = value; 153 break; 154 case 0x10: 155 i2c->directcntl = value & 0x7; 156 break; 157 } 158 } 159 160 static const MemoryRegionOps ppc4xx_i2c_ops = { 161 .read = ppc4xx_i2c_readb, 162 .write = ppc4xx_i2c_writeb, 163 .valid.min_access_size = 1, 164 .valid.max_access_size = 4, 165 .impl.min_access_size = 1, 166 .impl.max_access_size = 1, 167 .endianness = DEVICE_NATIVE_ENDIAN, 168 }; 169 170 static void ppc4xx_i2c_reset(DeviceState *s) 171 { 172 PPC4xxI2CState *i2c = PPC4xx_I2C(s); 173 174 i2c->mdata = 0x00; 175 i2c->sdata = 0x00; 176 i2c->cntl = 0x00; 177 i2c->mdcntl = 0x00; 178 i2c->sts = 0x00; 179 i2c->extsts = 0x00; 180 i2c->clkdiv = 0x00; 181 i2c->xfrcnt = 0x00; 182 i2c->directcntl = 0x0F; 183 } 184 185 static void ppc4xx_i2c_init(Object *o) 186 { 187 PPC4xxI2CState *s = PPC4xx_I2C(o); 188 189 memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s, 190 TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE); 191 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); 192 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); 193 s->bus = i2c_init_bus(DEVICE(s), "i2c"); 194 } 195 196 static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) 197 { 198 DeviceClass *dc = DEVICE_CLASS(klass); 199 200 dc->reset = ppc4xx_i2c_reset; 201 } 202 203 static const TypeInfo ppc4xx_i2c_type_info = { 204 .name = TYPE_PPC4xx_I2C, 205 .parent = TYPE_SYS_BUS_DEVICE, 206 .instance_size = sizeof(PPC4xxI2CState), 207 .instance_init = ppc4xx_i2c_init, 208 .class_init = ppc4xx_i2c_class_init, 209 }; 210 211 static void ppc4xx_i2c_register_types(void) 212 { 213 type_register_static(&ppc4xx_i2c_type_info); 214 } 215 216 type_init(ppc4xx_i2c_register_types) 217