Statistics
| Branch: | Revision:

root / hw / omap_gpio.c @ a1e47211

History | View | Annotate | Download (20.7 kB)

1 e5c6b25a cmchao
/*
2 e5c6b25a cmchao
 * TI OMAP processors GPIO emulation.
3 e5c6b25a cmchao
 *
4 e5c6b25a cmchao
 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
5 e5c6b25a cmchao
 * Copyright (C) 2007-2009 Nokia Corporation
6 e5c6b25a cmchao
 *
7 e5c6b25a cmchao
 * This program is free software; you can redistribute it and/or
8 e5c6b25a cmchao
 * modify it under the terms of the GNU General Public License as
9 e5c6b25a cmchao
 * published by the Free Software Foundation; either version 2 or
10 e5c6b25a cmchao
 * (at your option) version 3 of the License.
11 e5c6b25a cmchao
 *
12 e5c6b25a cmchao
 * This program is distributed in the hope that it will be useful,
13 e5c6b25a cmchao
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 e5c6b25a cmchao
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 e5c6b25a cmchao
 * GNU General Public License for more details.
16 e5c6b25a cmchao
 *
17 e5c6b25a cmchao
 * You should have received a copy of the GNU General Public License along
18 e5c6b25a cmchao
 * with this program; if not, see <http://www.gnu.org/licenses/>.
19 e5c6b25a cmchao
 */
20 e5c6b25a cmchao
21 e5c6b25a cmchao
#include "hw.h"
22 e5c6b25a cmchao
#include "omap.h"
23 77831c20 Juha Riihimäki
#include "sysbus.h"
24 77831c20 Juha Riihimäki
25 e5c6b25a cmchao
struct omap_gpio_s {
26 e5c6b25a cmchao
    qemu_irq irq;
27 e5c6b25a cmchao
    qemu_irq handler[16];
28 e5c6b25a cmchao
29 e5c6b25a cmchao
    uint16_t inputs;
30 e5c6b25a cmchao
    uint16_t outputs;
31 e5c6b25a cmchao
    uint16_t dir;
32 e5c6b25a cmchao
    uint16_t edge;
33 e5c6b25a cmchao
    uint16_t mask;
34 e5c6b25a cmchao
    uint16_t ints;
35 e5c6b25a cmchao
    uint16_t pins;
36 e5c6b25a cmchao
};
37 e5c6b25a cmchao
38 77831c20 Juha Riihimäki
struct omap_gpif_s {
39 77831c20 Juha Riihimäki
    SysBusDevice busdev;
40 9244b42d Avi Kivity
    MemoryRegion iomem;
41 77831c20 Juha Riihimäki
    int mpu_model;
42 77831c20 Juha Riihimäki
    void *clk;
43 77831c20 Juha Riihimäki
    struct omap_gpio_s omap1;
44 77831c20 Juha Riihimäki
};
45 77831c20 Juha Riihimäki
46 77831c20 Juha Riihimäki
/* General-Purpose I/O of OMAP1 */
47 e5c6b25a cmchao
static void omap_gpio_set(void *opaque, int line, int level)
48 e5c6b25a cmchao
{
49 77831c20 Juha Riihimäki
    struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
50 e5c6b25a cmchao
    uint16_t prev = s->inputs;
51 e5c6b25a cmchao
52 e5c6b25a cmchao
    if (level)
53 e5c6b25a cmchao
        s->inputs |= 1 << line;
54 e5c6b25a cmchao
    else
55 e5c6b25a cmchao
        s->inputs &= ~(1 << line);
56 e5c6b25a cmchao
57 e5c6b25a cmchao
    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
58 e5c6b25a cmchao
                    (1 << line) & s->dir & ~s->mask) {
59 e5c6b25a cmchao
        s->ints |= 1 << line;
60 e5c6b25a cmchao
        qemu_irq_raise(s->irq);
61 e5c6b25a cmchao
    }
62 e5c6b25a cmchao
}
63 e5c6b25a cmchao
64 9244b42d Avi Kivity
static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr,
65 9244b42d Avi Kivity
                               unsigned size)
66 e5c6b25a cmchao
{
67 e5c6b25a cmchao
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
68 e5c6b25a cmchao
    int offset = addr & OMAP_MPUI_REG_MASK;
69 e5c6b25a cmchao
70 9244b42d Avi Kivity
    if (size != 2) {
71 9244b42d Avi Kivity
        return omap_badwidth_read16(opaque, addr);
72 9244b42d Avi Kivity
    }
73 9244b42d Avi Kivity
74 e5c6b25a cmchao
    switch (offset) {
75 e5c6b25a cmchao
    case 0x00:        /* DATA_INPUT */
76 e5c6b25a cmchao
        return s->inputs & s->pins;
77 e5c6b25a cmchao
78 e5c6b25a cmchao
    case 0x04:        /* DATA_OUTPUT */
79 e5c6b25a cmchao
        return s->outputs;
80 e5c6b25a cmchao
81 e5c6b25a cmchao
    case 0x08:        /* DIRECTION_CONTROL */
82 e5c6b25a cmchao
        return s->dir;
83 e5c6b25a cmchao
84 e5c6b25a cmchao
    case 0x0c:        /* INTERRUPT_CONTROL */
85 e5c6b25a cmchao
        return s->edge;
86 e5c6b25a cmchao
87 e5c6b25a cmchao
    case 0x10:        /* INTERRUPT_MASK */
88 e5c6b25a cmchao
        return s->mask;
89 e5c6b25a cmchao
90 e5c6b25a cmchao
    case 0x14:        /* INTERRUPT_STATUS */
91 e5c6b25a cmchao
        return s->ints;
92 e5c6b25a cmchao
93 e5c6b25a cmchao
    case 0x18:        /* PIN_CONTROL (not in OMAP310) */
94 e5c6b25a cmchao
        OMAP_BAD_REG(addr);
95 e5c6b25a cmchao
        return s->pins;
96 e5c6b25a cmchao
    }
97 e5c6b25a cmchao
98 e5c6b25a cmchao
    OMAP_BAD_REG(addr);
99 e5c6b25a cmchao
    return 0;
100 e5c6b25a cmchao
}
101 e5c6b25a cmchao
102 e5c6b25a cmchao
static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
103 9244b42d Avi Kivity
                            uint64_t value, unsigned size)
104 e5c6b25a cmchao
{
105 e5c6b25a cmchao
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
106 e5c6b25a cmchao
    int offset = addr & OMAP_MPUI_REG_MASK;
107 e5c6b25a cmchao
    uint16_t diff;
108 e5c6b25a cmchao
    int ln;
109 e5c6b25a cmchao
110 9244b42d Avi Kivity
    if (size != 2) {
111 9244b42d Avi Kivity
        return omap_badwidth_write16(opaque, addr, value);
112 9244b42d Avi Kivity
    }
113 9244b42d Avi Kivity
114 e5c6b25a cmchao
    switch (offset) {
115 e5c6b25a cmchao
    case 0x00:        /* DATA_INPUT */
116 e5c6b25a cmchao
        OMAP_RO_REG(addr);
117 e5c6b25a cmchao
        return;
118 e5c6b25a cmchao
119 e5c6b25a cmchao
    case 0x04:        /* DATA_OUTPUT */
120 e5c6b25a cmchao
        diff = (s->outputs ^ value) & ~s->dir;
121 e5c6b25a cmchao
        s->outputs = value;
122 e5c6b25a cmchao
        while ((ln = ffs(diff))) {
123 e5c6b25a cmchao
            ln --;
124 e5c6b25a cmchao
            if (s->handler[ln])
125 e5c6b25a cmchao
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
126 e5c6b25a cmchao
            diff &= ~(1 << ln);
127 e5c6b25a cmchao
        }
128 e5c6b25a cmchao
        break;
129 e5c6b25a cmchao
130 e5c6b25a cmchao
    case 0x08:        /* DIRECTION_CONTROL */
131 e5c6b25a cmchao
        diff = s->outputs & (s->dir ^ value);
132 e5c6b25a cmchao
        s->dir = value;
133 e5c6b25a cmchao
134 e5c6b25a cmchao
        value = s->outputs & ~s->dir;
135 e5c6b25a cmchao
        while ((ln = ffs(diff))) {
136 e5c6b25a cmchao
            ln --;
137 e5c6b25a cmchao
            if (s->handler[ln])
138 e5c6b25a cmchao
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
139 e5c6b25a cmchao
            diff &= ~(1 << ln);
140 e5c6b25a cmchao
        }
141 e5c6b25a cmchao
        break;
142 e5c6b25a cmchao
143 e5c6b25a cmchao
    case 0x0c:        /* INTERRUPT_CONTROL */
144 e5c6b25a cmchao
        s->edge = value;
145 e5c6b25a cmchao
        break;
146 e5c6b25a cmchao
147 e5c6b25a cmchao
    case 0x10:        /* INTERRUPT_MASK */
148 e5c6b25a cmchao
        s->mask = value;
149 e5c6b25a cmchao
        break;
150 e5c6b25a cmchao
151 e5c6b25a cmchao
    case 0x14:        /* INTERRUPT_STATUS */
152 e5c6b25a cmchao
        s->ints &= ~value;
153 e5c6b25a cmchao
        if (!s->ints)
154 e5c6b25a cmchao
            qemu_irq_lower(s->irq);
155 e5c6b25a cmchao
        break;
156 e5c6b25a cmchao
157 e5c6b25a cmchao
    case 0x18:        /* PIN_CONTROL (not in OMAP310 TRM) */
158 e5c6b25a cmchao
        OMAP_BAD_REG(addr);
159 e5c6b25a cmchao
        s->pins = value;
160 e5c6b25a cmchao
        break;
161 e5c6b25a cmchao
162 e5c6b25a cmchao
    default:
163 e5c6b25a cmchao
        OMAP_BAD_REG(addr);
164 e5c6b25a cmchao
        return;
165 e5c6b25a cmchao
    }
166 e5c6b25a cmchao
}
167 e5c6b25a cmchao
168 e5c6b25a cmchao
/* *Some* sources say the memory region is 32-bit.  */
169 9244b42d Avi Kivity
static const MemoryRegionOps omap_gpio_ops = {
170 9244b42d Avi Kivity
    .read = omap_gpio_read,
171 9244b42d Avi Kivity
    .write = omap_gpio_write,
172 9244b42d Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
173 e5c6b25a cmchao
};
174 e5c6b25a cmchao
175 77831c20 Juha Riihimäki
static void omap_gpio_reset(struct omap_gpio_s *s)
176 e5c6b25a cmchao
{
177 e5c6b25a cmchao
    s->inputs = 0;
178 e5c6b25a cmchao
    s->outputs = ~0;
179 e5c6b25a cmchao
    s->dir = ~0;
180 e5c6b25a cmchao
    s->edge = ~0;
181 e5c6b25a cmchao
    s->mask = ~0;
182 e5c6b25a cmchao
    s->ints = 0;
183 e5c6b25a cmchao
    s->pins = ~0;
184 e5c6b25a cmchao
}
185 e5c6b25a cmchao
186 d82310f7 cmchao
struct omap2_gpio_s {
187 d82310f7 cmchao
    qemu_irq irq[2];
188 d82310f7 cmchao
    qemu_irq wkup;
189 77831c20 Juha Riihimäki
    qemu_irq *handler;
190 9244b42d Avi Kivity
    MemoryRegion iomem;
191 d82310f7 cmchao
192 77831c20 Juha Riihimäki
    uint8_t revision;
193 d82310f7 cmchao
    uint8_t config[2];
194 d82310f7 cmchao
    uint32_t inputs;
195 d82310f7 cmchao
    uint32_t outputs;
196 d82310f7 cmchao
    uint32_t dir;
197 d82310f7 cmchao
    uint32_t level[2];
198 d82310f7 cmchao
    uint32_t edge[2];
199 d82310f7 cmchao
    uint32_t mask[2];
200 d82310f7 cmchao
    uint32_t wumask;
201 d82310f7 cmchao
    uint32_t ints[2];
202 d82310f7 cmchao
    uint32_t debounce;
203 d82310f7 cmchao
    uint8_t delay;
204 d82310f7 cmchao
};
205 d82310f7 cmchao
206 77831c20 Juha Riihimäki
struct omap2_gpif_s {
207 77831c20 Juha Riihimäki
    SysBusDevice busdev;
208 9244b42d Avi Kivity
    MemoryRegion iomem;
209 77831c20 Juha Riihimäki
    int mpu_model;
210 77831c20 Juha Riihimäki
    void *iclk;
211 77831c20 Juha Riihimäki
    void *fclk[6];
212 77831c20 Juha Riihimäki
    int modulecount;
213 77831c20 Juha Riihimäki
    struct omap2_gpio_s *modules;
214 77831c20 Juha Riihimäki
    qemu_irq *handler;
215 77831c20 Juha Riihimäki
    int autoidle;
216 77831c20 Juha Riihimäki
    int gpo;
217 77831c20 Juha Riihimäki
};
218 77831c20 Juha Riihimäki
219 77831c20 Juha Riihimäki
/* General-Purpose Interface of OMAP2/3 */
220 d82310f7 cmchao
static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
221 77831c20 Juha Riihimäki
                                                int line)
222 d82310f7 cmchao
{
223 d82310f7 cmchao
    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
224 d82310f7 cmchao
}
225 d82310f7 cmchao
226 d82310f7 cmchao
static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
227 d82310f7 cmchao
{
228 d82310f7 cmchao
    if (!(s->config[0] & (1 << 2)))                        /* ENAWAKEUP */
229 d82310f7 cmchao
        return;
230 d82310f7 cmchao
    if (!(s->config[0] & (3 << 3)))                        /* Force Idle */
231 d82310f7 cmchao
        return;
232 d82310f7 cmchao
    if (!(s->wumask & (1 << line)))
233 d82310f7 cmchao
        return;
234 d82310f7 cmchao
235 d82310f7 cmchao
    qemu_irq_raise(s->wkup);
236 d82310f7 cmchao
}
237 d82310f7 cmchao
238 d82310f7 cmchao
static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
239 d82310f7 cmchao
                uint32_t diff)
240 d82310f7 cmchao
{
241 d82310f7 cmchao
    int ln;
242 d82310f7 cmchao
243 d82310f7 cmchao
    s->outputs ^= diff;
244 d82310f7 cmchao
    diff &= ~s->dir;
245 d82310f7 cmchao
    while ((ln = ffs(diff))) {
246 d82310f7 cmchao
        ln --;
247 d82310f7 cmchao
        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
248 d82310f7 cmchao
        diff &= ~(1 << ln);
249 d82310f7 cmchao
    }
250 d82310f7 cmchao
}
251 d82310f7 cmchao
252 d82310f7 cmchao
static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
253 d82310f7 cmchao
{
254 d82310f7 cmchao
    s->ints[line] |= s->dir &
255 d82310f7 cmchao
            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
256 d82310f7 cmchao
    omap2_gpio_module_int_update(s, line);
257 d82310f7 cmchao
}
258 d82310f7 cmchao
259 d82310f7 cmchao
static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
260 d82310f7 cmchao
{
261 d82310f7 cmchao
    s->ints[0] |= 1 << line;
262 d82310f7 cmchao
    omap2_gpio_module_int_update(s, 0);
263 d82310f7 cmchao
    s->ints[1] |= 1 << line;
264 d82310f7 cmchao
    omap2_gpio_module_int_update(s, 1);
265 d82310f7 cmchao
    omap2_gpio_module_wake(s, line);
266 d82310f7 cmchao
}
267 d82310f7 cmchao
268 77831c20 Juha Riihimäki
static void omap2_gpio_set(void *opaque, int line, int level)
269 d82310f7 cmchao
{
270 77831c20 Juha Riihimäki
    struct omap2_gpif_s *p = opaque;
271 77831c20 Juha Riihimäki
    struct omap2_gpio_s *s = &p->modules[line >> 5];
272 d82310f7 cmchao
273 77831c20 Juha Riihimäki
    line &= 31;
274 d82310f7 cmchao
    if (level) {
275 d82310f7 cmchao
        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
276 d82310f7 cmchao
            omap2_gpio_module_int(s, line);
277 d82310f7 cmchao
        s->inputs |= 1 << line;
278 d82310f7 cmchao
    } else {
279 d82310f7 cmchao
        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
280 d82310f7 cmchao
            omap2_gpio_module_int(s, line);
281 d82310f7 cmchao
        s->inputs &= ~(1 << line);
282 d82310f7 cmchao
    }
283 d82310f7 cmchao
}
284 d82310f7 cmchao
285 d82310f7 cmchao
static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
286 d82310f7 cmchao
{
287 d82310f7 cmchao
    s->config[0] = 0;
288 d82310f7 cmchao
    s->config[1] = 2;
289 d82310f7 cmchao
    s->ints[0] = 0;
290 d82310f7 cmchao
    s->ints[1] = 0;
291 d82310f7 cmchao
    s->mask[0] = 0;
292 d82310f7 cmchao
    s->mask[1] = 0;
293 d82310f7 cmchao
    s->wumask = 0;
294 d82310f7 cmchao
    s->dir = ~0;
295 d82310f7 cmchao
    s->level[0] = 0;
296 d82310f7 cmchao
    s->level[1] = 0;
297 d82310f7 cmchao
    s->edge[0] = 0;
298 d82310f7 cmchao
    s->edge[1] = 0;
299 d82310f7 cmchao
    s->debounce = 0;
300 d82310f7 cmchao
    s->delay = 0;
301 d82310f7 cmchao
}
302 d82310f7 cmchao
303 d82310f7 cmchao
static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
304 d82310f7 cmchao
{
305 d82310f7 cmchao
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
306 d82310f7 cmchao
307 d82310f7 cmchao
    switch (addr) {
308 d82310f7 cmchao
    case 0x00:        /* GPIO_REVISION */
309 77831c20 Juha Riihimäki
        return s->revision;
310 d82310f7 cmchao
311 d82310f7 cmchao
    case 0x10:        /* GPIO_SYSCONFIG */
312 d82310f7 cmchao
        return s->config[0];
313 d82310f7 cmchao
314 d82310f7 cmchao
    case 0x14:        /* GPIO_SYSSTATUS */
315 d82310f7 cmchao
        return 0x01;
316 d82310f7 cmchao
317 d82310f7 cmchao
    case 0x18:        /* GPIO_IRQSTATUS1 */
318 d82310f7 cmchao
        return s->ints[0];
319 d82310f7 cmchao
320 d82310f7 cmchao
    case 0x1c:        /* GPIO_IRQENABLE1 */
321 d82310f7 cmchao
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
322 d82310f7 cmchao
    case 0x64:        /* GPIO_SETIRQENABLE1 */
323 d82310f7 cmchao
        return s->mask[0];
324 d82310f7 cmchao
325 d82310f7 cmchao
    case 0x20:        /* GPIO_WAKEUPENABLE */
326 d82310f7 cmchao
    case 0x80:        /* GPIO_CLEARWKUENA */
327 d82310f7 cmchao
    case 0x84:        /* GPIO_SETWKUENA */
328 d82310f7 cmchao
        return s->wumask;
329 d82310f7 cmchao
330 d82310f7 cmchao
    case 0x28:        /* GPIO_IRQSTATUS2 */
331 d82310f7 cmchao
        return s->ints[1];
332 d82310f7 cmchao
333 d82310f7 cmchao
    case 0x2c:        /* GPIO_IRQENABLE2 */
334 d82310f7 cmchao
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
335 d82310f7 cmchao
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
336 d82310f7 cmchao
        return s->mask[1];
337 d82310f7 cmchao
338 d82310f7 cmchao
    case 0x30:        /* GPIO_CTRL */
339 d82310f7 cmchao
        return s->config[1];
340 d82310f7 cmchao
341 d82310f7 cmchao
    case 0x34:        /* GPIO_OE */
342 d82310f7 cmchao
        return s->dir;
343 d82310f7 cmchao
344 d82310f7 cmchao
    case 0x38:        /* GPIO_DATAIN */
345 d82310f7 cmchao
        return s->inputs;
346 d82310f7 cmchao
347 d82310f7 cmchao
    case 0x3c:        /* GPIO_DATAOUT */
348 d82310f7 cmchao
    case 0x90:        /* GPIO_CLEARDATAOUT */
349 d82310f7 cmchao
    case 0x94:        /* GPIO_SETDATAOUT */
350 d82310f7 cmchao
        return s->outputs;
351 d82310f7 cmchao
352 d82310f7 cmchao
    case 0x40:        /* GPIO_LEVELDETECT0 */
353 d82310f7 cmchao
        return s->level[0];
354 d82310f7 cmchao
355 d82310f7 cmchao
    case 0x44:        /* GPIO_LEVELDETECT1 */
356 d82310f7 cmchao
        return s->level[1];
357 d82310f7 cmchao
358 d82310f7 cmchao
    case 0x48:        /* GPIO_RISINGDETECT */
359 d82310f7 cmchao
        return s->edge[0];
360 d82310f7 cmchao
361 d82310f7 cmchao
    case 0x4c:        /* GPIO_FALLINGDETECT */
362 d82310f7 cmchao
        return s->edge[1];
363 d82310f7 cmchao
364 d82310f7 cmchao
    case 0x50:        /* GPIO_DEBOUNCENABLE */
365 d82310f7 cmchao
        return s->debounce;
366 d82310f7 cmchao
367 d82310f7 cmchao
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
368 d82310f7 cmchao
        return s->delay;
369 d82310f7 cmchao
    }
370 d82310f7 cmchao
371 d82310f7 cmchao
    OMAP_BAD_REG(addr);
372 d82310f7 cmchao
    return 0;
373 d82310f7 cmchao
}
374 d82310f7 cmchao
375 d82310f7 cmchao
static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
376 d82310f7 cmchao
                uint32_t value)
377 d82310f7 cmchao
{
378 d82310f7 cmchao
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
379 d82310f7 cmchao
    uint32_t diff;
380 d82310f7 cmchao
    int ln;
381 d82310f7 cmchao
382 d82310f7 cmchao
    switch (addr) {
383 d82310f7 cmchao
    case 0x00:        /* GPIO_REVISION */
384 d82310f7 cmchao
    case 0x14:        /* GPIO_SYSSTATUS */
385 d82310f7 cmchao
    case 0x38:        /* GPIO_DATAIN */
386 d82310f7 cmchao
        OMAP_RO_REG(addr);
387 d82310f7 cmchao
        break;
388 d82310f7 cmchao
389 d82310f7 cmchao
    case 0x10:        /* GPIO_SYSCONFIG */
390 d82310f7 cmchao
        if (((value >> 3) & 3) == 3)
391 d82310f7 cmchao
            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
392 d82310f7 cmchao
        if (value & 2)
393 d82310f7 cmchao
            omap2_gpio_module_reset(s);
394 d82310f7 cmchao
        s->config[0] = value & 0x1d;
395 d82310f7 cmchao
        break;
396 d82310f7 cmchao
397 d82310f7 cmchao
    case 0x18:        /* GPIO_IRQSTATUS1 */
398 d82310f7 cmchao
        if (s->ints[0] & value) {
399 d82310f7 cmchao
            s->ints[0] &= ~value;
400 d82310f7 cmchao
            omap2_gpio_module_level_update(s, 0);
401 d82310f7 cmchao
        }
402 d82310f7 cmchao
        break;
403 d82310f7 cmchao
404 d82310f7 cmchao
    case 0x1c:        /* GPIO_IRQENABLE1 */
405 d82310f7 cmchao
        s->mask[0] = value;
406 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 0);
407 d82310f7 cmchao
        break;
408 d82310f7 cmchao
409 d82310f7 cmchao
    case 0x20:        /* GPIO_WAKEUPENABLE */
410 d82310f7 cmchao
        s->wumask = value;
411 d82310f7 cmchao
        break;
412 d82310f7 cmchao
413 d82310f7 cmchao
    case 0x28:        /* GPIO_IRQSTATUS2 */
414 d82310f7 cmchao
        if (s->ints[1] & value) {
415 d82310f7 cmchao
            s->ints[1] &= ~value;
416 d82310f7 cmchao
            omap2_gpio_module_level_update(s, 1);
417 d82310f7 cmchao
        }
418 d82310f7 cmchao
        break;
419 d82310f7 cmchao
420 d82310f7 cmchao
    case 0x2c:        /* GPIO_IRQENABLE2 */
421 d82310f7 cmchao
        s->mask[1] = value;
422 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 1);
423 d82310f7 cmchao
        break;
424 d82310f7 cmchao
425 d82310f7 cmchao
    case 0x30:        /* GPIO_CTRL */
426 d82310f7 cmchao
        s->config[1] = value & 7;
427 d82310f7 cmchao
        break;
428 d82310f7 cmchao
429 d82310f7 cmchao
    case 0x34:        /* GPIO_OE */
430 d82310f7 cmchao
        diff = s->outputs & (s->dir ^ value);
431 d82310f7 cmchao
        s->dir = value;
432 d82310f7 cmchao
433 d82310f7 cmchao
        value = s->outputs & ~s->dir;
434 d82310f7 cmchao
        while ((ln = ffs(diff))) {
435 d82310f7 cmchao
            diff &= ~(1 <<-- ln);
436 d82310f7 cmchao
            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
437 d82310f7 cmchao
        }
438 d82310f7 cmchao
439 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 0);
440 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 1);
441 d82310f7 cmchao
        break;
442 d82310f7 cmchao
443 d82310f7 cmchao
    case 0x3c:        /* GPIO_DATAOUT */
444 d82310f7 cmchao
        omap2_gpio_module_out_update(s, s->outputs ^ value);
445 d82310f7 cmchao
        break;
446 d82310f7 cmchao
447 d82310f7 cmchao
    case 0x40:        /* GPIO_LEVELDETECT0 */
448 d82310f7 cmchao
        s->level[0] = value;
449 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 0);
450 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 1);
451 d82310f7 cmchao
        break;
452 d82310f7 cmchao
453 d82310f7 cmchao
    case 0x44:        /* GPIO_LEVELDETECT1 */
454 d82310f7 cmchao
        s->level[1] = value;
455 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 0);
456 d82310f7 cmchao
        omap2_gpio_module_level_update(s, 1);
457 d82310f7 cmchao
        break;
458 d82310f7 cmchao
459 d82310f7 cmchao
    case 0x48:        /* GPIO_RISINGDETECT */
460 d82310f7 cmchao
        s->edge[0] = value;
461 d82310f7 cmchao
        break;
462 d82310f7 cmchao
463 d82310f7 cmchao
    case 0x4c:        /* GPIO_FALLINGDETECT */
464 d82310f7 cmchao
        s->edge[1] = value;
465 d82310f7 cmchao
        break;
466 d82310f7 cmchao
467 d82310f7 cmchao
    case 0x50:        /* GPIO_DEBOUNCENABLE */
468 d82310f7 cmchao
        s->debounce = value;
469 d82310f7 cmchao
        break;
470 d82310f7 cmchao
471 d82310f7 cmchao
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
472 d82310f7 cmchao
        s->delay = value;
473 d82310f7 cmchao
        break;
474 d82310f7 cmchao
475 d82310f7 cmchao
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
476 d82310f7 cmchao
        s->mask[0] &= ~value;
477 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 0);
478 d82310f7 cmchao
        break;
479 d82310f7 cmchao
480 d82310f7 cmchao
    case 0x64:        /* GPIO_SETIRQENABLE1 */
481 d82310f7 cmchao
        s->mask[0] |= value;
482 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 0);
483 d82310f7 cmchao
        break;
484 d82310f7 cmchao
485 d82310f7 cmchao
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
486 d82310f7 cmchao
        s->mask[1] &= ~value;
487 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 1);
488 d82310f7 cmchao
        break;
489 d82310f7 cmchao
490 d82310f7 cmchao
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
491 d82310f7 cmchao
        s->mask[1] |= value;
492 d82310f7 cmchao
        omap2_gpio_module_int_update(s, 1);
493 d82310f7 cmchao
        break;
494 d82310f7 cmchao
495 d82310f7 cmchao
    case 0x80:        /* GPIO_CLEARWKUENA */
496 d82310f7 cmchao
        s->wumask &= ~value;
497 d82310f7 cmchao
        break;
498 d82310f7 cmchao
499 d82310f7 cmchao
    case 0x84:        /* GPIO_SETWKUENA */
500 d82310f7 cmchao
        s->wumask |= value;
501 d82310f7 cmchao
        break;
502 d82310f7 cmchao
503 d82310f7 cmchao
    case 0x90:        /* GPIO_CLEARDATAOUT */
504 d82310f7 cmchao
        omap2_gpio_module_out_update(s, s->outputs & value);
505 d82310f7 cmchao
        break;
506 d82310f7 cmchao
507 d82310f7 cmchao
    case 0x94:        /* GPIO_SETDATAOUT */
508 d82310f7 cmchao
        omap2_gpio_module_out_update(s, ~s->outputs & value);
509 d82310f7 cmchao
        break;
510 d82310f7 cmchao
511 d82310f7 cmchao
    default:
512 d82310f7 cmchao
        OMAP_BAD_REG(addr);
513 d82310f7 cmchao
        return;
514 d82310f7 cmchao
    }
515 d82310f7 cmchao
}
516 d82310f7 cmchao
517 d82310f7 cmchao
static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
518 d82310f7 cmchao
{
519 e1556ad5 Peter Maydell
    return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
520 d82310f7 cmchao
}
521 d82310f7 cmchao
522 d82310f7 cmchao
static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
523 d82310f7 cmchao
                uint32_t value)
524 d82310f7 cmchao
{
525 d82310f7 cmchao
    uint32_t cur = 0;
526 d82310f7 cmchao
    uint32_t mask = 0xffff;
527 d82310f7 cmchao
528 d82310f7 cmchao
    switch (addr & ~3) {
529 d82310f7 cmchao
    case 0x00:        /* GPIO_REVISION */
530 d82310f7 cmchao
    case 0x14:        /* GPIO_SYSSTATUS */
531 d82310f7 cmchao
    case 0x38:        /* GPIO_DATAIN */
532 d82310f7 cmchao
        OMAP_RO_REG(addr);
533 d82310f7 cmchao
        break;
534 d82310f7 cmchao
535 d82310f7 cmchao
    case 0x10:        /* GPIO_SYSCONFIG */
536 d82310f7 cmchao
    case 0x1c:        /* GPIO_IRQENABLE1 */
537 d82310f7 cmchao
    case 0x20:        /* GPIO_WAKEUPENABLE */
538 d82310f7 cmchao
    case 0x2c:        /* GPIO_IRQENABLE2 */
539 d82310f7 cmchao
    case 0x30:        /* GPIO_CTRL */
540 d82310f7 cmchao
    case 0x34:        /* GPIO_OE */
541 d82310f7 cmchao
    case 0x3c:        /* GPIO_DATAOUT */
542 d82310f7 cmchao
    case 0x40:        /* GPIO_LEVELDETECT0 */
543 d82310f7 cmchao
    case 0x44:        /* GPIO_LEVELDETECT1 */
544 d82310f7 cmchao
    case 0x48:        /* GPIO_RISINGDETECT */
545 d82310f7 cmchao
    case 0x4c:        /* GPIO_FALLINGDETECT */
546 d82310f7 cmchao
    case 0x50:        /* GPIO_DEBOUNCENABLE */
547 d82310f7 cmchao
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
548 d82310f7 cmchao
        cur = omap2_gpio_module_read(opaque, addr & ~3) &
549 d82310f7 cmchao
                ~(mask << ((addr & 3) << 3));
550 d82310f7 cmchao
551 d82310f7 cmchao
        /* Fall through.  */
552 d82310f7 cmchao
    case 0x18:        /* GPIO_IRQSTATUS1 */
553 d82310f7 cmchao
    case 0x28:        /* GPIO_IRQSTATUS2 */
554 d82310f7 cmchao
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
555 d82310f7 cmchao
    case 0x64:        /* GPIO_SETIRQENABLE1 */
556 d82310f7 cmchao
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
557 d82310f7 cmchao
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
558 d82310f7 cmchao
    case 0x80:        /* GPIO_CLEARWKUENA */
559 d82310f7 cmchao
    case 0x84:        /* GPIO_SETWKUENA */
560 d82310f7 cmchao
    case 0x90:        /* GPIO_CLEARDATAOUT */
561 d82310f7 cmchao
    case 0x94:        /* GPIO_SETDATAOUT */
562 d82310f7 cmchao
        value <<= (addr & 3) << 3;
563 d82310f7 cmchao
        omap2_gpio_module_write(opaque, addr, cur | value);
564 d82310f7 cmchao
        break;
565 d82310f7 cmchao
566 d82310f7 cmchao
    default:
567 d82310f7 cmchao
        OMAP_BAD_REG(addr);
568 d82310f7 cmchao
        return;
569 d82310f7 cmchao
    }
570 d82310f7 cmchao
}
571 d82310f7 cmchao
572 9244b42d Avi Kivity
static const MemoryRegionOps omap2_gpio_module_ops = {
573 9244b42d Avi Kivity
    .old_mmio = {
574 9244b42d Avi Kivity
        .read = {
575 9244b42d Avi Kivity
            omap2_gpio_module_readp,
576 9244b42d Avi Kivity
            omap2_gpio_module_readp,
577 9244b42d Avi Kivity
            omap2_gpio_module_read,
578 9244b42d Avi Kivity
        },
579 9244b42d Avi Kivity
        .write = {
580 9244b42d Avi Kivity
            omap2_gpio_module_writep,
581 9244b42d Avi Kivity
            omap2_gpio_module_writep,
582 9244b42d Avi Kivity
            omap2_gpio_module_write,
583 9244b42d Avi Kivity
        },
584 9244b42d Avi Kivity
    },
585 9244b42d Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
586 d82310f7 cmchao
};
587 d82310f7 cmchao
588 77831c20 Juha Riihimäki
static void omap_gpif_reset(DeviceState *dev)
589 d82310f7 cmchao
{
590 77831c20 Juha Riihimäki
    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
591 77831c20 Juha Riihimäki
                    sysbus_from_qdev(dev));
592 77831c20 Juha Riihimäki
    omap_gpio_reset(&s->omap1);
593 d82310f7 cmchao
}
594 d82310f7 cmchao
595 77831c20 Juha Riihimäki
static void omap2_gpif_reset(DeviceState *dev)
596 d82310f7 cmchao
{
597 d82310f7 cmchao
    int i;
598 77831c20 Juha Riihimäki
    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
599 77831c20 Juha Riihimäki
                    sysbus_from_qdev(dev));
600 77831c20 Juha Riihimäki
    for (i = 0; i < s->modulecount; i++) {
601 77831c20 Juha Riihimäki
        omap2_gpio_module_reset(&s->modules[i]);
602 77831c20 Juha Riihimäki
    }
603 d82310f7 cmchao
    s->autoidle = 0;
604 d82310f7 cmchao
    s->gpo = 0;
605 d82310f7 cmchao
}
606 d82310f7 cmchao
607 9244b42d Avi Kivity
static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr,
608 9244b42d Avi Kivity
                                    unsigned size)
609 d82310f7 cmchao
{
610 77831c20 Juha Riihimäki
    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
611 d82310f7 cmchao
612 d82310f7 cmchao
    switch (addr) {
613 d82310f7 cmchao
    case 0x00:        /* IPGENERICOCPSPL_REVISION */
614 d82310f7 cmchao
        return 0x18;
615 d82310f7 cmchao
616 d82310f7 cmchao
    case 0x10:        /* IPGENERICOCPSPL_SYSCONFIG */
617 d82310f7 cmchao
        return s->autoidle;
618 d82310f7 cmchao
619 d82310f7 cmchao
    case 0x14:        /* IPGENERICOCPSPL_SYSSTATUS */
620 d82310f7 cmchao
        return 0x01;
621 d82310f7 cmchao
622 d82310f7 cmchao
    case 0x18:        /* IPGENERICOCPSPL_IRQSTATUS */
623 d82310f7 cmchao
        return 0x00;
624 d82310f7 cmchao
625 d82310f7 cmchao
    case 0x40:        /* IPGENERICOCPSPL_GPO */
626 d82310f7 cmchao
        return s->gpo;
627 d82310f7 cmchao
628 d82310f7 cmchao
    case 0x50:        /* IPGENERICOCPSPL_GPI */
629 d82310f7 cmchao
        return 0x00;
630 d82310f7 cmchao
    }
631 d82310f7 cmchao
632 d82310f7 cmchao
    OMAP_BAD_REG(addr);
633 d82310f7 cmchao
    return 0;
634 d82310f7 cmchao
}
635 d82310f7 cmchao
636 77831c20 Juha Riihimäki
static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
637 9244b42d Avi Kivity
                                 uint64_t value, unsigned size)
638 d82310f7 cmchao
{
639 77831c20 Juha Riihimäki
    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
640 d82310f7 cmchao
641 d82310f7 cmchao
    switch (addr) {
642 d82310f7 cmchao
    case 0x00:        /* IPGENERICOCPSPL_REVISION */
643 d82310f7 cmchao
    case 0x14:        /* IPGENERICOCPSPL_SYSSTATUS */
644 d82310f7 cmchao
    case 0x18:        /* IPGENERICOCPSPL_IRQSTATUS */
645 d82310f7 cmchao
    case 0x50:        /* IPGENERICOCPSPL_GPI */
646 d82310f7 cmchao
        OMAP_RO_REG(addr);
647 d82310f7 cmchao
        break;
648 d82310f7 cmchao
649 d82310f7 cmchao
    case 0x10:        /* IPGENERICOCPSPL_SYSCONFIG */
650 d82310f7 cmchao
        if (value & (1 << 1))                                        /* SOFTRESET */
651 77831c20 Juha Riihimäki
            omap2_gpif_reset(&s->busdev.qdev);
652 d82310f7 cmchao
        s->autoidle = value & 1;
653 d82310f7 cmchao
        break;
654 d82310f7 cmchao
655 d82310f7 cmchao
    case 0x40:        /* IPGENERICOCPSPL_GPO */
656 d82310f7 cmchao
        s->gpo = value & 1;
657 d82310f7 cmchao
        break;
658 d82310f7 cmchao
659 d82310f7 cmchao
    default:
660 d82310f7 cmchao
        OMAP_BAD_REG(addr);
661 d82310f7 cmchao
        return;
662 d82310f7 cmchao
    }
663 d82310f7 cmchao
}
664 d82310f7 cmchao
665 9244b42d Avi Kivity
static const MemoryRegionOps omap2_gpif_top_ops = {
666 9244b42d Avi Kivity
    .read = omap2_gpif_top_read,
667 9244b42d Avi Kivity
    .write = omap2_gpif_top_write,
668 9244b42d Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
669 d82310f7 cmchao
};
670 d82310f7 cmchao
671 77831c20 Juha Riihimäki
static int omap_gpio_init(SysBusDevice *dev)
672 d82310f7 cmchao
{
673 77831c20 Juha Riihimäki
    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
674 77831c20 Juha Riihimäki
    if (!s->clk) {
675 77831c20 Juha Riihimäki
        hw_error("omap-gpio: clk not connected\n");
676 77831c20 Juha Riihimäki
    }
677 77831c20 Juha Riihimäki
    qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
678 77831c20 Juha Riihimäki
    qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
679 77831c20 Juha Riihimäki
    sysbus_init_irq(dev, &s->omap1.irq);
680 9244b42d Avi Kivity
    memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
681 9244b42d Avi Kivity
                          "omap.gpio", 0x1000);
682 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->iomem);
683 77831c20 Juha Riihimäki
    return 0;
684 77831c20 Juha Riihimäki
}
685 d82310f7 cmchao
686 77831c20 Juha Riihimäki
static int omap2_gpio_init(SysBusDevice *dev)
687 77831c20 Juha Riihimäki
{
688 77831c20 Juha Riihimäki
    int i;
689 77831c20 Juha Riihimäki
    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
690 77831c20 Juha Riihimäki
    if (!s->iclk) {
691 77831c20 Juha Riihimäki
        hw_error("omap2-gpio: iclk not connected\n");
692 77831c20 Juha Riihimäki
    }
693 77831c20 Juha Riihimäki
    if (s->mpu_model < omap3430) {
694 77831c20 Juha Riihimäki
        s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
695 9244b42d Avi Kivity
        memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
696 9244b42d Avi Kivity
                              "omap2.gpio", 0x1000);
697 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->iomem);
698 77831c20 Juha Riihimäki
    } else {
699 77831c20 Juha Riihimäki
        s->modulecount = 6;
700 77831c20 Juha Riihimäki
    }
701 7267c094 Anthony Liguori
    s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
702 7267c094 Anthony Liguori
    s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
703 77831c20 Juha Riihimäki
    qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
704 77831c20 Juha Riihimäki
    qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
705 77831c20 Juha Riihimäki
    for (i = 0; i < s->modulecount; i++) {
706 77831c20 Juha Riihimäki
        struct omap2_gpio_s *m = &s->modules[i];
707 77831c20 Juha Riihimäki
        if (!s->fclk[i]) {
708 77831c20 Juha Riihimäki
            hw_error("omap2-gpio: fclk%d not connected\n", i);
709 77831c20 Juha Riihimäki
        }
710 77831c20 Juha Riihimäki
        m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
711 77831c20 Juha Riihimäki
        m->handler = &s->handler[i * 32];
712 77831c20 Juha Riihimäki
        sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
713 77831c20 Juha Riihimäki
        sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
714 77831c20 Juha Riihimäki
        sysbus_init_irq(dev, &m->wkup);
715 9244b42d Avi Kivity
        memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
716 9244b42d Avi Kivity
                              "omap.gpio-module", 0x1000);
717 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &m->iomem);
718 77831c20 Juha Riihimäki
    }
719 77831c20 Juha Riihimäki
    return 0;
720 77831c20 Juha Riihimäki
}
721 d82310f7 cmchao
722 77831c20 Juha Riihimäki
/* Using qdev pointer properties for the clocks is not ideal.
723 77831c20 Juha Riihimäki
 * qdev should support a generic means of defining a 'port' with
724 77831c20 Juha Riihimäki
 * an arbitrary interface for connecting two devices. Then we
725 77831c20 Juha Riihimäki
 * could reframe the omap clock API in terms of clock ports,
726 77831c20 Juha Riihimäki
 * and get some type safety. For now the best qdev provides is
727 77831c20 Juha Riihimäki
 * passing an arbitrary pointer.
728 77831c20 Juha Riihimäki
 * (It's not possible to pass in the string which is the clock
729 77831c20 Juha Riihimäki
 * name, because this device does not have the necessary information
730 77831c20 Juha Riihimäki
 * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
731 77831c20 Juha Riihimäki
 * translation.)
732 77831c20 Juha Riihimäki
 */
733 d82310f7 cmchao
734 999e12bb Anthony Liguori
static Property omap_gpio_properties[] = {
735 999e12bb Anthony Liguori
    DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
736 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
737 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
738 77831c20 Juha Riihimäki
};
739 d82310f7 cmchao
740 999e12bb Anthony Liguori
static void omap_gpio_class_init(ObjectClass *klass, void *data)
741 999e12bb Anthony Liguori
{
742 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
743 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
744 999e12bb Anthony Liguori
745 999e12bb Anthony Liguori
    k->init = omap_gpio_init;
746 39bffca2 Anthony Liguori
    dc->reset = omap_gpif_reset;
747 39bffca2 Anthony Liguori
    dc->props = omap_gpio_properties;
748 999e12bb Anthony Liguori
}
749 999e12bb Anthony Liguori
750 39bffca2 Anthony Liguori
static TypeInfo omap_gpio_info = {
751 39bffca2 Anthony Liguori
    .name          = "omap-gpio",
752 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
753 39bffca2 Anthony Liguori
    .instance_size = sizeof(struct omap_gpif_s),
754 39bffca2 Anthony Liguori
    .class_init    = omap_gpio_class_init,
755 999e12bb Anthony Liguori
};
756 999e12bb Anthony Liguori
757 999e12bb Anthony Liguori
static Property omap2_gpio_properties[] = {
758 999e12bb Anthony Liguori
    DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
759 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
760 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
761 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
762 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
763 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
764 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
765 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
766 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
767 999e12bb Anthony Liguori
};
768 999e12bb Anthony Liguori
769 999e12bb Anthony Liguori
static void omap2_gpio_class_init(ObjectClass *klass, void *data)
770 999e12bb Anthony Liguori
{
771 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
772 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
773 999e12bb Anthony Liguori
774 999e12bb Anthony Liguori
    k->init = omap2_gpio_init;
775 39bffca2 Anthony Liguori
    dc->reset = omap2_gpif_reset;
776 39bffca2 Anthony Liguori
    dc->props = omap2_gpio_properties;
777 999e12bb Anthony Liguori
}
778 999e12bb Anthony Liguori
779 39bffca2 Anthony Liguori
static TypeInfo omap2_gpio_info = {
780 39bffca2 Anthony Liguori
    .name          = "omap2-gpio",
781 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
782 39bffca2 Anthony Liguori
    .instance_size = sizeof(struct omap2_gpif_s),
783 39bffca2 Anthony Liguori
    .class_init    = omap2_gpio_class_init,
784 77831c20 Juha Riihimäki
};
785 d82310f7 cmchao
786 83f7d43a Andreas Färber
static void omap_gpio_register_types(void)
787 d82310f7 cmchao
{
788 39bffca2 Anthony Liguori
    type_register_static(&omap_gpio_info);
789 39bffca2 Anthony Liguori
    type_register_static(&omap2_gpio_info);
790 d82310f7 cmchao
}
791 d82310f7 cmchao
792 83f7d43a Andreas Färber
type_init(omap_gpio_register_types)