Revision e5c6b25a

b/Makefile.target
268 268
obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
269 269
obj-arm-y += gumstix.o
270 270
obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
271
obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
271
obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o omap_gpio.o
272 272
obj-arm-y += omap2.o omap_dss.o soc_dma.o
273 273
obj-arm-y += omap_sx1.o palm.o tsc210x.o
274 274
obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
b/hw/omap.h
671 671
struct omap_gpio_s;
672 672
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
673 673
                qemu_irq irq, omap_clk clk);
674
void omap_gpio_reset(struct omap_gpio_s *s);
674 675
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
675 676
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
676 677

  
b/hw/omap1.c
2804 2804
    omap_mpuio_kbd_update(s);
2805 2805
}
2806 2806

  
2807
/* General-Purpose I/O */
2808
struct omap_gpio_s {
2809
    qemu_irq irq;
2810
    qemu_irq *in;
2811
    qemu_irq handler[16];
2812

  
2813
    uint16_t inputs;
2814
    uint16_t outputs;
2815
    uint16_t dir;
2816
    uint16_t edge;
2817
    uint16_t mask;
2818
    uint16_t ints;
2819
    uint16_t pins;
2820
};
2821

  
2822
static void omap_gpio_set(void *opaque, int line, int level)
2823
{
2824
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
2825
    uint16_t prev = s->inputs;
2826

  
2827
    if (level)
2828
        s->inputs |= 1 << line;
2829
    else
2830
        s->inputs &= ~(1 << line);
2831

  
2832
    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
2833
                    (1 << line) & s->dir & ~s->mask) {
2834
        s->ints |= 1 << line;
2835
        qemu_irq_raise(s->irq);
2836
    }
2837
}
2838

  
2839
static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
2840
{
2841
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
2842
    int offset = addr & OMAP_MPUI_REG_MASK;
2843

  
2844
    switch (offset) {
2845
    case 0x00:	/* DATA_INPUT */
2846
        return s->inputs & s->pins;
2847

  
2848
    case 0x04:	/* DATA_OUTPUT */
2849
        return s->outputs;
2850

  
2851
    case 0x08:	/* DIRECTION_CONTROL */
2852
        return s->dir;
2853

  
2854
    case 0x0c:	/* INTERRUPT_CONTROL */
2855
        return s->edge;
2856

  
2857
    case 0x10:	/* INTERRUPT_MASK */
2858
        return s->mask;
2859

  
2860
    case 0x14:	/* INTERRUPT_STATUS */
2861
        return s->ints;
2862

  
2863
    case 0x18:	/* PIN_CONTROL (not in OMAP310) */
2864
        OMAP_BAD_REG(addr);
2865
        return s->pins;
2866
    }
2867

  
2868
    OMAP_BAD_REG(addr);
2869
    return 0;
2870
}
2871

  
2872
static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
2873
                uint32_t value)
2874
{
2875
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
2876
    int offset = addr & OMAP_MPUI_REG_MASK;
2877
    uint16_t diff;
2878
    int ln;
2879

  
2880
    switch (offset) {
2881
    case 0x00:	/* DATA_INPUT */
2882
        OMAP_RO_REG(addr);
2883
        return;
2884

  
2885
    case 0x04:	/* DATA_OUTPUT */
2886
        diff = (s->outputs ^ value) & ~s->dir;
2887
        s->outputs = value;
2888
        while ((ln = ffs(diff))) {
2889
            ln --;
2890
            if (s->handler[ln])
2891
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2892
            diff &= ~(1 << ln);
2893
        }
2894
        break;
2895

  
2896
    case 0x08:	/* DIRECTION_CONTROL */
2897
        diff = s->outputs & (s->dir ^ value);
2898
        s->dir = value;
2899

  
2900
        value = s->outputs & ~s->dir;
2901
        while ((ln = ffs(diff))) {
2902
            ln --;
2903
            if (s->handler[ln])
2904
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2905
            diff &= ~(1 << ln);
2906
        }
2907
        break;
2908

  
2909
    case 0x0c:	/* INTERRUPT_CONTROL */
2910
        s->edge = value;
2911
        break;
2912

  
2913
    case 0x10:	/* INTERRUPT_MASK */
2914
        s->mask = value;
2915
        break;
2916

  
2917
    case 0x14:	/* INTERRUPT_STATUS */
2918
        s->ints &= ~value;
2919
        if (!s->ints)
2920
            qemu_irq_lower(s->irq);
2921
        break;
2922

  
2923
    case 0x18:	/* PIN_CONTROL (not in OMAP310 TRM) */
2924
        OMAP_BAD_REG(addr);
2925
        s->pins = value;
2926
        break;
2927

  
2928
    default:
2929
        OMAP_BAD_REG(addr);
2930
        return;
2931
    }
2932
}
2933

  
2934
/* *Some* sources say the memory region is 32-bit.  */
2935
static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
2936
    omap_badwidth_read16,
2937
    omap_gpio_read,
2938
    omap_badwidth_read16,
2939
};
2940

  
2941
static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
2942
    omap_badwidth_write16,
2943
    omap_gpio_write,
2944
    omap_badwidth_write16,
2945
};
2946

  
2947
static void omap_gpio_reset(struct omap_gpio_s *s)
2948
{
2949
    s->inputs = 0;
2950
    s->outputs = ~0;
2951
    s->dir = ~0;
2952
    s->edge = ~0;
2953
    s->mask = ~0;
2954
    s->ints = 0;
2955
    s->pins = ~0;
2956
}
2957

  
2958
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
2959
                qemu_irq irq, omap_clk clk)
2960
{
2961
    int iomemtype;
2962
    struct omap_gpio_s *s = (struct omap_gpio_s *)
2963
            qemu_mallocz(sizeof(struct omap_gpio_s));
2964

  
2965
    s->irq = irq;
2966
    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
2967
    omap_gpio_reset(s);
2968

  
2969
    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
2970
                    omap_gpio_writefn, s);
2971
    cpu_register_physical_memory(base, 0x1000, iomemtype);
2972

  
2973
    return s;
2974
}
2975

  
2976
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
2977
{
2978
    return s->in;
2979
}
2980

  
2981
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
2982
{
2983
    if (line >= 16 || line < 0)
2984
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
2985
    s->handler[line] = handler;
2986
}
2987

  
2988 2807
/* MicroWire Interface */
2989 2808
struct omap_uwire_s {
2990 2809
    qemu_irq txirq;
b/hw/omap_gpio.c
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);
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
}

Also available in: Unified diff