lkml.org 
[lkml]   [2023]   [Jan]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH V2 1/3] soc: qcom: dcc: Add bootconfig support for DCC
Date
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@quicinc.com>
---
drivers/soc/qcom/Kconfig | 1 +
drivers/soc/qcom/dcc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 21c4ce2..f913b72 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -73,6 +73,7 @@ config QCOM_LLCC
config QCOM_DCC
tristate "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
\
 
 \ /
  Last update: 2023-03-26 23:53    [W:0.066 / U:2.280 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site