9d73fe2c46d41617ce5e47a2253cacea763d6779
[k3conf/k3conf.git] / common / sec_proxy.c
1 /*
2  * K3 Secure proxy driver
3  *
4  * Copyright (C) 2019 Texas Instruments Incorporated - https://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>
42 #include <string.h>
44 #ifdef DEBUG
45 #define dprintf(format, ...)     printf(format, ## __VA_ARGS__)
46 #else
47 #define dprintf(format, ...)
48 #endif
50 /* SEC PROXY RT THREAD STATUS */
51 #define RT_THREAD_STATUS                        0x0
52 #define RT_THREAD_THRESHOLD                     0x4
53 #define RT_THREAD_STATUS_ERROR_SHIFT            31
54 #define RT_THREAD_STATUS_ERROR_MASK             (1 << 31)
55 #define RT_THREAD_STATUS_CUR_CNT_SHIFT          0
56 #define RT_THREAD_STATUS_CUR_CNT_MASK           0xff
58 /* SEC PROXY SCFG THREAD CTRL */
59 #define SCFG_THREAD_CTRL                        0x1000
60 #define SCFG_THREAD_CTRL_DIR_SHIFT              31
61 #define SCFG_THREAD_CTRL_DIR_MASK               (1 << 31)
63 #define SEC_PROXY_THREAD(base, x)               ((base) + (0x1000 * (x)))
64 #define SEC_PROXY_TX_THREAD                     0
65 #define SEC_PROXY_RX_THREAD                     1
66 #define SEC_PROXY_MAX_THREADS                   2
68 #define SEC_PROXY_TIMEOUT_US                    1000000
70 #define SEC_PROXY_DATA_START_OFFS               0x4
71 #define SEC_PROXY_DATA_END_OFFS                 0x3c
73 /* Physical address for AM6 NAVSS 256 Main domain */
74 #define SEC_PROXY0_CFG_MMRS             0x31140000
75 #define SEC_PROXY0_SRC_TARGET_DATA      0x32C00000
76 #define SEC_PROXY0_CFG_SCFG             0x32800000
77 #define SEC_PROXY0_CFG_RT               0x32400000
79 struct k3_sec_proxy_thread {
80         uint32_t id;
81         uintptr_t data;
82         uintptr_t scfg;
83         uintptr_t rt;
84 } spts[SEC_PROXY_MAX_THREADS];
86 static inline uint32_t sp_readl(uintptr_t addr)
87 {
88         return mmio_read_32(addr);
89 }
91 static inline void sp_writel(uintptr_t addr, uint32_t data)
92 {
93         mmio_write_32(addr, data);
94 }
96 static int k3_sec_proxy_verify_thread(uint32_t dir)
97 {
98         struct k3_sec_proxy_thread *spt = &spts[dir];
100         /* Check for any errors already available */
101         if (sp_readl(spt->rt + RT_THREAD_STATUS) &
102             RT_THREAD_STATUS_ERROR_MASK) {
103                 fprintf(stderr, "%s: Thread %d is corrupted, cannot send data.\n",
104                        __func__, spt->id);
105                 return -1;
106         }
108         /* Make sure thread is configured for right direction */
109         if ((sp_readl(spt->scfg + SCFG_THREAD_CTRL)
110             & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) {
111                 if (dir)
112                         fprintf(stderr, "%s: Trying to receive data on tx Thread %d\n",
113                                __func__, spt->id);
114                 else
115                         fprintf(stderr, "%s: Trying to send data on rx Thread %d\n",
116                                __func__, spt->id);
117                 return -1;
118         }
120         /* Check the message queue before sending/receiving data */
121         if (!(sp_readl(spt->rt + RT_THREAD_STATUS) &
122               RT_THREAD_STATUS_CUR_CNT_MASK))
123                 return -2;
125         return 0;
128 int k3_sec_proxy_send(struct k3_sec_proxy_msg *msg)
130         struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_TX_THREAD];
131         int num_words, trail_bytes, ret;
132         uint32_t *word_data;
133         uintptr_t data_reg;
135         ret = k3_sec_proxy_verify_thread(SEC_PROXY_TX_THREAD);
136         if (ret) {
137                 fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
138                         __func__, spt->id, ret);
139                 return ret;
140         }
142         /* Check the message size. */
143         if (msg->len > SEC_PROXY_MAX_MSG_SIZE) {
144                 fprintf(stderr, "%s: Thread %u message length %zu > max msg size %d\n",
145                        __func__, spt->id, msg->len, SEC_PROXY_MAX_MSG_SIZE);
146                 return -1;
147         }
149         /* Send the message */
150         data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
151         word_data = (uint32_t *)msg->buf;
152         for (num_words = msg->len / sizeof(uint32_t);
153              num_words;
154              num_words--, data_reg += sizeof(uint32_t), word_data++)
155                 sp_writel(data_reg, *word_data);
157         trail_bytes = msg->len % sizeof(uint32_t);
158         if (trail_bytes) {
159                 uint32_t data_trail = *word_data;
161                 /* Ensure all unused data is 0 */
162                 data_trail &= 0xFFFFFFFF >> (8 * (sizeof(uint32_t) - trail_bytes));
163                 sp_writel(data_reg, data_trail);
164                 data_reg++;
165         }
167         /*
168          * 'data_reg' indicates next register to write. If we did not already
169          * write on tx complete reg(last reg), we must do so for transmit
170          */
171         if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS))
172                 sp_writel(spt->data + SEC_PROXY_DATA_END_OFFS, 0);
174         return 0;
177 int k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg)
179         struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_RX_THREAD];
180         int num_words, ret = -1, retry = 10000;
181         uint32_t *word_data;
182         uintptr_t data_reg;
184         while (retry-- && ret) {
185                 ret = k3_sec_proxy_verify_thread(SEC_PROXY_RX_THREAD);
186                 if ((ret && ret != -2) || !retry) {
187                         fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
188                                 __func__, spt->id, ret);
189                         return ret;
190                 }
191         }
193         data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
194         word_data = (uint32_t *)(uintptr_t)msg->buf;
195         for (num_words = SEC_PROXY_MAX_MSG_SIZE / sizeof(uint32_t);
196              num_words;
197              num_words--, data_reg += sizeof(uint32_t), word_data++)
198                 *word_data = sp_readl(data_reg);
200         return 0;
203 static int get_thread_id(char *host_name, char *function)
205         struct ti_sci_info *sci_info = &soc_info.sci_info;
206         uint32_t i;
208         for (i = 0; i < sci_info->num_sp_threads[MAIN_SEC_PROXY]; i++)
209                 if (!strcmp(host_name,
210                             sci_info->sp_info[MAIN_SEC_PROXY][i].host) &&
211                     !strcmp(function,
212                             sci_info->sp_info[MAIN_SEC_PROXY][i].host_function))
213                         return sci_info->sp_info[MAIN_SEC_PROXY][i].sp_id;
215         return -1;
219 static char* get_host_name(uint32_t host_id)
221         struct ti_sci_info *sci_info = &soc_info.sci_info;
222         uint32_t i;
224         for (i = 0; i < sci_info->num_hosts; i++)
225                 if (host_id == sci_info->host_info[i].host_id)
226                         return sci_info->host_info[i].host_name;
228         return NULL;
231 int k3_sec_proxy_init(void)
233         int rx_thread, tx_thread;
234         char *host_name;
236         host_name = get_host_name(soc_info.host_id);
237         if (!host_name) {
238                 fprintf(stderr, "Invalid host id %d, using default host_id %d\n",
239                         soc_info.host_id, DEFAULT_HOST_ID);
240                 soc_info.host_id = DEFAULT_HOST_ID;
241                 host_name = get_host_name(soc_info.host_id);
242         }
244         rx_thread = get_thread_id(host_name, "response");
245         if (rx_thread < 0) {
246                 fprintf(stderr, "Invalid host id %d, using default host_id %d\n",
247                         soc_info.host_id, DEFAULT_HOST_ID);
248                 soc_info.host_id = DEFAULT_HOST_ID;
249                 host_name = get_host_name(soc_info.host_id);
250                 rx_thread = get_thread_id(host_name, "response");
251         }
252         tx_thread = get_thread_id(host_name, "low_priority");
253         dprintf("host_name = %s, tx_thread = %d, rx_thread = %d\n",
254                 host_name, tx_thread, rx_thread);
256         spts[SEC_PROXY_TX_THREAD].id = tx_thread;
257         spts[SEC_PROXY_TX_THREAD].data = SEC_PROXY_THREAD(SEC_PROXY0_SRC_TARGET_DATA, tx_thread);
258         spts[SEC_PROXY_TX_THREAD].scfg = SEC_PROXY_THREAD(SEC_PROXY0_CFG_SCFG, tx_thread);
259         spts[SEC_PROXY_TX_THREAD].rt = SEC_PROXY_THREAD(SEC_PROXY0_CFG_RT, tx_thread);
261         spts[SEC_PROXY_RX_THREAD].id = rx_thread;
262         spts[SEC_PROXY_RX_THREAD].data = SEC_PROXY_THREAD(SEC_PROXY0_SRC_TARGET_DATA, rx_thread);
263         spts[SEC_PROXY_RX_THREAD].scfg = SEC_PROXY_THREAD(SEC_PROXY0_CFG_SCFG, rx_thread);
264         spts[SEC_PROXY_RX_THREAD].rt = SEC_PROXY_THREAD(SEC_PROXY0_CFG_RT, rx_thread);
266         return 0;