~ubuntu-branches/ubuntu/wily/qemu-kvm-spice/wily

« back to all changes in this revision

Viewing changes to hw/omap_gpio.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-10-19 10:44:56 UTC
  • Revision ID: james.westby@ubuntu.com-20111019104456-xgvskumk3sxi97f4
Tags: upstream-0.15.0+noroms
ImportĀ upstreamĀ versionĀ 0.15.0+noroms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * TI OMAP processors GPIO emulation.
 
3
 *
 
4
 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
 
5
 * Copyright (C) 2007-2009 Nokia Corporation
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation; either version 2 or
 
10
 * (at your option) version 3 of the License.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include "hw.h"
 
22
#include "omap.h"
 
23
/* General-Purpose I/O */
 
24
struct omap_gpio_s {
 
25
    qemu_irq irq;
 
26
    qemu_irq *in;
 
27
    qemu_irq handler[16];
 
28
 
 
29
    uint16_t inputs;
 
30
    uint16_t outputs;
 
31
    uint16_t dir;
 
32
    uint16_t edge;
 
33
    uint16_t mask;
 
34
    uint16_t ints;
 
35
    uint16_t pins;
 
36
};
 
37
 
 
38
static void omap_gpio_set(void *opaque, int line, int level)
 
39
{
 
40
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
 
41
    uint16_t prev = s->inputs;
 
42
 
 
43
    if (level)
 
44
        s->inputs |= 1 << line;
 
45
    else
 
46
        s->inputs &= ~(1 << line);
 
47
 
 
48
    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
 
49
                    (1 << line) & s->dir & ~s->mask) {
 
50
        s->ints |= 1 << line;
 
51
        qemu_irq_raise(s->irq);
 
52
    }
 
53
}
 
54
 
 
55
static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
 
56
{
 
57
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
 
58
    int offset = addr & OMAP_MPUI_REG_MASK;
 
59
 
 
60
    switch (offset) {
 
61
    case 0x00:  /* DATA_INPUT */
 
62
        return s->inputs & s->pins;
 
63
 
 
64
    case 0x04:  /* DATA_OUTPUT */
 
65
        return s->outputs;
 
66
 
 
67
    case 0x08:  /* DIRECTION_CONTROL */
 
68
        return s->dir;
 
69
 
 
70
    case 0x0c:  /* INTERRUPT_CONTROL */
 
71
        return s->edge;
 
72
 
 
73
    case 0x10:  /* INTERRUPT_MASK */
 
74
        return s->mask;
 
75
 
 
76
    case 0x14:  /* INTERRUPT_STATUS */
 
77
        return s->ints;
 
78
 
 
79
    case 0x18:  /* PIN_CONTROL (not in OMAP310) */
 
80
        OMAP_BAD_REG(addr);
 
81
        return s->pins;
 
82
    }
 
83
 
 
84
    OMAP_BAD_REG(addr);
 
85
    return 0;
 
86
}
 
87
 
 
88
static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
 
89
                uint32_t value)
 
90
{
 
91
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
 
92
    int offset = addr & OMAP_MPUI_REG_MASK;
 
93
    uint16_t diff;
 
94
    int ln;
 
95
 
 
96
    switch (offset) {
 
97
    case 0x00:  /* DATA_INPUT */
 
98
        OMAP_RO_REG(addr);
 
99
        return;
 
100
 
 
101
    case 0x04:  /* DATA_OUTPUT */
 
102
        diff = (s->outputs ^ value) & ~s->dir;
 
103
        s->outputs = value;
 
104
        while ((ln = ffs(diff))) {
 
105
            ln --;
 
106
            if (s->handler[ln])
 
107
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 
108
            diff &= ~(1 << ln);
 
109
        }
 
110
        break;
 
111
 
 
112
    case 0x08:  /* DIRECTION_CONTROL */
 
113
        diff = s->outputs & (s->dir ^ value);
 
114
        s->dir = value;
 
115
 
 
116
        value = s->outputs & ~s->dir;
 
117
        while ((ln = ffs(diff))) {
 
118
            ln --;
 
119
            if (s->handler[ln])
 
120
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 
121
            diff &= ~(1 << ln);
 
122
        }
 
123
        break;
 
124
 
 
125
    case 0x0c:  /* INTERRUPT_CONTROL */
 
126
        s->edge = value;
 
127
        break;
 
128
 
 
129
    case 0x10:  /* INTERRUPT_MASK */
 
130
        s->mask = value;
 
131
        break;
 
132
 
 
133
    case 0x14:  /* INTERRUPT_STATUS */
 
134
        s->ints &= ~value;
 
135
        if (!s->ints)
 
136
            qemu_irq_lower(s->irq);
 
137
        break;
 
138
 
 
139
    case 0x18:  /* PIN_CONTROL (not in OMAP310 TRM) */
 
140
        OMAP_BAD_REG(addr);
 
141
        s->pins = value;
 
142
        break;
 
143
 
 
144
    default:
 
145
        OMAP_BAD_REG(addr);
 
146
        return;
 
147
    }
 
148
}
 
149
 
 
150
/* *Some* sources say the memory region is 32-bit.  */
 
151
static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
 
152
    omap_badwidth_read16,
 
153
    omap_gpio_read,
 
154
    omap_badwidth_read16,
 
155
};
 
156
 
 
157
static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
 
158
    omap_badwidth_write16,
 
159
    omap_gpio_write,
 
160
    omap_badwidth_write16,
 
161
};
 
162
 
 
163
void omap_gpio_reset(struct omap_gpio_s *s)
 
164
{
 
165
    s->inputs = 0;
 
166
    s->outputs = ~0;
 
167
    s->dir = ~0;
 
168
    s->edge = ~0;
 
169
    s->mask = ~0;
 
170
    s->ints = 0;
 
171
    s->pins = ~0;
 
172
}
 
173
 
 
174
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
 
175
                qemu_irq irq, omap_clk clk)
 
176
{
 
177
    int iomemtype;
 
178
    struct omap_gpio_s *s = (struct omap_gpio_s *)
 
179
            qemu_mallocz(sizeof(struct omap_gpio_s));
 
180
 
 
181
    s->irq = irq;
 
182
    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
 
183
    omap_gpio_reset(s);
 
184
 
 
185
    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
 
186
                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
 
187
    cpu_register_physical_memory(base, 0x1000, iomemtype);
 
188
 
 
189
    return s;
 
190
}
 
191
 
 
192
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
 
193
{
 
194
    return s->in;
 
195
}
 
196
 
 
197
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
 
198
{
 
199
    if (line >= 16 || line < 0)
 
200
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
 
201
    s->handler[line] = handler;
 
202
}
 
203
 
 
204
/* General-Purpose Interface of OMAP2 */
 
205
struct omap2_gpio_s {
 
206
    qemu_irq irq[2];
 
207
    qemu_irq wkup;
 
208
    qemu_irq *in;
 
209
    qemu_irq handler[32];
 
210
 
 
211
    uint8_t config[2];
 
212
    uint32_t inputs;
 
213
    uint32_t outputs;
 
214
    uint32_t dir;
 
215
    uint32_t level[2];
 
216
    uint32_t edge[2];
 
217
    uint32_t mask[2];
 
218
    uint32_t wumask;
 
219
    uint32_t ints[2];
 
220
    uint32_t debounce;
 
221
    uint8_t delay;
 
222
};
 
223
 
 
224
static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
 
225
                int line)
 
226
{
 
227
    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 
228
}
 
229
 
 
230
static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
 
231
{
 
232
    if (!(s->config[0] & (1 << 2)))                     /* ENAWAKEUP */
 
233
        return;
 
234
    if (!(s->config[0] & (3 << 3)))                     /* Force Idle */
 
235
        return;
 
236
    if (!(s->wumask & (1 << line)))
 
237
        return;
 
238
 
 
239
    qemu_irq_raise(s->wkup);
 
240
}
 
241
 
 
242
static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
 
243
                uint32_t diff)
 
244
{
 
245
    int ln;
 
246
 
 
247
    s->outputs ^= diff;
 
248
    diff &= ~s->dir;
 
249
    while ((ln = ffs(diff))) {
 
250
        ln --;
 
251
        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
 
252
        diff &= ~(1 << ln);
 
253
    }
 
254
}
 
255
 
 
256
static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
 
257
{
 
258
    s->ints[line] |= s->dir &
 
259
            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
 
260
    omap2_gpio_module_int_update(s, line);
 
261
}
 
262
 
 
263
static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
 
264
{
 
265
    s->ints[0] |= 1 << line;
 
266
    omap2_gpio_module_int_update(s, 0);
 
267
    s->ints[1] |= 1 << line;
 
268
    omap2_gpio_module_int_update(s, 1);
 
269
    omap2_gpio_module_wake(s, line);
 
270
}
 
271
 
 
272
static void omap2_gpio_module_set(void *opaque, int line, int level)
 
273
{
 
274
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 
275
 
 
276
    if (level) {
 
277
        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
 
278
            omap2_gpio_module_int(s, line);
 
279
        s->inputs |= 1 << line;
 
280
    } else {
 
281
        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
 
282
            omap2_gpio_module_int(s, line);
 
283
        s->inputs &= ~(1 << line);
 
284
    }
 
285
}
 
286
 
 
287
static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
 
288
{
 
289
    s->config[0] = 0;
 
290
    s->config[1] = 2;
 
291
    s->ints[0] = 0;
 
292
    s->ints[1] = 0;
 
293
    s->mask[0] = 0;
 
294
    s->mask[1] = 0;
 
295
    s->wumask = 0;
 
296
    s->dir = ~0;
 
297
    s->level[0] = 0;
 
298
    s->level[1] = 0;
 
299
    s->edge[0] = 0;
 
300
    s->edge[1] = 0;
 
301
    s->debounce = 0;
 
302
    s->delay = 0;
 
303
}
 
304
 
 
305
static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
 
306
{
 
307
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 
308
 
 
309
    switch (addr) {
 
310
    case 0x00:  /* GPIO_REVISION */
 
311
        return 0x18;
 
312
 
 
313
    case 0x10:  /* GPIO_SYSCONFIG */
 
314
        return s->config[0];
 
315
 
 
316
    case 0x14:  /* GPIO_SYSSTATUS */
 
317
        return 0x01;
 
318
 
 
319
    case 0x18:  /* GPIO_IRQSTATUS1 */
 
320
        return s->ints[0];
 
321
 
 
322
    case 0x1c:  /* GPIO_IRQENABLE1 */
 
323
    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 
324
    case 0x64:  /* GPIO_SETIRQENABLE1 */
 
325
        return s->mask[0];
 
326
 
 
327
    case 0x20:  /* GPIO_WAKEUPENABLE */
 
328
    case 0x80:  /* GPIO_CLEARWKUENA */
 
329
    case 0x84:  /* GPIO_SETWKUENA */
 
330
        return s->wumask;
 
331
 
 
332
    case 0x28:  /* GPIO_IRQSTATUS2 */
 
333
        return s->ints[1];
 
334
 
 
335
    case 0x2c:  /* GPIO_IRQENABLE2 */
 
336
    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 
337
    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 
338
        return s->mask[1];
 
339
 
 
340
    case 0x30:  /* GPIO_CTRL */
 
341
        return s->config[1];
 
342
 
 
343
    case 0x34:  /* GPIO_OE */
 
344
        return s->dir;
 
345
 
 
346
    case 0x38:  /* GPIO_DATAIN */
 
347
        return s->inputs;
 
348
 
 
349
    case 0x3c:  /* GPIO_DATAOUT */
 
350
    case 0x90:  /* GPIO_CLEARDATAOUT */
 
351
    case 0x94:  /* GPIO_SETDATAOUT */
 
352
        return s->outputs;
 
353
 
 
354
    case 0x40:  /* GPIO_LEVELDETECT0 */
 
355
        return s->level[0];
 
356
 
 
357
    case 0x44:  /* GPIO_LEVELDETECT1 */
 
358
        return s->level[1];
 
359
 
 
360
    case 0x48:  /* GPIO_RISINGDETECT */
 
361
        return s->edge[0];
 
362
 
 
363
    case 0x4c:  /* GPIO_FALLINGDETECT */
 
364
        return s->edge[1];
 
365
 
 
366
    case 0x50:  /* GPIO_DEBOUNCENABLE */
 
367
        return s->debounce;
 
368
 
 
369
    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 
370
        return s->delay;
 
371
    }
 
372
 
 
373
    OMAP_BAD_REG(addr);
 
374
    return 0;
 
375
}
 
376
 
 
377
static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
 
378
                uint32_t value)
 
379
{
 
380
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 
381
    uint32_t diff;
 
382
    int ln;
 
383
 
 
384
    switch (addr) {
 
385
    case 0x00:  /* GPIO_REVISION */
 
386
    case 0x14:  /* GPIO_SYSSTATUS */
 
387
    case 0x38:  /* GPIO_DATAIN */
 
388
        OMAP_RO_REG(addr);
 
389
        break;
 
390
 
 
391
    case 0x10:  /* GPIO_SYSCONFIG */
 
392
        if (((value >> 3) & 3) == 3)
 
393
            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
 
394
        if (value & 2)
 
395
            omap2_gpio_module_reset(s);
 
396
        s->config[0] = value & 0x1d;
 
397
        break;
 
398
 
 
399
    case 0x18:  /* GPIO_IRQSTATUS1 */
 
400
        if (s->ints[0] & value) {
 
401
            s->ints[0] &= ~value;
 
402
            omap2_gpio_module_level_update(s, 0);
 
403
        }
 
404
        break;
 
405
 
 
406
    case 0x1c:  /* GPIO_IRQENABLE1 */
 
407
        s->mask[0] = value;
 
408
        omap2_gpio_module_int_update(s, 0);
 
409
        break;
 
410
 
 
411
    case 0x20:  /* GPIO_WAKEUPENABLE */
 
412
        s->wumask = value;
 
413
        break;
 
414
 
 
415
    case 0x28:  /* GPIO_IRQSTATUS2 */
 
416
        if (s->ints[1] & value) {
 
417
            s->ints[1] &= ~value;
 
418
            omap2_gpio_module_level_update(s, 1);
 
419
        }
 
420
        break;
 
421
 
 
422
    case 0x2c:  /* GPIO_IRQENABLE2 */
 
423
        s->mask[1] = value;
 
424
        omap2_gpio_module_int_update(s, 1);
 
425
        break;
 
426
 
 
427
    case 0x30:  /* GPIO_CTRL */
 
428
        s->config[1] = value & 7;
 
429
        break;
 
430
 
 
431
    case 0x34:  /* GPIO_OE */
 
432
        diff = s->outputs & (s->dir ^ value);
 
433
        s->dir = value;
 
434
 
 
435
        value = s->outputs & ~s->dir;
 
436
        while ((ln = ffs(diff))) {
 
437
            diff &= ~(1 <<-- ln);
 
438
            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 
439
        }
 
440
 
 
441
        omap2_gpio_module_level_update(s, 0);
 
442
        omap2_gpio_module_level_update(s, 1);
 
443
        break;
 
444
 
 
445
    case 0x3c:  /* GPIO_DATAOUT */
 
446
        omap2_gpio_module_out_update(s, s->outputs ^ value);
 
447
        break;
 
448
 
 
449
    case 0x40:  /* GPIO_LEVELDETECT0 */
 
450
        s->level[0] = value;
 
451
        omap2_gpio_module_level_update(s, 0);
 
452
        omap2_gpio_module_level_update(s, 1);
 
453
        break;
 
454
 
 
455
    case 0x44:  /* GPIO_LEVELDETECT1 */
 
456
        s->level[1] = value;
 
457
        omap2_gpio_module_level_update(s, 0);
 
458
        omap2_gpio_module_level_update(s, 1);
 
459
        break;
 
460
 
 
461
    case 0x48:  /* GPIO_RISINGDETECT */
 
462
        s->edge[0] = value;
 
463
        break;
 
464
 
 
465
    case 0x4c:  /* GPIO_FALLINGDETECT */
 
466
        s->edge[1] = value;
 
467
        break;
 
468
 
 
469
    case 0x50:  /* GPIO_DEBOUNCENABLE */
 
470
        s->debounce = value;
 
471
        break;
 
472
 
 
473
    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 
474
        s->delay = value;
 
475
        break;
 
476
 
 
477
    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 
478
        s->mask[0] &= ~value;
 
479
        omap2_gpio_module_int_update(s, 0);
 
480
        break;
 
481
 
 
482
    case 0x64:  /* GPIO_SETIRQENABLE1 */
 
483
        s->mask[0] |= value;
 
484
        omap2_gpio_module_int_update(s, 0);
 
485
        break;
 
486
 
 
487
    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 
488
        s->mask[1] &= ~value;
 
489
        omap2_gpio_module_int_update(s, 1);
 
490
        break;
 
491
 
 
492
    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 
493
        s->mask[1] |= value;
 
494
        omap2_gpio_module_int_update(s, 1);
 
495
        break;
 
496
 
 
497
    case 0x80:  /* GPIO_CLEARWKUENA */
 
498
        s->wumask &= ~value;
 
499
        break;
 
500
 
 
501
    case 0x84:  /* GPIO_SETWKUENA */
 
502
        s->wumask |= value;
 
503
        break;
 
504
 
 
505
    case 0x90:  /* GPIO_CLEARDATAOUT */
 
506
        omap2_gpio_module_out_update(s, s->outputs & value);
 
507
        break;
 
508
 
 
509
    case 0x94:  /* GPIO_SETDATAOUT */
 
510
        omap2_gpio_module_out_update(s, ~s->outputs & value);
 
511
        break;
 
512
 
 
513
    default:
 
514
        OMAP_BAD_REG(addr);
 
515
        return;
 
516
    }
 
517
}
 
518
 
 
519
static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
 
520
{
 
521
    return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
 
522
}
 
523
 
 
524
static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
 
525
                uint32_t value)
 
526
{
 
527
    uint32_t cur = 0;
 
528
    uint32_t mask = 0xffff;
 
529
 
 
530
    switch (addr & ~3) {
 
531
    case 0x00:  /* GPIO_REVISION */
 
532
    case 0x14:  /* GPIO_SYSSTATUS */
 
533
    case 0x38:  /* GPIO_DATAIN */
 
534
        OMAP_RO_REG(addr);
 
535
        break;
 
536
 
 
537
    case 0x10:  /* GPIO_SYSCONFIG */
 
538
    case 0x1c:  /* GPIO_IRQENABLE1 */
 
539
    case 0x20:  /* GPIO_WAKEUPENABLE */
 
540
    case 0x2c:  /* GPIO_IRQENABLE2 */
 
541
    case 0x30:  /* GPIO_CTRL */
 
542
    case 0x34:  /* GPIO_OE */
 
543
    case 0x3c:  /* GPIO_DATAOUT */
 
544
    case 0x40:  /* GPIO_LEVELDETECT0 */
 
545
    case 0x44:  /* GPIO_LEVELDETECT1 */
 
546
    case 0x48:  /* GPIO_RISINGDETECT */
 
547
    case 0x4c:  /* GPIO_FALLINGDETECT */
 
548
    case 0x50:  /* GPIO_DEBOUNCENABLE */
 
549
    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 
550
        cur = omap2_gpio_module_read(opaque, addr & ~3) &
 
551
                ~(mask << ((addr & 3) << 3));
 
552
 
 
553
        /* Fall through.  */
 
554
    case 0x18:  /* GPIO_IRQSTATUS1 */
 
555
    case 0x28:  /* GPIO_IRQSTATUS2 */
 
556
    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 
557
    case 0x64:  /* GPIO_SETIRQENABLE1 */
 
558
    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 
559
    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 
560
    case 0x80:  /* GPIO_CLEARWKUENA */
 
561
    case 0x84:  /* GPIO_SETWKUENA */
 
562
    case 0x90:  /* GPIO_CLEARDATAOUT */
 
563
    case 0x94:  /* GPIO_SETDATAOUT */
 
564
        value <<= (addr & 3) << 3;
 
565
        omap2_gpio_module_write(opaque, addr, cur | value);
 
566
        break;
 
567
 
 
568
    default:
 
569
        OMAP_BAD_REG(addr);
 
570
        return;
 
571
    }
 
572
}
 
573
 
 
574
static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
 
575
    omap2_gpio_module_readp,
 
576
    omap2_gpio_module_readp,
 
577
    omap2_gpio_module_read,
 
578
};
 
579
 
 
580
static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
 
581
    omap2_gpio_module_writep,
 
582
    omap2_gpio_module_writep,
 
583
    omap2_gpio_module_write,
 
584
};
 
585
 
 
586
static void omap2_gpio_module_init(struct omap2_gpio_s *s,
 
587
                struct omap_target_agent_s *ta, int region,
 
588
                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
 
589
                omap_clk fclk, omap_clk iclk)
 
590
{
 
591
    int iomemtype;
 
592
 
 
593
    s->irq[0] = mpu;
 
594
    s->irq[1] = dsp;
 
595
    s->wkup = wkup;
 
596
    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
 
597
 
 
598
    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
 
599
                    omap2_gpio_module_writefn, s);
 
600
    omap_l4_attach(ta, region, iomemtype);
 
601
}
 
602
 
 
603
struct omap_gpif_s {
 
604
    struct omap2_gpio_s module[5];
 
605
    int modules;
 
606
 
 
607
    int autoidle;
 
608
    int gpo;
 
609
};
 
610
 
 
611
void omap_gpif_reset(struct omap_gpif_s *s)
 
612
{
 
613
    int i;
 
614
 
 
615
    for (i = 0; i < s->modules; i ++)
 
616
        omap2_gpio_module_reset(s->module + i);
 
617
 
 
618
    s->autoidle = 0;
 
619
    s->gpo = 0;
 
620
}
 
621
 
 
622
static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
 
623
{
 
624
    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
 
625
 
 
626
    switch (addr) {
 
627
    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 
628
        return 0x18;
 
629
 
 
630
    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 
631
        return s->autoidle;
 
632
 
 
633
    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 
634
        return 0x01;
 
635
 
 
636
    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 
637
        return 0x00;
 
638
 
 
639
    case 0x40:  /* IPGENERICOCPSPL_GPO */
 
640
        return s->gpo;
 
641
 
 
642
    case 0x50:  /* IPGENERICOCPSPL_GPI */
 
643
        return 0x00;
 
644
    }
 
645
 
 
646
    OMAP_BAD_REG(addr);
 
647
    return 0;
 
648
}
 
649
 
 
650
static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
 
651
                uint32_t value)
 
652
{
 
653
    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
 
654
 
 
655
    switch (addr) {
 
656
    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 
657
    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 
658
    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 
659
    case 0x50:  /* IPGENERICOCPSPL_GPI */
 
660
        OMAP_RO_REG(addr);
 
661
        break;
 
662
 
 
663
    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 
664
        if (value & (1 << 1))                                   /* SOFTRESET */
 
665
            omap_gpif_reset(s);
 
666
        s->autoidle = value & 1;
 
667
        break;
 
668
 
 
669
    case 0x40:  /* IPGENERICOCPSPL_GPO */
 
670
        s->gpo = value & 1;
 
671
        break;
 
672
 
 
673
    default:
 
674
        OMAP_BAD_REG(addr);
 
675
        return;
 
676
    }
 
677
}
 
678
 
 
679
static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
 
680
    omap_gpif_top_read,
 
681
    omap_gpif_top_read,
 
682
    omap_gpif_top_read,
 
683
};
 
684
 
 
685
static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
 
686
    omap_gpif_top_write,
 
687
    omap_gpif_top_write,
 
688
    omap_gpif_top_write,
 
689
};
 
690
 
 
691
struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
 
692
                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
 
693
{
 
694
    int iomemtype, i;
 
695
    struct omap_gpif_s *s = (struct omap_gpif_s *)
 
696
            qemu_mallocz(sizeof(struct omap_gpif_s));
 
697
    int region[4] = { 0, 2, 4, 5 };
 
698
 
 
699
    s->modules = modules;
 
700
    for (i = 0; i < modules; i ++)
 
701
        omap2_gpio_module_init(s->module + i, ta, region[i],
 
702
                              irq[i], NULL, NULL, fclk[i], iclk);
 
703
 
 
704
    omap_gpif_reset(s);
 
705
 
 
706
    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
 
707
                    omap_gpif_top_writefn, s);
 
708
    omap_l4_attach(ta, 1, iomemtype);
 
709
 
 
710
    return s;
 
711
}
 
712
 
 
713
qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
 
714
{
 
715
    if (start >= s->modules * 32 || start < 0)
 
716
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
 
717
    return s->module[start >> 5].in + (start & 31);
 
718
}
 
719
 
 
720
void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
 
721
{
 
722
    if (line >= s->modules * 32 || line < 0)
 
723
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
 
724
    s->module[line >> 5].handler[line & 31] = handler;
 
725
}