Install keymaps from new location
[qemu] / hw / mst_fpga.c
1 /*
2  * PXA270-based Intel Mainstone platforms.
3  * FPGA driver
4  *
5  * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
6  *                                    <akuster@mvista.com>
7  *
8  * This code is licensed under the GNU GPL v2.
9  */
10 #include "hw.h"
11 #include "pxa.h"
12 #include "mainstone.h"
13
14 /* Mainstone FPGA for extern irqs */
15 #define FPGA_GPIO_PIN   0
16 #define MST_NUM_IRQS    16
17 #define MST_LEDDAT1             0x10
18 #define MST_LEDDAT2             0x14
19 #define MST_LEDCTRL             0x40
20 #define MST_GPSWR               0x60
21 #define MST_MSCWR1              0x80
22 #define MST_MSCWR2              0x84
23 #define MST_MSCWR3              0x88
24 #define MST_MSCRD               0x90
25 #define MST_INTMSKENA   0xc0
26 #define MST_INTSETCLR   0xd0
27 #define MST_PCMCIA0             0xe0
28 #define MST_PCMCIA1             0xe4
29
30 typedef struct mst_irq_state{
31         qemu_irq *parent;
32         qemu_irq *pins;
33
34         uint32_t prev_level;
35         uint32_t leddat1;
36         uint32_t leddat2;
37         uint32_t ledctrl;
38         uint32_t gpswr;
39         uint32_t mscwr1;
40         uint32_t mscwr2;
41         uint32_t mscwr3;
42         uint32_t mscrd;
43         uint32_t intmskena;
44         uint32_t intsetclr;
45         uint32_t pcmcia0;
46         uint32_t pcmcia1;
47 }mst_irq_state;
48
49 static void
50 mst_fpga_update_gpio(mst_irq_state *s)
51 {
52         uint32_t level, diff;
53         int bit;
54         level = s->prev_level ^ s->intsetclr;
55
56         for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
57                 bit = ffs(diff) - 1;
58                 qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
59         }
60         s->prev_level = level;
61 }
62
63 static void
64 mst_fpga_set_irq(void *opaque, int irq, int level)
65 {
66         mst_irq_state *s = (mst_irq_state *)opaque;
67
68         if (level)
69                 s->prev_level |= 1u << irq;
70         else
71                 s->prev_level &= ~(1u << irq);
72
73         if(s->intmskena & (1u << irq)) {
74                 s->intsetclr = 1u << irq;
75                 qemu_set_irq(s->parent[0], level);
76         }
77 }
78
79
80 static uint32_t
81 mst_fpga_readb(void *opaque, target_phys_addr_t addr)
82 {
83         mst_irq_state *s = (mst_irq_state *) opaque;
84
85         switch (addr) {
86         case MST_LEDDAT1:
87                 return s->leddat1;
88         case MST_LEDDAT2:
89                 return s->leddat2;
90         case MST_LEDCTRL:
91                 return s->ledctrl;
92         case MST_GPSWR:
93                 return s->gpswr;
94         case MST_MSCWR1:
95                 return s->mscwr1;
96         case MST_MSCWR2:
97                 return s->mscwr2;
98         case MST_MSCWR3:
99                 return s->mscwr3;
100         case MST_MSCRD:
101                 return s->mscrd;
102         case MST_INTMSKENA:
103                 return s->intmskena;
104         case MST_INTSETCLR:
105                 return s->intsetclr;
106         case MST_PCMCIA0:
107                 return s->pcmcia0;
108         case MST_PCMCIA1:
109                 return s->pcmcia1;
110         default:
111                 printf("Mainstone - mst_fpga_readb: Bad register offset "
112                         REG_FMT " \n", addr);
113         }
114         return 0;
115 }
116
117 static void
118 mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
119 {
120         mst_irq_state *s = (mst_irq_state *) opaque;
121         value &= 0xffffffff;
122
123         switch (addr) {
124         case MST_LEDDAT1:
125                 s->leddat1 = value;
126                 break;
127         case MST_LEDDAT2:
128                 s->leddat2 = value;
129                 break;
130         case MST_LEDCTRL:
131                 s->ledctrl = value;
132                 break;
133         case MST_GPSWR:
134                 s->gpswr = value;
135                 break;
136         case MST_MSCWR1:
137                 s->mscwr1 = value;
138                 break;
139         case MST_MSCWR2:
140                 s->mscwr2 = value;
141                 break;
142         case MST_MSCWR3:
143                 s->mscwr3 = value;
144                 break;
145         case MST_MSCRD:
146                 s->mscrd =  value;
147                 break;
148         case MST_INTMSKENA:     /* Mask interupt */
149                 s->intmskena = (value & 0xFEEFF);
150                 mst_fpga_update_gpio(s);
151                 break;
152         case MST_INTSETCLR:     /* clear or set interrupt */
153                 s->intsetclr = (value & 0xFEEFF);
154                 break;
155         case MST_PCMCIA0:
156                 s->pcmcia0 = value;
157                 break;
158         case MST_PCMCIA1:
159                 s->pcmcia1 = value;
160                 break;
161         default:
162                 printf("Mainstone - mst_fpga_writeb: Bad register offset "
163                         REG_FMT " \n", addr);
164         }
165 }
166
167 static CPUReadMemoryFunc *mst_fpga_readfn[] = {
168         mst_fpga_readb,
169         mst_fpga_readb,
170         mst_fpga_readb,
171 };
172 static CPUWriteMemoryFunc *mst_fpga_writefn[] = {
173         mst_fpga_writeb,
174         mst_fpga_writeb,
175         mst_fpga_writeb,
176 };
177
178 static void
179 mst_fpga_save(QEMUFile *f, void *opaque)
180 {
181         struct mst_irq_state *s = (mst_irq_state *) opaque;
182
183         qemu_put_be32s(f, &s->prev_level);
184         qemu_put_be32s(f, &s->leddat1);
185         qemu_put_be32s(f, &s->leddat2);
186         qemu_put_be32s(f, &s->ledctrl);
187         qemu_put_be32s(f, &s->gpswr);
188         qemu_put_be32s(f, &s->mscwr1);
189         qemu_put_be32s(f, &s->mscwr2);
190         qemu_put_be32s(f, &s->mscwr3);
191         qemu_put_be32s(f, &s->mscrd);
192         qemu_put_be32s(f, &s->intmskena);
193         qemu_put_be32s(f, &s->intsetclr);
194         qemu_put_be32s(f, &s->pcmcia0);
195         qemu_put_be32s(f, &s->pcmcia1);
196 }
197
198 static int
199 mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
200 {
201         mst_irq_state *s = (mst_irq_state *) opaque;
202
203         qemu_get_be32s(f, &s->prev_level);
204         qemu_get_be32s(f, &s->leddat1);
205         qemu_get_be32s(f, &s->leddat2);
206         qemu_get_be32s(f, &s->ledctrl);
207         qemu_get_be32s(f, &s->gpswr);
208         qemu_get_be32s(f, &s->mscwr1);
209         qemu_get_be32s(f, &s->mscwr2);
210         qemu_get_be32s(f, &s->mscwr3);
211         qemu_get_be32s(f, &s->mscrd);
212         qemu_get_be32s(f, &s->intmskena);
213         qemu_get_be32s(f, &s->intsetclr);
214         qemu_get_be32s(f, &s->pcmcia0);
215         qemu_get_be32s(f, &s->pcmcia1);
216         return 0;
217 }
218
219 qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
220 {
221         mst_irq_state *s;
222         int iomemtype;
223         qemu_irq *qi;
224
225         s = (mst_irq_state  *)
226                 qemu_mallocz(sizeof(mst_irq_state));
227
228         s->parent = &cpu->pic[irq];
229
230         /* alloc the external 16 irqs */
231         qi  = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
232         s->pins = qi;
233
234         iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,
235                 mst_fpga_writefn, s);
236         cpu_register_physical_memory(base, 0x00100000, iomemtype);
237         register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
238         return qi;
239 }