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 /* 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