2 * BCM2835 One-Time Programmable (OTP) Memory
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.
7 * The OTP registers are unimplemented due to lack of documentation.
9 * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
11 * SPDX-License-Identifier: MIT
14 #include "qemu/osdep.h"
16 #include "hw/nvram/bcm2835_otp.h"
17 #include "migration/vmstate.h"
19 /* OTP rows are 1-indexed */
20 uint32_t bcm2835_otp_get_row(BCM2835OTPState
*s
, unsigned int row
)
22 assert(row
<= BCM2835_OTP_ROW_COUNT
&& row
>= 1);
24 return s
->otp_rows
[row
- 1];
27 void bcm2835_otp_set_row(BCM2835OTPState
*s
, unsigned int row
,
30 assert(row
<= BCM2835_OTP_ROW_COUNT
&& row
>= 1);
32 /* Real OTP rows work as e-fuses */
33 s
->otp_rows
[row
- 1] |= value
;
36 static uint64_t bcm2835_otp_read(void *opaque
, hwaddr addr
, unsigned size
)
39 case BCM2835_OTP_BOOTMODE_REG
:
40 qemu_log_mask(LOG_UNIMP
,
41 "bcm2835_otp: BCM2835_OTP_BOOTMODE_REG\n");
43 case BCM2835_OTP_CONFIG_REG
:
44 qemu_log_mask(LOG_UNIMP
,
45 "bcm2835_otp: BCM2835_OTP_CONFIG_REG\n");
47 case BCM2835_OTP_CTRL_LO_REG
:
48 qemu_log_mask(LOG_UNIMP
,
49 "bcm2835_otp: BCM2835_OTP_CTRL_LO_REG\n");
51 case BCM2835_OTP_CTRL_HI_REG
:
52 qemu_log_mask(LOG_UNIMP
,
53 "bcm2835_otp: BCM2835_OTP_CTRL_HI_REG\n");
55 case BCM2835_OTP_STATUS_REG
:
56 qemu_log_mask(LOG_UNIMP
,
57 "bcm2835_otp: BCM2835_OTP_STATUS_REG\n");
59 case BCM2835_OTP_BITSEL_REG
:
60 qemu_log_mask(LOG_UNIMP
,
61 "bcm2835_otp: BCM2835_OTP_BITSEL_REG\n");
63 case BCM2835_OTP_DATA_REG
:
64 qemu_log_mask(LOG_UNIMP
,
65 "bcm2835_otp: BCM2835_OTP_DATA_REG\n");
67 case BCM2835_OTP_ADDR_REG
:
68 qemu_log_mask(LOG_UNIMP
,
69 "bcm2835_otp: BCM2835_OTP_ADDR_REG\n");
71 case BCM2835_OTP_WRITE_DATA_READ_REG
:
72 qemu_log_mask(LOG_UNIMP
,
73 "bcm2835_otp: BCM2835_OTP_WRITE_DATA_READ_REG\n");
75 case BCM2835_OTP_INIT_STATUS_REG
:
76 qemu_log_mask(LOG_UNIMP
,
77 "bcm2835_otp: BCM2835_OTP_INIT_STATUS_REG\n");
80 qemu_log_mask(LOG_GUEST_ERROR
,
81 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
, addr
);
87 static void bcm2835_otp_write(void *opaque
, hwaddr addr
,
88 uint64_t value
, unsigned int size
)
91 case BCM2835_OTP_BOOTMODE_REG
:
92 qemu_log_mask(LOG_UNIMP
,
93 "bcm2835_otp: BCM2835_OTP_BOOTMODE_REG\n");
95 case BCM2835_OTP_CONFIG_REG
:
96 qemu_log_mask(LOG_UNIMP
,
97 "bcm2835_otp: BCM2835_OTP_CONFIG_REG\n");
99 case BCM2835_OTP_CTRL_LO_REG
:
100 qemu_log_mask(LOG_UNIMP
,
101 "bcm2835_otp: BCM2835_OTP_CTRL_LO_REG\n");
103 case BCM2835_OTP_CTRL_HI_REG
:
104 qemu_log_mask(LOG_UNIMP
,
105 "bcm2835_otp: BCM2835_OTP_CTRL_HI_REG\n");
107 case BCM2835_OTP_STATUS_REG
:
108 qemu_log_mask(LOG_UNIMP
,
109 "bcm2835_otp: BCM2835_OTP_STATUS_REG\n");
111 case BCM2835_OTP_BITSEL_REG
:
112 qemu_log_mask(LOG_UNIMP
,
113 "bcm2835_otp: BCM2835_OTP_BITSEL_REG\n");
115 case BCM2835_OTP_DATA_REG
:
116 qemu_log_mask(LOG_UNIMP
,
117 "bcm2835_otp: BCM2835_OTP_DATA_REG\n");
119 case BCM2835_OTP_ADDR_REG
:
120 qemu_log_mask(LOG_UNIMP
,
121 "bcm2835_otp: BCM2835_OTP_ADDR_REG\n");
123 case BCM2835_OTP_WRITE_DATA_READ_REG
:
124 qemu_log_mask(LOG_UNIMP
,
125 "bcm2835_otp: BCM2835_OTP_WRITE_DATA_READ_REG\n");
127 case BCM2835_OTP_INIT_STATUS_REG
:
128 qemu_log_mask(LOG_UNIMP
,
129 "bcm2835_otp: BCM2835_OTP_INIT_STATUS_REG\n");
132 qemu_log_mask(LOG_GUEST_ERROR
,
133 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
, addr
);
137 static const MemoryRegionOps bcm2835_otp_ops
= {
138 .read
= bcm2835_otp_read
,
139 .write
= bcm2835_otp_write
,
140 .endianness
= DEVICE_NATIVE_ENDIAN
,
142 .min_access_size
= 4,
143 .max_access_size
= 4,
147 static void bcm2835_otp_realize(DeviceState
*dev
, Error
**errp
)
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
);
154 memset(s
->otp_rows
, 0x00, sizeof(s
->otp_rows
));
157 static const VMStateDescription vmstate_bcm2835_otp
= {
158 .name
= TYPE_BCM2835_OTP
,
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()
167 static void bcm2835_otp_class_init(ObjectClass
*klass
, void *data
)
169 DeviceClass
*dc
= DEVICE_CLASS(klass
);
171 dc
->realize
= bcm2835_otp_realize
;
172 dc
->vmsd
= &vmstate_bcm2835_otp
;
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
,
182 static void bcm2835_otp_register_types(void)
184 type_register_static(&bcm2835_otp_info
);
187 type_init(bcm2835_otp_register_types
)