Statistics
| Branch: | Revision:

root / hw / exynos4210_i2c.c @ fa2ddcb4

History | View | Annotate | Download (10 kB)

1 ffbbe7d0 Mitsyanko Igor
/*
2 ffbbe7d0 Mitsyanko Igor
 *  Exynos4210 I2C Bus Serial Interface Emulation
3 ffbbe7d0 Mitsyanko Igor
 *
4 ffbbe7d0 Mitsyanko Igor
 *  Copyright (C) 2012 Samsung Electronics Co Ltd.
5 ffbbe7d0 Mitsyanko Igor
 *    Maksim Kozlov, <m.kozlov@samsung.com>
6 ffbbe7d0 Mitsyanko Igor
 *    Igor Mitsyanko, <i.mitsyanko@samsung.com>
7 ffbbe7d0 Mitsyanko Igor
 *
8 ffbbe7d0 Mitsyanko Igor
 *  This program is free software; you can redistribute it and/or modify it
9 ffbbe7d0 Mitsyanko Igor
 *  under the terms of the GNU General Public License as published by the
10 ffbbe7d0 Mitsyanko Igor
 *  Free Software Foundation; either version 2 of the License, or
11 ffbbe7d0 Mitsyanko Igor
 *  (at your option) any later version.
12 ffbbe7d0 Mitsyanko Igor
 *
13 ffbbe7d0 Mitsyanko Igor
 *  This program is distributed in the hope that it will be useful, but WITHOUT
14 ffbbe7d0 Mitsyanko Igor
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 ffbbe7d0 Mitsyanko Igor
 *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 ffbbe7d0 Mitsyanko Igor
 *  for more details.
17 ffbbe7d0 Mitsyanko Igor
 *
18 ffbbe7d0 Mitsyanko Igor
 *  You should have received a copy of the GNU General Public License along
19 ffbbe7d0 Mitsyanko Igor
 *  with this program; if not, see <http://www.gnu.org/licenses/>.
20 ffbbe7d0 Mitsyanko Igor
 *
21 ffbbe7d0 Mitsyanko Igor
 */
22 ffbbe7d0 Mitsyanko Igor
23 ffbbe7d0 Mitsyanko Igor
#include "qemu-timer.h"
24 ffbbe7d0 Mitsyanko Igor
#include "sysbus.h"
25 ffbbe7d0 Mitsyanko Igor
#include "i2c.h"
26 ffbbe7d0 Mitsyanko Igor
27 ffbbe7d0 Mitsyanko Igor
#ifndef EXYNOS4_I2C_DEBUG
28 ffbbe7d0 Mitsyanko Igor
#define EXYNOS4_I2C_DEBUG                 0
29 ffbbe7d0 Mitsyanko Igor
#endif
30 ffbbe7d0 Mitsyanko Igor
31 ffbbe7d0 Mitsyanko Igor
#define TYPE_EXYNOS4_I2C                  "exynos4210.i2c"
32 ffbbe7d0 Mitsyanko Igor
#define EXYNOS4_I2C(obj)                  \
33 ffbbe7d0 Mitsyanko Igor
    OBJECT_CHECK(Exynos4210I2CState, (obj), TYPE_EXYNOS4_I2C)
34 ffbbe7d0 Mitsyanko Igor
35 ffbbe7d0 Mitsyanko Igor
/* Exynos4210 I2C memory map */
36 ffbbe7d0 Mitsyanko Igor
#define EXYNOS4_I2C_MEM_SIZE              0x14
37 ffbbe7d0 Mitsyanko Igor
#define I2CCON_ADDR                       0x00  /* control register */
38 ffbbe7d0 Mitsyanko Igor
#define I2CSTAT_ADDR                      0x04  /* control/status register */
39 ffbbe7d0 Mitsyanko Igor
#define I2CADD_ADDR                       0x08  /* address register */
40 ffbbe7d0 Mitsyanko Igor
#define I2CDS_ADDR                        0x0c  /* data shift register */
41 ffbbe7d0 Mitsyanko Igor
#define I2CLC_ADDR                        0x10  /* line control register */
42 ffbbe7d0 Mitsyanko Igor
43 ffbbe7d0 Mitsyanko Igor
#define I2CCON_ACK_GEN                    (1 << 7)
44 ffbbe7d0 Mitsyanko Igor
#define I2CCON_INTRS_EN                   (1 << 5)
45 ffbbe7d0 Mitsyanko Igor
#define I2CCON_INT_PEND                   (1 << 4)
46 ffbbe7d0 Mitsyanko Igor
47 ffbbe7d0 Mitsyanko Igor
#define EXYNOS4_I2C_MODE(reg)             (((reg) >> 6) & 3)
48 ffbbe7d0 Mitsyanko Igor
#define I2C_IN_MASTER_MODE(reg)           (((reg) >> 6) & 2)
49 ffbbe7d0 Mitsyanko Igor
#define I2CMODE_MASTER_Rx                 0x2
50 ffbbe7d0 Mitsyanko Igor
#define I2CMODE_MASTER_Tx                 0x3
51 ffbbe7d0 Mitsyanko Igor
#define I2CSTAT_LAST_BIT                  (1 << 0)
52 ffbbe7d0 Mitsyanko Igor
#define I2CSTAT_OUTPUT_EN                 (1 << 4)
53 ffbbe7d0 Mitsyanko Igor
#define I2CSTAT_START_BUSY                (1 << 5)
54 ffbbe7d0 Mitsyanko Igor
55 ffbbe7d0 Mitsyanko Igor
56 ffbbe7d0 Mitsyanko Igor
#if EXYNOS4_I2C_DEBUG
57 ffbbe7d0 Mitsyanko Igor
#define DPRINT(fmt, args...)              \
58 ffbbe7d0 Mitsyanko Igor
    do { fprintf(stderr, "QEMU I2C: "fmt, ## args); } while (0)
59 ffbbe7d0 Mitsyanko Igor
60 ffbbe7d0 Mitsyanko Igor
static const char *exynos4_i2c_get_regname(unsigned offset)
61 ffbbe7d0 Mitsyanko Igor
{
62 ffbbe7d0 Mitsyanko Igor
    switch (offset) {
63 ffbbe7d0 Mitsyanko Igor
    case I2CCON_ADDR:
64 ffbbe7d0 Mitsyanko Igor
        return "I2CCON";
65 ffbbe7d0 Mitsyanko Igor
    case I2CSTAT_ADDR:
66 ffbbe7d0 Mitsyanko Igor
        return "I2CSTAT";
67 ffbbe7d0 Mitsyanko Igor
    case I2CADD_ADDR:
68 ffbbe7d0 Mitsyanko Igor
        return "I2CADD";
69 ffbbe7d0 Mitsyanko Igor
    case I2CDS_ADDR:
70 ffbbe7d0 Mitsyanko Igor
        return "I2CDS";
71 ffbbe7d0 Mitsyanko Igor
    case I2CLC_ADDR:
72 ffbbe7d0 Mitsyanko Igor
        return "I2CLC";
73 ffbbe7d0 Mitsyanko Igor
    default:
74 ffbbe7d0 Mitsyanko Igor
        return "[?]";
75 ffbbe7d0 Mitsyanko Igor
    }
76 ffbbe7d0 Mitsyanko Igor
}
77 ffbbe7d0 Mitsyanko Igor
78 ffbbe7d0 Mitsyanko Igor
#else
79 ffbbe7d0 Mitsyanko Igor
#define DPRINT(fmt, args...)              do { } while (0)
80 ffbbe7d0 Mitsyanko Igor
#endif
81 ffbbe7d0 Mitsyanko Igor
82 ffbbe7d0 Mitsyanko Igor
typedef struct Exynos4210I2CState {
83 ffbbe7d0 Mitsyanko Igor
    SysBusDevice busdev;
84 ffbbe7d0 Mitsyanko Igor
    MemoryRegion iomem;
85 ffbbe7d0 Mitsyanko Igor
    i2c_bus *bus;
86 ffbbe7d0 Mitsyanko Igor
    qemu_irq irq;
87 ffbbe7d0 Mitsyanko Igor
88 ffbbe7d0 Mitsyanko Igor
    uint8_t i2ccon;
89 ffbbe7d0 Mitsyanko Igor
    uint8_t i2cstat;
90 ffbbe7d0 Mitsyanko Igor
    uint8_t i2cadd;
91 ffbbe7d0 Mitsyanko Igor
    uint8_t i2cds;
92 ffbbe7d0 Mitsyanko Igor
    uint8_t i2clc;
93 ffbbe7d0 Mitsyanko Igor
    bool scl_free;
94 ffbbe7d0 Mitsyanko Igor
} Exynos4210I2CState;
95 ffbbe7d0 Mitsyanko Igor
96 ffbbe7d0 Mitsyanko Igor
static inline void exynos4210_i2c_raise_interrupt(Exynos4210I2CState *s)
97 ffbbe7d0 Mitsyanko Igor
{
98 ffbbe7d0 Mitsyanko Igor
    if (s->i2ccon & I2CCON_INTRS_EN) {
99 ffbbe7d0 Mitsyanko Igor
        s->i2ccon |= I2CCON_INT_PEND;
100 ffbbe7d0 Mitsyanko Igor
        qemu_irq_raise(s->irq);
101 ffbbe7d0 Mitsyanko Igor
    }
102 ffbbe7d0 Mitsyanko Igor
}
103 ffbbe7d0 Mitsyanko Igor
104 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_data_receive(void *opaque)
105 ffbbe7d0 Mitsyanko Igor
{
106 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
107 ffbbe7d0 Mitsyanko Igor
    int ret;
108 ffbbe7d0 Mitsyanko Igor
109 ffbbe7d0 Mitsyanko Igor
    s->i2cstat &= ~I2CSTAT_LAST_BIT;
110 ffbbe7d0 Mitsyanko Igor
    s->scl_free = false;
111 ffbbe7d0 Mitsyanko Igor
    ret = i2c_recv(s->bus);
112 ffbbe7d0 Mitsyanko Igor
    if (ret < 0 && (s->i2ccon & I2CCON_ACK_GEN)) {
113 ffbbe7d0 Mitsyanko Igor
        s->i2cstat |= I2CSTAT_LAST_BIT;  /* Data is not acknowledged */
114 ffbbe7d0 Mitsyanko Igor
    } else {
115 ffbbe7d0 Mitsyanko Igor
        s->i2cds = ret;
116 ffbbe7d0 Mitsyanko Igor
    }
117 ffbbe7d0 Mitsyanko Igor
    exynos4210_i2c_raise_interrupt(s);
118 ffbbe7d0 Mitsyanko Igor
}
119 ffbbe7d0 Mitsyanko Igor
120 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_data_send(void *opaque)
121 ffbbe7d0 Mitsyanko Igor
{
122 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
123 ffbbe7d0 Mitsyanko Igor
124 ffbbe7d0 Mitsyanko Igor
    s->i2cstat &= ~I2CSTAT_LAST_BIT;
125 ffbbe7d0 Mitsyanko Igor
    s->scl_free = false;
126 ffbbe7d0 Mitsyanko Igor
    if (i2c_send(s->bus, s->i2cds) < 0 && (s->i2ccon & I2CCON_ACK_GEN)) {
127 ffbbe7d0 Mitsyanko Igor
        s->i2cstat |= I2CSTAT_LAST_BIT;
128 ffbbe7d0 Mitsyanko Igor
    }
129 ffbbe7d0 Mitsyanko Igor
    exynos4210_i2c_raise_interrupt(s);
130 ffbbe7d0 Mitsyanko Igor
}
131 ffbbe7d0 Mitsyanko Igor
132 ffbbe7d0 Mitsyanko Igor
static uint64_t exynos4210_i2c_read(void *opaque, target_phys_addr_t offset,
133 ffbbe7d0 Mitsyanko Igor
                                 unsigned size)
134 ffbbe7d0 Mitsyanko Igor
{
135 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
136 ffbbe7d0 Mitsyanko Igor
    uint8_t value;
137 ffbbe7d0 Mitsyanko Igor
138 ffbbe7d0 Mitsyanko Igor
    switch (offset) {
139 ffbbe7d0 Mitsyanko Igor
    case I2CCON_ADDR:
140 ffbbe7d0 Mitsyanko Igor
        value = s->i2ccon;
141 ffbbe7d0 Mitsyanko Igor
        break;
142 ffbbe7d0 Mitsyanko Igor
    case I2CSTAT_ADDR:
143 ffbbe7d0 Mitsyanko Igor
        value = s->i2cstat;
144 ffbbe7d0 Mitsyanko Igor
        break;
145 ffbbe7d0 Mitsyanko Igor
    case I2CADD_ADDR:
146 ffbbe7d0 Mitsyanko Igor
        value = s->i2cadd;
147 ffbbe7d0 Mitsyanko Igor
        break;
148 ffbbe7d0 Mitsyanko Igor
    case I2CDS_ADDR:
149 ffbbe7d0 Mitsyanko Igor
        value = s->i2cds;
150 ffbbe7d0 Mitsyanko Igor
        s->scl_free = true;
151 ffbbe7d0 Mitsyanko Igor
        if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx &&
152 ffbbe7d0 Mitsyanko Igor
               (s->i2cstat & I2CSTAT_START_BUSY) &&
153 ffbbe7d0 Mitsyanko Igor
               !(s->i2ccon & I2CCON_INT_PEND)) {
154 ffbbe7d0 Mitsyanko Igor
            exynos4210_i2c_data_receive(s);
155 ffbbe7d0 Mitsyanko Igor
        }
156 ffbbe7d0 Mitsyanko Igor
        break;
157 ffbbe7d0 Mitsyanko Igor
    case I2CLC_ADDR:
158 ffbbe7d0 Mitsyanko Igor
        value = s->i2clc;
159 ffbbe7d0 Mitsyanko Igor
        break;
160 ffbbe7d0 Mitsyanko Igor
    default:
161 ffbbe7d0 Mitsyanko Igor
        value = 0;
162 ffbbe7d0 Mitsyanko Igor
        DPRINT("ERROR: Bad read offset 0x%x\n", (unsigned int)offset);
163 ffbbe7d0 Mitsyanko Igor
        break;
164 ffbbe7d0 Mitsyanko Igor
    }
165 ffbbe7d0 Mitsyanko Igor
166 ffbbe7d0 Mitsyanko Igor
    DPRINT("read %s [0x%02x] -> 0x%02x\n", exynos4_i2c_get_regname(offset),
167 ffbbe7d0 Mitsyanko Igor
            (unsigned int)offset, value);
168 ffbbe7d0 Mitsyanko Igor
    return value;
169 ffbbe7d0 Mitsyanko Igor
}
170 ffbbe7d0 Mitsyanko Igor
171 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_write(void *opaque, target_phys_addr_t offset,
172 ffbbe7d0 Mitsyanko Igor
                              uint64_t value, unsigned size)
173 ffbbe7d0 Mitsyanko Igor
{
174 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
175 ffbbe7d0 Mitsyanko Igor
    uint8_t v = value & 0xff;
176 ffbbe7d0 Mitsyanko Igor
177 ffbbe7d0 Mitsyanko Igor
    DPRINT("write %s [0x%02x] <- 0x%02x\n", exynos4_i2c_get_regname(offset),
178 ffbbe7d0 Mitsyanko Igor
            (unsigned int)offset, v);
179 ffbbe7d0 Mitsyanko Igor
180 ffbbe7d0 Mitsyanko Igor
    switch (offset) {
181 ffbbe7d0 Mitsyanko Igor
    case I2CCON_ADDR:
182 ffbbe7d0 Mitsyanko Igor
        s->i2ccon = (v & ~I2CCON_INT_PEND) | (s->i2ccon & I2CCON_INT_PEND);
183 ffbbe7d0 Mitsyanko Igor
        if ((s->i2ccon & I2CCON_INT_PEND) && !(v & I2CCON_INT_PEND)) {
184 ffbbe7d0 Mitsyanko Igor
            s->i2ccon &= ~I2CCON_INT_PEND;
185 ffbbe7d0 Mitsyanko Igor
            qemu_irq_lower(s->irq);
186 ffbbe7d0 Mitsyanko Igor
            if (!(s->i2ccon & I2CCON_INTRS_EN)) {
187 ffbbe7d0 Mitsyanko Igor
                s->i2cstat &= ~I2CSTAT_START_BUSY;
188 ffbbe7d0 Mitsyanko Igor
            }
189 ffbbe7d0 Mitsyanko Igor
190 ffbbe7d0 Mitsyanko Igor
            if (s->i2cstat & I2CSTAT_START_BUSY) {
191 ffbbe7d0 Mitsyanko Igor
                if (s->scl_free) {
192 ffbbe7d0 Mitsyanko Igor
                    if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx) {
193 ffbbe7d0 Mitsyanko Igor
                        exynos4210_i2c_data_send(s);
194 ffbbe7d0 Mitsyanko Igor
                    } else if (EXYNOS4_I2C_MODE(s->i2cstat) ==
195 ffbbe7d0 Mitsyanko Igor
                            I2CMODE_MASTER_Rx) {
196 ffbbe7d0 Mitsyanko Igor
                        exynos4210_i2c_data_receive(s);
197 ffbbe7d0 Mitsyanko Igor
                    }
198 ffbbe7d0 Mitsyanko Igor
                } else {
199 ffbbe7d0 Mitsyanko Igor
                    s->i2ccon |= I2CCON_INT_PEND;
200 ffbbe7d0 Mitsyanko Igor
                    qemu_irq_raise(s->irq);
201 ffbbe7d0 Mitsyanko Igor
                }
202 ffbbe7d0 Mitsyanko Igor
            }
203 ffbbe7d0 Mitsyanko Igor
        }
204 ffbbe7d0 Mitsyanko Igor
        break;
205 ffbbe7d0 Mitsyanko Igor
    case I2CSTAT_ADDR:
206 ffbbe7d0 Mitsyanko Igor
        s->i2cstat =
207 ffbbe7d0 Mitsyanko Igor
                (s->i2cstat & I2CSTAT_START_BUSY) | (v & ~I2CSTAT_START_BUSY);
208 ffbbe7d0 Mitsyanko Igor
209 ffbbe7d0 Mitsyanko Igor
        if (!(s->i2cstat & I2CSTAT_OUTPUT_EN)) {
210 ffbbe7d0 Mitsyanko Igor
            s->i2cstat &= ~I2CSTAT_START_BUSY;
211 ffbbe7d0 Mitsyanko Igor
            s->scl_free = true;
212 ffbbe7d0 Mitsyanko Igor
            qemu_irq_lower(s->irq);
213 ffbbe7d0 Mitsyanko Igor
            break;
214 ffbbe7d0 Mitsyanko Igor
        }
215 ffbbe7d0 Mitsyanko Igor
216 ffbbe7d0 Mitsyanko Igor
        /* Nothing to do if in i2c slave mode */
217 ffbbe7d0 Mitsyanko Igor
        if (!I2C_IN_MASTER_MODE(s->i2cstat)) {
218 ffbbe7d0 Mitsyanko Igor
            break;
219 ffbbe7d0 Mitsyanko Igor
        }
220 ffbbe7d0 Mitsyanko Igor
221 ffbbe7d0 Mitsyanko Igor
        if (v & I2CSTAT_START_BUSY) {
222 ffbbe7d0 Mitsyanko Igor
            s->i2cstat &= ~I2CSTAT_LAST_BIT;
223 ffbbe7d0 Mitsyanko Igor
            s->i2cstat |= I2CSTAT_START_BUSY;    /* Line is busy */
224 ffbbe7d0 Mitsyanko Igor
            s->scl_free = false;
225 ffbbe7d0 Mitsyanko Igor
226 ffbbe7d0 Mitsyanko Igor
            /* Generate start bit and send slave address */
227 ffbbe7d0 Mitsyanko Igor
            if (i2c_start_transfer(s->bus, s->i2cds >> 1, s->i2cds & 0x1) &&
228 ffbbe7d0 Mitsyanko Igor
                    (s->i2ccon & I2CCON_ACK_GEN)) {
229 ffbbe7d0 Mitsyanko Igor
                s->i2cstat |= I2CSTAT_LAST_BIT;
230 ffbbe7d0 Mitsyanko Igor
            } else if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx) {
231 ffbbe7d0 Mitsyanko Igor
                exynos4210_i2c_data_receive(s);
232 ffbbe7d0 Mitsyanko Igor
            }
233 ffbbe7d0 Mitsyanko Igor
            exynos4210_i2c_raise_interrupt(s);
234 ffbbe7d0 Mitsyanko Igor
        } else {
235 ffbbe7d0 Mitsyanko Igor
            i2c_end_transfer(s->bus);
236 ffbbe7d0 Mitsyanko Igor
            if (!(s->i2ccon & I2CCON_INT_PEND)) {
237 ffbbe7d0 Mitsyanko Igor
                s->i2cstat &= ~I2CSTAT_START_BUSY;
238 ffbbe7d0 Mitsyanko Igor
            }
239 ffbbe7d0 Mitsyanko Igor
            s->scl_free = true;
240 ffbbe7d0 Mitsyanko Igor
        }
241 ffbbe7d0 Mitsyanko Igor
        break;
242 ffbbe7d0 Mitsyanko Igor
    case I2CADD_ADDR:
243 ffbbe7d0 Mitsyanko Igor
        if ((s->i2cstat & I2CSTAT_OUTPUT_EN) == 0) {
244 ffbbe7d0 Mitsyanko Igor
            s->i2cadd = v;
245 ffbbe7d0 Mitsyanko Igor
        }
246 ffbbe7d0 Mitsyanko Igor
        break;
247 ffbbe7d0 Mitsyanko Igor
    case I2CDS_ADDR:
248 ffbbe7d0 Mitsyanko Igor
        if (s->i2cstat & I2CSTAT_OUTPUT_EN) {
249 ffbbe7d0 Mitsyanko Igor
            s->i2cds = v;
250 ffbbe7d0 Mitsyanko Igor
            s->scl_free = true;
251 ffbbe7d0 Mitsyanko Igor
            if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx &&
252 ffbbe7d0 Mitsyanko Igor
                    (s->i2cstat & I2CSTAT_START_BUSY) &&
253 ffbbe7d0 Mitsyanko Igor
                    !(s->i2ccon & I2CCON_INT_PEND)) {
254 ffbbe7d0 Mitsyanko Igor
                exynos4210_i2c_data_send(s);
255 ffbbe7d0 Mitsyanko Igor
            }
256 ffbbe7d0 Mitsyanko Igor
        }
257 ffbbe7d0 Mitsyanko Igor
        break;
258 ffbbe7d0 Mitsyanko Igor
    case I2CLC_ADDR:
259 ffbbe7d0 Mitsyanko Igor
        s->i2clc = v;
260 ffbbe7d0 Mitsyanko Igor
        break;
261 ffbbe7d0 Mitsyanko Igor
    default:
262 ffbbe7d0 Mitsyanko Igor
        DPRINT("ERROR: Bad write offset 0x%x\n", (unsigned int)offset);
263 ffbbe7d0 Mitsyanko Igor
        break;
264 ffbbe7d0 Mitsyanko Igor
    }
265 ffbbe7d0 Mitsyanko Igor
}
266 ffbbe7d0 Mitsyanko Igor
267 ffbbe7d0 Mitsyanko Igor
static const MemoryRegionOps exynos4210_i2c_ops = {
268 ffbbe7d0 Mitsyanko Igor
    .read = exynos4210_i2c_read,
269 ffbbe7d0 Mitsyanko Igor
    .write = exynos4210_i2c_write,
270 ffbbe7d0 Mitsyanko Igor
    .endianness = DEVICE_NATIVE_ENDIAN,
271 ffbbe7d0 Mitsyanko Igor
};
272 ffbbe7d0 Mitsyanko Igor
273 ffbbe7d0 Mitsyanko Igor
static const VMStateDescription exynos4210_i2c_vmstate = {
274 ffbbe7d0 Mitsyanko Igor
    .name = TYPE_EXYNOS4_I2C,
275 ffbbe7d0 Mitsyanko Igor
    .version_id = 1,
276 ffbbe7d0 Mitsyanko Igor
    .minimum_version_id = 1,
277 ffbbe7d0 Mitsyanko Igor
    .fields = (VMStateField[]) {
278 ffbbe7d0 Mitsyanko Igor
        VMSTATE_UINT8(i2ccon, Exynos4210I2CState),
279 ffbbe7d0 Mitsyanko Igor
        VMSTATE_UINT8(i2cstat, Exynos4210I2CState),
280 ffbbe7d0 Mitsyanko Igor
        VMSTATE_UINT8(i2cds, Exynos4210I2CState),
281 ffbbe7d0 Mitsyanko Igor
        VMSTATE_UINT8(i2cadd, Exynos4210I2CState),
282 ffbbe7d0 Mitsyanko Igor
        VMSTATE_UINT8(i2clc, Exynos4210I2CState),
283 ffbbe7d0 Mitsyanko Igor
        VMSTATE_BOOL(scl_free, Exynos4210I2CState),
284 ffbbe7d0 Mitsyanko Igor
        VMSTATE_END_OF_LIST()
285 ffbbe7d0 Mitsyanko Igor
    }
286 ffbbe7d0 Mitsyanko Igor
};
287 ffbbe7d0 Mitsyanko Igor
288 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_reset(DeviceState *d)
289 ffbbe7d0 Mitsyanko Igor
{
290 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = EXYNOS4_I2C(d);
291 ffbbe7d0 Mitsyanko Igor
292 ffbbe7d0 Mitsyanko Igor
    s->i2ccon  = 0x00;
293 ffbbe7d0 Mitsyanko Igor
    s->i2cstat = 0x00;
294 ffbbe7d0 Mitsyanko Igor
    s->i2cds   = 0xFF;
295 ffbbe7d0 Mitsyanko Igor
    s->i2clc   = 0x00;
296 ffbbe7d0 Mitsyanko Igor
    s->i2cadd  = 0xFF;
297 ffbbe7d0 Mitsyanko Igor
    s->scl_free = true;
298 ffbbe7d0 Mitsyanko Igor
}
299 ffbbe7d0 Mitsyanko Igor
300 ffbbe7d0 Mitsyanko Igor
static int exynos4210_i2c_realize(SysBusDevice *dev)
301 ffbbe7d0 Mitsyanko Igor
{
302 ffbbe7d0 Mitsyanko Igor
    Exynos4210I2CState *s = EXYNOS4_I2C(dev);
303 ffbbe7d0 Mitsyanko Igor
304 ffbbe7d0 Mitsyanko Igor
    memory_region_init_io(&s->iomem, &exynos4210_i2c_ops, s, TYPE_EXYNOS4_I2C,
305 ffbbe7d0 Mitsyanko Igor
                          EXYNOS4_I2C_MEM_SIZE);
306 ffbbe7d0 Mitsyanko Igor
    sysbus_init_mmio(dev, &s->iomem);
307 ffbbe7d0 Mitsyanko Igor
    sysbus_init_irq(dev, &s->irq);
308 ffbbe7d0 Mitsyanko Igor
    s->bus = i2c_init_bus(&dev->qdev, "i2c");
309 ffbbe7d0 Mitsyanko Igor
    return 0;
310 ffbbe7d0 Mitsyanko Igor
}
311 ffbbe7d0 Mitsyanko Igor
312 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_class_init(ObjectClass *klass, void *data)
313 ffbbe7d0 Mitsyanko Igor
{
314 ffbbe7d0 Mitsyanko Igor
    DeviceClass *dc = DEVICE_CLASS(klass);
315 ffbbe7d0 Mitsyanko Igor
    SysBusDeviceClass *sbdc = SYS_BUS_DEVICE_CLASS(klass);
316 ffbbe7d0 Mitsyanko Igor
317 ffbbe7d0 Mitsyanko Igor
    dc->vmsd = &exynos4210_i2c_vmstate;
318 ffbbe7d0 Mitsyanko Igor
    dc->reset = exynos4210_i2c_reset;
319 ffbbe7d0 Mitsyanko Igor
    sbdc->init = exynos4210_i2c_realize;
320 ffbbe7d0 Mitsyanko Igor
}
321 ffbbe7d0 Mitsyanko Igor
322 ffbbe7d0 Mitsyanko Igor
static const TypeInfo exynos4210_i2c_type_info = {
323 ffbbe7d0 Mitsyanko Igor
    .name = TYPE_EXYNOS4_I2C,
324 ffbbe7d0 Mitsyanko Igor
    .parent = TYPE_SYS_BUS_DEVICE,
325 ffbbe7d0 Mitsyanko Igor
    .instance_size = sizeof(Exynos4210I2CState),
326 ffbbe7d0 Mitsyanko Igor
    .class_init = exynos4210_i2c_class_init,
327 ffbbe7d0 Mitsyanko Igor
};
328 ffbbe7d0 Mitsyanko Igor
329 ffbbe7d0 Mitsyanko Igor
static void exynos4210_i2c_register_types(void)
330 ffbbe7d0 Mitsyanko Igor
{
331 ffbbe7d0 Mitsyanko Igor
    type_register_static(&exynos4210_i2c_type_info);
332 ffbbe7d0 Mitsyanko Igor
}
333 ffbbe7d0 Mitsyanko Igor
334 ffbbe7d0 Mitsyanko Igor
type_init(exynos4210_i2c_register_types)