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/sd/sd.h"
21 #include "hw/gpio/bcm2838_gpio.h"
22 #include "hw/irq.h"
23
24 #define GPFSEL0 0x00
25 #define GPFSEL1 0x04
26 #define GPFSEL2 0x08
27 #define GPFSEL3 0x0C
28 #define GPFSEL4 0x10
29 #define GPFSEL5 0x14
30 #define GPSET0 0x1C
31 #define GPSET1 0x20
32 #define GPCLR0 0x28
33 #define GPCLR1 0x2C
34 #define GPLEV0 0x34
35 #define GPLEV1 0x38
36 #define GPEDS0 0x40
37 #define GPEDS1 0x44
38 #define GPREN0 0x4C
39 #define GPREN1 0x50
40 #define GPFEN0 0x58
41 #define GPFEN1 0x5C
42 #define GPHEN0 0x64
43 #define GPHEN1 0x68
44 #define GPLEN0 0x70
45 #define GPLEN1 0x74
46 #define GPAREN0 0x7C
47 #define GPAREN1 0x80
48 #define GPAFEN0 0x88
49 #define GPAFEN1 0x8C
50
51 #define GPIO_PUP_PDN_CNTRL_REG0 0xE4
52 #define GPIO_PUP_PDN_CNTRL_REG1 0xE8
53 #define GPIO_PUP_PDN_CNTRL_REG2 0xEC
54 #define GPIO_PUP_PDN_CNTRL_REG3 0xF0
55
56 #define RESET_VAL_CNTRL_REG0 0xAAA95555
57 #define RESET_VAL_CNTRL_REG1 0xA0AAAAAA
58 #define RESET_VAL_CNTRL_REG2 0x50AAA95A
59 #define RESET_VAL_CNTRL_REG3 0x00055555
60
61 #define NUM_FSELN_IN_GPFSELN 10
62 #define NUM_BITS_FSELN 3
63 #define MASK_FSELN 0x7
64
65 #define BYTES_IN_WORD 4
66
67 /* bcm,function property */
68 #define BCM2838_FSEL_GPIO_IN 0
69 #define BCM2838_FSEL_GPIO_OUT 1
70 #define BCM2838_FSEL_ALT5 2
71 #define BCM2838_FSEL_ALT4 3
72 #define BCM2838_FSEL_ALT0 4
73 #define BCM2838_FSEL_ALT1 5
74 #define BCM2838_FSEL_ALT2 6
75 #define BCM2838_FSEL_ALT3 7
76
gpfsel_get(BCM2838GpioState * s,uint8_t reg)77 static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
78 {
79 int i;
80 uint32_t value = 0;
81 for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
82 uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
83 if (index < sizeof(s->fsel)) {
84 value |= (s->fsel[index] & MASK_FSELN) << (NUM_BITS_FSELN * i);
85 }
86 }
87 return value;
88 }
89
gpfsel_set(BCM2838GpioState * s,uint8_t reg,uint32_t value)90 static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, uint32_t value)
91 {
92 int i;
93 for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
94 uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
95 if (index < sizeof(s->fsel)) {
96 int fsel = (value >> (NUM_BITS_FSELN * i)) & MASK_FSELN;
97 s->fsel[index] = fsel;
98 }
99 }
100
101 /* SD controller selection (48-53) */
102 if (s->sd_fsel != BCM2838_FSEL_GPIO_IN
103 && (s->fsel[48] == BCM2838_FSEL_GPIO_IN)
104 && (s->fsel[49] == BCM2838_FSEL_GPIO_IN)
105 && (s->fsel[50] == BCM2838_FSEL_GPIO_IN)
106 && (s->fsel[51] == BCM2838_FSEL_GPIO_IN)
107 && (s->fsel[52] == BCM2838_FSEL_GPIO_IN)
108 && (s->fsel[53] == BCM2838_FSEL_GPIO_IN)
109 ) {
110 /* SDHCI controller selected */
111 sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
112 s->sd_fsel = BCM2838_FSEL_GPIO_IN;
113 } else if (s->sd_fsel != BCM2838_FSEL_ALT0
114 && (s->fsel[48] == BCM2838_FSEL_ALT0) /* SD_CLK_R */
115 && (s->fsel[49] == BCM2838_FSEL_ALT0) /* SD_CMD_R */
116 && (s->fsel[50] == BCM2838_FSEL_ALT0) /* SD_DATA0_R */
117 && (s->fsel[51] == BCM2838_FSEL_ALT0) /* SD_DATA1_R */
118 && (s->fsel[52] == BCM2838_FSEL_ALT0) /* SD_DATA2_R */
119 && (s->fsel[53] == BCM2838_FSEL_ALT0) /* SD_DATA3_R */
120 ) {
121 /* SDHost controller selected */
122 sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
123 s->sd_fsel = BCM2838_FSEL_ALT0;
124 }
125 }
126
gpfsel_is_out(BCM2838GpioState * s,int index)127 static int gpfsel_is_out(BCM2838GpioState *s, int index)
128 {
129 if (index >= 0 && index < BCM2838_GPIO_NUM) {
130 return s->fsel[index] == 1;
131 }
132 return 0;
133 }
134
gpset(BCM2838GpioState * s,uint32_t val,uint8_t start,uint8_t count,uint32_t * lev)135 static void gpset(BCM2838GpioState *s, uint32_t val, uint8_t start,
136 uint8_t count, uint32_t *lev)
137 {
138 uint32_t changes = val & ~*lev;
139 uint32_t cur = 1;
140
141 int i;
142 for (i = 0; i < count; i++) {
143 if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
144 qemu_set_irq(s->out[start + i], 1);
145 }
146 cur <<= 1;
147 }
148
149 *lev |= val;
150 }
151
gpclr(BCM2838GpioState * s,uint32_t val,uint8_t start,uint8_t count,uint32_t * lev)152 static void gpclr(BCM2838GpioState *s, uint32_t val, uint8_t start,
153 uint8_t count, uint32_t *lev)
154 {
155 uint32_t changes = val & *lev;
156 uint32_t cur = 1;
157
158 int i;
159 for (i = 0; i < count; i++) {
160 if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
161 qemu_set_irq(s->out[start + i], 0);
162 }
163 cur <<= 1;
164 }
165
166 *lev &= ~val;
167 }
168
bcm2838_gpio_read(void * opaque,hwaddr offset,unsigned size)169 static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
170 {
171 BCM2838GpioState *s = (BCM2838GpioState *)opaque;
172 uint64_t value = 0;
173
174 switch (offset) {
175 case GPFSEL0:
176 case GPFSEL1:
177 case GPFSEL2:
178 case GPFSEL3:
179 case GPFSEL4:
180 case GPFSEL5:
181 value = gpfsel_get(s, offset / BYTES_IN_WORD);
182 break;
183 case GPSET0:
184 case GPSET1:
185 case GPCLR0:
186 case GPCLR1:
187 /* Write Only */
188 qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Attempt reading from write only"
189 " register. 0x%"PRIx64" will be returned."
190 " Address 0x%"HWADDR_PRIx", size %u\n",
191 TYPE_BCM2838_GPIO, __func__, value, offset, size);
192 break;
193 case GPLEV0:
194 value = s->lev0;
195 break;
196 case GPLEV1:
197 value = s->lev1;
198 break;
199 case GPEDS0:
200 case GPEDS1:
201 case GPREN0:
202 case GPREN1:
203 case GPFEN0:
204 case GPFEN1:
205 case GPHEN0:
206 case GPHEN1:
207 case GPLEN0:
208 case GPLEN1:
209 case GPAREN0:
210 case GPAREN1:
211 case GPAFEN0:
212 case GPAFEN1:
213 /* Not implemented */
214 qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
215 TYPE_BCM2838_GPIO, __func__, offset);
216 break;
217 case GPIO_PUP_PDN_CNTRL_REG0:
218 case GPIO_PUP_PDN_CNTRL_REG1:
219 case GPIO_PUP_PDN_CNTRL_REG2:
220 case GPIO_PUP_PDN_CNTRL_REG3:
221 value = s->pup_cntrl_reg[(offset - GPIO_PUP_PDN_CNTRL_REG0)
222 / sizeof(s->pup_cntrl_reg[0])];
223 break;
224 default:
225 qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: bad offset %"HWADDR_PRIx"\n",
226 TYPE_BCM2838_GPIO, __func__, offset);
227 break;
228 }
229
230 return value;
231 }
232
bcm2838_gpio_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)233 static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
234 unsigned size)
235 {
236 BCM2838GpioState *s = (BCM2838GpioState *)opaque;
237
238 switch (offset) {
239 case GPFSEL0:
240 case GPFSEL1:
241 case GPFSEL2:
242 case GPFSEL3:
243 case GPFSEL4:
244 case GPFSEL5:
245 gpfsel_set(s, offset / BYTES_IN_WORD, value);
246 break;
247 case GPSET0:
248 gpset(s, value, 0, 32, &s->lev0);
249 break;
250 case GPSET1:
251 gpset(s, value, 32, 22, &s->lev1);
252 break;
253 case GPCLR0:
254 gpclr(s, value, 0, 32, &s->lev0);
255 break;
256 case GPCLR1:
257 gpclr(s, value, 32, 22, &s->lev1);
258 break;
259 case GPLEV0:
260 case GPLEV1:
261 /* Read Only */
262 qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Attempt writing 0x%"PRIx64""
263 " to read only register. Ignored."
264 " Address 0x%"HWADDR_PRIx", size %u\n",
265 TYPE_BCM2838_GPIO, __func__, value, offset, size);
266 break;
267 case GPEDS0:
268 case GPEDS1:
269 case GPREN0:
270 case GPREN1:
271 case GPFEN0:
272 case GPFEN1:
273 case GPHEN0:
274 case GPHEN1:
275 case GPLEN0:
276 case GPLEN1:
277 case GPAREN0:
278 case GPAREN1:
279 case GPAFEN0:
280 case GPAFEN1:
281 /* Not implemented */
282 qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
283 TYPE_BCM2838_GPIO, __func__, offset);
284 break;
285 case GPIO_PUP_PDN_CNTRL_REG0:
286 case GPIO_PUP_PDN_CNTRL_REG1:
287 case GPIO_PUP_PDN_CNTRL_REG2:
288 case GPIO_PUP_PDN_CNTRL_REG3:
289 s->pup_cntrl_reg[(offset - GPIO_PUP_PDN_CNTRL_REG0)
290 / sizeof(s->pup_cntrl_reg[0])] = value;
291 break;
292 default:
293 qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: bad offset %"HWADDR_PRIx"\n",
294 TYPE_BCM2838_GPIO, __func__, offset);
295 }
296 return;
297 }
298
bcm2838_gpio_reset(DeviceState * dev)299 static void bcm2838_gpio_reset(DeviceState *dev)
300 {
301 BCM2838GpioState *s = BCM2838_GPIO(dev);
302
303 memset(s->fsel, 0, sizeof(s->fsel));
304
305 s->sd_fsel = 0;
306
307 /* SDHCI is selected by default */
308 sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
309
310 s->lev0 = 0;
311 s->lev1 = 0;
312
313 memset(s->fsel, 0, sizeof(s->fsel));
314
315 s->pup_cntrl_reg[0] = RESET_VAL_CNTRL_REG0;
316 s->pup_cntrl_reg[1] = RESET_VAL_CNTRL_REG1;
317 s->pup_cntrl_reg[2] = RESET_VAL_CNTRL_REG2;
318 s->pup_cntrl_reg[3] = RESET_VAL_CNTRL_REG3;
319 }
320
321 static const MemoryRegionOps bcm2838_gpio_ops = {
322 .read = bcm2838_gpio_read,
323 .write = bcm2838_gpio_write,
324 .endianness = DEVICE_NATIVE_ENDIAN,
325 };
326
327 static const VMStateDescription vmstate_bcm2838_gpio = {
328 .name = "bcm2838_gpio",
329 .version_id = 1,
330 .minimum_version_id = 1,
331 .fields = (VMStateField[]) {
332 VMSTATE_UINT8_ARRAY(fsel, BCM2838GpioState, BCM2838_GPIO_NUM),
333 VMSTATE_UINT32(lev0, BCM2838GpioState),
334 VMSTATE_UINT32(lev1, BCM2838GpioState),
335 VMSTATE_UINT8(sd_fsel, BCM2838GpioState),
336 VMSTATE_UINT32_ARRAY(pup_cntrl_reg, BCM2838GpioState,
337 GPIO_PUP_PDN_CNTRL_NUM),
338 VMSTATE_END_OF_LIST()
339 }
340 };
341
bcm2838_gpio_init(Object * obj)342 static void bcm2838_gpio_init(Object *obj)
343 {
344 BCM2838GpioState *s = BCM2838_GPIO(obj);
345 DeviceState *dev = DEVICE(obj);
346 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
347
348 qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
349
350 memory_region_init_io(&s->iomem, obj, &bcm2838_gpio_ops, s,
351 "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
352 sysbus_init_mmio(sbd, &s->iomem);
353 qdev_init_gpio_out(dev, s->out, BCM2838_GPIO_NUM);
354 }
355
bcm2838_gpio_realize(DeviceState * dev,Error ** errp)356 static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
357 {
358 BCM2838GpioState *s = BCM2838_GPIO(dev);
359 Object *obj;
360
361 obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &error_abort);
362 s->sdbus_sdhci = SD_BUS(obj);
363
364 obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &error_abort);
365 s->sdbus_sdhost = SD_BUS(obj);
366 }
367
bcm2838_gpio_class_init(ObjectClass * klass,void * data)368 static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
369 {
370 DeviceClass *dc = DEVICE_CLASS(klass);
371
372 dc->vmsd = &vmstate_bcm2838_gpio;
373 dc->realize = &bcm2838_gpio_realize;
374 dc->reset = &bcm2838_gpio_reset;
375 }
376
377 static const TypeInfo bcm2838_gpio_info = {
378 .name = TYPE_BCM2838_GPIO,
379 .parent = TYPE_SYS_BUS_DEVICE,
380 .instance_size = sizeof(BCM2838GpioState),
381 .instance_init = bcm2838_gpio_init,
382 .class_init = bcm2838_gpio_class_init,
383 };
384
bcm2838_gpio_register_types(void)385 static void bcm2838_gpio_register_types(void)
386 {
387 type_register_static(&bcm2838_gpio_info);
388 }
389
390 type_init(bcm2838_gpio_register_types)
391