1 /* 2 * Raspberry Pi (BCM2835) GPIO Controller 3 * 4 * Copyright (c) 2017 Antfield SAS 5 * 6 * Authors: 7 * Clement Deschamps <clement.deschamps@antfield.fr> 8 * Luc Michel <luc.michel@antfield.fr> 9 * 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. 12 */ 13 14 #include "qemu/osdep.h" 15 #include "qemu/log.h" 16 #include "qemu/module.h" 17 #include "qemu/timer.h" 18 #include "qapi/error.h" 19 #include "hw/sysbus.h" 20 #include "hw/sd/sd.h" 21 #include "hw/gpio/bcm2835_gpio.h" 22 23 #define GPFSEL0 0x00 24 #define GPFSEL1 0x04 25 #define GPFSEL2 0x08 26 #define GPFSEL3 0x0C 27 #define GPFSEL4 0x10 28 #define GPFSEL5 0x14 29 #define GPSET0 0x1C 30 #define GPSET1 0x20 31 #define GPCLR0 0x28 32 #define GPCLR1 0x2C 33 #define GPLEV0 0x34 34 #define GPLEV1 0x38 35 #define GPEDS0 0x40 36 #define GPEDS1 0x44 37 #define GPREN0 0x4C 38 #define GPREN1 0x50 39 #define GPFEN0 0x58 40 #define GPFEN1 0x5C 41 #define GPHEN0 0x64 42 #define GPHEN1 0x68 43 #define GPLEN0 0x70 44 #define GPLEN1 0x74 45 #define GPAREN0 0x7C 46 #define GPAREN1 0x80 47 #define GPAFEN0 0x88 48 #define GPAFEN1 0x8C 49 #define GPPUD 0x94 50 #define GPPUDCLK0 0x98 51 #define GPPUDCLK1 0x9C 52 53 static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg) 54 { 55 int i; 56 uint32_t value = 0; 57 for (i = 0; i < 10; i++) { 58 uint32_t index = 10 * reg + i; 59 if (index < sizeof(s->fsel)) { 60 value |= (s->fsel[index] & 0x7) << (3 * i); 61 } 62 } 63 return value; 64 } 65 66 static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value) 67 { 68 int i; 69 for (i = 0; i < 10; i++) { 70 uint32_t index = 10 * reg + i; 71 if (index < sizeof(s->fsel)) { 72 int fsel = (value >> (3 * i)) & 0x7; 73 s->fsel[index] = fsel; 74 } 75 } 76 77 /* SD controller selection (48-53) */ 78 if (s->sd_fsel != 0 79 && (s->fsel[48] == 0) /* SD_CLK_R */ 80 && (s->fsel[49] == 0) /* SD_CMD_R */ 81 && (s->fsel[50] == 0) /* SD_DATA0_R */ 82 && (s->fsel[51] == 0) /* SD_DATA1_R */ 83 && (s->fsel[52] == 0) /* SD_DATA2_R */ 84 && (s->fsel[53] == 0) /* SD_DATA3_R */ 85 ) { 86 /* SDHCI controller selected */ 87 sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci); 88 s->sd_fsel = 0; 89 } else if (s->sd_fsel != 4 90 && (s->fsel[48] == 4) /* SD_CLK_R */ 91 && (s->fsel[49] == 4) /* SD_CMD_R */ 92 && (s->fsel[50] == 4) /* SD_DATA0_R */ 93 && (s->fsel[51] == 4) /* SD_DATA1_R */ 94 && (s->fsel[52] == 4) /* SD_DATA2_R */ 95 && (s->fsel[53] == 4) /* SD_DATA3_R */ 96 ) { 97 /* SDHost controller selected */ 98 sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost); 99 s->sd_fsel = 4; 100 } 101 } 102 103 static int gpfsel_is_out(BCM2835GpioState *s, int index) 104 { 105 if (index >= 0 && index < 54) { 106 return s->fsel[index] == 1; 107 } 108 return 0; 109 } 110 111 static void gpset(BCM2835GpioState *s, 112 uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) 113 { 114 uint32_t changes = val & ~*lev; 115 uint32_t cur = 1; 116 117 int i; 118 for (i = 0; i < count; i++) { 119 if ((changes & cur) && (gpfsel_is_out(s, start + i))) { 120 qemu_set_irq(s->out[start + i], 1); 121 } 122 cur <<= 1; 123 } 124 125 *lev |= val; 126 } 127 128 static void gpclr(BCM2835GpioState *s, 129 uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) 130 { 131 uint32_t changes = val & *lev; 132 uint32_t cur = 1; 133 134 int i; 135 for (i = 0; i < count; i++) { 136 if ((changes & cur) && (gpfsel_is_out(s, start + i))) { 137 qemu_set_irq(s->out[start + i], 0); 138 } 139 cur <<= 1; 140 } 141 142 *lev &= ~val; 143 } 144 145 static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset, 146 unsigned size) 147 { 148 BCM2835GpioState *s = (BCM2835GpioState *)opaque; 149 150 switch (offset) { 151 case GPFSEL0: 152 case GPFSEL1: 153 case GPFSEL2: 154 case GPFSEL3: 155 case GPFSEL4: 156 case GPFSEL5: 157 return gpfsel_get(s, offset / 4); 158 case GPSET0: 159 case GPSET1: 160 /* Write Only */ 161 return 0; 162 case GPCLR0: 163 case GPCLR1: 164 /* Write Only */ 165 return 0; 166 case GPLEV0: 167 return s->lev0; 168 case GPLEV1: 169 return s->lev1; 170 case GPEDS0: 171 case GPEDS1: 172 case GPREN0: 173 case GPREN1: 174 case GPFEN0: 175 case GPFEN1: 176 case GPHEN0: 177 case GPHEN1: 178 case GPLEN0: 179 case GPLEN1: 180 case GPAREN0: 181 case GPAREN1: 182 case GPAFEN0: 183 case GPAFEN1: 184 case GPPUD: 185 case GPPUDCLK0: 186 case GPPUDCLK1: 187 /* Not implemented */ 188 return 0; 189 default: 190 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 191 __func__, offset); 192 break; 193 } 194 195 return 0; 196 } 197 198 static void bcm2835_gpio_write(void *opaque, hwaddr offset, 199 uint64_t value, unsigned size) 200 { 201 BCM2835GpioState *s = (BCM2835GpioState *)opaque; 202 203 switch (offset) { 204 case GPFSEL0: 205 case GPFSEL1: 206 case GPFSEL2: 207 case GPFSEL3: 208 case GPFSEL4: 209 case GPFSEL5: 210 gpfsel_set(s, offset / 4, value); 211 break; 212 case GPSET0: 213 gpset(s, value, 0, 32, &s->lev0); 214 break; 215 case GPSET1: 216 gpset(s, value, 32, 22, &s->lev1); 217 break; 218 case GPCLR0: 219 gpclr(s, value, 0, 32, &s->lev0); 220 break; 221 case GPCLR1: 222 gpclr(s, value, 32, 22, &s->lev1); 223 break; 224 case GPLEV0: 225 case GPLEV1: 226 /* Read Only */ 227 break; 228 case GPEDS0: 229 case GPEDS1: 230 case GPREN0: 231 case GPREN1: 232 case GPFEN0: 233 case GPFEN1: 234 case GPHEN0: 235 case GPHEN1: 236 case GPLEN0: 237 case GPLEN1: 238 case GPAREN0: 239 case GPAREN1: 240 case GPAFEN0: 241 case GPAFEN1: 242 case GPPUD: 243 case GPPUDCLK0: 244 case GPPUDCLK1: 245 /* Not implemented */ 246 break; 247 default: 248 goto err_out; 249 } 250 return; 251 252 err_out: 253 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 254 __func__, offset); 255 } 256 257 static void bcm2835_gpio_reset(DeviceState *dev) 258 { 259 BCM2835GpioState *s = BCM2835_GPIO(dev); 260 261 int i; 262 for (i = 0; i < 6; i++) { 263 gpfsel_set(s, i, 0); 264 } 265 266 s->sd_fsel = 0; 267 268 /* SDHCI is selected by default */ 269 sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci); 270 271 s->lev0 = 0; 272 s->lev1 = 0; 273 } 274 275 static const MemoryRegionOps bcm2835_gpio_ops = { 276 .read = bcm2835_gpio_read, 277 .write = bcm2835_gpio_write, 278 .endianness = DEVICE_NATIVE_ENDIAN, 279 }; 280 281 static const VMStateDescription vmstate_bcm2835_gpio = { 282 .name = "bcm2835_gpio", 283 .version_id = 1, 284 .minimum_version_id = 1, 285 .fields = (VMStateField[]) { 286 VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), 287 VMSTATE_UINT32(lev0, BCM2835GpioState), 288 VMSTATE_UINT32(lev1, BCM2835GpioState), 289 VMSTATE_UINT8(sd_fsel, BCM2835GpioState), 290 VMSTATE_END_OF_LIST() 291 } 292 }; 293 294 static void bcm2835_gpio_init(Object *obj) 295 { 296 BCM2835GpioState *s = BCM2835_GPIO(obj); 297 DeviceState *dev = DEVICE(obj); 298 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 299 300 qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), 301 TYPE_SD_BUS, DEVICE(s), "sd-bus"); 302 303 memory_region_init_io(&s->iomem, obj, 304 &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000); 305 sysbus_init_mmio(sbd, &s->iomem); 306 qdev_init_gpio_out(dev, s->out, 54); 307 } 308 309 static void bcm2835_gpio_realize(DeviceState *dev, Error **errp) 310 { 311 BCM2835GpioState *s = BCM2835_GPIO(dev); 312 Object *obj; 313 Error *err = NULL; 314 315 obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err); 316 if (obj == NULL) { 317 error_setg(errp, "%s: required sdhci link not found: %s", 318 __func__, error_get_pretty(err)); 319 return; 320 } 321 s->sdbus_sdhci = SD_BUS(obj); 322 323 obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err); 324 if (obj == NULL) { 325 error_setg(errp, "%s: required sdhost link not found: %s", 326 __func__, error_get_pretty(err)); 327 return; 328 } 329 s->sdbus_sdhost = SD_BUS(obj); 330 } 331 332 static void bcm2835_gpio_class_init(ObjectClass *klass, void *data) 333 { 334 DeviceClass *dc = DEVICE_CLASS(klass); 335 336 dc->vmsd = &vmstate_bcm2835_gpio; 337 dc->realize = &bcm2835_gpio_realize; 338 dc->reset = &bcm2835_gpio_reset; 339 } 340 341 static const TypeInfo bcm2835_gpio_info = { 342 .name = TYPE_BCM2835_GPIO, 343 .parent = TYPE_SYS_BUS_DEVICE, 344 .instance_size = sizeof(BCM2835GpioState), 345 .instance_init = bcm2835_gpio_init, 346 .class_init = bcm2835_gpio_class_init, 347 }; 348 349 static void bcm2835_gpio_register_types(void) 350 { 351 type_register_static(&bcm2835_gpio_info); 352 } 353 354 type_init(bcm2835_gpio_register_types) 355