| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ARM SBSA Reference Platform Embedded Controller | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * A device to allow PSCI running in the secure side of sbsa-ref machine | 
					
						
							|  |  |  |  * to communicate platform power states to qemu. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2020 Nuvia Inc | 
					
						
							|  |  |  |  * Written by Graeme Gregory <graeme@nuviainc.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-02-01 12:01:47 -08:00
										 |  |  |  * SPDX-License-Identifier: GPL-2.0-or-later | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "qemu/osdep.h"
 | 
					
						
							|  |  |  | #include "qemu/log.h"
 | 
					
						
							|  |  |  | #include "hw/sysbus.h"
 | 
					
						
							|  |  |  | #include "sysemu/runstate.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:03 +01:00
										 |  |  | typedef struct SECUREECState { | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  |     SysBusDevice parent_obj; | 
					
						
							|  |  |  |     MemoryRegion iomem; | 
					
						
							|  |  |  | } SECUREECState; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:03 +01:00
										 |  |  | #define TYPE_SBSA_SECURE_EC "sbsa-ec"
 | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:04 +01:00
										 |  |  | OBJECT_DECLARE_SIMPLE_TYPE(SECUREECState, SBSA_SECURE_EC) | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | enum sbsa_ec_powerstates { | 
					
						
							|  |  |  |     SBSA_EC_CMD_POWEROFF = 0x01, | 
					
						
							|  |  |  |     SBSA_EC_CMD_REBOOT = 0x02, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* No use for this currently */ | 
					
						
							|  |  |  |     qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers"); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sbsa_ec_write(void *opaque, hwaddr offset, | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:03 +01:00
										 |  |  |                           uint64_t value, unsigned size) | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (offset == 0) { /* PSCI machine power command register */ | 
					
						
							|  |  |  |         switch (value) { | 
					
						
							|  |  |  |         case SBSA_EC_CMD_POWEROFF: | 
					
						
							|  |  |  |             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case SBSA_EC_CMD_REBOOT: | 
					
						
							|  |  |  |             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             qemu_log_mask(LOG_GUEST_ERROR, | 
					
						
							|  |  |  |                           "sbsa-ec: unknown power command"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const MemoryRegionOps sbsa_ec_ops = { | 
					
						
							|  |  |  |     .read = sbsa_ec_read, | 
					
						
							|  |  |  |     .write = sbsa_ec_write, | 
					
						
							|  |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							|  |  |  |     .valid.min_access_size = 4, | 
					
						
							|  |  |  |     .valid.max_access_size = 4, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sbsa_ec_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:03 +01:00
										 |  |  |     SECUREECState *s = SBSA_SECURE_EC(obj); | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  |     SysBusDevice *dev = SYS_BUS_DEVICE(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec", | 
					
						
							|  |  |  |                           0x1000); | 
					
						
							|  |  |  |     sysbus_init_mmio(dev, &s->iomem); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sbsa_ec_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* No vmstate or reset required: device has no internal state */ | 
					
						
							|  |  |  |     dc->user_creatable = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo sbsa_ec_info = { | 
					
						
							| 
									
										
										
										
											2023-01-09 15:03:03 +01:00
										 |  |  |     .name          = TYPE_SBSA_SECURE_EC, | 
					
						
							| 
									
										
										
										
											2020-08-26 15:19:51 +01:00
										 |  |  |     .parent        = TYPE_SYS_BUS_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(SECUREECState), | 
					
						
							|  |  |  |     .instance_init = sbsa_ec_init, | 
					
						
							|  |  |  |     .class_init    = sbsa_ec_class_init, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sbsa_ec_register_type(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     type_register_static(&sbsa_ec_info); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type_init(sbsa_ec_register_type); |