[v7,08/13] coresight-tpdm: Add node to set dsb programming mode
Commit Message
Add node to set and show programming mode for TPDM DSB subunit.
Once the DSB programming mode is set, it will be written to the
register DSB_CR.
Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
---
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++
drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++
3 files changed, 93 insertions(+)
Comments
Hi Tao,
kernel test robot noticed the following build warnings:
[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.5-rc3 next-20230725]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Tao-Zhang/coresight-tpdm-Remove-the-unnecessary-lock/20230725-152235
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/1690269353-10829-9-git-send-email-quic_taozha%40quicinc.com
patch subject: [PATCH v7 08/13] coresight-tpdm: Add node to set dsb programming mode
reproduce: (https://download.01.org/0day-ci/archive/20230726/202307260312.vf3OCV58-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202307260312.vf3OCV58-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm:50: WARNING: Unexpected indentation.
>> Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm:50: WARNING: Block quote ends without a blank line; unexpected unindent.
vim +50 Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> 50 Date: March 2023
On 25/07/2023 08:15, Tao Zhang wrote:
> Add node to set and show programming mode for TPDM DSB subunit.
> Once the DSB programming mode is set, it will be written to the
> register DSB_CR.
>
> Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++
> drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++
> drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++
> 3 files changed, 93 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> index 0b7b4ad..2a82cd0 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> @@ -45,3 +45,18 @@ Description:
> Accepts only one of the 2 values - 0 or 1.
> 0 : Set the DSB trigger type to false
> 1 : Set the DSB trigger type to true
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
> +Description:
> + (Write) Set the mode of DSB tpdm. Read the mode of DSB
> + tpdm.
(RW) ...
> +
> + Accepts the value needs to be greater than 0. What data
> + bits do is listed below.
> + Bit[0:1] : Test mode control bit for choosing the inputs.
> + Bit[3] : Set to 0 for low performance mode.
> + Set to 1 for high performance mode.
> + Bit[4:8] : Select byte lane for high performance mode.
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
> index 62efc18..c38760b 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/amba/bus.h>
> +#include <linux/bitfield.h>
> #include <linux/bitmap.h>
> #include <linux/coresight.h>
> #include <linux/coresight-pmu.h>
> @@ -42,6 +43,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)
> }
> }
>
> +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val)
> +{
> + u32 mode;
> +
> + mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode);
> + *val &= ~TPDM_DSB_TEST_MODE;
> + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode);
> +}
> +
> +static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val)
> +{
> + u32 mode;
> +
> + mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
> + *val &= ~TPDM_DSB_HPSEL;
> + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode);
> +}
> +
> +static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
> +{
> + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
> + *val |= TPDM_DSB_CR_MODE;
> + else
> + *val &= ~TPDM_DSB_CR_MODE;
> +}
> +
> static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> {
> u32 val;
> @@ -55,6 +82,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
>
> val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
> + /* Set the test accurate mode */
> + set_dsb_test_mode(drvdata, &val);
> + /* Set the byte lane for high-performance mode */
> + set_dsb_hpsel_mode(drvdata, &val);
> + /* Set the performance mode */
> + set_dsb_perf_mode(drvdata, &val);
Couldn't all of them be combined to a single function, as they
operate on a single value to be written ?
set_dsb_mode(drvdata, &val);
> /* Set trigger type */
> if (drvdata->dsb->trig_type)
> val |= TPDM_DSB_CR_TRIG_TYPE;
> @@ -241,6 +274,34 @@ static struct attribute_group tpdm_attr_grp = {
> .attrs = tpdm_attrs,
> };
>
> +static ssize_t dsb_mode_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> + return sysfs_emit(buf, "%lx\n",
> + (unsigned long)drvdata->dsb->mode);
It is u32 anyways, hence why not :
(buf, "%x\n", 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, 0, &val)) || val < 0)
> + return -EINVAL;
> +
Is it not an error :
if (val & ~TPDM_DSB_MODE_MASK) ?
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK;
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_mode);
> +
> static ssize_t dsb_trig_type_show(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> @@ -312,6 +373,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
> static DEVICE_ATTR_RW(dsb_trig_ts);
>
> static struct attribute *tpdm_dsb_attrs[] = {
> + &dev_attr_dsb_mode.attr,
> &dev_attr_dsb_trig_ts.attr,
> &dev_attr_dsb_trig_type.attr,
> NULL,
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
> index 92c34cd..49fffb1 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.h
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.h
> @@ -15,11 +15,25 @@
>
> /* Enable bit for DSB subunit */
> #define TPDM_DSB_CR_ENA BIT(0)
> +/* Enable bit for DSB subunit perfmance mode */
> +#define TPDM_DSB_CR_MODE BIT(1)
> /* Enable bit for DSB subunit trigger type */
> #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
> +
> /* Enable bit for DSB subunit trigger timestamp */
> #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
>
> +/* DSB programming modes */
> +/* Test mode control bit*/
> +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0))
What is the difference between MODE_TEST ^ and the TEST_MODE ( below ).
Please could we have clear naming conventions ?
> +/* Performance mode */
> +#define TPDM_DSB_MODE_PERF BIT(3)
> +/* High performance mode */
> +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4))
> +#define TPDM_DSB_MODE_MASK GENMASK(8, 0)
> +#define TPDM_DSB_TEST_MODE GENMASK(10, 9)
> +#define TPDM_DSB_HPSEL GENMASK(6, 2)
Ah, I read it again and these two are really TPDM_DSB_CR_x and
1) Must be defined as such (to avoid any confusion as above)
2) And defined closer to the other value defintions for the registers ?
Suzuki
> +
> /* TPDM integration test registers */
> #define TPDM_ITATBCNTRL (0xEF0)
> #define TPDM_ITCNTRL (0xF00)
> @@ -48,10 +62,12 @@
>
> /**
> * struct dsb_dataset - specifics associated to dsb dataset
> + * @mode: DSB programming mode
> * @trig_ts: Enable/Disable trigger timestamp.
> * @trig_type: Enable/Disable trigger type.
> */
> struct dsb_dataset {
> + u32 mode;
> bool trig_ts;
> bool trig_type;
> };
On 8/7/2023 6:00 PM, Suzuki K Poulose wrote:
> On 25/07/2023 08:15, Tao Zhang wrote:
>> Add node to set and show programming mode for TPDM DSB subunit.
>> Once the DSB programming mode is set, it will be written to the
>> register DSB_CR.
>>
>> Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
>> ---
>> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++
>> drivers/hwtracing/coresight/coresight-tpdm.c | 62
>> ++++++++++++++++++++++
>> drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++
>> 3 files changed, 93 insertions(+)
>>
>> diff --git
>> a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> index 0b7b4ad..2a82cd0 100644
>> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> @@ -45,3 +45,18 @@ Description:
>> Accepts only one of the 2 values - 0 or 1.
>> 0 : Set the DSB trigger type to false
>> 1 : Set the DSB trigger type to true
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
>> +Date: March 2023
>> +KernelVersion 6.5
>> +Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang
>> (QUIC) <quic_taozha@quicinc.com>
>> +Description:
>> + (Write) Set the mode of DSB tpdm. Read the mode of DSB
>> + tpdm.
>
> (RW) ...
Sure, I will update this to the next patch series.
>
>> +
>> + Accepts the value needs to be greater than 0. What data
>> + bits do is listed below.
>> + Bit[0:1] : Test mode control bit for choosing the inputs.
>> + Bit[3] : Set to 0 for low performance mode.
>> + Set to 1 for high performance mode.
>> + Bit[4:8] : Select byte lane for high performance mode.
>> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c
>> b/drivers/hwtracing/coresight/coresight-tpdm.c
>> index 62efc18..c38760b 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
>> @@ -4,6 +4,7 @@
>> */
>> #include <linux/amba/bus.h>
>> +#include <linux/bitfield.h>
>> #include <linux/bitmap.h>
>> #include <linux/coresight.h>
>> #include <linux/coresight-pmu.h>
>> @@ -42,6 +43,32 @@ static void tpdm_reset_datasets(struct
>> tpdm_drvdata *drvdata)
>> }
>> }
>> +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val)
>> +{
>> + u32 mode;
>> +
>> + mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode);
>> + *val &= ~TPDM_DSB_TEST_MODE;
>> + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode);
>> +}
>> +
>> +static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val)
>> +{
>> + u32 mode;
>> +
>> + mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
>> + *val &= ~TPDM_DSB_HPSEL;
>> + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode);
>> +}
>> +
>> +static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
>> +{
>> + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
>> + *val |= TPDM_DSB_CR_MODE;
>> + else
>> + *val &= ~TPDM_DSB_CR_MODE;
>> +}
>> +
>> static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
>> {
>> u32 val;
>> @@ -55,6 +82,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata
>> *drvdata)
>> writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
>> val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
>
>> + /* Set the test accurate mode */
>> + set_dsb_test_mode(drvdata, &val);
>> + /* Set the byte lane for high-performance mode */
>> + set_dsb_hpsel_mode(drvdata, &val);
>> + /* Set the performance mode */
>> + set_dsb_perf_mode(drvdata, &val);
>
> Couldn't all of them be combined to a single function, as they
> operate on a single value to be written ?
>
> set_dsb_mode(drvdata, &val);
>
Yes, I will update this to the next patch series.
>
>> /* Set trigger type */
>> if (drvdata->dsb->trig_type)
>> val |= TPDM_DSB_CR_TRIG_TYPE;
>> @@ -241,6 +274,34 @@ static struct attribute_group tpdm_attr_grp = {
>> .attrs = tpdm_attrs,
>> };
>> +static ssize_t dsb_mode_show(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +
>> + return sysfs_emit(buf, "%lx\n",
>> + (unsigned long)drvdata->dsb->mode);
>
> It is u32 anyways, hence why not :
>
> (buf, "%x\n", drvdata->dsb->mode) ?
>
Sure, I will update this to the next patch series.
>
>> +}
>> +
>> +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, 0, &val)) || val < 0)
>> + return -EINVAL;
>> +
>
> Is it not an error :
> if (val & ~TPDM_DSB_MODE_MASK) ?
We don't need to care about the data bits besides TPDM_DSB_MODE_MASK.
Do you think it is necessary to add this check?
If so, I can add this check in the next patch series.
>
>> + spin_lock(&drvdata->spinlock);
>> + drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK;
>> + spin_unlock(&drvdata->spinlock);
>> + return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_mode);
>> +
>> static ssize_t dsb_trig_type_show(struct device *dev,
>> struct device_attribute *attr, char *buf)
>> {
>> @@ -312,6 +373,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
>> static DEVICE_ATTR_RW(dsb_trig_ts);
>> static struct attribute *tpdm_dsb_attrs[] = {
>> + &dev_attr_dsb_mode.attr,
>> &dev_attr_dsb_trig_ts.attr,
>> &dev_attr_dsb_trig_type.attr,
>> NULL,
>> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h
>> b/drivers/hwtracing/coresight/coresight-tpdm.h
>> index 92c34cd..49fffb1 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpdm.h
>> +++ b/drivers/hwtracing/coresight/coresight-tpdm.h
>> @@ -15,11 +15,25 @@
>> /* Enable bit for DSB subunit */
>> #define TPDM_DSB_CR_ENA BIT(0)
>> +/* Enable bit for DSB subunit perfmance mode */
>> +#define TPDM_DSB_CR_MODE BIT(1)
>> /* Enable bit for DSB subunit trigger type */
>> #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
>> +
>> /* Enable bit for DSB subunit trigger timestamp */
>> #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
>> +/* DSB programming modes */
>> +/* Test mode control bit*/
>> +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0))
>
> What is the difference between MODE_TEST ^ and the TEST_MODE ( below ).
> Please could we have clear naming conventions ?
"TPDM_DSB_MODE_TEST" is to collect the data of test mode from user space
input.
"TPDM_DSB_TEST_MODE" is to set the data bits collected by
"TPDM_DSB_MODE_TEST"
to "TPDM_DSB_CR" register.
I will prefix the macro which is related to "TPDM_DSB_CR" to identify.
>
>> +/* Performance mode */
>> +#define TPDM_DSB_MODE_PERF BIT(3)
>
>> +/* High performance mode */
>> +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4))
>> +#define TPDM_DSB_MODE_MASK GENMASK(8, 0)
>
>
>> +#define TPDM_DSB_TEST_MODE GENMASK(10, 9)
>> +#define TPDM_DSB_HPSEL GENMASK(6, 2)
>
> Ah, I read it again and these two are really TPDM_DSB_CR_x and
> 1) Must be defined as such (to avoid any confusion as above)
> 2) And defined closer to the other value defintions for the registers ?
Sure, I will update this according to your advice in the next patch series.
Best,
Tao
>
>
> Suzuki
>
>> +
>> /* TPDM integration test registers */
>> #define TPDM_ITATBCNTRL (0xEF0)
>> #define TPDM_ITCNTRL (0xF00)
>> @@ -48,10 +62,12 @@
>> /**
>> * struct dsb_dataset - specifics associated to dsb dataset
>> + * @mode: DSB programming mode
>> * @trig_ts: Enable/Disable trigger timestamp.
>> * @trig_type: Enable/Disable trigger type.
>> */
>> struct dsb_dataset {
>> + u32 mode;
>> bool trig_ts;
>> bool trig_type;
>> };
>
@@ -45,3 +45,18 @@ Description:
Accepts only one of the 2 values - 0 or 1.
0 : Set the DSB trigger type to false
1 : Set the DSB trigger type to true
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+ (Write) Set the mode of DSB tpdm. Read the mode of DSB
+ tpdm.
+
+ Accepts the value needs to be greater than 0. What data
+ bits do is listed below.
+ Bit[0:1] : Test mode control bit for choosing the inputs.
+ Bit[3] : Set to 0 for low performance mode.
+ Set to 1 for high performance mode.
+ Bit[4:8] : Select byte lane for high performance mode.
@@ -4,6 +4,7 @@
*/
#include <linux/amba/bus.h>
+#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/coresight.h>
#include <linux/coresight-pmu.h>
@@ -42,6 +43,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)
}
}
+static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val)
+{
+ u32 mode;
+
+ mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode);
+ *val &= ~TPDM_DSB_TEST_MODE;
+ *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode);
+}
+
+static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val)
+{
+ u32 mode;
+
+ mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
+ *val &= ~TPDM_DSB_HPSEL;
+ *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode);
+}
+
+static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
+{
+ if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
+ *val |= TPDM_DSB_CR_MODE;
+ else
+ *val &= ~TPDM_DSB_CR_MODE;
+}
+
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
{
u32 val;
@@ -55,6 +82,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
+ /* Set the test accurate mode */
+ set_dsb_test_mode(drvdata, &val);
+ /* Set the byte lane for high-performance mode */
+ set_dsb_hpsel_mode(drvdata, &val);
+ /* Set the performance mode */
+ set_dsb_perf_mode(drvdata, &val);
/* Set trigger type */
if (drvdata->dsb->trig_type)
val |= TPDM_DSB_CR_TRIG_TYPE;
@@ -241,6 +274,34 @@ static struct attribute_group tpdm_attr_grp = {
.attrs = tpdm_attrs,
};
+static ssize_t dsb_mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ return sysfs_emit(buf, "%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, 0, &val)) || val < 0)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_mode);
+
static ssize_t dsb_trig_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -312,6 +373,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
static DEVICE_ATTR_RW(dsb_trig_ts);
static struct attribute *tpdm_dsb_attrs[] = {
+ &dev_attr_dsb_mode.attr,
&dev_attr_dsb_trig_ts.attr,
&dev_attr_dsb_trig_type.attr,
NULL,
@@ -15,11 +15,25 @@
/* Enable bit for DSB subunit */
#define TPDM_DSB_CR_ENA BIT(0)
+/* Enable bit for DSB subunit perfmance mode */
+#define TPDM_DSB_CR_MODE BIT(1)
/* Enable bit for DSB subunit trigger type */
#define TPDM_DSB_CR_TRIG_TYPE BIT(12)
+
/* Enable bit for DSB subunit trigger timestamp */
#define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
+/* DSB programming modes */
+/* Test mode control bit*/
+#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0))
+/* Performance mode */
+#define TPDM_DSB_MODE_PERF BIT(3)
+/* High performance mode */
+#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4))
+#define TPDM_DSB_MODE_MASK GENMASK(8, 0)
+#define TPDM_DSB_TEST_MODE GENMASK(10, 9)
+#define TPDM_DSB_HPSEL GENMASK(6, 2)
+
/* TPDM integration test registers */
#define TPDM_ITATBCNTRL (0xEF0)
#define TPDM_ITCNTRL (0xF00)
@@ -48,10 +62,12 @@
/**
* struct dsb_dataset - specifics associated to dsb dataset
+ * @mode: DSB programming mode
* @trig_ts: Enable/Disable trigger timestamp.
* @trig_type: Enable/Disable trigger type.
*/
struct dsb_dataset {
+ u32 mode;
bool trig_ts;
bool trig_type;
};