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/sysbus.h" 25 #include "qemu/log.h" 26 #include "qemu/module.h" 27 #include "hw/misc/sifive_u_otp.h" 28 #include "sysemu/blockdev.h" 29 #include "sysemu/block-backend.h" 30 31 #define WRITTEN_BIT_ON 0x1 32 33 #define SET_FUSEARRAY_BIT(map, i, off, bit) \ 34 map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off)) 35 36 #define GET_FUSEARRAY_BIT(map, i, off) \ 37 ((map[i] >> off) & 0x1) 38 39 static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) 40 { 41 SiFiveUOTPState *s = opaque; 42 43 switch (addr) { 44 case SIFIVE_U_OTP_PA: 45 return s->pa; 46 case SIFIVE_U_OTP_PAIO: 47 return s->paio; 48 case SIFIVE_U_OTP_PAS: 49 return s->pas; 50 case SIFIVE_U_OTP_PCE: 51 return s->pce; 52 case SIFIVE_U_OTP_PCLK: 53 return s->pclk; 54 case SIFIVE_U_OTP_PDIN: 55 return s->pdin; 56 case SIFIVE_U_OTP_PDOUT: 57 if ((s->pce & SIFIVE_U_OTP_PCE_EN) && 58 (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && 59 (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { 60 61 /* read from backend */ 62 if (s->blk) { 63 int32_t buf; 64 65 blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, 66 SIFIVE_U_OTP_FUSE_WORD); 67 return buf; 68 } 69 70 return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; 71 } else { 72 return 0xff; 73 } 74 case SIFIVE_U_OTP_PDSTB: 75 return s->pdstb; 76 case SIFIVE_U_OTP_PPROG: 77 return s->pprog; 78 case SIFIVE_U_OTP_PTC: 79 return s->ptc; 80 case SIFIVE_U_OTP_PTM: 81 return s->ptm; 82 case SIFIVE_U_OTP_PTM_REP: 83 return s->ptm_rep; 84 case SIFIVE_U_OTP_PTR: 85 return s->ptr; 86 case SIFIVE_U_OTP_PTRIM: 87 return s->ptrim; 88 case SIFIVE_U_OTP_PWE: 89 return s->pwe; 90 } 91 92 qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", 93 __func__, addr); 94 return 0; 95 } 96 97 static void sifive_u_otp_write(void *opaque, hwaddr addr, 98 uint64_t val64, unsigned int size) 99 { 100 SiFiveUOTPState *s = opaque; 101 uint32_t val32 = (uint32_t)val64; 102 103 switch (addr) { 104 case SIFIVE_U_OTP_PA: 105 s->pa = val32 & SIFIVE_U_OTP_PA_MASK; 106 break; 107 case SIFIVE_U_OTP_PAIO: 108 s->paio = val32; 109 break; 110 case SIFIVE_U_OTP_PAS: 111 s->pas = val32; 112 break; 113 case SIFIVE_U_OTP_PCE: 114 s->pce = val32; 115 break; 116 case SIFIVE_U_OTP_PCLK: 117 s->pclk = val32; 118 break; 119 case SIFIVE_U_OTP_PDIN: 120 s->pdin = val32; 121 break; 122 case SIFIVE_U_OTP_PDOUT: 123 /* read-only */ 124 break; 125 case SIFIVE_U_OTP_PDSTB: 126 s->pdstb = val32; 127 break; 128 case SIFIVE_U_OTP_PPROG: 129 s->pprog = val32; 130 break; 131 case SIFIVE_U_OTP_PTC: 132 s->ptc = val32; 133 break; 134 case SIFIVE_U_OTP_PTM: 135 s->ptm = val32; 136 break; 137 case SIFIVE_U_OTP_PTM_REP: 138 s->ptm_rep = val32; 139 break; 140 case SIFIVE_U_OTP_PTR: 141 s->ptr = val32; 142 break; 143 case SIFIVE_U_OTP_PTRIM: 144 s->ptrim = val32; 145 break; 146 case SIFIVE_U_OTP_PWE: 147 s->pwe = val32 & SIFIVE_U_OTP_PWE_EN; 148 149 /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */ 150 if (s->pwe && !s->pas) { 151 if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) { 152 qemu_log_mask(LOG_GUEST_ERROR, 153 "write once error: idx<%u>, bit<%u>\n", 154 s->pa, s->paio); 155 break; 156 } 157 158 /* write bit data */ 159 SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); 160 161 /* write to backend */ 162 if (s->blk) { 163 blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, 164 &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 0); 165 } 166 167 /* update written bit */ 168 SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); 169 } 170 171 break; 172 default: 173 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx 174 " v=0x%x\n", __func__, addr, val32); 175 } 176 } 177 178 static const MemoryRegionOps sifive_u_otp_ops = { 179 .read = sifive_u_otp_read, 180 .write = sifive_u_otp_write, 181 .endianness = DEVICE_NATIVE_ENDIAN, 182 .valid = { 183 .min_access_size = 4, 184 .max_access_size = 4 185 } 186 }; 187 188 static Property sifive_u_otp_properties[] = { 189 DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), 190 DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk), 191 DEFINE_PROP_END_OF_LIST(), 192 }; 193 194 static void sifive_u_otp_realize(DeviceState *dev, Error **errp) 195 { 196 SiFiveUOTPState *s = SIFIVE_U_OTP(dev); 197 DriveInfo *dinfo; 198 199 memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, 200 TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); 201 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); 202 203 dinfo = drive_get_next(IF_NONE); 204 if (dinfo) { 205 int ret; 206 uint64_t perm; 207 int filesize; 208 BlockBackend *blk; 209 210 blk = blk_by_legacy_dinfo(dinfo); 211 filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD; 212 if (blk_getlength(blk) < filesize) { 213 error_setg(errp, "OTP drive size < 16K"); 214 return; 215 } 216 217 qdev_prop_set_drive_err(dev, "drive", blk, errp); 218 219 if (s->blk) { 220 perm = BLK_PERM_CONSISTENT_READ | 221 (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); 222 ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); 223 if (ret < 0) { 224 return; 225 } 226 227 if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { 228 error_setg(errp, "failed to read the initial flash content"); 229 } 230 } 231 } 232 } 233 234 static void sifive_u_otp_reset(DeviceState *dev) 235 { 236 SiFiveUOTPState *s = SIFIVE_U_OTP(dev); 237 238 /* Initialize all fuses' initial value to 0xFFs */ 239 memset(s->fuse, 0xff, sizeof(s->fuse)); 240 241 /* Make a valid content of serial number */ 242 s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; 243 s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); 244 245 if (s->blk) { 246 /* Put serial number to backend as well*/ 247 uint32_t serial_data; 248 int index = SIFIVE_U_OTP_SERIAL_ADDR; 249 250 serial_data = s->serial; 251 blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, 252 &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); 253 254 serial_data = ~(s->serial); 255 blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, 256 &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); 257 } 258 259 /* Initialize write-once map */ 260 memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo)); 261 } 262 263 static void sifive_u_otp_class_init(ObjectClass *klass, void *data) 264 { 265 DeviceClass *dc = DEVICE_CLASS(klass); 266 267 device_class_set_props(dc, sifive_u_otp_properties); 268 dc->realize = sifive_u_otp_realize; 269 dc->reset = sifive_u_otp_reset; 270 } 271 272 static const TypeInfo sifive_u_otp_info = { 273 .name = TYPE_SIFIVE_U_OTP, 274 .parent = TYPE_SYS_BUS_DEVICE, 275 .instance_size = sizeof(SiFiveUOTPState), 276 .class_init = sifive_u_otp_class_init, 277 }; 278 279 static void sifive_u_otp_register_types(void) 280 { 281 type_register_static(&sifive_u_otp_info); 282 } 283 284 type_init(sifive_u_otp_register_types) 285