Add qemu 2.4.0
[kvmfornfv.git] / qemu / hw / gpio / puv3_gpio.c
1 /*
2  * GPIO device simulation in PKUnity SoC
3  *
4  * Copyright (C) 2010-2012 Guan Xuetao
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation, or any later version.
9  * See the COPYING file in the top-level directory.
10  */
11 #include "hw/hw.h"
12 #include "hw/sysbus.h"
13
14 #undef DEBUG_PUV3
15 #include "hw/unicore32/puv3.h"
16
17 #define TYPE_PUV3_GPIO "puv3_gpio"
18 #define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO)
19
20 typedef struct PUV3GPIOState {
21     SysBusDevice parent_obj;
22
23     MemoryRegion iomem;
24     qemu_irq irq[9];
25
26     uint32_t reg_GPLR;
27     uint32_t reg_GPDR;
28     uint32_t reg_GPIR;
29 } PUV3GPIOState;
30
31 static uint64_t puv3_gpio_read(void *opaque, hwaddr offset,
32         unsigned size)
33 {
34     PUV3GPIOState *s = opaque;
35     uint32_t ret = 0;
36
37     switch (offset) {
38     case 0x00:
39         ret = s->reg_GPLR;
40         break;
41     case 0x04:
42         ret = s->reg_GPDR;
43         break;
44     case 0x20:
45         ret = s->reg_GPIR;
46         break;
47     default:
48         DPRINTF("Bad offset 0x%x\n", offset);
49     }
50     DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
51
52     return ret;
53 }
54
55 static void puv3_gpio_write(void *opaque, hwaddr offset,
56         uint64_t value, unsigned size)
57 {
58     PUV3GPIOState *s = opaque;
59
60     DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
61     switch (offset) {
62     case 0x04:
63         s->reg_GPDR = value;
64         break;
65     case 0x08:
66         if (s->reg_GPDR & value) {
67             s->reg_GPLR |= value;
68         } else {
69             DPRINTF("Write gpio input port error!");
70         }
71         break;
72     case 0x0c:
73         if (s->reg_GPDR & value) {
74             s->reg_GPLR &= ~value;
75         } else {
76             DPRINTF("Write gpio input port error!");
77         }
78         break;
79     case 0x10: /* GRER */
80     case 0x14: /* GFER */
81     case 0x18: /* GEDR */
82         break;
83     case 0x20: /* GPIR */
84         s->reg_GPIR = value;
85         break;
86     default:
87         DPRINTF("Bad offset 0x%x\n", offset);
88     }
89 }
90
91 static const MemoryRegionOps puv3_gpio_ops = {
92     .read = puv3_gpio_read,
93     .write = puv3_gpio_write,
94     .impl = {
95         .min_access_size = 4,
96         .max_access_size = 4,
97     },
98     .endianness = DEVICE_NATIVE_ENDIAN,
99 };
100
101 static int puv3_gpio_init(SysBusDevice *dev)
102 {
103     PUV3GPIOState *s = PUV3_GPIO(dev);
104
105     s->reg_GPLR = 0;
106     s->reg_GPDR = 0;
107
108     /* FIXME: these irqs not handled yet */
109     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW0]);
110     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW1]);
111     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW2]);
112     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW3]);
113     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW4]);
114     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW5]);
115     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW6]);
116     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]);
117     sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]);
118
119     memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio",
120             PUV3_REGS_OFFSET);
121     sysbus_init_mmio(dev, &s->iomem);
122
123     return 0;
124 }
125
126 static void puv3_gpio_class_init(ObjectClass *klass, void *data)
127 {
128     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
129
130     sdc->init = puv3_gpio_init;
131 }
132
133 static const TypeInfo puv3_gpio_info = {
134     .name = TYPE_PUV3_GPIO,
135     .parent = TYPE_SYS_BUS_DEVICE,
136     .instance_size = sizeof(PUV3GPIOState),
137     .class_init = puv3_gpio_class_init,
138 };
139
140 static void puv3_gpio_register_type(void)
141 {
142     type_register_static(&puv3_gpio_info);
143 }
144
145 type_init(puv3_gpio_register_type)