1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2024, Telechips Inc.
4 */
5
6 #include <drivers/tcc_otp.h>
7 #include <io.h>
8 #include <kernel/delay.h>
9 #include <mm/core_memprot.h>
10 #include <otprom.h>
11 #include <string.h>
12
13 #define OTP_CTRL_SIZE U(0x1000)
14 #define OTP_CMD_SIZE U(0x1000)
15
16 #define GENERAL_STATUS U(0x0)
17 #define READ_STATUS U(0x4)
18 #define PROG_STATUS U(0x8)
19 #define OTP_ADDRESS U(0x10)
20 #define OTP_CONTROL U(0x14)
21 #define READ_DATA_PAYLOAD0 U(0x20)
22 #define READ_DATA_PAYLOAD1 U(0x24)
23 #define READ_DATA_PAYLOAD2 U(0x28)
24 #define READ_DATA_PAYLOAD3 U(0x2C)
25 #define READ_ADMIN_INFO0 U(0x30)
26 #define READ_ADMIN_INFO1 U(0x34)
27 #define READ_ADMIN_INFO2 U(0x38)
28 #define READ_ADMIN_INFO3 U(0x3C)
29 #define PROG_DATA_PAYLOAD0 U(0x40)
30 #define PROG_DATA_PAYLOAD1 U(0x44)
31 #define PROG_DATA_PAYLOAD2 U(0x48)
32 #define PROG_DATA_PAYLOAD3 U(0x4C)
33 #define PROG_ADMIN_INFO0 U(0x50)
34 #define PROG_ADMIN_INFO1 U(0x54)
35 #define PROG_ADMIN_INFO2 U(0x58)
36 #define PROG_ADMIN_INFO3 U(0x5C)
37
38 /* GENERAL_STATUS */
39 #define STATUS_READY BIT(0)
40
41 /* READ_STATUS */
42 #define DATA_ERR BIT(3)
43 #define PERMISSION_ERR BIT(0)
44
45 /* OTP_CONTROL Register */
46 #define CTRL_DONE BIT(16)
47 #define CTRL_START BIT(0)
48 #define CTRL_CMD_PROG SHIFT_U32(0xA, 4)
49 #define CTRL_CMD_READ SHIFT_U32(0xF, 4)
50
51 /* Admin Info */
52 #define ADMIN_VALID BIT(0)
53
54 /* Write Protection Control */
55 #define EXT_WP BIT(30)
56 #define SOFT_WP BIT(3)
57
58 #define IS_16BYTE_ALIGNED(x) IS_ALIGNED(x, 16)
59
60 register_phys_mem(MEM_AREA_IO_SEC, OTP_CMD_BASE, OTP_CMD_SIZE);
61
wait_for_ready(vaddr_t reg)62 static void wait_for_ready(vaddr_t reg)
63 {
64 while (!(io_read32(reg + GENERAL_STATUS) & STATUS_READY))
65 udelay(1);
66 }
67
wait_for_done(vaddr_t reg)68 static void wait_for_done(vaddr_t reg)
69 {
70 while (!(io_read32(reg + OTP_CONTROL) & CTRL_DONE))
71 udelay(1);
72 }
73
tcc_otp_read_128(uint32_t offset,uint32_t * buf)74 TEE_Result tcc_otp_read_128(uint32_t offset, uint32_t *buf)
75 {
76 vaddr_t reg = (vaddr_t)phys_to_virt_io(OTP_CMD_BASE, OTP_CMD_SIZE);
77 uint32_t status = 0;
78 uint32_t admin_info0 = 0;
79
80 if (!IS_16BYTE_ALIGNED(offset) || offset >= OTPROM_128_LIMIT ||
81 offset < OTPROM_128_START || !buf || !reg) {
82 EMSG("Invalid parameters");
83 return TEE_ERROR_BAD_PARAMETERS;
84 }
85
86 wait_for_ready(reg);
87 io_write32(reg + OTP_ADDRESS, offset);
88 io_write32(reg + OTP_CONTROL, CTRL_CMD_READ | CTRL_START);
89 wait_for_done(reg);
90
91 admin_info0 = io_read32(reg + READ_ADMIN_INFO0);
92 if (!(admin_info0 & ADMIN_VALID)) {
93 if (!admin_info0 && !io_read32(reg + READ_STATUS))
94 return TEE_ERROR_NO_DATA;
95 return TEE_ERROR_BAD_STATE;
96 }
97
98 status = io_read32(reg + READ_STATUS);
99 if (status & (DATA_ERR | PERMISSION_ERR)) {
100 EMSG("Failed to read OTP (%#"PRIx32")", status);
101 return TEE_ERROR_BAD_STATE;
102 }
103
104 buf[0] = io_read32(reg + READ_DATA_PAYLOAD0);
105 buf[1] = io_read32(reg + READ_DATA_PAYLOAD1);
106 buf[2] = io_read32(reg + READ_DATA_PAYLOAD2);
107 buf[3] = io_read32(reg + READ_DATA_PAYLOAD3);
108
109 return TEE_SUCCESS;
110 }
111
tcc_otp_write_128(uint32_t offset,const uint32_t * buf)112 TEE_Result tcc_otp_write_128(uint32_t offset, const uint32_t *buf)
113 {
114 vaddr_t reg = (vaddr_t)phys_to_virt_io(OTP_CMD_BASE, OTP_CMD_SIZE);
115 vaddr_t ctrl = (vaddr_t)phys_to_virt_io(OTP_CTRL_BASE, OTP_CTRL_SIZE);
116
117 if (!IS_16BYTE_ALIGNED(offset) || offset >= OTPROM_128_LIMIT ||
118 offset < OTPROM_128_START || !buf || !reg) {
119 EMSG("Invalid parameters");
120 return TEE_ERROR_BAD_PARAMETERS;
121 }
122
123 if (io_read32(ctrl) & EXT_WP) {
124 EMSG("EXT_WP is high");
125 return TEE_ERROR_BAD_STATE;
126 }
127
128 wait_for_ready(reg);
129 io_clrbits32(ctrl, SOFT_WP);
130 io_write32(reg + OTP_ADDRESS, offset);
131 io_write32(reg + PROG_DATA_PAYLOAD0, buf[0]);
132 io_write32(reg + PROG_DATA_PAYLOAD1, buf[1]);
133 io_write32(reg + PROG_DATA_PAYLOAD2, buf[2]);
134 io_write32(reg + PROG_DATA_PAYLOAD3, buf[3]);
135 io_write32(reg + PROG_ADMIN_INFO0, 0);
136 io_write32(reg + PROG_ADMIN_INFO1, 0);
137 io_write32(reg + PROG_ADMIN_INFO2, 0);
138 io_write32(reg + PROG_ADMIN_INFO3, 0);
139 io_write32(reg + OTP_CONTROL, CTRL_CMD_PROG | CTRL_START);
140 wait_for_done(reg);
141 io_setbits32(ctrl, SOFT_WP);
142
143 return TEE_SUCCESS;
144 }
145