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