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