diff options
| author | Linus Torvalds <[email protected]> | 2023-02-24 20:47:33 +0000 |
|---|---|---|
| committer | Linus Torvalds <[email protected]> | 2023-02-24 20:47:33 +0000 |
| commit | 693fed981eb9bf6e70bfda66bb872e2bb8155671 (patch) | |
| tree | f37b03fde9901e75fa77d6943ee54b29f9064f53 /drivers/misc/xilinx_tmr_inject.c | |
| parent | Merge tag 'staging-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
| parent | scripts/tags.sh: fix incompatibility with PCRE2 (diff) | |
| download | kernel-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.c | 171 |
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"); |
