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" 16*32cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h" 17dccb92b5SGraeme Gregory 1897b49d35SPhilippe Mathieu-Daudé typedef struct SECUREECState { 19dccb92b5SGraeme Gregory SysBusDevice parent_obj; 20dccb92b5SGraeme Gregory MemoryRegion iomem; 21dccb92b5SGraeme Gregory } SECUREECState; 22dccb92b5SGraeme Gregory 2397b49d35SPhilippe Mathieu-Daudé #define TYPE_SBSA_SECURE_EC "sbsa-ec" 2495700465SPhilippe Mathieu-Daudé OBJECT_DECLARE_SIMPLE_TYPE(SECUREECState, SBSA_SECURE_EC) 25dccb92b5SGraeme Gregory 26dccb92b5SGraeme Gregory enum sbsa_ec_powerstates { 27dccb92b5SGraeme Gregory SBSA_EC_CMD_POWEROFF = 0x01, 28dccb92b5SGraeme Gregory SBSA_EC_CMD_REBOOT = 0x02, 29dccb92b5SGraeme Gregory }; 30dccb92b5SGraeme Gregory 31dccb92b5SGraeme Gregory static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size) 32dccb92b5SGraeme Gregory { 33dccb92b5SGraeme Gregory /* No use for this currently */ 34dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers"); 35dccb92b5SGraeme Gregory return 0; 36dccb92b5SGraeme Gregory } 37dccb92b5SGraeme Gregory 38dccb92b5SGraeme Gregory static void sbsa_ec_write(void *opaque, hwaddr offset, 39dccb92b5SGraeme Gregory uint64_t value, unsigned size) 40dccb92b5SGraeme Gregory { 41dccb92b5SGraeme Gregory if (offset == 0) { /* PSCI machine power command register */ 42dccb92b5SGraeme Gregory switch (value) { 43dccb92b5SGraeme Gregory case SBSA_EC_CMD_POWEROFF: 44dccb92b5SGraeme Gregory qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 45dccb92b5SGraeme Gregory break; 46dccb92b5SGraeme Gregory case SBSA_EC_CMD_REBOOT: 47dccb92b5SGraeme Gregory qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 48dccb92b5SGraeme Gregory break; 49dccb92b5SGraeme Gregory default: 50dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, 51dccb92b5SGraeme Gregory "sbsa-ec: unknown power command"); 52dccb92b5SGraeme Gregory } 53dccb92b5SGraeme Gregory } else { 54dccb92b5SGraeme Gregory qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register"); 55dccb92b5SGraeme Gregory } 56dccb92b5SGraeme Gregory } 57dccb92b5SGraeme Gregory 58dccb92b5SGraeme Gregory static const MemoryRegionOps sbsa_ec_ops = { 59dccb92b5SGraeme Gregory .read = sbsa_ec_read, 60dccb92b5SGraeme Gregory .write = sbsa_ec_write, 61dccb92b5SGraeme Gregory .endianness = DEVICE_NATIVE_ENDIAN, 62dccb92b5SGraeme Gregory .valid.min_access_size = 4, 63dccb92b5SGraeme Gregory .valid.max_access_size = 4, 64dccb92b5SGraeme Gregory }; 65dccb92b5SGraeme Gregory 66dccb92b5SGraeme Gregory static void sbsa_ec_init(Object *obj) 67dccb92b5SGraeme Gregory { 6897b49d35SPhilippe Mathieu-Daudé SECUREECState *s = SBSA_SECURE_EC(obj); 69dccb92b5SGraeme Gregory SysBusDevice *dev = SYS_BUS_DEVICE(obj); 70dccb92b5SGraeme Gregory 71dccb92b5SGraeme Gregory memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec", 72dccb92b5SGraeme Gregory 0x1000); 73dccb92b5SGraeme Gregory sysbus_init_mmio(dev, &s->iomem); 74dccb92b5SGraeme Gregory } 75dccb92b5SGraeme Gregory 76dccb92b5SGraeme Gregory static void sbsa_ec_class_init(ObjectClass *klass, void *data) 77dccb92b5SGraeme Gregory { 78dccb92b5SGraeme Gregory DeviceClass *dc = DEVICE_CLASS(klass); 79dccb92b5SGraeme Gregory 80dccb92b5SGraeme Gregory /* No vmstate or reset required: device has no internal state */ 81dccb92b5SGraeme Gregory dc->user_creatable = false; 82dccb92b5SGraeme Gregory } 83dccb92b5SGraeme Gregory 84dccb92b5SGraeme Gregory static const TypeInfo sbsa_ec_info = { 8597b49d35SPhilippe Mathieu-Daudé .name = TYPE_SBSA_SECURE_EC, 86dccb92b5SGraeme Gregory .parent = TYPE_SYS_BUS_DEVICE, 87dccb92b5SGraeme Gregory .instance_size = sizeof(SECUREECState), 88dccb92b5SGraeme Gregory .instance_init = sbsa_ec_init, 89dccb92b5SGraeme Gregory .class_init = sbsa_ec_class_init, 90dccb92b5SGraeme Gregory }; 91dccb92b5SGraeme Gregory 92dccb92b5SGraeme Gregory static void sbsa_ec_register_type(void) 93dccb92b5SGraeme Gregory { 94dccb92b5SGraeme Gregory type_register_static(&sbsa_ec_info); 95dccb92b5SGraeme Gregory } 96dccb92b5SGraeme Gregory 97dccb92b5SGraeme Gregory type_init(sbsa_ec_register_type); 98