xref: /rk3399_rockchip-uboot/drivers/misc/misc_otp.c (revision b80b67f1b0eddd191aff8a99fe2c41c0666c801a)
16a8fa29eSJason Zhu // SPDX-License-Identifier:     GPL-2.0+
26a8fa29eSJason Zhu /*
36a8fa29eSJason Zhu  * Copyright (C) 2020 Rockchip Electronics Co., Ltd
46a8fa29eSJason Zhu  */
56a8fa29eSJason Zhu 
66a8fa29eSJason Zhu #include <common.h>
76a8fa29eSJason Zhu #include <dm.h>
86a8fa29eSJason Zhu #include <dm/uclass.h>
96a8fa29eSJason Zhu #include <misc.h>
106a8fa29eSJason Zhu 
116a8fa29eSJason Zhu struct udevice *misc_otp_get_device(u32 capability)
126a8fa29eSJason Zhu {
13374c241cSJoseph Chen 	return misc_get_device_by_capability(capability);
146a8fa29eSJason Zhu }
156a8fa29eSJason Zhu 
166a8fa29eSJason Zhu int misc_otp_read(struct udevice *dev, int offset, void *buf, int size)
176a8fa29eSJason Zhu {
186a8fa29eSJason Zhu 	return misc_read(dev, offset, buf, size);
196a8fa29eSJason Zhu }
206a8fa29eSJason Zhu 
216a8fa29eSJason Zhu int misc_otp_write(struct udevice *dev, int offset, const void *buf, int size)
226a8fa29eSJason Zhu {
236a8fa29eSJason Zhu 	return misc_write(dev, offset, (void *)buf, size);
246a8fa29eSJason Zhu }
25368f3065SXuhui Lin 
26368f3065SXuhui Lin int misc_otp_ioctl(struct udevice *dev, unsigned long request, void *buf)
27368f3065SXuhui Lin {
28368f3065SXuhui Lin 	return misc_ioctl(dev, request, buf);
29368f3065SXuhui Lin }
30*b80b67f1SXuhui Lin 
31*b80b67f1SXuhui Lin int misc_otp_write_verify(struct udevice *dev, int offset, const uint8_t *write_buf, int size)
32*b80b67f1SXuhui Lin {
33*b80b67f1SXuhui Lin 	uint8_t verify_buf[size];
34*b80b67f1SXuhui Lin 	uint8_t read_buf[size];
35*b80b67f1SXuhui Lin 	int i, written_size = 0, ret = 0;
36*b80b67f1SXuhui Lin 
37*b80b67f1SXuhui Lin 	memset(verify_buf, 0, sizeof(verify_buf));
38*b80b67f1SXuhui Lin 	memset(read_buf, 0, sizeof(read_buf));
39*b80b67f1SXuhui Lin 
40*b80b67f1SXuhui Lin 	ret = misc_otp_read(dev, offset, &read_buf, size);
41*b80b67f1SXuhui Lin 	if (ret) {
42*b80b67f1SXuhui Lin 		printf("OTP: misc_otp_read fail, ret=%d\n", ret);
43*b80b67f1SXuhui Lin 		goto out;
44*b80b67f1SXuhui Lin 	}
45*b80b67f1SXuhui Lin 
46*b80b67f1SXuhui Lin 	for (i = 0; i < size; i++) {
47*b80b67f1SXuhui Lin 		if (read_buf[i] == write_buf[i])
48*b80b67f1SXuhui Lin 			written_size++;
49*b80b67f1SXuhui Lin 		else
50*b80b67f1SXuhui Lin 			break;
51*b80b67f1SXuhui Lin 	}
52*b80b67f1SXuhui Lin 
53*b80b67f1SXuhui Lin 	if (size == written_size) {
54*b80b67f1SXuhui Lin 		printf("OTP: The secure region has been written.\n");
55*b80b67f1SXuhui Lin 		ret = -EIO;
56*b80b67f1SXuhui Lin 		goto out;
57*b80b67f1SXuhui Lin 	}
58*b80b67f1SXuhui Lin 
59*b80b67f1SXuhui Lin 	ret = misc_otp_write(dev, (offset + written_size), &write_buf[written_size],
60*b80b67f1SXuhui Lin 			     (size - written_size));
61*b80b67f1SXuhui Lin 	if (ret) {
62*b80b67f1SXuhui Lin 		printf("OTP: misc_otp_write fail, ret=%d\n", ret);
63*b80b67f1SXuhui Lin 		goto out;
64*b80b67f1SXuhui Lin 	}
65*b80b67f1SXuhui Lin 
66*b80b67f1SXuhui Lin 	ret = misc_otp_read(dev, (offset + written_size), verify_buf, (size - written_size));
67*b80b67f1SXuhui Lin 	if (ret) {
68*b80b67f1SXuhui Lin 		printf("OTP: misc_otp_read(verify) fail, ret=%d\n", ret);
69*b80b67f1SXuhui Lin 		goto out;
70*b80b67f1SXuhui Lin 	}
71*b80b67f1SXuhui Lin 
72*b80b67f1SXuhui Lin 	for (i = 0; i < (size - written_size); i++) {
73*b80b67f1SXuhui Lin 		if ((write_buf[i + written_size] | read_buf[i + written_size]) != verify_buf[i]) {
74*b80b67f1SXuhui Lin 			ret = -EIO;
75*b80b67f1SXuhui Lin 			printf("OTP: Actual value(%u) is different from expected value(%u).\n",
76*b80b67f1SXuhui Lin 			       verify_buf[i], (write_buf[i + written_size] | read_buf[i + written_size]));
77*b80b67f1SXuhui Lin 			goto out;
78*b80b67f1SXuhui Lin 		}
79*b80b67f1SXuhui Lin 	}
80*b80b67f1SXuhui Lin 
81*b80b67f1SXuhui Lin out:
82*b80b67f1SXuhui Lin 	return ret;
83*b80b67f1SXuhui Lin }
84