[PATCH V14 2/7] soc: qcom: dcc: Add driver support for Data Capture and Compare unit(DCC)
Souradeep Chowdhury
quic_schowdhu at quicinc.com
Fri Sep 30 00:05:27 PDT 2022
On 9/28/2022 11:05 PM, Krzysztof Kozlowski wrote:
> On 28/09/2022 19:11, Souradeep Chowdhury wrote:
>> The DCC is a DMA Engine designed to capture and store data
>> during system crash or software triggers. The DCC operates
>> based on user inputs via the debugfs interface. The user gives
>> addresses as inputs and these addresses are stored in the
>> dcc sram. In case of a system crash or a manual software
>> trigger by the user through the debugfs interface,
>> the dcc captures and stores the values at these addresses.
>> This patch contains the driver which has all the methods
>> pertaining to the debugfs interface, auxiliary functions to
>> support all the four fundamental operations of dcc namely
>> read, write, read/modify/write and loop. The probe method
>> here instantiates all the resources necessary for dcc to
>> operate mainly the dedicated dcc sram where it stores the
>> values. The DCC driver can be used for debugging purposes
>> without going for a reboot since it can perform software
>> triggers as well based on user inputs.
>>
>> Also added the documentation for debugfs entries and explained
>> the functionalities of each debugfs file that has been created
>> for dcc.
>>
>> The following is the justification of using debugfs interface
>> over the other alternatives like sysfs/ioctls
>>
>> i) As can be seen from the debugfs attribute descriptions,
>> some of the debugfs attribute files here contains multiple
>> arguments which needs to be accepted from the user. This goes
>> against the design style of sysfs.
>>
>> ii) The user input patterns have been made simple and convenient
>> in this case with the use of debugfs interface as user doesn't
>> need to shuffle between different files to execute one instruction
>> as was the case on using other alternatives.
>>
>> Signed-off-by: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> ---
>> Documentation/ABI/testing/debugfs-driver-dcc | 98 ++
>> drivers/soc/qcom/Kconfig | 8 +
>> drivers/soc/qcom/Makefile | 1 +
>> drivers/soc/qcom/dcc.c | 1352 ++++++++++++++++++++++++++
>> 4 files changed, 1459 insertions(+)
>> create mode 100644 Documentation/ABI/testing/debugfs-driver-dcc
>> create mode 100644 drivers/soc/qcom/dcc.c
>>
>> diff --git a/Documentation/ABI/testing/debugfs-driver-dcc b/Documentation/ABI/testing/debugfs-driver-dcc
>> new file mode 100644
>> index 0000000..387f67e
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/debugfs-driver-dcc
>> @@ -0,0 +1,98 @@
>> +What: /sys/kernel/debug/dcc/.../ready
>> +Date: September 2022
>> +Contact: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> +Description:
>> + This file is used to check the status of the dcc
>> + hardware if it's ready to take the inputs. A 'Y'
>> + here indicates dcc is in a ready condition.
>> + Example:
>> + cat /sys/kernel/debug/dcc/.../ready
>> +
>> +What: /sys/kernel/debug/dcc/.../trigger
>> +Date: September 2022
>> +Contact: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> +Description:
>> + This is the debugfs interface for manual software
>> + triggers. The user can simply enter a 1 against
>> + the debugfs file and enable a manual trigger.
>> + Example:
>> + echo 1 > /sys/kernel/debug/dcc/.../trigger
>> +
>> +What: /sys/kernel/debug/dcc/.../config_reset
>> +Date: September 2022
>> +Contact: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> +Description:
>> + This file is used to reset the configuration of
>> + a dcc driver to the default configuration. This
>> + means that all the previous addresses stored in
>> + the driver gets removed and user needs to enter
>> + the address values from the start.
>> + Example:
>> + echo 1 > /sys/kernel/debug/dcc/../config_reset
>> +
>> +What: /sys/kernel/debug/dcc/.../[list-number]/config
>> +Date: September 2022
>> +Contact: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> +Description:
>> + This stores the addresses of the registers which
>> + should be read in case of a hardware crash or
>> + manual software triggers. The addresses entered here
>> + are considered under all the 4 types of dcc
>> + instructions Read type, Write type, Read Modify Write
>> + type and Loop type. The lists need to be configured
>> + sequentially and not in a overlapping manner. As an
>> + example user can jump to list x only after list y is
>> + configured and enabled. The format for entering all
>> + types of instructions are explained in examples as
>> + follows.
>> + Example:
>> + i)Read Type Instruction
>> + echo R <1> <2> <3> >/sys/kernel/debug/dcc/../[list-number]/config
>> + 1->Address to be considered for reading the value.
>> + 2->The word count of the addresses, read n words
>> + starting from address <1>. Each word is of 32 bits.
>> + If not entered 1 is considered.
>> + 3->Can be 'apb' or 'ahb' which indicates if it is apb or ahb
>> + bus respectively. If not entered ahb is considered.
>> + ii)Write Type Instruction
>> + echo W <1> <2> <3> > /sys/kernel/debug/dcc/../[list-number]/config
>> + 1->Address to be considered for writing the value.
>> + 2->The value that needs to be written at the location.
>> + 3->Can be a 'apb' or 'ahb' which indicates if it is apb or ahb
>> + but respectively.
>> + iii)Read Modify Write type instruction
>> + echo RW <1> <2> <3> > /sys/kernel/debug/dcc/../[list-number]/config
>> + 1->The address which needs to be considered for read then write.
>> + 2->The value that needs to be written on the address.
>> + 3->The mask of the value to be written.
>> + iv)Loop Type Instruction
>> + echo L <1> <2> <3> > /sys/kernel/debug/dcc/../[list-number]/config
>> + 1->The loop count, the number of times the value of the addresses will be
>> + captured.
>> + 2->The address count, total number of addresses to be entered in this
>> + instruction.
>> + 3->The series of addresses to be entered separated by a space like <addr1>
>> + <addr2>... and so on.
>> +
>> +What: /sys/kernel/debug/dcc/.../[list-number]/enable
>> +Date: September 2022
>> +Contact: Souradeep Chowdhury <quic_schowdhu at quicinc.com>
>> +Description:
>> + This debugfs interface is used for enabling the
>> + the dcc hardware. Enable file is kept under the
>> + directory list number for which the user wants
>> + to enable it. For example if the user wants to
>> + enable list 1, then he should go for
>> + echo 1 > /sys/kernel/debug/dcc/.../1/enable.
>> + On enabling the dcc, all the addresses entered
>> + by the user for the corresponding list is written
>> + into dcc sram which is read by the dcc hardware
>> + on manual or crash induced triggers. Lists should
>> + be enabled sequentially.For example after configuring
>> + addresses for list 1 and enabling it, a user can
>> + proceed to enable list 2 or vice versa.
>> + Example:
>> + echo 0 > /sys/kernel/debug/dcc/.../[list-number]/enable
>> + (disable dcc for the corresponding list number)
>> + echo 1 > /sys/kernel/debug/dcc/.../[list-number]/enable
>> + (enable dcc for the corresponding list number)
>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>> index 024e420..d5730bf 100644
>> --- a/drivers/soc/qcom/Kconfig
>> +++ b/drivers/soc/qcom/Kconfig
>> @@ -69,6 +69,14 @@ config QCOM_LLCC
>> SDM845. This provides interfaces to clients that use the LLCC.
>> Say yes here to enable LLCC slice driver.
>>
>> +config QCOM_DCC
>> + tristate "Qualcomm Technologies, Inc. Data Capture and Compare(DCC) engine driver"
>> + depends on ARCH_QCOM || COMPILE_TEST
>> + help
>> + This option enables driver for Data Capture and Compare engine. DCC
>> + driver provides interface to configure DCC block and read back
>> + captured data from DCC's internal SRAM.
>> +
>> config QCOM_KRYO_L2_ACCESSORS
>> bool
>> depends on ARCH_QCOM && ARM64 || COMPILE_TEST
>> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
>> index d66604a..b1fe812 100644
>> --- a/drivers/soc/qcom/Makefile
>> +++ b/drivers/soc/qcom/Makefile
>> @@ -4,6 +4,7 @@ obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
>> obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
>> obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
>> obj-$(CONFIG_QCOM_CPR) += cpr.o
>> +obj-$(CONFIG_QCOM_DCC) += dcc.o
>> obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
>> obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
>> obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
>> diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
>> new file mode 100644
>> index 0000000..e16c074
>> --- /dev/null
>> +++ b/drivers/soc/qcom/dcc.c
>> @@ -0,0 +1,1352 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include <linux/bitfield.h>
>> +#include <linux/bitops.h>
>> +#include <linux/debugfs.h>
>> +#include <linux/delay.h>
>> +#include <linux/fs.h>
>> +#include <linux/io.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/miscdevice.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +
>> +#define STATUS_READY_TIMEOUT 5000 /*microseconds*/
>> +
>> +#define DCC_SRAM_NODE "dcc_sram"
>> +
>> +/* DCC registers */
>> +#define DCC_HW_INFO 0x04
>> +#define DCC_LL_NUM_INFO 0x10
>> +#define DCC_STATUS(vers) ((vers) == 1 ? 0x0c : 0x1c)
>> +#define DCC_LL_LOCK 0x00
>> +#define DCC_LL_CFG 0x04
>> +#define DCC_LL_BASE 0x08
>> +#define DCC_FD_BASE 0x0c
>> +#define DCC_LL_TIMEOUT 0x10
>> +#define DCC_LL_INT_ENABLE 0x18
>> +#define DCC_LL_INT_STATUS 0x1c
>> +#define DCC_LL_SW_TRIGGER 0x2c
>> +#define DCC_LL_BUS_ACCESS_STATUS 0x30
>> +
>> +#define DCC_MAP_LEVEL1 0x18
>> +#define DCC_MAP_LEVEL2 0x34
>> +#define DCC_MAP_LEVEL3 0x4C
>> +
>> +#define DCC_MAP_OFFSET1 0x10
>> +#define DCC_MAP_OFFSET2 0x18
>> +#define DCC_MAP_OFFSET3 0x1C
>> +#define DCC_MAP_OFFSET4 0x8
>> +
>> +/*Default value used if a bit 6 in the HW_INFO register is set.*/
>> +#define DCC_FIX_LOOP_OFFSET 16
>> +
>> +/*Mask to find version info from HW_Info register*/
>> +#define DCC_VER_INFO_MASK BIT(9)
>> +
>> +#define DCC_READ 0
>> +#define DCC_WRITE 1
>> +#define DCC_LOOP 2
>> +#define DCC_READ_WRITE 3
>> +
>> +#define MAX_DCC_OFFSET GENMASK(9, 2)
>> +#define MAX_DCC_LEN GENMASK(6, 0)
>> +#define MAX_LOOP_CNT GENMASK(7, 0)
>> +#define MAX_LOOP_ADDR 10
>> +
>> +#define DCC_ADDR_DESCRIPTOR 0x00
>> +#define DCC_ADDR_LIMIT 27
>> +#define DCC_ADDR_OFF_RANGE 8
>> +#define DCC_ADDR_RANGE_MASK GENMASK(31, 4)
>> +#define DCC_LOOP_DESCRIPTOR BIT(30)
>> +#define DCC_RD_MOD_WR_DESCRIPTOR BIT(31)
>> +#define DCC_LINK_DESCRIPTOR GENMASK(31, 30)
>> +#define DCC_STATUS_MASK GENMASK(1, 0)
>> +#define DCC_LOCK_MASK BIT(0)
>> +#define DCC_LOOP_OFFSET_MASK BIT(6)
>> +#define DCC_TRIGGER_MASK BIT(9)
>> +
>> +#define DCC_WRITE_MASK BIT(15)
>> +#define DCC_WRITE_OFF_MASK GENMASK(7, 0)
>> +#define DCC_WRITE_LEN_MASK GENMASK(14, 8)
>> +
>> +#define DCC_READ_IND 0x00
>> +#define DCC_WRITE_IND (BIT(28))
>> +
>> +#define DCC_AHB_IND 0x00
>> +#define DCC_APB_IND BIT(29)
>> +
>> +#define DCC_MAX_LINK_LIST 8
>> +#define DCC_INVALID_LINK_LIST GENMASK(7, 0)
>> +
>> +#define DCC_VER_MASK1 GENMASK(6, 0)
>> +#define DCC_VER_MASK2 GENMASK(5, 0)
>> +
>> +#define DCC_SRAM_WORD_LENGTH 4
>> +
>> +#define DCC_RD_MOD_WR_ADDR 0xC105E
>> +
>> +/*DCC debugfs directory*/
>> +static struct dentry *dcc_dbg;
>> +
>> +enum dcc_descriptor_type {
>> + DCC_READ_TYPE,
>> + DCC_LOOP_TYPE,
>> + DCC_READ_WRITE_TYPE,
>> + DCC_WRITE_TYPE
>> +};
>> +
>> +struct dcc_config_entry {
>> + u32 base;
>> + u32 offset;
>> + u32 len;
>> + u32 loop_cnt;
>> + u32 write_val;
>> + u32 mask;
>> + bool apb_bus;
>> + enum dcc_descriptor_type desc_type;
>> + struct list_head list;
>> +};
>> +
>> +/**
>> + * struct dcc_drvdata - configuration information related to a dcc device
>> + * @base: Base Address of the dcc device
>> + * @dev: The device attached to the driver data
>> + * @mutex: Lock to protect access and manipulation of dcc_drvdata
>> + * @ram_base: Base address for the SRAM dedicated for the dcc device
>> + * @ram_size: Total size of the SRAM dedicated for the dcc device
>> + * @ram_offset: Offset to the SRAM dedicated for dcc device
>> + * @mem_map_ver: Memory map version of DCC hardware
>> + * @ram_cfg: Used for address limit calculation for dcc
>> + * @ram_start: Starting address of DCC SRAM
>> + * @sram_dev: Miscellaneous device equivalent of dcc SRAM
>> + * @cfg_head: Points to the head of the linked list of addresses
> So where is the list item? Is it dcc_config_entry?
Yes that's right.
>
>> + * @dbg_dir: The dcc debugfs directory under which all the debugfs files are placed
>> + * @nr_link_list: Total number of linkedlists supported by the DCC configuration
>> + * @loopoff: Loop offset bits range for the addresses
>> + * @enable; This contains an array of linkedlist enable flags
> Typo: ;
>
> Compile it with W=1 and fix all the warnings.
>
> The description of this field still looks wrong. It does not have array
> of linked lists. Linked list is list_head, this is a bool.
Ack
>
> Best regards,
> Krzysztof
>
More information about the linux-arm-kernel
mailing list