xref: /rk3399_rockchip-uboot/drivers/misc/misc_otp.c (revision 60bee396ec03ff5bfce10a0f0efd85e5a5783257)
1 // SPDX-License-Identifier:     GPL-2.0+
2 /*
3  * Copyright (C) 2020 Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <dm/uclass.h>
9 #include <misc.h>
10 
11 struct udevice *misc_otp_get_device(u32 capability)
12 {
13 	return misc_get_device_by_capability(capability);
14 }
15 
16 int misc_otp_read(struct udevice *dev, int offset, void *buf, int size)
17 {
18 	return misc_read(dev, offset, buf, size);
19 }
20 
21 int misc_otp_write(struct udevice *dev, int offset, const void *buf, int size)
22 {
23 	return misc_write(dev, offset, (void *)buf, size);
24 }
25 
26 int misc_otp_ioctl(struct udevice *dev, unsigned long request, void *buf)
27 {
28 	return misc_ioctl(dev, request, buf);
29 }
30 
31 int misc_otp_write_verify(struct udevice *dev, int offset, const uint8_t *write_buf, int size)
32 {
33 	uint8_t verify_buf[size];
34 	uint8_t read_buf[size];
35 	int i, written_size = 0, ret = 0;
36 
37 	memset(verify_buf, 0, sizeof(verify_buf));
38 	memset(read_buf, 0, sizeof(read_buf));
39 
40 	ret = misc_otp_read(dev, offset, &read_buf, size);
41 	if (ret) {
42 		printf("OTP: misc_otp_read fail, ret=%d\n", ret);
43 		goto out;
44 	}
45 
46 	for (i = 0; i < size; i++) {
47 		if (read_buf[i] == write_buf[i])
48 			written_size++;
49 		else
50 			break;
51 	}
52 
53 	if (size == written_size) {
54 		printf("OTP: The secure region has been written.\n");
55 		ret = -EIO;
56 		goto out;
57 	}
58 
59 	ret = misc_otp_write(dev, (offset + written_size), &write_buf[written_size],
60 			     (size - written_size));
61 	if (ret) {
62 		printf("OTP: misc_otp_write fail, ret=%d\n", ret);
63 		goto out;
64 	}
65 
66 	ret = misc_otp_read(dev, (offset + written_size), verify_buf, (size - written_size));
67 	if (ret) {
68 		printf("OTP: misc_otp_read(verify) fail, ret=%d\n", ret);
69 		goto out;
70 	}
71 
72 	for (i = 0; i < (size - written_size); i++) {
73 		if ((write_buf[i + written_size] | read_buf[i + written_size]) != verify_buf[i]) {
74 			ret = -EIO;
75 			printf("OTP: Actual value(%u) is different from expected value(%u).\n",
76 			       verify_buf[i], (write_buf[i + written_size] | read_buf[i + written_size]));
77 			goto out;
78 		}
79 	}
80 
81 out:
82 	return ret;
83 }
84