xref: /openbmc/qemu/hw/i2c/ppc4xx_i2c.c (revision 98979cdc)
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