[PATCH 2/7] firmware: ti_sci: update from U-Boot
Sascha Hauer
s.hauer at pengutronix.de
Fri Nov 8 05:15:00 PST 2024
This imports some U-Boot changes into the ti_sci driver. For upcoming
k3-udma driver we'll need ti_sci_get_by_phandle() and
devm_ti_sci_get_of_resource().
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
drivers/firmware/ti_sci.c | 276 ++++++++++++++++++++++++++++++++-------
drivers/firmware/ti_sci.h | 2 +-
include/soc/ti/ti_sci_protocol.h | 38 +++++-
3 files changed, 264 insertions(+), 52 deletions(-)
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index c81e8aa1e7..9047f84434 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -3,18 +3,22 @@
* Texas Instruments System Control Interface Protocol Driver
* Based on drivers/firmware/ti_sci.c from Linux.
*
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
* Lokesh Vutla <lokeshvutla at ti.com>
*/
-#include <common.h>
#include <mailbox.h>
-#include <restart.h>
+#include <driver.h>
#include <soc/ti/k3-sec-proxy.h>
#include <soc/ti/ti_sci_protocol.h>
+#include <linux/slab.h>
+#include <linux/device.h>
#include "ti_sci.h"
+/* List of all TI SCI devices active in system */
+static LIST_HEAD(ti_sci_list);
+
/**
* struct ti_sci_xfer - Structure representing a message flow
* @tx_message: Transmit message
@@ -126,7 +130,6 @@ static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
return ERR_PTR(-ERANGE);
}
-
info->seq = ~info->seq;
xfer->tx_message.buf = buf;
xfer->tx_message.len = tx_message_size;
@@ -223,21 +226,27 @@ static int ti_sci_do_xfer(struct ti_sci_info *info,
{
struct k3_sec_proxy_msg *msg = &xfer->tx_message;
u8 secure_buf[info->desc->max_msg_size];
- struct ti_sci_secure_msg_hdr secure_hdr;
+ struct ti_sci_secure_msg_hdr *secure_hdr = (struct ti_sci_secure_msg_hdr *)secure_buf;
int ret;
+ /*
+ * The reason why we need the is_secure code is because of boot R5.
+ * boot R5 starts off in "secure mode" when it hands off from Boot
+ * ROM over to the Secondary bootloader. The initial set of calls
+ * we have to make need to be on a secure pipe.
+ */
if (info->is_secure) {
/* ToDo: get checksum of the entire message */
- secure_hdr.checksum = 0;
- secure_hdr.reserved = 0;
- memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
+ secure_hdr->checksum = 0;
+ secure_hdr->reserved = 0;
+ memcpy(&secure_buf[sizeof(*secure_hdr)], xfer->tx_message.buf,
xfer->tx_message.len);
xfer->tx_message.buf = (u32 *)secure_buf;
- xfer->tx_message.len += sizeof(secure_hdr);
+ xfer->tx_message.len += sizeof(*secure_hdr);
if (xfer->rx_len)
- xfer->rx_len += sizeof(secure_hdr);
+ xfer->rx_len += sizeof(*secure_hdr);
}
/* Send the message */
@@ -2558,13 +2567,6 @@ static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle,
return ret;
}
-static struct ti_sci_handle *g_handle;
-
-const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
-{
- return g_handle;
-}
-
/*
* ti_sci_setup_ops() - Setup the operations structures
* @info: pointer to TISCI pointer
@@ -2648,57 +2650,231 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner;
}
-static void ti_sci_reset(struct restart_handler *unused)
+/**
+ * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
+ * @dev: Pointer to the SYSFW device
+ *
+ * Return: pointer to handle if successful, else EINVAL if invalid conditions
+ * are encountered.
+ */
+const
+struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct device *sci_dev)
{
- ti_sci_cmd_core_reboot(g_handle);
+ struct ti_sci_info *info;
+ int ret;
+
+ if (!sci_dev)
+ return ERR_PTR(-EINVAL);
+
+ info = dev_get_priv(sci_dev);
+ if (!info)
+ return ERR_PTR(-EINVAL);
+
+ ret = ti_sci_cmd_get_revision(&info->handle);
+ if (ret)
+ return ERR_PTR(-EINVAL);
+
+ return &info->handle;
}
-static int ti_sci_probe(struct device *dev)
+/**
+ * ti_sci_get_handle() - Get the TI SCI handle for a device
+ * @dev: Pointer to device for which we want SCI handle
+ *
+ * Return: pointer to handle if successful, else EINVAL if invalid conditions
+ * are encountered.
+ */
+const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
{
- struct ti_sci_info *info;
- const void *data;
- int ret;
+ struct device *sci_dev;
- if (g_handle)
- return 0;
+ if (!dev)
+ return ERR_PTR(-EINVAL);
- ret = dev_get_drvdata(dev, &data);
- if (ret)
- return ret;
+ sci_dev = dev->parent;
- info = xzalloc(sizeof(*info));
+ return ti_sci_get_handle_from_sysfw(sci_dev);
+}
- info->chan_rx = mbox_request_channel_byname(dev, "rx");
- if (IS_ERR(info->chan_rx))
- return PTR_ERR(info->chan_rx);
+/**
+ * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
+ * @dev: device node
+ * @propname: property name containing phandle on TISCI node
+ *
+ * Return: pointer to handle if successful, else appropriate error value.
+ */
+const struct ti_sci_handle *ti_sci_get_by_phandle(struct device *dev,
+ const char *property)
+{
+ struct ti_sci_info *entry, *info = NULL;
+ struct device_node *np;
+
+ np = of_parse_phandle(dev->of_node, property, 0);
+ if (!np)
+ return ERR_PTR(-EINVAL);
+
+ of_device_ensure_probed(np);
+
+ list_for_each_entry(entry, &ti_sci_list, list)
+ if (dev_of_node(entry->dev) == np) {
+ info = entry;
+ break;
+ }
+ if (!info)
+ return ERR_PTR(-ENODEV);
+
+ return &info->handle;
+}
+
+/**
+ * ti_sci_of_to_info() - generate private data from device tree
+ * @dev: corresponding system controller interface device
+ * @info: pointer to driver specific private data
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int ti_sci_of_to_info(struct device *dev, struct ti_sci_info *info)
+{
info->chan_tx = mbox_request_channel_byname(dev, "tx");
- if (IS_ERR(info->chan_tx))
+ if (IS_ERR(info->chan_tx)) {
+ dev_err(dev, "%s: Acquiring Tx channel failed: %pe\n",
+ __func__, info->chan_tx);
return PTR_ERR(info->chan_tx);
+ }
+
+ info->chan_rx = mbox_request_channel_byname(dev, "rx");
+ if (IS_ERR(info->chan_rx)) {
+ dev_err(dev, "%s: Acquiring Rx channel failed: %pe\n",
+ __func__, info->chan_rx);
+ return PTR_ERR(info->chan_rx);
+ }
+
+ /* Notify channel is optional. Enable only if populated */
+ info->chan_notify = mbox_request_channel_byname(dev, "notify");
+ if (IS_ERR(info->chan_notify)) {
+ dev_dbg(dev, "%s: Acquiring notify channel failed: %pe\n",
+ __func__, info->chan_notify);
+ }
- info->desc = data;
info->host_id = info->desc->default_host_id;
of_property_read_u32(dev->of_node, "ti,host-id", &info->host_id);
- info->is_secure = of_property_read_bool(dev->of_node, "ti,secure-host");
+ info->is_secure = of_property_read_bool(dev->of_node, "ti,secure-host");
+
+ return 0;
+}
+
+/**
+ * ti_sci_probe() - Basic probe
+ * @dev: corresponding system controller interface device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int ti_sci_probe(struct device *dev)
+{
+ struct ti_sci_info *info;
+ int ret;
+
+ info = xzalloc(sizeof(*info));
+ info->desc = device_get_match_data(dev);
+
+ ret = ti_sci_of_to_info(dev, info);
+ if (ret) {
+ dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
+ return ret;
+ }
+ dev->priv = info;
info->dev = dev;
- info->seq = 0xA;
- INIT_LIST_HEAD(&info->dev_list);
+ info->seq = 0xa;
+ list_add_tail(&info->list, &ti_sci_list);
ti_sci_setup_ops(info);
- ret = ti_sci_cmd_get_revision(&info->handle);
+ INIT_LIST_HEAD(&info->dev_list);
+
+ return 0;
+}
+
+/**
+ * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
+ * @handle: TISCI handle
+ * @dev: Device pointer to which the resource is assigned
+ * @of_prop: property name by which the resource are represented
+ *
+ * Note: This function expects of_prop to be in the form of tuples
+ * <type, subtype>. Allocates and initializes ti_sci_resource structure
+ * for each of_prop. Client driver can directly call
+ * ti_sci_(get_free, release)_resource apis for handling the resource.
+ *
+ * Return: Pointer to ti_sci_resource if all went well else appropriate
+ * error pointer.
+ */
+struct ti_sci_resource *
+devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
+ struct device *dev, u32 dev_id, char *of_prop)
+{
+ u32 resource_subtype;
+ struct ti_sci_resource *res;
+ bool valid_set = false;
+ int sets, i, ret;
+ u32 *temp;
+ const void *pp;
+
+ res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return ERR_PTR(-ENOMEM);
+
+ pp = of_get_property(dev->of_node, of_prop, &sets);
+ if (!pp) {
+ dev_err(dev, "%s resource type ids not available\n", of_prop);
+ return ERR_PTR(sets);
+ }
+ temp = malloc(sets);
+ sets /= sizeof(u32);
+ res->sets = sets;
+
+ res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
+ GFP_KERNEL);
+ if (!res->desc)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32_array(dev->of_node, of_prop, temp, res->sets);
if (ret)
- return ret;
+ return ERR_PTR(-EINVAL);
+
+ for (i = 0; i < res->sets; i++) {
+ resource_subtype = temp[i];
+ ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
+ resource_subtype,
+ &res->desc[i].start,
+ &res->desc[i].num);
+ if (ret) {
+ dev_dbg(dev, "type %d subtype %d not allocated for host %d\n",
+ dev_id, resource_subtype,
+ handle_to_ti_sci_info(handle)->host_id);
+ res->desc[i].start = 0;
+ res->desc[i].num = 0;
+ continue;
+ }
- g_handle = &info->handle;
+ valid_set = true;
+ dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n",
+ dev_id, resource_subtype, res->desc[i].start,
+ res->desc[i].num);
- of_platform_populate(dev->of_node, NULL, NULL);
+ res->desc[i].res_map =
+ devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
+ sizeof(*res->desc[i].res_map), GFP_KERNEL);
+ if (!res->desc[i].res_map)
+ return ERR_PTR(-ENOMEM);
+ }
- restart_handler_register_fn("ti-sci", ti_sci_reset);
+ if (valid_set)
+ return res;
- return 0;
+ return ERR_PTR(-EINVAL);
}
/* Description for K2G */
@@ -2721,7 +2897,7 @@ static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
.max_msg_size = 60,
};
-static const struct of_device_id ti_sci_of_match[] = {
+static const struct of_device_id of_ti_sci_ids[] = {
{
.compatible = "ti,k2g-sci",
.data = &ti_sci_pmmc_k2g_desc
@@ -2729,14 +2905,14 @@ static const struct of_device_id ti_sci_of_match[] = {
.compatible = "ti,am654-sci",
.data = &ti_sci_pmmc_am654_desc
}, {
- /* sentinel */
- }
+ /* Sentinel */
+ },
};
-MODULE_DEVICE_TABLE(of, ti_sci_of_match);
static struct driver ti_sci_driver = {
- .name = "ti-sci",
- .probe = ti_sci_probe,
- .of_compatible = DRV_OF_COMPAT(ti_sci_of_match),
+ .probe = ti_sci_probe,
+ .name = "ti_sci",
+ .of_compatible = of_ti_sci_ids,
};
+
core_platform_driver(ti_sci_driver);
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 101210eb21..bb8bc7beea 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -6,7 +6,7 @@
* 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/
+ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
* Based on drivers/firmware/ti_sci.h from Linux.
*
*/
diff --git a/include/soc/ti/ti_sci_protocol.h b/include/soc/ti/ti_sci_protocol.h
index ec69f07b8e..f41ed82b91 100644
--- a/include/soc/ti/ti_sci_protocol.h
+++ b/include/soc/ti/ti_sci_protocol.h
@@ -3,7 +3,7 @@
* Texas Instruments System Control Interface Protocol
* Based on include/linux/soc/ti/ti_sci_protocol.h from Linux.
*
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
* Nishanth Menon
* Lokesh Vutla <lokeshvutla at ti.com>
*/
@@ -652,6 +652,42 @@ struct ti_sci_resource {
struct ti_sci_resource_desc *desc;
};
+#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
+
+const struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct device *dev);
const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
+const struct ti_sci_handle *ti_sci_get_by_phandle(struct device *dev,
+ const char *property);
+struct ti_sci_resource *
+devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
+ struct device *dev, u32 dev_id, char *of_prop);
+#else /* CONFIG_TI_SCI_PROTOCOL */
+
+static inline
+const struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline
+const struct ti_sci_handle *ti_sci_get_by_phandle(struct device *dev,
+ const char *property)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct ti_sci_resource *
+devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
+ struct device *dev, u32 dev_id, char *of_prop)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+#endif /* CONFIG_TI_SCI_PROTOCOL */
#endif /* __TISCI_PROTOCOL_H */
--
2.39.5
More information about the barebox
mailing list