xref: /openbmc/qemu/hw/gpio/bcm2838_gpio.c (revision 23c82c1daf30b3ed8d988f3f1d7fbb0557059ac6)
1 /*
2  * Raspberry Pi (BCM2838) GPIO Controller
3  * This implementation is based on bcm2835_gpio (hw/gpio/bcm2835_gpio.c)
4  *
5  * Copyright (c) 2022 Auriga LLC
6  *
7  * Authors:
8  *  Lotosh, Aleksey <aleksey.lotosh@auriga.com>
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qemu/log.h"
15 #include "qemu/module.h"
16 #include "qemu/timer.h"
17 #include "qapi/error.h"
18 #include "hw/sysbus.h"
19 #include "migration/vmstate.h"
20 #include "hw/gpio/bcm2838_gpio.h"
21 
22 #define GPFSEL0   0x00
23 #define GPFSEL1   0x04
24 #define GPFSEL2   0x08
25 #define GPFSEL3   0x0C
26 #define GPFSEL4   0x10
27 #define GPFSEL5   0x14
28 #define GPSET0    0x1C
29 #define GPSET1    0x20
30 #define GPCLR0    0x28
31 #define GPCLR1    0x2C
32 #define GPLEV0    0x34
33 #define GPLEV1    0x38
34 #define GPEDS0    0x40
35 #define GPEDS1    0x44
36 #define GPREN0    0x4C
37 #define GPREN1    0x50
38 #define GPFEN0    0x58
39 #define GPFEN1    0x5C
40 #define GPHEN0    0x64
41 #define GPHEN1    0x68
42 #define GPLEN0    0x70
43 #define GPLEN1    0x74
44 #define GPAREN0   0x7C
45 #define GPAREN1   0x80
46 #define GPAFEN0   0x88
47 #define GPAFEN1   0x8C
48 
49 #define GPIO_PUP_PDN_CNTRL_REG0 0xE4
50 #define GPIO_PUP_PDN_CNTRL_REG1 0xE8
51 #define GPIO_PUP_PDN_CNTRL_REG2 0xEC
52 #define GPIO_PUP_PDN_CNTRL_REG3 0xF0
53 
54 #define RESET_VAL_CNTRL_REG0 0xAAA95555
55 #define RESET_VAL_CNTRL_REG1 0xA0AAAAAA
56 #define RESET_VAL_CNTRL_REG2 0x50AAA95A
57 #define RESET_VAL_CNTRL_REG3 0x00055555
58 
59 #define BYTES_IN_WORD        4
60 
61 static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
62 {
63     uint64_t value = 0;
64 
65     qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
66                   TYPE_BCM2838_GPIO, __func__, offset);
67 
68     return value;
69 }
70 
71 static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
72                                unsigned size)
73 {
74     qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
75                   TYPE_BCM2838_GPIO, __func__, offset);
76 }
77 
78 static void bcm2838_gpio_reset(DeviceState *dev)
79 {
80     BCM2838GpioState *s = BCM2838_GPIO(dev);
81 
82     s->lev0 = 0;
83     s->lev1 = 0;
84 
85     memset(s->fsel, 0, sizeof(s->fsel));
86 
87     s->pup_cntrl_reg[0] = RESET_VAL_CNTRL_REG0;
88     s->pup_cntrl_reg[1] = RESET_VAL_CNTRL_REG1;
89     s->pup_cntrl_reg[2] = RESET_VAL_CNTRL_REG2;
90     s->pup_cntrl_reg[3] = RESET_VAL_CNTRL_REG3;
91 }
92 
93 static const MemoryRegionOps bcm2838_gpio_ops = {
94     .read = bcm2838_gpio_read,
95     .write = bcm2838_gpio_write,
96     .endianness = DEVICE_NATIVE_ENDIAN,
97 };
98 
99 static const VMStateDescription vmstate_bcm2838_gpio = {
100     .name = "bcm2838_gpio",
101     .version_id = 1,
102     .minimum_version_id = 1,
103     .fields = (VMStateField[]) {
104         VMSTATE_UINT8_ARRAY(fsel, BCM2838GpioState, BCM2838_GPIO_NUM),
105         VMSTATE_UINT32(lev0, BCM2838GpioState),
106         VMSTATE_UINT32(lev1, BCM2838GpioState),
107         VMSTATE_UINT8(sd_fsel, BCM2838GpioState),
108         VMSTATE_UINT32_ARRAY(pup_cntrl_reg, BCM2838GpioState,
109                              GPIO_PUP_PDN_CNTRL_NUM),
110         VMSTATE_END_OF_LIST()
111     }
112 };
113 
114 static void bcm2838_gpio_init(Object *obj)
115 {
116     BCM2838GpioState *s = BCM2838_GPIO(obj);
117     DeviceState *dev = DEVICE(obj);
118     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
119 
120     memory_region_init_io(&s->iomem, obj, &bcm2838_gpio_ops, s,
121                           "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
122     sysbus_init_mmio(sbd, &s->iomem);
123     qdev_init_gpio_out(dev, s->out, BCM2838_GPIO_NUM);
124 }
125 
126 static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
127 {
128     /* Temporary stub. Do nothing */
129 }
130 
131 static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
132 {
133     DeviceClass *dc = DEVICE_CLASS(klass);
134 
135     dc->vmsd = &vmstate_bcm2838_gpio;
136     dc->realize = &bcm2838_gpio_realize;
137     dc->reset = &bcm2838_gpio_reset;
138 }
139 
140 static const TypeInfo bcm2838_gpio_info = {
141     .name          = TYPE_BCM2838_GPIO,
142     .parent        = TYPE_SYS_BUS_DEVICE,
143     .instance_size = sizeof(BCM2838GpioState),
144     .instance_init = bcm2838_gpio_init,
145     .class_init    = bcm2838_gpio_class_init,
146 };
147 
148 static void bcm2838_gpio_register_types(void)
149 {
150     type_register_static(&bcm2838_gpio_info);
151 }
152 
153 type_init(bcm2838_gpio_register_types)
154