mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-19 02:54:24 +00:00
ti: k3: drivers: Add Secure Proxy driver
Secure Proxy module manages hardware threads that are meant for communication between the processor entities. Add support for this here. Signed-off-by: Andrew F. Davis <afd@ti.com>
This commit is contained in:
parent
6d4f6aea2c
commit
d76fdd33e0
5 changed files with 366 additions and 1 deletions
289
plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
Normal file
289
plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Texas Instruments K3 Secure Proxy Driver
|
||||
* Based on Linux and U-Boot implementation
|
||||
*
|
||||
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdlib.h>
|
||||
#include <utils.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
#include "sec_proxy.h"
|
||||
|
||||
/* SEC PROXY RT THREAD STATUS */
|
||||
#define RT_THREAD_STATUS (0x0)
|
||||
#define RT_THREAD_STATUS_ERROR_SHIFT (31)
|
||||
#define RT_THREAD_STATUS_ERROR_MASK BIT(31)
|
||||
#define RT_THREAD_STATUS_CUR_CNT_SHIFT (0)
|
||||
#define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK(7, 0)
|
||||
|
||||
/* SEC PROXY SCFG THREAD CTRL */
|
||||
#define SCFG_THREAD_CTRL (0x1000)
|
||||
#define SCFG_THREAD_CTRL_DIR_SHIFT (31)
|
||||
#define SCFG_THREAD_CTRL_DIR_MASK BIT(31)
|
||||
|
||||
#define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x)))
|
||||
#define THREAD_IS_RX (1)
|
||||
#define THREAD_IS_TX (0)
|
||||
|
||||
/**
|
||||
* struct k3_sec_proxy_desc - Description of secure proxy integration
|
||||
* @timeout_us: Timeout for communication (in Microseconds)
|
||||
* @max_msg_size: Message size in bytes
|
||||
* @data_start_offset: Offset of the First data register of the thread
|
||||
* @data_end_offset: Offset of the Last data register of the thread
|
||||
*/
|
||||
struct k3_sec_proxy_desc {
|
||||
uint32_t timeout_us;
|
||||
uint16_t max_msg_size;
|
||||
uint16_t data_start_offset;
|
||||
uint16_t data_end_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct k3_sec_proxy_thread - Description of a secure proxy Thread
|
||||
* @id: Thread ID
|
||||
* @data: Thread Data path region for target
|
||||
* @scfg: Secure Config Region for Thread
|
||||
* @rt: RealTime Region for Thread
|
||||
*/
|
||||
struct k3_sec_proxy_thread {
|
||||
uint32_t id;
|
||||
uintptr_t data;
|
||||
uintptr_t scfg;
|
||||
uintptr_t rt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct k3_sec_proxy_mbox - Description of a Secure Proxy Instance
|
||||
* @desc: Description of the SoC integration
|
||||
* @chans: Array for valid thread instances
|
||||
*/
|
||||
struct k3_sec_proxy_mbox {
|
||||
const struct k3_sec_proxy_desc desc;
|
||||
struct k3_sec_proxy_thread threads[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Thread ID #0: DMSC notify
|
||||
* Thread ID #1: DMSC request response
|
||||
* Thread ID #2: DMSC request high priority
|
||||
* Thread ID #3: DMSC request low priority
|
||||
* Thread ID #4: DMSC notify response
|
||||
*/
|
||||
#define SP_THREAD(_x) \
|
||||
[_x] = { \
|
||||
.id = _x, \
|
||||
.data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, _x), \
|
||||
.scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, _x), \
|
||||
.rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, _x), \
|
||||
}
|
||||
|
||||
static struct k3_sec_proxy_mbox spm = {
|
||||
.desc = {
|
||||
.timeout_us = SEC_PROXY_TIMEOUT_US,
|
||||
.max_msg_size = SEC_PROXY_MAX_MESSAGE_SIZE,
|
||||
.data_start_offset = 0x4,
|
||||
.data_end_offset = 0x3C,
|
||||
},
|
||||
.threads = {
|
||||
SP_THREAD(SP_NOTIFY),
|
||||
SP_THREAD(SP_RESPONSE),
|
||||
SP_THREAD(SP_HIGH_PRIORITY),
|
||||
SP_THREAD(SP_LOW_PRIORITY),
|
||||
SP_THREAD(SP_NOTIFY_RESP),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sec_msg_hdr - Message header for secure messages and responses
|
||||
* @checksum: CRC of message for integrity checking
|
||||
*/
|
||||
union sec_msg_hdr {
|
||||
struct {
|
||||
uint16_t checksum;
|
||||
uint16_t reserved;
|
||||
} __packed;
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* k3_sec_proxy_verify_thread() - Verify thread status before
|
||||
* sending/receiving data
|
||||
* @spt: Pointer to Secure Proxy thread description
|
||||
* @dir: Direction of the thread
|
||||
*
|
||||
* Return: 0 if all goes well, else appropriate error message
|
||||
*/
|
||||
static inline int k3_sec_proxy_verify_thread(struct k3_sec_proxy_thread *spt,
|
||||
uint32_t dir)
|
||||
{
|
||||
/* Check for any errors already available */
|
||||
if (mmio_read_32(spt->rt + RT_THREAD_STATUS) &
|
||||
RT_THREAD_STATUS_ERROR_MASK) {
|
||||
ERROR("Thread %d is corrupted, cannot send data\n", spt->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Make sure thread is configured for right direction */
|
||||
if ((mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)
|
||||
!= (dir << SCFG_THREAD_CTRL_DIR_SHIFT)) {
|
||||
if (dir)
|
||||
ERROR("Trying to receive data on tx Thread %d\n",
|
||||
spt->id);
|
||||
else
|
||||
ERROR("Trying to send data on rx Thread %d\n",
|
||||
spt->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check the message queue before sending/receiving data */
|
||||
uint32_t tick_start = (uint32_t)read_cntpct_el0();
|
||||
uint32_t ticks_per_us = SYS_COUNTER_FREQ_IN_TICKS / 1000000;
|
||||
while (!(mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK)) {
|
||||
VERBOSE("Waiting for thread %d to clear\n", spt->id);
|
||||
if (((uint32_t)read_cntpct_el0() - tick_start) >
|
||||
(spm.desc.timeout_us * ticks_per_us)) {
|
||||
ERROR("Timeout waiting for thread %d to clear\n", spt->id);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* k3_sec_proxy_send() - Send data over a Secure Proxy thread
|
||||
* @id: Channel Identifier
|
||||
* @msg: Pointer to k3_sec_proxy_msg
|
||||
*
|
||||
* Return: 0 if all goes well, else appropriate error message
|
||||
*/
|
||||
int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg)
|
||||
{
|
||||
struct k3_sec_proxy_thread *spt = &spm.threads[id];
|
||||
union sec_msg_hdr secure_header;
|
||||
int num_words, trail_bytes, i, ret;
|
||||
uintptr_t data_reg;
|
||||
|
||||
ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX);
|
||||
if (ret) {
|
||||
ERROR("Thread %d verification failed (%d)\n", spt->id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check the message size */
|
||||
if (msg->len + sizeof(secure_header) > spm.desc.max_msg_size) {
|
||||
ERROR("Thread %d message length %lu > max msg size\n",
|
||||
spt->id, msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: Calculate checksum */
|
||||
secure_header.checksum = 0;
|
||||
|
||||
/* Send the secure header */
|
||||
data_reg = spm.desc.data_start_offset;
|
||||
mmio_write_32(spt->data + data_reg, secure_header.data);
|
||||
data_reg += sizeof(uint32_t);
|
||||
|
||||
/* Send whole words */
|
||||
num_words = msg->len / sizeof(uint32_t);
|
||||
for (i = 0; i < num_words; i++) {
|
||||
mmio_write_32(spt->data + data_reg, ((uint32_t *)msg->buf)[i]);
|
||||
data_reg += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/* Send remaining bytes */
|
||||
trail_bytes = msg->len % sizeof(uint32_t);
|
||||
if (trail_bytes) {
|
||||
uint32_t data_trail = 0;
|
||||
|
||||
i = msg->len - trail_bytes;
|
||||
while (trail_bytes--) {
|
||||
data_trail <<= 8;
|
||||
data_trail |= msg->buf[i++];
|
||||
}
|
||||
|
||||
mmio_write_32(spt->data + data_reg, data_trail);
|
||||
data_reg += sizeof(uint32_t);
|
||||
}
|
||||
/*
|
||||
* 'data_reg' indicates next register to write. If we did not already
|
||||
* write on tx complete reg(last reg), we must do so for transmit
|
||||
*/
|
||||
if (data_reg <= spm.desc.data_end_offset)
|
||||
mmio_write_32(spt->data + spm.desc.data_end_offset, 0);
|
||||
|
||||
VERBOSE("Message successfully sent on thread %ud\n", id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
|
||||
* @id: Channel Identifier
|
||||
* @msg: Pointer to k3_sec_proxy_msg
|
||||
*
|
||||
* Return: 0 if all goes well, else appropriate error message
|
||||
*/
|
||||
int k3_sec_proxy_recv(uint32_t id, struct k3_sec_proxy_msg *msg)
|
||||
{
|
||||
struct k3_sec_proxy_thread *spt = &spm.threads[id];
|
||||
union sec_msg_hdr secure_header;
|
||||
uintptr_t data_reg;
|
||||
int num_words, trail_bytes, i, ret;
|
||||
|
||||
ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX);
|
||||
if (ret) {
|
||||
ERROR("Thread %d verification failed (%d)\n", spt->id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read secure header */
|
||||
data_reg = spm.desc.data_start_offset;
|
||||
secure_header.data = mmio_read_32(spt->data + data_reg);
|
||||
data_reg += sizeof(uint32_t);
|
||||
|
||||
/* Read whole words */
|
||||
num_words = msg->len / sizeof(uint32_t);
|
||||
for (i = 0; i < num_words; i++) {
|
||||
((uint32_t *)msg->buf)[i] = mmio_read_32(spt->data + data_reg);
|
||||
data_reg += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/* Read remaining bytes */
|
||||
trail_bytes = msg->len % sizeof(uint32_t);
|
||||
if (trail_bytes) {
|
||||
uint32_t data_trail = mmio_read_32(spt->data + data_reg);
|
||||
data_reg += sizeof(uint32_t);
|
||||
|
||||
i = msg->len - trail_bytes;
|
||||
while (trail_bytes--) {
|
||||
msg->buf[i] = data_trail & 0xff;
|
||||
data_trail >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 'data_reg' indicates next register to read. If we did not already
|
||||
* read on rx complete reg(last reg), we must do so for receive
|
||||
*/
|
||||
if (data_reg <= spm.desc.data_end_offset)
|
||||
mmio_read_32(spt->data + spm.desc.data_end_offset);
|
||||
|
||||
/* TODO: Verify checksum */
|
||||
(void)secure_header.checksum;
|
||||
|
||||
VERBOSE("Message successfully received from thread %ud\n", id);
|
||||
|
||||
return 0;
|
||||
}
|
58
plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
Normal file
58
plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Texas Instruments K3 Secure Proxy Driver
|
||||
* Based on Linux and U-Boot implementation
|
||||
*
|
||||
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef K3_SEC_PROXY_H
|
||||
#define K3_SEC_PROXY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* enum k3_sec_proxy_chan_id - Secure Proxy thread IDs
|
||||
*
|
||||
* These the available IDs used in k3_sec_proxy_{send,recv}()
|
||||
*/
|
||||
enum k3_sec_proxy_chan_id {
|
||||
SP_NOTIFY = 0,
|
||||
SP_RESPONSE,
|
||||
SP_HIGH_PRIORITY,
|
||||
SP_LOW_PRIORITY,
|
||||
SP_NOTIFY_RESP,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct k3_sec_proxy_msg - Secure proxy message structure
|
||||
* @len: Length of data in the Buffer
|
||||
* @buf: Buffer pointer
|
||||
*
|
||||
* This is the structure for data used in k3_sec_proxy_{send,recv}()
|
||||
*/
|
||||
struct k3_sec_proxy_msg {
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* k3_sec_proxy_send() - Send data over a Secure Proxy thread
|
||||
* @id: Channel Identifier
|
||||
* @msg: Pointer to k3_sec_proxy_msg
|
||||
*
|
||||
* Return: 0 if all goes well, else appropriate error message
|
||||
*/
|
||||
int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg);
|
||||
|
||||
/**
|
||||
* k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
|
||||
* @id: Channel Identifier
|
||||
* @msg: Pointer to k3_sec_proxy_msg
|
||||
*
|
||||
* Return: 0 if all goes well, else appropriate error message
|
||||
*/
|
||||
int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg);
|
||||
|
||||
#endif /* K3_SEC_PROXY_H */
|
|
@ -21,6 +21,9 @@ const mmap_region_t plat_arm_mmap[] = {
|
|||
MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ PLAT_INCLUDES += \
|
|||
-I${PLAT_PATH}/include \
|
||||
-Iinclude/plat/arm/common/ \
|
||||
-Iinclude/plat/arm/common/aarch64/ \
|
||||
-I${PLAT_PATH}/common/drivers/sec_proxy \
|
||||
|
||||
K3_CONSOLE_SOURCES += \
|
||||
drivers/console/aarch64/console.S \
|
||||
|
@ -53,6 +54,9 @@ K3_PSCI_SOURCES += \
|
|||
plat/common/plat_psci_common.c \
|
||||
${PLAT_PATH}/common/k3_psci.c \
|
||||
|
||||
K3_SEC_PROXY_SOURCES += \
|
||||
${PLAT_PATH}/common/drivers/sec_proxy/sec_proxy.c \
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += \
|
||||
plat/arm/common/arm_common.c \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
|
@ -65,3 +69,4 @@ BL31_SOURCES += \
|
|||
${PLAT_PATH}/common/k3_topology.c \
|
||||
${K3_GIC_SOURCES} \
|
||||
${K3_PSCI_SOURCES} \
|
||||
${K3_SEC_PROXY_SOURCES} \
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
* runtime memory used, choose the smallest value needed to register the
|
||||
* required regions for each BL stage.
|
||||
*/
|
||||
#define MAX_MMAP_REGIONS 8
|
||||
#define MAX_MMAP_REGIONS 11
|
||||
|
||||
/*
|
||||
* Defines the total size of the address space in bytes. For example, for a 32
|
||||
|
@ -193,4 +193,14 @@
|
|||
#define K3_GICR_BASE 0x01880000
|
||||
#define K3_GICR_SIZE 0x100000
|
||||
|
||||
#define SEC_PROXY_DATA_BASE 0x32C00000
|
||||
#define SEC_PROXY_DATA_SIZE 0x80000
|
||||
#define SEC_PROXY_SCFG_BASE 0x32800000
|
||||
#define SEC_PROXY_SCFG_SIZE 0x80000
|
||||
#define SEC_PROXY_RT_BASE 0x32400000
|
||||
#define SEC_PROXY_RT_SIZE 0x80000
|
||||
|
||||
#define SEC_PROXY_TIMEOUT_US 1000000
|
||||
#define SEC_PROXY_MAX_MESSAGE_SIZE 56
|
||||
|
||||
#endif /* __PLATFORM_DEF_H__ */
|
||||
|
|
Loading…
Add table
Reference in a new issue