From a78cd9121b5bae2b0cea254303044a8677698657 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 21 Aug 2019 11:17:46 +0530 Subject: [PATCH] tisci: Add support for handling clocks Add support for following tisci commands for handling clocks: - ti_sci_cmd_get_clk - ti_sci_cmd_put_clk - ti_sci_cmd_get_clk_state - ti_sci_cmd_set_clk_freq - ti_sci_cmd_get_clk_freq Signed-off-by: Lokesh Vutla --- Makefile | 3 +- common/tisci/tisci_clock.c | 174 +++++++++++++++++++++++++++++++++++++ include/tisci.h | 6 ++ include/tisci_protocol.h | 74 ++++++++++++++++ 4 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 common/tisci/tisci_clock.c diff --git a/Makefile b/Makefile index b06a829..6171a12 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,8 @@ COMMONSOURCES=\ common/socinfo.c \ common/sec_proxy.c \ common/tisci/tisci_core.c \ - common/tisci/tisci_device.c + common/tisci/tisci_device.c \ + common/tisci/tisci_clock.c COMMONOBJECTS= $(COMMONSOURCES:.c=.o) diff --git a/common/tisci/tisci_clock.c b/common/tisci/tisci_clock.c new file mode 100644 index 0000000..d0de918 --- /dev/null +++ b/common/tisci/tisci_clock.c @@ -0,0 +1,174 @@ +/* + * TISCI clock ops library + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +static const char clock_state[MAX_CLOCK_HW_STATES + 1][MAX_CLOCK_STATE_LENGTH] = { + [MSG_CLOCK_HW_STATE_NOT_READY] = "CLK_STATE_NOT_READY", + [MSG_CLOCK_HW_STATE_READY] = "CLK_STATE_READY", + [MAX_CLOCK_HW_STATES] = "CLK_STATE_UNKNOWN" +}; + +static int ti_sci_set_clock_state(uint32_t dev_id, uint32_t clk_id, + uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_clock_state *req; + uint8_t buf[SEC_PROXY_MAX_MSG_SIZE]; + struct k3_sec_proxy_msg msg; + + memset(buf, 0, sizeof(buf)); + ti_sci_setup_header((struct ti_sci_msg_hdr *)buf, + TI_SCI_MSG_SET_CLOCK_STATE, flags); + req = (struct ti_sci_msg_req_set_clock_state *)buf; + req->dev_id = dev_id; + if (clk_id < 255) { + req->clk_id = clk_id; + } else { + req->clk_id = 255; + req->clk_id_32 = clk_id; + } + req->request_state = state; + + msg.len = sizeof(*req); + msg.buf = buf; + return ti_sci_xfer_msg(&msg); +} + +int ti_sci_cmd_get_clk(uint32_t dev_id, uint32_t clk_id) +{ + return ti_sci_set_clock_state(dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, + MSG_CLOCK_SW_STATE_REQ); +} + +int ti_sci_cmd_put_clk(uint32_t dev_id, uint32_t clk_id) +{ + return ti_sci_set_clock_state(dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, + MSG_CLOCK_SW_STATE_UNREQ); +} + +const char *ti_sci_cmd_get_clk_state(uint32_t dev_id, uint32_t clk_id) +{ + struct ti_sci_msg_resp_get_clock_state *resp; + struct ti_sci_msg_req_get_clock_state *req; + uint8_t buf[SEC_PROXY_MAX_MSG_SIZE]; + struct k3_sec_proxy_msg msg; + int ret; + + memset(buf, 0, sizeof(buf)); + ti_sci_setup_header((struct ti_sci_msg_hdr *)buf, + TI_SCI_MSG_GET_CLOCK_STATE, 0); + req = (struct ti_sci_msg_req_get_clock_state *)buf; + req->dev_id = dev_id; + if (clk_id < 255) { + req->clk_id = clk_id; + } else { + req->clk_id = 255; + req->clk_id_32 = clk_id; + } + + msg.len = sizeof(*req); + msg.buf = buf; + ret = ti_sci_xfer_msg(&msg); + if (ret) + return NULL; + + resp = (struct ti_sci_msg_resp_get_clock_state *)buf; + + return clock_state[resp->current_state]; +} + +int ti_sci_cmd_set_clk_freq(uint32_t dev_id, uint32_t clk_id, uint64_t freq) +{ + struct ti_sci_msg_req_set_clock_freq *req; + uint8_t buf[SEC_PROXY_MAX_MSG_SIZE]; + struct k3_sec_proxy_msg msg; + + memset(buf, 0, sizeof(buf)); + ti_sci_setup_header((struct ti_sci_msg_hdr *)buf, + TI_SCI_MSG_SET_CLOCK_FREQ, 0); + req = (struct ti_sci_msg_req_set_clock_freq *)buf; + req->dev_id = dev_id; + if (clk_id < 255) { + req->clk_id = clk_id; + } else { + req->clk_id = 255; + req->clk_id_32 = clk_id; + } + /* ToDo: Get best match freq and set that freq */ + req->min_freq_hz = freq; + req->target_freq_hz = freq; + req->max_freq_hz = freq; + + msg.len = sizeof(*req); + msg.buf = buf; + return ti_sci_xfer_msg(&msg); +} + +int ti_sci_cmd_get_clk_freq(uint32_t dev_id, uint32_t clk_id, uint64_t *freq) +{ + struct ti_sci_msg_resp_get_clock_freq *resp; + struct ti_sci_msg_req_get_clock_freq *req; + uint8_t buf[SEC_PROXY_MAX_MSG_SIZE]; + struct k3_sec_proxy_msg msg; + int ret; + + memset(buf, 0, sizeof(buf)); + ti_sci_setup_header((struct ti_sci_msg_hdr *)buf, + TI_SCI_MSG_GET_CLOCK_FREQ, 0); + req = (struct ti_sci_msg_req_get_clock_freq *)buf; + req->dev_id = dev_id; + if (clk_id < 255) { + req->clk_id = clk_id; + } else { + req->clk_id = 255; + req->clk_id_32 = clk_id; + } + + msg.len = sizeof(*req); + msg.buf = buf; + ret = ti_sci_xfer_msg(&msg); + if (ret) + return ret; + + resp = (struct ti_sci_msg_resp_get_clock_freq *)buf; + *freq = resp->freq_hz; + + return 0; +} diff --git a/include/tisci.h b/include/tisci.h index c339de7..71fca60 100644 --- a/include/tisci.h +++ b/include/tisci.h @@ -51,10 +51,16 @@ struct ti_sci_info { }; #define MAX_DEVICE_STATE_LENGTH 25 +#define MAX_CLOCK_STATE_LENGTH 25 int ti_sci_init(void); const char *ti_sci_cmd_get_device_status(uint32_t dev_id); int ti_sci_cmd_disable_device(uint32_t dev_id); int ti_sci_cmd_enable_device(uint32_t dev_id); +int ti_sci_cmd_get_clk(uint32_t dev_id, uint32_t clk_id); +int ti_sci_cmd_put_clk(uint32_t dev_id, uint32_t clk_id); +const char *ti_sci_cmd_get_clk_state(uint32_t dev_id, uint32_t clk_id); +int ti_sci_cmd_set_clk_freq(uint32_t dev_id, uint32_t clk_id, uint64_t freq); +int ti_sci_cmd_get_clk_freq(uint32_t dev_id, uint32_t clk_id, uint64_t *freq); #endif diff --git a/include/tisci_protocol.h b/include/tisci_protocol.h index 78dec07..6d28bbb 100644 --- a/include/tisci_protocol.h +++ b/include/tisci_protocol.h @@ -43,6 +43,12 @@ /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 #define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 +/* Clock requests */ +#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 +#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 +#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c +#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e #define TI_SCI_MSG_FLAG(val) (1 << (val)) #define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 @@ -102,6 +108,74 @@ struct ti_sci_msg_resp_get_device_state { uint8_t current_state; } __attribute__ ((__packed__)); +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; + uint32_t clk_id_32; +} __attribute__ ((__packed__)); + +struct ti_sci_msg_req_get_clock_state { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; + uint32_t clk_id_32; +} __attribute__ ((__packed__)); + +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 +#define MAX_CLOCK_HW_STATES 2 + uint8_t current_state; +} __attribute__ ((__packed__)); + +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; + uint32_t clk_id_32; +} __attribute__ ((__packed__)); + +struct ti_sci_msg_resp_query_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __attribute__ ((__packed__)); + +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; + uint32_t clk_id_32; +} __attribute__ ((__packed__)); + +struct ti_sci_msg_req_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; + uint32_t clk_id_32; +} __attribute__ ((__packed__)); + +struct ti_sci_msg_resp_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __attribute__ ((__packed__)); + void ti_sci_setup_header(struct ti_sci_msg_hdr *hdr, uint16_t type, uint32_t flags); int ti_sci_xfer_msg(struct k3_sec_proxy_msg *msg); -- 2.39.2