Statistics
| Branch: | Revision:

root / hw / omap_gpio.c @ b0eb8449

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