1 /* 2 * ASPEED OTP (One-Time Programmable) memory 3 * 4 * Copyright (C) 2025 Aspeed 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 "system/block-backend.h" 13 #include "hw/qdev-properties.h" 14 #include "hw/nvram/aspeed_otp.h" 15 16 static uint64_t aspeed_otp_read(void *opaque, hwaddr offset, unsigned size) 17 { 18 AspeedOTPState *s = opaque; 19 uint64_t val = 0; 20 21 memcpy(&val, s->storage + offset, size); 22 23 return val; 24 } 25 26 static void aspeed_otp_write(void *opaque, hwaddr otp_addr, 27 uint64_t val, unsigned size) 28 { 29 AspeedOTPState *s = opaque; 30 31 memcpy(s->storage + otp_addr, &val, size); 32 } 33 34 static bool aspeed_otp_init_storage(AspeedOTPState *s, Error **errp) 35 { 36 uint32_t *p; 37 int i, num; 38 39 num = s->size / sizeof(uint32_t); 40 p = (uint32_t *)s->storage; 41 for (i = 0; i < num; i++) { 42 p[i] = (i % 2 == 0) ? 0x00000000 : 0xFFFFFFFF; 43 } 44 45 return true; 46 } 47 48 static const MemoryRegionOps aspeed_otp_ops = { 49 .read = aspeed_otp_read, 50 .write = aspeed_otp_write, 51 .endianness = DEVICE_LITTLE_ENDIAN, 52 .valid.min_access_size = 1, 53 .valid.max_access_size = 4, 54 }; 55 56 static void aspeed_otp_realize(DeviceState *dev, Error **errp) 57 { 58 AspeedOTPState *s = ASPEED_OTP(dev); 59 60 if (s->size == 0) { 61 error_setg(errp, "aspeed.otp: 'size' property must be set"); 62 return; 63 } 64 65 s->storage = blk_blockalign(s->blk, s->size); 66 67 if (!aspeed_otp_init_storage(s, errp)) { 68 return; 69 } 70 71 memory_region_init_io(&s->mmio, OBJECT(dev), &aspeed_otp_ops, 72 s, "aspeed.otp", s->size); 73 address_space_init(&s->as, &s->mmio, NULL); 74 } 75 76 static const Property aspeed_otp_properties[] = { 77 DEFINE_PROP_UINT64("size", AspeedOTPState, size, 0), 78 }; 79 80 static void aspeed_otp_class_init(ObjectClass *klass, const void *data) 81 { 82 DeviceClass *dc = DEVICE_CLASS(klass); 83 dc->realize = aspeed_otp_realize; 84 device_class_set_props(dc, aspeed_otp_properties); 85 } 86 87 static const TypeInfo aspeed_otp_info = { 88 .name = TYPE_ASPEED_OTP, 89 .parent = TYPE_DEVICE, 90 .instance_size = sizeof(AspeedOTPState), 91 .class_init = aspeed_otp_class_init, 92 }; 93 94 static void aspeed_otp_register_types(void) 95 { 96 type_register_static(&aspeed_otp_info); 97 } 98 99 type_init(aspeed_otp_register_types) 100