[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <82087136234e84eb0e10f0f168e1edb171e6d692.1675054375.git.quic_schowdhu@quicinc.com>
Date: Mon, 30 Jan 2023 10:43:55 +0530
From: Souradeep Chowdhury <quic_schowdhu@...cinc.com>
To: Andy Gross <agross@...nel.org>,
Konrad Dybcio <konrad.dybcio@...ainline.org>,
Bjorn Andersson <andersson@...nel.org>,
"Alex Elder" <elder@...e.org>
CC: <linux-arm-kernel@...ts.infradead.org>,
<linux-kernel@...r.kernel.org>, <linux-arm-msm@...r.kernel.org>,
Sai Prakash Ranjan <quic_saipraka@...cinc.com>,
Sibi Sankar <quic_sibis@...cinc.com>,
"Rajendra Nayak" <quic_rjendra@...cinc.com>, <vkoul@...nel.org>,
Souradeep Chowdhury <quic_schowdhu@...cinc.com>
Subject: [PATCH V3 1/3] soc: qcom: dcc: Add bootconfig support for DCC
Add bootconfig parser for DCC which is used to configure addresses
in DCC during boot time. This is needed to debug crashes that can happen
during boot-time. The expected format of a bootconfig file is as follows:-
dcc_config {
link_list_<The list number to configure> {
id = <The list number to configure>
items = <Address as same format as dcc separated by '_'>,
}
}
Example:-
dcc_config {
link_list_6 {
id = 6
items = R_0x1781005c_1_apb,
R_0x1782005c_1_apb
}
}
Signed-off-by: Souradeep Chowdhury <quic_schowdhu@...cinc.com>
---
drivers/soc/qcom/Kconfig | 3 +-
drivers/soc/qcom/dcc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 21c4ce2..d11bda2 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -71,8 +71,9 @@ config QCOM_LLCC
Say yes here to enable LLCC slice driver.
config QCOM_DCC
- tristate "Qualcomm Technologies, Inc. Data Capture and Compare(DCC) engine driver"
+ bool "Qualcomm Technologies, Inc. Data Capture and Compare(DCC) engine driver"
depends on ARCH_QCOM || COMPILE_TEST
+ select BOOT_CONFIG
help
This option enables driver for Data Capture and Compare engine. DCC
driver provides interface to configure DCC block and read back
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index 5b50d63..93e8f86 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -6,6 +6,7 @@
#include <linux/bitfield.h>
#include <linux/bitops.h>
+#include <linux/bootconfig.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/fs.h>
@@ -148,6 +149,18 @@ struct dcc_cfg_loop_attr {
bool loop_start;
};
+static char *replace_char(char *str, char find, char replace)
+{
+ char *current_pos = strchr(str, find);
+
+ while (current_pos) {
+ *current_pos = replace;
+ current_pos = strchr(current_pos, find);
+ }
+
+ return str;
+}
+
static inline u32 dcc_list_offset(int version)
{
return version == 1 ? 0x1c : version == 2 ? 0x2c : 0x34;
@@ -1185,13 +1198,62 @@ static void dcc_sram_dev_exit(struct dcc_drvdata *drvdata)
misc_deregister(&drvdata->sram_dev);
}
-static int dcc_probe(struct platform_device *pdev)
+static int __init dcc_bootconfig_parse(struct dcc_drvdata *drvdata, struct xbc_node *dcc_node)
+{
+ struct xbc_node *linked_list, *node;
+ int curr_list, ret;
+ const char *p;
+ char *input, *token;
+ char val[30];
+
+ xbc_node_for_each_subkey(dcc_node, linked_list) {
+ p = xbc_node_find_value(linked_list, "id", &node);
+ if (p) {
+ ret = kstrtoint(p, 0, &curr_list);
+ if (ret)
+ return ret;
+ } else {
+ dev_err(drvdata->dev, "List number not specified\n");
+ continue;
+ }
+
+ p = xbc_node_find_value(linked_list, "items", &node);
+ if (!p)
+ continue;
+ xbc_array_for_each_value(node, p) {
+ strcpy(val, p);
+ input = replace_char(val, '_', ' ');
+ token = strsep(&input, " ");
+
+ if (!strcmp("R", token)) {
+ ret = dcc_config_add_read(drvdata, input, curr_list);
+ } else if (!strcmp("W", token)) {
+ ret = dcc_config_add_write(drvdata, input, curr_list);
+ } else if (!strcmp("RW", token)) {
+ ret = dcc_config_add_read_write(drvdata, input, curr_list);
+ } else if (!strcmp("L", token)) {
+ ret = dcc_config_add_loop(drvdata, input, curr_list);
+ } else {
+ dev_err(drvdata->dev, "%s is not a correct input\n", token);
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+ dcc_enable(drvdata, curr_list);
+ }
+
+ return 0;
+}
+
+static int __init dcc_probe(struct platform_device *pdev)
{
u32 val;
int ret = 0, i;
struct device *dev = &pdev->dev;
struct dcc_drvdata *drvdata;
struct resource *res;
+ struct xbc_node *dcc_node;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
@@ -1263,6 +1325,13 @@ static int dcc_probe(struct platform_device *pdev)
dcc_create_debug_dir(drvdata);
+ dcc_node = xbc_find_node("dcc_config");
+ if (dcc_node) {
+ ret = dcc_bootconfig_parse(drvdata, dcc_node);
+ if (ret)
+ dev_err(drvdata->dev, "DCC: Bootconfig parse error.\n");
+ }
+
return 0;
}
@@ -1287,14 +1356,13 @@ static const struct of_device_id dcc_match_table[] = {
MODULE_DEVICE_TABLE(of, dcc_match_table);
static struct platform_driver dcc_driver = {
- .probe = dcc_probe,
.remove = dcc_remove,
.driver = {
.name = "qcom-dcc",
.of_match_table = dcc_match_table,
},
};
-module_platform_driver(dcc_driver);
+module_platform_driver_probe(dcc_driver, dcc_probe);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver");
--
2.7.4
Powered by blists - more mailing lists