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