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