Commit b5c2e1c4 authored by Andrew F. Davis's avatar Andrew F. Davis
Browse files

ti: k3: drivers: Add support for TI System Control Interface protocol



Texas Instrument's System Control Interface (TI-SCI) Message Protocol
is used in Texas Instrument's System on Chip (SoC) such as those
in K3 family AM654x SoCs to communicate between various compute
processors with a central system controller entity.

TI-SCI message protocol provides support for management of various
hardware entities within the SoC. Add support driver to allow
communication with system controller entity within the SoC.
Signed-off-by: default avatarAndrew F. Davis <afd@ti.com>
Reviewed-by: default avatarAndreas Dannenberg <dannenberg@ti.com>
parent d76fdd33
/*
* Texas Instruments System Control Interface 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 <debug.h>
#include <errno.h>
#include <platform_def.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <sec_proxy.h>
#include "ti_sci_protocol.h"
#include "ti_sci.h"
/**
* struct ti_sci_desc - Description of SoC integration
* @host_id: Host identifier representing the compute entity
* @max_msg_size: Maximum size of data per message that can be handled
*/
struct ti_sci_desc {
uint8_t host_id;
int max_msg_size;
};
/**
* struct ti_sci_info - Structure representing a TI SCI instance
* @desc: SoC description for this instance
* @seq: Seq id used for verification for tx and rx message
*/
struct ti_sci_info {
const struct ti_sci_desc desc;
uint8_t seq;
};
static struct ti_sci_info info = {
.desc = {
.host_id = TI_SCI_HOST_ID,
.max_msg_size = TI_SCI_MAX_MESSAGE_SIZE,
},
.seq = 0x0a,
};
/**
* struct ti_sci_xfer - Structure representing a message flow
* @tx_message: Transmit message
* @rx_message: Receive message
*/
struct ti_sci_xfer {
struct k3_sec_proxy_msg tx_message;
struct k3_sec_proxy_msg rx_message;
};
/**
* ti_sci_setup_one_xfer() - Setup one message type
*
* @msg_type: Message type
* @msg_flags: Flag to set for the message
* @tx_buf: Buffer to be sent to mailbox channel
* @tx_message_size: transmit message size
* @rx_buf: Buffer to be received from mailbox channel
* @rx_message_size: receive message size
*
* Helper function which is used by various command functions that are
* exposed to clients of this driver for allocating a message traffic event.
*
* Return: 0 if all goes well, else appropriate error message
*/
static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
void *tx_buf,
size_t tx_message_size,
void *rx_buf,
size_t rx_message_size,
struct ti_sci_xfer *xfer)
{
struct ti_sci_msg_hdr *hdr;
/* Ensure we have sane transfer sizes */
if (rx_message_size > info.desc.max_msg_size ||
tx_message_size > info.desc.max_msg_size ||
rx_message_size < sizeof(*hdr) ||
tx_message_size < sizeof(*hdr))
return -ERANGE;
info.seq++;
hdr = (struct ti_sci_msg_hdr *)tx_buf;
hdr->seq = info.seq;
hdr->type = msg_type;
hdr->host = info.desc.host_id;
hdr->flags = msg_flags;
xfer->tx_message.buf = tx_buf;
xfer->tx_message.len = tx_message_size;
xfer->rx_message.buf = rx_buf;
xfer->rx_message.len = rx_message_size;
return 0;
}
/**
* ti_sci_get_response() - Receive response from mailbox channel
*
* @xfer: Transfer to initiate and wait for response
* @chan: Channel to receive the response
*
* Return: 0 if all goes well, else appropriate error message
*/
static inline int ti_sci_get_response(struct ti_sci_xfer *xfer,
enum k3_sec_proxy_chan_id chan)
{
struct k3_sec_proxy_msg *msg = &xfer->rx_message;
struct ti_sci_msg_hdr *hdr;
int ret;
/* Receive the response */
ret = k3_sec_proxy_recv(chan, msg);
if (ret) {
ERROR("Message receive failed (%d)\n", ret);
return ret;
}
/* msg is updated by Secure Proxy driver */
hdr = (struct ti_sci_msg_hdr *)msg->buf;
/* Sanity check for message response */
if (hdr->seq != info.seq) {
ERROR("Message for %d is not expected\n", hdr->seq);
return -EINVAL;
}
if (msg->len > info.desc.max_msg_size) {
ERROR("Unable to handle %lu xfer (max %d)\n",
msg->len, info.desc.max_msg_size);
return -EINVAL;
}
return 0;
}
/**
* ti_sci_do_xfer() - Do one transfer
*
* @xfer: Transfer to initiate and wait for response
*
* Return: 0 if all goes well, else appropriate error message
*/
static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
{
struct k3_sec_proxy_msg *msg = &xfer->tx_message;
int ret;
/* Send the message */
ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, msg);
if (ret) {
ERROR("Message sending failed (%d)\n", ret);
return ret;
}
ret = ti_sci_get_response(xfer, SP_RESPONSE);
if (ret) {
ERROR("Failed to get response (%d)\n", ret);
return ret;
}
return 0;
}
/**
* ti_sci_get_revision() - Get the revision of the SCI entity
*
* Updates the SCI information in the internal data structure.
*
* Return: 0 if all goes well, else appropriate error message
*/
int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
{
struct ti_sci_msg_hdr hdr;
struct ti_sci_xfer xfer;
int ret;
ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
&hdr, sizeof(hdr),
rev_info, sizeof(*rev_info),
&xfer);
if (ret) {
ERROR("Message alloc failed (%d)\n", ret);
return ret;
}
ret = ti_sci_do_xfer(&xfer);
if (ret) {
ERROR("Transfer send failed (%d)\n", ret);
return ret;
}
return 0;
}
/**
* ti_sci_init() - Basic initialization
*
* Return: 0 if all goes well, else appropriate error message
*/
int ti_sci_init(void)
{
struct ti_sci_msg_resp_version rev_info;
int ret;
ret = ti_sci_get_revision(&rev_info);
if (ret) {
ERROR("Unable to communicate with control firmware (%d)\n", ret);
return ret;
}
INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
rev_info.abi_major, rev_info.abi_minor,
rev_info.firmware_revision,
rev_info.firmware_description);
return 0;
}
/*
* Texas Instruments System Control Interface API
* Based on Linux and U-Boot implementation
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __TI_SCI_H
#define __TI_SCI_H
/**
* ti_sci_init() - Basic initialization
*
* Return: 0 if all goes good, else appropriate error message.
*/
int ti_sci_init(void);
#endif /* __TI_SCI_H */
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include <platform_def.h>
#include <k3_gicv3.h>
#include <string.h>
#include <ti_sci.h>
/* Table of regions to map using the MMU */
const mmap_region_t plat_arm_mmap[] = {
......@@ -121,6 +122,8 @@ void bl31_platform_setup(void)
{
k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE);
k3_gic_init();
ti_sci_init();
}
void platform_mem_init(void)
......
......@@ -37,6 +37,7 @@ PLAT_INCLUDES += \
-Iinclude/plat/arm/common/ \
-Iinclude/plat/arm/common/aarch64/ \
-I${PLAT_PATH}/common/drivers/sec_proxy \
-I${PLAT_PATH}/common/drivers/ti_sci \
K3_CONSOLE_SOURCES += \
drivers/console/aarch64/console.S \
......@@ -57,6 +58,9 @@ K3_PSCI_SOURCES += \
K3_SEC_PROXY_SOURCES += \
${PLAT_PATH}/common/drivers/sec_proxy/sec_proxy.c \
K3_TI_SCI_SOURCES += \
${PLAT_PATH}/common/drivers/ti_sci/ti_sci.c \
PLAT_BL_COMMON_SOURCES += \
plat/arm/common/arm_common.c \
lib/cpus/aarch64/cortex_a53.S \
......@@ -70,3 +74,4 @@ BL31_SOURCES += \
${K3_GIC_SOURCES} \
${K3_PSCI_SOURCES} \
${K3_SEC_PROXY_SOURCES} \
${K3_TI_SCI_SOURCES} \
......@@ -203,4 +203,7 @@
#define SEC_PROXY_TIMEOUT_US 1000000
#define SEC_PROXY_MAX_MESSAGE_SIZE 56
#define TI_SCI_HOST_ID 10
#define TI_SCI_MAX_MESSAGE_SIZE 52
#endif /* __PLATFORM_DEF_H__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment