xref: /optee_os/core/drivers/rockchip_otp.c (revision 3d0429ac12cd2ab11c047b0814ac2f833471bbfb)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
4  * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
5  * Copyright (C) 2025, Pengutronix, Michael Tretter <m.tretter@pengutronix.de>
6  */
7 
8 #include <common.h>
9 #include <drivers/rockchip_otp.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <kernel/tee_common_otp.h>
13 #include <mm/core_memprot.h>
14 #include <utee_defines.h>
15 
16 #define OTP_S_AUTO_CTRL	0x0004
17 #define OTP_S_AUTO_EN	0x0008
18 #define OTP_S_PROG_DATA	0x0010
19 #define OTP_S_DOUT	0x0020
20 #define OTP_S_INT_ST	0x0084
21 
22 #define ADDR_SHIFT	16
23 #define BURST_SHIFT	8
24 #define CMD_READ	0
25 #define CMD_WRITE	2
26 #define EN_ENABLE	1
27 #define EN_DISABLE	0
28 
29 #define MAX_INDEX	0x300
30 #define BURST_SIZE	8
31 #define OTP_WORD	1
32 
33 #define OTP_S_ERROR_BIT		BIT32(4)
34 #define OTP_S_WR_DONE_BIT	BIT32(3)
35 #define OTP_S_VERIFY_BIT	BIT32(2)
36 #define OTP_S_RD_DONE_BIT	BIT32(1)
37 
38 #define OTP_POLL_PERIOD_US	0
39 #define OTP_POLL_TIMEOUT_US	1000
40 
41 register_phys_mem_pgdir(MEM_AREA_IO_SEC, OTP_S_BASE, OTP_S_SIZE);
42 
43 TEE_Result rockchip_otp_read_secure(uint32_t *value, uint32_t index,
44 				    uint32_t count)
45 {
46 	vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
47 					     OTP_S_SIZE);
48 	uint32_t int_status = 0;
49 	uint32_t i = 0;
50 	uint32_t val = 0;
51 	uint32_t auto_ctrl_val = 0;
52 	TEE_Result res = TEE_SUCCESS;
53 
54 	if (!base)
55 		panic("OTP_S base not mapped");
56 
57 	/* Check for invalid parameters or exceeding hardware burst limit */
58 	if (!value || !count || count > BURST_SIZE ||
59 	    (index + count > MAX_INDEX))
60 		return TEE_ERROR_BAD_PARAMETERS;
61 
62 	/* Setup read: index, count, command = READ */
63 	auto_ctrl_val = SHIFT_U32(index, ADDR_SHIFT) |
64 			SHIFT_U32(count, BURST_SHIFT) |
65 			CMD_READ;
66 
67 	/* Clear any pending interrupts by reading & writing back INT_ST */
68 	io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
69 
70 	/* Set read command */
71 	io_write32(base + OTP_S_AUTO_CTRL, auto_ctrl_val);
72 
73 	/* Enable read */
74 	io_write32(base + OTP_S_AUTO_EN, EN_ENABLE);
75 
76 	/* Wait for RD_DONE or ERROR bits */
77 	res = IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
78 				     int_status,
79 				     (int_status & OTP_S_RD_DONE_BIT) ||
80 				     (int_status & OTP_S_ERROR_BIT),
81 				     OTP_POLL_PERIOD_US,
82 				     OTP_POLL_TIMEOUT_US);
83 
84 	/* Clear the interrupt again */
85 	io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
86 
87 	if (int_status & OTP_S_ERROR_BIT) {
88 		EMSG("OTP_S Error");
89 		return TEE_ERROR_GENERIC;
90 	}
91 	if (res) {
92 		EMSG("OTP_S Timeout");
93 		return TEE_ERROR_BUSY;
94 	}
95 
96 	/* Read out the data */
97 	for (i = 0; i < count; i++) {
98 		val = io_read32(base + OTP_S_DOUT +
99 				(i * sizeof(uint32_t)));
100 		value[i] = val;
101 	}
102 
103 	return TEE_SUCCESS;
104 }
105 
106 TEE_Result rockchip_otp_write_secure(const uint32_t *value, uint32_t index,
107 				     uint32_t count)
108 {
109 	vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
110 					     OTP_S_SIZE);
111 	uint32_t int_status = 0;
112 	uint32_t i = 0;
113 
114 	if (!base)
115 		panic("OTP_S base not mapped");
116 
117 	/* Check for invalid parameters or exceeding hardware limits */
118 	if (!value || !count || count > BURST_SIZE ||
119 	    (index + count > MAX_INDEX))
120 		return TEE_ERROR_BAD_PARAMETERS;
121 
122 	/* Program OTP words */
123 	for (i = 0; i < count; i++) {
124 		uint32_t old_val = 0;
125 		uint32_t new_val = 0;
126 		uint32_t curr_idx = index + i;
127 		TEE_Result res = TEE_SUCCESS;
128 
129 		/* Setup write: curr_idx, command = WRITE */
130 		uint32_t auto_ctrl_val = SHIFT_U32(curr_idx, ADDR_SHIFT) |
131 						   CMD_WRITE;
132 
133 		/* Read existing OTP word to see which bits can be set */
134 		res = rockchip_otp_read_secure(&old_val, curr_idx, OTP_WORD);
135 		if (res != TEE_SUCCESS)
136 			return res;
137 
138 		/* Check if bits in value conflict with old_val */
139 		if (~*value & old_val) {
140 			EMSG("OTP_S Program fail");
141 			return TEE_ERROR_GENERIC;
142 		}
143 
144 		/* Only program bits that are currently 0 (0->1) */
145 		new_val = *value & ~old_val;
146 		value++;
147 		if (!new_val)
148 			continue;
149 
150 		/* Clear any pending interrupts */
151 		io_write32(base + OTP_S_INT_ST, io_read32(base + OTP_S_INT_ST));
152 
153 		/* Set write command */
154 		io_write32(base + OTP_S_AUTO_CTRL, auto_ctrl_val);
155 
156 		/* Write the new bits into PROG_DATA register */
157 		io_write32(base + OTP_S_PROG_DATA, new_val);
158 
159 		/* Enable the write */
160 		io_write32(base + OTP_S_AUTO_EN, EN_ENABLE);
161 
162 		/* Poll for WR_DONE or verify/error bits */
163 		res = IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
164 					     int_status,
165 					     (int_status & OTP_S_WR_DONE_BIT) ||
166 					     (int_status & OTP_S_VERIFY_BIT) ||
167 					     (int_status & OTP_S_ERROR_BIT),
168 					     OTP_POLL_PERIOD_US,
169 					     OTP_POLL_TIMEOUT_US);
170 
171 		/* Clear INT status bits */
172 		io_write32(base + OTP_S_INT_ST, int_status);
173 
174 		/* Check for VERIFY_FAIL, ERROR or timeout */
175 		if (int_status & OTP_S_VERIFY_BIT) {
176 			EMSG("OTP_S Verification fail");
177 			return TEE_ERROR_GENERIC;
178 		}
179 		if (int_status & OTP_S_ERROR_BIT) {
180 			EMSG("OTP_S Error");
181 			return TEE_ERROR_GENERIC;
182 		}
183 		if (res) {
184 			EMSG("OTP_S Timeout");
185 			return TEE_ERROR_BUSY;
186 		}
187 	}
188 
189 	return TEE_SUCCESS;
190 }
191