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
misc_otp_get_device(u32 capability)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
misc_otp_read(struct udevice * dev,int offset,void * buf,int size)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
misc_otp_write(struct udevice * dev,int offset,const void * buf,int size)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
misc_otp_ioctl(struct udevice * dev,unsigned long request,void * buf)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 }
30b80b67f1SXuhui Lin
misc_otp_write_verify(struct udevice * dev,int offset,const uint8_t * write_buf,int size)31b80b67f1SXuhui Lin int misc_otp_write_verify(struct udevice *dev, int offset, const uint8_t *write_buf, int size)
32b80b67f1SXuhui Lin {
33b80b67f1SXuhui Lin uint8_t verify_buf[size];
34b80b67f1SXuhui Lin uint8_t read_buf[size];
35b80b67f1SXuhui Lin int i, written_size = 0, ret = 0;
36b80b67f1SXuhui Lin
37b80b67f1SXuhui Lin memset(verify_buf, 0, sizeof(verify_buf));
38b80b67f1SXuhui Lin memset(read_buf, 0, sizeof(read_buf));
39b80b67f1SXuhui Lin
40b80b67f1SXuhui Lin ret = misc_otp_read(dev, offset, &read_buf, size);
41b80b67f1SXuhui Lin if (ret) {
42b80b67f1SXuhui Lin printf("OTP: misc_otp_read fail, ret=%d\n", ret);
43b80b67f1SXuhui Lin goto out;
44b80b67f1SXuhui Lin }
45b80b67f1SXuhui Lin
46b80b67f1SXuhui Lin for (i = 0; i < size; i++) {
47*5bb91450SXuhui Lin /* Already 1 value in otp can't be written to 0. */
48*5bb91450SXuhui Lin if (read_buf[i] & ~write_buf[i]) {
49*5bb91450SXuhui Lin printf("OTP: The zone is partly written.\n");
50*5bb91450SXuhui Lin ret = -EACCES;
51*5bb91450SXuhui Lin goto out;
52*5bb91450SXuhui Lin }
53*5bb91450SXuhui Lin if ((read_buf[i] == write_buf[i]) && write_buf[i])
54b80b67f1SXuhui Lin written_size++;
55b80b67f1SXuhui Lin else
56b80b67f1SXuhui Lin break;
57b80b67f1SXuhui Lin }
58b80b67f1SXuhui Lin
59b80b67f1SXuhui Lin if (size == written_size) {
60b80b67f1SXuhui Lin printf("OTP: The secure region has been written.\n");
61b80b67f1SXuhui Lin ret = -EIO;
62b80b67f1SXuhui Lin goto out;
63b80b67f1SXuhui Lin }
64b80b67f1SXuhui Lin
65b80b67f1SXuhui Lin ret = misc_otp_write(dev, (offset + written_size), &write_buf[written_size],
66b80b67f1SXuhui Lin (size - written_size));
67b80b67f1SXuhui Lin if (ret) {
68b80b67f1SXuhui Lin printf("OTP: misc_otp_write fail, ret=%d\n", ret);
69b80b67f1SXuhui Lin goto out;
70b80b67f1SXuhui Lin }
71b80b67f1SXuhui Lin
72b80b67f1SXuhui Lin ret = misc_otp_read(dev, (offset + written_size), verify_buf, (size - written_size));
73b80b67f1SXuhui Lin if (ret) {
74b80b67f1SXuhui Lin printf("OTP: misc_otp_read(verify) fail, ret=%d\n", ret);
75b80b67f1SXuhui Lin goto out;
76b80b67f1SXuhui Lin }
77b80b67f1SXuhui Lin
78b80b67f1SXuhui Lin for (i = 0; i < (size - written_size); i++) {
79b80b67f1SXuhui Lin if ((write_buf[i + written_size] | read_buf[i + written_size]) != verify_buf[i]) {
80b80b67f1SXuhui Lin ret = -EIO;
81b80b67f1SXuhui Lin printf("OTP: Actual value(%u) is different from expected value(%u).\n",
82b80b67f1SXuhui Lin verify_buf[i], (write_buf[i + written_size] | read_buf[i + written_size]));
83b80b67f1SXuhui Lin goto out;
84b80b67f1SXuhui Lin }
85b80b67f1SXuhui Lin }
86b80b67f1SXuhui Lin
87b80b67f1SXuhui Lin out:
88b80b67f1SXuhui Lin return ret;
89b80b67f1SXuhui Lin }
90