Update GitHub action for new Meson based build
[qemu/ar7.git] / hw / arm / s3c24xx_gpio.c
blobbefc68edd74695be5057975539612811042314cf
1 /* hw/s3c24xx_gpio.c
3 * Samsung S3C24XX GPIO emulation (mostly for E-INT)
5 * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
7 * Copyright 2010, 2013, 2020 Stefan Weil
9 * This file is under the terms of the GNU General Public License Version 2.
12 #include "qemu/osdep.h"
13 #include "cpu.h"
14 #include "hw/hw.h"
15 #include "hw/irq.h" /* qemu_set_irq */
16 #include "hw/qdev-properties.h" /* DEFINE_PROP_END_OF_LIST */
17 #include "hw/sysbus.h"
18 #include "migration/vmstate.h" /* VMStateDescription */
19 #include "s3c24xx.h"
21 #define S3C_GPIO_GPECON 0x40
22 #define S3C_GPIO_GPEDAT 0x44
23 #define S3C_GPIO_GPEUP 0x48
25 #define S3C_GPIO_EINT_MASK 0xA4
26 #define S3C_GPIO_EINT_PEND 0xA8
27 #define S3C_GPIO_GSTATUS0 0xAC
28 #define S3C_GPIO_GSTATUS1 0xB0
29 #define S3C_GPIO_GSTATUS2 0xB4
30 #define S3C_GPIO_GSTATUS3 0xB8
31 #define S3C_GPIO_GSTATUS4 0xBC
33 #define GPRN(r) (r>>2)
34 #define GPR(P) s->gpio_reg[P>>2]
36 #define S3C_GPIO_MAX 0x43
38 /* GPIO controller state */
40 #define TYPE_S3C24XX_GPIO "s3c24xx_gpio"
41 #define S3C24XX_GPIO(obj) \
42 OBJECT_CHECK(S3C24xxGpioState, (obj), TYPE_S3C24XX_GPIO)
44 struct S3C24xxGpioState {
45 SysBusDevice busdev;
46 MemoryRegion mmio;
48 uint32_t gpio_reg[S3C_GPIO_MAX];
50 qemu_irq *eirqs; /* gpio external interrupts */
52 qemu_irq irqs[6]; /* cpu irqs to cascade */
55 static void
56 s3c24xx_gpio_propagate_eint(S3C24xxGpioState *s)
58 uint32_t ints, i;
60 ints = GPR(S3C_GPIO_EINT_PEND) & ~GPR(S3C_GPIO_EINT_MASK);
62 /* EINT0 - EINT3 are INT0 - INT3 */
63 for (i=0; i < 4; ++i) {
64 qemu_set_irq(s->irqs[i], (ints & (1<<i))?1:0);
67 /* EINT4 - EINT7 are INT4 */
68 qemu_set_irq(s->irqs[4], (ints & 0xf0)?1:0);
70 /* EINT8 - EINT23 are INT5 */
71 qemu_set_irq(s->irqs[5], (ints & 0x00ffff00)?1:0);
74 static uint32_t
75 gpio_con_to_mask(uint32_t con)
77 uint32_t mask = 0x0;
78 int bit;
80 for (bit = 0; bit < 16; bit++) {
81 if (((con >> (bit * 2)) & 0x3) == 0x01) {
82 mask |= 1 << bit;
86 return mask;
89 static void
90 s3c24xx_gpio_write_f(void *opaque, hwaddr addr_, uint64_t value,
91 unsigned size)
93 S3C24xxGpioState *s = opaque;
94 uint32_t addr = (addr_ >> 2);
96 assert(addr < S3C_GPIO_MAX);
98 assert(!(addr > 0x3f));
99 addr &= 0x3f;
101 if (addr == (S3C_GPIO_EINT_MASK>>2)) {
102 value &= ~0xf; /* cannot mask EINT0-EINT3 */
105 if (addr == (S3C_GPIO_EINT_PEND>>2)) {
106 s->gpio_reg[addr] &= ~value;
107 } else {
108 if (addr < (0x80/4) && (addr_ & 0xf) == 0x04) {
109 uint32_t mask = gpio_con_to_mask(s->gpio_reg[addr - 1]);
111 value &= mask;
113 s->gpio_reg[addr] &= ~mask;
114 s->gpio_reg[addr] |= value;
115 } else {
116 s->gpio_reg[addr] = value;
120 if ((addr == (S3C_GPIO_EINT_MASK)>>2) ||
121 (addr == (S3C_GPIO_EINT_PEND)>>2)) {
122 /* A write to the EINT regs leads us to determine the interrupts to
123 * propagate
125 s3c24xx_gpio_propagate_eint(s);
129 static uint64_t
130 s3c24xx_gpio_read_f(void *opaque, hwaddr addr_, unsigned size)
132 S3C24xxGpioState *s = opaque;
133 uint32_t addr = (addr_ >> 2);
134 uint32_t ret;
136 assert(addr < S3C_GPIO_MAX);
138 assert(!(addr > 0x3f));
139 addr &= 0x3f;
141 ret = s->gpio_reg[addr];
143 if (addr == GPRN(S3C_GPIO_GPEDAT)) {
144 /* IIC pins are special function pins on GPE14 and GPE15. If GPE is is
145 * in input mode make the IIC lines appear to be pulled high. This is
146 * neccissary because OS i2c drivers use this to ensure the I2C bus is
147 * clear.
149 if ((GPR(S3C_GPIO_GPECON) & (3<<28)) == 0) {
150 ret |= 1 << 14;
153 if ((GPR(S3C_GPIO_GPECON) & (3<<30)) == 0) {
154 ret |= 1 << 15;
158 return ret;
161 static const MemoryRegionOps s3c24xx_gpio_ops = {
162 .read = s3c24xx_gpio_read_f,
163 .write = s3c24xx_gpio_write_f,
164 .endianness = DEVICE_NATIVE_ENDIAN,
165 .valid = {
166 .min_access_size = 1,
167 .max_access_size = 4
171 static void
172 s3c24xx_gpio_irq_handler(void *opaque, int n, int level)
174 S3C24xxGpioState *s = opaque;
176 if (level) {
177 GPR(S3C_GPIO_EINT_PEND) |= (1<<n);
180 s3c24xx_gpio_propagate_eint(s);
183 static void s3c24xx_gpio_realize(DeviceState *dev, Error **errp)
185 S3C24xxGpioState *s = S3C24XX_GPIO(dev);
186 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
188 //~ qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
189 //~ sysbus_init_irq(dev, &s->parent_irq);
190 memory_region_init_io(&s->mmio, OBJECT(s), &s3c24xx_gpio_ops, s,
191 "s3c24xx-gpio", S3C_GPIO_MAX * 4);
192 sysbus_init_mmio(sbd, &s->mmio);
193 #if 0
194 TODO: i/o starting at base_addr, S3C_GPIO_MAX * 4 bytes.
195 #endif
197 /* Set non zero default values. */
198 GPR(0x00) = 0x7fffff;
199 GPR(0x34) = 0xfefc;
200 GPR(0x38) = 0xf000;
201 GPR(0x68) = 0xf800;
202 GPR(0x80) = 0x10330;
203 GPR(S3C_GPIO_EINT_MASK) = 0xfffff0;
204 //~ GPR(S3C_GPIO_GSTATUS1) = cpu_id;
205 GPR(S3C_GPIO_GSTATUS2) = 1;
206 GPR(S3C_GPIO_GSTATUS3) = 0;
207 GPR(S3C_GPIO_GSTATUS4) = 0;
210 S3C24xxGpioState *
211 s3c24xx_gpio_init(S3CState *soc, hwaddr base_addr, uint32_t cpu_id)
213 /* Samsung S3C24XX GPIO
215 * The primary operation here is the ID register and IRQs
217 int i;
219 S3C24xxGpioState *s = g_new0(S3C24xxGpioState, 1);
221 /* TODO: Diese Funktion ist veraltet und soll ersetzt werden, s.o. */
223 /* Set non zero default values. */
224 GPR(0x00) = 0x7fffff;
225 GPR(0x34) = 0xfefc;
226 GPR(0x38) = 0xf000;
227 GPR(0x68) = 0xf800;
228 GPR(0x80) = 0x10330;
229 GPR(S3C_GPIO_EINT_MASK) = 0xfffff0;
230 GPR(S3C_GPIO_GSTATUS1) = cpu_id;
231 GPR(S3C_GPIO_GSTATUS2) = 1;
232 GPR(S3C_GPIO_GSTATUS3) = 0;
233 GPR(S3C_GPIO_GSTATUS4) = 0;
235 /* obtain first level IRQs for cascade */
236 for (i = 0; i <= 5; i++) {
237 s->irqs[i] = s3c24xx_get_irq(soc->irq, i);
240 /* EINTs 0-23 -- Only 24, not 48 because EINTs are not level */
241 s->eirqs = qemu_allocate_irqs(s3c24xx_gpio_irq_handler, s, 24);
243 return s;
246 /* get the qemu interrupt from an eirq number */
247 qemu_irq
248 s3c24xx_get_eirq(S3C24xxGpioState *s, unsigned einum)
250 assert(einum < 24);
251 return s->eirqs[einum];
254 static const VMStateDescription s3c24xx_gpio_vmstate = {
255 .name = TYPE_S3C24XX_GPIO,
256 .version_id = 1,
257 .minimum_version_id = 1,
258 .minimum_version_id_old = 1,
259 .fields = (VMStateField[]) {
260 VMSTATE_UINT32_ARRAY(gpio_reg, S3C24xxGpioState, S3C_GPIO_MAX),
261 VMSTATE_END_OF_LIST()
265 static Property s3c24xx_gpio_properties[] = {
266 DEFINE_PROP_END_OF_LIST()
269 static void s3c24xx_gpio_class_init(ObjectClass *klass, void *data)
271 DeviceClass *dc = DEVICE_CLASS(klass);
272 dc->props = s3c24xx_gpio_properties;
273 dc->realize = s3c24xx_gpio_realize;
274 dc->vmsd = &s3c24xx_gpio_vmstate;
277 static const TypeInfo s3c24xx_gpio_info = {
278 .name = TYPE_S3C24XX_GPIO,
279 .parent = TYPE_SYS_BUS_DEVICE,
280 .instance_size = sizeof(S3C24xxGpioState),
281 .class_init = s3c24xx_gpio_class_init
284 static void s3c24xx_register_types(void)
286 type_register_static(&s3c24xx_gpio_info);
289 type_init(s3c24xx_register_types)