qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

stm32f100_soc.c (8360B)


      1 /*
      2  * STM32F100 SoC
      3  *
      4  * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
      5  * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  */
     25 
     26 #include "qemu/osdep.h"
     27 #include "qapi/error.h"
     28 #include "qemu/module.h"
     29 #include "hw/arm/boot.h"
     30 #include "exec/address-spaces.h"
     31 #include "hw/arm/stm32f100_soc.h"
     32 #include "hw/qdev-properties.h"
     33 #include "hw/qdev-clock.h"
     34 #include "hw/misc/unimp.h"
     35 #include "sysemu/sysemu.h"
     36 
     37 /* stm32f100_soc implementation is derived from stm32f205_soc */
     38 
     39 static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400,
     40     0x40004800 };
     41 static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800 };
     42 
     43 static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39};
     44 static const int spi_irq[STM_NUM_SPIS] = {35, 36};
     45 
     46 static void stm32f100_soc_initfn(Object *obj)
     47 {
     48     STM32F100State *s = STM32F100_SOC(obj);
     49     int i;
     50 
     51     object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
     52 
     53     for (i = 0; i < STM_NUM_USARTS; i++) {
     54         object_initialize_child(obj, "usart[*]", &s->usart[i],
     55                                 TYPE_STM32F2XX_USART);
     56     }
     57 
     58     for (i = 0; i < STM_NUM_SPIS; i++) {
     59         object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
     60     }
     61 
     62     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
     63     s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
     64 }
     65 
     66 static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
     67 {
     68     STM32F100State *s = STM32F100_SOC(dev_soc);
     69     DeviceState *dev, *armv7m;
     70     SysBusDevice *busdev;
     71     int i;
     72 
     73     MemoryRegion *system_memory = get_system_memory();
     74 
     75     /*
     76      * We use s->refclk internally and only define it with qdev_init_clock_in()
     77      * so it is correctly parented and not leaked on an init/deinit; it is not
     78      * intended as an externally exposed clock.
     79      */
     80     if (clock_has_source(s->refclk)) {
     81         error_setg(errp, "refclk clock must not be wired up by the board code");
     82         return;
     83     }
     84 
     85     if (!clock_has_source(s->sysclk)) {
     86         error_setg(errp, "sysclk clock must be wired up by the board code");
     87         return;
     88     }
     89 
     90     /*
     91      * TODO: ideally we should model the SoC RCC and its ability to
     92      * change the sysclk frequency and define different sysclk sources.
     93      */
     94 
     95     /* The refclk always runs at frequency HCLK / 8 */
     96     clock_set_mul_div(s->refclk, 8, 1);
     97     clock_set_source(s->refclk, s->sysclk);
     98 
     99     /*
    100      * Init flash region
    101      * Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
    102      */
    103     memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F100.flash",
    104                            FLASH_SIZE, &error_fatal);
    105     memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
    106                              "STM32F100.flash.alias", &s->flash, 0, FLASH_SIZE);
    107     memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
    108     memory_region_add_subregion(system_memory, 0, &s->flash_alias);
    109 
    110     /* Init SRAM region */
    111     memory_region_init_ram(&s->sram, NULL, "STM32F100.sram", SRAM_SIZE,
    112                            &error_fatal);
    113     memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
    114 
    115     /* Init ARMv7m */
    116     armv7m = DEVICE(&s->armv7m);
    117     qdev_prop_set_uint32(armv7m, "num-irq", 61);
    118     qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
    119     qdev_prop_set_bit(armv7m, "enable-bitband", true);
    120     qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
    121     qdev_connect_clock_in(armv7m, "refclk", s->refclk);
    122     object_property_set_link(OBJECT(&s->armv7m), "memory",
    123                              OBJECT(get_system_memory()), &error_abort);
    124     if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
    125         return;
    126     }
    127 
    128     /* Attach UART (uses USART registers) and USART controllers */
    129     for (i = 0; i < STM_NUM_USARTS; i++) {
    130         dev = DEVICE(&(s->usart[i]));
    131         qdev_prop_set_chr(dev, "chardev", serial_hd(i));
    132         if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) {
    133             return;
    134         }
    135         busdev = SYS_BUS_DEVICE(dev);
    136         sysbus_mmio_map(busdev, 0, usart_addr[i]);
    137         sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
    138     }
    139 
    140     /* SPI 1 and 2 */
    141     for (i = 0; i < STM_NUM_SPIS; i++) {
    142         dev = DEVICE(&(s->spi[i]));
    143         if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
    144             return;
    145         }
    146         busdev = SYS_BUS_DEVICE(dev);
    147         sysbus_mmio_map(busdev, 0, spi_addr[i]);
    148         sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
    149     }
    150 
    151     create_unimplemented_device("timer[2]",  0x40000000, 0x400);
    152     create_unimplemented_device("timer[3]",  0x40000400, 0x400);
    153     create_unimplemented_device("timer[4]",  0x40000800, 0x400);
    154     create_unimplemented_device("timer[6]",  0x40001000, 0x400);
    155     create_unimplemented_device("timer[7]",  0x40001400, 0x400);
    156     create_unimplemented_device("RTC",       0x40002800, 0x400);
    157     create_unimplemented_device("WWDG",      0x40002C00, 0x400);
    158     create_unimplemented_device("IWDG",      0x40003000, 0x400);
    159     create_unimplemented_device("I2C1",      0x40005400, 0x400);
    160     create_unimplemented_device("I2C2",      0x40005800, 0x400);
    161     create_unimplemented_device("BKP",       0x40006C00, 0x400);
    162     create_unimplemented_device("PWR",       0x40007000, 0x400);
    163     create_unimplemented_device("DAC",       0x40007400, 0x400);
    164     create_unimplemented_device("CEC",       0x40007800, 0x400);
    165     create_unimplemented_device("AFIO",      0x40010000, 0x400);
    166     create_unimplemented_device("EXTI",      0x40010400, 0x400);
    167     create_unimplemented_device("GPIOA",     0x40010800, 0x400);
    168     create_unimplemented_device("GPIOB",     0x40010C00, 0x400);
    169     create_unimplemented_device("GPIOC",     0x40011000, 0x400);
    170     create_unimplemented_device("GPIOD",     0x40011400, 0x400);
    171     create_unimplemented_device("GPIOE",     0x40011800, 0x400);
    172     create_unimplemented_device("ADC1",      0x40012400, 0x400);
    173     create_unimplemented_device("timer[1]",  0x40012C00, 0x400);
    174     create_unimplemented_device("timer[15]", 0x40014000, 0x400);
    175     create_unimplemented_device("timer[16]", 0x40014400, 0x400);
    176     create_unimplemented_device("timer[17]", 0x40014800, 0x400);
    177     create_unimplemented_device("DMA",       0x40020000, 0x400);
    178     create_unimplemented_device("RCC",       0x40021000, 0x400);
    179     create_unimplemented_device("Flash Int", 0x40022000, 0x400);
    180     create_unimplemented_device("CRC",       0x40023000, 0x400);
    181 }
    182 
    183 static Property stm32f100_soc_properties[] = {
    184     DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type),
    185     DEFINE_PROP_END_OF_LIST(),
    186 };
    187 
    188 static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
    189 {
    190     DeviceClass *dc = DEVICE_CLASS(klass);
    191 
    192     dc->realize = stm32f100_soc_realize;
    193     device_class_set_props(dc, stm32f100_soc_properties);
    194 }
    195 
    196 static const TypeInfo stm32f100_soc_info = {
    197     .name          = TYPE_STM32F100_SOC,
    198     .parent        = TYPE_SYS_BUS_DEVICE,
    199     .instance_size = sizeof(STM32F100State),
    200     .instance_init = stm32f100_soc_initfn,
    201     .class_init    = stm32f100_soc_class_init,
    202 };
    203 
    204 static void stm32f100_soc_types(void)
    205 {
    206     type_register_static(&stm32f100_soc_info);
    207 }
    208 
    209 type_init(stm32f100_soc_types)