9de3f9331bb1f9c982feb54c569e649913ebf50c
1 /*
2 * K3 Secure proxy driver
3 *
4 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
5 * Lokesh Vutla <lokeshvutla@ti.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution.
18 *
19 * Neither the name of Texas Instruments Incorporated nor the names of
20 * its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <sec_proxy.h>
39 #include <mmio.h>
40 #include <error.h>
41 #include <socinfo.h>
43 /* SEC PROXY RT THREAD STATUS */
44 #define RT_THREAD_STATUS 0x0
45 #define RT_THREAD_THRESHOLD 0x4
46 #define RT_THREAD_STATUS_ERROR_SHIFT 31
47 #define RT_THREAD_STATUS_ERROR_MASK (1 << 31)
48 #define RT_THREAD_STATUS_CUR_CNT_SHIFT 0
49 #define RT_THREAD_STATUS_CUR_CNT_MASK 0xff
51 /* SEC PROXY SCFG THREAD CTRL */
52 #define SCFG_THREAD_CTRL 0x1000
53 #define SCFG_THREAD_CTRL_DIR_SHIFT 31
54 #define SCFG_THREAD_CTRL_DIR_MASK (1 << 31)
56 #define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x)))
57 #define SEC_PROXY_TX_THREAD 0
58 #define SEC_PROXY_RX_THREAD 1
59 #define SEC_PROXY_MAX_THREADS 2
61 #define SEC_PROXY_TIMEOUT_US 1000000
63 #define SEC_PROXY_DATA_START_OFFS 0x4
64 #define SEC_PROXY_DATA_END_OFFS 0x3c
66 /* Physical address for AM6 NAVSS 256 Main domain */
67 #define SEC_PROXY0_CFG_MMRS 0x31140000
68 #define SEC_PROXY0_SRC_TARGET_DATA 0x32C00000
69 #define SEC_PROXY0_CFG_SCFG 0x32800000
70 #define SEC_PROXY0_CFG_RT 0x32400000
72 struct k3_sec_proxy_thread {
73 uint32_t id;
74 uintptr_t data;
75 uintptr_t scfg;
76 uintptr_t rt;
77 } spts[SEC_PROXY_MAX_THREADS];
79 static inline uint32_t sp_readl(uintptr_t addr)
80 {
81 return mmio_read_32(addr);
82 }
84 static inline void sp_writel(uintptr_t addr, uint32_t data)
85 {
86 mmio_write_32(addr, data);
87 }
89 static int k3_sec_proxy_verify_thread(uint32_t dir)
90 {
91 struct k3_sec_proxy_thread *spt = &spts[dir];
93 /* Check for any errors already available */
94 if (sp_readl(spt->rt + RT_THREAD_STATUS) &
95 RT_THREAD_STATUS_ERROR_MASK) {
96 fprintf(stderr, "%s: Thread %d is corrupted, cannot send data.\n",
97 __func__, spt->id);
98 return -1;
99 }
101 /* Make sure thread is configured for right direction */
102 if ((sp_readl(spt->scfg + SCFG_THREAD_CTRL)
103 & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) {
104 if (dir)
105 fprintf(stderr, "%s: Trying to receive data on tx Thread %d\n",
106 __func__, spt->id);
107 else
108 fprintf(stderr, "%s: Trying to send data on rx Thread %d\n",
109 __func__, spt->id);
110 return -1;
111 }
113 /* Check the message queue before sending/receiving data */
114 if (!(sp_readl(spt->rt + RT_THREAD_STATUS) &
115 RT_THREAD_STATUS_CUR_CNT_MASK))
116 return -2;
118 return 0;
119 }
121 int k3_sec_proxy_send(struct k3_sec_proxy_msg *msg)
122 {
123 struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_TX_THREAD];
124 int num_words, trail_bytes, ret;
125 uint32_t *word_data;
126 uintptr_t data_reg;
128 ret = k3_sec_proxy_verify_thread(SEC_PROXY_TX_THREAD);
129 if (ret) {
130 fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
131 __func__, spt->id, ret);
132 return ret;
133 }
135 /* Check the message size. */
136 if (msg->len > SEC_PROXY_MAX_MSG_SIZE) {
137 fprintf(stderr, "%s: Thread %u message length %zu > max msg size %d\n",
138 __func__, spt->id, msg->len, SEC_PROXY_MAX_MSG_SIZE);
139 return -1;
140 }
142 /* Send the message */
143 data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
144 word_data = (uint32_t *)msg->buf;
145 for (num_words = msg->len / sizeof(uint32_t);
146 num_words;
147 num_words--, data_reg += sizeof(uint32_t), word_data++)
148 sp_writel(data_reg, *word_data);
150 trail_bytes = msg->len % sizeof(uint32_t);
151 if (trail_bytes) {
152 uint32_t data_trail = *word_data;
154 /* Ensure all unused data is 0 */
155 data_trail &= 0xFFFFFFFF >> (8 * (sizeof(uint32_t) - trail_bytes));
156 sp_writel(data_reg, data_trail);
157 data_reg++;
158 }
160 /*
161 * 'data_reg' indicates next register to write. If we did not already
162 * write on tx complete reg(last reg), we must do so for transmit
163 */
164 if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS))
165 sp_writel(spt->data + SEC_PROXY_DATA_END_OFFS, 0);
167 return 0;
168 }
170 int k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg)
171 {
172 struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_RX_THREAD];
173 int num_words, ret = -1, retry = 10000;
174 uint32_t *word_data;
175 uintptr_t data_reg;
177 while (retry-- && ret) {
178 ret = k3_sec_proxy_verify_thread(SEC_PROXY_RX_THREAD);
179 if ((ret && ret != -2) || !retry) {
180 fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
181 __func__, spt->id, ret);
182 return ret;
183 }
184 }
186 data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
187 word_data = (uint32_t *)(uintptr_t)msg->buf;
188 for (num_words = SEC_PROXY_MAX_MSG_SIZE / sizeof(uint32_t);
189 num_words;
190 num_words--, data_reg += sizeof(uint32_t), word_data++)
191 *word_data = sp_readl(data_reg);
193 return 0;
194 }
196 int k3_sec_proxy_init(void)
197 {
198 uint32_t rx_thread, tx_thread;
200 if (soc_info.host_id == DEFAULT_HOST_ID) {
201 tx_thread = DEFAULT_SEC_PROXY_TX_THREAD;
202 rx_thread = DEFAULT_SEC_PROXY_RX_THREAD;
203 }
205 /* ToDO: Get thread ids using host_id and soc information */
206 spts[SEC_PROXY_TX_THREAD].id = tx_thread;
207 spts[SEC_PROXY_TX_THREAD].data = SEC_PROXY_THREAD(SEC_PROXY0_SRC_TARGET_DATA, tx_thread);
208 spts[SEC_PROXY_TX_THREAD].scfg = SEC_PROXY_THREAD(SEC_PROXY0_CFG_SCFG, tx_thread);
209 spts[SEC_PROXY_TX_THREAD].rt = SEC_PROXY_THREAD(SEC_PROXY0_CFG_RT, tx_thread);
211 spts[SEC_PROXY_RX_THREAD].id = rx_thread;
212 spts[SEC_PROXY_RX_THREAD].data = SEC_PROXY_THREAD(SEC_PROXY0_SRC_TARGET_DATA, rx_thread);
213 spts[SEC_PROXY_RX_THREAD].scfg = SEC_PROXY_THREAD(SEC_PROXY0_CFG_SCFG, rx_thread);
214 spts[SEC_PROXY_RX_THREAD].rt = SEC_PROXY_THREAD(SEC_PROXY0_CFG_RT, rx_thread);
216 return 0;
217 }