common: Add support for printing tables
[k3conf/k3conf.git] / common / sec_proxy.c
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;
121 int k3_sec_proxy_send(struct k3_sec_proxy_msg *msg)
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;
170 int k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg)
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;
196 int k3_sec_proxy_init(void)
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;