tisci: Add support for handling clocks
authorLokesh Vutla <lokeshvutla@ti.com>
Wed, 21 Aug 2019 05:47:46 +0000 (11:17 +0530)
committerLokesh Vutla <lokeshvutla@ti.com>
Sun, 25 Aug 2019 03:14:04 +0000 (08:44 +0530)
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 <lokeshvutla@ti.com>
Makefile
common/tisci/tisci_clock.c [new file with mode: 0644]
include/tisci.h
include/tisci_protocol.h

index b06a8296479b92df3b4913e4f24975c00d182ffc..6171a127c2d9261161995e14741d761018c2521e 100644 (file)
--- 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 (file)
index 0000000..d0de918
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * TISCI clock ops library
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *     Lokesh Vutla <lokeshvutla@ti.com>
+ *
+ *  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 <string.h>
+#include <sec_proxy.h>
+#include <tisci_protocol.h>
+#include <tisci.h>
+
+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;
+}
index c339de7b2c6dd0ec704e02ad69300f51352e5ea7..71fca60d4fd3d56118d577448808591a85145fc6 100644 (file)
@@ -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
index 78dec078b3b7ce8823eac00662a7e603a6c1795f..6d28bbbfd70cac6a056169c6f6fc51aa16da07f0 100644 (file)
 /* 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);