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
aspeed_otp_read(void * opaque,hwaddr offset,unsigned size)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
valid_program_data(uint32_t otp_addr,uint32_t value,uint32_t prog_bit)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
program_otpmem_data(void * opaque,uint32_t otp_addr,uint32_t prog_bit,uint32_t * value)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
aspeed_otp_write(void * opaque,hwaddr otp_addr,uint64_t val,unsigned size)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
aspeed_otp_init_storage(AspeedOTPState * s,Error ** errp)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
aspeed_otp_realize(DeviceState * dev,Error ** errp)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
aspeed_otp_class_init(ObjectClass * klass,const void * data)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
aspeed_otp_register_types(void)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