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