1 /*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "cc3xx_otp.h"
9
10 #include "cc3xx_reg_defs.h"
11
12 #include <stdint.h>
13 #include <stddef.h>
14 #include <string.h>
15
cc3xx_otp_wait_until_fuse_programming_complete(void)16 void cc3xx_otp_wait_until_fuse_programming_complete(void) {
17 while (! (*CC3XX_REG_NVM_AIB_FUSE_PROG_COMPLETED & 1)) {}
18 }
19
cc3xx_otp_write(uint8_t * otp_addr,size_t size,const uint8_t * buf)20 cc3xx_err_t cc3xx_otp_write(uint8_t *otp_addr, size_t size, const uint8_t *buf)
21 {
22 uint32_t* word_ptr;
23 uint32_t current_word;
24 uint32_t word;
25 uint32_t start_offset;
26 uint8_t in_done = 0;
27 size_t copy_size;
28
29 /* First iterate through and check all values are valid (will not require a
30 * 1 bit to be unset).
31 */
32 for(in_done = 0; in_done < size;) {
33 start_offset = ((uint32_t)otp_addr + in_done) & 0x3;
34 word_ptr = (uint32_t*)(otp_addr + in_done - start_offset);
35
36 current_word = *word_ptr;
37 word = 0;
38
39 copy_size = sizeof(word) - start_offset;
40 if (in_done + copy_size > size) {
41 copy_size = size - in_done;
42 }
43
44 memcpy(((uint8_t*)&word) + start_offset, buf + in_done, copy_size);
45 word |= current_word;
46
47 if (memcmp(((uint8_t*)&word) + start_offset, buf + in_done, copy_size)) {
48 return CC3XX_ERR_INVALID_DATA;
49 }
50
51 in_done += copy_size;
52 }
53
54 /* Then write the OTP */
55 for(in_done = 0; in_done < size;) {
56 start_offset = ((uint32_t)otp_addr + in_done) & 0x3;
57 word_ptr = (uint32_t*)(otp_addr + in_done - start_offset);
58
59 word = *word_ptr;
60
61 copy_size = sizeof(word) - start_offset;
62 if (in_done + copy_size > size) {
63 copy_size = size - in_done;
64 }
65
66 memcpy(((uint8_t*)&word) + start_offset, buf + in_done, copy_size);
67
68 *word_ptr = word;
69 cc3xx_otp_wait_until_fuse_programming_complete();
70
71 in_done += copy_size;
72 }
73
74 return CC3XX_ERR_SUCCESS;
75 }
76
cc3xx_otp_read(const uint8_t * otp_addr,size_t size,uint8_t * buf)77 cc3xx_err_t cc3xx_otp_read(const uint8_t *otp_addr, size_t size, uint8_t *buf)
78 {
79 uint32_t* word_ptr;
80 uint32_t word;
81 uint32_t start_offset;
82 uint8_t out_done;
83 size_t copy_size;
84
85 for(out_done = 0; out_done < size;) {
86 start_offset = ((uint32_t)otp_addr + out_done) & 0x3;
87 word_ptr = (uint32_t*)(otp_addr + out_done - start_offset);
88
89 word = *word_ptr;
90
91 copy_size = sizeof(word) - start_offset;
92 if (out_done + copy_size > size) {
93 copy_size = size - out_done;
94 }
95
96 memcpy(buf + out_done, ((uint8_t*)&word) + start_offset, copy_size);
97 out_done += copy_size;
98 }
99
100 return CC3XX_ERR_SUCCESS;
101 }
102