[PATCH V3 2/3] soc: qcom: dcc: Add CTI-trigger support for DCC

From: Souradeep Chowdhury
Date: Mon Jan 30 2023 - 00:15:09 EST


CTI trigger is used to enable the Cross trigger interface for DCC.
On enabling CTI trigger the dcc software trigger can be done by
writing to CTI trig-out. Add the debugfs file ctitrigger which
gives the user option to enable ctitrigger for a list. Also add
hwtrigger debugfs file which needs to be disabled on enabling
the CTI-trigger. Hwtrigger needs to be disabled for components
to be able to write to cti-trigout.

Signed-off-by: Souradeep Chowdhury <quic_schowdhu@xxxxxxxxxxx>
---
Documentation/ABI/testing/debugfs-driver-dcc | 16 +++
drivers/soc/qcom/dcc.c | 148 ++++++++++++++++++++++++++-
2 files changed, 160 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/debugfs-driver-dcc b/Documentation/ABI/testing/debugfs-driver-dcc
index 27ed591..6f5d965 100644
--- a/Documentation/ABI/testing/debugfs-driver-dcc
+++ b/Documentation/ABI/testing/debugfs-driver-dcc
@@ -125,3 +125,19 @@ Description:
on manual or crash induced triggers. Lists must
be configured and enabled sequentially, e.g. list
2 can only be enabled when list 1 have so.
+
+What: /sys/kernel/debug/dcc/.../[list-number]/ctitrigger
+Date: January 2023
+Contact: Souradeep Chowdhury <quic_schowdhu@xxxxxxxxxxx>
+Description:
+ This debugfs interface is used for enabling the
+ ctitrigger. Ctitrigger can be enabled by writing
+ a '1' to the file.
+
+What: /sys/kernel/debug/dcc/.../[list-number]/hwtrigger
+Date: January 2023
+Contact: Souradeep Chowdhury <quic_schowdhu@xxxxxxxxxxx>
+Description:
+ This debugfs interface is used for enabling the
+ hwtrigger. Hwtrigger can be enabled by writing
+ a '1' to the file.
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index 93e8f86..a75b9af 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -37,6 +37,7 @@
#define DCC_LL_INT_STATUS 0x1c
#define DCC_LL_SW_TRIGGER 0x2c
#define DCC_LL_BUS_ACCESS_STATUS 0x30
+#define DCC_CTI_TRIG 0x34

/* Default value used if a bit 6 in the HW_INFO register is set. */
#define DCC_FIX_LOOP_OFFSET 16
@@ -115,6 +116,8 @@ struct dcc_config_entry {
* @nr_link_list: Total number of linkedlists supported by the DCC configuration
* @loop_shift: Loop offset bits range for the addresses
* @enable_bitmap: Bitmap to capture the enabled status of each linked list of addresses
+ * @cti_bitmap: Bitmap to capture the cti-trigger status of each linked list of addresses
+ * @hwtrig_bitmap: Bitmap to capture the hwtrig status of each linked list of addresses
*/
struct dcc_drvdata {
void __iomem *base;
@@ -132,6 +135,8 @@ struct dcc_drvdata {
size_t nr_link_list;
u8 loop_shift;
unsigned long *enable_bitmap;
+ unsigned long *cti_bitmap;
+ unsigned long *hwtrig_bitmap;
};

struct dcc_cfg_attr {
@@ -213,7 +218,10 @@ static int dcc_sw_trigger(struct dcc_drvdata *drvdata)
if (!test_bit(i, drvdata->enable_bitmap))
continue;
ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG);
- tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK;
+ if (drvdata->mem_map_ver != 3)
+ tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK;
+ else
+ tmp_ll_cfg = ll_cfg & ~BIT(8);
dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG);
dcc_list_writel(drvdata, 1, i, DCC_LL_SW_TRIGGER);
dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG);
@@ -590,6 +598,23 @@ static int dcc_enable(struct dcc_drvdata *drvdata, unsigned int curr_list)
/* 5. Configure trigger */
dcc_list_writel(drvdata, DCC_TRIGGER_MASK,
curr_list, DCC_LL_CFG);
+ if (drvdata->mem_map_ver == 3) {
+ dcc_list_writel(drvdata, test_bit(curr_list, drvdata->cti_bitmap), curr_list,
+ DCC_CTI_TRIG);
+ if (test_bit(curr_list, drvdata->hwtrig_bitmap))
+ dcc_list_writel(drvdata, BIT(8), curr_list, DCC_LL_CFG);
+ else
+ dcc_list_writel(drvdata, (unsigned int)~BIT(8), curr_list, DCC_LL_CFG);
+ } else {
+ if (test_bit(curr_list, drvdata->hwtrig_bitmap))
+ dcc_list_writel(drvdata, DCC_TRIGGER_MASK |
+ test_bit(curr_list, drvdata->cti_bitmap) << 8,
+ curr_list, DCC_LL_CFG);
+ else
+ dcc_list_writel(drvdata, ~DCC_TRIGGER_MASK &
+ test_bit(curr_list, drvdata->cti_bitmap) << 8,
+ curr_list, DCC_LL_CFG);
+ }

out_unlock:
mutex_unlock(&drvdata->mutex);
@@ -1116,6 +1141,110 @@ static const struct file_operations config_fops = {
.release = single_release,
};

+static ssize_t ctitrigger_read(struct file *filp, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int curr_list;
+ struct dcc_drvdata *drvdata = filp->private_data;
+
+ curr_list = dcc_filp_curr_list(filp);
+
+ mutex_lock(&drvdata->mutex);
+
+ if (test_bit(curr_list, drvdata->cti_bitmap))
+ buf = "Y\n";
+ else
+ buf = "N\n";
+
+ mutex_unlock(&drvdata->mutex);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static ssize_t ctitrigger_write(struct file *filp, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ int ret, curr_list;
+ bool val;
+ struct dcc_drvdata *drvdata = filp->private_data;
+
+ curr_list = dcc_filp_curr_list(filp);
+
+ if (test_bit(curr_list, drvdata->enable_bitmap))
+ return -EBUSY;
+
+ ret = kstrtobool_from_user(userbuf, count, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val)
+ set_bit(curr_list, drvdata->cti_bitmap);
+ else
+ clear_bit(curr_list, drvdata->cti_bitmap);
+
+ return count;
+}
+
+static const struct file_operations ctitrigger_fops = {
+ .read = ctitrigger_read,
+ .write = ctitrigger_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static ssize_t hwtrigger_read(struct file *filp, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int curr_list;
+ struct dcc_drvdata *drvdata = filp->private_data;
+
+ curr_list = dcc_filp_curr_list(filp);
+
+ mutex_lock(&drvdata->mutex);
+
+ if (test_bit(curr_list, drvdata->hwtrig_bitmap))
+ buf = "Y\n";
+ else
+ buf = "N\n";
+
+ mutex_unlock(&drvdata->mutex);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static ssize_t hwtrigger_write(struct file *filp, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ int ret, curr_list;
+ bool val;
+ struct dcc_drvdata *drvdata = filp->private_data;
+
+ curr_list = dcc_filp_curr_list(filp);
+
+ if (test_bit(curr_list, drvdata->enable_bitmap))
+ return -EBUSY;
+
+ ret = kstrtobool_from_user(userbuf, count, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val)
+ set_bit(curr_list, drvdata->hwtrig_bitmap);
+ else
+ clear_bit(curr_list, drvdata->hwtrig_bitmap);
+
+ return count;
+}
+
+static const struct file_operations hwtrigger_fops = {
+ .read = hwtrigger_read,
+ .write = hwtrigger_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
static void dcc_delete_debug_dir(struct dcc_drvdata *drvdata)
{
debugfs_remove_recursive(drvdata->dbg_dir);
@@ -1145,6 +1274,8 @@ static void dcc_create_debug_dir(struct dcc_drvdata *drvdata)
debugfs_create_file("ready", 0400, drvdata->dbg_dir, drvdata, &ready_fops);
debugfs_create_file("config_reset", 0200, drvdata->dbg_dir,
drvdata, &config_reset_fops);
+ debugfs_create_file("ctitrigger", 0600, list, drvdata, &ctitrigger_fops);
+ debugfs_create_file("hwtrigger", 0600, list, drvdata, &hwtrigger_fops);
}

static ssize_t dcc_sram_read(struct file *file, char __user *data,
@@ -1304,18 +1435,27 @@ static int __init dcc_probe(struct platform_device *pdev)

mutex_init(&drvdata->mutex);

- drvdata->enable_bitmap = devm_kcalloc(dev, BITS_TO_LONGS(drvdata->nr_link_list),
- sizeof(*drvdata->enable_bitmap), GFP_KERNEL);
+ drvdata->enable_bitmap = devm_bitmap_alloc(dev, drvdata->nr_link_list, GFP_KERNEL);
if (!drvdata->enable_bitmap)
return -ENOMEM;

+ drvdata->cti_bitmap = devm_bitmap_alloc(dev, drvdata->nr_link_list, GFP_KERNEL);
+ if (!drvdata->cti_bitmap)
+ return -ENOMEM;
+
+ drvdata->hwtrig_bitmap = devm_bitmap_alloc(dev, drvdata->nr_link_list, GFP_KERNEL);
+ if (!drvdata->hwtrig_bitmap)
+ return -ENOMEM;
+
drvdata->cfg_head = devm_kcalloc(dev, drvdata->nr_link_list,
sizeof(*drvdata->cfg_head), GFP_KERNEL);
if (!drvdata->cfg_head)
return -ENOMEM;

- for (i = 0; i < drvdata->nr_link_list; i++)
+ for (i = 0; i < drvdata->nr_link_list; i++) {
INIT_LIST_HEAD(&drvdata->cfg_head[i]);
+ set_bit(i, drvdata->hwtrig_bitmap);
+ }

ret = dcc_sram_dev_init(drvdata);
if (ret) {
--
2.7.4