1dccb92b5SGraeme Gregory /* 2dccb92b5SGraeme Gregory * ARM SBSA Reference Platform Embedded Controller 3dccb92b5SGraeme Gregory * 4dccb92b5SGraeme Gregory * A device to allow PSCI running in the secure side of sbsa-ref machine 5dccb92b5SGraeme Gregory * to communicate platform power states to qemu. 6dccb92b5SGraeme Gregory * 7dccb92b5SGraeme Gregory * Copyright (c) 2020 Nuvia Inc 8dccb92b5SGraeme Gregory * Written by Graeme Gregory <graeme@nuviainc.com> 9dccb92b5SGraeme Gregory * 105054ba10SRyan Finnie * SPDX-License-Identifier: GPL-2.0-or-later 11dccb92b5SGraeme Gregory */ 12dccb92b5SGraeme Gregory 13dccb92b5SGraeme Gregory #include "qemu/osdep.h" 14dccb92b5SGraeme Gregory #include "qemu/log.h" 15dccb92b5SGraeme Gregory #include "hw/sysbus.h" 16dccb92b5SGraeme Gregory #include "sysemu/runstate.h" 17dccb92b5SGraeme Gregory 18*97b49d35SPhilippe Mathieu-Daudé typedef struct SECUREECState { 19dccb92b5SGraeme Gregory SysBusDevice parent_obj; 20dccb92b5SGraeme Gregory MemoryRegion iomem; 21dccb92b5SGraeme Gregory } SECUREECState; 22dccb92b5SGraeme Gregory 23*97b49d35SPhilippe Mathieu-Daudé #define TYPE_SBSA_SECURE_EC "sbsa-ec" 24*97b49d35SPhilippe Mathieu-Daudé #define SBSA_SECURE_EC(obj) \ 25*97b49d35SPhilippe Mathieu-Daudé OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC) 26dccb92b5SGraeme Gregory 27dccb92b5SGraeme Gregory enum sbsa_ec_powerstates { 28dccb92b5SGraeme Gregory SBSA_EC_CMD_POWEROFF = 0x01, 29dccb92b5SGraeme Gregory SBSA_EC_CMD_REBOOT = 0x02, 30dccb92b5SGraeme Gregory }; 31dccb92b5SGraeme Gregory 32dccb92b5SGraeme Gregory static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size) 33dccb92b5SGraeme Gregory { 34dccb92b5SGraeme Gregory /* No use for this currently */ 35dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers"); 36dccb92b5SGraeme Gregory return 0; 37dccb92b5SGraeme Gregory } 38dccb92b5SGraeme Gregory 39dccb92b5SGraeme Gregory static void sbsa_ec_write(void *opaque, hwaddr offset, 40dccb92b5SGraeme Gregory uint64_t value, unsigned size) 41dccb92b5SGraeme Gregory { 42dccb92b5SGraeme Gregory if (offset == 0) { /* PSCI machine power command register */ 43dccb92b5SGraeme Gregory switch (value) { 44dccb92b5SGraeme Gregory case SBSA_EC_CMD_POWEROFF: 45dccb92b5SGraeme Gregory qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 46dccb92b5SGraeme Gregory break; 47dccb92b5SGraeme Gregory case SBSA_EC_CMD_REBOOT: 48dccb92b5SGraeme Gregory qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 49dccb92b5SGraeme Gregory break; 50dccb92b5SGraeme Gregory default: 51dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, 52dccb92b5SGraeme Gregory "sbsa-ec: unknown power command"); 53dccb92b5SGraeme Gregory } 54dccb92b5SGraeme Gregory } else { 55dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register"); 56dccb92b5SGraeme Gregory } 57dccb92b5SGraeme Gregory } 58dccb92b5SGraeme Gregory 59dccb92b5SGraeme Gregory static const MemoryRegionOps sbsa_ec_ops = { 60dccb92b5SGraeme Gregory .read = sbsa_ec_read, 61dccb92b5SGraeme Gregory .write = sbsa_ec_write, 62dccb92b5SGraeme Gregory .endianness = DEVICE_NATIVE_ENDIAN, 63dccb92b5SGraeme Gregory .valid.min_access_size = 4, 64dccb92b5SGraeme Gregory .valid.max_access_size = 4, 65dccb92b5SGraeme Gregory }; 66dccb92b5SGraeme Gregory 67dccb92b5SGraeme Gregory static void sbsa_ec_init(Object *obj) 68dccb92b5SGraeme Gregory { 69*97b49d35SPhilippe Mathieu-Daudé SECUREECState *s = SBSA_SECURE_EC(obj); 70dccb92b5SGraeme Gregory SysBusDevice *dev = SYS_BUS_DEVICE(obj); 71dccb92b5SGraeme Gregory 72dccb92b5SGraeme Gregory memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec", 73dccb92b5SGraeme Gregory 0x1000); 74dccb92b5SGraeme Gregory sysbus_init_mmio(dev, &s->iomem); 75dccb92b5SGraeme Gregory } 76dccb92b5SGraeme Gregory 77dccb92b5SGraeme Gregory static void sbsa_ec_class_init(ObjectClass *klass, void *data) 78dccb92b5SGraeme Gregory { 79dccb92b5SGraeme Gregory DeviceClass *dc = DEVICE_CLASS(klass); 80dccb92b5SGraeme Gregory 81dccb92b5SGraeme Gregory /* No vmstate or reset required: device has no internal state */ 82dccb92b5SGraeme Gregory dc->user_creatable = false; 83dccb92b5SGraeme Gregory } 84dccb92b5SGraeme Gregory 85dccb92b5SGraeme Gregory static const TypeInfo sbsa_ec_info = { 86*97b49d35SPhilippe Mathieu-Daudé .name = TYPE_SBSA_SECURE_EC, 87dccb92b5SGraeme Gregory .parent = TYPE_SYS_BUS_DEVICE, 88dccb92b5SGraeme Gregory .instance_size = sizeof(SECUREECState), 89dccb92b5SGraeme Gregory .instance_init = sbsa_ec_init, 90dccb92b5SGraeme Gregory .class_init = sbsa_ec_class_init, 91dccb92b5SGraeme Gregory }; 92dccb92b5SGraeme Gregory 93dccb92b5SGraeme Gregory static void sbsa_ec_register_type(void) 94dccb92b5SGraeme Gregory { 95dccb92b5SGraeme Gregory type_register_static(&sbsa_ec_info); 96dccb92b5SGraeme Gregory } 97dccb92b5SGraeme Gregory 98dccb92b5SGraeme Gregory type_init(sbsa_ec_register_type); 99