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