]> git.proxmox.com Git - mirror_qemu.git/blame - hw/mainstone.c
Name the magic constants, wrap long lines
[mirror_qemu.git] / hw / mainstone.c
CommitLineData
ef056e43
AZ
1/*
2 * PXA270-based Intel Mainstone platforms.
3 *
4 * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
5 * <akuster@mvista.com>
6 *
7 * Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
8 *
9 * This code is licensed under the GNU GPL v2.
10 */
11#include "hw.h"
12#include "pxa.h"
13#include "arm-misc.h"
ef056e43
AZ
14#include "net.h"
15#include "devices.h"
16#include "boards.h"
17
18#define MST_ETH_PHYS 0x10000300
19#define MST_FPGA_PHYS 0x08000000
20
21/* Mainstone FPGA for extern irqs */
22#define FPGA_GPIO_PIN 0
23#define MST_NUM_IRQS 16
24#define MST_BASE MST_FPGA_PHYS
25#define MST_LEDDAT1 0x10
26#define MST_LEDDAT2 0x14
27#define MST_LEDCTRL 0x40
28#define MST_GPSWR 0x60
29#define MST_MSCWR1 0x80
30#define MST_MSCWR2 0x84
31#define MST_MSCWR3 0x88
32#define MST_MSCRD 0x90
33#define MST_INTMSKENA 0xc0
34#define MST_INTSETCLR 0xd0
35#define MST_PCMCIA0 0xe0
36#define MST_PCMCIA1 0xe4
37
38/* IRQ definitions */
39#define ETHERNET_IRQ 3
40
41typedef struct mst_irq_state {
42 target_phys_addr_t target_base;
43 qemu_irq *parent;
44 qemu_irq *pins;
45
46 uint32_t prev_level;
47 uint32_t leddat1;
48 uint32_t leddat2;
49 uint32_t ledctrl;
50 uint32_t gpswr;
51 uint32_t mscwr1;
52 uint32_t mscwr2;
53 uint32_t mscwr3;
54 uint32_t mscrd;
55 uint32_t intmskena;
56 uint32_t intsetclr;
57 uint32_t pcmcia0;
58 uint32_t pcmcia1;
59} mst_irq_state;
60
61static void
62mst_fpga_update_gpio(mst_irq_state *s)
63{
64 uint32_t level, diff;
65 int bit;
66 level = s->prev_level ^ s->intsetclr;
67
68 for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
69 bit = ffs(diff) - 1;
70 qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
71 }
72 s->prev_level = level;
73}
74
75static void
76mst_fpga_set_irq(void *opaque, int irq, int level)
77{
78 mst_irq_state *s = (mst_irq_state *)opaque;
79
80 if (level)
81 s->prev_level |= 1u << irq;
82 else
83 s->prev_level &= ~(1u << irq);
84
85 if(s->intmskena & (1u << irq)) {
86 s->intsetclr = 1u << irq;
87 qemu_set_irq(s->parent[0], level);
88 }
89}
90
91static uint32_t
92mst_fpga_readb(void *opaque, target_phys_addr_t addr)
93{
94 mst_irq_state *s = (mst_irq_state *) opaque;
95 addr -= s->target_base;
96
97 switch (addr) {
98 case MST_LEDDAT1:
99 return s->leddat1;
100 case MST_LEDDAT2:
101 return s->leddat2;
102 case MST_LEDCTRL:
103 return s->ledctrl;
104 case MST_GPSWR:
105 return s->gpswr;
106 case MST_MSCWR1:
107 return s->mscwr1;
108 case MST_MSCWR2:
109 return s->mscwr2;
110 case MST_MSCWR3:
111 return s->mscwr3;
112 case MST_MSCRD:
113 return s->mscrd;
114 case MST_INTMSKENA:
115 return s->intmskena;
116 case MST_INTSETCLR:
117 return s->intsetclr;
118 case MST_PCMCIA0:
119 return s->pcmcia0;
120 case MST_PCMCIA1:
121 return s->pcmcia1;
122 default:
123 printf("Mainstone - mst_fpga_readb: Bad register offset "
124 REG_FMT " \n", addr);
125 }
126 return 0;
127}
128
129static void
130mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
131{
132 mst_irq_state *s = (mst_irq_state *) opaque;
133 addr -= s->target_base;
134 value &= 0xffffffff;
135
136 switch (addr) {
137 case MST_LEDDAT1:
138 s->leddat1 = value;
139 break;
140 case MST_LEDDAT2:
141 s->leddat2 = value;
142 break;
143 case MST_LEDCTRL:
144 s->ledctrl = value;
145 break;
146 case MST_GPSWR:
147 s->gpswr = value;
148 break;
149 case MST_MSCWR1:
150 s->mscwr1 = value;
151 break;
152 case MST_MSCWR2:
153 s->mscwr2 = value;
154 break;
155 case MST_MSCWR3:
156 s->mscwr3 = value;
157 break;
158 case MST_MSCRD:
159 s->mscrd = value;
160 break;
161 case MST_INTMSKENA: /* Mask interupt */
162 s->intmskena = (value & 0xFEEFF);
163 mst_fpga_update_gpio(s);
164 break;
165 case MST_INTSETCLR: /* clear or set interrupt */
166 s->intsetclr = (value & 0xFEEFF);
167 break;
168 case MST_PCMCIA0:
169 s->pcmcia0 = value;
170 break;
171 case MST_PCMCIA1:
172 s->pcmcia1 = value;
173 break;
174 default:
175 printf("Mainstone - mst_fpga_writeb: Bad register offset "
176 REG_FMT " \n", addr);
177 }
178}
179
180CPUReadMemoryFunc *mst_fpga_readfn[] = {
181 mst_fpga_readb,
182 mst_fpga_readb,
183 mst_fpga_readb,
184};
185CPUWriteMemoryFunc *mst_fpga_writefn[] = {
186 mst_fpga_writeb,
187 mst_fpga_writeb,
188 mst_fpga_writeb,
189};
190
191static void
192mst_fpga_save(QEMUFile *f, void *opaque)
193{
194 struct mst_irq_state *s = (mst_irq_state *) opaque;
195
196 qemu_put_be32s(f, &s->prev_level);
197 qemu_put_be32s(f, &s->leddat1);
198 qemu_put_be32s(f, &s->leddat2);
199 qemu_put_be32s(f, &s->ledctrl);
200 qemu_put_be32s(f, &s->gpswr);
201 qemu_put_be32s(f, &s->mscwr1);
202 qemu_put_be32s(f, &s->mscwr2);
203 qemu_put_be32s(f, &s->mscwr3);
204 qemu_put_be32s(f, &s->mscrd);
205 qemu_put_be32s(f, &s->intmskena);
206 qemu_put_be32s(f, &s->intsetclr);
207 qemu_put_be32s(f, &s->pcmcia0);
208 qemu_put_be32s(f, &s->pcmcia1);
209}
210
211static int
212mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
213{
214 mst_irq_state *s = (mst_irq_state *) opaque;
215
216 qemu_get_be32s(f, &s->prev_level);
217 qemu_get_be32s(f, &s->leddat1);
218 qemu_get_be32s(f, &s->leddat2);
219 qemu_get_be32s(f, &s->ledctrl);
220 qemu_get_be32s(f, &s->gpswr);
221 qemu_get_be32s(f, &s->mscwr1);
222 qemu_get_be32s(f, &s->mscwr2);
223 qemu_get_be32s(f, &s->mscwr3);
224 qemu_get_be32s(f, &s->mscrd);
225 qemu_get_be32s(f, &s->intmskena);
226 qemu_get_be32s(f, &s->intsetclr);
227 qemu_get_be32s(f, &s->pcmcia0);
228 qemu_get_be32s(f, &s->pcmcia1);
229 return 0;
230}
231
232static qemu_irq
233*mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq)
234{
235 mst_irq_state *s;
236 int iomemtype;
237 qemu_irq *qi;
238
239 s = (mst_irq_state *) qemu_mallocz(sizeof(mst_irq_state));
240
241 if (!s)
242 return NULL;
243 s->target_base = base;
244 s->parent = &cpu->pic[irq];
245
246 /* alloc the external 16 irqs */
247 qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
248 s->pins = qi;
249
250 iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,
251 mst_fpga_writefn, s);
252 cpu_register_physical_memory(MST_BASE, 0x00100000, iomemtype);
253 register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
254 return qi;
255}
256
257enum mainstone_model_e { mainstone };
258
259static void mainstone_common_init(int ram_size, int vga_ram_size,
260 DisplayState *ds, const char *kernel_filename,
261 const char *kernel_cmdline, const char *initrd_filename,
262 const char *cpu_model, enum mainstone_model_e model, int arm_id)
263{
264 uint32_t mainstone_ram = 0x04000000;
265 uint32_t mainstone_rom = 0x00800000;
266 struct pxa2xx_state_s *cpu;
267 qemu_irq *mst_irq;
268
269 if (!cpu_model)
270 cpu_model = "pxa270-c5";
271
272 /* Setup CPU & memory */
273 if (ram_size < mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE) {
274 fprintf(stderr, "This platform requires %i bytes of memory\n",
275 mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE);
276 exit(1);
277 }
278
279 cpu = pxa270_init(mainstone_ram, ds, cpu_model);
280 cpu_register_physical_memory(0, mainstone_rom,
281 qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM);
282
283 /* Setup initial (reset) machine state */
284 cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
285
286 mst_irq = mst_irq_init(cpu, MST_BASE, PXA2XX_PIC_GPIO_0);
287 smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
288
289 arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline,
290 initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
291}
292
293static void mainstone_init(int ram_size, int vga_ram_size,
294 const char *boot_device, DisplayState *ds,
295 const char *kernel_filename, const char *kernel_cmdline,
296 const char *initrd_filename, const char *cpu_model)
297{
298 mainstone_common_init(ram_size, vga_ram_size, ds, kernel_filename,
299 kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196);
300}
301
302QEMUMachine mainstone2_machine = {
303 "mainstone",
304 "Mainstone II (PXA27x)",
305 mainstone_init,
306};