aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/xilinx_tmr_inject.c
diff options
context:
space:
mode:
authorLinus Torvalds <[email protected]>2023-02-24 20:47:33 +0000
committerLinus Torvalds <[email protected]>2023-02-24 20:47:33 +0000
commit693fed981eb9bf6e70bfda66bb872e2bb8155671 (patch)
treef37b03fde9901e75fa77d6943ee54b29f9064f53 /drivers/misc/xilinx_tmr_inject.c
parentMerge tag 'staging-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff)
parentscripts/tags.sh: fix incompatibility with PCRE2 (diff)
downloadkernel-693fed981eb9bf6e70bfda66bb872e2bb8155671.tar.gz
kernel-693fed981eb9bf6e70bfda66bb872e2bb8155671.zip
Merge tag 'char-misc-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc and other driver subsystem updates from Greg KH: "Here is the large set of driver changes for char/misc drivers and other smaller driver subsystems that flow through this git tree. Included in here are: - New IIO drivers and features and improvments in that subsystem - New hwtracing drivers and additions to that subsystem - lots of interconnect changes and new drivers as that subsystem seems under very active development recently. This required also merging in the icc subsystem changes through this tree. - FPGA driver updates - counter subsystem and driver updates - MHI driver updates - nvmem driver updates - documentation updates - Other smaller driver updates and fixes, full details in the shortlog All of these have been in linux-next for a while with no reported problems" * tag 'char-misc-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (223 commits) scripts/tags.sh: fix incompatibility with PCRE2 firmware: coreboot: Remove GOOGLE_COREBOOT_TABLE_ACPI/OF Kconfig entries mei: lower the log level for non-fatal failed messages mei: bus: disallow driver match while dismantling device misc: vmw_balloon: fix memory leak with using debugfs_lookup() nvmem: stm32: fix OPTEE dependency dt-bindings: nvmem: qfprom: add IPQ8074 compatible nvmem: qcom-spmi-sdam: register at device init time nvmem: rave-sp-eeprm: fix kernel-doc bad line warning nvmem: stm32: detect bsec pta presence for STM32MP15x nvmem: stm32: add OP-TEE support for STM32MP13x nvmem: core: use nvmem_add_one_cell() in nvmem_add_cells_from_of() nvmem: core: add nvmem_add_one_cell() nvmem: core: drop the removal of the cells in nvmem_add_cells() nvmem: core: move struct nvmem_cell_info to nvmem-provider.h nvmem: core: add an index parameter to the cell of: property: add #nvmem-cell-cells property of: property: make #.*-cells optional for simple props of: base: add of_parse_phandle_with_optional_args() net: add helper eth_addr_add() ...
Diffstat (limited to 'drivers/misc/xilinx_tmr_inject.c')
-rw-r--r--drivers/misc/xilinx_tmr_inject.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/drivers/misc/xilinx_tmr_inject.c b/drivers/misc/xilinx_tmr_inject.c
new file mode 100644
index 000000000000..d96f6d7cd109
--- /dev/null
+++ b/drivers/misc/xilinx_tmr_inject.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx TMR Inject IP.
+ *
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ *
+ * Description:
+ * This driver is developed for TMR Inject IP,The Triple Modular Redundancy(TMR)
+ * Inject provides fault injection.
+ */
+
+#include <asm/xilinx_mb_manager.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/fault-inject.h>
+
+/* TMR Inject Register offsets */
+#define XTMR_INJECT_CR_OFFSET 0x0
+#define XTMR_INJECT_AIR_OFFSET 0x4
+#define XTMR_INJECT_IIR_OFFSET 0xC
+#define XTMR_INJECT_EAIR_OFFSET 0x10
+#define XTMR_INJECT_ERR_OFFSET 0x204
+
+/* Register Bitmasks/shifts */
+#define XTMR_INJECT_CR_CPUID_SHIFT 8
+#define XTMR_INJECT_CR_IE_SHIFT 10
+#define XTMR_INJECT_IIR_ADDR_MASK GENMASK(31, 16)
+
+#define XTMR_INJECT_MAGIC_MAX_VAL 255
+
+/**
+ * struct xtmr_inject_dev - Driver data for TMR Inject
+ * @regs: device physical base address
+ * @magic: Magic hardware configuration value
+ */
+struct xtmr_inject_dev {
+ void __iomem *regs;
+ u32 magic;
+};
+
+static DECLARE_FAULT_ATTR(inject_fault);
+static char *inject_request;
+module_param(inject_request, charp, 0);
+MODULE_PARM_DESC(inject_request, "default fault injection attributes");
+static struct dentry *dbgfs_root;
+
+/* IO accessors */
+static inline void xtmr_inject_write(struct xtmr_inject_dev *xtmr_inject,
+ u32 addr, u32 value)
+{
+ iowrite32(value, xtmr_inject->regs + addr);
+}
+
+static inline u32 xtmr_inject_read(struct xtmr_inject_dev *xtmr_inject,
+ u32 addr)
+{
+ return ioread32(xtmr_inject->regs + addr);
+}
+
+static int xtmr_inject_set(void *data, u64 val)
+{
+ if (val != 1)
+ return -EINVAL;
+
+ xmb_inject_err();
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(xtmr_inject_fops, NULL, xtmr_inject_set, "%llu\n");
+
+static void xtmr_init_debugfs(struct xtmr_inject_dev *xtmr_inject)
+{
+ struct dentry *dir;
+
+ dbgfs_root = debugfs_create_dir("xtmr_inject", NULL);
+ dir = fault_create_debugfs_attr("inject_fault", dbgfs_root,
+ &inject_fault);
+ debugfs_create_file("inject_fault", 0200, dir, NULL,
+ &xtmr_inject_fops);
+}
+
+static void xtmr_inject_init(struct xtmr_inject_dev *xtmr_inject)
+{
+ u32 cr_val;
+
+ if (inject_request)
+ setup_fault_attr(&inject_fault, inject_request);
+ /* Allow fault injection */
+ cr_val = xtmr_inject->magic |
+ (1 << XTMR_INJECT_CR_IE_SHIFT) |
+ (1 << XTMR_INJECT_CR_CPUID_SHIFT);
+ xtmr_inject_write(xtmr_inject, XTMR_INJECT_CR_OFFSET,
+ cr_val);
+ /* Initialize the address inject and instruction inject registers */
+ xtmr_inject_write(xtmr_inject, XTMR_INJECT_AIR_OFFSET,
+ XMB_INJECT_ERR_OFFSET);
+ xtmr_inject_write(xtmr_inject, XTMR_INJECT_IIR_OFFSET,
+ XMB_INJECT_ERR_OFFSET & XTMR_INJECT_IIR_ADDR_MASK);
+}
+
+/**
+ * xtmr_inject_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * This is the driver probe routine. It does all the memory
+ * allocation for the device.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xtmr_inject_probe(struct platform_device *pdev)
+{
+ struct xtmr_inject_dev *xtmr_inject;
+ int err;
+
+ xtmr_inject = devm_kzalloc(&pdev->dev, sizeof(*xtmr_inject),
+ GFP_KERNEL);
+ if (!xtmr_inject)
+ return -ENOMEM;
+
+ xtmr_inject->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xtmr_inject->regs))
+ return PTR_ERR(xtmr_inject->regs);
+
+ err = of_property_read_u32(pdev->dev.of_node, "xlnx,magic",
+ &xtmr_inject->magic);
+ if (err < 0) {
+ dev_err(&pdev->dev, "unable to read xlnx,magic property");
+ return err;
+ }
+
+ if (xtmr_inject->magic > XTMR_INJECT_MAGIC_MAX_VAL) {
+ dev_err(&pdev->dev, "invalid xlnx,magic property value");
+ return -EINVAL;
+ }
+
+ /* Initialize TMR Inject */
+ xtmr_inject_init(xtmr_inject);
+
+ xtmr_init_debugfs(xtmr_inject);
+
+ platform_set_drvdata(pdev, xtmr_inject);
+
+ return 0;
+}
+
+static int xtmr_inject_remove(struct platform_device *pdev)
+{
+ debugfs_remove_recursive(dbgfs_root);
+ dbgfs_root = NULL;
+ return 0;
+}
+
+static const struct of_device_id xtmr_inject_of_match[] = {
+ {
+ .compatible = "xlnx,tmr-inject-1.0",
+ },
+ { /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xtmr_inject_of_match);
+
+static struct platform_driver xtmr_inject_driver = {
+ .driver = {
+ .name = "xilinx-tmr_inject",
+ .of_match_table = xtmr_inject_of_match,
+ },
+ .probe = xtmr_inject_probe,
+ .remove = xtmr_inject_remove,
+};
+module_platform_driver(xtmr_inject_driver);
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("Xilinx TMR Inject Driver");
+MODULE_LICENSE("GPL");