lkml.org 
[lkml]   [2021]   [Oct]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 07/10] Coresight: Enable DSB subunit for TPDM
Date
Enable Discrete Single Bit(DSB) subunit for TPDM. The DSB dataset
elements flow out ATB while the BC/TC dataset elements are sent
only on ATB flush requests from the TPDA.
The DSB data set subunit is responsible for collection of DSB data
sets. The width of the DSB subunit interface must be between 8 and
256 bits. A monitor may support either a 32 or 64 bit DSB data set
element size (e.g. via a hardware parameter).

Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
---
drivers/hwtracing/coresight/coresight-tpdm.c | 680 +++++++++++++++++++
1 file changed, 680 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 635382be5de6..5f07363e4650 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -309,6 +309,17 @@ static void __tpdm_config_tc_msr(struct tpdm_drvdata *drvdata)
tpdm_writel(drvdata, drvdata->tc->msr[i], TPDM_TC_MSR(i));
}

+static void __tpdm_config_dsb_msr(struct tpdm_drvdata *drvdata)
+{
+ int i;
+
+ if (!drvdata->msr_support)
+ return;
+
+ for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
+ tpdm_writel(drvdata, drvdata->dsb->msr[i], TPDM_DSB_MSR(i));
+}
+
static void __tpdm_enable_bc(struct tpdm_drvdata *drvdata)
{
int i;
@@ -434,6 +445,86 @@ static void __tpdm_enable_tc(struct tpdm_drvdata *drvdata)
tpdm_writel(drvdata, val, TPDM_TC_CR);
}

+static void __tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
+{
+ uint32_t val, mode, i;
+
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
+ tpdm_writel(drvdata, drvdata->dsb->edge_ctrl[i],
+ TPDM_DSB_EDCR(i));
+ for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++)
+ tpdm_writel(drvdata, drvdata->dsb->edge_ctrl_mask[i],
+ TPDM_DSB_EDCMR(i));
+
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ tpdm_writel(drvdata, drvdata->dsb->patt_val[i],
+ TPDM_DSB_TPR(i));
+ tpdm_writel(drvdata, drvdata->dsb->patt_mask[i],
+ TPDM_DSB_TPMR(i));
+ }
+
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ tpdm_writel(drvdata, drvdata->dsb->trig_patt_val[i],
+ TPDM_DSB_XPR(i));
+ tpdm_writel(drvdata, drvdata->dsb->trig_patt_mask[i],
+ TPDM_DSB_XPMR(i));
+ }
+
+ for (i = 0; i < TPDM_DSB_MAX_SELECT; i++)
+ tpdm_writel(drvdata, drvdata->dsb->select_val[i],
+ TPDM_DSB_CA_SELECT(i));
+
+ val = tpdm_readl(drvdata, TPDM_DSB_TIER);
+ if (drvdata->dsb->patt_ts) {
+ val = val | BIT(0);
+ if (drvdata->dsb->patt_type)
+ val = val | BIT(2);
+ else
+ val = val & ~BIT(2);
+ } else {
+ val = val & ~BIT(0);
+ }
+ if (drvdata->dsb->trig_ts)
+ val = val | BIT(1);
+ else
+ val = val & ~BIT(1);
+ tpdm_writel(drvdata, val, TPDM_DSB_TIER);
+
+ if (!drvdata->msr_fix_req)
+ __tpdm_config_dsb_msr(drvdata);
+
+ val = tpdm_readl(drvdata, TPDM_DSB_CR);
+ /* Set the cycle accurate mode */
+ mode = TPDM_DSB_MODE_CYCACC(drvdata->dsb->mode);
+ val = val & ~(0x7 << 9);
+ val = val | (mode << 9);
+ /* Set the byte lane for high-performance mode */
+ mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
+ val = val & ~(0x1F << 2);
+ val = val | (mode << 2);
+ /* Set the performance mode */
+ if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
+ val = val | BIT(1);
+ else
+ val = val & ~BIT(1);
+
+ /* Set trigger type */
+ if (drvdata->dsb->trig_type)
+ val = val | BIT(12);
+ else
+ val = val & ~BIT(12);
+
+ tpdm_writel(drvdata, val, TPDM_DSB_CR);
+
+ val = tpdm_readl(drvdata, TPDM_DSB_CR);
+ /* Set the enable bit */
+ val = val | BIT(0);
+ tpdm_writel(drvdata, val, TPDM_DSB_CR);
+
+ if (drvdata->msr_fix_req)
+ __tpdm_config_dsb_msr(drvdata);
+}
+
static void __tpdm_enable(struct tpdm_drvdata *drvdata)
{
TPDM_UNLOCK(drvdata);
@@ -450,6 +541,9 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
__tpdm_enable_tc(drvdata);

+ if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
+ __tpdm_enable_dsb(drvdata);
+
TPDM_LOCK(drvdata);
}

@@ -492,6 +586,15 @@ static void __tpdm_disable_tc(struct tpdm_drvdata *drvdata)
tpdm_writel(drvdata, config, TPDM_TC_CR);
}

+static void __tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
+{
+ uint32_t config;
+
+ config = tpdm_readl(drvdata, TPDM_DSB_CR);
+ config = config & ~BIT(0);
+ tpdm_writel(drvdata, config, TPDM_DSB_CR);
+}
+
static void __tpdm_disable(struct tpdm_drvdata *drvdata)
{
TPDM_UNLOCK(drvdata);
@@ -502,6 +605,9 @@ static void __tpdm_disable(struct tpdm_drvdata *drvdata)
if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
__tpdm_disable_tc(drvdata);

+ if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
+ __tpdm_disable_dsb(drvdata);
+
if (drvdata->clk_enable)
tpdm_writel(drvdata, 0x0, TPDM_CLK_CTRL);

@@ -2474,6 +2580,558 @@ static ssize_t tc_msr_store(struct device *dev,
}
static DEVICE_ATTR_RW(tc_msr);

+static ssize_t dsb_mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%lx\n",
+ (unsigned long)drvdata->dsb->mode);
+}
+
+static ssize_t dsb_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->mode = val & TPDM_MODE_ALL;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_mode);
+
+static ssize_t dsb_edge_ctrl_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index:0x%x Val:0x%x\n", i,
+ drvdata->dsb->edge_ctrl[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_edge_ctrl_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long start, end, edge_ctrl;
+ uint32_t val;
+ int i, bit, reg;
+
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
+ edge_ctrl > 0x2)
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = start; i <= end; i++) {
+ reg = i / (NUM_OF_BITS / 2);
+ bit = i % (NUM_OF_BITS / 2);
+ bit = bit * 2;
+
+ val = drvdata->dsb->edge_ctrl[reg];
+ val = val & ~GENMASK((bit + 1), bit);
+ val = val | (edge_ctrl << bit);
+ drvdata->dsb->edge_ctrl[reg] = val;
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_edge_ctrl);
+
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index:0x%x Val:0x%x\n", i,
+ drvdata->dsb->edge_ctrl_mask[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long start, end, val;
+ uint32_t set;
+ int i, bit, reg;
+
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = start; i <= end; i++) {
+ reg = i / NUM_OF_BITS;
+ bit = (i % NUM_OF_BITS);
+
+ set = drvdata->dsb->edge_ctrl_mask[reg];
+ if (val)
+ set = set | BIT(bit);
+ else
+ set = set & ~BIT(bit);
+ drvdata->dsb->edge_ctrl_mask[reg] = set;
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+
+static ssize_t dsb_patt_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->patt_val[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_patt_val_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->patt_val[index] = val;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_val);
+
+static ssize_t dsb_patt_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->patt_mask[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_patt_mask_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->patt_mask[index] = val;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_mask);
+
+static ssize_t dsb_patt_ts_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned int)drvdata->dsb->patt_ts);
+}
+
+static ssize_t dsb_patt_ts_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ if (val)
+ drvdata->dsb->patt_ts = true;
+ else
+ drvdata->dsb->patt_ts = false;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_ts);
+
+static ssize_t dsb_patt_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned int)drvdata->dsb->patt_type);
+}
+
+static ssize_t dsb_patt_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ if (val)
+ drvdata->dsb->patt_type = true;
+ else
+ drvdata->dsb->patt_type = false;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_type);
+
+static ssize_t dsb_trig_patt_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->trig_patt_val[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_trig_patt_val_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->trig_patt_val[index] = val;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_patt_val);
+
+static ssize_t dsb_trig_patt_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->trig_patt_mask[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_trig_patt_mask_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->trig_patt_mask[index] = val;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_patt_mask);
+
+static ssize_t dsb_trig_type_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned int)drvdata->dsb->trig_type);
+}
+
+static ssize_t dsb_trig_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ if (val)
+ drvdata->dsb->trig_type = true;
+ else
+ drvdata->dsb->trig_type = false;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_type);
+
+static ssize_t dsb_trig_ts_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned int)drvdata->dsb->trig_ts);
+}
+
+static ssize_t dsb_trig_ts_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ if (val)
+ drvdata->dsb->trig_ts = true;
+ else
+ drvdata->dsb->trig_ts = false;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_ts);
+
+static ssize_t dsb_select_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_DSB_MAX_SELECT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index:0x%x Val:0x%x\n", i,
+ drvdata->dsb->select_val[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+
+static ssize_t dsb_select_val_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long start, end;
+ uint32_t val;
+ int i, bit, reg;
+
+ if (sscanf(buf, "%lx %lx", &start, &end) != 2)
+ return -EINVAL;
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
+ (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
+ return -EPERM;
+
+ mutex_lock(&drvdata->lock);
+ for (i = start; i <= end; i++) {
+ reg = i / NUM_OF_BITS;
+ bit = (i % NUM_OF_BITS);
+
+ val = drvdata->dsb->select_val[reg];
+ val = val | BIT(bit);
+ drvdata->dsb->select_val[reg] = val;
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_select_val);
+
+static ssize_t dsb_msr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned int i;
+ ssize_t len = 0;
+
+ if (!drvdata->msr_support)
+ return -EINVAL;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
+ i, drvdata->dsb->msr[i]);
+
+ return len;
+}
+
+static ssize_t dsb_msr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned int num, val;
+ int nval;
+
+ if (!drvdata->msr_support)
+ return -EINVAL;
+
+ if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
+ return -EPERM;
+
+ nval = sscanf(buf, "%u %x", &num, &val);
+ if (nval != 2)
+ return -EINVAL;
+
+ if (num >= TPDM_DSB_MAX_MSR)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->lock);
+ drvdata->dsb->msr[num] = val;
+ mutex_unlock(&drvdata->lock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_msr);
+
static struct attribute *tpdm_bc_attrs[] = {
&dev_attr_bc_capture_mode.attr,
&dev_attr_bc_retrieval_mode.attr,
@@ -2522,6 +3180,23 @@ static struct attribute *tpdm_tc_attrs[] = {
NULL,
};

+static struct attribute *tpdm_dsb_attrs[] = {
+ &dev_attr_dsb_mode.attr,
+ &dev_attr_dsb_edge_ctrl.attr,
+ &dev_attr_dsb_edge_ctrl_mask.attr,
+ &dev_attr_dsb_patt_val.attr,
+ &dev_attr_dsb_patt_mask.attr,
+ &dev_attr_dsb_patt_ts.attr,
+ &dev_attr_dsb_patt_type.attr,
+ &dev_attr_dsb_trig_patt_val.attr,
+ &dev_attr_dsb_trig_patt_mask.attr,
+ &dev_attr_dsb_trig_ts.attr,
+ &dev_attr_dsb_trig_type.attr,
+ &dev_attr_dsb_select_val.attr,
+ &dev_attr_dsb_msr.attr,
+ NULL,
+};
+
static struct attribute_group tpdm_bc_attr_grp = {
.attrs = tpdm_bc_attrs,
};
@@ -2530,6 +3205,10 @@ static struct attribute_group tpdm_tc_attr_grp = {
.attrs = tpdm_tc_attrs,
};

+static struct attribute_group tpdm_dsb_attr_grp = {
+ .attrs = tpdm_dsb_attrs,
+};
+
static struct attribute *tpdm_attrs[] = {
&dev_attr_available_datasets.attr,
&dev_attr_enable_datasets.attr,
@@ -2547,6 +3226,7 @@ static const struct attribute_group *tpdm_attr_grps[] = {
&tpdm_attr_grp,
&tpdm_bc_attr_grp,
&tpdm_tc_attr_grp,
+ &tpdm_dsb_attr_grp,
NULL,
};

--
2.17.1
\
 
 \ /
  Last update: 2021-10-21 09:40    [W:0.240 / U:1.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site