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