qemu

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

bcm2835_thermal.c (3517B)


      1 /*
      2  * BCM2835 dummy thermal sensor
      3  *
      4  * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
      5  *
      6  * SPDX-License-Identifier: GPL-2.0-or-later
      7  */
      8 
      9 #include "qemu/osdep.h"
     10 #include "qemu/log.h"
     11 #include "qapi/error.h"
     12 #include "hw/misc/bcm2835_thermal.h"
     13 #include "hw/registerfields.h"
     14 #include "migration/vmstate.h"
     15 
     16 REG32(CTL, 0)
     17 FIELD(CTL, POWER_DOWN, 0, 1)
     18 FIELD(CTL, RESET, 1, 1)
     19 FIELD(CTL, BANDGAP_CTRL, 2, 3)
     20 FIELD(CTL, INTERRUPT_ENABLE, 5, 1)
     21 FIELD(CTL, DIRECT, 6, 1)
     22 FIELD(CTL, INTERRUPT_CLEAR, 7, 1)
     23 FIELD(CTL, HOLD, 8, 10)
     24 FIELD(CTL, RESET_DELAY, 18, 8)
     25 FIELD(CTL, REGULATOR_ENABLE, 26, 1)
     26 
     27 REG32(STAT, 4)
     28 FIELD(STAT, DATA, 0, 10)
     29 FIELD(STAT, VALID, 10, 1)
     30 FIELD(STAT, INTERRUPT, 11, 1)
     31 
     32 #define THERMAL_OFFSET_C 412
     33 #define THERMAL_COEFF  (-0.538f)
     34 
     35 static uint16_t bcm2835_thermal_temp2adc(int temp_C)
     36 {
     37     return (temp_C - THERMAL_OFFSET_C) / THERMAL_COEFF;
     38 }
     39 
     40 static uint64_t bcm2835_thermal_read(void *opaque, hwaddr addr, unsigned size)
     41 {
     42     Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
     43     uint32_t val = 0;
     44 
     45     switch (addr) {
     46     case A_CTL:
     47         val = s->ctl;
     48         break;
     49     case A_STAT:
     50         /* Temperature is constantly 25°C. */
     51         val = FIELD_DP32(bcm2835_thermal_temp2adc(25), STAT, VALID, true);
     52         break;
     53     default:
     54         /* MemoryRegionOps are aligned, so this can not happen. */
     55         g_assert_not_reached();
     56     }
     57     return val;
     58 }
     59 
     60 static void bcm2835_thermal_write(void *opaque, hwaddr addr,
     61                                   uint64_t value, unsigned size)
     62 {
     63     Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
     64 
     65     switch (addr) {
     66     case A_CTL:
     67         s->ctl = value;
     68         break;
     69     case A_STAT:
     70         qemu_log_mask(LOG_GUEST_ERROR, "%s: write 0x%" PRIx64
     71                                        " to 0x%" HWADDR_PRIx "\n",
     72                        __func__, value, addr);
     73         break;
     74     default:
     75         /* MemoryRegionOps are aligned, so this can not happen. */
     76         g_assert_not_reached();
     77     }
     78 }
     79 
     80 static const MemoryRegionOps bcm2835_thermal_ops = {
     81     .read = bcm2835_thermal_read,
     82     .write = bcm2835_thermal_write,
     83     .impl.max_access_size = 4,
     84     .valid.min_access_size = 4,
     85     .endianness = DEVICE_NATIVE_ENDIAN,
     86 };
     87 
     88 static void bcm2835_thermal_reset(DeviceState *dev)
     89 {
     90     Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
     91 
     92     s->ctl = 0;
     93 }
     94 
     95 static void bcm2835_thermal_realize(DeviceState *dev, Error **errp)
     96 {
     97     Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
     98 
     99     memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_thermal_ops,
    100                           s, TYPE_BCM2835_THERMAL, 8);
    101     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
    102 }
    103 
    104 static const VMStateDescription bcm2835_thermal_vmstate = {
    105     .name = "bcm2835_thermal",
    106     .version_id = 1,
    107     .minimum_version_id = 1,
    108     .fields = (VMStateField[]) {
    109         VMSTATE_UINT32(ctl, Bcm2835ThermalState),
    110         VMSTATE_END_OF_LIST()
    111     }
    112 };
    113 
    114 static void bcm2835_thermal_class_init(ObjectClass *klass, void *data)
    115 {
    116     DeviceClass *dc = DEVICE_CLASS(klass);
    117 
    118     dc->realize = bcm2835_thermal_realize;
    119     dc->reset = bcm2835_thermal_reset;
    120     dc->vmsd = &bcm2835_thermal_vmstate;
    121 }
    122 
    123 static const TypeInfo bcm2835_thermal_info = {
    124     .name = TYPE_BCM2835_THERMAL,
    125     .parent = TYPE_SYS_BUS_DEVICE,
    126     .instance_size = sizeof(Bcm2835ThermalState),
    127     .class_init = bcm2835_thermal_class_init,
    128 };
    129 
    130 static void bcm2835_thermal_register_types(void)
    131 {
    132     type_register_static(&bcm2835_thermal_info);
    133 }
    134 
    135 type_init(bcm2835_thermal_register_types)