1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Texas Instruments' K3 Secure proxy Driver 4 * 5 * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ 6 * Lokesh Vutla <lokeshvutla@ti.com> 7 */ 8 9 #include <common.h> 10 #include <asm/io.h> 11 #include <linux/types.h> 12 #include <linux/bitops.h> 13 #include <linux/soc/ti/k3-sec-proxy.h> 14 #include <dm.h> 15 #include <mailbox-uclass.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 /* SEC PROXY RT THREAD STATUS */ 20 #define RT_THREAD_STATUS 0x0 21 #define RT_THREAD_THRESHOLD 0x4 22 #define RT_THREAD_STATUS_ERROR_SHIFT 31 23 #define RT_THREAD_STATUS_ERROR_MASK BIT(31) 24 #define RT_THREAD_STATUS_CUR_CNT_SHIFT 0 25 #define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK(7, 0) 26 27 /* SEC PROXY SCFG THREAD CTRL */ 28 #define SCFG_THREAD_CTRL 0x1000 29 #define SCFG_THREAD_CTRL_DIR_SHIFT 31 30 #define SCFG_THREAD_CTRL_DIR_MASK BIT(31) 31 32 #define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x))) 33 #define THREAD_IS_RX 1 34 #define THREAD_IS_TX 0 35 36 /** 37 * struct k3_sec_proxy_desc - Description of secure proxy integration. 38 * @thread_count: Number of Threads. 39 * @max_msg_size: Message size in bytes. 40 * @data_start_offset: Offset of the First data register of the thread 41 * @data_end_offset: Offset of the Last data register of the thread 42 * @valid_threads: List of Valid threads that the processor can access 43 * @num_valid_threads: Number of valid threads. 44 */ 45 struct k3_sec_proxy_desc { 46 u16 thread_count; 47 u16 max_msg_size; 48 u16 data_start_offset; 49 u16 data_end_offset; 50 const u32 *valid_threads; 51 u32 num_valid_threads; 52 }; 53 54 /** 55 * struct k3_sec_proxy_thread - Description of a secure proxy Thread 56 * @id: Thread ID 57 * @data: Thread Data path region for target 58 * @scfg: Secure Config Region for Thread 59 * @rt: RealTime Region for Thread 60 * @rx_buf: Receive buffer data, max message size. 61 */ 62 struct k3_sec_proxy_thread { 63 u32 id; 64 void __iomem *data; 65 void __iomem *scfg; 66 void __iomem *rt; 67 u32 *rx_buf; 68 }; 69 70 /** 71 * struct k3_sec_proxy_mbox - Description of a Secure Proxy Instance 72 * @chan: Mailbox Channel 73 * @desc: Description of the SoC integration 74 * @chans: Array for valid thread instances 75 * @target_data: Secure Proxy region for Target Data 76 * @scfg: Secure Proxy Region for Secure configuration. 77 * @rt: Secure proxy Region for Real Time Region. 78 */ 79 struct k3_sec_proxy_mbox { 80 struct mbox_chan chan; 81 struct k3_sec_proxy_desc *desc; 82 struct k3_sec_proxy_thread *chans; 83 phys_addr_t target_data; 84 phys_addr_t scfg; 85 phys_addr_t rt; 86 }; 87 88 static inline u32 sp_readl(void __iomem *addr, unsigned int offset) 89 { 90 return readl(addr + offset); 91 } 92 93 static inline void sp_writel(void __iomem *addr, unsigned int offset, u32 data) 94 { 95 writel(data, addr + offset); 96 } 97 98 /** 99 * k3_sec_proxy_of_xlate() - Translation of phandle to channel 100 * @chan: Mailbox channel 101 * @args: Phandle Pointer 102 * 103 * Translates the phandle args and fills up the Mailbox channel from client. 104 * Return: 0 if all goes good, else return corresponding error message. 105 */ 106 static int k3_sec_proxy_of_xlate(struct mbox_chan *chan, 107 struct ofnode_phandle_args *args) 108 { 109 struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); 110 int ind, i; 111 112 debug("%s(chan=%p)\n", __func__, chan); 113 114 if (args->args_count != 1) { 115 debug("Invaild args_count: %d\n", args->args_count); 116 return -EINVAL; 117 } 118 ind = args->args[0]; 119 120 for (i = 0; i < spm->desc->num_valid_threads; i++) 121 if (spm->chans[i].id == ind) { 122 chan->id = ind; 123 chan->con_priv = &spm->chans[i]; 124 return 0; 125 } 126 127 dev_err(chan->dev, "%s: Invalid Thread ID %d\n", __func__, ind); 128 return -ENOENT; 129 } 130 131 /** 132 * k3_sec_proxy_request() - Request for mailbox channel 133 * @chan: Channel Pointer 134 */ 135 static int k3_sec_proxy_request(struct mbox_chan *chan) 136 { 137 debug("%s(chan=%p)\n", __func__, chan); 138 139 return 0; 140 } 141 142 /** 143 * k3_sec_proxy_free() - Free the mailbox channel 144 * @chan: Channel Pointer 145 */ 146 static int k3_sec_proxy_free(struct mbox_chan *chan) 147 { 148 debug("%s(chan=%p)\n", __func__, chan); 149 150 return 0; 151 } 152 153 /** 154 * k3_sec_proxy_verify_thread() - Verify thread status before 155 * sending/receiving data. 156 * @spt: pointer to secure proxy thread description 157 * @dir: Direction of the thread 158 * 159 * Return: 0 if all goes good, else appropriate error message. 160 */ 161 static inline int k3_sec_proxy_verify_thread(struct k3_sec_proxy_thread *spt, 162 u8 dir) 163 { 164 /* Check for any errors already available */ 165 if (sp_readl(spt->rt, RT_THREAD_STATUS) & 166 RT_THREAD_STATUS_ERROR_MASK) { 167 printf("%s: Thread %d is corrupted, cannot send data.\n", 168 __func__, spt->id); 169 return -EINVAL; 170 } 171 172 /* Make sure thread is configured for right direction */ 173 if ((sp_readl(spt->scfg, SCFG_THREAD_CTRL) 174 & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) { 175 if (dir) 176 printf("%s: Trying to receive data on tx Thread %d\n", 177 __func__, spt->id); 178 else 179 printf("%s: Trying to send data on rx Thread %d\n", 180 __func__, spt->id); 181 return -EINVAL; 182 } 183 184 /* Check the message queue before sending/receiving data */ 185 if (!(sp_readl(spt->rt, RT_THREAD_STATUS) & 186 RT_THREAD_STATUS_CUR_CNT_MASK)) 187 return -ENODATA; 188 189 return 0; 190 } 191 192 /** 193 * k3_sec_proxy_send() - Send data via mailbox channel 194 * @chan: Channel Pointer 195 * @data: Pointer to k3_sec_proxy_msg 196 * 197 * Return: 0 if all goes good, else appropriate error message. 198 */ 199 static int k3_sec_proxy_send(struct mbox_chan *chan, const void *data) 200 { 201 const struct k3_sec_proxy_msg *msg = (struct k3_sec_proxy_msg *)data; 202 struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); 203 struct k3_sec_proxy_thread *spt = chan->con_priv; 204 int num_words, trail_bytes, ret; 205 void __iomem *data_reg; 206 u32 *word_data; 207 208 debug("%s(chan=%p, data=%p)\n", __func__, chan, data); 209 210 ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX); 211 if (ret) { 212 dev_err(dev, "%s: Thread%d verification failed. ret = %d\n", 213 __func__, spt->id, ret); 214 return ret; 215 } 216 217 /* Check the message size. */ 218 if (msg->len > spm->desc->max_msg_size) { 219 printf("%s: Thread %ld message length %zu > max msg size %d\n", 220 __func__, chan->id, msg->len, spm->desc->max_msg_size); 221 return -EINVAL; 222 } 223 224 /* Send the message */ 225 data_reg = spt->data + spm->desc->data_start_offset; 226 for (num_words = msg->len / sizeof(u32), word_data = (u32 *)msg->buf; 227 num_words; 228 num_words--, data_reg += sizeof(u32), word_data++) 229 writel(*word_data, data_reg); 230 231 trail_bytes = msg->len % sizeof(u32); 232 if (trail_bytes) { 233 u32 data_trail = *word_data; 234 235 /* Ensure all unused data is 0 */ 236 data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); 237 writel(data_trail, data_reg); 238 data_reg++; 239 } 240 241 /* 242 * 'data_reg' indicates next register to write. If we did not already 243 * write on tx complete reg(last reg), we must do so for transmit 244 */ 245 if (data_reg <= (spt->data + spm->desc->data_end_offset)) 246 sp_writel(spt->data, spm->desc->data_end_offset, 0); 247 248 debug("%s: Message successfully sent on thread %ld\n", 249 __func__, chan->id); 250 251 return 0; 252 } 253 254 /** 255 * k3_sec_proxy_recv() - Receive data via mailbox channel 256 * @chan: Channel Pointer 257 * @data: Pointer to k3_sec_proxy_msg 258 * 259 * Return: 0 if all goes good, else appropriate error message. 260 */ 261 static int k3_sec_proxy_recv(struct mbox_chan *chan, void *data) 262 { 263 struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); 264 struct k3_sec_proxy_thread *spt = chan->con_priv; 265 struct k3_sec_proxy_msg *msg = data; 266 void __iomem *data_reg; 267 int num_words, ret; 268 u32 *word_data; 269 270 debug("%s(chan=%p, data=%p)\n", __func__, chan, data); 271 272 ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX); 273 if (ret) 274 return ret; 275 276 msg->len = spm->desc->max_msg_size; 277 msg->buf = spt->rx_buf; 278 data_reg = spt->data + spm->desc->data_start_offset; 279 word_data = spt->rx_buf; 280 for (num_words = spm->desc->max_msg_size / sizeof(u32); 281 num_words; 282 num_words--, data_reg += sizeof(u32), word_data++) 283 *word_data = readl(data_reg); 284 285 debug("%s: Message successfully received from thread %ld\n", 286 __func__, chan->id); 287 288 return 0; 289 } 290 291 struct mbox_ops k3_sec_proxy_mbox_ops = { 292 .of_xlate = k3_sec_proxy_of_xlate, 293 .request = k3_sec_proxy_request, 294 .free = k3_sec_proxy_free, 295 .send = k3_sec_proxy_send, 296 .recv = k3_sec_proxy_recv, 297 }; 298 299 /** 300 * k3_sec_proxy_of_to_priv() - generate private data from device tree 301 * @dev: corresponding k3 secure proxy device 302 * @spm: pointer to driver specific private data 303 * 304 * Return: 0 if all went ok, else corresponding error message. 305 */ 306 static int k3_sec_proxy_of_to_priv(struct udevice *dev, 307 struct k3_sec_proxy_mbox *spm) 308 { 309 const void *blob = gd->fdt_blob; 310 311 if (!blob) { 312 debug("'%s' no dt?\n", dev->name); 313 return -ENODEV; 314 } 315 316 spm->target_data = devfdt_get_addr_name(dev, "target_data"); 317 if (spm->target_data == FDT_ADDR_T_NONE) { 318 dev_err(dev, "No reg property for target data base\n"); 319 return -EINVAL; 320 } 321 322 spm->scfg = devfdt_get_addr_name(dev, "scfg"); 323 if (spm->rt == FDT_ADDR_T_NONE) { 324 dev_err(dev, "No reg property for Secure Cfg base\n"); 325 return -EINVAL; 326 } 327 328 spm->rt = devfdt_get_addr_name(dev, "rt"); 329 if (spm->rt == FDT_ADDR_T_NONE) { 330 dev_err(dev, "No reg property for Real Time Cfg base\n"); 331 return -EINVAL; 332 } 333 334 return 0; 335 } 336 337 /** 338 * k3_sec_proxy_thread_setup - Initialize the parameters for all valid threads 339 * @spm: Mailbox instance for which threads needs to be initialized 340 * 341 * Return: 0 if all went ok, else corresponding error message 342 */ 343 static int k3_sec_proxy_thread_setup(struct k3_sec_proxy_mbox *spm) 344 { 345 struct k3_sec_proxy_thread *spt; 346 int i, ind; 347 348 for (i = 0; i < spm->desc->num_valid_threads; i++) { 349 spt = &spm->chans[i]; 350 ind = spm->desc->valid_threads[i]; 351 spt->id = ind; 352 spt->data = (void *)SEC_PROXY_THREAD(spm->target_data, ind); 353 spt->scfg = (void *)SEC_PROXY_THREAD(spm->scfg, ind); 354 spt->rt = (void *)SEC_PROXY_THREAD(spm->rt, ind); 355 spt->rx_buf = calloc(1, spm->desc->max_msg_size); 356 if (!spt->rx_buf) 357 return -ENOMEM; 358 } 359 360 return 0; 361 } 362 363 /** 364 * k3_sec_proxy_probe() - Basic probe 365 * @dev: corresponding mailbox device 366 * 367 * Return: 0 if all went ok, else corresponding error message 368 */ 369 static int k3_sec_proxy_probe(struct udevice *dev) 370 { 371 struct k3_sec_proxy_mbox *spm = dev_get_priv(dev); 372 int ret; 373 374 debug("%s(dev=%p)\n", __func__, dev); 375 376 ret = k3_sec_proxy_of_to_priv(dev, spm); 377 if (ret) 378 return ret; 379 380 spm->desc = (void *)dev_get_driver_data(dev); 381 spm->chans = calloc(spm->desc->num_valid_threads, 382 sizeof(struct k3_sec_proxy_thread)); 383 if (!spm->chans) 384 return -ENOMEM; 385 386 ret = k3_sec_proxy_thread_setup(spm); 387 if (ret) { 388 debug("%s: secure proxy thread setup failed\n", __func__); 389 return ret; 390 } 391 392 return 0; 393 } 394 395 static int k3_sec_proxy_remove(struct udevice *dev) 396 { 397 struct k3_sec_proxy_mbox *spm = dev_get_priv(dev); 398 399 debug("%s(dev=%p)\n", __func__, dev); 400 401 free(spm->chans); 402 403 return 0; 404 } 405 406 /* 407 * Thread ID #4: ROM request 408 * Thread ID #5: ROM response, SYSFW notify 409 * Thread ID #6: SYSFW request response 410 * Thread ID #7: SYSFW request high priority 411 * Thread ID #8: SYSFW request low priority 412 * Thread ID #9: SYSFW notify response 413 */ 414 static const u32 am6x_valid_threads[] = { 4, 5, 6, 7, 8, 9, 11, 13 }; 415 416 static const struct k3_sec_proxy_desc am654_desc = { 417 .thread_count = 90, 418 .max_msg_size = 60, 419 .data_start_offset = 0x4, 420 .data_end_offset = 0x3C, 421 .valid_threads = am6x_valid_threads, 422 .num_valid_threads = ARRAY_SIZE(am6x_valid_threads), 423 }; 424 425 static const struct udevice_id k3_sec_proxy_ids[] = { 426 { .compatible = "ti,am654-secure-proxy", .data = (ulong)&am654_desc}, 427 { } 428 }; 429 430 U_BOOT_DRIVER(k3_sec_proxy) = { 431 .name = "k3-secure-proxy", 432 .id = UCLASS_MAILBOX, 433 .of_match = k3_sec_proxy_ids, 434 .probe = k3_sec_proxy_probe, 435 .remove = k3_sec_proxy_remove, 436 .priv_auto_alloc_size = sizeof(struct k3_sec_proxy_mbox), 437 .ops = &k3_sec_proxy_mbox_ops, 438 }; 439