atmega.c (15858B)
1/* 2 * QEMU ATmega MCU 3 * 4 * Copyright (c) 2019-2020 Philippe Mathieu-Daudé 5 * 6 * This work is licensed under the terms of the GNU GPLv2 or later. 7 * See the COPYING file in the top-level directory. 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11#include "qemu/osdep.h" 12#include "qemu/module.h" 13#include "qemu/units.h" 14#include "qapi/error.h" 15#include "exec/memory.h" 16#include "exec/address-spaces.h" 17#include "sysemu/sysemu.h" 18#include "hw/qdev-properties.h" 19#include "hw/sysbus.h" 20#include "qom/object.h" 21#include "hw/misc/unimp.h" 22#include "atmega.h" 23 24enum AtmegaPeripheral { 25 POWER0, POWER1, 26 GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, 27 GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL, 28 USART0, USART1, USART2, USART3, 29 TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5, 30 PERIFMAX 31}; 32 33#define GPIO(n) (n + GPIOA) 34#define USART(n) (n + USART0) 35#define TIMER(n) (n + TIMER0) 36#define POWER(n) (n + POWER0) 37 38typedef struct { 39 uint16_t addr; 40 enum AtmegaPeripheral power_index; 41 uint8_t power_bit; 42 /* timer specific */ 43 uint16_t intmask_addr; 44 uint16_t intflag_addr; 45 bool is_timer16; 46} peripheral_cfg; 47 48struct AtmegaMcuClass { 49 /*< private >*/ 50 SysBusDeviceClass parent_class; 51 /*< public >*/ 52 const char *uc_name; 53 const char *cpu_type; 54 size_t flash_size; 55 size_t eeprom_size; 56 size_t sram_size; 57 size_t io_size; 58 size_t gpio_count; 59 size_t adc_count; 60 const uint8_t *irq; 61 const peripheral_cfg *dev; 62}; 63typedef struct AtmegaMcuClass AtmegaMcuClass; 64 65DECLARE_CLASS_CHECKERS(AtmegaMcuClass, ATMEGA_MCU, 66 TYPE_ATMEGA_MCU) 67 68static const peripheral_cfg dev168_328[PERIFMAX] = { 69 [USART0] = { 0xc0, POWER0, 1 }, 70 [TIMER2] = { 0xb0, POWER0, 6, 0x70, 0x37, false }, 71 [TIMER1] = { 0x80, POWER0, 3, 0x6f, 0x36, true }, 72 [POWER0] = { 0x64 }, 73 [TIMER0] = { 0x44, POWER0, 5, 0x6e, 0x35, false }, 74 [GPIOD] = { 0x29 }, 75 [GPIOC] = { 0x26 }, 76 [GPIOB] = { 0x23 }, 77}, dev1280_2560[PERIFMAX] = { 78 [USART3] = { 0x130, POWER1, 2 }, 79 [TIMER5] = { 0x120, POWER1, 5, 0x73, 0x3a, true }, 80 [GPIOL] = { 0x109 }, 81 [GPIOK] = { 0x106 }, 82 [GPIOJ] = { 0x103 }, 83 [GPIOH] = { 0x100 }, 84 [USART2] = { 0xd0, POWER1, 1 }, 85 [USART1] = { 0xc8, POWER1, 0 }, 86 [USART0] = { 0xc0, POWER0, 1 }, 87 [TIMER2] = { 0xb0, POWER0, 6, 0x70, 0x37, false }, /* TODO async */ 88 [TIMER4] = { 0xa0, POWER1, 4, 0x72, 0x39, true }, 89 [TIMER3] = { 0x90, POWER1, 3, 0x71, 0x38, true }, 90 [TIMER1] = { 0x80, POWER0, 3, 0x6f, 0x36, true }, 91 [POWER1] = { 0x65 }, 92 [POWER0] = { 0x64 }, 93 [TIMER0] = { 0x44, POWER0, 5, 0x6e, 0x35, false }, 94 [GPIOG] = { 0x32 }, 95 [GPIOF] = { 0x2f }, 96 [GPIOE] = { 0x2c }, 97 [GPIOD] = { 0x29 }, 98 [GPIOC] = { 0x26 }, 99 [GPIOB] = { 0x23 }, 100 [GPIOA] = { 0x20 }, 101}; 102 103enum AtmegaIrq { 104 USART0_RXC_IRQ, USART0_DRE_IRQ, USART0_TXC_IRQ, 105 USART1_RXC_IRQ, USART1_DRE_IRQ, USART1_TXC_IRQ, 106 USART2_RXC_IRQ, USART2_DRE_IRQ, USART2_TXC_IRQ, 107 USART3_RXC_IRQ, USART3_DRE_IRQ, USART3_TXC_IRQ, 108 TIMER0_CAPT_IRQ, TIMER0_COMPA_IRQ, TIMER0_COMPB_IRQ, 109 TIMER0_COMPC_IRQ, TIMER0_OVF_IRQ, 110 TIMER1_CAPT_IRQ, TIMER1_COMPA_IRQ, TIMER1_COMPB_IRQ, 111 TIMER1_COMPC_IRQ, TIMER1_OVF_IRQ, 112 TIMER2_CAPT_IRQ, TIMER2_COMPA_IRQ, TIMER2_COMPB_IRQ, 113 TIMER2_COMPC_IRQ, TIMER2_OVF_IRQ, 114 TIMER3_CAPT_IRQ, TIMER3_COMPA_IRQ, TIMER3_COMPB_IRQ, 115 TIMER3_COMPC_IRQ, TIMER3_OVF_IRQ, 116 TIMER4_CAPT_IRQ, TIMER4_COMPA_IRQ, TIMER4_COMPB_IRQ, 117 TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ, 118 TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ, 119 TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ, 120 IRQ_COUNT 121}; 122 123#define USART_IRQ_COUNT 3 124#define USART_RXC_IRQ(n) (n * USART_IRQ_COUNT + USART0_RXC_IRQ) 125#define USART_DRE_IRQ(n) (n * USART_IRQ_COUNT + USART0_DRE_IRQ) 126#define USART_TXC_IRQ(n) (n * USART_IRQ_COUNT + USART0_TXC_IRQ) 127#define TIMER_IRQ_COUNT 5 128#define TIMER_CAPT_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_CAPT_IRQ) 129#define TIMER_COMPA_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPA_IRQ) 130#define TIMER_COMPB_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPB_IRQ) 131#define TIMER_COMPC_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPC_IRQ) 132#define TIMER_OVF_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_OVF_IRQ) 133 134static const uint8_t irq168_328[IRQ_COUNT] = { 135 [TIMER2_COMPA_IRQ] = 8, 136 [TIMER2_COMPB_IRQ] = 9, 137 [TIMER2_OVF_IRQ] = 10, 138 [TIMER1_CAPT_IRQ] = 11, 139 [TIMER1_COMPA_IRQ] = 12, 140 [TIMER1_COMPB_IRQ] = 13, 141 [TIMER1_OVF_IRQ] = 14, 142 [TIMER0_COMPA_IRQ] = 15, 143 [TIMER0_COMPB_IRQ] = 16, 144 [TIMER0_OVF_IRQ] = 17, 145 [USART0_RXC_IRQ] = 19, 146 [USART0_DRE_IRQ] = 20, 147 [USART0_TXC_IRQ] = 21, 148}, irq1280_2560[IRQ_COUNT] = { 149 [TIMER2_COMPA_IRQ] = 14, 150 [TIMER2_COMPB_IRQ] = 15, 151 [TIMER2_OVF_IRQ] = 16, 152 [TIMER1_CAPT_IRQ] = 17, 153 [TIMER1_COMPA_IRQ] = 18, 154 [TIMER1_COMPB_IRQ] = 19, 155 [TIMER1_COMPC_IRQ] = 20, 156 [TIMER1_OVF_IRQ] = 21, 157 [TIMER0_COMPA_IRQ] = 22, 158 [TIMER0_COMPB_IRQ] = 23, 159 [TIMER0_OVF_IRQ] = 24, 160 [USART0_RXC_IRQ] = 26, 161 [USART0_DRE_IRQ] = 27, 162 [USART0_TXC_IRQ] = 28, 163 [TIMER3_CAPT_IRQ] = 32, 164 [TIMER3_COMPA_IRQ] = 33, 165 [TIMER3_COMPB_IRQ] = 34, 166 [TIMER3_COMPC_IRQ] = 35, 167 [TIMER3_OVF_IRQ] = 36, 168 [USART1_RXC_IRQ] = 37, 169 [USART1_DRE_IRQ] = 38, 170 [USART1_TXC_IRQ] = 39, 171 [TIMER4_CAPT_IRQ] = 42, 172 [TIMER4_COMPA_IRQ] = 43, 173 [TIMER4_COMPB_IRQ] = 44, 174 [TIMER4_COMPC_IRQ] = 45, 175 [TIMER4_OVF_IRQ] = 46, 176 [TIMER5_CAPT_IRQ] = 47, 177 [TIMER5_COMPA_IRQ] = 48, 178 [TIMER5_COMPB_IRQ] = 49, 179 [TIMER5_COMPC_IRQ] = 50, 180 [TIMER5_OVF_IRQ] = 51, 181 [USART2_RXC_IRQ] = 52, 182 [USART2_DRE_IRQ] = 53, 183 [USART2_TXC_IRQ] = 54, 184 [USART3_RXC_IRQ] = 55, 185 [USART3_DRE_IRQ] = 56, 186 [USART3_TXC_IRQ] = 57, 187}; 188 189static void connect_peripheral_irq(const AtmegaMcuClass *k, 190 SysBusDevice *dev, int dev_irqn, 191 DeviceState *cpu, 192 unsigned peripheral_index) 193{ 194 int cpu_irq = k->irq[peripheral_index]; 195 196 if (!cpu_irq) { 197 return; 198 } 199 /* FIXME move that to avr_cpu_set_int() once 'sample' board is removed */ 200 assert(cpu_irq >= 2); 201 cpu_irq -= 2; 202 203 sysbus_connect_irq(dev, dev_irqn, qdev_get_gpio_in(cpu, cpu_irq)); 204} 205 206static void connect_power_reduction_gpio(AtmegaMcuState *s, 207 const AtmegaMcuClass *k, 208 DeviceState *cpu, 209 unsigned peripheral_index) 210{ 211 unsigned power_index = k->dev[peripheral_index].power_index; 212 assert(k->dev[power_index].addr); 213 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwr[power_index - POWER0]), 214 k->dev[peripheral_index].power_bit, 215 qdev_get_gpio_in(cpu, 0)); 216} 217 218static void atmega_realize(DeviceState *dev, Error **errp) 219{ 220 AtmegaMcuState *s = ATMEGA_MCU(dev); 221 const AtmegaMcuClass *mc = ATMEGA_MCU_GET_CLASS(dev); 222 DeviceState *cpudev; 223 SysBusDevice *sbd; 224 char *devname; 225 size_t i; 226 227 assert(mc->io_size <= 0x200); 228 229 if (!s->xtal_freq_hz) { 230 error_setg(errp, "\"xtal-frequency-hz\" property must be provided."); 231 return; 232 } 233 234 /* CPU */ 235 object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type); 236 object_property_set_bool(OBJECT(&s->cpu), "realized", true, &error_abort); 237 cpudev = DEVICE(&s->cpu); 238 239 /* SRAM */ 240 memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, 241 &error_abort); 242 memory_region_add_subregion(get_system_memory(), 243 OFFSET_DATA + mc->io_size, &s->sram); 244 245 /* Flash */ 246 memory_region_init_rom(&s->flash, OBJECT(dev), 247 "flash", mc->flash_size, &error_fatal); 248 memory_region_add_subregion(get_system_memory(), OFFSET_CODE, &s->flash); 249 250 /* 251 * I/O 252 * 253 * 0x00 - 0x1f: Registers 254 * 0x20 - 0x5f: I/O memory 255 * 0x60 - 0xff: Extended I/O 256 */ 257 s->io = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); 258 qdev_prop_set_string(s->io, "name", "I/O"); 259 qdev_prop_set_uint64(s->io, "size", mc->io_size); 260 sysbus_realize_and_unref(SYS_BUS_DEVICE(s->io), &error_fatal); 261 sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->io), 0, OFFSET_DATA, -1234); 262 263 /* Power Reduction */ 264 for (i = 0; i < POWER_MAX; i++) { 265 int idx = POWER(i); 266 if (!mc->dev[idx].addr) { 267 continue; 268 } 269 devname = g_strdup_printf("power%zu", i); 270 object_initialize_child(OBJECT(dev), devname, &s->pwr[i], 271 TYPE_AVR_MASK); 272 sysbus_realize(SYS_BUS_DEVICE(&s->pwr[i]), &error_abort); 273 sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwr[i]), 0, 274 OFFSET_DATA + mc->dev[idx].addr); 275 g_free(devname); 276 } 277 278 /* GPIO */ 279 for (i = 0; i < GPIO_MAX; i++) { 280 int idx = GPIO(i); 281 if (!mc->dev[idx].addr) { 282 continue; 283 } 284 devname = g_strdup_printf("atmega-gpio-%c", 'a' + (char)i); 285 create_unimplemented_device(devname, 286 OFFSET_DATA + mc->dev[idx].addr, 3); 287 g_free(devname); 288 } 289 290 /* USART */ 291 for (i = 0; i < USART_MAX; i++) { 292 int idx = USART(i); 293 if (!mc->dev[idx].addr) { 294 continue; 295 } 296 devname = g_strdup_printf("usart%zu", i); 297 object_initialize_child(OBJECT(dev), devname, &s->usart[i], 298 TYPE_AVR_USART); 299 qdev_prop_set_chr(DEVICE(&s->usart[i]), "chardev", serial_hd(i)); 300 sbd = SYS_BUS_DEVICE(&s->usart[i]); 301 sysbus_realize(sbd, &error_abort); 302 sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[USART(i)].addr); 303 connect_peripheral_irq(mc, sbd, 0, cpudev, USART_RXC_IRQ(i)); 304 connect_peripheral_irq(mc, sbd, 1, cpudev, USART_DRE_IRQ(i)); 305 connect_peripheral_irq(mc, sbd, 2, cpudev, USART_TXC_IRQ(i)); 306 connect_power_reduction_gpio(s, mc, DEVICE(&s->usart[i]), idx); 307 g_free(devname); 308 } 309 310 /* Timer */ 311 for (i = 0; i < TIMER_MAX; i++) { 312 int idx = TIMER(i); 313 if (!mc->dev[idx].addr) { 314 continue; 315 } 316 if (!mc->dev[idx].is_timer16) { 317 create_unimplemented_device("avr-timer8", 318 OFFSET_DATA + mc->dev[idx].addr, 5); 319 create_unimplemented_device("avr-timer8-intmask", 320 OFFSET_DATA 321 + mc->dev[idx].intmask_addr, 1); 322 create_unimplemented_device("avr-timer8-intflag", 323 OFFSET_DATA 324 + mc->dev[idx].intflag_addr, 1); 325 continue; 326 } 327 devname = g_strdup_printf("timer%zu", i); 328 object_initialize_child(OBJECT(dev), devname, &s->timer[i], 329 TYPE_AVR_TIMER16); 330 object_property_set_uint(OBJECT(&s->timer[i]), "cpu-frequency-hz", 331 s->xtal_freq_hz, &error_abort); 332 sbd = SYS_BUS_DEVICE(&s->timer[i]); 333 sysbus_realize(sbd, &error_abort); 334 sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[idx].addr); 335 sysbus_mmio_map(sbd, 1, OFFSET_DATA + mc->dev[idx].intmask_addr); 336 sysbus_mmio_map(sbd, 2, OFFSET_DATA + mc->dev[idx].intflag_addr); 337 connect_peripheral_irq(mc, sbd, 0, cpudev, TIMER_CAPT_IRQ(i)); 338 connect_peripheral_irq(mc, sbd, 1, cpudev, TIMER_COMPA_IRQ(i)); 339 connect_peripheral_irq(mc, sbd, 2, cpudev, TIMER_COMPB_IRQ(i)); 340 connect_peripheral_irq(mc, sbd, 3, cpudev, TIMER_COMPC_IRQ(i)); 341 connect_peripheral_irq(mc, sbd, 4, cpudev, TIMER_OVF_IRQ(i)); 342 connect_power_reduction_gpio(s, mc, DEVICE(&s->timer[i]), idx); 343 g_free(devname); 344 } 345 346 create_unimplemented_device("avr-twi", OFFSET_DATA + 0x0b8, 6); 347 create_unimplemented_device("avr-adc", OFFSET_DATA + 0x078, 8); 348 create_unimplemented_device("avr-ext-mem-ctrl", OFFSET_DATA + 0x074, 2); 349 create_unimplemented_device("avr-watchdog", OFFSET_DATA + 0x060, 1); 350 create_unimplemented_device("avr-spi", OFFSET_DATA + 0x04c, 3); 351 create_unimplemented_device("avr-eeprom", OFFSET_DATA + 0x03f, 3); 352} 353 354static Property atmega_props[] = { 355 DEFINE_PROP_UINT64("xtal-frequency-hz", AtmegaMcuState, 356 xtal_freq_hz, 0), 357 DEFINE_PROP_END_OF_LIST() 358}; 359 360static void atmega_class_init(ObjectClass *oc, void *data) 361{ 362 DeviceClass *dc = DEVICE_CLASS(oc); 363 364 dc->realize = atmega_realize; 365 device_class_set_props(dc, atmega_props); 366 /* Reason: Mapped at fixed location on the system bus */ 367 dc->user_creatable = false; 368} 369 370static void atmega168_class_init(ObjectClass *oc, void *data) 371{ 372 AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); 373 374 amc->cpu_type = AVR_CPU_TYPE_NAME("avr5"); 375 amc->flash_size = 16 * KiB; 376 amc->eeprom_size = 512; 377 amc->sram_size = 1 * KiB; 378 amc->io_size = 256; 379 amc->gpio_count = 23; 380 amc->adc_count = 6; 381 amc->irq = irq168_328; 382 amc->dev = dev168_328; 383}; 384 385static void atmega328_class_init(ObjectClass *oc, void *data) 386{ 387 AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); 388 389 amc->cpu_type = AVR_CPU_TYPE_NAME("avr5"); 390 amc->flash_size = 32 * KiB; 391 amc->eeprom_size = 1 * KiB; 392 amc->sram_size = 2 * KiB; 393 amc->io_size = 256; 394 amc->gpio_count = 23; 395 amc->adc_count = 6; 396 amc->irq = irq168_328; 397 amc->dev = dev168_328; 398}; 399 400static void atmega1280_class_init(ObjectClass *oc, void *data) 401{ 402 AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); 403 404 amc->cpu_type = AVR_CPU_TYPE_NAME("avr51"); 405 amc->flash_size = 128 * KiB; 406 amc->eeprom_size = 4 * KiB; 407 amc->sram_size = 8 * KiB; 408 amc->io_size = 512; 409 amc->gpio_count = 86; 410 amc->adc_count = 16; 411 amc->irq = irq1280_2560; 412 amc->dev = dev1280_2560; 413}; 414 415static void atmega2560_class_init(ObjectClass *oc, void *data) 416{ 417 AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); 418 419 amc->cpu_type = AVR_CPU_TYPE_NAME("avr6"); 420 amc->flash_size = 256 * KiB; 421 amc->eeprom_size = 4 * KiB; 422 amc->sram_size = 8 * KiB; 423 amc->io_size = 512; 424 amc->gpio_count = 54; 425 amc->adc_count = 16; 426 amc->irq = irq1280_2560; 427 amc->dev = dev1280_2560; 428}; 429 430static const TypeInfo atmega_mcu_types[] = { 431 { 432 .name = TYPE_ATMEGA168_MCU, 433 .parent = TYPE_ATMEGA_MCU, 434 .class_init = atmega168_class_init, 435 }, { 436 .name = TYPE_ATMEGA328_MCU, 437 .parent = TYPE_ATMEGA_MCU, 438 .class_init = atmega328_class_init, 439 }, { 440 .name = TYPE_ATMEGA1280_MCU, 441 .parent = TYPE_ATMEGA_MCU, 442 .class_init = atmega1280_class_init, 443 }, { 444 .name = TYPE_ATMEGA2560_MCU, 445 .parent = TYPE_ATMEGA_MCU, 446 .class_init = atmega2560_class_init, 447 }, { 448 .name = TYPE_ATMEGA_MCU, 449 .parent = TYPE_SYS_BUS_DEVICE, 450 .instance_size = sizeof(AtmegaMcuState), 451 .class_size = sizeof(AtmegaMcuClass), 452 .class_init = atmega_class_init, 453 .abstract = true, 454 } 455}; 456 457DEFINE_TYPES(atmega_mcu_types)