Skip to content

Commit 0895ce4

Browse files
committed
drivers: rockchip: extract OTP driver from rk3588 platform
The OTP handling is useful outside the rk3588 platform implementation. For example, the fuses for secure boot are accessible via the OTP. Extract the OTP write and read support to a separate driver to make it available for other modules. Signed-off-by: Michael Tretter <[email protected]>
1 parent e7f979e commit 0895ce4

File tree

5 files changed

+226
-177
lines changed

5 files changed

+226
-177
lines changed

core/arch/arm/plat-rockchip/conf.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ $(call force,CFG_TEE_CORE_NB_CORE,8)
6262
$(call force,CFG_ARM_GICV3,y)
6363
$(call force,CFG_AUTO_MAX_PA_BITS,y)
6464
$(call force,CFG_CRYPTO_WITH_CE,y)
65+
$(call force,CFG_ROCKCHIP_OTP,y)
6566

6667
CFG_TZDRAM_START ?= 0x30000000
6768
CFG_TZDRAM_SIZE ?= 0x02000000

core/arch/arm/plat-rockchip/platform_rk3588.c

Lines changed: 1 addition & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <common.h>
8+
#include <drivers/rockchip_otp.h>
89
#include <io.h>
910
#include <kernel/panic.h>
1011
#include <kernel/mutex.h>
@@ -49,37 +50,9 @@
4950
#define TRNG_POLL_PERIOD_US 0
5051
#define TRNG_POLL_TIMEOUT_US 1000
5152

52-
#define OTP_S_AUTO_CTRL 0x0004
53-
#define OTP_S_AUTO_EN 0x0008
54-
#define OTP_S_PROG_DATA 0x0010
55-
#define OTP_S_DOUT 0x0020
56-
#define OTP_S_INT_ST 0x0084
57-
58-
#define ADDR_SHIFT 16
59-
#define BURST_SHIFT 8
60-
#define CMD_READ 0
61-
#define CMD_WRITE 2
62-
#define EN_ENABLE 1
63-
#define EN_DISABLE 0
64-
65-
#define MAX_INDEX 0x300
66-
#define BURST_SIZE 8
67-
#define OTP_WORD 1
68-
69-
#define OTP_S_ERROR_BIT BIT32(4)
70-
#define OTP_S_WR_DONE_BIT BIT32(3)
71-
#define OTP_S_VERIFY_BIT BIT32(2)
72-
#define OTP_S_RD_DONE_BIT BIT32(1)
73-
74-
#define OTP_POLL_PERIOD_US 0
75-
#define OTP_POLL_TIMEOUT_US 1000
76-
77-
#define HW_UNIQUE_KEY_INDEX 0x104
78-
7953
register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE);
8054
register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DSU_BASE, FIREWALL_DSU_SIZE);
8155
register_phys_mem_pgdir(MEM_AREA_IO_SEC, TRNG_S_BASE, TRNG_S_SIZE);
82-
register_phys_mem_pgdir(MEM_AREA_IO_SEC, OTP_S_BASE, OTP_S_SIZE);
8356

8457
static struct mutex trng_mutex = MUTEX_INITIALIZER;
8558
static struct mutex huk_mutex = MUTEX_INITIALIZER;
@@ -193,155 +166,6 @@ TEE_Result hw_get_random_bytes(void *buf, size_t blen)
193166
return TEE_SUCCESS;
194167
}
195168

196-
static TEE_Result tee_otp_read_secure(uint32_t *value, uint32_t index,
197-
uint32_t count)
198-
{
199-
vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
200-
OTP_S_SIZE);
201-
uint32_t int_status = 0;
202-
uint32_t i = 0;
203-
uint32_t val = 0;
204-
uint32_t auto_ctrl_val = 0;
205-
TEE_Result res = TEE_SUCCESS;
206-
207-
if (!base)
208-
panic("OTP_S base not mapped");
209-
210-
/* Check for invalid parameters or exceeding hardware burst limit */
211-
if (!value || !count || count > BURST_SIZE ||
212-
(index + count > MAX_INDEX))
213-
return TEE_ERROR_BAD_PARAMETERS;
214-
215-
/* Setup read: index, count, command = READ */
216-
auto_ctrl_val = SHIFT_U32(index, ADDR_SHIFT) |
217-
SHIFT_U32(count, BURST_SHIFT) |
218-
CMD_READ;
219-
220-
/* Clear any pending interrupts by reading & writing back INT_ST */
221-
io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
222-
223-
/* Set read command */
224-
io_write32(base + OTP_S_AUTO_CTRL, auto_ctrl_val);
225-
226-
/* Enable read */
227-
io_write32(base + OTP_S_AUTO_EN, EN_ENABLE);
228-
229-
/* Wait for RD_DONE or ERROR bits */
230-
res = IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
231-
int_status,
232-
(int_status & OTP_S_RD_DONE_BIT) ||
233-
(int_status & OTP_S_ERROR_BIT),
234-
OTP_POLL_PERIOD_US,
235-
OTP_POLL_TIMEOUT_US);
236-
237-
/* Clear the interrupt again */
238-
io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
239-
240-
if (int_status & OTP_S_ERROR_BIT) {
241-
EMSG("OTP_S Error");
242-
return TEE_ERROR_GENERIC;
243-
}
244-
if (res) {
245-
EMSG("OTP_S Timeout");
246-
return TEE_ERROR_BUSY;
247-
}
248-
249-
/* Read out the data */
250-
for (i = 0; i < count; i++) {
251-
val = io_read32(base + OTP_S_DOUT +
252-
(i * sizeof(uint32_t)));
253-
value[i] = val;
254-
}
255-
256-
return TEE_SUCCESS;
257-
}
258-
259-
static TEE_Result tee_otp_write_secure(const uint32_t *value, uint32_t index,
260-
uint32_t count)
261-
{
262-
vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
263-
OTP_S_SIZE);
264-
uint32_t int_status = 0;
265-
uint32_t i = 0;
266-
267-
if (!base)
268-
panic("OTP_S base not mapped");
269-
270-
/* Check for invalid parameters or exceeding hardware limits */
271-
if (!value || !count || count > BURST_SIZE ||
272-
(index + count > MAX_INDEX))
273-
return TEE_ERROR_BAD_PARAMETERS;
274-
275-
/* Program OTP words */
276-
for (i = 0; i < count; i++) {
277-
uint32_t old_val = 0;
278-
uint32_t new_val = 0;
279-
uint32_t curr_idx = index + i;
280-
TEE_Result res = TEE_SUCCESS;
281-
282-
/* Setup write: curr_idx, command = WRITE */
283-
uint32_t auto_ctrl_val = SHIFT_U32(curr_idx, ADDR_SHIFT) |
284-
CMD_WRITE;
285-
286-
/* Read existing OTP word to see which bits can be set */
287-
res = tee_otp_read_secure(&old_val, curr_idx, OTP_WORD);
288-
if (res != TEE_SUCCESS)
289-
return res;
290-
291-
/* Check if bits in value conflict with old_val */
292-
if (~*value & old_val) {
293-
EMSG("OTP_S Program fail");
294-
return TEE_ERROR_GENERIC;
295-
}
296-
297-
/* Only program bits that are currently 0 (0->1) */
298-
new_val = *value & ~old_val;
299-
value++;
300-
if (!new_val)
301-
continue;
302-
303-
/* Clear any pending interrupts */
304-
io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
305-
306-
/* Set write command */
307-
io_write32(base + OTP_S_AUTO_CTRL, auto_ctrl_val);
308-
309-
/* Write the new bits into PROG_DATA register */
310-
io_write32(base + OTP_S_PROG_DATA, new_val);
311-
312-
/* Enable the write */
313-
io_write32(base + OTP_S_AUTO_EN, EN_ENABLE);
314-
315-
/* Poll for WR_DONE or verify/error bits */
316-
res = IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
317-
int_status,
318-
(int_status & OTP_S_WR_DONE_BIT) ||
319-
(int_status & OTP_S_VERIFY_BIT) ||
320-
(int_status & OTP_S_ERROR_BIT),
321-
OTP_POLL_PERIOD_US,
322-
OTP_POLL_TIMEOUT_US);
323-
324-
/* Clear INT status bits */
325-
io_write32(base + OTP_S_INT_ST, int_status);
326-
327-
/* Check for VERIFY_FAIL, ERROR or timeout */
328-
if (int_status & OTP_S_VERIFY_BIT) {
329-
EMSG("OTP_S Verification fail");
330-
return TEE_ERROR_GENERIC;
331-
}
332-
if (int_status & OTP_S_ERROR_BIT) {
333-
EMSG("OTP_S Error");
334-
return TEE_ERROR_GENERIC;
335-
}
336-
if (res) {
337-
EMSG("OTP_S Timeout");
338-
return TEE_ERROR_BUSY;
339-
}
340-
}
341-
342-
return TEE_SUCCESS;
343-
}
344-
345169
TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
346170
{
347171
TEE_Result res = TEE_SUCCESS;

0 commit comments

Comments
 (0)