xref: /openbmc/u-boot/cmd/otp.c (revision b458cd62)
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
28a6d0d645SJohnny Huang #define OTP_REGION_STRAP		1
29a6d0d645SJohnny Huang #define OTP_REGION_CONF			2
30a6d0d645SJohnny Huang #define OTP_REGION_DATA			3
31a6d0d645SJohnny Huang #define OTP_REGION_ALL			4
3269d5fd8fSJohnny Huang 
332a856b9aSJohnny Huang #define OTP_USAGE			-1
342a856b9aSJohnny Huang #define OTP_FAILURE			-2
352a856b9aSJohnny Huang #define OTP_SUCCESS			0
362a856b9aSJohnny Huang 
37a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
38a6af4a17SJohnny Huang 
39a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
40*b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
41*b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4276d13988SJohnny Huang 
434c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
444c1c9b35SJohnny Huang #define PBWIDTH 60
454c1c9b35SJohnny Huang 
4666f2f8e5SJohnny Huang struct otpstrap_status {
4769d5fd8fSJohnny Huang 	int value;
4869d5fd8fSJohnny Huang 	int option_array[7];
4969d5fd8fSJohnny Huang 	int remain_times;
5069d5fd8fSJohnny Huang 	int writeable_option;
5169d5fd8fSJohnny Huang 	int protected;
5269d5fd8fSJohnny Huang };
5369d5fd8fSJohnny Huang 
5466f2f8e5SJohnny Huang struct otpconf_parse {
5566f2f8e5SJohnny Huang 	int dw_offset;
5666f2f8e5SJohnny Huang 	int bit;
5766f2f8e5SJohnny Huang 	int length;
5866f2f8e5SJohnny Huang 	int value;
5966f2f8e5SJohnny Huang 	int keep;
6066f2f8e5SJohnny Huang 	char status[80];
6166f2f8e5SJohnny Huang };
6266f2f8e5SJohnny Huang 
63a8bd6d8cSJohnny Huang struct otpstrap_info {
64a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
65a8bd6d8cSJohnny Huang 	uint32_t length;
6676d13988SJohnny Huang 	int value;
67a8bd6d8cSJohnny Huang 	char information[80];
68a8bd6d8cSJohnny Huang };
69a8bd6d8cSJohnny Huang 
70a8bd6d8cSJohnny Huang struct otpconf_info {
71a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
72a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
73a8bd6d8cSJohnny Huang 	uint32_t length;
74a8bd6d8cSJohnny Huang 	int value;
75a8bd6d8cSJohnny Huang 	char information[80];
76a8bd6d8cSJohnny Huang };
77a8bd6d8cSJohnny Huang 
78a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...)
79a8bd6d8cSJohnny Huang {
80a8bd6d8cSJohnny Huang 	int val = numerator * 100 / denominator;
81a8bd6d8cSJohnny Huang 	int lpad = numerator * PBWIDTH / denominator;
82a8bd6d8cSJohnny Huang 	int rpad = PBWIDTH - lpad;
83a8bd6d8cSJohnny Huang 	char buffer[256];
84a8bd6d8cSJohnny Huang 	va_list aptr;
85a8bd6d8cSJohnny Huang 
86a8bd6d8cSJohnny Huang 	va_start(aptr, format);
87a8bd6d8cSJohnny Huang 	vsprintf(buffer, format, aptr);
88a8bd6d8cSJohnny Huang 	va_end(aptr);
89a8bd6d8cSJohnny Huang 
90a8bd6d8cSJohnny Huang 	printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer);
91a8bd6d8cSJohnny Huang 	if (numerator == denominator)
92a8bd6d8cSJohnny Huang 		printf("\n");
93a8bd6d8cSJohnny Huang }
94a8bd6d8cSJohnny Huang 
95a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = {
96a8bd6d8cSJohnny Huang 	{
97a8bd6d8cSJohnny Huang 		0, 1, 0, "Disable secure boot"
98a8bd6d8cSJohnny Huang 	}, {
99a8bd6d8cSJohnny Huang 		0, 1, 1, "Enable secure boot"
100a8bd6d8cSJohnny Huang 	}, {
101a8bd6d8cSJohnny Huang 		1, 1, 0, "Disable boot from eMMC"
102a8bd6d8cSJohnny Huang 	}, {
103a8bd6d8cSJohnny Huang 		1, 1, 1, "Enable boot from eMMC"
104a8bd6d8cSJohnny Huang 	}, {
105a8bd6d8cSJohnny Huang 		2, 1, 0, "Disable Boot from debug SPI"
106a8bd6d8cSJohnny Huang 	}, {
107a8bd6d8cSJohnny Huang 		2, 1, 1, "Enable Boot from debug SPI"
108a8bd6d8cSJohnny Huang 	}, {
109a8bd6d8cSJohnny Huang 		3, 1, 0, "Enable ARM CM3"
110a8bd6d8cSJohnny Huang 	}, {
111a8bd6d8cSJohnny Huang 		3, 1, 1, "Disable ARM CM3"
112a8bd6d8cSJohnny Huang 	}, {
113a8bd6d8cSJohnny Huang 		4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS"
114a8bd6d8cSJohnny Huang 	}, {
115a8bd6d8cSJohnny Huang 		4, 1, 1, "Enable dedicated VGA BIOS ROM"
116a8bd6d8cSJohnny Huang 	}, {
117a8bd6d8cSJohnny Huang 		5, 1, 0, "MAC 1 : RMII/NCSI"
118a8bd6d8cSJohnny Huang 	}, {
119a8bd6d8cSJohnny Huang 		5, 1, 1, "MAC 1 : RGMII"
120a8bd6d8cSJohnny Huang 	}, {
121a8bd6d8cSJohnny Huang 		6, 1, 0, "MAC 2 : RMII/NCSI"
122a8bd6d8cSJohnny Huang 	}, {
123a8bd6d8cSJohnny Huang 		6, 1, 1, "MAC 2 : RGMII"
124a8bd6d8cSJohnny Huang 	}, {
125a8bd6d8cSJohnny Huang 		7, 3, 0, "CPU Frequency : 1GHz"
126a8bd6d8cSJohnny Huang 	}, {
127a8bd6d8cSJohnny Huang 		7, 3, 1, "CPU Frequency : 800MHz"
128a8bd6d8cSJohnny Huang 	}, {
129a8bd6d8cSJohnny Huang 		7, 3, 2, "CPU Frequency : 1.2GHz"
130a8bd6d8cSJohnny Huang 	}, {
131a8bd6d8cSJohnny Huang 		7, 3, 3, "CPU Frequency : 1.4GHz"
132a8bd6d8cSJohnny Huang 	}, {
133a8bd6d8cSJohnny Huang 		10, 2, 0, "HCLK ratio AXI:AHB = 2:1"
134a8bd6d8cSJohnny Huang 	}, {
135a8bd6d8cSJohnny Huang 		10, 2, 1, "HCLK ratio AXI:AHB = 2:1"
136a8bd6d8cSJohnny Huang 	}, {
137a8bd6d8cSJohnny Huang 		10, 2, 2, "HCLK ratio AXI:AHB = 3:1"
138a8bd6d8cSJohnny Huang 	}, {
139a8bd6d8cSJohnny Huang 		10, 2, 3, "HCLK ratio AXI:AHB = 4:1"
140a8bd6d8cSJohnny Huang 	}, {
141a8bd6d8cSJohnny Huang 		12, 2, 0, "VGA memory size : 8MB"
142a8bd6d8cSJohnny Huang 	}, {
143a8bd6d8cSJohnny Huang 		12, 2, 1, "VGA memory size : 16MB"
144a8bd6d8cSJohnny Huang 	}, {
145a8bd6d8cSJohnny Huang 		12, 2, 2, "VGA memory size : 32MB"
146a8bd6d8cSJohnny Huang 	}, {
147a8bd6d8cSJohnny Huang 		12, 2, 3, "VGA memory size : 64MB"
148a8bd6d8cSJohnny Huang 	}, {
149a8bd6d8cSJohnny Huang 		14, 3, OTP_REG_RESERVED, ""
150a8bd6d8cSJohnny Huang 	}, {
151a8bd6d8cSJohnny Huang 		17, 1, 0, "VGA class code : Class Code for video device"
152a8bd6d8cSJohnny Huang 	}, {
153a8bd6d8cSJohnny Huang 		17, 1, 1, "VGA class code : Class Code for VGA device"
154a8bd6d8cSJohnny Huang 	}, {
155a8bd6d8cSJohnny Huang 		18, 1, 0, "Enable debug interfaces 0"
156a8bd6d8cSJohnny Huang 	}, {
157a8bd6d8cSJohnny Huang 		18, 1, 1, "Disable debug interfaces 0"
158a8bd6d8cSJohnny Huang 	}, {
159a8bd6d8cSJohnny Huang 		19, 1, 0, "Boot from emmc mode : High eMMC speed"
160a8bd6d8cSJohnny Huang 	}, {
161a8bd6d8cSJohnny Huang 		19, 1, 1, "Boot from emmc mode : Normal eMMC speed"
162a8bd6d8cSJohnny Huang 	}, {
163a8bd6d8cSJohnny Huang 		20, 1, 0, "Enable Pcie EHCI device"
164a8bd6d8cSJohnny Huang 	}, {
165a8bd6d8cSJohnny Huang 		20, 1, 1, "Disable Pcie EHCI device"
166a8bd6d8cSJohnny Huang 	}, {
167a8bd6d8cSJohnny Huang 		21, 1, 0, "Enable VGA XDMA function"
168a8bd6d8cSJohnny Huang 	}, {
169a8bd6d8cSJohnny Huang 		21, 1, 1, "Disable VGA XDMA function"
170a8bd6d8cSJohnny Huang 	}, {
171a8bd6d8cSJohnny Huang 		22, 1, 0, "Normal BMC mode"
172a8bd6d8cSJohnny Huang 	}, {
173a8bd6d8cSJohnny Huang 		22, 1, 1, "Disable dedicated BMC functions for non-BMC application"
174a8bd6d8cSJohnny Huang 	}, {
175a8bd6d8cSJohnny Huang 		23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin"
176a8bd6d8cSJohnny Huang 	}, {
177a8bd6d8cSJohnny Huang 		23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin"
178a8bd6d8cSJohnny Huang 	}, {
179a8bd6d8cSJohnny Huang 		24, 1, 0, "DRAM types : DDR3"
180a8bd6d8cSJohnny Huang 	}, {
181a8bd6d8cSJohnny Huang 		24, 1, 1, "DRAM types : DDR4"
182a8bd6d8cSJohnny Huang 	}, {
183a8bd6d8cSJohnny Huang 		25, 5, OTP_REG_RESERVED, ""
184a8bd6d8cSJohnny Huang 	}, {
185a8bd6d8cSJohnny Huang 		30, 2, OTP_REG_RESERVED, ""
186a8bd6d8cSJohnny Huang 	}, {
187a8bd6d8cSJohnny Huang 		32, 1, 0, "MAC 3 : RMII/NCSI"
188a8bd6d8cSJohnny Huang 	}, {
189a8bd6d8cSJohnny Huang 		32, 1, 1, "MAC 3 : RGMII"
190a8bd6d8cSJohnny Huang 	}, {
191a8bd6d8cSJohnny Huang 		33, 1, 0, "MAC 4 : RMII/NCSI"
192a8bd6d8cSJohnny Huang 	}, {
193a8bd6d8cSJohnny Huang 		33, 1, 1, "MAC 4 : RGMII"
194a8bd6d8cSJohnny Huang 	}, {
195a8bd6d8cSJohnny Huang 		34, 1, 0, "SuperIO configuration address : 0x2E"
196a8bd6d8cSJohnny Huang 	}, {
197a8bd6d8cSJohnny Huang 		34, 1, 1, "SuperIO configuration address : 0x4E"
198a8bd6d8cSJohnny Huang 	}, {
199a8bd6d8cSJohnny Huang 		35, 1, 0, "Enable LPC to decode SuperIO"
200a8bd6d8cSJohnny Huang 	}, {
201a8bd6d8cSJohnny Huang 		35, 1, 1, "Disable LPC to decode SuperIO"
202a8bd6d8cSJohnny Huang 	}, {
203a8bd6d8cSJohnny Huang 		36, 1, 0, "Enable debug interfaces 1"
204a8bd6d8cSJohnny Huang 	}, {
205a8bd6d8cSJohnny Huang 		36, 1, 1, "Disable debug interfaces 1"
206a8bd6d8cSJohnny Huang 	}, {
207a8bd6d8cSJohnny Huang 		37, 1, 0, "Disable ACPI function"
208a8bd6d8cSJohnny Huang 	}, {
209a8bd6d8cSJohnny Huang 		37, 1, 1, "Enable ACPI function"
210a8bd6d8cSJohnny Huang 	}, {
211a8bd6d8cSJohnny Huang 		38, 1, 0, "Enable eSPI mode"
212a8bd6d8cSJohnny Huang 	}, {
213a8bd6d8cSJohnny Huang 		38, 1, 1, "Enable LPC mode"
214a8bd6d8cSJohnny Huang 	}, {
215a8bd6d8cSJohnny Huang 		39, 1, 0, "Enable SAFS mode"
216a8bd6d8cSJohnny Huang 	}, {
217a8bd6d8cSJohnny Huang 		39, 1, 1, "Enable SAFS mode"
218a8bd6d8cSJohnny Huang 	}, {
219a8bd6d8cSJohnny Huang 		40, 2, OTP_REG_RESERVED, ""
220a8bd6d8cSJohnny Huang 	}, {
221a8bd6d8cSJohnny Huang 		42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection"
222a8bd6d8cSJohnny Huang 	}, {
223a8bd6d8cSJohnny Huang 		42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection"
224a8bd6d8cSJohnny Huang 	}, {
225a8bd6d8cSJohnny Huang 		43, 1, 0, "Disable boot SPI ABR"
226a8bd6d8cSJohnny Huang 	}, {
227a8bd6d8cSJohnny Huang 		43, 1, 1, "Enable boot SPI ABR"
228a8bd6d8cSJohnny Huang 	}, {
229a8bd6d8cSJohnny Huang 		44, 1, 0, "Boot SPI ABR mode : dual SPI flash"
230a8bd6d8cSJohnny Huang 	}, {
231a8bd6d8cSJohnny Huang 		44, 1, 1, "Boot SPI ABR mode : single SPI flash"
232a8bd6d8cSJohnny Huang 	}, {
233a8bd6d8cSJohnny Huang 		45, 3, 0, "Boot SPI flash size : no define size"
234a8bd6d8cSJohnny Huang 	}, {
235a8bd6d8cSJohnny Huang 		45, 3, 1, "Boot SPI flash size : 2MB"
236a8bd6d8cSJohnny Huang 	}, {
237a8bd6d8cSJohnny Huang 		45, 3, 2, "Boot SPI flash size : 4MB"
238a8bd6d8cSJohnny Huang 	}, {
239a8bd6d8cSJohnny Huang 		45, 3, 3, "Boot SPI flash size : 8MB"
240a8bd6d8cSJohnny Huang 	}, {
241a8bd6d8cSJohnny Huang 		45, 3, 4, "Boot SPI flash size : 16MB"
242a8bd6d8cSJohnny Huang 	}, {
243a8bd6d8cSJohnny Huang 		45, 3, 5, "Boot SPI flash size : 32MB"
244a8bd6d8cSJohnny Huang 	}, {
245a8bd6d8cSJohnny Huang 		45, 3, 6, "Boot SPI flash size : 64MB"
246a8bd6d8cSJohnny Huang 	}, {
247a8bd6d8cSJohnny Huang 		45, 3, 7, "Boot SPI flash size : 128MB"
248a8bd6d8cSJohnny Huang 	}, {
249a8bd6d8cSJohnny Huang 		48, 1, 0, "Disable host SPI ABR"
250a8bd6d8cSJohnny Huang 	}, {
251a8bd6d8cSJohnny Huang 		48, 1, 1, "Enable host SPI ABR"
252a8bd6d8cSJohnny Huang 	}, {
253a8bd6d8cSJohnny Huang 		49, 1, 0, "Disable host SPI ABR mode select pin"
254a8bd6d8cSJohnny Huang 	}, {
255a8bd6d8cSJohnny Huang 		49, 1, 1, "Enable host SPI ABR mode select pin"
256a8bd6d8cSJohnny Huang 	}, {
257a8bd6d8cSJohnny Huang 		50, 1, 0, "Host SPI ABR mode : dual SPI flash"
258a8bd6d8cSJohnny Huang 	}, {
259a8bd6d8cSJohnny Huang 		50, 1, 1, "Host SPI ABR mode : single SPI flash"
260a8bd6d8cSJohnny Huang 	}, {
261a8bd6d8cSJohnny Huang 		51, 3, 0, "Host SPI flash size : no define size"
262a8bd6d8cSJohnny Huang 	}, {
263a8bd6d8cSJohnny Huang 		51, 3, 1, "Host SPI flash size : 2MB"
264a8bd6d8cSJohnny Huang 	}, {
265a8bd6d8cSJohnny Huang 		51, 3, 2, "Host SPI flash size : 4MB"
266a8bd6d8cSJohnny Huang 	}, {
267a8bd6d8cSJohnny Huang 		51, 3, 3, "Host SPI flash size : 8MB"
268a8bd6d8cSJohnny Huang 	}, {
269a8bd6d8cSJohnny Huang 		51, 3, 4, "Host SPI flash size : 16MB"
270a8bd6d8cSJohnny Huang 	}, {
271a8bd6d8cSJohnny Huang 		51, 3, 5, "Host SPI flash size : 32MB"
272a8bd6d8cSJohnny Huang 	}, {
273a8bd6d8cSJohnny Huang 		51, 3, 6, "Host SPI flash size : 64MB"
274a8bd6d8cSJohnny Huang 	}, {
275a8bd6d8cSJohnny Huang 		51, 3, 7, "Host SPI flash size : 128MB"
276a8bd6d8cSJohnny Huang 	}, {
277a8bd6d8cSJohnny Huang 		54, 1, 0, "Disable boot SPI auxiliary control pins"
278a8bd6d8cSJohnny Huang 	}, {
279a8bd6d8cSJohnny Huang 		54, 1, 1, "Enable boot SPI auxiliary control pins"
280a8bd6d8cSJohnny Huang 	}, {
281a8bd6d8cSJohnny Huang 		55, 2, 0, "Boot SPI CRTM size : disable CRTM"
282a8bd6d8cSJohnny Huang 	}, {
283a8bd6d8cSJohnny Huang 		55, 2, 1, "Boot SPI CRTM size : 256KB"
284a8bd6d8cSJohnny Huang 	}, {
285a8bd6d8cSJohnny Huang 		55, 2, 2, "Boot SPI CRTM size : 512KB"
286a8bd6d8cSJohnny Huang 	}, {
287a8bd6d8cSJohnny Huang 		55, 2, 3, "Boot SPI CRTM size : 1MB"
288a8bd6d8cSJohnny Huang 	}, {
289a8bd6d8cSJohnny Huang 		57, 2, 0, "Host SPI CRTM size : disable CRTM"
290a8bd6d8cSJohnny Huang 	}, {
291a8bd6d8cSJohnny Huang 		57, 2, 1, "Host SPI CRTM size : 256KB"
292a8bd6d8cSJohnny Huang 	}, {
293a8bd6d8cSJohnny Huang 		57, 2, 2, "Host SPI CRTM size : 512KB"
294a8bd6d8cSJohnny Huang 	}, {
295a8bd6d8cSJohnny Huang 		57, 2, 3, "Host SPI CRTM size : 1MB"
296a8bd6d8cSJohnny Huang 	}, {
297a8bd6d8cSJohnny Huang 		59, 1, 0, "Disable host SPI auxiliary control pins"
298a8bd6d8cSJohnny Huang 	}, {
299a8bd6d8cSJohnny Huang 		59, 1, 1, "Enable host SPI auxiliary control pins"
300a8bd6d8cSJohnny Huang 	}, {
301a8bd6d8cSJohnny Huang 		60, 1, 0, "Disable GPIO pass through"
302a8bd6d8cSJohnny Huang 	}, {
303a8bd6d8cSJohnny Huang 		60, 1, 1, "Enable GPIO pass through"
304a8bd6d8cSJohnny Huang 	}, {
305a8bd6d8cSJohnny Huang 		61, 1, 0, "Enable low security secure boot key"
306a8bd6d8cSJohnny Huang 	}, {
307a8bd6d8cSJohnny Huang 		61, 1, 1, "Disable low security secure boot key"
308a8bd6d8cSJohnny Huang 	}, {
309a8bd6d8cSJohnny Huang 		62, 1, 0, "Disable dedicate GPIO strap pins"
310a8bd6d8cSJohnny Huang 	}, {
311a8bd6d8cSJohnny Huang 		62, 1, 1, "Enable dedicate GPIO strap pins"
312*b458cd62SJohnny Huang 	}, {
313*b458cd62SJohnny Huang 		63, 1, OTP_REG_RESERVED, ""
314a8bd6d8cSJohnny Huang 	}
31576d13988SJohnny Huang };
316*b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = {
317*b458cd62SJohnny Huang 	{
318*b458cd62SJohnny Huang 		0, 0, 1, 0, "Enable Secure Region programming"
319*b458cd62SJohnny Huang 	}, {
320*b458cd62SJohnny Huang 		0, 0, 1, 1, "Disable Secure Region programming"
321*b458cd62SJohnny Huang 	}, {
322*b458cd62SJohnny Huang 		0, 1, 1, 0, "Disable Secure Boot"
323*b458cd62SJohnny Huang 	}, {
324*b458cd62SJohnny Huang 		0, 1, 1, 1, "Enable Secure Boot"
325*b458cd62SJohnny Huang 	}, {
326*b458cd62SJohnny Huang 		0, 2, 1, 0, "Initialization programming not done"
327*b458cd62SJohnny Huang 	}, {
328*b458cd62SJohnny Huang 		0, 2, 1, 1, "Initialization programming done"
329*b458cd62SJohnny Huang 	}, {
330*b458cd62SJohnny Huang 		0, 3, 1, 0, "User region ECC disable"
331*b458cd62SJohnny Huang 	}, {
332*b458cd62SJohnny Huang 		0, 3, 1, 1, "User region ECC enable"
333*b458cd62SJohnny Huang 	}, {
334*b458cd62SJohnny Huang 		0, 4, 1, 0, "Secure Region ECC disable"
335*b458cd62SJohnny Huang 	}, {
336*b458cd62SJohnny Huang 		0, 4, 1, 1, "Secure Region ECC enable"
337*b458cd62SJohnny Huang 	}, {
338*b458cd62SJohnny Huang 		0, 5, 1, 0, "Enable low security key"
339*b458cd62SJohnny Huang 	}, {
340*b458cd62SJohnny Huang 		0, 5, 1, 1, "Disable low security key"
341*b458cd62SJohnny Huang 	}, {
342*b458cd62SJohnny Huang 		0, 6, 1, 0, "Do not ignore Secure Boot hardware strap"
343*b458cd62SJohnny Huang 	}, {
344*b458cd62SJohnny Huang 		0, 6, 1, 1, "Ignore Secure Boot hardware strap"
345*b458cd62SJohnny Huang 	}, {
346*b458cd62SJohnny Huang 		0, 7, 1, 0, "Secure Boot Mode: 2"
347*b458cd62SJohnny Huang 	}, {
348*b458cd62SJohnny Huang 		0, 7, 1, 1, "Secure Boot Mode: 1"
349*b458cd62SJohnny Huang 	}, {
350*b458cd62SJohnny Huang 		0, 8, 2, 0, "Single cell mode (recommended)"
351*b458cd62SJohnny Huang 	}, {
352*b458cd62SJohnny Huang 		0, 8, 2, 1, "Differnetial mode"
353*b458cd62SJohnny Huang 	}, {
354*b458cd62SJohnny Huang 		0, 8, 2, 2, "Differential-redundant mode"
355*b458cd62SJohnny Huang 	}, {
356*b458cd62SJohnny Huang 		0, 10, 2, 0, "RSA mode : RSA1024"
357*b458cd62SJohnny Huang 	}, {
358*b458cd62SJohnny Huang 		0, 10, 2, 1, "RSA mode : RSA2048"
359*b458cd62SJohnny Huang 	}, {
360*b458cd62SJohnny Huang 		0, 10, 2, 2, "RSA mode : RSA3072"
361*b458cd62SJohnny Huang 	}, {
362*b458cd62SJohnny Huang 		0, 10, 2, 3, "RSA mode : RSA4096"
363*b458cd62SJohnny Huang 	}, {
364*b458cd62SJohnny Huang 		0, 12, 2, 0, "SHA mode : SHA224"
365*b458cd62SJohnny Huang 	}, {
366*b458cd62SJohnny Huang 		0, 12, 2, 1, "SHA mode : SHA256"
367*b458cd62SJohnny Huang 	}, {
368*b458cd62SJohnny Huang 		0, 12, 2, 2, "SHA mode : SHA384"
369*b458cd62SJohnny Huang 	}, {
370*b458cd62SJohnny Huang 		0, 12, 2, 3, "SHA mode : SHA512"
371*b458cd62SJohnny Huang 	}, {
372*b458cd62SJohnny Huang 		0, 14, 2, OTP_REG_RESERVED, ""
373*b458cd62SJohnny Huang 	}, {
374*b458cd62SJohnny Huang 		0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x"
375*b458cd62SJohnny Huang 	}, {
376*b458cd62SJohnny Huang 		0, 22, 1, 0, "Secure Region : Writable"
377*b458cd62SJohnny Huang 	}, {
378*b458cd62SJohnny Huang 		0, 22, 1, 1, "Secure Region : Write Protect"
379*b458cd62SJohnny Huang 	}, {
380*b458cd62SJohnny Huang 		0, 23, 1, 0, "User Region : Writable"
381*b458cd62SJohnny Huang 	}, {
382*b458cd62SJohnny Huang 		0, 23, 1, 1, "User Region : Write Protect"
383*b458cd62SJohnny Huang 	}, {
384*b458cd62SJohnny Huang 		0, 24, 1, 0, "Configure Region : Writable"
385*b458cd62SJohnny Huang 	}, {
386*b458cd62SJohnny Huang 		0, 24, 1, 1, "Configure Region : Write Protect"
387*b458cd62SJohnny Huang 	}, {
388*b458cd62SJohnny Huang 		0, 25, 1, 0, "OTP strap Region : Writable"
389*b458cd62SJohnny Huang 	}, {
390*b458cd62SJohnny Huang 		0, 25, 1, 1, "OTP strap Region : Write Protect"
391*b458cd62SJohnny Huang 	}, {
392*b458cd62SJohnny Huang 		0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM"
393*b458cd62SJohnny Huang 	}, {
394*b458cd62SJohnny Huang 		0, 26, 1, 1, "Copy Boot Image to Internal SRAM"
395*b458cd62SJohnny Huang 	}, {
396*b458cd62SJohnny Huang 		0, 27, 1, 0, "Disable image encryption"
397*b458cd62SJohnny Huang 	}, {
398*b458cd62SJohnny Huang 		0, 27, 1, 1, "Enable image encryption"
399*b458cd62SJohnny Huang 	}, {
400*b458cd62SJohnny Huang 		0, 28, 1, OTP_REG_RESERVED, ""
401*b458cd62SJohnny Huang 	}, {
402*b458cd62SJohnny Huang 		0, 29, 1, 0, "OTP key retire Region : Writable"
403*b458cd62SJohnny Huang 	}, {
404*b458cd62SJohnny Huang 		0, 29, 1, 1, "OTP key retire Region : Write Protect"
405*b458cd62SJohnny Huang 	}, {
406*b458cd62SJohnny Huang 		0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable"
407*b458cd62SJohnny Huang 	}, {
408*b458cd62SJohnny Huang 		0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable"
409*b458cd62SJohnny Huang 	}, {
410*b458cd62SJohnny Huang 		0, 31, 1, 0, "SIPROM Mlock memory lock disable"
411*b458cd62SJohnny Huang 	}, {
412*b458cd62SJohnny Huang 		0, 31, 1, 1, "SIPROM Mlock memory lock enable"
413*b458cd62SJohnny Huang 	}, {
414*b458cd62SJohnny Huang 		2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x"
415*b458cd62SJohnny Huang 	}, {
416*b458cd62SJohnny Huang 		2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x"
417*b458cd62SJohnny Huang 	}, {
418*b458cd62SJohnny Huang 		3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x"
419*b458cd62SJohnny Huang 	}, {
420*b458cd62SJohnny Huang 		4, 0, 8, OTP_REG_VALID_BIT, "Keys valid  : %d"
421*b458cd62SJohnny Huang 	}, {
422*b458cd62SJohnny Huang 		4, 16, 8, OTP_REG_VALID_BIT, "Keys retire  : %d"
423*b458cd62SJohnny Huang 	}, {
424*b458cd62SJohnny Huang 		5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x"
425*b458cd62SJohnny Huang 	}, {
426*b458cd62SJohnny Huang 		6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x"
427*b458cd62SJohnny Huang 	}, {
428*b458cd62SJohnny Huang 		8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x"
429*b458cd62SJohnny Huang 	}, {
430*b458cd62SJohnny Huang 		10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x"
431*b458cd62SJohnny Huang 	}, {
432*b458cd62SJohnny Huang 		11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x"
433*b458cd62SJohnny Huang 	}
434*b458cd62SJohnny Huang };
4352a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
43669d5fd8fSJohnny Huang {
43769d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
43869d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
43969d5fd8fSJohnny Huang 	udelay(2);
44069d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
44169d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
44269d5fd8fSJohnny Huang }
44369d5fd8fSJohnny Huang 
4442a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
44569d5fd8fSJohnny Huang {
44669d5fd8fSJohnny Huang 	int config_offset;
44769d5fd8fSJohnny Huang 
44869d5fd8fSJohnny Huang 	config_offset = 0x800;
44969d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
45069d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
45169d5fd8fSJohnny Huang 
45269d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
45369d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
45469d5fd8fSJohnny Huang 	udelay(2);
45569d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
45669d5fd8fSJohnny Huang }
45769d5fd8fSJohnny Huang 
45869d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
45969d5fd8fSJohnny Huang {
46069d5fd8fSJohnny Huang 	int i;
46169d5fd8fSJohnny Huang 	uint32_t ret[1];
46269d5fd8fSJohnny Huang 
46369d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
4642a856b9aSJohnny Huang 		return OTP_USAGE;
46569d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
46669d5fd8fSJohnny Huang 		otp_read_config(i, ret);
467a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
46869d5fd8fSJohnny Huang 	}
46969d5fd8fSJohnny Huang 	printf("\n");
4702a856b9aSJohnny Huang 	return OTP_SUCCESS;
47169d5fd8fSJohnny Huang }
47269d5fd8fSJohnny Huang 
47369d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
47469d5fd8fSJohnny Huang {
47569d5fd8fSJohnny Huang 	int i;
47669d5fd8fSJohnny Huang 	uint32_t ret[2];
47769d5fd8fSJohnny Huang 
47869d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
4792a856b9aSJohnny Huang 		return OTP_USAGE;
48069d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
48169d5fd8fSJohnny Huang 		otp_read_data(i, ret);
48269d5fd8fSJohnny Huang 		if (i % 4 == 0)
48369d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
48469d5fd8fSJohnny Huang 		else
48569d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
48669d5fd8fSJohnny Huang 
48769d5fd8fSJohnny Huang 	}
48869d5fd8fSJohnny Huang 	printf("\n");
4892a856b9aSJohnny Huang 	return OTP_SUCCESS;
49069d5fd8fSJohnny Huang }
49169d5fd8fSJohnny Huang 
49269d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
49369d5fd8fSJohnny Huang {
49469d5fd8fSJohnny Huang 	uint32_t ret;
49569d5fd8fSJohnny Huang 	uint32_t *buf;
49669d5fd8fSJohnny Huang 
49769d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
49869d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
49969d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
50069d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
50169d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
50269d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
50369d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
50469d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
50569d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
50669d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
50769d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
50869d5fd8fSJohnny Huang 	udelay(10);
50969d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
51069d5fd8fSJohnny Huang 	if (ret & 0x1)
51169d5fd8fSJohnny Huang 		return 0;
51269d5fd8fSJohnny Huang 	else
51369d5fd8fSJohnny Huang 		return -1;
51469d5fd8fSJohnny Huang }
51569d5fd8fSJohnny Huang 
51669d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
51769d5fd8fSJohnny Huang {
51869d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
51969d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
52069d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
52169d5fd8fSJohnny Huang 	udelay(100);
52269d5fd8fSJohnny Huang }
52369d5fd8fSJohnny Huang 
52469d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
52569d5fd8fSJohnny Huang {
52669d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
52769d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
52869d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
52969d5fd8fSJohnny Huang 	udelay(85);
53069d5fd8fSJohnny Huang }
53169d5fd8fSJohnny Huang 
532a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
53369d5fd8fSJohnny Huang {
53469d5fd8fSJohnny Huang 	int ret;
53569d5fd8fSJohnny Huang 
53669d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
53769d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
53869d5fd8fSJohnny Huang 	udelay(2);
53969d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
540a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
54169d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
54269d5fd8fSJohnny Huang 		return 0;
54369d5fd8fSJohnny Huang 	else
54469d5fd8fSJohnny Huang 		return -1;
54569d5fd8fSJohnny Huang }
54669d5fd8fSJohnny Huang 
547d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
5484c1c9b35SJohnny Huang {
5494c1c9b35SJohnny Huang 	uint32_t ret[2];
5504c1c9b35SJohnny Huang 
5514c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
5524c1c9b35SJohnny Huang 
5534c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
5544c1c9b35SJohnny Huang 		writel(otp_addr, 0x1e6f2010); //Read address
5554c1c9b35SJohnny Huang 	else
5564c1c9b35SJohnny Huang 		writel(otp_addr - 1, 0x1e6f2010); //Read address
5574c1c9b35SJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
5584c1c9b35SJohnny Huang 	udelay(2);
5594c1c9b35SJohnny Huang 	ret[0] = readl(0x1e6f2020);
5604c1c9b35SJohnny Huang 	ret[1] = readl(0x1e6f2024);
5614c1c9b35SJohnny Huang 	if (size == 1) {
5624c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
5634c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
564d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
5654c1c9b35SJohnny Huang 				compare[0] = 0;
5664c1c9b35SJohnny Huang 				return 0;
5674c1c9b35SJohnny Huang 			} else {
5684c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
5694c1c9b35SJohnny Huang 				return -1;
5704c1c9b35SJohnny Huang 			}
5714c1c9b35SJohnny Huang 
5724c1c9b35SJohnny Huang 		} else {
5734c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
574d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
5754c1c9b35SJohnny Huang 				compare[0] = ~0;
5764c1c9b35SJohnny Huang 				return 0;
5774c1c9b35SJohnny Huang 			} else {
578d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
5794c1c9b35SJohnny Huang 				return -1;
5804c1c9b35SJohnny Huang 			}
5814c1c9b35SJohnny Huang 		}
5824c1c9b35SJohnny Huang 	} else if (size == 2) {
5834c1c9b35SJohnny Huang 		// otp_addr should be even
584d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
5854c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
5864c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
5874c1c9b35SJohnny Huang 			compare[0] = 0;
5884c1c9b35SJohnny Huang 			compare[1] = ~0;
5894c1c9b35SJohnny Huang 			return 0;
5904c1c9b35SJohnny Huang 		} else {
5914c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
5924c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
5934c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
5944c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
5954c1c9b35SJohnny Huang 			return -1;
5964c1c9b35SJohnny Huang 		}
5974c1c9b35SJohnny Huang 	} else {
5984c1c9b35SJohnny Huang 		return -1;
5994c1c9b35SJohnny Huang 	}
6004c1c9b35SJohnny Huang }
6014c1c9b35SJohnny Huang 
6027e22f42dSJohnny Huang static void otp_soak(int soak)
603d90825e2SJohnny Huang {
604d90825e2SJohnny Huang 	if (soak) {
605d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
606d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
607d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
608d90825e2SJohnny Huang 		writel(0x041930d4, 0x1e602008); //soak program
609d90825e2SJohnny Huang 	} else {
610d90825e2SJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
611d90825e2SJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
612d90825e2SJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
613d90825e2SJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
614d90825e2SJohnny Huang 	}
615d90825e2SJohnny Huang }
616d90825e2SJohnny Huang 
617d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
618d90825e2SJohnny Huang {
619d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
620d90825e2SJohnny Huang 
621d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
622d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
623d90825e2SJohnny Huang 			continue;
624d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
625d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
626d90825e2SJohnny Huang 			if (bit_value)
627d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
628d90825e2SJohnny Huang 			else
629d90825e2SJohnny Huang 				continue;
630d90825e2SJohnny Huang 		} else {
631d90825e2SJohnny Huang 			prog_address |= 1 << 15;
632d90825e2SJohnny Huang 			if (bit_value)
633d90825e2SJohnny Huang 				continue;
634d90825e2SJohnny Huang 			else
635d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
636d90825e2SJohnny Huang 		}
637d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
638d90825e2SJohnny Huang 	}
639d90825e2SJohnny Huang }
640d90825e2SJohnny Huang 
64176d13988SJohnny Huang 
64276d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap)
64376d13988SJohnny Huang {
64476d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
64576d13988SJohnny Huang 	int i, j;
64676d13988SJohnny Huang 
64776d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
64876d13988SJohnny Huang 		otpstrap[j].value = 0;
64976d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
65076d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
65176d13988SJohnny Huang 		otpstrap[j].protected = 0;
65276d13988SJohnny Huang 	}
65376d13988SJohnny Huang 
65476d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
65576d13988SJohnny Huang 		int option = (i - 16) / 2;
65676d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
65776d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
65876d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
65976d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
66076d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
66176d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
66276d13988SJohnny Huang 			}
66376d13988SJohnny Huang 			if (bit_value == 1)
66476d13988SJohnny Huang 				otpstrap[j].remain_times --;
66576d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
66676d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
66776d13988SJohnny Huang 		}
66876d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
66976d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
67076d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
67176d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
67276d13988SJohnny Huang 			}
67376d13988SJohnny Huang 			if (bit_value == 1)
67476d13988SJohnny Huang 				otpstrap[j].remain_times --;
67576d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
67676d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
67776d13988SJohnny Huang 		}
67876d13988SJohnny Huang 	}
67976d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
68076d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
68176d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
68276d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
68376d13988SJohnny Huang 			otpstrap[j].protected = 1;
68476d13988SJohnny Huang 	}
68576d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
68676d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
68776d13988SJohnny Huang 			otpstrap[j].protected = 1;
68876d13988SJohnny Huang 	}
68976d13988SJohnny Huang }
69076d13988SJohnny Huang 
691*b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG)
69269d5fd8fSJohnny Huang {
693442839bbSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[12];
694*b458cd62SJohnny Huang 	uint32_t mask;
695*b458cd62SJohnny Huang 	uint32_t dw_offset;
696*b458cd62SJohnny Huang 	uint32_t bit_offset;
697*b458cd62SJohnny Huang 	uint32_t otp_value;
698*b458cd62SJohnny Huang 	uint32_t otp_keep;
699*b458cd62SJohnny Huang 	int fail = 0;
700*b458cd62SJohnny Huang 	int valid_bit = 0;
70166f2f8e5SJohnny Huang 	int i;
70266f2f8e5SJohnny Huang 
703737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
70466f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
705*b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
706*b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
707*b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
708*b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
709*b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
710*b458cd62SJohnny Huang 		otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask;
711*b458cd62SJohnny Huang 
712*b458cd62SJohnny Huang 		if (otp_keep == mask) {
713*b458cd62SJohnny Huang 			continue;
714*b458cd62SJohnny Huang 		} else if (otp_keep != 0) {
715*b458cd62SJohnny Huang 			fail = 1;
716*b458cd62SJohnny Huang 		}
717*b458cd62SJohnny Huang 
718*b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
719*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
720*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
721*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
722*b458cd62SJohnny Huang 			continue;
723*b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
724*b458cd62SJohnny Huang 
725*b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
726*b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
72766f2f8e5SJohnny Huang 		} else {
728*b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
729*b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
730*b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
73166f2f8e5SJohnny Huang 		}
732*b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
733*b458cd62SJohnny Huang 
734*b458cd62SJohnny Huang 		if (fail) {
735*b458cd62SJohnny Huang 			printf("Keep mask error\n");
736*b458cd62SJohnny Huang 		} else {
737*b458cd62SJohnny Huang 			if (a0_conf_info[i].value == OTP_REG_RESERVED) {
738*b458cd62SJohnny Huang 				printf("Reserved\n");
739*b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
740*b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, otp_value);
741*b458cd62SJohnny Huang 				printf("\n");
742*b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
743*b458cd62SJohnny Huang 				if (otp_value != 0) {
744*b458cd62SJohnny Huang 					for (i = 0; i < 7; i++) {
745*b458cd62SJohnny Huang 						if (otp_value == (1 << i)) {
746*b458cd62SJohnny Huang 							valid_bit = i + 1;
74766f2f8e5SJohnny Huang 						}
748*b458cd62SJohnny Huang 					}
749*b458cd62SJohnny Huang 				} else {
750*b458cd62SJohnny Huang 					valid_bit = 0;
751*b458cd62SJohnny Huang 				}
752*b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, valid_bit);
753*b458cd62SJohnny Huang 				printf("\n");
754*b458cd62SJohnny Huang 			} else {
755*b458cd62SJohnny Huang 				printf("%s\n", a0_conf_info[i].information);
756*b458cd62SJohnny Huang 			}
757*b458cd62SJohnny Huang 		}
758*b458cd62SJohnny Huang 	}
759*b458cd62SJohnny Huang 
760*b458cd62SJohnny Huang 	if (fail)
761*b458cd62SJohnny Huang 		return OTP_FAILURE;
762*b458cd62SJohnny Huang 
76366f2f8e5SJohnny Huang 	return OTP_SUCCESS;
76466f2f8e5SJohnny Huang }
76566f2f8e5SJohnny Huang 
766*b458cd62SJohnny Huang static int otp_print_conf_info(int view)
76766f2f8e5SJohnny Huang {
768*b458cd62SJohnny Huang 	uint32_t OTPCFG[12];
769*b458cd62SJohnny Huang 	uint32_t mask;
770*b458cd62SJohnny Huang 	uint32_t dw_offset;
771*b458cd62SJohnny Huang 	uint32_t bit_offset;
772*b458cd62SJohnny Huang 	uint32_t otp_value;
773*b458cd62SJohnny Huang 	int valid_bit = 0;
77466f2f8e5SJohnny Huang 	int i;
77566f2f8e5SJohnny Huang 
77666f2f8e5SJohnny Huang 	for (i = 0; i < 12; i++)
77766f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
77866f2f8e5SJohnny Huang 
77966f2f8e5SJohnny Huang 
780*b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
781*b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
782*b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
783*b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
784*b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
785*b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
786*b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
787*b458cd62SJohnny Huang 
788*b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
789*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
790*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
791*b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
792*b458cd62SJohnny Huang 			continue;
793*b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
794*b458cd62SJohnny Huang 
795*b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
796*b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
797*b458cd62SJohnny Huang 		} else {
798*b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
799*b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
800*b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
801*b458cd62SJohnny Huang 		}
802*b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
803*b458cd62SJohnny Huang 
804*b458cd62SJohnny Huang 		if (a0_conf_info[i].value == OTP_REG_RESERVED) {
805*b458cd62SJohnny Huang 			printf("Reserved\n");
806*b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
807*b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, otp_value);
808*b458cd62SJohnny Huang 			printf("\n");
809*b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
810*b458cd62SJohnny Huang 			if (otp_value != 0) {
811*b458cd62SJohnny Huang 				for (i = 0; i < 7; i++) {
812*b458cd62SJohnny Huang 					if (otp_value == (1 << i)) {
813*b458cd62SJohnny Huang 						valid_bit = i + 1;
814*b458cd62SJohnny Huang 					}
815*b458cd62SJohnny Huang 				}
816*b458cd62SJohnny Huang 			} else {
817*b458cd62SJohnny Huang 				valid_bit = 0;
818*b458cd62SJohnny Huang 			}
819*b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, valid_bit);
820*b458cd62SJohnny Huang 			printf("\n");
821*b458cd62SJohnny Huang 		} else {
822*b458cd62SJohnny Huang 			printf("%s\n", a0_conf_info[i].information);
823*b458cd62SJohnny Huang 		}
824*b458cd62SJohnny Huang 	}
825*b458cd62SJohnny Huang 	return OTP_SUCCESS;
82666f2f8e5SJohnny Huang }
82766f2f8e5SJohnny Huang 
828*b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP)
82976d13988SJohnny Huang {
830a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
831a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
83276d13988SJohnny Huang 	int i;
833a8bd6d8cSJohnny Huang 	int fail = 0;
834a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
835a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
836a8bd6d8cSJohnny Huang 	uint32_t mask;
837a8bd6d8cSJohnny Huang 	uint32_t otp_value;
838a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
839a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
84076d13988SJohnny Huang 
841a8bd6d8cSJohnny Huang 	printf("BIT(hex)   Value       Protect     Description\n");
842a8bd6d8cSJohnny Huang 	printf("__________________________________________________________________________________________\n");
843*b458cd62SJohnny Huang 
844a8bd6d8cSJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
845a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].bit_offset > 32) {
846a8bd6d8cSJohnny Huang 			dw_offset = 1;
847a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset - 32;
848a8bd6d8cSJohnny Huang 		} else {
849a8bd6d8cSJohnny Huang 			dw_offset = 0;
850a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset;
851a8bd6d8cSJohnny Huang 		}
85276d13988SJohnny Huang 
853a8bd6d8cSJohnny Huang 		mask = BIT(a0_strap_info[i].length) - 1;
854a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
855a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
856a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
857a8bd6d8cSJohnny Huang 
858a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
859a8bd6d8cSJohnny Huang 			continue;
860a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
861a8bd6d8cSJohnny Huang 			fail = 1;
862a8bd6d8cSJohnny Huang 		}
863a8bd6d8cSJohnny Huang 
864a8bd6d8cSJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
865a8bd6d8cSJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
866a8bd6d8cSJohnny Huang 			continue;
867a8bd6d8cSJohnny Huang 
868a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].length == 1) {
869*b458cd62SJohnny Huang 			printf("0x%-9X", a0_strap_info[i].bit_offset);
870a8bd6d8cSJohnny Huang 		} else {
871*b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
872a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1,
873a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset);
874a8bd6d8cSJohnny Huang 		}
875a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
876a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
877a8bd6d8cSJohnny Huang 
878a8bd6d8cSJohnny Huang 		if (fail) {
879a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
880a8bd6d8cSJohnny Huang 		} else {
881a8bd6d8cSJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
882a8bd6d8cSJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
883a8bd6d8cSJohnny Huang 			else
884a8bd6d8cSJohnny Huang 				printf("Reserved\n");
885a8bd6d8cSJohnny Huang 		}
886a8bd6d8cSJohnny Huang 	}
887a8bd6d8cSJohnny Huang 
888a8bd6d8cSJohnny Huang 	if (fail)
88976d13988SJohnny Huang 		return OTP_FAILURE;
89076d13988SJohnny Huang 
89176d13988SJohnny Huang 	return OTP_SUCCESS;
89276d13988SJohnny Huang }
89376d13988SJohnny Huang 
894*b458cd62SJohnny Huang static int otp_print_strap_info(int view)
89576d13988SJohnny Huang {
89676d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
897*b458cd62SJohnny Huang 	int i, j, k;
898*b458cd62SJohnny Huang 	int fail = 0;
899*b458cd62SJohnny Huang 	uint32_t bit_offset;
900*b458cd62SJohnny Huang 	uint32_t length;
901*b458cd62SJohnny Huang 	uint32_t otp_value;
902*b458cd62SJohnny Huang 	uint32_t otp_protect;
90376d13988SJohnny Huang 
90476d13988SJohnny Huang 	otp_strp_status(strap_status);
90576d13988SJohnny Huang 
906*b458cd62SJohnny Huang 	if (view) {
907*b458cd62SJohnny Huang 		printf("BIT(hex) Value  Option         Protect   Description\n");
908*b458cd62SJohnny Huang 		printf("                0 1 2 3 4 5 6\n");
909*b458cd62SJohnny Huang 		printf("_________________________________________________________________________________________________________\n");
910*b458cd62SJohnny Huang 	} else {
911*b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
912*b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
91376d13988SJohnny Huang 	}
914*b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
915*b458cd62SJohnny Huang 		otp_value = 0;
916*b458cd62SJohnny Huang 		bit_offset = a0_strap_info[i].bit_offset;
917*b458cd62SJohnny Huang 		length = a0_strap_info[i].length;
918*b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
919*b458cd62SJohnny Huang 			otp_value |= strap_status[bit_offset].value << j;
920*b458cd62SJohnny Huang 			otp_protect |= strap_status[bit_offset].protected << j;
921*b458cd62SJohnny Huang 		}
922*b458cd62SJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
923*b458cd62SJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
924*b458cd62SJohnny Huang 			continue;
925*b458cd62SJohnny Huang 		if (view) {
926*b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
927*b458cd62SJohnny Huang 				printf("0x%-7X", a0_strap_info[i].bit_offset + j);
928*b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
929*b458cd62SJohnny Huang 				for (k = 0; k < 7; k++) {
930*b458cd62SJohnny Huang 					printf("%X ", strap_status[bit_offset + j].option_array[k]);
931*b458cd62SJohnny Huang 				}
932*b458cd62SJohnny Huang 				printf(" ");
933*b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
934*b458cd62SJohnny Huang 				if (a0_strap_info[i].value == OTP_REG_RESERVED) {
935*b458cd62SJohnny Huang 					printf(" Reserved\n");
936*b458cd62SJohnny Huang 					continue;
937*b458cd62SJohnny Huang 				}
938*b458cd62SJohnny Huang 				if (length == 1) {
939*b458cd62SJohnny Huang 					printf(" %s\n", a0_strap_info[i].information);
940*b458cd62SJohnny Huang 					continue;
94176d13988SJohnny Huang 				}
94276d13988SJohnny Huang 
943*b458cd62SJohnny Huang 				if (j == 0)
944*b458cd62SJohnny Huang 					printf("/%s\n", a0_strap_info[i].information);
945*b458cd62SJohnny Huang 				else if (j == length - 1)
946*b458cd62SJohnny Huang 					printf("\\ \"\n");
947*b458cd62SJohnny Huang 				else
948*b458cd62SJohnny Huang 					printf("| \"\n");
94976d13988SJohnny Huang 			}
950*b458cd62SJohnny Huang 		} else {
951*b458cd62SJohnny Huang 			if (a0_strap_info[i].length == 1) {
952*b458cd62SJohnny Huang 				printf("0x%-9X", a0_strap_info[i].bit_offset);
953*b458cd62SJohnny Huang 			} else {
954*b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
955*b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
956*b458cd62SJohnny Huang 			}
957*b458cd62SJohnny Huang 
958*b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
959*b458cd62SJohnny Huang 
960*b458cd62SJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
961*b458cd62SJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
962*b458cd62SJohnny Huang 			else
963*b458cd62SJohnny Huang 				printf("Reserved\n");
964*b458cd62SJohnny Huang 		}
965*b458cd62SJohnny Huang 	}
966*b458cd62SJohnny Huang 
967*b458cd62SJohnny Huang 	if (fail)
968*b458cd62SJohnny Huang 		return OTP_FAILURE;
969*b458cd62SJohnny Huang 
970*b458cd62SJohnny Huang 	return OTP_SUCCESS;
971*b458cd62SJohnny Huang }
972*b458cd62SJohnny Huang 
973*b458cd62SJohnny Huang // static void otp_info_strap(int view)
974*b458cd62SJohnny Huang // {
975*b458cd62SJohnny Huang // 	struct otpstrap_status strap_status[64];
976*b458cd62SJohnny Huang // 	uint32_t OTPSTRAP[6];
977*b458cd62SJohnny Huang // 	int i;
978*b458cd62SJohnny Huang 
979*b458cd62SJohnny Huang 
980*b458cd62SJohnny Huang // 	otp_strp_status(strap_status);
981*b458cd62SJohnny Huang 
982*b458cd62SJohnny Huang // 	for (i = 0; i < 6; i++)
983*b458cd62SJohnny Huang // 		OTPSTRAP[i] = 0;
984*b458cd62SJohnny Huang // 	for (i = 0; i < 32; i++) {
985*b458cd62SJohnny Huang // 		OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i;
986*b458cd62SJohnny Huang // 		OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i;
987*b458cd62SJohnny Huang // 	}
988*b458cd62SJohnny Huang // 	for (i = 0; i < 32; i++) {
989*b458cd62SJohnny Huang // 		OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i;
990*b458cd62SJohnny Huang // 		OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i;
991*b458cd62SJohnny Huang // 	}
992*b458cd62SJohnny Huang 
993*b458cd62SJohnny Huang // 	otp_print_strap_info(OTPSTRAP, view);
994*b458cd62SJohnny Huang // }
99576d13988SJohnny Huang 
99669d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
99769d5fd8fSJohnny Huang {
99869d5fd8fSJohnny Huang 	int i;
99969d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
100069d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
100169d5fd8fSJohnny Huang 		if (i % 16 == 0) {
100269d5fd8fSJohnny Huang 			printf("%04X: ", i);
100369d5fd8fSJohnny Huang 		}
100469d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
100569d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
100669d5fd8fSJohnny Huang 			printf("\n");
100769d5fd8fSJohnny Huang 		}
100869d5fd8fSJohnny Huang 	}
100969d5fd8fSJohnny Huang }
101069d5fd8fSJohnny Huang 
10117f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
101269d5fd8fSJohnny Huang {
101369d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
101469d5fd8fSJohnny Huang 	char *byte_buf;
101569d5fd8fSJohnny Huang 	int i = 0, len = 0;
101669d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
101769d5fd8fSJohnny Huang 	while (1) {
101869d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
101969d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
102069d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
102169d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
102269d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
102369d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
10247f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
102569d5fd8fSJohnny Huang 		printf("Key Type: ");
102669d5fd8fSJohnny Huang 		switch (key_type) {
102769d5fd8fSJohnny Huang 		case 0:
102869d5fd8fSJohnny Huang 			printf("AES-256 as OEM platform key for image encryption/decryption\n");
102969d5fd8fSJohnny Huang 			break;
103069d5fd8fSJohnny Huang 		case 1:
103169d5fd8fSJohnny Huang 			printf("AES-256 as secret vault key\n");
103269d5fd8fSJohnny Huang 			break;
103369d5fd8fSJohnny Huang 		case 4:
103469d5fd8fSJohnny Huang 			printf("HMAC as encrypted OEM HMAC keys in Mode 1\n");
103569d5fd8fSJohnny Huang 			break;
103669d5fd8fSJohnny Huang 		case 8:
103769d5fd8fSJohnny Huang 			printf("RSA-public as OEM DSS public keys in Mode 2\n");
103869d5fd8fSJohnny Huang 			break;
103969d5fd8fSJohnny Huang 		case 9:
104069d5fd8fSJohnny Huang 			printf("RSA-public as SOC public key\n");
104169d5fd8fSJohnny Huang 			break;
104269d5fd8fSJohnny Huang 		case 10:
104369d5fd8fSJohnny Huang 			printf("RSA-public as AES key decryption key\n");
104469d5fd8fSJohnny Huang 			break;
104569d5fd8fSJohnny Huang 		case 13:
104669d5fd8fSJohnny Huang 			printf("RSA-private as SOC private key\n");
104769d5fd8fSJohnny Huang 			break;
104869d5fd8fSJohnny Huang 		case 14:
104969d5fd8fSJohnny Huang 			printf("RSA-private as AES key decryption key\n");
105069d5fd8fSJohnny Huang 			break;
105169d5fd8fSJohnny Huang 		default:
105269d5fd8fSJohnny Huang 			printf("key_type error: %x\n", key_type);
105369d5fd8fSJohnny Huang 			return -1;
105469d5fd8fSJohnny Huang 		}
105569d5fd8fSJohnny Huang 		if (key_type == 4) {
105669d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
105769d5fd8fSJohnny Huang 			switch (key_length) {
105869d5fd8fSJohnny Huang 			case 0:
105969d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
106069d5fd8fSJohnny Huang 				break;
106169d5fd8fSJohnny Huang 			case 1:
106269d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
106369d5fd8fSJohnny Huang 				break;
106469d5fd8fSJohnny Huang 			case 2:
106569d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
106669d5fd8fSJohnny Huang 				break;
106769d5fd8fSJohnny Huang 			case 3:
106869d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
106969d5fd8fSJohnny Huang 				break;
107069d5fd8fSJohnny Huang 			}
1071cd1610b4SJohnny Huang 		} else if (key_type != 0 && key_type != 1) {
107269d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
107369d5fd8fSJohnny Huang 			switch (key_length) {
107469d5fd8fSJohnny Huang 			case 0:
107569d5fd8fSJohnny Huang 				printf("RSA1024\n");
107669d5fd8fSJohnny Huang 				len = 0x100;
107769d5fd8fSJohnny Huang 				break;
107869d5fd8fSJohnny Huang 			case 1:
107969d5fd8fSJohnny Huang 				printf("RSA2048\n");
108069d5fd8fSJohnny Huang 				len = 0x200;
108169d5fd8fSJohnny Huang 				break;
108269d5fd8fSJohnny Huang 			case 2:
108369d5fd8fSJohnny Huang 				printf("RSA3072\n");
108469d5fd8fSJohnny Huang 				len = 0x300;
108569d5fd8fSJohnny Huang 				break;
108669d5fd8fSJohnny Huang 			case 3:
108769d5fd8fSJohnny Huang 				printf("RSA4096\n");
108869d5fd8fSJohnny Huang 				len = 0x400;
108969d5fd8fSJohnny Huang 				break;
109069d5fd8fSJohnny Huang 			}
109169d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
109269d5fd8fSJohnny Huang 		}
109369d5fd8fSJohnny Huang 		if (key_type == 4 || key_type == 8)
109469d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
109569d5fd8fSJohnny Huang 		printf("Key Value:\n");
109669d5fd8fSJohnny Huang 		if (key_type == 4) {
109769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
109869d5fd8fSJohnny Huang 		} else if (key_type == 0 || key_type == 1) {
109969d5fd8fSJohnny Huang 			printf("AES Key:\n");
110069d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
110169d5fd8fSJohnny Huang 			printf("AES IV:\n");
110269d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + 0x20], 0x10);
110369d5fd8fSJohnny Huang 
110469d5fd8fSJohnny Huang 		} else {
110569d5fd8fSJohnny Huang 			printf("RSA mod:\n");
110669d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
110769d5fd8fSJohnny Huang 			printf("RSA exp:\n");
110869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
110969d5fd8fSJohnny Huang 		}
111069d5fd8fSJohnny Huang 		if (last)
111169d5fd8fSJohnny Huang 			break;
111269d5fd8fSJohnny Huang 		i++;
111369d5fd8fSJohnny Huang 	}
111469d5fd8fSJohnny Huang 	return 0;
111569d5fd8fSJohnny Huang }
111669d5fd8fSJohnny Huang 
1117a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
111869d5fd8fSJohnny Huang {
1119a6d0d645SJohnny Huang 	int i, k;
1120d90825e2SJohnny Huang 	int pass = 0;
1121d90825e2SJohnny Huang 	int soak = 0;
1122a6d0d645SJohnny Huang 	uint32_t prog_address;
1123a6d0d645SJohnny Huang 	uint32_t data[12];
1124a6d0d645SJohnny Huang 	uint32_t compare[2];
1125d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[12];
1126d90825e2SJohnny Huang 	uint32_t data_masked;
1127d90825e2SJohnny Huang 	uint32_t buf_masked;
112869d5fd8fSJohnny Huang 
1129a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1130a6d0d645SJohnny Huang 
1131a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1132a6d0d645SJohnny Huang 	for (i = 0; i < 12 ; i ++) {
1133a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "");
113469d5fd8fSJohnny Huang 		prog_address = 0x800;
1135a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1136a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1137a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1138a6d0d645SJohnny Huang 	}
1139a6d0d645SJohnny Huang 
1140a6d0d645SJohnny Huang 	printf("Check writable...\n");
1141a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1142d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1143d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1144d90825e2SJohnny Huang 		if (data_masked == buf_masked)
114569d5fd8fSJohnny Huang 			continue;
1146d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1147a6d0d645SJohnny Huang 			continue;
1148a6d0d645SJohnny Huang 		} else {
1149a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1150a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1151a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1152a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
11532a856b9aSJohnny Huang 			return OTP_FAILURE;
1154a6d0d645SJohnny Huang 		}
1155a6d0d645SJohnny Huang 	}
1156a6d0d645SJohnny Huang 
1157a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1158a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1159d90825e2SJohnny Huang 	otp_soak(0);
1160a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1161d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1162d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1163a6d0d645SJohnny Huang 		prog_address = 0x800;
1164a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1165a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1166d90825e2SJohnny Huang 		if (data_masked == buf_masked) {
1167a6d0d645SJohnny Huang 			printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]);
1168a6d0d645SJohnny Huang 			continue;
1169a6d0d645SJohnny Huang 		}
1170d90825e2SJohnny Huang 		if (soak) {
1171d90825e2SJohnny Huang 			soak = 0;
1172d90825e2SJohnny Huang 			otp_soak(0);
1173d90825e2SJohnny Huang 		}
1174a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "[%03X]=%08X    ", prog_address, buf[i]);
1175a6d0d645SJohnny Huang 
1176d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1177a6d0d645SJohnny Huang 
117869d5fd8fSJohnny Huang 		pass = 0;
117969d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1180d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1181d90825e2SJohnny Huang 				if (soak == 0) {
1182d90825e2SJohnny Huang 					soak = 1;
1183d90825e2SJohnny Huang 					otp_soak(1);
1184d90825e2SJohnny Huang 				}
1185a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1186a6d0d645SJohnny Huang 			} else {
118769d5fd8fSJohnny Huang 				pass = 1;
118869d5fd8fSJohnny Huang 				break;
118969d5fd8fSJohnny Huang 			}
119069d5fd8fSJohnny Huang 		}
1191a6d0d645SJohnny Huang 	}
1192a6d0d645SJohnny Huang 
119369d5fd8fSJohnny Huang 	if (!pass)
11942a856b9aSJohnny Huang 		return OTP_FAILURE;
1195a6d0d645SJohnny Huang 
11962a856b9aSJohnny Huang 	return OTP_SUCCESS;
1197d90825e2SJohnny Huang 
119869d5fd8fSJohnny Huang }
119969d5fd8fSJohnny Huang 
120069d5fd8fSJohnny Huang 
120176d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
120269d5fd8fSJohnny Huang {
120369d5fd8fSJohnny Huang 	int i;
120469d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
120569d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
120669d5fd8fSJohnny Huang 	int bit, pbit, kbit;
120769d5fd8fSJohnny Huang 	int fail = 0;
1208a6af4a17SJohnny Huang 	int skip = -1;
120966f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
121069d5fd8fSJohnny Huang 
121169d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
121269d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
121369d5fd8fSJohnny Huang 		if (i < 32) {
121469d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
121569d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
121669d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
121769d5fd8fSJohnny Huang 		} else {
121869d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
121969d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
122069d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
122169d5fd8fSJohnny Huang 		}
122269d5fd8fSJohnny Huang 
122369d5fd8fSJohnny Huang 		if (kbit == 1) {
122469d5fd8fSJohnny Huang 			continue;
122569d5fd8fSJohnny Huang 		} else {
1226a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
122769d5fd8fSJohnny Huang 		}
122869d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
122969d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1230a6af4a17SJohnny Huang 			if (skip == -1)
1231a6af4a17SJohnny Huang 				skip = 1;
123269d5fd8fSJohnny Huang 			continue;
1233a6af4a17SJohnny Huang 		} else {
1234a6af4a17SJohnny Huang 			skip = 0;
123569d5fd8fSJohnny Huang 		}
123669d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
123769d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
123869d5fd8fSJohnny Huang 			fail = 1;
123969d5fd8fSJohnny Huang 			continue;
124069d5fd8fSJohnny Huang 		}
124169d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1242a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
124369d5fd8fSJohnny Huang 			fail = 1;
124469d5fd8fSJohnny Huang 			continue;
124569d5fd8fSJohnny Huang 		}
124669d5fd8fSJohnny Huang 		if (pbit == 1) {
124769d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
124869d5fd8fSJohnny Huang 		}
1249a6af4a17SJohnny 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);
125069d5fd8fSJohnny Huang 	}
125169d5fd8fSJohnny Huang 	if (fail == 1)
1252a6af4a17SJohnny Huang 		return OTP_FAILURE;
1253a6af4a17SJohnny Huang 	else if (skip == 1)
1254a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
12557e22f42dSJohnny Huang 
12567e22f42dSJohnny Huang 	return 0;
125769d5fd8fSJohnny Huang }
125869d5fd8fSJohnny Huang 
12592a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
126069d5fd8fSJohnny Huang {
126169d5fd8fSJohnny Huang 	int i, j;
126266f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
126369d5fd8fSJohnny Huang 
12642a856b9aSJohnny Huang 	if (start < 0 || start > 64)
12652a856b9aSJohnny Huang 		return OTP_USAGE;
12662a856b9aSJohnny Huang 
12672a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
12682a856b9aSJohnny Huang 		return OTP_USAGE;
12692a856b9aSJohnny Huang 
127069d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
127169d5fd8fSJohnny Huang 
1272a8bd6d8cSJohnny Huang 	printf("BIT(hex)  Value  Avaliable        Status\n");
1273a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1274737ed20bSJohnny Huang 
1275cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
1276a8bd6d8cSJohnny Huang 		printf("%-10X", i);
1277737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1278737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1279737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1280737ed20bSJohnny Huang 		printf("   ");
128169d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1282737ed20bSJohnny Huang 			printf("protected and not writable");
128369d5fd8fSJohnny Huang 		} else {
1284737ed20bSJohnny Huang 			printf("not protected ");
128569d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1286737ed20bSJohnny Huang 				printf("and no remaining times to write.");
128769d5fd8fSJohnny Huang 			} else {
1288737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
128969d5fd8fSJohnny Huang 			}
129069d5fd8fSJohnny Huang 		}
1291737ed20bSJohnny Huang 		printf("\n");
129269d5fd8fSJohnny Huang 	}
12932a856b9aSJohnny Huang 
12942a856b9aSJohnny Huang 	return OTP_SUCCESS;
129569d5fd8fSJohnny Huang }
129669d5fd8fSJohnny Huang 
129769d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
129869d5fd8fSJohnny Huang {
129969d5fd8fSJohnny Huang 	int i, j;
130069d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
130169d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
130269d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
130369d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
130469d5fd8fSJohnny Huang 	int fail = 0;
13057e22f42dSJohnny Huang 	int pass = 0;
13067e22f42dSJohnny Huang 	int soak = 0;
130766f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
130869d5fd8fSJohnny Huang 
13097f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
131069d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
131169d5fd8fSJohnny Huang 
13127f795e57SJohnny Huang 	printf("Check writable...\n");
13137f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
13147f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
13157f795e57SJohnny Huang 		return OTP_FAILURE;
13167f795e57SJohnny Huang 	}
13177e22f42dSJohnny Huang 
13187f795e57SJohnny Huang 	otp_soak(0);
131969d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
13204c1c9b35SJohnny Huang 		printProgress(i + 1, 64, "");
132169d5fd8fSJohnny Huang 		prog_address = 0x800;
132269d5fd8fSJohnny Huang 		if (i < 32) {
132369d5fd8fSJohnny Huang 			offset = i;
132469d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
132569d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
132669d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
132769d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
132869d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
132969d5fd8fSJohnny Huang 
133069d5fd8fSJohnny Huang 		} else {
133169d5fd8fSJohnny Huang 			offset = (i - 32);
133269d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
133369d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
133469d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
133569d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
133669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
133769d5fd8fSJohnny Huang 		}
133869d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
133969d5fd8fSJohnny Huang 
134069d5fd8fSJohnny Huang 		if (kbit == 1) {
134169d5fd8fSJohnny Huang 			continue;
134269d5fd8fSJohnny Huang 		}
134369d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
134469d5fd8fSJohnny Huang 			continue;
134569d5fd8fSJohnny Huang 		}
134669d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
134769d5fd8fSJohnny Huang 			fail = 1;
134869d5fd8fSJohnny Huang 			continue;
134969d5fd8fSJohnny Huang 		}
135069d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
135169d5fd8fSJohnny Huang 			fail = 1;
135269d5fd8fSJohnny Huang 			continue;
135369d5fd8fSJohnny Huang 		}
13547e22f42dSJohnny Huang 
13557e22f42dSJohnny Huang 		if (soak) {
135669d5fd8fSJohnny Huang 			soak = 0;
13577e22f42dSJohnny Huang 			otp_soak(0);
13587e22f42dSJohnny Huang 		}
13597e22f42dSJohnny Huang 
13607e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
13617e22f42dSJohnny Huang 
13627e22f42dSJohnny Huang 		pass = 0;
13637e22f42dSJohnny Huang 
136469d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1365a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
136669d5fd8fSJohnny Huang 				pass = 1;
136769d5fd8fSJohnny Huang 				break;
136869d5fd8fSJohnny Huang 			}
13697e22f42dSJohnny Huang 			if (soak == 0) {
137069d5fd8fSJohnny Huang 				soak = 1;
13717e22f42dSJohnny Huang 				otp_soak(1);
13724b65a65dSJohnny Huang 			}
137369d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
137469d5fd8fSJohnny Huang 		}
137569d5fd8fSJohnny Huang 		if (!pass)
13762a856b9aSJohnny Huang 			return OTP_FAILURE;
137769d5fd8fSJohnny Huang 
137869d5fd8fSJohnny Huang 		if (pbit == 0)
137969d5fd8fSJohnny Huang 			continue;
138069d5fd8fSJohnny Huang 		prog_address = 0x800;
138169d5fd8fSJohnny Huang 		if (i < 32)
138269d5fd8fSJohnny Huang 			prog_address |= 0x60c;
138369d5fd8fSJohnny Huang 		else
138469d5fd8fSJohnny Huang 			prog_address |= 0x60e;
138569d5fd8fSJohnny Huang 
13867e22f42dSJohnny Huang 
13877e22f42dSJohnny Huang 		if (soak) {
13887e22f42dSJohnny Huang 			soak = 0;
13897e22f42dSJohnny Huang 			otp_soak(0);
13907e22f42dSJohnny Huang 		}
13917e22f42dSJohnny Huang 
13927e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
13937e22f42dSJohnny Huang 
13947e22f42dSJohnny Huang 		pass = 0;
13957e22f42dSJohnny Huang 
139669d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
13977e22f42dSJohnny Huang 
1398a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
139969d5fd8fSJohnny Huang 				pass = 1;
140069d5fd8fSJohnny Huang 				break;
140169d5fd8fSJohnny Huang 			}
14027e22f42dSJohnny Huang 			if (soak == 0) {
140369d5fd8fSJohnny Huang 				soak = 1;
14047e22f42dSJohnny Huang 				otp_soak(1);
140569d5fd8fSJohnny Huang 			}
140669d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
140769d5fd8fSJohnny Huang 		}
140869d5fd8fSJohnny Huang 		if (!pass)
14092a856b9aSJohnny Huang 			return OTP_FAILURE;
141069d5fd8fSJohnny Huang 
141169d5fd8fSJohnny Huang 	}
141269d5fd8fSJohnny Huang 	if (fail == 1)
14132a856b9aSJohnny Huang 		return OTP_FAILURE;
141469d5fd8fSJohnny Huang 	else
14152a856b9aSJohnny Huang 		return OTP_SUCCESS;
141669d5fd8fSJohnny Huang 
141769d5fd8fSJohnny Huang }
141869d5fd8fSJohnny Huang 
1419cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak)
1420cd1610b4SJohnny Huang {
1421cd1610b4SJohnny Huang 	int prog_bit;
1422cd1610b4SJohnny Huang 
14237e22f42dSJohnny Huang 	otp_soak(soak);
14247e22f42dSJohnny Huang 
1425cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1426cd1610b4SJohnny Huang 		if (value)
1427cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1428cd1610b4SJohnny Huang 		else
1429cd1610b4SJohnny Huang 			return;
1430cd1610b4SJohnny Huang 	} else {
1431cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1432cd1610b4SJohnny Huang 		if (!value)
1433cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1434cd1610b4SJohnny Huang 		else
1435cd1610b4SJohnny Huang 			return;
1436cd1610b4SJohnny Huang 	}
1437cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1438cd1610b4SJohnny Huang }
1439cd1610b4SJohnny Huang 
1440d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
14414c1c9b35SJohnny Huang {
14424c1c9b35SJohnny Huang 	int i, k;
14434c1c9b35SJohnny Huang 	int pass;
1444d90825e2SJohnny Huang 	int soak = 0;
14454c1c9b35SJohnny Huang 	uint32_t prog_address;
1446d90825e2SJohnny Huang 	uint32_t data[2048];
14474c1c9b35SJohnny Huang 	uint32_t compare[2];
1448d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
14494c1c9b35SJohnny Huang 
1450d90825e2SJohnny Huang 	uint32_t data0_masked;
1451d90825e2SJohnny Huang 	uint32_t data1_masked;
1452d90825e2SJohnny Huang 	uint32_t buf0_masked;
1453d90825e2SJohnny Huang 	uint32_t buf1_masked;
14544c1c9b35SJohnny Huang 
14554c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
14564c1c9b35SJohnny Huang 
1457d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1458d90825e2SJohnny Huang 	for (i = 0; i < 2048 ; i += 2) {
1459d90825e2SJohnny Huang 		printProgress(i + 2, 2048, "");
1460d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
14614c1c9b35SJohnny Huang 	}
1462d90825e2SJohnny Huang 
14634c1c9b35SJohnny Huang 
14644c1c9b35SJohnny Huang 	printf("Check writable...\n");
1465d90825e2SJohnny Huang 	for (i = 0; i < 2048; i++) {
1466d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1467d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1468d90825e2SJohnny Huang 		if (data0_masked == buf0_masked)
14694c1c9b35SJohnny Huang 			continue;
1470d90825e2SJohnny Huang 		if (i % 2 == 0) {
1471d90825e2SJohnny Huang 			if ((data0_masked | buf0_masked) == buf0_masked) {
14724c1c9b35SJohnny Huang 				continue;
14734c1c9b35SJohnny Huang 			} else {
14744c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1475d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
14764c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1477d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
14782a856b9aSJohnny Huang 				return OTP_FAILURE;
147969d5fd8fSJohnny Huang 			}
1480d90825e2SJohnny Huang 		} else {
1481d90825e2SJohnny Huang 			if ((data0_masked & buf0_masked) == buf0_masked) {
1482d90825e2SJohnny Huang 				continue;
1483d90825e2SJohnny Huang 			} else {
1484d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1485d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1486d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1487d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
14882a856b9aSJohnny Huang 				return OTP_FAILURE;
1489d90825e2SJohnny Huang 			}
1490d90825e2SJohnny Huang 		}
1491d90825e2SJohnny Huang 	}
149269d5fd8fSJohnny Huang 
1493d90825e2SJohnny Huang 	printf("Start Programing...\n");
1494d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1495d90825e2SJohnny Huang 
1496d90825e2SJohnny Huang 	for (i = 0; i < 2048; i += 2) {
1497d90825e2SJohnny Huang 		prog_address = i;
1498d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1499d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1500d90825e2SJohnny Huang 		data1_masked = data[i + 1]  & ~buf_keep[i + 1];
1501d90825e2SJohnny Huang 		buf1_masked  = buf[i + 1] & ~buf_keep[i + 1];
1502d90825e2SJohnny Huang 		if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) {
1503d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1504d90825e2SJohnny Huang 			continue;
1505d90825e2SJohnny Huang 		}
1506d90825e2SJohnny Huang 		if (soak) {
1507d90825e2SJohnny Huang 			soak = 0;
1508d90825e2SJohnny Huang 			otp_soak(0);
1509d90825e2SJohnny Huang 		}
1510d90825e2SJohnny Huang 		if (data1_masked == buf1_masked) {
1511d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1512d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1513d90825e2SJohnny Huang 		} else if (data0_masked == buf0_masked) {
1514d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1515d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1516d90825e2SJohnny Huang 		} else {
1517d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1518d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1519d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1520d90825e2SJohnny Huang 		}
1521d90825e2SJohnny Huang 
1522d90825e2SJohnny Huang 		pass = 0;
1523d90825e2SJohnny Huang 		for (k = 0; k < RETRY; k++) {
1524d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) {
1525d90825e2SJohnny Huang 				if (soak == 0) {
1526d90825e2SJohnny Huang 					soak = 1;
1527d90825e2SJohnny Huang 					otp_soak(1);
1528d90825e2SJohnny Huang 				}
1529d90825e2SJohnny Huang 				if (compare[0] != 0) {
1530d90825e2SJohnny Huang 					otp_prog_dw(compare[0], buf_keep[i], prog_address);
1531d90825e2SJohnny Huang 				}
1532d90825e2SJohnny Huang 				if (compare[1] != ~0) {
1533d90825e2SJohnny Huang 					otp_prog_dw(compare[1], buf_keep[i], prog_address + 1);
1534d90825e2SJohnny Huang 				}
1535d90825e2SJohnny Huang 			} else {
1536d90825e2SJohnny Huang 				pass = 1;
1537d90825e2SJohnny Huang 				break;
1538d90825e2SJohnny Huang 			}
1539d90825e2SJohnny Huang 		}
1540d90825e2SJohnny Huang 
1541d90825e2SJohnny Huang 		if (!pass)
15422a856b9aSJohnny Huang 			return OTP_FAILURE;
1543d90825e2SJohnny Huang 	}
15442a856b9aSJohnny Huang 	return OTP_SUCCESS;
1545d90825e2SJohnny Huang 
1546d90825e2SJohnny Huang }
1547d90825e2SJohnny Huang 
1548d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
154969d5fd8fSJohnny Huang {
155069d5fd8fSJohnny Huang 	int ret;
1551d90825e2SJohnny Huang 	int mode;
155269d5fd8fSJohnny Huang 	uint32_t *buf;
1553d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1554d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1555d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
155669d5fd8fSJohnny Huang 
1557d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
155869d5fd8fSJohnny Huang 	if (!buf) {
155969d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
15602a856b9aSJohnny Huang 		return OTP_FAILURE;
156169d5fd8fSJohnny Huang 	}
1562d90825e2SJohnny Huang 
1563d90825e2SJohnny Huang 	if (((buf[0] >> 29) & 0x7) == 0x7) {
1564d90825e2SJohnny Huang 		mode = OTP_REGION_ALL;
1565d90825e2SJohnny Huang 		conf_region = &buf[1];
1566d90825e2SJohnny Huang 		strap_region = &buf[25];
1567d90825e2SJohnny Huang 		data_region = &buf[31];
1568d90825e2SJohnny Huang 	} else {
1569d90825e2SJohnny Huang 		if (buf[0] & BIT(29)) {
1570d90825e2SJohnny Huang 			mode = OTP_REGION_DATA;
1571d90825e2SJohnny Huang 			data_region = &buf[31];
1572d90825e2SJohnny Huang 		}
1573d90825e2SJohnny Huang 		if (buf[0] & BIT(30)) {
1574d90825e2SJohnny Huang 			mode = OTP_REGION_CONF;
1575d90825e2SJohnny Huang 			strap_region = &buf[25];
1576d90825e2SJohnny Huang 		}
1577d90825e2SJohnny Huang 		if (buf[0] & BIT(31)) {
1578d90825e2SJohnny Huang 			mode = OTP_REGION_STRAP;
1579d90825e2SJohnny Huang 			conf_region = &buf[1];
1580d90825e2SJohnny Huang 		}
1581d90825e2SJohnny Huang 	}
158269d5fd8fSJohnny Huang 	if (!nconfirm) {
1583a6d0d645SJohnny Huang 		if (mode == OTP_REGION_CONF) {
15847f795e57SJohnny Huang 			printf("\nOTP configuration region :\n");
1585*b458cd62SJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
158669d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
15872a856b9aSJohnny Huang 				return OTP_FAILURE;
158869d5fd8fSJohnny Huang 			}
1589a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_DATA) {
15907f795e57SJohnny Huang 			printf("\nOTP data region :\n");
15917f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
159269d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
15932a856b9aSJohnny Huang 				return OTP_FAILURE;
159469d5fd8fSJohnny Huang 			}
1595a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_STRAP) {
15967f795e57SJohnny Huang 			printf("\nOTP strap region :\n");
1597*b458cd62SJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
159869d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
15992a856b9aSJohnny Huang 				return OTP_FAILURE;
160069d5fd8fSJohnny Huang 			}
1601a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_ALL) {
16027f795e57SJohnny Huang 			printf("\nOTP configuration region :\n");
1603*b458cd62SJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
160469d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
16052a856b9aSJohnny Huang 				return OTP_FAILURE;
160669d5fd8fSJohnny Huang 			}
16077f795e57SJohnny Huang 			printf("\nOTP strap region :\n");
1608*b458cd62SJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
160969d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
16102a856b9aSJohnny Huang 				return OTP_FAILURE;
161169d5fd8fSJohnny Huang 			}
16127f795e57SJohnny Huang 			printf("\nOTP data region :\n");
16137f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
161469d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16152a856b9aSJohnny Huang 				return OTP_FAILURE;
161669d5fd8fSJohnny Huang 			}
161769d5fd8fSJohnny Huang 		}
161869d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
161969d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
162069d5fd8fSJohnny Huang 			printf(" Aborting\n");
16212a856b9aSJohnny Huang 			return OTP_FAILURE;
162269d5fd8fSJohnny Huang 		}
162369d5fd8fSJohnny Huang 	}
1624a6d0d645SJohnny Huang 	if (mode == OTP_REGION_CONF) {
1625d90825e2SJohnny Huang 		return otp_prog_conf(conf_region);
1626a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_STRAP) {
1627d90825e2SJohnny Huang 		return otp_prog_strap(strap_region);
1628a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_DATA) {
1629d90825e2SJohnny Huang 		return otp_prog_data(data_region);
1630a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_ALL) {
163169d5fd8fSJohnny Huang 		printf("programing data region ... ");
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 		}
163969d5fd8fSJohnny Huang 		printf("programing strap region ... ");
1640d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
16412a856b9aSJohnny Huang 		if (ret != 0) {
164269d5fd8fSJohnny Huang 			printf("Error\n");
164369d5fd8fSJohnny Huang 			return ret;
164469d5fd8fSJohnny Huang 		} else {
164569d5fd8fSJohnny Huang 			printf("Done\n");
164669d5fd8fSJohnny Huang 		}
164769d5fd8fSJohnny Huang 		printf("programing configuration region ... ");
1648d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
16492a856b9aSJohnny Huang 		if (ret != 0) {
165069d5fd8fSJohnny Huang 			printf("Error\n");
165169d5fd8fSJohnny Huang 			return ret;
165269d5fd8fSJohnny Huang 		}
165369d5fd8fSJohnny Huang 		printf("Done\n");
16542a856b9aSJohnny Huang 		return OTP_SUCCESS;
165569d5fd8fSJohnny Huang 	}
1656cd1610b4SJohnny Huang 
16572a856b9aSJohnny Huang 	return OTP_USAGE;
16582a856b9aSJohnny Huang }
16592a856b9aSJohnny Huang 
16602a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1661cd1610b4SJohnny Huang {
1662a6af4a17SJohnny Huang 	uint32_t read[2];
1663cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1664d90825e2SJohnny Huang 	uint32_t prog_address = 0;
166566f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1666cd1610b4SJohnny Huang 	int otp_bit;
1667cd1610b4SJohnny Huang 	int i;
1668cd1610b4SJohnny Huang 	int pass;
1669a6af4a17SJohnny Huang 	int ret;
1670cd1610b4SJohnny Huang 
1671cd1610b4SJohnny Huang 	switch (mode) {
1672a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1673a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1674cd1610b4SJohnny Huang 		prog_address = 0x800;
1675cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1676cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1677a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1678cd1610b4SJohnny Huang 		if (otp_bit == value) {
1679a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1680cd1610b4SJohnny Huang 			printf("No need to program\n");
16812a856b9aSJohnny Huang 			return OTP_SUCCESS;
1682cd1610b4SJohnny Huang 		}
1683cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1684a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1685cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
16862a856b9aSJohnny Huang 			return OTP_FAILURE;
1687cd1610b4SJohnny Huang 		}
1688a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1689cd1610b4SJohnny Huang 		break;
1690a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1691cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1692cd1610b4SJohnny Huang 
1693cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1694a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1695a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1696cd1610b4SJohnny Huang 		} else {
1697a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1698a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1699cd1610b4SJohnny Huang 		}
1700cd1610b4SJohnny Huang 		if (otp_bit == value) {
1701a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1702cd1610b4SJohnny Huang 			printf("No need to program\n");
17032a856b9aSJohnny Huang 			return OTP_SUCCESS;
1704cd1610b4SJohnny Huang 		}
1705cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1706a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1707cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
17082a856b9aSJohnny Huang 			return OTP_FAILURE;
1709cd1610b4SJohnny Huang 		}
1710a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1711cd1610b4SJohnny Huang 		break;
1712a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1713cd1610b4SJohnny Huang 		otp_strp_status(otpstrap);
1714cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1715cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1716cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
1717cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1718cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
1719cd1610b4SJohnny Huang 			strap_buf[5] = 0;
17202a856b9aSJohnny Huang 			// if (protect)
17212a856b9aSJohnny Huang 			// 	strap_buf[4] = BIT(bit_offset);
17222a856b9aSJohnny Huang 			// else
17232a856b9aSJohnny Huang 			// 	strap_buf[4] = 0;
1724cd1610b4SJohnny Huang 		} else {
1725cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1726cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1727cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1728cd1610b4SJohnny Huang 			strap_buf[4] = 0;
17292a856b9aSJohnny Huang 			// if (protect)
17302a856b9aSJohnny Huang 			// 	strap_buf[5] = BIT(bit_offset - 32);
17312a856b9aSJohnny Huang 			// else
17322a856b9aSJohnny Huang 			// 	strap_buf[5] = 0;
1733cd1610b4SJohnny Huang 		}
173476d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1735a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
17362a856b9aSJohnny Huang 			return OTP_FAILURE;
1737a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1738a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1739a6af4a17SJohnny Huang 
1740cd1610b4SJohnny Huang 		break;
1741cd1610b4SJohnny Huang 	}
1742cd1610b4SJohnny Huang 
1743cd1610b4SJohnny Huang 	if (!nconfirm) {
1744cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1745cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1746cd1610b4SJohnny Huang 			printf(" Aborting\n");
17472a856b9aSJohnny Huang 			return OTP_FAILURE;
1748cd1610b4SJohnny Huang 		}
1749cd1610b4SJohnny Huang 	}
1750cd1610b4SJohnny Huang 
1751cd1610b4SJohnny Huang 	switch (mode) {
1752a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1753cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
1754a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1755a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1756cd1610b4SJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset, 0);
1757cd1610b4SJohnny Huang 		pass = -1;
1758cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
1759a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
1760cd1610b4SJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset, 1);
1761cd1610b4SJohnny Huang 			} else {
1762cd1610b4SJohnny Huang 				pass = 0;
1763cd1610b4SJohnny Huang 				break;
1764cd1610b4SJohnny Huang 			}
1765cd1610b4SJohnny Huang 		}
17662a856b9aSJohnny Huang 		if (pass == 0)
17672a856b9aSJohnny Huang 			return OTP_SUCCESS;
1768cd1610b4SJohnny Huang 	}
1769cd1610b4SJohnny Huang 
17702a856b9aSJohnny Huang 	return OTP_USAGE;
1771cd1610b4SJohnny Huang }
1772cd1610b4SJohnny Huang 
17732a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
177469d5fd8fSJohnny Huang {
17752a856b9aSJohnny Huang 	uint32_t offset, count;
17762a856b9aSJohnny Huang 	int ret;
177769d5fd8fSJohnny Huang 
17782a856b9aSJohnny Huang 	if (argc == 4) {
17792a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17802a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
17812a856b9aSJohnny Huang 	} else if (argc == 3) {
17822a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17832a856b9aSJohnny Huang 		count = 1;
17842a856b9aSJohnny Huang 	} else {
178569d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
178669d5fd8fSJohnny Huang 	}
178769d5fd8fSJohnny Huang 
178869d5fd8fSJohnny Huang 
17892a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
179069d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17912a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
17922a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
17932a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17942a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
17952a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
17962a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17972a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
17982a856b9aSJohnny Huang 	} else {
17992a856b9aSJohnny Huang 		return CMD_RET_USAGE;
180069d5fd8fSJohnny Huang 	}
180169d5fd8fSJohnny Huang 
18022a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18032a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18042a856b9aSJohnny Huang 	else
18052a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18062a856b9aSJohnny Huang 
18072a856b9aSJohnny Huang }
18082a856b9aSJohnny Huang 
18092a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18102a856b9aSJohnny Huang {
18112a856b9aSJohnny Huang 	phys_addr_t addr;
18122a856b9aSJohnny Huang 	uint32_t byte_size;
18132a856b9aSJohnny Huang 	int ret;
18142a856b9aSJohnny Huang 
18152a856b9aSJohnny Huang 	if (argc == 4) {
18162a856b9aSJohnny Huang 		if (strcmp(argv[1], "f"))
18172a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18182a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
18192a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
182069d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18212a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
18222a856b9aSJohnny Huang 	} else if (argc == 3) {
18232a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
18242a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
18252a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18262a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
18272a856b9aSJohnny Huang 	} else {
18282a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18292a856b9aSJohnny Huang 	}
18302a856b9aSJohnny Huang 
18312a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18322a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18332a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18342a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18352a856b9aSJohnny Huang 	else
18362a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18372a856b9aSJohnny Huang }
18382a856b9aSJohnny Huang 
18392a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18402a856b9aSJohnny Huang {
18412a856b9aSJohnny Huang 	int mode = 0;
18422a856b9aSJohnny Huang 	int nconfirm = 0;
18432a856b9aSJohnny Huang 	int otp_addr = 0;
18442a856b9aSJohnny Huang 	int bit_offset;
18452a856b9aSJohnny Huang 	int value;
18462a856b9aSJohnny Huang 	int ret;
18472a856b9aSJohnny Huang 
18482a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
18492a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18502a856b9aSJohnny Huang 
18512a856b9aSJohnny Huang 	/* Drop the pb cmd */
18522a856b9aSJohnny Huang 	argc--;
18532a856b9aSJohnny Huang 	argv++;
18542a856b9aSJohnny Huang 
18552a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1856a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
18572a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1858a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
18592a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1860a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1861cd1610b4SJohnny Huang 	else
18622a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18632a856b9aSJohnny Huang 
18642a856b9aSJohnny Huang 	/* Drop the region cmd */
18652a856b9aSJohnny Huang 	argc--;
18662a856b9aSJohnny Huang 	argv++;
18672a856b9aSJohnny Huang 
18682a856b9aSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1869cd1610b4SJohnny Huang 		nconfirm = 1;
18702a856b9aSJohnny Huang 		/* Drop the force option */
18712a856b9aSJohnny Huang 		argc--;
18722a856b9aSJohnny Huang 		argv++;
18732a856b9aSJohnny Huang 	}
1874cd1610b4SJohnny Huang 
1875a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
18762a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
18772a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
1878cd1610b4SJohnny Huang 		if (bit_offset >= 64)
18792a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1880cd1610b4SJohnny Huang 	} else {
18812a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
18822a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
18832a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
1884cd1610b4SJohnny Huang 		if (bit_offset >= 32)
18852a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1886cd1610b4SJohnny Huang 	}
1887cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
18882a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1889cd1610b4SJohnny Huang 
1890cd1610b4SJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
18912a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
18922a856b9aSJohnny Huang 
18932a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18942a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18952a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18962a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18972a856b9aSJohnny Huang 	else
18982a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18992a856b9aSJohnny Huang }
19002a856b9aSJohnny Huang 
19012a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19022a856b9aSJohnny Huang {
19032a856b9aSJohnny Huang 	phys_addr_t addr;
19042a856b9aSJohnny Huang 	int otp_addr = 0;
19052a856b9aSJohnny Huang 
19062a856b9aSJohnny Huang 	if (argc != 3)
19072a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19082a856b9aSJohnny Huang 
190969d5fd8fSJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
19102a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
19112a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
19122a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
191369d5fd8fSJohnny Huang 		printf("Compare pass\n");
19142a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
191569d5fd8fSJohnny Huang 	} else {
191669d5fd8fSJohnny Huang 		printf("Compare fail\n");
19172a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
191869d5fd8fSJohnny Huang 	}
191969d5fd8fSJohnny Huang }
192069d5fd8fSJohnny Huang 
192166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
192266f2f8e5SJohnny Huang {
1923a8bd6d8cSJohnny Huang 	int mode = 0;
1924a8bd6d8cSJohnny Huang 	int view = 0;
1925a8bd6d8cSJohnny Huang 
1926a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
192766f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
192866f2f8e5SJohnny Huang 
1929a8bd6d8cSJohnny Huang 	/* Drop the info cmd */
1930a8bd6d8cSJohnny Huang 	argc--;
1931a8bd6d8cSJohnny Huang 	argv++;
193266f2f8e5SJohnny Huang 
1933a8bd6d8cSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1934a8bd6d8cSJohnny Huang 		mode = OTP_REGION_CONF;
1935a8bd6d8cSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1936a8bd6d8cSJohnny Huang 		mode = OTP_REGION_STRAP;
1937a8bd6d8cSJohnny Huang 	else
1938a8bd6d8cSJohnny Huang 		return CMD_RET_USAGE;
1939a8bd6d8cSJohnny Huang 
1940a8bd6d8cSJohnny Huang 	/* Drop the region cmd */
1941a8bd6d8cSJohnny Huang 	argc--;
1942a8bd6d8cSJohnny Huang 	argv++;
1943a8bd6d8cSJohnny Huang 
1944a8bd6d8cSJohnny Huang 	if (!strcmp(argv[0], "v")) {
1945a8bd6d8cSJohnny Huang 		view = 1;
1946a8bd6d8cSJohnny Huang 		/* Drop the view option */
1947a8bd6d8cSJohnny Huang 		argc--;
1948a8bd6d8cSJohnny Huang 		argv++;
1949a8bd6d8cSJohnny Huang 	}
1950a8bd6d8cSJohnny Huang 
1951a8bd6d8cSJohnny Huang 	if (mode == OTP_REGION_CONF) {
195266f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
1953*b458cd62SJohnny Huang 		otp_print_conf_info(view);
1954a8bd6d8cSJohnny Huang 	} else if (mode == OTP_REGION_STRAP) {
195566f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
1956*b458cd62SJohnny Huang 		otp_print_strap_info(view);
195766f2f8e5SJohnny Huang 	} else {
195866f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
195966f2f8e5SJohnny Huang 	}
196066f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
196166f2f8e5SJohnny Huang }
196266f2f8e5SJohnny Huang 
1963737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1964737ed20bSJohnny Huang {
1965737ed20bSJohnny Huang 	int input;
1966737ed20bSJohnny Huang 	int bit_offset;
1967737ed20bSJohnny Huang 	int prog_address;
1968737ed20bSJohnny Huang 	int pass;
1969737ed20bSJohnny Huang 	int i;
1970737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1971737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1972737ed20bSJohnny Huang 
1973737ed20bSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1974737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1975737ed20bSJohnny Huang 	} else {
1976737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1977737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
1978737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1979737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1980737ed20bSJohnny Huang 			printf(" Aborting\n");
1981737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
1982737ed20bSJohnny Huang 		}
1983737ed20bSJohnny Huang 	}
1984737ed20bSJohnny Huang 
1985737ed20bSJohnny Huang 	prog_address = 0x800;
1986737ed20bSJohnny Huang 	if (input < 32) {
1987737ed20bSJohnny Huang 		bit_offset = input;
1988737ed20bSJohnny Huang 		prog_address |= 0x60c;
1989737ed20bSJohnny Huang 	} else if (input < 64) {
1990737ed20bSJohnny Huang 		bit_offset = input - 32;
1991737ed20bSJohnny Huang 		prog_address |= 0x60e;
1992737ed20bSJohnny Huang 	} else {
1993737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1994737ed20bSJohnny Huang 	}
1995737ed20bSJohnny Huang 
1996737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
1997737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
1998737ed20bSJohnny Huang 	}
1999737ed20bSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset, 0);
2000737ed20bSJohnny Huang 	pass = -1;
2001737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2002737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2003737ed20bSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset, 1);
2004737ed20bSJohnny Huang 		} else {
2005737ed20bSJohnny Huang 			pass = 0;
2006737ed20bSJohnny Huang 			break;
2007737ed20bSJohnny Huang 		}
2008737ed20bSJohnny Huang 	}
2009737ed20bSJohnny Huang 	if (pass == 0) {
2010737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2011737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2012737ed20bSJohnny Huang 	}
2013737ed20bSJohnny Huang 
2014737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2015737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2016737ed20bSJohnny Huang 
2017737ed20bSJohnny Huang }
20182a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
20192a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2020a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
20212a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
20222a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2023737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
20242a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
20252a856b9aSJohnny Huang };
20262a856b9aSJohnny Huang 
20272a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20282a856b9aSJohnny Huang {
20292a856b9aSJohnny Huang 	cmd_tbl_t *cp;
20302a856b9aSJohnny Huang 
20312a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
20322a856b9aSJohnny Huang 
2033737ed20bSJohnny Huang 	/* Drop the otp command */
20342a856b9aSJohnny Huang 	argc--;
20352a856b9aSJohnny Huang 	argv++;
20362a856b9aSJohnny Huang 
20372a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
20382a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20392a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
20402a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20412a856b9aSJohnny Huang 
20422a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
204369d5fd8fSJohnny Huang }
204469d5fd8fSJohnny Huang 
204569d5fd8fSJohnny Huang U_BOOT_CMD(
204669d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
204769d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
20482a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
20492a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
2050a8bd6d8cSJohnny Huang 	"otp info conf|strap [v]\n"
2051d90825e2SJohnny Huang 	"otp prog [f] <addr> <byte_size>\n"
2052cd1610b4SJohnny Huang 	"otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n"
2053737ed20bSJohnny Huang 	"otp pb strap [f] <bit_offset> <value>\n"
2054737ed20bSJohnny Huang 	"otp protect [f] <bit_offset>\n"
20552a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
205669d5fd8fSJohnny Huang );
2057