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