2 * Raspberry Pi (BCM2835) GPIO Controller
4 * Copyright (c) 2017 Antfield SAS
7 * Clement Deschamps <clement.deschamps@antfield.fr>
8 * Luc Michel <luc.michel@antfield.fr>
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include "qemu/module.h"
17 #include "qemu/timer.h"
18 #include "qapi/error.h"
19 #include "hw/sysbus.h"
20 #include "migration/vmstate.h"
22 #include "hw/gpio/bcm2835_gpio.h"
52 #define GPPUDCLK0 0x98
53 #define GPPUDCLK1 0x9C
55 static uint32_t gpfsel_get(BCM2835GpioState
*s
, uint8_t reg
)
59 for (i
= 0; i
< 10; i
++) {
60 uint32_t index
= 10 * reg
+ i
;
61 if (index
< sizeof(s
->fsel
)) {
62 value
|= (s
->fsel
[index
] & 0x7) << (3 * i
);
68 static void gpfsel_set(BCM2835GpioState
*s
, uint8_t reg
, uint32_t value
)
71 for (i
= 0; i
< 10; i
++) {
72 uint32_t index
= 10 * reg
+ i
;
73 if (index
< sizeof(s
->fsel
)) {
74 int fsel
= (value
>> (3 * i
)) & 0x7;
75 s
->fsel
[index
] = fsel
;
79 /* SD controller selection (48-53) */
81 && (s
->fsel
[48] == 0) /* SD_CLK_R */
82 && (s
->fsel
[49] == 0) /* SD_CMD_R */
83 && (s
->fsel
[50] == 0) /* SD_DATA0_R */
84 && (s
->fsel
[51] == 0) /* SD_DATA1_R */
85 && (s
->fsel
[52] == 0) /* SD_DATA2_R */
86 && (s
->fsel
[53] == 0) /* SD_DATA3_R */
88 /* SDHCI controller selected */
89 sdbus_reparent_card(s
->sdbus_sdhost
, s
->sdbus_sdhci
);
91 } else if (s
->sd_fsel
!= 4
92 && (s
->fsel
[48] == 4) /* SD_CLK_R */
93 && (s
->fsel
[49] == 4) /* SD_CMD_R */
94 && (s
->fsel
[50] == 4) /* SD_DATA0_R */
95 && (s
->fsel
[51] == 4) /* SD_DATA1_R */
96 && (s
->fsel
[52] == 4) /* SD_DATA2_R */
97 && (s
->fsel
[53] == 4) /* SD_DATA3_R */
99 /* SDHost controller selected */
100 sdbus_reparent_card(s
->sdbus_sdhci
, s
->sdbus_sdhost
);
105 static int gpfsel_is_out(BCM2835GpioState
*s
, int index
)
107 if (index
>= 0 && index
< 54) {
108 return s
->fsel
[index
] == 1;
113 static void gpset(BCM2835GpioState
*s
,
114 uint32_t val
, uint8_t start
, uint8_t count
, uint32_t *lev
)
116 uint32_t changes
= val
& ~*lev
;
120 for (i
= 0; i
< count
; i
++) {
121 if ((changes
& cur
) && (gpfsel_is_out(s
, start
+ i
))) {
122 qemu_set_irq(s
->out
[start
+ i
], 1);
130 static void gpclr(BCM2835GpioState
*s
,
131 uint32_t val
, uint8_t start
, uint8_t count
, uint32_t *lev
)
133 uint32_t changes
= val
& *lev
;
137 for (i
= 0; i
< count
; i
++) {
138 if ((changes
& cur
) && (gpfsel_is_out(s
, start
+ i
))) {
139 qemu_set_irq(s
->out
[start
+ i
], 0);
147 static uint64_t bcm2835_gpio_read(void *opaque
, hwaddr offset
,
150 BCM2835GpioState
*s
= (BCM2835GpioState
*)opaque
;
159 return gpfsel_get(s
, offset
/ 4);
189 /* Not implemented */
192 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset %"HWADDR_PRIx
"\n",
200 static void bcm2835_gpio_write(void *opaque
, hwaddr offset
,
201 uint64_t value
, unsigned size
)
203 BCM2835GpioState
*s
= (BCM2835GpioState
*)opaque
;
212 gpfsel_set(s
, offset
/ 4, value
);
215 gpset(s
, value
, 0, 32, &s
->lev0
);
218 gpset(s
, value
, 32, 22, &s
->lev1
);
221 gpclr(s
, value
, 0, 32, &s
->lev0
);
224 gpclr(s
, value
, 32, 22, &s
->lev1
);
247 /* Not implemented */
255 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset %"HWADDR_PRIx
"\n",
259 static void bcm2835_gpio_reset(DeviceState
*dev
)
261 BCM2835GpioState
*s
= BCM2835_GPIO(dev
);
264 for (i
= 0; i
< 6; i
++) {
270 /* SDHCI is selected by default */
271 sdbus_reparent_card(&s
->sdbus
, s
->sdbus_sdhci
);
277 static const MemoryRegionOps bcm2835_gpio_ops
= {
278 .read
= bcm2835_gpio_read
,
279 .write
= bcm2835_gpio_write
,
280 .endianness
= DEVICE_NATIVE_ENDIAN
,
283 static const VMStateDescription vmstate_bcm2835_gpio
= {
284 .name
= "bcm2835_gpio",
286 .minimum_version_id
= 1,
287 .fields
= (VMStateField
[]) {
288 VMSTATE_UINT8_ARRAY(fsel
, BCM2835GpioState
, 54),
289 VMSTATE_UINT32(lev0
, BCM2835GpioState
),
290 VMSTATE_UINT32(lev1
, BCM2835GpioState
),
291 VMSTATE_UINT8(sd_fsel
, BCM2835GpioState
),
292 VMSTATE_END_OF_LIST()
296 static void bcm2835_gpio_init(Object
*obj
)
298 BCM2835GpioState
*s
= BCM2835_GPIO(obj
);
299 DeviceState
*dev
= DEVICE(obj
);
300 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
302 qbus_create_inplace(&s
->sdbus
, sizeof(s
->sdbus
),
303 TYPE_SD_BUS
, DEVICE(s
), "sd-bus");
305 memory_region_init_io(&s
->iomem
, obj
,
306 &bcm2835_gpio_ops
, s
, "bcm2835_gpio", 0x1000);
307 sysbus_init_mmio(sbd
, &s
->iomem
);
308 qdev_init_gpio_out(dev
, s
->out
, 54);
311 static void bcm2835_gpio_realize(DeviceState
*dev
, Error
**errp
)
313 BCM2835GpioState
*s
= BCM2835_GPIO(dev
);
317 obj
= object_property_get_link(OBJECT(dev
), "sdbus-sdhci", &err
);
319 error_setg(errp
, "%s: required sdhci link not found: %s",
320 __func__
, error_get_pretty(err
));
323 s
->sdbus_sdhci
= SD_BUS(obj
);
325 obj
= object_property_get_link(OBJECT(dev
), "sdbus-sdhost", &err
);
327 error_setg(errp
, "%s: required sdhost link not found: %s",
328 __func__
, error_get_pretty(err
));
331 s
->sdbus_sdhost
= SD_BUS(obj
);
334 static void bcm2835_gpio_class_init(ObjectClass
*klass
, void *data
)
336 DeviceClass
*dc
= DEVICE_CLASS(klass
);
338 dc
->vmsd
= &vmstate_bcm2835_gpio
;
339 dc
->realize
= &bcm2835_gpio_realize
;
340 dc
->reset
= &bcm2835_gpio_reset
;
343 static const TypeInfo bcm2835_gpio_info
= {
344 .name
= TYPE_BCM2835_GPIO
,
345 .parent
= TYPE_SYS_BUS_DEVICE
,
346 .instance_size
= sizeof(BCM2835GpioState
),
347 .instance_init
= bcm2835_gpio_init
,
348 .class_init
= bcm2835_gpio_class_init
,
351 static void bcm2835_gpio_register_types(void)
353 type_register_static(&bcm2835_gpio_info
);
356 type_init(bcm2835_gpio_register_types
)