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 #include "hw/nvram/trace.h" 16 17 static uint64_t aspeed_otp_read(void *opaque, hwaddr offset, unsigned size) 18 { 19 AspeedOTPState *s = opaque; 20 uint64_t val = 0; 21 22 memcpy(&val, s->storage + offset, size); 23 24 return val; 25 } 26 27 static bool valid_program_data(uint32_t otp_addr, 28 uint32_t value, uint32_t prog_bit) 29 { 30 uint32_t programmed_bits, has_programmable_bits; 31 bool is_odd = otp_addr & 1; 32 33 /* 34 * prog_bit uses 0s to indicate target bits to program: 35 * - if OTP word is even-indexed, programmed bits flip 0->1 36 * - if odd, bits flip 1->0 37 * Bit programming is one-way only and irreversible. 38 */ 39 if (is_odd) { 40 programmed_bits = ~value & prog_bit; 41 } else { 42 programmed_bits = value & (~prog_bit); 43 } 44 45 /* If any bit can be programmed, accept the request */ 46 has_programmable_bits = value ^ (~prog_bit); 47 48 if (programmed_bits) { 49 trace_aspeed_otp_prog_conflict(otp_addr, programmed_bits); 50 for (int i = 0; i < 32; ++i) { 51 if (programmed_bits & (1U << i)) { 52 trace_aspeed_otp_prog_bit(i); 53 } 54 } 55 } 56 57 return has_programmable_bits != 0; 58 } 59 60 static bool program_otpmem_data(void *opaque, uint32_t otp_addr, 61 uint32_t prog_bit, uint32_t *value) 62 { 63 AspeedOTPState *s = opaque; 64 bool is_odd = otp_addr & 1; 65 uint32_t otp_offset = otp_addr << 2; 66 67 memcpy(value, s->storage + otp_offset, sizeof(uint32_t)); 68 69 if (!valid_program_data(otp_addr, *value, prog_bit)) { 70 return false; 71 } 72 73 if (is_odd) { 74 *value &= ~prog_bit; 75 } else { 76 *value |= ~prog_bit; 77 } 78 79 return true; 80 } 81 82 static void aspeed_otp_write(void *opaque, hwaddr otp_addr, 83 uint64_t val, unsigned size) 84 { 85 AspeedOTPState *s = opaque; 86 uint32_t otp_offset, value; 87 88 if (!program_otpmem_data(s, otp_addr, val, &value)) { 89 qemu_log_mask(LOG_GUEST_ERROR, 90 "%s: Failed to program data, value = %x, bit = %"PRIx64"\n", 91 __func__, value, val); 92 return; 93 } 94 95 otp_offset = otp_addr << 2; 96 memcpy(s->storage + otp_offset, &value, size); 97 98 if (s->blk) { 99 if (blk_pwrite(s->blk, otp_offset, size, &value, 0) < 0) { 100 qemu_log_mask(LOG_GUEST_ERROR, 101 "%s: Failed to write %x to %x\n", 102 __func__, value, otp_offset); 103 104 return; 105 } 106 } 107 trace_aspeed_otp_prog(otp_offset, val, value); 108 } 109 110 static bool aspeed_otp_init_storage(AspeedOTPState *s, Error **errp) 111 { 112 uint32_t *p; 113 int i, num; 114 uint64_t perm; 115 116 if (s->blk) { 117 perm = BLK_PERM_CONSISTENT_READ | 118 (blk_supports_write_perm(s->blk) ? BLK_PERM_WRITE : 0); 119 if (blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp) < 0) { 120 return false; 121 } 122 if (blk_pread(s->blk, 0, s->size, s->storage, 0) < 0) { 123 error_setg(errp, "Failed to read the initial flash content"); 124 return false; 125 } 126 } else { 127 num = s->size / sizeof(uint32_t); 128 p = (uint32_t *)s->storage; 129 for (i = 0; i < num; i++) { 130 p[i] = (i % 2 == 0) ? 0x00000000 : 0xFFFFFFFF; 131 } 132 } 133 return true; 134 } 135 136 static const MemoryRegionOps aspeed_otp_ops = { 137 .read = aspeed_otp_read, 138 .write = aspeed_otp_write, 139 .endianness = DEVICE_LITTLE_ENDIAN, 140 .valid.min_access_size = 1, 141 .valid.max_access_size = 4, 142 .valid.unaligned = true, 143 .impl.unaligned = true 144 }; 145 146 static void aspeed_otp_realize(DeviceState *dev, Error **errp) 147 { 148 AspeedOTPState *s = ASPEED_OTP(dev); 149 150 if (s->size == 0) { 151 error_setg(errp, "aspeed.otp: 'size' property must be set"); 152 return; 153 } 154 155 s->storage = blk_blockalign(s->blk, s->size); 156 157 if (!aspeed_otp_init_storage(s, errp)) { 158 return; 159 } 160 161 memory_region_init_io(&s->mmio, OBJECT(dev), &aspeed_otp_ops, 162 s, "aspeed.otp", s->size); 163 address_space_init(&s->as, &s->mmio, NULL); 164 } 165 166 static const Property aspeed_otp_properties[] = { 167 DEFINE_PROP_UINT64("size", AspeedOTPState, size, 0), 168 DEFINE_PROP_DRIVE("drive", AspeedOTPState, blk), 169 }; 170 171 static void aspeed_otp_class_init(ObjectClass *klass, const void *data) 172 { 173 DeviceClass *dc = DEVICE_CLASS(klass); 174 dc->realize = aspeed_otp_realize; 175 device_class_set_props(dc, aspeed_otp_properties); 176 } 177 178 static const TypeInfo aspeed_otp_info = { 179 .name = TYPE_ASPEED_OTP, 180 .parent = TYPE_DEVICE, 181 .instance_size = sizeof(AspeedOTPState), 182 .class_init = aspeed_otp_class_init, 183 }; 184 185 static void aspeed_otp_register_types(void) 186 { 187 type_register_static(&aspeed_otp_info); 188 } 189 190 type_init(aspeed_otp_register_types) 191