Bump up version to 0.2
[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 struct k3_sec_proxy_base k3_generic_sec_proxy_base = {
74         .src_target_data = 0x32c00000,
75         .cfg_scfg = 0x32800000,
76         .cfg_rt = 0x32400000,
77 };
79 struct k3_sec_proxy_base k3_lite_sec_proxy_base = {
80         .src_target_data = 0x4d000000,
81         .cfg_scfg = 0x4a400000,
82         .cfg_rt = 0x4a600000,
83 };
85 struct k3_sec_proxy_thread {
86         uint32_t id;
87         uintptr_t data;
88         uintptr_t scfg;
89         uintptr_t rt;
90 } spts[SEC_PROXY_MAX_THREADS];
92 static inline uint32_t sp_readl(uintptr_t addr)
93 {
94         return mmio_read_32(addr);
95 }
97 static inline void sp_writel(uintptr_t addr, uint32_t data)
98 {
99         mmio_write_32(addr, data);
102 static int k3_sec_proxy_verify_thread(uint32_t dir)
104         struct k3_sec_proxy_thread *spt = &spts[dir];
106         /* Check for any errors already available */
107         if (sp_readl(spt->rt + RT_THREAD_STATUS) &
108             RT_THREAD_STATUS_ERROR_MASK) {
109                 fprintf(stderr, "%s: Thread %d is corrupted, cannot send data.\n",
110                        __func__, spt->id);
111                 return -1;
112         }
114         /* Make sure thread is configured for right direction */
115         if ((sp_readl(spt->scfg + SCFG_THREAD_CTRL)
116             & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) {
117                 if (dir)
118                         fprintf(stderr, "%s: Trying to receive data on tx Thread %d\n",
119                                __func__, spt->id);
120                 else
121                         fprintf(stderr, "%s: Trying to send data on rx Thread %d\n",
122                                __func__, spt->id);
123                 return -1;
124         }
126         /* Check the message queue before sending/receiving data */
127         if (!(sp_readl(spt->rt + RT_THREAD_STATUS) &
128               RT_THREAD_STATUS_CUR_CNT_MASK))
129                 return -2;
131         return 0;
134 int k3_sec_proxy_send(struct k3_sec_proxy_msg *msg)
136         struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_TX_THREAD];
137         int num_words, trail_bytes, ret;
138         uint32_t *word_data;
139         uintptr_t data_reg;
141         ret = k3_sec_proxy_verify_thread(SEC_PROXY_TX_THREAD);
142         if (ret) {
143                 fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
144                         __func__, spt->id, ret);
145                 return ret;
146         }
148         /* Check the message size. */
149         if (msg->len > SEC_PROXY_MAX_MSG_SIZE) {
150                 fprintf(stderr, "%s: Thread %u message length %zu > max msg size %d\n",
151                        __func__, spt->id, msg->len, SEC_PROXY_MAX_MSG_SIZE);
152                 return -1;
153         }
155         /* Send the message */
156         data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
157         word_data = (uint32_t *)msg->buf;
158         for (num_words = msg->len / sizeof(uint32_t);
159              num_words;
160              num_words--, data_reg += sizeof(uint32_t), word_data++)
161                 sp_writel(data_reg, *word_data);
163         trail_bytes = msg->len % sizeof(uint32_t);
164         if (trail_bytes) {
165                 uint32_t data_trail = *word_data;
167                 /* Ensure all unused data is 0 */
168                 data_trail &= 0xFFFFFFFF >> (8 * (sizeof(uint32_t) - trail_bytes));
169                 sp_writel(data_reg, data_trail);
170                 data_reg++;
171         }
173         /*
174          * 'data_reg' indicates next register to write. If we did not already
175          * write on tx complete reg(last reg), we must do so for transmit
176          */
177         if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS))
178                 sp_writel(spt->data + SEC_PROXY_DATA_END_OFFS, 0);
180         return 0;
183 int k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg)
185         struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_RX_THREAD];
186         int num_words, ret = -1, retry = 10000;
187         uint32_t *word_data;
188         uintptr_t data_reg;
190         while (retry-- && ret) {
191                 ret = k3_sec_proxy_verify_thread(SEC_PROXY_RX_THREAD);
192                 if ((ret && ret != -2) || !retry) {
193                         fprintf(stderr, "%s: Thread%d verification failed. ret = %d\n",
194                                 __func__, spt->id, ret);
195                         return ret;
196                 }
197         }
199         data_reg = spt->data + SEC_PROXY_DATA_START_OFFS;
200         word_data = (uint32_t *)(uintptr_t)msg->buf;
201         for (num_words = SEC_PROXY_MAX_MSG_SIZE / sizeof(uint32_t);
202              num_words;
203              num_words--, data_reg += sizeof(uint32_t), word_data++)
204                 *word_data = sp_readl(data_reg);
206         return 0;
209 static int get_thread_id(char *host_name, char *function)
211         struct ti_sci_info *sci_info = &soc_info.sci_info;
212         uint32_t i;
214         for (i = 0; i < sci_info->num_sp_threads[MAIN_SEC_PROXY]; i++)
215                 if (!strcmp(host_name,
216                             sci_info->sp_info[MAIN_SEC_PROXY][i].host) &&
217                     !strcmp(function,
218                             sci_info->sp_info[MAIN_SEC_PROXY][i].host_function))
219                         return sci_info->sp_info[MAIN_SEC_PROXY][i].sp_id;
221         return -1;
225 static char* get_host_name(uint32_t host_id)
227         struct ti_sci_info *sci_info = &soc_info.sci_info;
228         uint32_t i;
230         for (i = 0; i < sci_info->num_hosts; i++)
231                 if (host_id == sci_info->host_info[i].host_id)
232                         return sci_info->host_info[i].host_name;
234         return NULL;
237 int k3_sec_proxy_init(void)
239         struct k3_sec_proxy_base *spb = soc_info.sec_proxy;
240         int rx_thread, tx_thread;
241         char *host_name;
243         host_name = get_host_name(soc_info.host_id);
244         if (!host_name) {
245                 fprintf(stderr, "Invalid host id %d, using default host_id %d\n",
246                         soc_info.host_id, DEFAULT_HOST_ID);
247                 soc_info.host_id = DEFAULT_HOST_ID;
248                 host_name = get_host_name(soc_info.host_id);
249         }
251         rx_thread = get_thread_id(host_name, "response");
252         if (rx_thread < 0) {
253                 fprintf(stderr, "Invalid host id %d, using default host_id %d\n",
254                         soc_info.host_id, DEFAULT_HOST_ID);
255                 soc_info.host_id = DEFAULT_HOST_ID;
256                 host_name = get_host_name(soc_info.host_id);
257                 rx_thread = get_thread_id(host_name, "response");
258         }
259         tx_thread = get_thread_id(host_name, "low_priority");
260         dprintf("host_name = %s, tx_thread = %d, rx_thread = %d\n",
261                 host_name, tx_thread, rx_thread);
263         spts[SEC_PROXY_TX_THREAD].id = tx_thread;
264         spts[SEC_PROXY_TX_THREAD].data = SEC_PROXY_THREAD(spb->src_target_data, tx_thread);
265         spts[SEC_PROXY_TX_THREAD].scfg = SEC_PROXY_THREAD(spb->cfg_scfg, tx_thread);
266         spts[SEC_PROXY_TX_THREAD].rt = SEC_PROXY_THREAD(spb->cfg_rt, tx_thread);
268         spts[SEC_PROXY_RX_THREAD].id = rx_thread;
269         spts[SEC_PROXY_RX_THREAD].data = SEC_PROXY_THREAD(spb->src_target_data, rx_thread);
270         spts[SEC_PROXY_RX_THREAD].scfg = SEC_PROXY_THREAD(spb->cfg_scfg, rx_thread);
271         spts[SEC_PROXY_RX_THREAD].rt = SEC_PROXY_THREAD(spb->cfg_rt, rx_thread);
273         return 0;