xilinx_tmr_manager.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for Xilinx TMR Manager IP.
  4. *
  5. * Copyright (C) 2022 Advanced Micro Devices, Inc.
  6. *
  7. * Description:
  8. * This driver is developed for TMR Manager,The Triple Modular Redundancy(TMR)
  9. * Manager is responsible for handling the TMR subsystem state, including
  10. * fault detection and error recovery. The core is triplicated in each of
  11. * the sub-blocks in the TMR subsystem, and provides majority voting of
  12. * its internal state provides soft error detection, correction and
  13. * recovery.
  14. */
  15. #include <asm/xilinx_mb_manager.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/platform_device.h>
  19. /* TMR Manager Register offsets */
  20. #define XTMR_MANAGER_CR_OFFSET 0x0
  21. #define XTMR_MANAGER_FFR_OFFSET 0x4
  22. #define XTMR_MANAGER_CMR0_OFFSET 0x8
  23. #define XTMR_MANAGER_CMR1_OFFSET 0xC
  24. #define XTMR_MANAGER_BDIR_OFFSET 0x10
  25. #define XTMR_MANAGER_SEMIMR_OFFSET 0x1C
  26. /* Register Bitmasks/shifts */
  27. #define XTMR_MANAGER_CR_MAGIC1_MASK GENMASK(7, 0)
  28. #define XTMR_MANAGER_CR_MAGIC2_MASK GENMASK(15, 8)
  29. #define XTMR_MANAGER_CR_RIR_MASK BIT(16)
  30. #define XTMR_MANAGER_FFR_LM12_MASK BIT(0)
  31. #define XTMR_MANAGER_FFR_LM13_MASK BIT(1)
  32. #define XTMR_MANAGER_FFR_LM23_MASK BIT(2)
  33. #define XTMR_MANAGER_CR_MAGIC2_SHIFT 4
  34. #define XTMR_MANAGER_CR_RIR_SHIFT 16
  35. #define XTMR_MANAGER_CR_BB_SHIFT 18
  36. #define XTMR_MANAGER_MAGIC1_MAX_VAL 255
  37. /**
  38. * struct xtmr_manager_dev - Driver data for TMR Manager
  39. * @regs: device physical base address
  40. * @cr_val: control register value
  41. * @magic1: Magic 1 hardware configuration value
  42. * @err_cnt: error statistics count
  43. * @phys_baseaddr: Physical base address
  44. */
  45. struct xtmr_manager_dev {
  46. void __iomem *regs;
  47. u32 cr_val;
  48. u32 magic1;
  49. u32 err_cnt;
  50. resource_size_t phys_baseaddr;
  51. };
  52. /* IO accessors */
  53. static inline void xtmr_manager_write(struct xtmr_manager_dev *xtmr_manager,
  54. u32 addr, u32 value)
  55. {
  56. iowrite32(value, xtmr_manager->regs + addr);
  57. }
  58. static inline u32 xtmr_manager_read(struct xtmr_manager_dev *xtmr_manager,
  59. u32 addr)
  60. {
  61. return ioread32(xtmr_manager->regs + addr);
  62. }
  63. static void xmb_manager_reset_handler(struct xtmr_manager_dev *xtmr_manager)
  64. {
  65. /* Clear the FFR Register contents as a part of recovery process. */
  66. xtmr_manager_write(xtmr_manager, XTMR_MANAGER_FFR_OFFSET, 0);
  67. }
  68. static void xmb_manager_update_errcnt(struct xtmr_manager_dev *xtmr_manager)
  69. {
  70. xtmr_manager->err_cnt++;
  71. }
  72. static ssize_t errcnt_show(struct device *dev, struct device_attribute *attr,
  73. char *buf)
  74. {
  75. struct xtmr_manager_dev *xtmr_manager = dev_get_drvdata(dev);
  76. return sysfs_emit(buf, "%x\n", xtmr_manager->err_cnt);
  77. }
  78. static DEVICE_ATTR_RO(errcnt);
  79. static ssize_t dis_block_break_store(struct device *dev,
  80. struct device_attribute *attr,
  81. const char *buf, size_t size)
  82. {
  83. struct xtmr_manager_dev *xtmr_manager = dev_get_drvdata(dev);
  84. int ret;
  85. long value;
  86. ret = kstrtoul(buf, 16, &value);
  87. if (ret)
  88. return ret;
  89. /* unblock the break signal*/
  90. xtmr_manager->cr_val &= ~(1 << XTMR_MANAGER_CR_BB_SHIFT);
  91. xtmr_manager_write(xtmr_manager, XTMR_MANAGER_CR_OFFSET,
  92. xtmr_manager->cr_val);
  93. return size;
  94. }
  95. static DEVICE_ATTR_WO(dis_block_break);
  96. static struct attribute *xtmr_manager_dev_attrs[] = {
  97. &dev_attr_dis_block_break.attr,
  98. &dev_attr_errcnt.attr,
  99. NULL,
  100. };
  101. ATTRIBUTE_GROUPS(xtmr_manager_dev);
  102. static void xtmr_manager_init(struct xtmr_manager_dev *xtmr_manager)
  103. {
  104. /* Clear the SEM interrupt mask register to disable the interrupt */
  105. xtmr_manager_write(xtmr_manager, XTMR_MANAGER_SEMIMR_OFFSET, 0);
  106. /* Allow recovery reset by default */
  107. xtmr_manager->cr_val = (1 << XTMR_MANAGER_CR_RIR_SHIFT) |
  108. xtmr_manager->magic1;
  109. xtmr_manager_write(xtmr_manager, XTMR_MANAGER_CR_OFFSET,
  110. xtmr_manager->cr_val);
  111. /*
  112. * Configure Break Delay Initialization Register to zero so that
  113. * break occurs immediately
  114. */
  115. xtmr_manager_write(xtmr_manager, XTMR_MANAGER_BDIR_OFFSET, 0);
  116. /*
  117. * To come out of break handler need to block the break signal
  118. * in the tmr manager, update the xtmr_manager cr_val for the same
  119. */
  120. xtmr_manager->cr_val |= (1 << XTMR_MANAGER_CR_BB_SHIFT);
  121. /*
  122. * When the break vector gets asserted because of error injection,
  123. * the break signal must be blocked before exiting from the
  124. * break handler, Below api updates the TMR manager address and
  125. * control register and error counter callback arguments,
  126. * which will be used by the break handler to block the
  127. * break and call the callback function.
  128. */
  129. xmb_manager_register(xtmr_manager->phys_baseaddr, xtmr_manager->cr_val,
  130. (void *)xmb_manager_update_errcnt,
  131. xtmr_manager, (void *)xmb_manager_reset_handler);
  132. }
  133. /**
  134. * xtmr_manager_probe - Driver probe function
  135. * @pdev: Pointer to the platform_device structure
  136. *
  137. * This is the driver probe routine. It does all the memory
  138. * allocation for the device.
  139. *
  140. * Return: 0 on success and failure value on error
  141. */
  142. static int xtmr_manager_probe(struct platform_device *pdev)
  143. {
  144. struct xtmr_manager_dev *xtmr_manager;
  145. struct resource *res;
  146. int err;
  147. xtmr_manager = devm_kzalloc(&pdev->dev, sizeof(*xtmr_manager),
  148. GFP_KERNEL);
  149. if (!xtmr_manager)
  150. return -ENOMEM;
  151. xtmr_manager->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
  152. if (IS_ERR(xtmr_manager->regs))
  153. return PTR_ERR(xtmr_manager->regs);
  154. xtmr_manager->phys_baseaddr = res->start;
  155. err = of_property_read_u32(pdev->dev.of_node, "xlnx,magic1",
  156. &xtmr_manager->magic1);
  157. if (err < 0) {
  158. dev_err(&pdev->dev, "unable to read xlnx,magic1 property");
  159. return err;
  160. }
  161. if (xtmr_manager->magic1 > XTMR_MANAGER_MAGIC1_MAX_VAL) {
  162. dev_err(&pdev->dev, "invalid xlnx,magic1 property value");
  163. return -EINVAL;
  164. }
  165. /* Initialize TMR Manager */
  166. xtmr_manager_init(xtmr_manager);
  167. platform_set_drvdata(pdev, xtmr_manager);
  168. return 0;
  169. }
  170. static const struct of_device_id xtmr_manager_of_match[] = {
  171. {
  172. .compatible = "xlnx,tmr-manager-1.0",
  173. },
  174. { /* end of table */ }
  175. };
  176. MODULE_DEVICE_TABLE(of, xtmr_manager_of_match);
  177. static struct platform_driver xtmr_manager_driver = {
  178. .driver = {
  179. .name = "xilinx-tmr_manager",
  180. .of_match_table = xtmr_manager_of_match,
  181. .dev_groups = xtmr_manager_dev_groups,
  182. },
  183. .probe = xtmr_manager_probe,
  184. };
  185. module_platform_driver(xtmr_manager_driver);
  186. MODULE_AUTHOR("Advanced Micro Devices, Inc");
  187. MODULE_DESCRIPTION("Xilinx TMR Manager Driver");
  188. MODULE_LICENSE("GPL");