1 /* 2 * QEMU SiFive U OTP (One-Time Programmable) Memory interface 3 * 4 * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com> 5 * 6 * Simple model of the OTP to emulate register reads made by the SDK BSP 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms and conditions of the GNU General Public License, 10 * version 2 or later, as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qapi/error.h" 23 #include "hw/qdev-properties.h" 24 #include "hw/qdev-properties-system.h" 25 #include "hw/sysbus.h" 26 #include "qemu/log.h" 27 #include "qemu/module.h" 28 #include "hw/misc/sifive_u_otp.h" 29 #include "sysemu/blockdev.h" 30 #include "sysemu/block-backend.h" 31 32 #define WRITTEN_BIT_ON 0x1 33 34 #define SET_FUSEARRAY_BIT(map, i, off, bit) \ 35 map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off)) 36 37 #define GET_FUSEARRAY_BIT(map, i, off) \ 38 ((map[i] >> off) & 0x1) 39 40 static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) 41 { 42 SiFiveUOTPState *s = opaque; 43 44 switch (addr) { 45 case SIFIVE_U_OTP_PA: 46 return s->pa; 47 case SIFIVE_U_OTP_PAIO: 48 return s->paio; 49 case SIFIVE_U_OTP_PAS: 50 return s->pas; 51 case SIFIVE_U_OTP_PCE: 52 return s->pce; 53 case SIFIVE_U_OTP_PCLK: 54 return s->pclk; 55 case SIFIVE_U_OTP_PDIN: 56 return s->pdin; 57 case SIFIVE_U_OTP_PDOUT: 58 if ((s->pce & SIFIVE_U_OTP_PCE_EN) && 59 (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && 60 (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { 61 62 /* read from backend */ 63 if (s->blk) { 64 int32_t buf; 65 66 if (blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, 67 SIFIVE_U_OTP_FUSE_WORD) < 0) { 68 qemu_log_mask(LOG_GUEST_ERROR, 69 "read error index<%d>\n", s->pa); 70 return 0xff; 71 } 72 73 return buf; 74 } 75 76 return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; 77 } else { 78 return 0xff; 79 } 80 case SIFIVE_U_OTP_PDSTB: 81 return s->pdstb; 82 case SIFIVE_U_OTP_PPROG: 83 return s->pprog; 84 case SIFIVE_U_OTP_PTC: 85 return s->ptc; 86 case SIFIVE_U_OTP_PTM: 87 return s->ptm; 88 case SIFIVE_U_OTP_PTM_REP: 89 return s->ptm_rep; 90 case SIFIVE_U_OTP_PTR: 91 return s->ptr; 92 case SIFIVE_U_OTP_PTRIM: 93 return s->ptrim; 94 case SIFIVE_U_OTP_PWE: 95 return s->pwe; 96 } 97 98 qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", 99 __func__, addr); 100 return 0; 101 } 102 103 static void sifive_u_otp_write(void *opaque, hwaddr addr, 104 uint64_t val64, unsigned int size) 105 { 106 SiFiveUOTPState *s = opaque; 107 uint32_t val32 = (uint32_t)val64; 108 109 switch (addr) { 110 case SIFIVE_U_OTP_PA: 111 s->pa = val32 & SIFIVE_U_OTP_PA_MASK; 112 break; 113 case SIFIVE_U_OTP_PAIO: 114 s->paio = val32; 115 break; 116 case SIFIVE_U_OTP_PAS: 117 s->pas = val32; 118 break; 119 case SIFIVE_U_OTP_PCE: 120 s->pce = val32; 121 break; 122 case SIFIVE_U_OTP_PCLK: 123 s->pclk = val32; 124 break; 125 case SIFIVE_U_OTP_PDIN: 126 s->pdin = val32; 127 break; 128 case SIFIVE_U_OTP_PDOUT: 129 /* read-only */ 130 break; 131 case SIFIVE_U_OTP_PDSTB: 132 s->pdstb = val32; 133 break; 134 case SIFIVE_U_OTP_PPROG: 135 s->pprog = val32; 136 break; 137 case SIFIVE_U_OTP_PTC: 138 s->ptc = val32; 139 break; 140 case SIFIVE_U_OTP_PTM: 141 s->ptm = val32; 142 break; 143 case SIFIVE_U_OTP_PTM_REP: 144 s->ptm_rep = val32; 145 break; 146 case SIFIVE_U_OTP_PTR: 147 s->ptr = val32; 148 break; 149 case SIFIVE_U_OTP_PTRIM: 150 s->ptrim = val32; 151 break; 152 case SIFIVE_U_OTP_PWE: 153 s->pwe = val32 & SIFIVE_U_OTP_PWE_EN; 154 155 /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */ 156 if (s->pwe && !s->pas) { 157 if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) { 158 qemu_log_mask(LOG_GUEST_ERROR, 159 "write once error: idx<%u>, bit<%u>\n", 160 s->pa, s->paio); 161 break; 162 } 163 164 /* write bit data */ 165 SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); 166 167 /* write to backend */ 168 if (s->blk) { 169 if (blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, 170 &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 171 0) < 0) { 172 qemu_log_mask(LOG_GUEST_ERROR, 173 "write error index<%d>\n", s->pa); 174 } 175 } 176 177 /* update written bit */ 178 SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); 179 } 180 181 break; 182 default: 183 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx 184 " v=0x%x\n", __func__, addr, val32); 185 } 186 } 187 188 static const MemoryRegionOps sifive_u_otp_ops = { 189 .read = sifive_u_otp_read, 190 .write = sifive_u_otp_write, 191 .endianness = DEVICE_NATIVE_ENDIAN, 192 .valid = { 193 .min_access_size = 4, 194 .max_access_size = 4 195 } 196 }; 197 198 static Property sifive_u_otp_properties[] = { 199 DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), 200 DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk), 201 DEFINE_PROP_END_OF_LIST(), 202 }; 203 204 static void sifive_u_otp_realize(DeviceState *dev, Error **errp) 205 { 206 SiFiveUOTPState *s = SIFIVE_U_OTP(dev); 207 DriveInfo *dinfo; 208 209 memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, 210 TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); 211 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); 212 213 dinfo = drive_get_next(IF_NONE); 214 if (dinfo) { 215 int ret; 216 uint64_t perm; 217 int filesize; 218 BlockBackend *blk; 219 220 blk = blk_by_legacy_dinfo(dinfo); 221 filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD; 222 if (blk_getlength(blk) < filesize) { 223 error_setg(errp, "OTP drive size < 16K"); 224 return; 225 } 226 227 qdev_prop_set_drive_err(dev, "drive", blk, errp); 228 229 if (s->blk) { 230 perm = BLK_PERM_CONSISTENT_READ | 231 (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); 232 ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); 233 if (ret < 0) { 234 return; 235 } 236 237 if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { 238 error_setg(errp, "failed to read the initial flash content"); 239 } 240 } 241 } 242 } 243 244 static void sifive_u_otp_reset(DeviceState *dev) 245 { 246 SiFiveUOTPState *s = SIFIVE_U_OTP(dev); 247 248 /* Initialize all fuses' initial value to 0xFFs */ 249 memset(s->fuse, 0xff, sizeof(s->fuse)); 250 251 /* Make a valid content of serial number */ 252 s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; 253 s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); 254 255 if (s->blk) { 256 /* Put serial number to backend as well*/ 257 uint32_t serial_data; 258 int index = SIFIVE_U_OTP_SERIAL_ADDR; 259 260 serial_data = s->serial; 261 if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, 262 &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { 263 qemu_log_mask(LOG_GUEST_ERROR, 264 "write error index<%d>\n", index); 265 } 266 267 serial_data = ~(s->serial); 268 if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, 269 &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { 270 qemu_log_mask(LOG_GUEST_ERROR, 271 "write error index<%d>\n", index + 1); 272 } 273 } 274 275 /* Initialize write-once map */ 276 memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo)); 277 } 278 279 static void sifive_u_otp_class_init(ObjectClass *klass, void *data) 280 { 281 DeviceClass *dc = DEVICE_CLASS(klass); 282 283 device_class_set_props(dc, sifive_u_otp_properties); 284 dc->realize = sifive_u_otp_realize; 285 dc->reset = sifive_u_otp_reset; 286 } 287 288 static const TypeInfo sifive_u_otp_info = { 289 .name = TYPE_SIFIVE_U_OTP, 290 .parent = TYPE_SYS_BUS_DEVICE, 291 .instance_size = sizeof(SiFiveUOTPState), 292 .class_init = sifive_u_otp_class_init, 293 }; 294 295 static void sifive_u_otp_register_types(void) 296 { 297 type_register_static(&sifive_u_otp_info); 298 } 299 300 type_init(sifive_u_otp_register_types) 301