diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h index fe0a062aec94560e8e55677bca28c0f624f0c6e0..1bf58eda82230b6c9f7453cd0ba13d06d88fc1a7 100644 --- a/plat/ti/k3/board/generic/include/board_def.h +++ b/plat/ti/k3/board/generic/include/board_def.h @@ -32,4 +32,7 @@ #define PLAT_MAX_OFF_STATE U(2) #define PLAT_MAX_RET_STATE U(1) +#define PLAT_PROC_START_ID 32 +#define PLAT_PROC_DEVICE_START_ID 202 + #endif /* BOARD_DEF_H */ diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c new file mode 100644 index 0000000000000000000000000000000000000000..92414b9050f0ae1d82be1e5e08a28a3ffc7ce4be --- /dev/null +++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..facfd198833c82035047253f0d7c9437e2eac552 --- /dev/null +++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h @@ -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 + +/** + * 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 */ diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c new file mode 100644 index 0000000000000000000000000000000000000000..7ba0267dcc31ce38967ecdbc3660750878239c44 --- /dev/null +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -0,0 +1,1482 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include + +#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_is_response_ack() - Generic ACK/NACK message check + * + * @r: pointer to response buffer + * + * Return: true if the response was an ACK, else returns false + */ +static inline bool ti_sci_is_response_ack(void *r) +{ + struct ti_sci_msg_hdr *hdr = r; + + return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false; +} + +/** + * ti_sci_device_set_state() - Set device state + * + * @id: Device identifier + * @flags: flags to setup for the device + * @state: State to move the device to + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_device_state req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + req.state = state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_device_get_state() - Get device state + * + * @id: Device Identifier + * @clcnt: Pointer to Context Loss Count + * @resets: pointer to resets + * @p_state: pointer to p_state + * @c_state: pointer to c_state + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, uint32_t *resets, + uint8_t *p_state, uint8_t *c_state) +{ + struct ti_sci_msg_req_get_device_state req; + struct ti_sci_msg_resp_get_device_state resp; + + struct ti_sci_xfer xfer; + int ret; + + if (!clcnt && !resets && !p_state && !c_state) + return -EINVAL; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + if (clcnt) + *clcnt = resp.context_loss_count; + if (resets) + *resets = resp.resets; + if (p_state) + *p_state = resp.programmed_state; + if (c_state) + *c_state = resp.current_state; + + return 0; +} + +/** + * ti_sci_device_get() - Request for device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * NOTE: The request is for exclusive access for the processor. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get(uint32_t id) +{ + return ti_sci_device_set_state(id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_ON); +} + +/** + * ti_sci_device_idle() - Idle a device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_idle(uint32_t id) +{ + return ti_sci_device_set_state(id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_RETENTION); +} + +/** + * ti_sci_device_put() - Release a device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_put(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +/** + * ti_sci_device_is_valid() - Is the device valid + * + * @id: Device Identifier + * + * Return: 0 if all goes well and the device ID is valid, else return + * appropriate error + */ +int ti_sci_device_is_valid(uint32_t id) +{ + uint8_t unused; + + /* check the device state which will also tell us if the ID is valid */ + return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused); +} + +/** + * ti_sci_device_get_clcnt() - Get context loss counter + * + * @id: Device Identifier + * @count: Pointer to Context Loss counter to populate + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count) +{ + return ti_sci_device_get_state(id, count, NULL, NULL, NULL); +} + +/** + * ti_sci_device_is_idle() - Check if the device is requested to be idle + * + * @id: Device Identifier + * @r_state: true if requested to be idle + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_idle(uint32_t id, bool *r_state) +{ + int ret; + uint8_t state; + + if (!r_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL); + if (ret) + return ret; + + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); + + return 0; +} + +/** + * ti_sci_device_is_stop() - Check if the device is requested to be stopped + * + * @id: Device Identifier + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); + + return 0; +} + +/** + * ti_sci_device_is_on() - Check if the device is requested to be ON + * + * @id: Device Identifier + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); + + return 0; +} + +/** + * ti_sci_device_is_trans() - Check if the device is currently transitioning + * + * @id: Device Identifier + * @curr_state: true if currently transitioning + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_trans(uint32_t id, bool *curr_state) +{ + int ret; + uint8_t state; + + if (!curr_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state); + if (ret) + return ret; + + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); + + return 0; +} + +/** + * ti_sci_device_set_resets() - Set resets for device managed by TISCI + * + * @id: Device Identifier + * @reset_state: Device specific reset bit field + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state) +{ + struct ti_sci_msg_req_set_device_resets req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + req.resets = reset_state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_device_get_resets() - Get reset state for device managed by TISCI + * + * @id: Device Identifier + * @reset_state: Pointer to reset state to populate + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state) +{ + return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL); +} + +/** + * ti_sci_clock_set_state() - Set clock state helper + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request, + * Each device has its own set of clock inputs, This indexes + * which clock input to modify + * @flags: Header flags as needed + * @state: State to request for the clock + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id, + uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_clock_state req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.request_state = state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_clock_get_state() - Get clock state helper + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @programmed_state: State requested for clock to move to + * @current_state: State that the clock is currently in + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id, + uint8_t *programmed_state, + uint8_t *current_state) +{ + struct ti_sci_msg_req_get_clock_state req; + struct ti_sci_msg_resp_get_clock_state resp; + + struct ti_sci_xfer xfer; + int ret; + + if (!programmed_state && !current_state) + return -EINVAL; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + if (programmed_state) + *programmed_state = resp.programmed_state; + if (current_state) + *current_state = resp.current_state; + + return 0; +} + +/** + * ti_sci_clock_get() - Get control of a clock from TI SCI + + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @needs_ssc: 'true' iff Spread Spectrum clock is desired + * @can_change_freq: 'true' iff frequency change is desired + * @enable_input_term: 'true' iff input termination is desired + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, + bool needs_ssc, bool can_change_freq, + bool enable_input_term) +{ + uint32_t flags = 0; + + flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; + flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; + flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; + + return ti_sci_clock_set_state(dev_id, clk_id, flags, + MSG_CLOCK_SW_STATE_REQ); +} + +/** + * ti_sci_clock_idle() - Idle a clock which is in our control + + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id) +{ + return ti_sci_clock_set_state(dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_UNREQ); +} + +/** + * ti_sci_clock_put() - Release a clock from our control + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id) +{ + return ti_sci_clock_set_state(dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_AUTO); +} + +/** + * ti_sci_clock_is_auto() - Is the clock being auto managed + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is auto managed + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state) +{ + uint8_t state = 0; + int ret; + + if (!req_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL); + if (ret) + return ret; + + *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); + + return 0; +} + +/** + * ti_sci_clock_is_on() - Is the clock ON + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); + + return 0; +} + +/** + * ti_sci_clock_is_off() - Is the clock OFF + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); + + return 0; +} + +/** + * ti_sci_clock_set_parent() - Set the clock source of a specific device clock + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Parent clock identifier to set + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id) +{ + struct ti_sci_msg_req_set_clock_parent req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.parent_id = parent_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_clock_get_parent() - Get current parent clock source + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Current clock parent + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id) +{ + struct ti_sci_msg_req_get_clock_parent req; + struct ti_sci_msg_resp_get_clock_parent resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + *parent_id = resp.parent_id; + + return 0; +} + +/** + * ti_sci_clock_get_num_parents() - Get num parents of the current clk source + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @num_parents: Returns he number of parents to the current clock. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents) +{ + struct ti_sci_msg_req_get_clock_num_parents req; + struct ti_sci_msg_resp_get_clock_num_parents resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + *num_parents = resp.num_parents; + + return 0; +} + +/** + * ti_sci_clock_get_match_freq() - Find a good match for frequency + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @match_freq: Frequency match in Hz response. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq, uint64_t *match_freq) +{ + struct ti_sci_msg_req_query_clock_freq req; + struct ti_sci_msg_resp_query_clock_freq resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + *match_freq = resp.freq_hz; + + return 0; +} + +/** + * ti_sci_clock_set_freq() - Set a frequency for clock + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq, + uint64_t target_freq, uint64_t max_freq) +{ + struct ti_sci_msg_req_set_clock_freq req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_clock_get_freq() - Get current frequency + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @freq: Currently frequency in Hz + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq) +{ + struct ti_sci_msg_req_get_clock_freq req; + struct ti_sci_msg_resp_get_clock_freq resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + *freq = resp.freq_hz; + + return 0; +} + +/** + * ti_sci_core_reboot() - Command to request system reset + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_core_reboot(void) +{ + struct ti_sci_msg_req_reboot req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &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; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_request() - Request a physical processor control + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_request(uint8_t proc_id) +{ + struct ti_sci_msg_req_proc_request req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_release() - Release a physical processor control + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_release(uint8_t proc_id) +{ + struct ti_sci_msg_req_proc_release req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_handover() - Handover a physical processor control to a host in + * the processor's access control list. + * + * @proc_id: Processor ID this request is for + * @host_id: Host ID to get the control of the processor + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id) +{ + struct ti_sci_msg_req_proc_handover req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.host_id = host_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags + * + * @proc_id: Processor ID this request is for + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, + uint32_t config_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_config req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; + req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + req.config_flags_set = config_flags_set; + req.config_flags_clear = config_flags_clear; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags + * + * @proc_id: Processor ID this request is for + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, + uint32_t control_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_ctrl req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.control_flags_set = control_flags_set; + req.control_flags_clear = control_flags_clear; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the + * processor configuration flags + * + * @proc_id: Processor ID this request is for + * @cert_addr: Memory address at which payload image certificate is located + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr) +{ + struct ti_sci_msg_req_proc_auth_boot_image req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMIAGE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_proc_get_boot_status() - Get the processor boot status + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, + uint32_t *ctrl_flags, + uint32_t *sts_flags) +{ + struct ti_sci_msg_req_get_proc_boot_status req; + struct ti_sci_msg_resp_get_proc_boot_status resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (!ti_sci_is_response_ack(&resp)) + return -ENODEV; + + *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) | + (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) & + TISCI_ADDR_HIGH_MASK); + *cfg_flags = resp.config_flags; + *ctrl_flags = resp.control_flags; + *sts_flags = resp.status_flags; + + 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; +} diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h new file mode 100644 index 0000000000000000000000000000000000000000..e40ad6bc51c34a6cf9301b22c166e9f5035a63e1 --- /dev/null +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h @@ -0,0 +1,208 @@ +/* + * 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 + +#include +#include + +/** + * Device control operations + * + * - ti_sci_device_set_state - Set device state helper + * @flags: flags to setup for the device + * @state: State to move the device to + * - ti_sci_device_get_state - Get device state helper + * @clcnt: Pointer to Context Loss Count + * @resets: pointer to resets + * @p_state: pointer to p_state + * @c_state: pointer to c_state + * - ti_sci_device_get - command to request for device managed by TISCI + * - ti_sci_device_idle - Command to idle a device managed by TISCI + * - ti_sci_device_put - command to release a device managed by TISCI + * - ti_sci_device_is_valid - Is the device valid + * - ti_sci_device_get_clcnt - Get context loss counter + * @count: Pointer to Context Loss counter to populate + * - ti_sci_device_is_idle - Check if the device is requested to be idle + * @r_state: true if requested to be idle + * - ti_sci_device_is_stop - Check if the device is requested to be stopped + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped. + * - ti_sci_device_is_on - Check if the device is requested to be ON + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * - ti_sci_device_is_trans - Check if the device is currently transitioning + * @curr_state: true if currently transitioning. + * - ti_sci_device_set_resets - Command to set resets for + * device managed by TISCI + * @reset_state: Device specific reset bit field + * - ti_sci_device_get_resets - Get reset state for device managed by TISCI + * @reset_state: Pointer to reset state to populate + * + * NOTE: for all these functions, the following are generic in nature: + * @id: Device Identifier + * Returns 0 for successful request, else returns corresponding error message. + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + */ +int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state); +int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, uint32_t *resets, + uint8_t *p_state, uint8_t *c_state); +int ti_sci_device_get(uint32_t id); +int ti_sci_device_idle(uint32_t id); +int ti_sci_device_put(uint32_t id); +int ti_sci_device_is_valid(uint32_t id); +int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count); +int ti_sci_device_is_idle(uint32_t id, bool *r_state); +int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state); +int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state); +int ti_sci_device_is_trans(uint32_t id, bool *curr_state); +int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state); +int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state); + +/** + * Clock control operations + * + * - ti_sci_clock_set_state - Set clock state helper + * @flags: Header flags as needed + * @state: State to request for the clock. + * - ti_sci_clock_get_state - Get clock state helper + * @programmed_state: State requested for clock to move to + * @current_state: State that the clock is currently in + * - ti_sci_clock_get - Get control of a clock from TI SCI + * @needs_ssc: 'true' iff Spread Spectrum clock is desired + * @can_change_freq: 'true' iff frequency change is desired + * @enable_input_term: 'true' iff input termination is desired + * - ti_sci_clock_idle - Idle a clock which is in our control + * - ti_sci_clock_put - Release a clock from our control + * - ti_sci_clock_is_auto - Is the clock being auto managed + * @req_state: state indicating if the clock is auto managed + * - ti_sci_clock_is_on - Is the clock ON + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * - ti_sci_clock_is_off - Is the clock OFF + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * - ti_sci_clock_set_parent - Set the clock source of a specific device clock + * @parent_id: Parent clock identifier to set + * - ti_sci_clock_get_parent - Get current parent clock source + * @parent_id: Current clock parent + * - ti_sci_clock_get_num_parents - Get num parents of the current clk source + * @num_parents: Returns he number of parents to the current clock. + * - ti_sci_clock_get_match_freq - Find a good match for frequency + * @match_freq: Frequency match in Hz response. + * - ti_sci_clock_set_freq - Set a frequency for clock + * - ti_sci_clock_get_freq - Get current frequency + * @freq: Currently frequency in Hz + * + * NOTE: for all these functions, the following are generic in nature: + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * Returns 0 for successful request, else returns corresponding error message. + * + * Request for the clock - NOTE: the client MUST maintain integrity of + * usage count by balancing get_clock with put_clock. No refcounting is + * managed by driver for that purpose. + */ +int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id, + uint32_t flags, uint8_t state); +int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id, + uint8_t *programmed_state, uint8_t *current_state); +int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, + bool needs_ssc, bool can_change_freq, + bool enable_input_term); +int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id); +int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id); +int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, + bool *req_state); +int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state); +int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state); +int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, + uint8_t parent_id); +int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, + uint8_t *parent_id); +int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents); +int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq, uint64_t *match_freq); +int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq); +int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq); + +/** + * Core control operations + * + * - ti_sci_core_reboot() - Command to request system reset + * + * Return: 0 if all went well, else returns appropriate error value. + */ +int ti_sci_core_reboot(void); + +/** + * Processor control operations + * + * - ti_sci_proc_request - Command to request a physical processor control + * - ti_sci_proc_release - Command to release a physical processor control + * - ti_sci_proc_handover - Command to handover a physical processor control to + * a host in the processor's access control list. + * @host_id: Host ID to get the control of the processor + * - ti_sci_proc_set_boot_cfg - Command to set the processor boot configuration flags + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared. + * - ti_sci_proc_set_boot_ctrl - Command to set the processor boot control flags + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * - ti_sci_proc_auth_boot_image - Command to authenticate and load the image + * and then set the processor configuration flags. + * @cert_addr: Memory address at which payload image certificate is located. + * - ti_sci_proc_get_boot_status - Command to get the processor boot status + * + * NOTE: for all these functions, the following are generic in nature: + * @proc_id: Processor ID + * Returns 0 for successful request, else returns corresponding error message. + */ +int ti_sci_proc_request(uint8_t proc_id); +int ti_sci_proc_release(uint8_t proc_id); +int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id); +int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, + uint32_t config_flags_clear); +int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, + uint32_t control_flags_clear); +int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr); +int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, + uint32_t *ctrl_flags, + uint32_t *sts_flags); + +/** + * ti_sci_init() - Basic initialization + * + * Return: 0 if all goes good, else appropriate error message. + */ +int ti_sci_init(void); + +#endif /* __TI_SCI_H */ diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h new file mode 100644 index 0000000000000000000000000000000000000000..2c4b23fcbdd7aa3f25f8fb89079e1e1ad0d6c923 --- /dev/null +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -0,0 +1,650 @@ +/* + * Texas Instruments System Control Interface (TISCI) Protocol + * + * Communication protocol with TI SCI hardware + * The system works in a message response protocol + * See: http://processors.wiki.ti.com/index.php/TISCI for details + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TI_SCI_PROTOCOL_H +#define __TI_SCI_PROTOCOL_H + +#include + +/* Generic Messages */ +#define TI_SCI_MSG_ENABLE_WDT 0x0000 +#define TI_SCI_MSG_WAKE_RESET 0x0001 +#define TI_SCI_MSG_VERSION 0x0002 +#define TI_SCI_MSG_WAKE_REASON 0x0003 +#define TI_SCI_MSG_GOODBYE 0x0004 +#define TI_SCI_MSG_SYS_RESET 0x0005 + +/* Device requests */ +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 +#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 +#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 + +/* Clock requests */ +#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 +#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 +#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102 +#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103 +#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104 +#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c +#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e + +/* Processor Control Messages */ +#define TISCI_MSG_PROC_REQUEST 0xc000 +#define TISCI_MSG_PROC_RELEASE 0xc001 +#define TISCI_MSG_PROC_HANDOVER 0xc005 +#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100 +#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101 +#define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120 +#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 + +/** + * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses + * @type: Type of messages: One of TI_SCI_MSG* values + * @host: Host of the message + * @seq: Message identifier indicating a transfer sequence + * @flags: Flag for the message + */ +struct ti_sci_msg_hdr { + uint16_t type; + uint8_t host; + uint8_t seq; +#define TI_SCI_MSG_FLAG(val) (1 << (val)) +#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) +#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) +#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) + /* Additional Flags */ + uint32_t flags; +} __packed; + +/** + * struct ti_sci_msg_resp_version - Response for a message + * @hdr: Generic header + * @firmware_description: String describing the firmware + * @firmware_revision: Firmware revision + * @abi_major: Major version of the ABI that firmware supports + * @abi_minor: Minor version of the ABI that firmware supports + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to a generic message with message type TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_resp_version { + struct ti_sci_msg_hdr hdr; +#define FIRMWARE_DESCRIPTION_LENGTH 32 + char firmware_description[FIRMWARE_DESCRIPTION_LENGTH]; + uint16_t firmware_revision; + uint8_t abi_major; + uint8_t abi_minor; +} __packed; + +/** + * struct ti_sci_msg_req_reboot - Reboot the SoC + * @hdr: Generic Header + * + * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_reboot { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @reserved: Reserved space in message, must be 0 for backward compatibility + * @state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + uint32_t id; + uint32_t reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + uint8_t state; +} __packed; + +/** + * struct ti_sci_msg_req_get_device_state - Request to get device. + * @hdr: Generic header + * @id: Device Identifier + * + * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state + * information + */ +struct ti_sci_msg_req_get_device_state { + struct ti_sci_msg_hdr hdr; + uint32_t id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_device_state - Response to get device request. + * @hdr: Generic header + * @context_loss_count: Indicates how many times the device has lost context. A + * driver can use this monotonic counter to determine if the device has + * lost context since the last time this message was exchanged. + * @resets: Programmed state of the reset lines. + * @programmed_state: The state as programmed by set_device. + * - Uses the MSG_DEVICE_SW_* macros + * @current_state: The actual state of the hardware. + * + * Response to request TI_SCI_MSG_GET_DEVICE_STATE. + */ +struct ti_sci_msg_resp_get_device_state { + struct ti_sci_msg_hdr hdr; + uint32_t context_loss_count; + uint32_t resets; + uint8_t programmed_state; +#define MSG_DEVICE_HW_STATE_OFF 0 +#define MSG_DEVICE_HW_STATE_ON 1 +#define MSG_DEVICE_HW_STATE_TRANS 2 + uint8_t current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_resets - Set the desired resets + * configuration of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @resets: A bit field of resets for the device. The meaning, behavior, + * and usage of the reset flags are device specific. 0 for a bit + * indicates releasing the reset represented by that bit while 1 + * indicates keeping it held. + * + * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_resets { + struct ti_sci_msg_hdr hdr; + uint32_t id; + uint32_t resets; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state + * @hdr: Generic Header, Certain flags can be set specific to the clocks: + * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified + * via spread spectrum clocking. + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's + * frequency to be changed while it is running so long as it + * is within the min/max limits. + * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this + * is only applicable to clock inputs on the SoC pseudo-device. + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @request_state: Request the state for the clock to be set to. + * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock, + * it can be disabled, regardless of the state of the device + * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to + * automatically manage the state of this clock. If the device + * is enabled, then the clock is enabled. If the device is set + * to off or retention, then the clock is internally set as not + * being required by the device.(default) + * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled, + * regardless of the state of the device. + * + * Normally, all required clocks are managed by TISCI entity, this is used + * only for specific control *IF* required. Auto managed state is + * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote + * will explicitly control. + * + * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic + * ACK or NACK message. + */ +struct ti_sci_msg_req_set_clock_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +#define MSG_CLOCK_SW_STATE_UNREQ 0 +#define MSG_CLOCK_SW_STATE_AUTO 1 +#define MSG_CLOCK_SW_STATE_REQ 2 + uint8_t request_state; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_state - Request for clock state + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get state of. + * + * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state + * of the clock + */ +struct ti_sci_msg_req_get_clock_state { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_state - Response to get clock state + * @hdr: Generic Header + * @programmed_state: Any programmed state of the clock. This is one of + * MSG_CLOCK_SW_STATE* values. + * @current_state: Current state of the clock. This is one of: + * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready + * MSG_CLOCK_HW_STATE_READY: Clock is ready + * + * Response to TI_SCI_MSG_GET_CLOCK_STATE. + */ +struct ti_sci_msg_resp_get_clock_state { + struct ti_sci_msg_hdr hdr; + uint8_t programmed_state; +#define MSG_CLOCK_HW_STATE_NOT_READY 0 +#define MSG_CLOCK_HW_STATE_READY 1 + uint8_t current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_parent - Set the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: The new clock parent is selectable by an index via this + * parameter. + * + * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic + * ACK / NACK message. + */ +struct ti_sci_msg_req_set_clock_parent { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; + uint8_t parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_parent - Get the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get the parent for. + * + * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information + */ +struct ti_sci_msg_req_get_clock_parent { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent + * @hdr: Generic Header + * @parent_id: The current clock parent + * + * Response to TI_SCI_MSG_GET_CLOCK_PARENT. + */ +struct ti_sci_msg_resp_get_clock_parent { + struct ti_sci_msg_hdr hdr; + uint8_t parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents + * @hdr: Generic header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * This request provides information about how many clock parent options + * are available for a given clock to a device. This is typically used + * for input clocks. + * + * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents + * @hdr: Generic header + * @num_parents: Number of clock parents + * + * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS + */ +struct ti_sci_msg_resp_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + uint8_t num_parents; +} __packed; + +/** + * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. A frequency will be found + * as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested frequency within provided range and responds with + * result message. + * + * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message, + * or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_query_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query + * @hdr: Generic Header + * @freq_hz: Frequency that is the best match in Hz. + * + * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request + * cannot be satisfied, the message will be of type NACK. + */ +struct ti_sci_msg_resp_query_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. The clock will be programmed + * at a rate as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested range and responds with success/failure message. + * + * This sets the desired frequency for a clock within an allowable + * range. This message will fail on an enabled clock unless + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, + * if other clocks have their frequency modified due to this message, + * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. + * + * Calling set frequency on a clock input to the SoC pseudo-device will + * inform the PMMC of that clock's frequency. Setting a frequency of + * zero will indicate the clock is disabled. + * + * Calling set frequency on clock outputs from the SoC pseudo-device will + * function similarly to setting the clock frequency on a device. + * + * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In some cases, clock frequencies are configured by host. + * + * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency + * that the clock is currently at. + */ +struct ti_sci_msg_req_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request + * @hdr: Generic Header + * @freq_hz: Frequency that the clock is currently on, in Hz. + * + * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ. + */ +struct ti_sci_msg_resp_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +#define TISCI_ADDR_LOW_MASK 0x00000000ffffffff +#define TISCI_ADDR_HIGH_MASK 0xffffffff00000000 +#define TISCI_ADDR_HIGH_SHIFT 32 + +/** + * struct ti_sci_msg_req_proc_request - Request a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_REQUEST, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_request { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_release - Release a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_RELEASE, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_release { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_handover - Handover a processor to a host + * + * @hdr: Generic Header + * @processor_id: ID of processor + * @host_id: New Host we want to give control to + * + * Request type is TISCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_handover { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint8_t host_id; +} __packed; + +/* A53 Config Flags */ +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPIDEN 0x00000004 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPNIDEN 0x00000008 +#define PROC_BOOT_CFG_FLAG_ARMV8_AARCH32 0x00000100 + +/* R5 Config Flags */ +#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100 +#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200 +#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400 +#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800 +#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 +#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 + +/** + * struct ti_sci_msg_req_set_proc_boot_config - Set Processor boot configuration + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CONFIG, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_proc_boot_config { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags_set; + uint32_t config_flags_clear; +} __packed; + +/* R5 Control Flags */ +#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 + +/** + * struct ti_sci_msg_req_set_proc_boot_ctrl - Set Processor boot control flags + * @hdr: Generic Header + * @processor_id: ID of processor + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CTRL, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_proc_boot_ctrl { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t control_flags_set; + uint32_t control_flags_clear; +} __packed; + +/** + * struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image + * @hdr: Generic Header + * @processor_id: ID of processor + * @cert_addr_low: Lower 32bit (Little Endian) of certificate + * @cert_addr_high: Higher 32bit (Little Endian) of certificate + * + * Request type is TISCI_MSG_PROC_AUTH_BOOT_IMAGE, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_proc_auth_boot_image { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t cert_addr_low; + uint32_t cert_addr_high; +} __packed; + +/** + * struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_GET_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/* ARMv8 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002 + +/* R5 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 +#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 + +/** + * \brief Processor Status Response + * struct ti_sci_msg_resp_get_proc_boot_status - Processor boot status response + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags: Optional Processor specific Config Flags set. + * @control_flags: Optional Processor specific Control Flags. + * @status_flags: Optional Processor specific Status Flags set. + * + * Response to TISCI_MSG_GET_PROC_BOOT_STATUS. + */ +struct ti_sci_msg_resp_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags; + uint32_t control_flags; + uint32_t status_flags; +} __packed; + +#endif /* __TI_SCI_PROTOCOL_H */ diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c index 3de57a7c4f61786cb435f0917115838123426320..2d4d1c2783e7aa651fb29806a1ae3cd50405cbde 100644 --- a/plat/ti/k3/common/k3_bl31_setup.c +++ b/plat/ti/k3/common/k3_bl31_setup.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Table of regions to map using the MMU */ const mmap_region_t plat_arm_mmap[] = { @@ -21,6 +22,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 */ } }; @@ -118,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) diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c index 4d6428b5c61903b9211ec04c0af1abb476de565c..4c501f571e75a854c4f92970196c1e07e53f6a02 100644 --- a/plat/ti/k3/common/k3_psci.c +++ b/plat/ti/k3/common/k3_psci.c @@ -9,8 +9,11 @@ #include #include #include +#include #include +#include + #define STUB() ERROR("stub %s called\n", __func__) uintptr_t k3_sec_entrypoint; @@ -33,9 +36,40 @@ static void k3_cpu_standby(plat_local_state_t cpu_state) static int k3_pwr_domain_on(u_register_t mpidr) { - sev(); - - /* TODO: Indicate to System firmware about powering up */ + int core_id, proc, device, ret; + + core_id = plat_core_pos_by_mpidr(mpidr); + if (core_id < 0) { + ERROR("Could not get target core id: %d\n", core_id); + return PSCI_E_INTERN_FAIL; + } + + proc = PLAT_PROC_START_ID + core_id; + device = PLAT_PROC_DEVICE_START_ID + core_id; + + ret = ti_sci_proc_request(proc); + if (ret) { + ERROR("Request for processor failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + ret = ti_sci_proc_set_boot_cfg(proc, k3_sec_entrypoint, 0, 0); + if (ret) { + ERROR("Request to set core boot address failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + ret = ti_sci_device_get(device); + if (ret) { + ERROR("Request to start core failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + ret = ti_sci_proc_release(proc); + if (ret) { + /* this is not fatal */ + WARN("Could not release processor control: %d\n", ret); + } return PSCI_E_SUCCESS; } @@ -58,8 +92,8 @@ void k3_pwr_domain_on_finish(const psci_power_state_t *target_state) static void __dead2 k3_system_reset(void) { - /* TODO: Indicate to System firmware about system reset */ - STUB(); + /* Send the system reset request to system firmware */ + ti_sci_core_reboot(); while (true) wfi(); diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk index 7cb6eb78ef982dd97311486752309576c6c8cfbf..446d8afba2b8d6af68095458043ebafb3cbe5158 100644 --- a/plat/ti/k3/common/plat_common.mk +++ b/plat/ti/k3/common/plat_common.mk @@ -36,6 +36,8 @@ PLAT_INCLUDES += \ -I${PLAT_PATH}/include \ -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 \ @@ -53,6 +55,12 @@ 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 \ + +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 \ @@ -65,3 +73,5 @@ BL31_SOURCES += \ ${PLAT_PATH}/common/k3_topology.c \ ${K3_GIC_SOURCES} \ ${K3_PSCI_SOURCES} \ + ${K3_SEC_PROXY_SOURCES} \ + ${K3_TI_SCI_SOURCES} \ diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h index ebc9c477091a96e413f7d2afa00938295b3aed63..ab0739e90b63299e385faee2994c1b5e1ebef5c8 100644 --- a/plat/ti/k3/include/platform_def.h +++ b/plat/ti/k3/include/platform_def.h @@ -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,17 @@ #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 + +#define TI_SCI_HOST_ID 10 +#define TI_SCI_MAX_MESSAGE_SIZE 52 + #endif /* __PLATFORM_DEF_H__ */