sync with tizen_2.2
[sdk/emulator/qemu.git] / hw / slavio_misc.c
1 /*
2  * QEMU Sparc SLAVIO aux io port emulation
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "sysemu.h"
26 #include "sysbus.h"
27 #include "trace.h"
28
29 /*
30  * This is the auxio port, chip control and system control part of
31  * chip STP2001 (Slave I/O), also produced as NCR89C105. See
32  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
33  *
34  * This also includes the PMC CPU idle controller.
35  */
36
37 typedef struct MiscState {
38     SysBusDevice busdev;
39     MemoryRegion cfg_iomem;
40     MemoryRegion diag_iomem;
41     MemoryRegion mdm_iomem;
42     MemoryRegion led_iomem;
43     MemoryRegion sysctrl_iomem;
44     MemoryRegion aux1_iomem;
45     MemoryRegion aux2_iomem;
46     qemu_irq irq;
47     qemu_irq fdc_tc;
48     uint32_t dummy;
49     uint8_t config;
50     uint8_t aux1, aux2;
51     uint8_t diag, mctrl;
52     uint8_t sysctrl;
53     uint16_t leds;
54 } MiscState;
55
56 typedef struct APCState {
57     SysBusDevice busdev;
58     MemoryRegion iomem;
59     qemu_irq cpu_halt;
60 } APCState;
61
62 #define MISC_SIZE 1
63 #define SYSCTRL_SIZE 4
64
65 #define AUX1_TC        0x02
66
67 #define AUX2_PWROFF    0x01
68 #define AUX2_PWRINTCLR 0x02
69 #define AUX2_PWRFAIL   0x20
70
71 #define CFG_PWRINTEN   0x08
72
73 #define SYS_RESET      0x01
74 #define SYS_RESETSTAT  0x02
75
76 static void slavio_misc_update_irq(void *opaque)
77 {
78     MiscState *s = opaque;
79
80     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
81         trace_slavio_misc_update_irq_raise();
82         qemu_irq_raise(s->irq);
83     } else {
84         trace_slavio_misc_update_irq_lower();
85         qemu_irq_lower(s->irq);
86     }
87 }
88
89 static void slavio_misc_reset(DeviceState *d)
90 {
91     MiscState *s = container_of(d, MiscState, busdev.qdev);
92
93     // Diagnostic and system control registers not cleared in reset
94     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
95 }
96
97 static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
98 {
99     MiscState *s = opaque;
100
101     trace_slavio_set_power_fail(power_failing, s->config);
102     if (power_failing && (s->config & CFG_PWRINTEN)) {
103         s->aux2 |= AUX2_PWRFAIL;
104     } else {
105         s->aux2 &= ~AUX2_PWRFAIL;
106     }
107     slavio_misc_update_irq(s);
108 }
109
110 static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
111                                   uint64_t val, unsigned size)
112 {
113     MiscState *s = opaque;
114
115     trace_slavio_cfg_mem_writeb(val & 0xff);
116     s->config = val & 0xff;
117     slavio_misc_update_irq(s);
118 }
119
120 static uint64_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr,
121                                      unsigned size)
122 {
123     MiscState *s = opaque;
124     uint32_t ret = 0;
125
126     ret = s->config;
127     trace_slavio_cfg_mem_readb(ret);
128     return ret;
129 }
130
131 static const MemoryRegionOps slavio_cfg_mem_ops = {
132     .read = slavio_cfg_mem_readb,
133     .write = slavio_cfg_mem_writeb,
134     .endianness = DEVICE_NATIVE_ENDIAN,
135     .valid = {
136         .min_access_size = 1,
137         .max_access_size = 1,
138     },
139 };
140
141 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
142                                    uint64_t val, unsigned size)
143 {
144     MiscState *s = opaque;
145
146     trace_slavio_diag_mem_writeb(val & 0xff);
147     s->diag = val & 0xff;
148 }
149
150 static uint64_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr,
151                                       unsigned size)
152 {
153     MiscState *s = opaque;
154     uint32_t ret = 0;
155
156     ret = s->diag;
157     trace_slavio_diag_mem_readb(ret);
158     return ret;
159 }
160
161 static const MemoryRegionOps slavio_diag_mem_ops = {
162     .read = slavio_diag_mem_readb,
163     .write = slavio_diag_mem_writeb,
164     .endianness = DEVICE_NATIVE_ENDIAN,
165     .valid = {
166         .min_access_size = 1,
167         .max_access_size = 1,
168     },
169 };
170
171 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
172                                   uint64_t val, unsigned size)
173 {
174     MiscState *s = opaque;
175
176     trace_slavio_mdm_mem_writeb(val & 0xff);
177     s->mctrl = val & 0xff;
178 }
179
180 static uint64_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr,
181                                      unsigned size)
182 {
183     MiscState *s = opaque;
184     uint32_t ret = 0;
185
186     ret = s->mctrl;
187     trace_slavio_mdm_mem_readb(ret);
188     return ret;
189 }
190
191 static const MemoryRegionOps slavio_mdm_mem_ops = {
192     .read = slavio_mdm_mem_readb,
193     .write = slavio_mdm_mem_writeb,
194     .endianness = DEVICE_NATIVE_ENDIAN,
195     .valid = {
196         .min_access_size = 1,
197         .max_access_size = 1,
198     },
199 };
200
201 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
202                                    uint64_t val, unsigned size)
203 {
204     MiscState *s = opaque;
205
206     trace_slavio_aux1_mem_writeb(val & 0xff);
207     if (val & AUX1_TC) {
208         // Send a pulse to floppy terminal count line
209         if (s->fdc_tc) {
210             qemu_irq_raise(s->fdc_tc);
211             qemu_irq_lower(s->fdc_tc);
212         }
213         val &= ~AUX1_TC;
214     }
215     s->aux1 = val & 0xff;
216 }
217
218 static uint64_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr,
219                                       unsigned size)
220 {
221     MiscState *s = opaque;
222     uint32_t ret = 0;
223
224     ret = s->aux1;
225     trace_slavio_aux1_mem_readb(ret);
226     return ret;
227 }
228
229 static const MemoryRegionOps slavio_aux1_mem_ops = {
230     .read = slavio_aux1_mem_readb,
231     .write = slavio_aux1_mem_writeb,
232     .endianness = DEVICE_NATIVE_ENDIAN,
233     .valid = {
234         .min_access_size = 1,
235         .max_access_size = 1,
236     },
237 };
238
239 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
240                                    uint64_t val, unsigned size)
241 {
242     MiscState *s = opaque;
243
244     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
245     trace_slavio_aux2_mem_writeb(val & 0xff);
246     val |= s->aux2 & AUX2_PWRFAIL;
247     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
248         val &= AUX2_PWROFF;
249     s->aux2 = val;
250     if (val & AUX2_PWROFF)
251         qemu_system_shutdown_request();
252     slavio_misc_update_irq(s);
253 }
254
255 static uint64_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr,
256                                       unsigned size)
257 {
258     MiscState *s = opaque;
259     uint32_t ret = 0;
260
261     ret = s->aux2;
262     trace_slavio_aux2_mem_readb(ret);
263     return ret;
264 }
265
266 static const MemoryRegionOps slavio_aux2_mem_ops = {
267     .read = slavio_aux2_mem_readb,
268     .write = slavio_aux2_mem_writeb,
269     .endianness = DEVICE_NATIVE_ENDIAN,
270     .valid = {
271         .min_access_size = 1,
272         .max_access_size = 1,
273     },
274 };
275
276 static void apc_mem_writeb(void *opaque, target_phys_addr_t addr,
277                            uint64_t val, unsigned size)
278 {
279     APCState *s = opaque;
280
281     trace_apc_mem_writeb(val & 0xff);
282     qemu_irq_raise(s->cpu_halt);
283 }
284
285 static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr,
286                               unsigned size)
287 {
288     uint32_t ret = 0;
289
290     trace_apc_mem_readb(ret);
291     return ret;
292 }
293
294 static const MemoryRegionOps apc_mem_ops = {
295     .read = apc_mem_readb,
296     .write = apc_mem_writeb,
297     .endianness = DEVICE_NATIVE_ENDIAN,
298     .valid = {
299         .min_access_size = 1,
300         .max_access_size = 1,
301     }
302 };
303
304 static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr,
305                                          unsigned size)
306 {
307     MiscState *s = opaque;
308     uint32_t ret = 0;
309
310     switch (addr) {
311     case 0:
312         ret = s->sysctrl;
313         break;
314     default:
315         break;
316     }
317     trace_slavio_sysctrl_mem_readl(ret);
318     return ret;
319 }
320
321 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
322                                       uint64_t val, unsigned size)
323 {
324     MiscState *s = opaque;
325
326     trace_slavio_sysctrl_mem_writel(val);
327     switch (addr) {
328     case 0:
329         if (val & SYS_RESET) {
330             s->sysctrl = SYS_RESETSTAT;
331             qemu_system_reset_request();
332         }
333         break;
334     default:
335         break;
336     }
337 }
338
339 static const MemoryRegionOps slavio_sysctrl_mem_ops = {
340     .read = slavio_sysctrl_mem_readl,
341     .write = slavio_sysctrl_mem_writel,
342     .endianness = DEVICE_NATIVE_ENDIAN,
343     .valid = {
344         .min_access_size = 4,
345         .max_access_size = 4,
346     },
347 };
348
349 static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr,
350                                      unsigned size)
351 {
352     MiscState *s = opaque;
353     uint32_t ret = 0;
354
355     switch (addr) {
356     case 0:
357         ret = s->leds;
358         break;
359     default:
360         break;
361     }
362     trace_slavio_led_mem_readw(ret);
363     return ret;
364 }
365
366 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
367                                   uint64_t val, unsigned size)
368 {
369     MiscState *s = opaque;
370
371     trace_slavio_led_mem_readw(val & 0xffff);
372     switch (addr) {
373     case 0:
374         s->leds = val;
375         break;
376     default:
377         break;
378     }
379 }
380
381 static const MemoryRegionOps slavio_led_mem_ops = {
382     .read = slavio_led_mem_readw,
383     .write = slavio_led_mem_writew,
384     .endianness = DEVICE_NATIVE_ENDIAN,
385     .valid = {
386         .min_access_size = 2,
387         .max_access_size = 2,
388     },
389 };
390
391 static const VMStateDescription vmstate_misc = {
392     .name ="slavio_misc",
393     .version_id = 1,
394     .minimum_version_id = 1,
395     .minimum_version_id_old = 1,
396     .fields      = (VMStateField []) {
397         VMSTATE_UINT32(dummy, MiscState),
398         VMSTATE_UINT8(config, MiscState),
399         VMSTATE_UINT8(aux1, MiscState),
400         VMSTATE_UINT8(aux2, MiscState),
401         VMSTATE_UINT8(diag, MiscState),
402         VMSTATE_UINT8(mctrl, MiscState),
403         VMSTATE_UINT8(sysctrl, MiscState),
404         VMSTATE_END_OF_LIST()
405     }
406 };
407
408 static int apc_init1(SysBusDevice *dev)
409 {
410     APCState *s = FROM_SYSBUS(APCState, dev);
411
412     sysbus_init_irq(dev, &s->cpu_halt);
413
414     /* Power management (APC) XXX: not a Slavio device */
415     memory_region_init_io(&s->iomem, &apc_mem_ops, s,
416                           "apc", MISC_SIZE);
417     sysbus_init_mmio(dev, &s->iomem);
418     return 0;
419 }
420
421 static int slavio_misc_init1(SysBusDevice *dev)
422 {
423     MiscState *s = FROM_SYSBUS(MiscState, dev);
424
425     sysbus_init_irq(dev, &s->irq);
426     sysbus_init_irq(dev, &s->fdc_tc);
427
428     /* 8 bit registers */
429     /* Slavio control */
430     memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
431                           "configuration", MISC_SIZE);
432     sysbus_init_mmio(dev, &s->cfg_iomem);
433
434     /* Diagnostics */
435     memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
436                           "diagnostic", MISC_SIZE);
437     sysbus_init_mmio(dev, &s->diag_iomem);
438
439     /* Modem control */
440     memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
441                           "modem", MISC_SIZE);
442     sysbus_init_mmio(dev, &s->mdm_iomem);
443
444     /* 16 bit registers */
445     /* ss600mp diag LEDs */
446     memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
447                           "leds", MISC_SIZE);
448     sysbus_init_mmio(dev, &s->led_iomem);
449
450     /* 32 bit registers */
451     /* System control */
452     memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
453                           "system-control", MISC_SIZE);
454     sysbus_init_mmio(dev, &s->sysctrl_iomem);
455
456     /* AUX 1 (Misc System Functions) */
457     memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
458                           "misc-system-functions", MISC_SIZE);
459     sysbus_init_mmio(dev, &s->aux1_iomem);
460
461     /* AUX 2 (Software Powerdown Control) */
462     memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
463                           "software-powerdown-control", MISC_SIZE);
464     sysbus_init_mmio(dev, &s->aux2_iomem);
465
466     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
467
468     return 0;
469 }
470
471 static void slavio_misc_class_init(ObjectClass *klass, void *data)
472 {
473     DeviceClass *dc = DEVICE_CLASS(klass);
474     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
475
476     k->init = slavio_misc_init1;
477     dc->reset = slavio_misc_reset;
478     dc->vmsd = &vmstate_misc;
479 }
480
481 static TypeInfo slavio_misc_info = {
482     .name          = "slavio_misc",
483     .parent        = TYPE_SYS_BUS_DEVICE,
484     .instance_size = sizeof(MiscState),
485     .class_init    = slavio_misc_class_init,
486 };
487
488 static void apc_class_init(ObjectClass *klass, void *data)
489 {
490     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
491
492     k->init = apc_init1;
493 }
494
495 static TypeInfo apc_info = {
496     .name          = "apc",
497     .parent        = TYPE_SYS_BUS_DEVICE,
498     .instance_size = sizeof(MiscState),
499     .class_init    = apc_class_init,
500 };
501
502 static void slavio_misc_register_types(void)
503 {
504     type_register_static(&slavio_misc_info);
505     type_register_static(&apc_info);
506 }
507
508 type_init(slavio_misc_register_types)