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