[PATCH V14 2/7] soc: qcom: dcc: Add driver support for Data Capture and Compare unit(DCC)
Krzysztof Kozlowski
krzk at kernel.org
Wed Sep 28 10:35:30 PDT 2022
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?
> + * @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.
Best regards,
Krzysztof
More information about the linux-arm-kernel
mailing list