xref: /openbmc/u-boot/cmd/otp.c (revision 7332532c3fa42790303e4b71750891fa4316e5cd)
169d5fd8fSJohnny Huang /*
269d5fd8fSJohnny Huang  *  This program is distributed in the hope that it will be useful,
369d5fd8fSJohnny Huang  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
469d5fd8fSJohnny Huang  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
569d5fd8fSJohnny Huang  *  GNU General Public License for more details.
669d5fd8fSJohnny Huang  *
769d5fd8fSJohnny Huang  *  You should have received a copy of the GNU General Public License
869d5fd8fSJohnny Huang  *  along with this program; if not, write to the Free Software
969d5fd8fSJohnny Huang  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1069d5fd8fSJohnny Huang  */
114c1c9b35SJohnny Huang #include <stdlib.h>
1269d5fd8fSJohnny Huang #include <common.h>
1369d5fd8fSJohnny Huang #include <console.h>
1469d5fd8fSJohnny Huang #include <bootretry.h>
1569d5fd8fSJohnny Huang #include <cli.h>
1669d5fd8fSJohnny Huang #include <command.h>
1769d5fd8fSJohnny Huang #include <console.h>
184c1c9b35SJohnny Huang #include <malloc.h>
1969d5fd8fSJohnny Huang #include <inttypes.h>
2069d5fd8fSJohnny Huang #include <mapmem.h>
2169d5fd8fSJohnny Huang #include <asm/io.h>
2269d5fd8fSJohnny Huang #include <linux/compiler.h>
2369d5fd8fSJohnny Huang 
2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2569d5fd8fSJohnny Huang 
2669d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
2769d5fd8fSJohnny Huang #define RETRY				3
28*7332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
29*7332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
30*7332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
3169d5fd8fSJohnny Huang 
322a856b9aSJohnny Huang #define OTP_USAGE			-1
332a856b9aSJohnny Huang #define OTP_FAILURE			-2
342a856b9aSJohnny Huang #define OTP_SUCCESS			0
352a856b9aSJohnny Huang 
36a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
37a6af4a17SJohnny Huang 
38a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
39b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
40b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4176d13988SJohnny Huang 
424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
434c1c9b35SJohnny Huang #define PBWIDTH 60
444c1c9b35SJohnny Huang 
4566f2f8e5SJohnny Huang struct otpstrap_status {
4669d5fd8fSJohnny Huang 	int value;
4769d5fd8fSJohnny Huang 	int option_array[7];
4869d5fd8fSJohnny Huang 	int remain_times;
4969d5fd8fSJohnny Huang 	int writeable_option;
5069d5fd8fSJohnny Huang 	int protected;
5169d5fd8fSJohnny Huang };
5269d5fd8fSJohnny Huang 
5366f2f8e5SJohnny Huang struct otpconf_parse {
5466f2f8e5SJohnny Huang 	int dw_offset;
5566f2f8e5SJohnny Huang 	int bit;
5666f2f8e5SJohnny Huang 	int length;
5766f2f8e5SJohnny Huang 	int value;
5866f2f8e5SJohnny Huang 	int keep;
5966f2f8e5SJohnny Huang 	char status[80];
6066f2f8e5SJohnny Huang };
6166f2f8e5SJohnny Huang 
62a8bd6d8cSJohnny Huang struct otpstrap_info {
63a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
64a8bd6d8cSJohnny Huang 	uint32_t length;
6576d13988SJohnny Huang 	int value;
66a8bd6d8cSJohnny Huang 	char information[80];
67a8bd6d8cSJohnny Huang };
68a8bd6d8cSJohnny Huang 
69a8bd6d8cSJohnny Huang struct otpconf_info {
70a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
71a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
72a8bd6d8cSJohnny Huang 	uint32_t length;
73a8bd6d8cSJohnny Huang 	int value;
74a8bd6d8cSJohnny Huang 	char information[80];
75a8bd6d8cSJohnny Huang };
76a8bd6d8cSJohnny Huang 
77a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...)
78a8bd6d8cSJohnny Huang {
79a8bd6d8cSJohnny Huang 	int val = numerator * 100 / denominator;
80a8bd6d8cSJohnny Huang 	int lpad = numerator * PBWIDTH / denominator;
81a8bd6d8cSJohnny Huang 	int rpad = PBWIDTH - lpad;
82a8bd6d8cSJohnny Huang 	char buffer[256];
83a8bd6d8cSJohnny Huang 	va_list aptr;
84a8bd6d8cSJohnny Huang 
85a8bd6d8cSJohnny Huang 	va_start(aptr, format);
86a8bd6d8cSJohnny Huang 	vsprintf(buffer, format, aptr);
87a8bd6d8cSJohnny Huang 	va_end(aptr);
88a8bd6d8cSJohnny Huang 
89a8bd6d8cSJohnny Huang 	printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer);
90a8bd6d8cSJohnny Huang 	if (numerator == denominator)
91a8bd6d8cSJohnny Huang 		printf("\n");
92a8bd6d8cSJohnny Huang }
93a8bd6d8cSJohnny Huang 
94a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = {
95a8bd6d8cSJohnny Huang 	{
96a8bd6d8cSJohnny Huang 		0, 1, 0, "Disable secure boot"
97a8bd6d8cSJohnny Huang 	}, {
98a8bd6d8cSJohnny Huang 		0, 1, 1, "Enable secure boot"
99a8bd6d8cSJohnny Huang 	}, {
100a8bd6d8cSJohnny Huang 		1, 1, 0, "Disable boot from eMMC"
101a8bd6d8cSJohnny Huang 	}, {
102a8bd6d8cSJohnny Huang 		1, 1, 1, "Enable boot from eMMC"
103a8bd6d8cSJohnny Huang 	}, {
104a8bd6d8cSJohnny Huang 		2, 1, 0, "Disable Boot from debug SPI"
105a8bd6d8cSJohnny Huang 	}, {
106a8bd6d8cSJohnny Huang 		2, 1, 1, "Enable Boot from debug SPI"
107a8bd6d8cSJohnny Huang 	}, {
108a8bd6d8cSJohnny Huang 		3, 1, 0, "Enable ARM CM3"
109a8bd6d8cSJohnny Huang 	}, {
110a8bd6d8cSJohnny Huang 		3, 1, 1, "Disable ARM CM3"
111a8bd6d8cSJohnny Huang 	}, {
112a8bd6d8cSJohnny Huang 		4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS"
113a8bd6d8cSJohnny Huang 	}, {
114a8bd6d8cSJohnny Huang 		4, 1, 1, "Enable dedicated VGA BIOS ROM"
115a8bd6d8cSJohnny Huang 	}, {
116a8bd6d8cSJohnny Huang 		5, 1, 0, "MAC 1 : RMII/NCSI"
117a8bd6d8cSJohnny Huang 	}, {
118a8bd6d8cSJohnny Huang 		5, 1, 1, "MAC 1 : RGMII"
119a8bd6d8cSJohnny Huang 	}, {
120a8bd6d8cSJohnny Huang 		6, 1, 0, "MAC 2 : RMII/NCSI"
121a8bd6d8cSJohnny Huang 	}, {
122a8bd6d8cSJohnny Huang 		6, 1, 1, "MAC 2 : RGMII"
123a8bd6d8cSJohnny Huang 	}, {
124a8bd6d8cSJohnny Huang 		7, 3, 0, "CPU Frequency : 1GHz"
125a8bd6d8cSJohnny Huang 	}, {
126a8bd6d8cSJohnny Huang 		7, 3, 1, "CPU Frequency : 800MHz"
127a8bd6d8cSJohnny Huang 	}, {
128a8bd6d8cSJohnny Huang 		7, 3, 2, "CPU Frequency : 1.2GHz"
129a8bd6d8cSJohnny Huang 	}, {
130a8bd6d8cSJohnny Huang 		7, 3, 3, "CPU Frequency : 1.4GHz"
131a8bd6d8cSJohnny Huang 	}, {
132a8bd6d8cSJohnny Huang 		10, 2, 0, "HCLK ratio AXI:AHB = 2:1"
133a8bd6d8cSJohnny Huang 	}, {
134a8bd6d8cSJohnny Huang 		10, 2, 1, "HCLK ratio AXI:AHB = 2:1"
135a8bd6d8cSJohnny Huang 	}, {
136a8bd6d8cSJohnny Huang 		10, 2, 2, "HCLK ratio AXI:AHB = 3:1"
137a8bd6d8cSJohnny Huang 	}, {
138a8bd6d8cSJohnny Huang 		10, 2, 3, "HCLK ratio AXI:AHB = 4:1"
139a8bd6d8cSJohnny Huang 	}, {
140a8bd6d8cSJohnny Huang 		12, 2, 0, "VGA memory size : 8MB"
141a8bd6d8cSJohnny Huang 	}, {
142a8bd6d8cSJohnny Huang 		12, 2, 1, "VGA memory size : 16MB"
143a8bd6d8cSJohnny Huang 	}, {
144a8bd6d8cSJohnny Huang 		12, 2, 2, "VGA memory size : 32MB"
145a8bd6d8cSJohnny Huang 	}, {
146a8bd6d8cSJohnny Huang 		12, 2, 3, "VGA memory size : 64MB"
147a8bd6d8cSJohnny Huang 	}, {
148a8bd6d8cSJohnny Huang 		14, 3, OTP_REG_RESERVED, ""
149a8bd6d8cSJohnny Huang 	}, {
150a8bd6d8cSJohnny Huang 		17, 1, 0, "VGA class code : Class Code for video device"
151a8bd6d8cSJohnny Huang 	}, {
152a8bd6d8cSJohnny Huang 		17, 1, 1, "VGA class code : Class Code for VGA device"
153a8bd6d8cSJohnny Huang 	}, {
154a8bd6d8cSJohnny Huang 		18, 1, 0, "Enable debug interfaces 0"
155a8bd6d8cSJohnny Huang 	}, {
156a8bd6d8cSJohnny Huang 		18, 1, 1, "Disable debug interfaces 0"
157a8bd6d8cSJohnny Huang 	}, {
158a8bd6d8cSJohnny Huang 		19, 1, 0, "Boot from emmc mode : High eMMC speed"
159a8bd6d8cSJohnny Huang 	}, {
160a8bd6d8cSJohnny Huang 		19, 1, 1, "Boot from emmc mode : Normal eMMC speed"
161a8bd6d8cSJohnny Huang 	}, {
162a8bd6d8cSJohnny Huang 		20, 1, 0, "Enable Pcie EHCI device"
163a8bd6d8cSJohnny Huang 	}, {
164a8bd6d8cSJohnny Huang 		20, 1, 1, "Disable Pcie EHCI device"
165a8bd6d8cSJohnny Huang 	}, {
166a8bd6d8cSJohnny Huang 		21, 1, 0, "Enable VGA XDMA function"
167a8bd6d8cSJohnny Huang 	}, {
168a8bd6d8cSJohnny Huang 		21, 1, 1, "Disable VGA XDMA function"
169a8bd6d8cSJohnny Huang 	}, {
170a8bd6d8cSJohnny Huang 		22, 1, 0, "Normal BMC mode"
171a8bd6d8cSJohnny Huang 	}, {
172a8bd6d8cSJohnny Huang 		22, 1, 1, "Disable dedicated BMC functions for non-BMC application"
173a8bd6d8cSJohnny Huang 	}, {
174a8bd6d8cSJohnny Huang 		23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin"
175a8bd6d8cSJohnny Huang 	}, {
176a8bd6d8cSJohnny Huang 		23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin"
177a8bd6d8cSJohnny Huang 	}, {
178*7332532cSJohnny Huang 		24, 1, 0, "DRAM types : DDR4"
179a8bd6d8cSJohnny Huang 	}, {
180*7332532cSJohnny Huang 		24, 1, 1, "DRAM types : DDR3"
181a8bd6d8cSJohnny Huang 	}, {
182a8bd6d8cSJohnny Huang 		25, 5, OTP_REG_RESERVED, ""
183a8bd6d8cSJohnny Huang 	}, {
184a8bd6d8cSJohnny Huang 		30, 2, OTP_REG_RESERVED, ""
185a8bd6d8cSJohnny Huang 	}, {
186a8bd6d8cSJohnny Huang 		32, 1, 0, "MAC 3 : RMII/NCSI"
187a8bd6d8cSJohnny Huang 	}, {
188a8bd6d8cSJohnny Huang 		32, 1, 1, "MAC 3 : RGMII"
189a8bd6d8cSJohnny Huang 	}, {
190a8bd6d8cSJohnny Huang 		33, 1, 0, "MAC 4 : RMII/NCSI"
191a8bd6d8cSJohnny Huang 	}, {
192a8bd6d8cSJohnny Huang 		33, 1, 1, "MAC 4 : RGMII"
193a8bd6d8cSJohnny Huang 	}, {
194a8bd6d8cSJohnny Huang 		34, 1, 0, "SuperIO configuration address : 0x2E"
195a8bd6d8cSJohnny Huang 	}, {
196a8bd6d8cSJohnny Huang 		34, 1, 1, "SuperIO configuration address : 0x4E"
197a8bd6d8cSJohnny Huang 	}, {
198a8bd6d8cSJohnny Huang 		35, 1, 0, "Enable LPC to decode SuperIO"
199a8bd6d8cSJohnny Huang 	}, {
200a8bd6d8cSJohnny Huang 		35, 1, 1, "Disable LPC to decode SuperIO"
201a8bd6d8cSJohnny Huang 	}, {
202a8bd6d8cSJohnny Huang 		36, 1, 0, "Enable debug interfaces 1"
203a8bd6d8cSJohnny Huang 	}, {
204a8bd6d8cSJohnny Huang 		36, 1, 1, "Disable debug interfaces 1"
205a8bd6d8cSJohnny Huang 	}, {
206a8bd6d8cSJohnny Huang 		37, 1, 0, "Disable ACPI function"
207a8bd6d8cSJohnny Huang 	}, {
208a8bd6d8cSJohnny Huang 		37, 1, 1, "Enable ACPI function"
209a8bd6d8cSJohnny Huang 	}, {
210a8bd6d8cSJohnny Huang 		38, 1, 0, "Enable eSPI mode"
211a8bd6d8cSJohnny Huang 	}, {
212a8bd6d8cSJohnny Huang 		38, 1, 1, "Enable LPC mode"
213a8bd6d8cSJohnny Huang 	}, {
214a8bd6d8cSJohnny Huang 		39, 1, 0, "Enable SAFS mode"
215a8bd6d8cSJohnny Huang 	}, {
216a8bd6d8cSJohnny Huang 		39, 1, 1, "Enable SAFS mode"
217a8bd6d8cSJohnny Huang 	}, {
218a8bd6d8cSJohnny Huang 		40, 2, OTP_REG_RESERVED, ""
219a8bd6d8cSJohnny Huang 	}, {
220a8bd6d8cSJohnny Huang 		42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection"
221a8bd6d8cSJohnny Huang 	}, {
222a8bd6d8cSJohnny Huang 		42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection"
223a8bd6d8cSJohnny Huang 	}, {
224a8bd6d8cSJohnny Huang 		43, 1, 0, "Disable boot SPI ABR"
225a8bd6d8cSJohnny Huang 	}, {
226a8bd6d8cSJohnny Huang 		43, 1, 1, "Enable boot SPI ABR"
227a8bd6d8cSJohnny Huang 	}, {
228a8bd6d8cSJohnny Huang 		44, 1, 0, "Boot SPI ABR mode : dual SPI flash"
229a8bd6d8cSJohnny Huang 	}, {
230a8bd6d8cSJohnny Huang 		44, 1, 1, "Boot SPI ABR mode : single SPI flash"
231a8bd6d8cSJohnny Huang 	}, {
232a8bd6d8cSJohnny Huang 		45, 3, 0, "Boot SPI flash size : no define size"
233a8bd6d8cSJohnny Huang 	}, {
234a8bd6d8cSJohnny Huang 		45, 3, 1, "Boot SPI flash size : 2MB"
235a8bd6d8cSJohnny Huang 	}, {
236a8bd6d8cSJohnny Huang 		45, 3, 2, "Boot SPI flash size : 4MB"
237a8bd6d8cSJohnny Huang 	}, {
238a8bd6d8cSJohnny Huang 		45, 3, 3, "Boot SPI flash size : 8MB"
239a8bd6d8cSJohnny Huang 	}, {
240a8bd6d8cSJohnny Huang 		45, 3, 4, "Boot SPI flash size : 16MB"
241a8bd6d8cSJohnny Huang 	}, {
242a8bd6d8cSJohnny Huang 		45, 3, 5, "Boot SPI flash size : 32MB"
243a8bd6d8cSJohnny Huang 	}, {
244a8bd6d8cSJohnny Huang 		45, 3, 6, "Boot SPI flash size : 64MB"
245a8bd6d8cSJohnny Huang 	}, {
246a8bd6d8cSJohnny Huang 		45, 3, 7, "Boot SPI flash size : 128MB"
247a8bd6d8cSJohnny Huang 	}, {
248a8bd6d8cSJohnny Huang 		48, 1, 0, "Disable host SPI ABR"
249a8bd6d8cSJohnny Huang 	}, {
250a8bd6d8cSJohnny Huang 		48, 1, 1, "Enable host SPI ABR"
251a8bd6d8cSJohnny Huang 	}, {
252a8bd6d8cSJohnny Huang 		49, 1, 0, "Disable host SPI ABR mode select pin"
253a8bd6d8cSJohnny Huang 	}, {
254a8bd6d8cSJohnny Huang 		49, 1, 1, "Enable host SPI ABR mode select pin"
255a8bd6d8cSJohnny Huang 	}, {
256a8bd6d8cSJohnny Huang 		50, 1, 0, "Host SPI ABR mode : dual SPI flash"
257a8bd6d8cSJohnny Huang 	}, {
258a8bd6d8cSJohnny Huang 		50, 1, 1, "Host SPI ABR mode : single SPI flash"
259a8bd6d8cSJohnny Huang 	}, {
260a8bd6d8cSJohnny Huang 		51, 3, 0, "Host SPI flash size : no define size"
261a8bd6d8cSJohnny Huang 	}, {
262a8bd6d8cSJohnny Huang 		51, 3, 1, "Host SPI flash size : 2MB"
263a8bd6d8cSJohnny Huang 	}, {
264a8bd6d8cSJohnny Huang 		51, 3, 2, "Host SPI flash size : 4MB"
265a8bd6d8cSJohnny Huang 	}, {
266a8bd6d8cSJohnny Huang 		51, 3, 3, "Host SPI flash size : 8MB"
267a8bd6d8cSJohnny Huang 	}, {
268a8bd6d8cSJohnny Huang 		51, 3, 4, "Host SPI flash size : 16MB"
269a8bd6d8cSJohnny Huang 	}, {
270a8bd6d8cSJohnny Huang 		51, 3, 5, "Host SPI flash size : 32MB"
271a8bd6d8cSJohnny Huang 	}, {
272a8bd6d8cSJohnny Huang 		51, 3, 6, "Host SPI flash size : 64MB"
273a8bd6d8cSJohnny Huang 	}, {
274a8bd6d8cSJohnny Huang 		51, 3, 7, "Host SPI flash size : 128MB"
275a8bd6d8cSJohnny Huang 	}, {
276a8bd6d8cSJohnny Huang 		54, 1, 0, "Disable boot SPI auxiliary control pins"
277a8bd6d8cSJohnny Huang 	}, {
278a8bd6d8cSJohnny Huang 		54, 1, 1, "Enable boot SPI auxiliary control pins"
279a8bd6d8cSJohnny Huang 	}, {
280a8bd6d8cSJohnny Huang 		55, 2, 0, "Boot SPI CRTM size : disable CRTM"
281a8bd6d8cSJohnny Huang 	}, {
282a8bd6d8cSJohnny Huang 		55, 2, 1, "Boot SPI CRTM size : 256KB"
283a8bd6d8cSJohnny Huang 	}, {
284a8bd6d8cSJohnny Huang 		55, 2, 2, "Boot SPI CRTM size : 512KB"
285a8bd6d8cSJohnny Huang 	}, {
286a8bd6d8cSJohnny Huang 		55, 2, 3, "Boot SPI CRTM size : 1MB"
287a8bd6d8cSJohnny Huang 	}, {
288a8bd6d8cSJohnny Huang 		57, 2, 0, "Host SPI CRTM size : disable CRTM"
289a8bd6d8cSJohnny Huang 	}, {
290a8bd6d8cSJohnny Huang 		57, 2, 1, "Host SPI CRTM size : 256KB"
291a8bd6d8cSJohnny Huang 	}, {
292a8bd6d8cSJohnny Huang 		57, 2, 2, "Host SPI CRTM size : 512KB"
293a8bd6d8cSJohnny Huang 	}, {
294a8bd6d8cSJohnny Huang 		57, 2, 3, "Host SPI CRTM size : 1MB"
295a8bd6d8cSJohnny Huang 	}, {
296a8bd6d8cSJohnny Huang 		59, 1, 0, "Disable host SPI auxiliary control pins"
297a8bd6d8cSJohnny Huang 	}, {
298a8bd6d8cSJohnny Huang 		59, 1, 1, "Enable host SPI auxiliary control pins"
299a8bd6d8cSJohnny Huang 	}, {
300a8bd6d8cSJohnny Huang 		60, 1, 0, "Disable GPIO pass through"
301a8bd6d8cSJohnny Huang 	}, {
302a8bd6d8cSJohnny Huang 		60, 1, 1, "Enable GPIO pass through"
303a8bd6d8cSJohnny Huang 	}, {
304a8bd6d8cSJohnny Huang 		61, 1, 0, "Enable low security secure boot key"
305a8bd6d8cSJohnny Huang 	}, {
306a8bd6d8cSJohnny Huang 		61, 1, 1, "Disable low security secure boot key"
307a8bd6d8cSJohnny Huang 	}, {
308a8bd6d8cSJohnny Huang 		62, 1, 0, "Disable dedicate GPIO strap pins"
309a8bd6d8cSJohnny Huang 	}, {
310a8bd6d8cSJohnny Huang 		62, 1, 1, "Enable dedicate GPIO strap pins"
311b458cd62SJohnny Huang 	}, {
312b458cd62SJohnny Huang 		63, 1, OTP_REG_RESERVED, ""
313a8bd6d8cSJohnny Huang 	}
31476d13988SJohnny Huang };
315b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = {
316b458cd62SJohnny Huang 	{
317b458cd62SJohnny Huang 		0, 0, 1, 0, "Enable Secure Region programming"
318b458cd62SJohnny Huang 	}, {
319b458cd62SJohnny Huang 		0, 0, 1, 1, "Disable Secure Region programming"
320b458cd62SJohnny Huang 	}, {
321b458cd62SJohnny Huang 		0, 1, 1, 0, "Disable Secure Boot"
322b458cd62SJohnny Huang 	}, {
323b458cd62SJohnny Huang 		0, 1, 1, 1, "Enable Secure Boot"
324b458cd62SJohnny Huang 	}, {
325b458cd62SJohnny Huang 		0, 2, 1, 0, "Initialization programming not done"
326b458cd62SJohnny Huang 	}, {
327b458cd62SJohnny Huang 		0, 2, 1, 1, "Initialization programming done"
328b458cd62SJohnny Huang 	}, {
329b458cd62SJohnny Huang 		0, 3, 1, 0, "User region ECC disable"
330b458cd62SJohnny Huang 	}, {
331b458cd62SJohnny Huang 		0, 3, 1, 1, "User region ECC enable"
332b458cd62SJohnny Huang 	}, {
333b458cd62SJohnny Huang 		0, 4, 1, 0, "Secure Region ECC disable"
334b458cd62SJohnny Huang 	}, {
335b458cd62SJohnny Huang 		0, 4, 1, 1, "Secure Region ECC enable"
336b458cd62SJohnny Huang 	}, {
337b458cd62SJohnny Huang 		0, 5, 1, 0, "Enable low security key"
338b458cd62SJohnny Huang 	}, {
339b458cd62SJohnny Huang 		0, 5, 1, 1, "Disable low security key"
340b458cd62SJohnny Huang 	}, {
341b458cd62SJohnny Huang 		0, 6, 1, 0, "Do not ignore Secure Boot hardware strap"
342b458cd62SJohnny Huang 	}, {
343b458cd62SJohnny Huang 		0, 6, 1, 1, "Ignore Secure Boot hardware strap"
344b458cd62SJohnny Huang 	}, {
345*7332532cSJohnny Huang 		0, 7, 1, 0, "Secure Boot Mode: 1"
346b458cd62SJohnny Huang 	}, {
347*7332532cSJohnny Huang 		0, 7, 1, 1, "Secure Boot Mode: 2"
348b458cd62SJohnny Huang 	}, {
349b458cd62SJohnny Huang 		0, 8, 2, 0, "Single cell mode (recommended)"
350b458cd62SJohnny Huang 	}, {
351b458cd62SJohnny Huang 		0, 8, 2, 1, "Differnetial mode"
352b458cd62SJohnny Huang 	}, {
353b458cd62SJohnny Huang 		0, 8, 2, 2, "Differential-redundant mode"
354b458cd62SJohnny Huang 	}, {
355b458cd62SJohnny Huang 		0, 10, 2, 0, "RSA mode : RSA1024"
356b458cd62SJohnny Huang 	}, {
357b458cd62SJohnny Huang 		0, 10, 2, 1, "RSA mode : RSA2048"
358b458cd62SJohnny Huang 	}, {
359b458cd62SJohnny Huang 		0, 10, 2, 2, "RSA mode : RSA3072"
360b458cd62SJohnny Huang 	}, {
361b458cd62SJohnny Huang 		0, 10, 2, 3, "RSA mode : RSA4096"
362b458cd62SJohnny Huang 	}, {
363b458cd62SJohnny Huang 		0, 12, 2, 0, "SHA mode : SHA224"
364b458cd62SJohnny Huang 	}, {
365b458cd62SJohnny Huang 		0, 12, 2, 1, "SHA mode : SHA256"
366b458cd62SJohnny Huang 	}, {
367b458cd62SJohnny Huang 		0, 12, 2, 2, "SHA mode : SHA384"
368b458cd62SJohnny Huang 	}, {
369b458cd62SJohnny Huang 		0, 12, 2, 3, "SHA mode : SHA512"
370b458cd62SJohnny Huang 	}, {
371b458cd62SJohnny Huang 		0, 14, 2, OTP_REG_RESERVED, ""
372b458cd62SJohnny Huang 	}, {
373b458cd62SJohnny Huang 		0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x"
374b458cd62SJohnny Huang 	}, {
375b458cd62SJohnny Huang 		0, 22, 1, 0, "Secure Region : Writable"
376b458cd62SJohnny Huang 	}, {
377b458cd62SJohnny Huang 		0, 22, 1, 1, "Secure Region : Write Protect"
378b458cd62SJohnny Huang 	}, {
379b458cd62SJohnny Huang 		0, 23, 1, 0, "User Region : Writable"
380b458cd62SJohnny Huang 	}, {
381b458cd62SJohnny Huang 		0, 23, 1, 1, "User Region : Write Protect"
382b458cd62SJohnny Huang 	}, {
383b458cd62SJohnny Huang 		0, 24, 1, 0, "Configure Region : Writable"
384b458cd62SJohnny Huang 	}, {
385b458cd62SJohnny Huang 		0, 24, 1, 1, "Configure Region : Write Protect"
386b458cd62SJohnny Huang 	}, {
387b458cd62SJohnny Huang 		0, 25, 1, 0, "OTP strap Region : Writable"
388b458cd62SJohnny Huang 	}, {
389b458cd62SJohnny Huang 		0, 25, 1, 1, "OTP strap Region : Write Protect"
390b458cd62SJohnny Huang 	}, {
391b458cd62SJohnny Huang 		0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM"
392b458cd62SJohnny Huang 	}, {
393b458cd62SJohnny Huang 		0, 26, 1, 1, "Copy Boot Image to Internal SRAM"
394b458cd62SJohnny Huang 	}, {
395b458cd62SJohnny Huang 		0, 27, 1, 0, "Disable image encryption"
396b458cd62SJohnny Huang 	}, {
397b458cd62SJohnny Huang 		0, 27, 1, 1, "Enable image encryption"
398b458cd62SJohnny Huang 	}, {
399b458cd62SJohnny Huang 		0, 28, 1, OTP_REG_RESERVED, ""
400b458cd62SJohnny Huang 	}, {
401b458cd62SJohnny Huang 		0, 29, 1, 0, "OTP key retire Region : Writable"
402b458cd62SJohnny Huang 	}, {
403b458cd62SJohnny Huang 		0, 29, 1, 1, "OTP key retire Region : Write Protect"
404b458cd62SJohnny Huang 	}, {
405b458cd62SJohnny Huang 		0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable"
406b458cd62SJohnny Huang 	}, {
407b458cd62SJohnny Huang 		0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable"
408b458cd62SJohnny Huang 	}, {
409b458cd62SJohnny Huang 		0, 31, 1, 0, "SIPROM Mlock memory lock disable"
410b458cd62SJohnny Huang 	}, {
411b458cd62SJohnny Huang 		0, 31, 1, 1, "SIPROM Mlock memory lock enable"
412b458cd62SJohnny Huang 	}, {
413b458cd62SJohnny Huang 		2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x"
414b458cd62SJohnny Huang 	}, {
415b458cd62SJohnny Huang 		2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x"
416b458cd62SJohnny Huang 	}, {
417b458cd62SJohnny Huang 		3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x"
418b458cd62SJohnny Huang 	}, {
419b458cd62SJohnny Huang 		4, 0, 8, OTP_REG_VALID_BIT, "Keys valid  : %d"
420b458cd62SJohnny Huang 	}, {
421b458cd62SJohnny Huang 		4, 16, 8, OTP_REG_VALID_BIT, "Keys retire  : %d"
422b458cd62SJohnny Huang 	}, {
423b458cd62SJohnny Huang 		5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x"
424b458cd62SJohnny Huang 	}, {
425b458cd62SJohnny Huang 		6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x"
426b458cd62SJohnny Huang 	}, {
42707baa4e8SJohnny Huang 		7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge"
42807baa4e8SJohnny Huang 	}, {
42907baa4e8SJohnny Huang 		7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge"
43007baa4e8SJohnny Huang 	}, {
43107baa4e8SJohnny Huang 		7, 1, 1, 0, "Force enable UART5 debug port function"
43207baa4e8SJohnny Huang 	}, {
43307baa4e8SJohnny Huang 		7, 1, 1, 1, "Force disable UART5 debug port function"
43407baa4e8SJohnny Huang 	}, {
43507baa4e8SJohnny Huang 		7, 2, 1, 0, "Force enable XDMA function"
43607baa4e8SJohnny Huang 	}, {
43707baa4e8SJohnny Huang 		7, 2, 1, 1, "Force disable XDMA function"
43807baa4e8SJohnny Huang 	}, {
43907baa4e8SJohnny Huang 		7, 3, 1, 0, "Force enable APB to PCIE device bridge"
44007baa4e8SJohnny Huang 	}, {
44107baa4e8SJohnny Huang 		7, 3, 1, 1, "Force disable APB to PCIE device bridge"
44207baa4e8SJohnny Huang 	}, {
44307baa4e8SJohnny Huang 		7, 4, 1, 0, "Force enable APB to PCIE bridge config access"
44407baa4e8SJohnny Huang 	}, {
44507baa4e8SJohnny Huang 		7, 4, 1, 1, "Force disable APB to PCIE bridge config access"
44607baa4e8SJohnny Huang 	}, {
44707baa4e8SJohnny Huang 		7, 5, 1, 0, "Force enable PCIE bus trace buffer"
44807baa4e8SJohnny Huang 	}, {
44907baa4e8SJohnny Huang 		7, 5, 1, 1, "Force disable PCIE bus trace buffer"
45007baa4e8SJohnny Huang 	}, {
45107baa4e8SJohnny Huang 		7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex"
45207baa4e8SJohnny Huang 	}, {
45307baa4e8SJohnny Huang 		7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex"
45407baa4e8SJohnny Huang 	}, {
45507baa4e8SJohnny Huang 		7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge"
45607baa4e8SJohnny Huang 	}, {
45707baa4e8SJohnny Huang 		7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge"
45807baa4e8SJohnny Huang 	}, {
45907baa4e8SJohnny Huang 		7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1"
46007baa4e8SJohnny Huang 	}, {
46107baa4e8SJohnny Huang 		7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1"
46207baa4e8SJohnny Huang 	}, {
46307baa4e8SJohnny Huang 		7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2"
46407baa4e8SJohnny Huang 	}, {
46507baa4e8SJohnny Huang 		7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2"
46607baa4e8SJohnny Huang 	}, {
46707baa4e8SJohnny Huang 		7, 19, 1, 0, "Force enable UART1 debug port function"
46807baa4e8SJohnny Huang 	}, {
46907baa4e8SJohnny Huang 		7, 19, 1, 1, "Force disable UART1 debug port function"
47007baa4e8SJohnny Huang 	}, {
47107baa4e8SJohnny Huang 		7, 31, 1, 0, "Disable chip security setting"
47207baa4e8SJohnny Huang 	}, {
47307baa4e8SJohnny Huang 		7, 31, 1, 1, "Enable chip security setting"
47407baa4e8SJohnny Huang 	}, {
475b458cd62SJohnny Huang 		8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x"
476b458cd62SJohnny Huang 	}, {
477b458cd62SJohnny Huang 		10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x"
478b458cd62SJohnny Huang 	}, {
479b458cd62SJohnny Huang 		11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x"
480b458cd62SJohnny Huang 	}
481b458cd62SJohnny Huang };
4822a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
48369d5fd8fSJohnny Huang {
48469d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
48569d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
48669d5fd8fSJohnny Huang 	udelay(2);
48769d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
48869d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
48969d5fd8fSJohnny Huang }
49069d5fd8fSJohnny Huang 
4912a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
49269d5fd8fSJohnny Huang {
49369d5fd8fSJohnny Huang 	int config_offset;
49469d5fd8fSJohnny Huang 
49569d5fd8fSJohnny Huang 	config_offset = 0x800;
49669d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
49769d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
49869d5fd8fSJohnny Huang 
49969d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
50069d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
50169d5fd8fSJohnny Huang 	udelay(2);
50269d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
50369d5fd8fSJohnny Huang }
50469d5fd8fSJohnny Huang 
50569d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
50669d5fd8fSJohnny Huang {
50769d5fd8fSJohnny Huang 	int i;
50869d5fd8fSJohnny Huang 	uint32_t ret[1];
50969d5fd8fSJohnny Huang 
51069d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
5112a856b9aSJohnny Huang 		return OTP_USAGE;
51269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
51369d5fd8fSJohnny Huang 		otp_read_config(i, ret);
514a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
51569d5fd8fSJohnny Huang 	}
51669d5fd8fSJohnny Huang 	printf("\n");
5172a856b9aSJohnny Huang 	return OTP_SUCCESS;
51869d5fd8fSJohnny Huang }
51969d5fd8fSJohnny Huang 
52069d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
52169d5fd8fSJohnny Huang {
52269d5fd8fSJohnny Huang 	int i;
52369d5fd8fSJohnny Huang 	uint32_t ret[2];
52469d5fd8fSJohnny Huang 
52569d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
5262a856b9aSJohnny Huang 		return OTP_USAGE;
52769d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
52869d5fd8fSJohnny Huang 		otp_read_data(i, ret);
52969d5fd8fSJohnny Huang 		if (i % 4 == 0)
53069d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
53169d5fd8fSJohnny Huang 		else
53269d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
53369d5fd8fSJohnny Huang 
53469d5fd8fSJohnny Huang 	}
53569d5fd8fSJohnny Huang 	printf("\n");
5362a856b9aSJohnny Huang 	return OTP_SUCCESS;
53769d5fd8fSJohnny Huang }
53869d5fd8fSJohnny Huang 
53969d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
54069d5fd8fSJohnny Huang {
54169d5fd8fSJohnny Huang 	uint32_t ret;
54269d5fd8fSJohnny Huang 	uint32_t *buf;
54369d5fd8fSJohnny Huang 
54469d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
54569d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
54669d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
54769d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
54869d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
54969d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
55069d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
55169d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
55269d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
55369d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
55469d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
55569d5fd8fSJohnny Huang 	udelay(10);
55669d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
55769d5fd8fSJohnny Huang 	if (ret & 0x1)
55869d5fd8fSJohnny Huang 		return 0;
55969d5fd8fSJohnny Huang 	else
56069d5fd8fSJohnny Huang 		return -1;
56169d5fd8fSJohnny Huang }
56269d5fd8fSJohnny Huang 
56369d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
56469d5fd8fSJohnny Huang {
56569d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
56669d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
56769d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
56869d5fd8fSJohnny Huang 	udelay(100);
56969d5fd8fSJohnny Huang }
57069d5fd8fSJohnny Huang 
57169d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
57269d5fd8fSJohnny Huang {
57369d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
57469d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
57569d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
57669d5fd8fSJohnny Huang 	udelay(85);
57769d5fd8fSJohnny Huang }
57869d5fd8fSJohnny Huang 
579a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
58069d5fd8fSJohnny Huang {
58169d5fd8fSJohnny Huang 	int ret;
58269d5fd8fSJohnny Huang 
58369d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
58469d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
58569d5fd8fSJohnny Huang 	udelay(2);
58669d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
587a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
58869d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
58969d5fd8fSJohnny Huang 		return 0;
59069d5fd8fSJohnny Huang 	else
59169d5fd8fSJohnny Huang 		return -1;
59269d5fd8fSJohnny Huang }
59369d5fd8fSJohnny Huang 
594d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
5954c1c9b35SJohnny Huang {
5964c1c9b35SJohnny Huang 	uint32_t ret[2];
5974c1c9b35SJohnny Huang 
5984c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
5994c1c9b35SJohnny Huang 
6004c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
6014c1c9b35SJohnny Huang 		writel(otp_addr, 0x1e6f2010); //Read address
6024c1c9b35SJohnny Huang 	else
6034c1c9b35SJohnny Huang 		writel(otp_addr - 1, 0x1e6f2010); //Read address
6044c1c9b35SJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
6054c1c9b35SJohnny Huang 	udelay(2);
6064c1c9b35SJohnny Huang 	ret[0] = readl(0x1e6f2020);
6074c1c9b35SJohnny Huang 	ret[1] = readl(0x1e6f2024);
6084c1c9b35SJohnny Huang 	if (size == 1) {
6094c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
6104c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
611d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
6124c1c9b35SJohnny Huang 				compare[0] = 0;
6134c1c9b35SJohnny Huang 				return 0;
6144c1c9b35SJohnny Huang 			} else {
6154c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
6164c1c9b35SJohnny Huang 				return -1;
6174c1c9b35SJohnny Huang 			}
6184c1c9b35SJohnny Huang 
6194c1c9b35SJohnny Huang 		} else {
6204c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
621d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
6224c1c9b35SJohnny Huang 				compare[0] = ~0;
6234c1c9b35SJohnny Huang 				return 0;
6244c1c9b35SJohnny Huang 			} else {
625d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
6264c1c9b35SJohnny Huang 				return -1;
6274c1c9b35SJohnny Huang 			}
6284c1c9b35SJohnny Huang 		}
6294c1c9b35SJohnny Huang 	} else if (size == 2) {
6304c1c9b35SJohnny Huang 		// otp_addr should be even
631d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
6324c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
6334c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
6344c1c9b35SJohnny Huang 			compare[0] = 0;
6354c1c9b35SJohnny Huang 			compare[1] = ~0;
6364c1c9b35SJohnny Huang 			return 0;
6374c1c9b35SJohnny Huang 		} else {
6384c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
6394c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
6404c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
6414c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
6424c1c9b35SJohnny Huang 			return -1;
6434c1c9b35SJohnny Huang 		}
6444c1c9b35SJohnny Huang 	} else {
6454c1c9b35SJohnny Huang 		return -1;
6464c1c9b35SJohnny Huang 	}
6474c1c9b35SJohnny Huang }
6484c1c9b35SJohnny Huang 
6497e22f42dSJohnny Huang static void otp_soak(int soak)
650d90825e2SJohnny Huang {
651d90825e2SJohnny Huang 	if (soak) {
652d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
653d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
654d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
655d90825e2SJohnny Huang 		writel(0x041930d4, 0x1e602008); //soak program
656d90825e2SJohnny Huang 	} else {
657d90825e2SJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
658d90825e2SJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
659d90825e2SJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
660d90825e2SJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
661d90825e2SJohnny Huang 	}
662d90825e2SJohnny Huang }
663d90825e2SJohnny Huang 
664d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
665d90825e2SJohnny Huang {
666d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
667d90825e2SJohnny Huang 
668d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
669d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
670d90825e2SJohnny Huang 			continue;
671d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
672d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
673d90825e2SJohnny Huang 			if (bit_value)
674d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
675d90825e2SJohnny Huang 			else
676d90825e2SJohnny Huang 				continue;
677d90825e2SJohnny Huang 		} else {
678d90825e2SJohnny Huang 			prog_address |= 1 << 15;
679d90825e2SJohnny Huang 			if (bit_value)
680d90825e2SJohnny Huang 				continue;
681d90825e2SJohnny Huang 			else
682d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
683d90825e2SJohnny Huang 		}
684d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
685d90825e2SJohnny Huang 	}
686d90825e2SJohnny Huang }
687d90825e2SJohnny Huang 
68876d13988SJohnny Huang 
68976d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap)
69076d13988SJohnny Huang {
69176d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
69276d13988SJohnny Huang 	int i, j;
69376d13988SJohnny Huang 
69476d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
69576d13988SJohnny Huang 		otpstrap[j].value = 0;
69676d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
69776d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
69876d13988SJohnny Huang 		otpstrap[j].protected = 0;
69976d13988SJohnny Huang 	}
70076d13988SJohnny Huang 
70176d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
70276d13988SJohnny Huang 		int option = (i - 16) / 2;
70376d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
70476d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
70576d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
70676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
70776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
70876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
70976d13988SJohnny Huang 			}
71076d13988SJohnny Huang 			if (bit_value == 1)
71176d13988SJohnny Huang 				otpstrap[j].remain_times --;
71276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
71376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
71476d13988SJohnny Huang 		}
71576d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
71676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
71776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
71876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
71976d13988SJohnny Huang 			}
72076d13988SJohnny Huang 			if (bit_value == 1)
72176d13988SJohnny Huang 				otpstrap[j].remain_times --;
72276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
72376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
72476d13988SJohnny Huang 		}
72576d13988SJohnny Huang 	}
72676d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
72776d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
72876d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
72976d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
73076d13988SJohnny Huang 			otpstrap[j].protected = 1;
73176d13988SJohnny Huang 	}
73276d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
73376d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
73476d13988SJohnny Huang 			otpstrap[j].protected = 1;
73576d13988SJohnny Huang 	}
73676d13988SJohnny Huang }
73776d13988SJohnny Huang 
738b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG)
73969d5fd8fSJohnny Huang {
740442839bbSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[12];
741b458cd62SJohnny Huang 	uint32_t mask;
742b458cd62SJohnny Huang 	uint32_t dw_offset;
743b458cd62SJohnny Huang 	uint32_t bit_offset;
744b458cd62SJohnny Huang 	uint32_t otp_value;
745b458cd62SJohnny Huang 	uint32_t otp_keep;
746b458cd62SJohnny Huang 	int fail = 0;
747b458cd62SJohnny Huang 	int valid_bit = 0;
74866f2f8e5SJohnny Huang 	int i;
74966f2f8e5SJohnny Huang 
750737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
75166f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
752b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
753b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
754b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
755b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
756b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
757b458cd62SJohnny Huang 		otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask;
758b458cd62SJohnny Huang 
759b458cd62SJohnny Huang 		if (otp_keep == mask) {
760b458cd62SJohnny Huang 			continue;
761b458cd62SJohnny Huang 		} else if (otp_keep != 0) {
762b458cd62SJohnny Huang 			fail = 1;
763b458cd62SJohnny Huang 		}
764b458cd62SJohnny Huang 
765b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
766b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
767b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
768b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
769b458cd62SJohnny Huang 			continue;
770b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
771b458cd62SJohnny Huang 
772b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
773b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
77466f2f8e5SJohnny Huang 		} else {
775b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
776b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
777b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
77866f2f8e5SJohnny Huang 		}
779b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
780b458cd62SJohnny Huang 
781b458cd62SJohnny Huang 		if (fail) {
782b458cd62SJohnny Huang 			printf("Keep mask error\n");
783b458cd62SJohnny Huang 		} else {
784b458cd62SJohnny Huang 			if (a0_conf_info[i].value == OTP_REG_RESERVED) {
785b458cd62SJohnny Huang 				printf("Reserved\n");
786b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
787b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, otp_value);
788b458cd62SJohnny Huang 				printf("\n");
789b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
790b458cd62SJohnny Huang 				if (otp_value != 0) {
791b458cd62SJohnny Huang 					for (i = 0; i < 7; i++) {
792b458cd62SJohnny Huang 						if (otp_value == (1 << i)) {
793b458cd62SJohnny Huang 							valid_bit = i + 1;
79466f2f8e5SJohnny Huang 						}
795b458cd62SJohnny Huang 					}
796b458cd62SJohnny Huang 				} else {
797b458cd62SJohnny Huang 					valid_bit = 0;
798b458cd62SJohnny Huang 				}
799b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, valid_bit);
800b458cd62SJohnny Huang 				printf("\n");
801b458cd62SJohnny Huang 			} else {
802b458cd62SJohnny Huang 				printf("%s\n", a0_conf_info[i].information);
803b458cd62SJohnny Huang 			}
804b458cd62SJohnny Huang 		}
805b458cd62SJohnny Huang 	}
806b458cd62SJohnny Huang 
807b458cd62SJohnny Huang 	if (fail)
808b458cd62SJohnny Huang 		return OTP_FAILURE;
809b458cd62SJohnny Huang 
81066f2f8e5SJohnny Huang 	return OTP_SUCCESS;
81166f2f8e5SJohnny Huang }
81266f2f8e5SJohnny Huang 
8132d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
81466f2f8e5SJohnny Huang {
815b458cd62SJohnny Huang 	uint32_t OTPCFG[12];
816b458cd62SJohnny Huang 	uint32_t mask;
817b458cd62SJohnny Huang 	uint32_t dw_offset;
818b458cd62SJohnny Huang 	uint32_t bit_offset;
819b458cd62SJohnny Huang 	uint32_t otp_value;
820b458cd62SJohnny Huang 	int valid_bit = 0;
82166f2f8e5SJohnny Huang 	int i;
82266f2f8e5SJohnny Huang 
82366f2f8e5SJohnny Huang 	for (i = 0; i < 12; i++)
82466f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
82566f2f8e5SJohnny Huang 
82666f2f8e5SJohnny Huang 
827b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
828b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
829b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
8302d4b0742SJohnny Huang 		if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset)
8312d4b0742SJohnny Huang 			continue;
832b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
833b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
834b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
835b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
836b458cd62SJohnny Huang 
837b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
838b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
839b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
840b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
841b458cd62SJohnny Huang 			continue;
842b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
843b458cd62SJohnny Huang 
844b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
845b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
846b458cd62SJohnny Huang 		} else {
847b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
848b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
849b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
850b458cd62SJohnny Huang 		}
851b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
852b458cd62SJohnny Huang 
853b458cd62SJohnny Huang 		if (a0_conf_info[i].value == OTP_REG_RESERVED) {
854b458cd62SJohnny Huang 			printf("Reserved\n");
855b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
856b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, otp_value);
857b458cd62SJohnny Huang 			printf("\n");
858b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
859b458cd62SJohnny Huang 			if (otp_value != 0) {
860b458cd62SJohnny Huang 				for (i = 0; i < 7; i++) {
861b458cd62SJohnny Huang 					if (otp_value == (1 << i)) {
862b458cd62SJohnny Huang 						valid_bit = i + 1;
863b458cd62SJohnny Huang 					}
864b458cd62SJohnny Huang 				}
865b458cd62SJohnny Huang 			} else {
866b458cd62SJohnny Huang 				valid_bit = 0;
867b458cd62SJohnny Huang 			}
868b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, valid_bit);
869b458cd62SJohnny Huang 			printf("\n");
870b458cd62SJohnny Huang 		} else {
871b458cd62SJohnny Huang 			printf("%s\n", a0_conf_info[i].information);
872b458cd62SJohnny Huang 		}
873b458cd62SJohnny Huang 	}
874b458cd62SJohnny Huang 	return OTP_SUCCESS;
87566f2f8e5SJohnny Huang }
87666f2f8e5SJohnny Huang 
877b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP)
87876d13988SJohnny Huang {
879a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
880a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
88176d13988SJohnny Huang 	int i;
882a8bd6d8cSJohnny Huang 	int fail = 0;
883a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
884a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
885a8bd6d8cSJohnny Huang 	uint32_t mask;
886a8bd6d8cSJohnny Huang 	uint32_t otp_value;
887a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
888a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
88976d13988SJohnny Huang 
890a8bd6d8cSJohnny Huang 	printf("BIT(hex)   Value       Protect     Description\n");
891a8bd6d8cSJohnny Huang 	printf("__________________________________________________________________________________________\n");
892b458cd62SJohnny Huang 
893a8bd6d8cSJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
894a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].bit_offset > 32) {
895a8bd6d8cSJohnny Huang 			dw_offset = 1;
896a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset - 32;
897a8bd6d8cSJohnny Huang 		} else {
898a8bd6d8cSJohnny Huang 			dw_offset = 0;
899a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset;
900a8bd6d8cSJohnny Huang 		}
90176d13988SJohnny Huang 
902a8bd6d8cSJohnny Huang 		mask = BIT(a0_strap_info[i].length) - 1;
903a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
904a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
905a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
906a8bd6d8cSJohnny Huang 
907a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
908a8bd6d8cSJohnny Huang 			continue;
909a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
910a8bd6d8cSJohnny Huang 			fail = 1;
911a8bd6d8cSJohnny Huang 		}
912a8bd6d8cSJohnny Huang 
913a8bd6d8cSJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
914a8bd6d8cSJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
915a8bd6d8cSJohnny Huang 			continue;
916a8bd6d8cSJohnny Huang 
917a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].length == 1) {
918b458cd62SJohnny Huang 			printf("0x%-9X", a0_strap_info[i].bit_offset);
919a8bd6d8cSJohnny Huang 		} else {
920b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
921a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1,
922a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset);
923a8bd6d8cSJohnny Huang 		}
924a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
925a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
926a8bd6d8cSJohnny Huang 
927a8bd6d8cSJohnny Huang 		if (fail) {
928a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
929a8bd6d8cSJohnny Huang 		} else {
930a8bd6d8cSJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
931a8bd6d8cSJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
932a8bd6d8cSJohnny Huang 			else
933a8bd6d8cSJohnny Huang 				printf("Reserved\n");
934a8bd6d8cSJohnny Huang 		}
935a8bd6d8cSJohnny Huang 	}
936a8bd6d8cSJohnny Huang 
937a8bd6d8cSJohnny Huang 	if (fail)
93876d13988SJohnny Huang 		return OTP_FAILURE;
93976d13988SJohnny Huang 
94076d13988SJohnny Huang 	return OTP_SUCCESS;
94176d13988SJohnny Huang }
94276d13988SJohnny Huang 
943b458cd62SJohnny Huang static int otp_print_strap_info(int view)
94476d13988SJohnny Huang {
94576d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
94607baa4e8SJohnny Huang 	int i, j;
947b458cd62SJohnny Huang 	int fail = 0;
948b458cd62SJohnny Huang 	uint32_t bit_offset;
949b458cd62SJohnny Huang 	uint32_t length;
950b458cd62SJohnny Huang 	uint32_t otp_value;
951b458cd62SJohnny Huang 	uint32_t otp_protect;
95276d13988SJohnny Huang 
95376d13988SJohnny Huang 	otp_strp_status(strap_status);
95476d13988SJohnny Huang 
955b458cd62SJohnny Huang 	if (view) {
95607baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
95707baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
95807baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
95907baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
960b458cd62SJohnny Huang 	} else {
961b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
962b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
96376d13988SJohnny Huang 	}
964b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
965b458cd62SJohnny Huang 		otp_value = 0;
966b458cd62SJohnny Huang 		bit_offset = a0_strap_info[i].bit_offset;
967b458cd62SJohnny Huang 		length = a0_strap_info[i].length;
968b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
969c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
970c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
971b458cd62SJohnny Huang 		}
972b458cd62SJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
973b458cd62SJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
974b458cd62SJohnny Huang 			continue;
975b458cd62SJohnny Huang 		if (view) {
976b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
977b458cd62SJohnny Huang 				printf("0x%-7X", a0_strap_info[i].bit_offset + j);
978b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
97907baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
980b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
981b458cd62SJohnny Huang 				if (a0_strap_info[i].value == OTP_REG_RESERVED) {
982b458cd62SJohnny Huang 					printf(" Reserved\n");
983b458cd62SJohnny Huang 					continue;
984b458cd62SJohnny Huang 				}
985b458cd62SJohnny Huang 				if (length == 1) {
986b458cd62SJohnny Huang 					printf(" %s\n", a0_strap_info[i].information);
987b458cd62SJohnny Huang 					continue;
98876d13988SJohnny Huang 				}
98976d13988SJohnny Huang 
990b458cd62SJohnny Huang 				if (j == 0)
991b458cd62SJohnny Huang 					printf("/%s\n", a0_strap_info[i].information);
992b458cd62SJohnny Huang 				else if (j == length - 1)
993b458cd62SJohnny Huang 					printf("\\ \"\n");
994b458cd62SJohnny Huang 				else
995b458cd62SJohnny Huang 					printf("| \"\n");
99676d13988SJohnny Huang 			}
997b458cd62SJohnny Huang 		} else {
998c947ef08SJohnny Huang 			if (length == 1) {
999b458cd62SJohnny Huang 				printf("0x%-9X", a0_strap_info[i].bit_offset);
1000b458cd62SJohnny Huang 			} else {
1001b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1002b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1003b458cd62SJohnny Huang 			}
1004b458cd62SJohnny Huang 
1005b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1006b458cd62SJohnny Huang 
1007b458cd62SJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
1008b458cd62SJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
1009b458cd62SJohnny Huang 			else
1010b458cd62SJohnny Huang 				printf("Reserved\n");
1011b458cd62SJohnny Huang 		}
1012b458cd62SJohnny Huang 	}
1013b458cd62SJohnny Huang 
1014b458cd62SJohnny Huang 	if (fail)
1015b458cd62SJohnny Huang 		return OTP_FAILURE;
1016b458cd62SJohnny Huang 
1017b458cd62SJohnny Huang 	return OTP_SUCCESS;
1018b458cd62SJohnny Huang }
1019b458cd62SJohnny Huang 
102069d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
102169d5fd8fSJohnny Huang {
102269d5fd8fSJohnny Huang 	int i;
102369d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
102469d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
102569d5fd8fSJohnny Huang 		if (i % 16 == 0) {
102669d5fd8fSJohnny Huang 			printf("%04X: ", i);
102769d5fd8fSJohnny Huang 		}
102869d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
102969d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
103069d5fd8fSJohnny Huang 			printf("\n");
103169d5fd8fSJohnny Huang 		}
103269d5fd8fSJohnny Huang 	}
103369d5fd8fSJohnny Huang }
103469d5fd8fSJohnny Huang 
10357f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
103669d5fd8fSJohnny Huang {
103769d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
103869d5fd8fSJohnny Huang 	char *byte_buf;
103969d5fd8fSJohnny Huang 	int i = 0, len = 0;
104069d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
104169d5fd8fSJohnny Huang 	while (1) {
104269d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
104369d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
104469d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
104569d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
104669d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
104769d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
10487f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
104969d5fd8fSJohnny Huang 		printf("Key Type: ");
105069d5fd8fSJohnny Huang 		switch (key_type) {
105169d5fd8fSJohnny Huang 		case 0:
105269d5fd8fSJohnny Huang 			printf("AES-256 as OEM platform key for image encryption/decryption\n");
105369d5fd8fSJohnny Huang 			break;
105469d5fd8fSJohnny Huang 		case 1:
105569d5fd8fSJohnny Huang 			printf("AES-256 as secret vault key\n");
105669d5fd8fSJohnny Huang 			break;
105769d5fd8fSJohnny Huang 		case 4:
105869d5fd8fSJohnny Huang 			printf("HMAC as encrypted OEM HMAC keys in Mode 1\n");
105969d5fd8fSJohnny Huang 			break;
106069d5fd8fSJohnny Huang 		case 8:
106169d5fd8fSJohnny Huang 			printf("RSA-public as OEM DSS public keys in Mode 2\n");
106269d5fd8fSJohnny Huang 			break;
106369d5fd8fSJohnny Huang 		case 9:
106469d5fd8fSJohnny Huang 			printf("RSA-public as SOC public key\n");
106569d5fd8fSJohnny Huang 			break;
106669d5fd8fSJohnny Huang 		case 10:
106769d5fd8fSJohnny Huang 			printf("RSA-public as AES key decryption key\n");
106869d5fd8fSJohnny Huang 			break;
106969d5fd8fSJohnny Huang 		case 13:
107069d5fd8fSJohnny Huang 			printf("RSA-private as SOC private key\n");
107169d5fd8fSJohnny Huang 			break;
107269d5fd8fSJohnny Huang 		case 14:
107369d5fd8fSJohnny Huang 			printf("RSA-private as AES key decryption key\n");
107469d5fd8fSJohnny Huang 			break;
107569d5fd8fSJohnny Huang 		default:
107669d5fd8fSJohnny Huang 			printf("key_type error: %x\n", key_type);
107769d5fd8fSJohnny Huang 			return -1;
107869d5fd8fSJohnny Huang 		}
107969d5fd8fSJohnny Huang 		if (key_type == 4) {
108069d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
108169d5fd8fSJohnny Huang 			switch (key_length) {
108269d5fd8fSJohnny Huang 			case 0:
108369d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
108469d5fd8fSJohnny Huang 				break;
108569d5fd8fSJohnny Huang 			case 1:
108669d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
108769d5fd8fSJohnny Huang 				break;
108869d5fd8fSJohnny Huang 			case 2:
108969d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
109069d5fd8fSJohnny Huang 				break;
109169d5fd8fSJohnny Huang 			case 3:
109269d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
109369d5fd8fSJohnny Huang 				break;
109469d5fd8fSJohnny Huang 			}
1095cd1610b4SJohnny Huang 		} else if (key_type != 0 && key_type != 1) {
109669d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
109769d5fd8fSJohnny Huang 			switch (key_length) {
109869d5fd8fSJohnny Huang 			case 0:
109969d5fd8fSJohnny Huang 				printf("RSA1024\n");
110069d5fd8fSJohnny Huang 				len = 0x100;
110169d5fd8fSJohnny Huang 				break;
110269d5fd8fSJohnny Huang 			case 1:
110369d5fd8fSJohnny Huang 				printf("RSA2048\n");
110469d5fd8fSJohnny Huang 				len = 0x200;
110569d5fd8fSJohnny Huang 				break;
110669d5fd8fSJohnny Huang 			case 2:
110769d5fd8fSJohnny Huang 				printf("RSA3072\n");
110869d5fd8fSJohnny Huang 				len = 0x300;
110969d5fd8fSJohnny Huang 				break;
111069d5fd8fSJohnny Huang 			case 3:
111169d5fd8fSJohnny Huang 				printf("RSA4096\n");
111269d5fd8fSJohnny Huang 				len = 0x400;
111369d5fd8fSJohnny Huang 				break;
111469d5fd8fSJohnny Huang 			}
111569d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
111669d5fd8fSJohnny Huang 		}
111769d5fd8fSJohnny Huang 		if (key_type == 4 || key_type == 8)
111869d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
111969d5fd8fSJohnny Huang 		printf("Key Value:\n");
112069d5fd8fSJohnny Huang 		if (key_type == 4) {
112169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
112269d5fd8fSJohnny Huang 		} else if (key_type == 0 || key_type == 1) {
112369d5fd8fSJohnny Huang 			printf("AES Key:\n");
112469d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
112569d5fd8fSJohnny Huang 			printf("AES IV:\n");
112669d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + 0x20], 0x10);
112769d5fd8fSJohnny Huang 
112869d5fd8fSJohnny Huang 		} else {
112969d5fd8fSJohnny Huang 			printf("RSA mod:\n");
113069d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
113169d5fd8fSJohnny Huang 			printf("RSA exp:\n");
113269d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
113369d5fd8fSJohnny Huang 		}
113469d5fd8fSJohnny Huang 		if (last)
113569d5fd8fSJohnny Huang 			break;
113669d5fd8fSJohnny Huang 		i++;
113769d5fd8fSJohnny Huang 	}
113869d5fd8fSJohnny Huang 	return 0;
113969d5fd8fSJohnny Huang }
114069d5fd8fSJohnny Huang 
1141a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
114269d5fd8fSJohnny Huang {
1143a6d0d645SJohnny Huang 	int i, k;
1144d90825e2SJohnny Huang 	int pass = 0;
1145d90825e2SJohnny Huang 	int soak = 0;
1146a6d0d645SJohnny Huang 	uint32_t prog_address;
1147a6d0d645SJohnny Huang 	uint32_t data[12];
1148a6d0d645SJohnny Huang 	uint32_t compare[2];
1149d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[12];
1150d90825e2SJohnny Huang 	uint32_t data_masked;
1151d90825e2SJohnny Huang 	uint32_t buf_masked;
115269d5fd8fSJohnny Huang 
1153a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1154a6d0d645SJohnny Huang 
1155a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1156a6d0d645SJohnny Huang 	for (i = 0; i < 12 ; i ++) {
1157a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "");
115869d5fd8fSJohnny Huang 		prog_address = 0x800;
1159a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1160a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1161a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1162a6d0d645SJohnny Huang 	}
1163a6d0d645SJohnny Huang 
1164a6d0d645SJohnny Huang 	printf("Check writable...\n");
1165a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1166d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1167d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1168d90825e2SJohnny Huang 		if (data_masked == buf_masked)
116969d5fd8fSJohnny Huang 			continue;
1170d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1171a6d0d645SJohnny Huang 			continue;
1172a6d0d645SJohnny Huang 		} else {
1173a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1174a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1175a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1176a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
11772a856b9aSJohnny Huang 			return OTP_FAILURE;
1178a6d0d645SJohnny Huang 		}
1179a6d0d645SJohnny Huang 	}
1180a6d0d645SJohnny Huang 
1181a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1182a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1183d90825e2SJohnny Huang 	otp_soak(0);
1184a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1185d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1186d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1187a6d0d645SJohnny Huang 		prog_address = 0x800;
1188a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1189a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1190d90825e2SJohnny Huang 		if (data_masked == buf_masked) {
1191a6d0d645SJohnny Huang 			printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]);
1192a6d0d645SJohnny Huang 			continue;
1193a6d0d645SJohnny Huang 		}
1194d90825e2SJohnny Huang 		if (soak) {
1195d90825e2SJohnny Huang 			soak = 0;
1196d90825e2SJohnny Huang 			otp_soak(0);
1197d90825e2SJohnny Huang 		}
1198a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "[%03X]=%08X    ", prog_address, buf[i]);
1199a6d0d645SJohnny Huang 
1200d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1201a6d0d645SJohnny Huang 
120269d5fd8fSJohnny Huang 		pass = 0;
120369d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1204d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1205d90825e2SJohnny Huang 				if (soak == 0) {
1206d90825e2SJohnny Huang 					soak = 1;
1207d90825e2SJohnny Huang 					otp_soak(1);
1208d90825e2SJohnny Huang 				}
1209a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1210a6d0d645SJohnny Huang 			} else {
121169d5fd8fSJohnny Huang 				pass = 1;
121269d5fd8fSJohnny Huang 				break;
121369d5fd8fSJohnny Huang 			}
121469d5fd8fSJohnny Huang 		}
1215a6d0d645SJohnny Huang 	}
1216a6d0d645SJohnny Huang 
121769d5fd8fSJohnny Huang 	if (!pass)
12182a856b9aSJohnny Huang 		return OTP_FAILURE;
1219a6d0d645SJohnny Huang 
12202a856b9aSJohnny Huang 	return OTP_SUCCESS;
1221d90825e2SJohnny Huang 
122269d5fd8fSJohnny Huang }
122369d5fd8fSJohnny Huang 
122469d5fd8fSJohnny Huang 
122576d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
122669d5fd8fSJohnny Huang {
122769d5fd8fSJohnny Huang 	int i;
122869d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
122969d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
123069d5fd8fSJohnny Huang 	int bit, pbit, kbit;
123169d5fd8fSJohnny Huang 	int fail = 0;
1232a6af4a17SJohnny Huang 	int skip = -1;
123366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
123469d5fd8fSJohnny Huang 
123569d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
123669d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
123769d5fd8fSJohnny Huang 		if (i < 32) {
123869d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
123969d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
124069d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
124169d5fd8fSJohnny Huang 		} else {
124269d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
124369d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
124469d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
124569d5fd8fSJohnny Huang 		}
124669d5fd8fSJohnny Huang 
124769d5fd8fSJohnny Huang 		if (kbit == 1) {
124869d5fd8fSJohnny Huang 			continue;
124969d5fd8fSJohnny Huang 		} else {
1250a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
125169d5fd8fSJohnny Huang 		}
125269d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
125369d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1254a6af4a17SJohnny Huang 			if (skip == -1)
1255a6af4a17SJohnny Huang 				skip = 1;
125669d5fd8fSJohnny Huang 			continue;
1257a6af4a17SJohnny Huang 		} else {
1258a6af4a17SJohnny Huang 			skip = 0;
125969d5fd8fSJohnny Huang 		}
126069d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
126169d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
126269d5fd8fSJohnny Huang 			fail = 1;
126369d5fd8fSJohnny Huang 			continue;
126469d5fd8fSJohnny Huang 		}
126569d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1266a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
126769d5fd8fSJohnny Huang 			fail = 1;
126869d5fd8fSJohnny Huang 			continue;
126969d5fd8fSJohnny Huang 		}
127069d5fd8fSJohnny Huang 		if (pbit == 1) {
127169d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
127269d5fd8fSJohnny Huang 		}
1273a6af4a17SJohnny Huang 		printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1);
127469d5fd8fSJohnny Huang 	}
127569d5fd8fSJohnny Huang 	if (fail == 1)
1276a6af4a17SJohnny Huang 		return OTP_FAILURE;
1277a6af4a17SJohnny Huang 	else if (skip == 1)
1278a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
12797e22f42dSJohnny Huang 
12807e22f42dSJohnny Huang 	return 0;
128169d5fd8fSJohnny Huang }
128269d5fd8fSJohnny Huang 
12832a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
128469d5fd8fSJohnny Huang {
128569d5fd8fSJohnny Huang 	int i, j;
128666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
128769d5fd8fSJohnny Huang 
12882a856b9aSJohnny Huang 	if (start < 0 || start > 64)
12892a856b9aSJohnny Huang 		return OTP_USAGE;
12902a856b9aSJohnny Huang 
12912a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
12922a856b9aSJohnny Huang 		return OTP_USAGE;
12932a856b9aSJohnny Huang 
129469d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
129569d5fd8fSJohnny Huang 
129607baa4e8SJohnny Huang 	printf("BIT(hex)  Value  Option           Status\n");
1297a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1298737ed20bSJohnny Huang 
1299cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
130007baa4e8SJohnny Huang 		printf("0x%-8X", i);
1301737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1302737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1303737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1304737ed20bSJohnny Huang 		printf("   ");
130569d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1306737ed20bSJohnny Huang 			printf("protected and not writable");
130769d5fd8fSJohnny Huang 		} else {
1308737ed20bSJohnny Huang 			printf("not protected ");
130969d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1310737ed20bSJohnny Huang 				printf("and no remaining times to write.");
131169d5fd8fSJohnny Huang 			} else {
1312737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
131369d5fd8fSJohnny Huang 			}
131469d5fd8fSJohnny Huang 		}
1315737ed20bSJohnny Huang 		printf("\n");
131669d5fd8fSJohnny Huang 	}
13172a856b9aSJohnny Huang 
13182a856b9aSJohnny Huang 	return OTP_SUCCESS;
131969d5fd8fSJohnny Huang }
132069d5fd8fSJohnny Huang 
132169d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
132269d5fd8fSJohnny Huang {
132369d5fd8fSJohnny Huang 	int i, j;
132469d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
132569d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
132669d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
132769d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
132869d5fd8fSJohnny Huang 	int fail = 0;
13297e22f42dSJohnny Huang 	int pass = 0;
13307e22f42dSJohnny Huang 	int soak = 0;
133166f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
133269d5fd8fSJohnny Huang 
13337f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
133469d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
133569d5fd8fSJohnny Huang 
13367f795e57SJohnny Huang 	printf("Check writable...\n");
13377f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
13387f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
13397f795e57SJohnny Huang 		return OTP_FAILURE;
13407f795e57SJohnny Huang 	}
13417e22f42dSJohnny Huang 
13427f795e57SJohnny Huang 	otp_soak(0);
134369d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
13444c1c9b35SJohnny Huang 		printProgress(i + 1, 64, "");
134569d5fd8fSJohnny Huang 		prog_address = 0x800;
134669d5fd8fSJohnny Huang 		if (i < 32) {
134769d5fd8fSJohnny Huang 			offset = i;
134869d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
134969d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
135069d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
135169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
135269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
135369d5fd8fSJohnny Huang 
135469d5fd8fSJohnny Huang 		} else {
135569d5fd8fSJohnny Huang 			offset = (i - 32);
135669d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
135769d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
135869d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
135969d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
136069d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
136169d5fd8fSJohnny Huang 		}
136269d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
136369d5fd8fSJohnny Huang 
136469d5fd8fSJohnny Huang 		if (kbit == 1) {
136569d5fd8fSJohnny Huang 			continue;
136669d5fd8fSJohnny Huang 		}
136769d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
136869d5fd8fSJohnny Huang 			continue;
136969d5fd8fSJohnny Huang 		}
137069d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
137169d5fd8fSJohnny Huang 			fail = 1;
137269d5fd8fSJohnny Huang 			continue;
137369d5fd8fSJohnny Huang 		}
137469d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
137569d5fd8fSJohnny Huang 			fail = 1;
137669d5fd8fSJohnny Huang 			continue;
137769d5fd8fSJohnny Huang 		}
13787e22f42dSJohnny Huang 
13797e22f42dSJohnny Huang 		if (soak) {
138069d5fd8fSJohnny Huang 			soak = 0;
13817e22f42dSJohnny Huang 			otp_soak(0);
13827e22f42dSJohnny Huang 		}
13837e22f42dSJohnny Huang 
13847e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
13857e22f42dSJohnny Huang 
13867e22f42dSJohnny Huang 		pass = 0;
13877e22f42dSJohnny Huang 
138869d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1389a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
139069d5fd8fSJohnny Huang 				pass = 1;
139169d5fd8fSJohnny Huang 				break;
139269d5fd8fSJohnny Huang 			}
13937e22f42dSJohnny Huang 			if (soak == 0) {
139469d5fd8fSJohnny Huang 				soak = 1;
13957e22f42dSJohnny Huang 				otp_soak(1);
13964b65a65dSJohnny Huang 			}
139769d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
139869d5fd8fSJohnny Huang 		}
139969d5fd8fSJohnny Huang 		if (!pass)
14002a856b9aSJohnny Huang 			return OTP_FAILURE;
140169d5fd8fSJohnny Huang 
140269d5fd8fSJohnny Huang 		if (pbit == 0)
140369d5fd8fSJohnny Huang 			continue;
140469d5fd8fSJohnny Huang 		prog_address = 0x800;
140569d5fd8fSJohnny Huang 		if (i < 32)
140669d5fd8fSJohnny Huang 			prog_address |= 0x60c;
140769d5fd8fSJohnny Huang 		else
140869d5fd8fSJohnny Huang 			prog_address |= 0x60e;
140969d5fd8fSJohnny Huang 
14107e22f42dSJohnny Huang 
14117e22f42dSJohnny Huang 		if (soak) {
14127e22f42dSJohnny Huang 			soak = 0;
14137e22f42dSJohnny Huang 			otp_soak(0);
14147e22f42dSJohnny Huang 		}
14157e22f42dSJohnny Huang 
14167e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
14177e22f42dSJohnny Huang 
14187e22f42dSJohnny Huang 		pass = 0;
14197e22f42dSJohnny Huang 
142069d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
14217e22f42dSJohnny Huang 
1422a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
142369d5fd8fSJohnny Huang 				pass = 1;
142469d5fd8fSJohnny Huang 				break;
142569d5fd8fSJohnny Huang 			}
14267e22f42dSJohnny Huang 			if (soak == 0) {
142769d5fd8fSJohnny Huang 				soak = 1;
14287e22f42dSJohnny Huang 				otp_soak(1);
142969d5fd8fSJohnny Huang 			}
143069d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
143169d5fd8fSJohnny Huang 		}
143269d5fd8fSJohnny Huang 		if (!pass)
14332a856b9aSJohnny Huang 			return OTP_FAILURE;
143469d5fd8fSJohnny Huang 
143569d5fd8fSJohnny Huang 	}
143669d5fd8fSJohnny Huang 	if (fail == 1)
14372a856b9aSJohnny Huang 		return OTP_FAILURE;
143869d5fd8fSJohnny Huang 	else
14392a856b9aSJohnny Huang 		return OTP_SUCCESS;
144069d5fd8fSJohnny Huang 
144169d5fd8fSJohnny Huang }
144269d5fd8fSJohnny Huang 
1443cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak)
1444cd1610b4SJohnny Huang {
1445cd1610b4SJohnny Huang 	int prog_bit;
1446cd1610b4SJohnny Huang 
14477e22f42dSJohnny Huang 	otp_soak(soak);
14487e22f42dSJohnny Huang 
1449cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1450cd1610b4SJohnny Huang 		if (value)
1451cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1452cd1610b4SJohnny Huang 		else
1453cd1610b4SJohnny Huang 			return;
1454cd1610b4SJohnny Huang 	} else {
1455cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1456cd1610b4SJohnny Huang 		if (!value)
1457cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1458cd1610b4SJohnny Huang 		else
1459cd1610b4SJohnny Huang 			return;
1460cd1610b4SJohnny Huang 	}
1461cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1462cd1610b4SJohnny Huang }
1463cd1610b4SJohnny Huang 
1464d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
14654c1c9b35SJohnny Huang {
14664c1c9b35SJohnny Huang 	int i, k;
14674c1c9b35SJohnny Huang 	int pass;
1468d90825e2SJohnny Huang 	int soak = 0;
14694c1c9b35SJohnny Huang 	uint32_t prog_address;
1470d90825e2SJohnny Huang 	uint32_t data[2048];
14714c1c9b35SJohnny Huang 	uint32_t compare[2];
1472d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
14734c1c9b35SJohnny Huang 
1474d90825e2SJohnny Huang 	uint32_t data0_masked;
1475d90825e2SJohnny Huang 	uint32_t data1_masked;
1476d90825e2SJohnny Huang 	uint32_t buf0_masked;
1477d90825e2SJohnny Huang 	uint32_t buf1_masked;
14784c1c9b35SJohnny Huang 
14794c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
14804c1c9b35SJohnny Huang 
1481d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1482d90825e2SJohnny Huang 	for (i = 0; i < 2048 ; i += 2) {
1483d90825e2SJohnny Huang 		printProgress(i + 2, 2048, "");
1484d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
14854c1c9b35SJohnny Huang 	}
1486d90825e2SJohnny Huang 
14874c1c9b35SJohnny Huang 
14884c1c9b35SJohnny Huang 	printf("Check writable...\n");
1489d90825e2SJohnny Huang 	for (i = 0; i < 2048; i++) {
1490d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1491d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1492d90825e2SJohnny Huang 		if (data0_masked == buf0_masked)
14934c1c9b35SJohnny Huang 			continue;
1494d90825e2SJohnny Huang 		if (i % 2 == 0) {
1495d90825e2SJohnny Huang 			if ((data0_masked | buf0_masked) == buf0_masked) {
14964c1c9b35SJohnny Huang 				continue;
14974c1c9b35SJohnny Huang 			} else {
14984c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1499d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
15004c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1501d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
15022a856b9aSJohnny Huang 				return OTP_FAILURE;
150369d5fd8fSJohnny Huang 			}
1504d90825e2SJohnny Huang 		} else {
1505d90825e2SJohnny Huang 			if ((data0_masked & buf0_masked) == buf0_masked) {
1506d90825e2SJohnny Huang 				continue;
1507d90825e2SJohnny Huang 			} else {
1508d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1509d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1510d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1511d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
15122a856b9aSJohnny Huang 				return OTP_FAILURE;
1513d90825e2SJohnny Huang 			}
1514d90825e2SJohnny Huang 		}
1515d90825e2SJohnny Huang 	}
151669d5fd8fSJohnny Huang 
1517d90825e2SJohnny Huang 	printf("Start Programing...\n");
1518d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1519d90825e2SJohnny Huang 
1520d90825e2SJohnny Huang 	for (i = 0; i < 2048; i += 2) {
1521d90825e2SJohnny Huang 		prog_address = i;
1522d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1523d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1524d90825e2SJohnny Huang 		data1_masked = data[i + 1]  & ~buf_keep[i + 1];
1525d90825e2SJohnny Huang 		buf1_masked  = buf[i + 1] & ~buf_keep[i + 1];
1526d90825e2SJohnny Huang 		if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) {
1527d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1528d90825e2SJohnny Huang 			continue;
1529d90825e2SJohnny Huang 		}
1530d90825e2SJohnny Huang 		if (soak) {
1531d90825e2SJohnny Huang 			soak = 0;
1532d90825e2SJohnny Huang 			otp_soak(0);
1533d90825e2SJohnny Huang 		}
1534d90825e2SJohnny Huang 		if (data1_masked == buf1_masked) {
1535d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1536d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1537d90825e2SJohnny Huang 		} else if (data0_masked == buf0_masked) {
1538d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1539d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1540d90825e2SJohnny Huang 		} else {
1541d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1542d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1543d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1544d90825e2SJohnny Huang 		}
1545d90825e2SJohnny Huang 
1546d90825e2SJohnny Huang 		pass = 0;
1547d90825e2SJohnny Huang 		for (k = 0; k < RETRY; k++) {
1548d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) {
1549d90825e2SJohnny Huang 				if (soak == 0) {
1550d90825e2SJohnny Huang 					soak = 1;
1551d90825e2SJohnny Huang 					otp_soak(1);
1552d90825e2SJohnny Huang 				}
1553d90825e2SJohnny Huang 				if (compare[0] != 0) {
1554d90825e2SJohnny Huang 					otp_prog_dw(compare[0], buf_keep[i], prog_address);
1555d90825e2SJohnny Huang 				}
1556d90825e2SJohnny Huang 				if (compare[1] != ~0) {
1557d90825e2SJohnny Huang 					otp_prog_dw(compare[1], buf_keep[i], prog_address + 1);
1558d90825e2SJohnny Huang 				}
1559d90825e2SJohnny Huang 			} else {
1560d90825e2SJohnny Huang 				pass = 1;
1561d90825e2SJohnny Huang 				break;
1562d90825e2SJohnny Huang 			}
1563d90825e2SJohnny Huang 		}
1564d90825e2SJohnny Huang 
1565d90825e2SJohnny Huang 		if (!pass)
15662a856b9aSJohnny Huang 			return OTP_FAILURE;
1567d90825e2SJohnny Huang 	}
15682a856b9aSJohnny Huang 	return OTP_SUCCESS;
1569d90825e2SJohnny Huang 
1570d90825e2SJohnny Huang }
1571d90825e2SJohnny Huang 
1572d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
157369d5fd8fSJohnny Huang {
157469d5fd8fSJohnny Huang 	int ret;
1575*7332532cSJohnny Huang 	int mode = 0;
157669d5fd8fSJohnny Huang 	uint32_t *buf;
1577d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1578d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1579d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
158069d5fd8fSJohnny Huang 
1581d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
158269d5fd8fSJohnny Huang 	if (!buf) {
158369d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
15842a856b9aSJohnny Huang 		return OTP_FAILURE;
158569d5fd8fSJohnny Huang 	}
1586d90825e2SJohnny Huang 
1587d90825e2SJohnny Huang 	if (buf[0] & BIT(29)) {
1588*7332532cSJohnny Huang 		mode |= OTP_REGION_DATA;
1589*7332532cSJohnny Huang 		data_region = &buf[36];
1590d90825e2SJohnny Huang 	}
1591d90825e2SJohnny Huang 	if (buf[0] & BIT(30)) {
1592*7332532cSJohnny Huang 		mode |= OTP_REGION_CONF;
1593*7332532cSJohnny Huang 		conf_region = &buf[12];
1594d90825e2SJohnny Huang 	}
1595d90825e2SJohnny Huang 	if (buf[0] & BIT(31)) {
1596*7332532cSJohnny Huang 		mode |= OTP_REGION_STRAP;
1597*7332532cSJohnny Huang 		strap_region = &buf[4];
1598d90825e2SJohnny Huang 	}
1599*7332532cSJohnny Huang 
160069d5fd8fSJohnny Huang 	if (!nconfirm) {
1601*7332532cSJohnny Huang 		if (mode & OTP_REGION_DATA) {
16027f795e57SJohnny Huang 			printf("\nOTP data region :\n");
16037f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
160469d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16052a856b9aSJohnny Huang 				return OTP_FAILURE;
160669d5fd8fSJohnny Huang 			}
160769d5fd8fSJohnny Huang 		}
1608*7332532cSJohnny Huang 		if (mode & OTP_REGION_STRAP) {
1609*7332532cSJohnny Huang 			printf("\nOTP strap region :\n");
1610*7332532cSJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
1611*7332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
1612*7332532cSJohnny Huang 				return OTP_FAILURE;
1613*7332532cSJohnny Huang 			}
1614*7332532cSJohnny Huang 		}
1615*7332532cSJohnny Huang 		if (mode & OTP_REGION_CONF) {
1616*7332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
1617*7332532cSJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
1618*7332532cSJohnny Huang 				printf("OTP config error, please check.\n");
1619*7332532cSJohnny Huang 				return OTP_FAILURE;
1620*7332532cSJohnny Huang 			}
1621*7332532cSJohnny Huang 		}
1622*7332532cSJohnny Huang 
162369d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
162469d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
162569d5fd8fSJohnny Huang 			printf(" Aborting\n");
16262a856b9aSJohnny Huang 			return OTP_FAILURE;
162769d5fd8fSJohnny Huang 		}
162869d5fd8fSJohnny Huang 	}
1629*7332532cSJohnny Huang 
1630*7332532cSJohnny Huang 	if (mode & OTP_REGION_DATA) {
1631*7332532cSJohnny Huang 		printf("programing data region ...\n");
1632d90825e2SJohnny Huang 		ret = otp_prog_data(data_region);
16332a856b9aSJohnny Huang 		if (ret != 0) {
163469d5fd8fSJohnny Huang 			printf("Error\n");
163569d5fd8fSJohnny Huang 			return ret;
163669d5fd8fSJohnny Huang 		} else {
163769d5fd8fSJohnny Huang 			printf("Done\n");
163869d5fd8fSJohnny Huang 		}
1639*7332532cSJohnny Huang 	}
1640*7332532cSJohnny Huang 	if (mode & OTP_REGION_STRAP) {
1641*7332532cSJohnny Huang 		printf("programing strap region ...\n");
1642d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
16432a856b9aSJohnny Huang 		if (ret != 0) {
164469d5fd8fSJohnny Huang 			printf("Error\n");
164569d5fd8fSJohnny Huang 			return ret;
164669d5fd8fSJohnny Huang 		} else {
164769d5fd8fSJohnny Huang 			printf("Done\n");
164869d5fd8fSJohnny Huang 		}
1649*7332532cSJohnny Huang 	}
1650*7332532cSJohnny Huang 	if (mode & OTP_REGION_CONF) {
1651*7332532cSJohnny Huang 		printf("programing configuration region ...\n");
1652d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
16532a856b9aSJohnny Huang 		if (ret != 0) {
165469d5fd8fSJohnny Huang 			printf("Error\n");
165569d5fd8fSJohnny Huang 			return ret;
165669d5fd8fSJohnny Huang 		}
165769d5fd8fSJohnny Huang 		printf("Done\n");
165869d5fd8fSJohnny Huang 	}
1659cd1610b4SJohnny Huang 
1660*7332532cSJohnny Huang 	return OTP_SUCCESS;
16612a856b9aSJohnny Huang }
16622a856b9aSJohnny Huang 
16632a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1664cd1610b4SJohnny Huang {
1665a6af4a17SJohnny Huang 	uint32_t read[2];
1666cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1667d90825e2SJohnny Huang 	uint32_t prog_address = 0;
166866f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1669cd1610b4SJohnny Huang 	int otp_bit;
1670cd1610b4SJohnny Huang 	int i;
1671cd1610b4SJohnny Huang 	int pass;
1672a6af4a17SJohnny Huang 	int ret;
1673cd1610b4SJohnny Huang 
1674cd1610b4SJohnny Huang 	switch (mode) {
1675a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1676a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1677cd1610b4SJohnny Huang 		prog_address = 0x800;
1678cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1679cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1680a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1681cd1610b4SJohnny Huang 		if (otp_bit == value) {
1682a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1683cd1610b4SJohnny Huang 			printf("No need to program\n");
16842a856b9aSJohnny Huang 			return OTP_SUCCESS;
1685cd1610b4SJohnny Huang 		}
1686cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1687a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1688cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
16892a856b9aSJohnny Huang 			return OTP_FAILURE;
1690cd1610b4SJohnny Huang 		}
1691a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1692cd1610b4SJohnny Huang 		break;
1693a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1694cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1695cd1610b4SJohnny Huang 
1696cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1697a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1698a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1699cd1610b4SJohnny Huang 		} else {
1700a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1701a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1702cd1610b4SJohnny Huang 		}
1703cd1610b4SJohnny Huang 		if (otp_bit == value) {
1704a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1705cd1610b4SJohnny Huang 			printf("No need to program\n");
17062a856b9aSJohnny Huang 			return OTP_SUCCESS;
1707cd1610b4SJohnny Huang 		}
1708cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1709a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1710cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
17112a856b9aSJohnny Huang 			return OTP_FAILURE;
1712cd1610b4SJohnny Huang 		}
1713a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1714cd1610b4SJohnny Huang 		break;
1715a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1716cd1610b4SJohnny Huang 		otp_strp_status(otpstrap);
1717cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1718cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1719cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
1720cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1721cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
1722cd1610b4SJohnny Huang 			strap_buf[5] = 0;
17232a856b9aSJohnny Huang 			// if (protect)
17242a856b9aSJohnny Huang 			// 	strap_buf[4] = BIT(bit_offset);
17252a856b9aSJohnny Huang 			// else
17262a856b9aSJohnny Huang 			// 	strap_buf[4] = 0;
1727cd1610b4SJohnny Huang 		} else {
1728cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1729cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1730cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1731cd1610b4SJohnny Huang 			strap_buf[4] = 0;
17322a856b9aSJohnny Huang 			// if (protect)
17332a856b9aSJohnny Huang 			// 	strap_buf[5] = BIT(bit_offset - 32);
17342a856b9aSJohnny Huang 			// else
17352a856b9aSJohnny Huang 			// 	strap_buf[5] = 0;
1736cd1610b4SJohnny Huang 		}
173776d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1738a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
17392a856b9aSJohnny Huang 			return OTP_FAILURE;
1740a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1741a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1742a6af4a17SJohnny Huang 
1743cd1610b4SJohnny Huang 		break;
1744cd1610b4SJohnny Huang 	}
1745cd1610b4SJohnny Huang 
1746cd1610b4SJohnny Huang 	if (!nconfirm) {
1747cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1748cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1749cd1610b4SJohnny Huang 			printf(" Aborting\n");
17502a856b9aSJohnny Huang 			return OTP_FAILURE;
1751cd1610b4SJohnny Huang 		}
1752cd1610b4SJohnny Huang 	}
1753cd1610b4SJohnny Huang 
1754cd1610b4SJohnny Huang 	switch (mode) {
1755a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1756cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
1757a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1758a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1759cd1610b4SJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset, 0);
1760cd1610b4SJohnny Huang 		pass = -1;
1761cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
1762a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
1763cd1610b4SJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset, 1);
1764cd1610b4SJohnny Huang 			} else {
1765cd1610b4SJohnny Huang 				pass = 0;
1766cd1610b4SJohnny Huang 				break;
1767cd1610b4SJohnny Huang 			}
1768cd1610b4SJohnny Huang 		}
17692a856b9aSJohnny Huang 		if (pass == 0)
17702a856b9aSJohnny Huang 			return OTP_SUCCESS;
1771cd1610b4SJohnny Huang 	}
1772cd1610b4SJohnny Huang 
17732a856b9aSJohnny Huang 	return OTP_USAGE;
1774cd1610b4SJohnny Huang }
1775cd1610b4SJohnny Huang 
17762a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
177769d5fd8fSJohnny Huang {
17782a856b9aSJohnny Huang 	uint32_t offset, count;
17792a856b9aSJohnny Huang 	int ret;
178069d5fd8fSJohnny Huang 
17812a856b9aSJohnny Huang 	if (argc == 4) {
17822a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17832a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
17842a856b9aSJohnny Huang 	} else if (argc == 3) {
17852a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17862a856b9aSJohnny Huang 		count = 1;
17872a856b9aSJohnny Huang 	} else {
178869d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
178969d5fd8fSJohnny Huang 	}
179069d5fd8fSJohnny Huang 
179169d5fd8fSJohnny Huang 
17922a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
179369d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17942a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
17952a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
17962a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17972a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
17982a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
17992a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18002a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
18012a856b9aSJohnny Huang 	} else {
18022a856b9aSJohnny Huang 		return CMD_RET_USAGE;
180369d5fd8fSJohnny Huang 	}
180469d5fd8fSJohnny Huang 
18052a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18062a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18072a856b9aSJohnny Huang 	else
18082a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18092a856b9aSJohnny Huang 
18102a856b9aSJohnny Huang }
18112a856b9aSJohnny Huang 
18122a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18132a856b9aSJohnny Huang {
18142a856b9aSJohnny Huang 	phys_addr_t addr;
18152a856b9aSJohnny Huang 	uint32_t byte_size;
18162a856b9aSJohnny Huang 	int ret;
18172a856b9aSJohnny Huang 
18182a856b9aSJohnny Huang 	if (argc == 4) {
18192a856b9aSJohnny Huang 		if (strcmp(argv[1], "f"))
18202a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18212a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
18222a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
182369d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18242a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
18252a856b9aSJohnny Huang 	} else if (argc == 3) {
18262a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
18272a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
18282a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18292a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
18302a856b9aSJohnny Huang 	} else {
18312a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18322a856b9aSJohnny Huang 	}
18332a856b9aSJohnny Huang 
18342a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18352a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18362a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18372a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18382a856b9aSJohnny Huang 	else
18392a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18402a856b9aSJohnny Huang }
18412a856b9aSJohnny Huang 
18422a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18432a856b9aSJohnny Huang {
18442a856b9aSJohnny Huang 	int mode = 0;
18452a856b9aSJohnny Huang 	int nconfirm = 0;
18462a856b9aSJohnny Huang 	int otp_addr = 0;
18472a856b9aSJohnny Huang 	int bit_offset;
18482a856b9aSJohnny Huang 	int value;
18492a856b9aSJohnny Huang 	int ret;
18502a856b9aSJohnny Huang 
18512a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
18522a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18532a856b9aSJohnny Huang 
18542a856b9aSJohnny Huang 	/* Drop the pb cmd */
18552a856b9aSJohnny Huang 	argc--;
18562a856b9aSJohnny Huang 	argv++;
18572a856b9aSJohnny Huang 
18582a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1859a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
18602a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1861a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
18622a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1863a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1864cd1610b4SJohnny Huang 	else
18652a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18662a856b9aSJohnny Huang 
18672a856b9aSJohnny Huang 	/* Drop the region cmd */
18682a856b9aSJohnny Huang 	argc--;
18692a856b9aSJohnny Huang 	argv++;
18702a856b9aSJohnny Huang 
18712a856b9aSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1872cd1610b4SJohnny Huang 		nconfirm = 1;
18732a856b9aSJohnny Huang 		/* Drop the force option */
18742a856b9aSJohnny Huang 		argc--;
18752a856b9aSJohnny Huang 		argv++;
18762a856b9aSJohnny Huang 	}
1877cd1610b4SJohnny Huang 
1878a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
18792a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
18802a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
1881cd1610b4SJohnny Huang 		if (bit_offset >= 64)
18822a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1883cd1610b4SJohnny Huang 	} else {
18842a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
18852a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
18862a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
1887cd1610b4SJohnny Huang 		if (bit_offset >= 32)
18882a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1889cd1610b4SJohnny Huang 	}
1890cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
18912a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1892cd1610b4SJohnny Huang 
1893cd1610b4SJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
18942a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
18952a856b9aSJohnny Huang 
18962a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18972a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18982a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18992a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19002a856b9aSJohnny Huang 	else
19012a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19022a856b9aSJohnny Huang }
19032a856b9aSJohnny Huang 
19042a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19052a856b9aSJohnny Huang {
19062a856b9aSJohnny Huang 	phys_addr_t addr;
19072a856b9aSJohnny Huang 	int otp_addr = 0;
19082a856b9aSJohnny Huang 
19092a856b9aSJohnny Huang 	if (argc != 3)
19102a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19112a856b9aSJohnny Huang 
191269d5fd8fSJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
19132a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
19142a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
19152a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
191669d5fd8fSJohnny Huang 		printf("Compare pass\n");
19172a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
191869d5fd8fSJohnny Huang 	} else {
191969d5fd8fSJohnny Huang 		printf("Compare fail\n");
19202a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
192169d5fd8fSJohnny Huang 	}
192269d5fd8fSJohnny Huang }
192369d5fd8fSJohnny Huang 
192466f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
192566f2f8e5SJohnny Huang {
1926a8bd6d8cSJohnny Huang 	int view = 0;
19272d4b0742SJohnny Huang 	int input;
1928a8bd6d8cSJohnny Huang 
1929a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
193066f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
193166f2f8e5SJohnny Huang 
19322d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
193366f2f8e5SJohnny Huang 
19342d4b0742SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
19352d4b0742SJohnny Huang 		if (argc == 3) {
19362d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
19372d4b0742SJohnny Huang 			otp_print_conf_info(input);
19382d4b0742SJohnny Huang 		} else {
19392d4b0742SJohnny Huang 			otp_print_conf_info(-1);
19402d4b0742SJohnny Huang 		}
19412d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
19422d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
1943a8bd6d8cSJohnny Huang 			view = 1;
1944a8bd6d8cSJohnny Huang 			/* Drop the view option */
1945a8bd6d8cSJohnny Huang 			argc--;
1946a8bd6d8cSJohnny Huang 			argv++;
1947a8bd6d8cSJohnny Huang 		}
194866f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
1949b458cd62SJohnny Huang 		otp_print_strap_info(view);
195066f2f8e5SJohnny Huang 	} else {
195166f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
195266f2f8e5SJohnny Huang 	}
19532d4b0742SJohnny Huang 
195466f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
195566f2f8e5SJohnny Huang }
195666f2f8e5SJohnny Huang 
1957737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1958737ed20bSJohnny Huang {
1959737ed20bSJohnny Huang 	int input;
1960737ed20bSJohnny Huang 	int bit_offset;
1961737ed20bSJohnny Huang 	int prog_address;
1962737ed20bSJohnny Huang 	int pass;
1963737ed20bSJohnny Huang 	int i;
1964737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1965737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1966737ed20bSJohnny Huang 
1967737ed20bSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1968737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1969737ed20bSJohnny Huang 	} else {
1970737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1971737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
1972737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1973737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1974737ed20bSJohnny Huang 			printf(" Aborting\n");
1975737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
1976737ed20bSJohnny Huang 		}
1977737ed20bSJohnny Huang 	}
1978737ed20bSJohnny Huang 
1979737ed20bSJohnny Huang 	prog_address = 0x800;
1980737ed20bSJohnny Huang 	if (input < 32) {
1981737ed20bSJohnny Huang 		bit_offset = input;
1982737ed20bSJohnny Huang 		prog_address |= 0x60c;
1983737ed20bSJohnny Huang 	} else if (input < 64) {
1984737ed20bSJohnny Huang 		bit_offset = input - 32;
1985737ed20bSJohnny Huang 		prog_address |= 0x60e;
1986737ed20bSJohnny Huang 	} else {
1987737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1988737ed20bSJohnny Huang 	}
1989737ed20bSJohnny Huang 
1990737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
1991737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
1992737ed20bSJohnny Huang 	}
1993737ed20bSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset, 0);
1994737ed20bSJohnny Huang 	pass = -1;
1995737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
1996737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
1997737ed20bSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset, 1);
1998737ed20bSJohnny Huang 		} else {
1999737ed20bSJohnny Huang 			pass = 0;
2000737ed20bSJohnny Huang 			break;
2001737ed20bSJohnny Huang 		}
2002737ed20bSJohnny Huang 	}
2003737ed20bSJohnny Huang 	if (pass == 0) {
2004737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2005737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2006737ed20bSJohnny Huang 	}
2007737ed20bSJohnny Huang 
2008737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2009737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2010737ed20bSJohnny Huang 
2011737ed20bSJohnny Huang }
20122a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
20132a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2014a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
20152a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
20162a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2017737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
20182a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
20192a856b9aSJohnny Huang };
20202a856b9aSJohnny Huang 
20212a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20222a856b9aSJohnny Huang {
20232a856b9aSJohnny Huang 	cmd_tbl_t *cp;
20242a856b9aSJohnny Huang 
20252a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
20262a856b9aSJohnny Huang 
2027737ed20bSJohnny Huang 	/* Drop the otp command */
20282a856b9aSJohnny Huang 	argc--;
20292a856b9aSJohnny Huang 	argv++;
20302a856b9aSJohnny Huang 
20312a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
20322a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20332a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
20342a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20352a856b9aSJohnny Huang 
20362a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
203769d5fd8fSJohnny Huang }
203869d5fd8fSJohnny Huang 
203969d5fd8fSJohnny Huang U_BOOT_CMD(
204069d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
204169d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
20422a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
20432a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
20442d4b0742SJohnny Huang 	"otp info strap [v]\n"
20452d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2046d90825e2SJohnny Huang 	"otp prog [f] <addr> <byte_size>\n"
2047cd1610b4SJohnny Huang 	"otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n"
2048737ed20bSJohnny Huang 	"otp pb strap [f] <bit_offset> <value>\n"
2049737ed20bSJohnny Huang 	"otp protect [f] <bit_offset>\n"
20502a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
205169d5fd8fSJohnny Huang );
2052