--- /dev/null
+// 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");