1 /* 2 * BCM2835 One-Time Programmable (OTP) Memory 3 * 4 * The OTP implementation is mostly a stub except for the OTP rows 5 * which are accessed directly by other peripherals such as the mailbox. 6 * 7 * The OTP registers are unimplemented due to lack of documentation. 8 * 9 * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com> 10 * 11 * SPDX-License-Identifier: MIT 12 */ 13 14 #include "qemu/osdep.h" 15 #include "qemu/log.h" 16 #include "hw/nvram/bcm2835_otp.h" 17 #include "migration/vmstate.h" 18 19 /* OTP rows are 1-indexed */ 20 uint32_t bcm2835_otp_get_row(BCM2835OTPState *s, unsigned int row) 21 { 22 assert(row <= BCM2835_OTP_ROW_COUNT && row >= 1); 23 24 return s->otp_rows[row - 1]; 25 } 26 27 void bcm2835_otp_set_row(BCM2835OTPState *s, unsigned int row, 28 uint32_t value) 29 { 30 assert(row <= BCM2835_OTP_ROW_COUNT && row >= 1); 31 32 /* Real OTP rows work as e-fuses */ 33 s->otp_rows[row - 1] |= value; 34 } 35 36 static uint64_t bcm2835_otp_read(void *opaque, hwaddr addr, unsigned size) 37 { 38 switch (addr) { 39 case BCM2835_OTP_BOOTMODE_REG: 40 qemu_log_mask(LOG_UNIMP, 41 "bcm2835_otp: BCM2835_OTP_BOOTMODE_REG\n"); 42 break; 43 case BCM2835_OTP_CONFIG_REG: 44 qemu_log_mask(LOG_UNIMP, 45 "bcm2835_otp: BCM2835_OTP_CONFIG_REG\n"); 46 break; 47 case BCM2835_OTP_CTRL_LO_REG: 48 qemu_log_mask(LOG_UNIMP, 49 "bcm2835_otp: BCM2835_OTP_CTRL_LO_REG\n"); 50 break; 51 case BCM2835_OTP_CTRL_HI_REG: 52 qemu_log_mask(LOG_UNIMP, 53 "bcm2835_otp: BCM2835_OTP_CTRL_HI_REG\n"); 54 break; 55 case BCM2835_OTP_STATUS_REG: 56 qemu_log_mask(LOG_UNIMP, 57 "bcm2835_otp: BCM2835_OTP_STATUS_REG\n"); 58 break; 59 case BCM2835_OTP_BITSEL_REG: 60 qemu_log_mask(LOG_UNIMP, 61 "bcm2835_otp: BCM2835_OTP_BITSEL_REG\n"); 62 break; 63 case BCM2835_OTP_DATA_REG: 64 qemu_log_mask(LOG_UNIMP, 65 "bcm2835_otp: BCM2835_OTP_DATA_REG\n"); 66 break; 67 case BCM2835_OTP_ADDR_REG: 68 qemu_log_mask(LOG_UNIMP, 69 "bcm2835_otp: BCM2835_OTP_ADDR_REG\n"); 70 break; 71 case BCM2835_OTP_WRITE_DATA_READ_REG: 72 qemu_log_mask(LOG_UNIMP, 73 "bcm2835_otp: BCM2835_OTP_WRITE_DATA_READ_REG\n"); 74 break; 75 case BCM2835_OTP_INIT_STATUS_REG: 76 qemu_log_mask(LOG_UNIMP, 77 "bcm2835_otp: BCM2835_OTP_INIT_STATUS_REG\n"); 78 break; 79 default: 80 qemu_log_mask(LOG_GUEST_ERROR, 81 "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr); 82 } 83 84 return 0; 85 } 86 87 static void bcm2835_otp_write(void *opaque, hwaddr addr, 88 uint64_t value, unsigned int size) 89 { 90 switch (addr) { 91 case BCM2835_OTP_BOOTMODE_REG: 92 qemu_log_mask(LOG_UNIMP, 93 "bcm2835_otp: BCM2835_OTP_BOOTMODE_REG\n"); 94 break; 95 case BCM2835_OTP_CONFIG_REG: 96 qemu_log_mask(LOG_UNIMP, 97 "bcm2835_otp: BCM2835_OTP_CONFIG_REG\n"); 98 break; 99 case BCM2835_OTP_CTRL_LO_REG: 100 qemu_log_mask(LOG_UNIMP, 101 "bcm2835_otp: BCM2835_OTP_CTRL_LO_REG\n"); 102 break; 103 case BCM2835_OTP_CTRL_HI_REG: 104 qemu_log_mask(LOG_UNIMP, 105 "bcm2835_otp: BCM2835_OTP_CTRL_HI_REG\n"); 106 break; 107 case BCM2835_OTP_STATUS_REG: 108 qemu_log_mask(LOG_UNIMP, 109 "bcm2835_otp: BCM2835_OTP_STATUS_REG\n"); 110 break; 111 case BCM2835_OTP_BITSEL_REG: 112 qemu_log_mask(LOG_UNIMP, 113 "bcm2835_otp: BCM2835_OTP_BITSEL_REG\n"); 114 break; 115 case BCM2835_OTP_DATA_REG: 116 qemu_log_mask(LOG_UNIMP, 117 "bcm2835_otp: BCM2835_OTP_DATA_REG\n"); 118 break; 119 case BCM2835_OTP_ADDR_REG: 120 qemu_log_mask(LOG_UNIMP, 121 "bcm2835_otp: BCM2835_OTP_ADDR_REG\n"); 122 break; 123 case BCM2835_OTP_WRITE_DATA_READ_REG: 124 qemu_log_mask(LOG_UNIMP, 125 "bcm2835_otp: BCM2835_OTP_WRITE_DATA_READ_REG\n"); 126 break; 127 case BCM2835_OTP_INIT_STATUS_REG: 128 qemu_log_mask(LOG_UNIMP, 129 "bcm2835_otp: BCM2835_OTP_INIT_STATUS_REG\n"); 130 break; 131 default: 132 qemu_log_mask(LOG_GUEST_ERROR, 133 "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr); 134 } 135 } 136 137 static const MemoryRegionOps bcm2835_otp_ops = { 138 .read = bcm2835_otp_read, 139 .write = bcm2835_otp_write, 140 .endianness = DEVICE_NATIVE_ENDIAN, 141 .impl = { 142 .min_access_size = 4, 143 .max_access_size = 4, 144 }, 145 }; 146 147 static void bcm2835_otp_realize(DeviceState *dev, Error **errp) 148 { 149 BCM2835OTPState *s = BCM2835_OTP(dev); 150 memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_otp_ops, s, 151 TYPE_BCM2835_OTP, 0x80); 152 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); 153 154 memset(s->otp_rows, 0x00, sizeof(s->otp_rows)); 155 } 156 157 static const VMStateDescription vmstate_bcm2835_otp = { 158 .name = TYPE_BCM2835_OTP, 159 .version_id = 1, 160 .minimum_version_id = 1, 161 .fields = (const VMStateField[]) { 162 VMSTATE_UINT32_ARRAY(otp_rows, BCM2835OTPState, BCM2835_OTP_ROW_COUNT), 163 VMSTATE_END_OF_LIST() 164 } 165 }; 166 167 static void bcm2835_otp_class_init(ObjectClass *klass, void *data) 168 { 169 DeviceClass *dc = DEVICE_CLASS(klass); 170 171 dc->realize = bcm2835_otp_realize; 172 dc->vmsd = &vmstate_bcm2835_otp; 173 } 174 175 static const TypeInfo bcm2835_otp_info = { 176 .name = TYPE_BCM2835_OTP, 177 .parent = TYPE_SYS_BUS_DEVICE, 178 .instance_size = sizeof(BCM2835OTPState), 179 .class_init = bcm2835_otp_class_init, 180 }; 181 182 static void bcm2835_otp_register_types(void) 183 { 184 type_register_static(&bcm2835_otp_info); 185 } 186 187 type_init(bcm2835_otp_register_types) 188