Commit | Line | Data |
---|---|---|
4a4a4e9e QN |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | |
3 | * Ampere Computing SoC's SMpro Error Monitoring Driver | |
4 | * | |
5 | * Copyright (c) 2022, Ampere Computing LLC | |
6 | * | |
7 | */ | |
8 | ||
4a4a4e9e QN |
9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/module.h> | |
11 | #include <linux/platform_device.h> | |
12 | #include <linux/regmap.h> | |
13 | ||
14 | /* GPI RAS Error Registers */ | |
15 | #define GPI_RAS_ERR 0x7E | |
16 | ||
17 | /* Core and L2C Error Registers */ | |
18 | #define CORE_CE_ERR_CNT 0x80 | |
19 | #define CORE_CE_ERR_LEN 0x81 | |
20 | #define CORE_CE_ERR_DATA 0x82 | |
21 | #define CORE_UE_ERR_CNT 0x83 | |
22 | #define CORE_UE_ERR_LEN 0x84 | |
23 | #define CORE_UE_ERR_DATA 0x85 | |
24 | ||
25 | /* Memory Error Registers */ | |
26 | #define MEM_CE_ERR_CNT 0x90 | |
27 | #define MEM_CE_ERR_LEN 0x91 | |
28 | #define MEM_CE_ERR_DATA 0x92 | |
29 | #define MEM_UE_ERR_CNT 0x93 | |
30 | #define MEM_UE_ERR_LEN 0x94 | |
31 | #define MEM_UE_ERR_DATA 0x95 | |
32 | ||
33 | /* RAS Error/Warning Registers */ | |
34 | #define ERR_SMPRO_TYPE 0xA0 | |
35 | #define ERR_PMPRO_TYPE 0xA1 | |
36 | #define ERR_SMPRO_INFO_LO 0xA2 | |
37 | #define ERR_SMPRO_INFO_HI 0xA3 | |
38 | #define ERR_SMPRO_DATA_LO 0xA4 | |
39 | #define ERR_SMPRO_DATA_HI 0xA5 | |
40 | #define WARN_SMPRO_INFO_LO 0xAA | |
41 | #define WARN_SMPRO_INFO_HI 0xAB | |
42 | #define ERR_PMPRO_INFO_LO 0xA6 | |
43 | #define ERR_PMPRO_INFO_HI 0xA7 | |
44 | #define ERR_PMPRO_DATA_LO 0xA8 | |
45 | #define ERR_PMPRO_DATA_HI 0xA9 | |
46 | #define WARN_PMPRO_INFO_LO 0xAC | |
47 | #define WARN_PMPRO_INFO_HI 0xAD | |
48 | ||
c2c99326 QN |
49 | /* Boot Stage Register */ |
50 | #define BOOTSTAGE 0xB0 | |
51 | #define DIMM_SYNDROME_SEL 0xB4 | |
52 | #define DIMM_SYNDROME_ERR 0xB5 | |
53 | #define DIMM_SYNDROME_STAGE 4 | |
54 | ||
4a4a4e9e QN |
55 | /* PCIE Error Registers */ |
56 | #define PCIE_CE_ERR_CNT 0xC0 | |
57 | #define PCIE_CE_ERR_LEN 0xC1 | |
58 | #define PCIE_CE_ERR_DATA 0xC2 | |
59 | #define PCIE_UE_ERR_CNT 0xC3 | |
60 | #define PCIE_UE_ERR_LEN 0xC4 | |
61 | #define PCIE_UE_ERR_DATA 0xC5 | |
62 | ||
63 | /* Other Error Registers */ | |
64 | #define OTHER_CE_ERR_CNT 0xD0 | |
65 | #define OTHER_CE_ERR_LEN 0xD1 | |
66 | #define OTHER_CE_ERR_DATA 0xD2 | |
67 | #define OTHER_UE_ERR_CNT 0xD8 | |
68 | #define OTHER_UE_ERR_LEN 0xD9 | |
69 | #define OTHER_UE_ERR_DATA 0xDA | |
70 | ||
71 | /* Event Data Registers */ | |
72 | #define VRD_WARN_FAULT_EVENT_DATA 0x78 | |
73 | #define VRD_HOT_EVENT_DATA 0x79 | |
74 | #define DIMM_HOT_EVENT_DATA 0x7A | |
b0f64c80 | 75 | #define DIMM_2X_REFRESH_EVENT_DATA 0x96 |
4a4a4e9e QN |
76 | |
77 | #define MAX_READ_BLOCK_LENGTH 48 | |
78 | ||
79 | #define RAS_SMPRO_ERR 0 | |
80 | #define RAS_PMPRO_ERR 1 | |
81 | ||
82 | enum RAS_48BYTES_ERR_TYPES { | |
83 | CORE_CE_ERR, | |
84 | CORE_UE_ERR, | |
85 | MEM_CE_ERR, | |
86 | MEM_UE_ERR, | |
87 | PCIE_CE_ERR, | |
88 | PCIE_UE_ERR, | |
89 | OTHER_CE_ERR, | |
90 | OTHER_UE_ERR, | |
91 | NUM_48BYTES_ERR_TYPE, | |
92 | }; | |
93 | ||
94 | struct smpro_error_hdr { | |
95 | u8 count; /* Number of the RAS errors */ | |
96 | u8 len; /* Number of data bytes */ | |
97 | u8 data; /* Start of 48-byte data */ | |
98 | u8 max_cnt; /* Max num of errors */ | |
99 | }; | |
100 | ||
101 | /* | |
102 | * Included Address of registers to get Count, Length of data and Data | |
103 | * of the 48 bytes error data | |
104 | */ | |
105 | static struct smpro_error_hdr smpro_error_table[] = { | |
106 | [CORE_CE_ERR] = { | |
107 | .count = CORE_CE_ERR_CNT, | |
108 | .len = CORE_CE_ERR_LEN, | |
109 | .data = CORE_CE_ERR_DATA, | |
110 | .max_cnt = 32 | |
111 | }, | |
112 | [CORE_UE_ERR] = { | |
113 | .count = CORE_UE_ERR_CNT, | |
114 | .len = CORE_UE_ERR_LEN, | |
115 | .data = CORE_UE_ERR_DATA, | |
116 | .max_cnt = 32 | |
117 | }, | |
118 | [MEM_CE_ERR] = { | |
119 | .count = MEM_CE_ERR_CNT, | |
120 | .len = MEM_CE_ERR_LEN, | |
121 | .data = MEM_CE_ERR_DATA, | |
122 | .max_cnt = 16 | |
123 | }, | |
124 | [MEM_UE_ERR] = { | |
125 | .count = MEM_UE_ERR_CNT, | |
126 | .len = MEM_UE_ERR_LEN, | |
127 | .data = MEM_UE_ERR_DATA, | |
128 | .max_cnt = 16 | |
129 | }, | |
130 | [PCIE_CE_ERR] = { | |
131 | .count = PCIE_CE_ERR_CNT, | |
132 | .len = PCIE_CE_ERR_LEN, | |
133 | .data = PCIE_CE_ERR_DATA, | |
134 | .max_cnt = 96 | |
135 | }, | |
136 | [PCIE_UE_ERR] = { | |
137 | .count = PCIE_UE_ERR_CNT, | |
138 | .len = PCIE_UE_ERR_LEN, | |
139 | .data = PCIE_UE_ERR_DATA, | |
140 | .max_cnt = 96 | |
141 | }, | |
142 | [OTHER_CE_ERR] = { | |
143 | .count = OTHER_CE_ERR_CNT, | |
144 | .len = OTHER_CE_ERR_LEN, | |
145 | .data = OTHER_CE_ERR_DATA, | |
146 | .max_cnt = 8 | |
147 | }, | |
148 | [OTHER_UE_ERR] = { | |
149 | .count = OTHER_UE_ERR_CNT, | |
150 | .len = OTHER_UE_ERR_LEN, | |
151 | .data = OTHER_UE_ERR_DATA, | |
152 | .max_cnt = 8 | |
153 | }, | |
154 | }; | |
155 | ||
156 | /* | |
157 | * List of SCP registers which are used to get | |
158 | * one type of RAS Internal errors. | |
159 | */ | |
160 | struct smpro_int_error_hdr { | |
161 | u8 type; | |
162 | u8 info_l; | |
163 | u8 info_h; | |
164 | u8 data_l; | |
165 | u8 data_h; | |
166 | u8 warn_l; | |
167 | u8 warn_h; | |
168 | }; | |
169 | ||
170 | static struct smpro_int_error_hdr list_smpro_int_error_hdr[] = { | |
171 | [RAS_SMPRO_ERR] = { | |
172 | .type = ERR_SMPRO_TYPE, | |
173 | .info_l = ERR_SMPRO_INFO_LO, | |
174 | .info_h = ERR_SMPRO_INFO_HI, | |
175 | .data_l = ERR_SMPRO_DATA_LO, | |
176 | .data_h = ERR_SMPRO_DATA_HI, | |
177 | .warn_l = WARN_SMPRO_INFO_LO, | |
178 | .warn_h = WARN_SMPRO_INFO_HI, | |
179 | }, | |
180 | [RAS_PMPRO_ERR] = { | |
181 | .type = ERR_PMPRO_TYPE, | |
182 | .info_l = ERR_PMPRO_INFO_LO, | |
183 | .info_h = ERR_PMPRO_INFO_HI, | |
184 | .data_l = ERR_PMPRO_DATA_LO, | |
185 | .data_h = ERR_PMPRO_DATA_HI, | |
186 | .warn_l = WARN_PMPRO_INFO_LO, | |
187 | .warn_h = WARN_PMPRO_INFO_HI, | |
188 | }, | |
189 | }; | |
190 | ||
191 | struct smpro_errmon { | |
192 | struct regmap *regmap; | |
193 | }; | |
194 | ||
195 | enum EVENT_TYPES { | |
196 | VRD_WARN_FAULT_EVENT, | |
197 | VRD_HOT_EVENT, | |
198 | DIMM_HOT_EVENT, | |
b0f64c80 | 199 | DIMM_2X_REFRESH_EVENT, |
4a4a4e9e QN |
200 | NUM_EVENTS_TYPE, |
201 | }; | |
202 | ||
203 | /* Included Address of event source and data registers */ | |
204 | static u8 smpro_event_table[NUM_EVENTS_TYPE] = { | |
205 | VRD_WARN_FAULT_EVENT_DATA, | |
206 | VRD_HOT_EVENT_DATA, | |
207 | DIMM_HOT_EVENT_DATA, | |
b0f64c80 | 208 | DIMM_2X_REFRESH_EVENT_DATA, |
4a4a4e9e QN |
209 | }; |
210 | ||
211 | static ssize_t smpro_event_data_read(struct device *dev, | |
212 | struct device_attribute *da, char *buf, | |
213 | int channel) | |
214 | { | |
215 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
216 | s32 event_data; | |
217 | int ret; | |
218 | ||
219 | ret = regmap_read(errmon->regmap, smpro_event_table[channel], &event_data); | |
220 | if (ret) | |
221 | return ret; | |
222 | /* Clear event after read */ | |
223 | if (event_data != 0) | |
224 | regmap_write(errmon->regmap, smpro_event_table[channel], event_data); | |
225 | ||
226 | return sysfs_emit(buf, "%04x\n", event_data); | |
227 | } | |
228 | ||
229 | static ssize_t smpro_overflow_data_read(struct device *dev, struct device_attribute *da, | |
230 | char *buf, int channel) | |
231 | { | |
232 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
233 | struct smpro_error_hdr *err_info; | |
234 | s32 err_count; | |
235 | int ret; | |
236 | ||
237 | err_info = &smpro_error_table[channel]; | |
238 | ||
239 | ret = regmap_read(errmon->regmap, err_info->count, &err_count); | |
240 | if (ret) | |
241 | return ret; | |
242 | ||
243 | /* Bit 8 indicates the overflow status */ | |
244 | return sysfs_emit(buf, "%d\n", (err_count & BIT(8)) ? 1 : 0); | |
245 | } | |
246 | ||
247 | static ssize_t smpro_error_data_read(struct device *dev, struct device_attribute *da, | |
248 | char *buf, int channel) | |
249 | { | |
250 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
251 | unsigned char err_data[MAX_READ_BLOCK_LENGTH]; | |
252 | struct smpro_error_hdr *err_info; | |
253 | s32 err_count, err_length; | |
254 | int ret; | |
255 | ||
256 | err_info = &smpro_error_table[channel]; | |
257 | ||
258 | ret = regmap_read(errmon->regmap, err_info->count, &err_count); | |
259 | /* Error count is the low byte */ | |
260 | err_count &= 0xff; | |
261 | if (ret || !err_count || err_count > err_info->max_cnt) | |
262 | return ret; | |
263 | ||
264 | ret = regmap_read(errmon->regmap, err_info->len, &err_length); | |
265 | if (ret || err_length <= 0) | |
266 | return ret; | |
267 | ||
268 | if (err_length > MAX_READ_BLOCK_LENGTH) | |
269 | err_length = MAX_READ_BLOCK_LENGTH; | |
270 | ||
271 | memset(err_data, 0x00, MAX_READ_BLOCK_LENGTH); | |
272 | ret = regmap_noinc_read(errmon->regmap, err_info->data, err_data, err_length); | |
273 | if (ret < 0) | |
274 | return ret; | |
275 | ||
276 | /* clear the error */ | |
277 | ret = regmap_write(errmon->regmap, err_info->count, 0x100); | |
278 | if (ret) | |
279 | return ret; | |
280 | /* | |
281 | * The output of Core/Memory/PCIe/Others UE/CE errors follows the format | |
282 | * specified in section 5.8.1 CE/UE Error Data record in | |
283 | * Altra SOC BMC Interface specification. | |
284 | */ | |
285 | return sysfs_emit(buf, "%*phN\n", MAX_READ_BLOCK_LENGTH, err_data); | |
286 | } | |
287 | ||
288 | /* | |
289 | * Output format: | |
290 | * <4-byte hex value of error info><4-byte hex value of error extensive data> | |
291 | * Where: | |
292 | * + error info : The error information | |
293 | * + error data : Extensive data (32 bits) | |
294 | * Reference to section 5.10 RAS Internal Error Register Definition in | |
295 | * Altra SOC BMC Interface specification | |
296 | */ | |
297 | static ssize_t smpro_internal_err_read(struct device *dev, struct device_attribute *da, | |
298 | char *buf, int channel) | |
299 | { | |
300 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
301 | struct smpro_int_error_hdr *err_info; | |
302 | unsigned int err[4] = { 0 }; | |
303 | unsigned int err_type; | |
304 | unsigned int val; | |
305 | int ret; | |
306 | ||
307 | /* read error status */ | |
308 | ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val); | |
309 | if (ret) | |
310 | return ret; | |
311 | ||
312 | if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) || | |
313 | (channel == RAS_PMPRO_ERR && !(val & BIT(1)))) | |
314 | return 0; | |
315 | ||
316 | err_info = &list_smpro_int_error_hdr[channel]; | |
317 | ret = regmap_read(errmon->regmap, err_info->type, &val); | |
318 | if (ret) | |
319 | return ret; | |
320 | ||
321 | err_type = (val & BIT(1)) ? BIT(1) : | |
322 | (val & BIT(2)) ? BIT(2) : 0; | |
323 | ||
324 | if (!err_type) | |
325 | return 0; | |
326 | ||
327 | ret = regmap_read(errmon->regmap, err_info->info_l, err + 1); | |
328 | if (ret) | |
329 | return ret; | |
330 | ||
331 | ret = regmap_read(errmon->regmap, err_info->info_h, err); | |
332 | if (ret) | |
333 | return ret; | |
334 | ||
335 | if (err_type & BIT(2)) { | |
336 | /* Error with data type */ | |
337 | ret = regmap_read(errmon->regmap, err_info->data_l, err + 3); | |
338 | if (ret) | |
339 | return ret; | |
340 | ||
341 | ret = regmap_read(errmon->regmap, err_info->data_h, err + 2); | |
342 | if (ret) | |
343 | return ret; | |
344 | } | |
345 | ||
346 | /* clear the read errors */ | |
347 | ret = regmap_write(errmon->regmap, err_info->type, err_type); | |
348 | if (ret) | |
349 | return ret; | |
350 | ||
351 | return sysfs_emit(buf, "%*phN\n", (int)sizeof(err), err); | |
352 | } | |
353 | ||
354 | /* | |
355 | * Output format: | |
356 | * <4-byte hex value of warining info> | |
357 | * Reference to section 5.10 RAS Internal Error Register Definition in | |
358 | * Altra SOC BMC Interface specification | |
359 | */ | |
360 | static ssize_t smpro_internal_warn_read(struct device *dev, struct device_attribute *da, | |
361 | char *buf, int channel) | |
362 | { | |
363 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
364 | struct smpro_int_error_hdr *err_info; | |
365 | unsigned int warn[2] = { 0 }; | |
366 | unsigned int val; | |
367 | int ret; | |
368 | ||
369 | /* read error status */ | |
370 | ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val); | |
371 | if (ret) | |
372 | return ret; | |
373 | ||
374 | if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) || | |
375 | (channel == RAS_PMPRO_ERR && !(val & BIT(1)))) | |
376 | return 0; | |
377 | ||
378 | err_info = &list_smpro_int_error_hdr[channel]; | |
379 | ret = regmap_read(errmon->regmap, err_info->type, &val); | |
380 | if (ret) | |
381 | return ret; | |
382 | ||
383 | if (!(val & BIT(0))) | |
384 | return 0; | |
385 | ||
386 | ret = regmap_read(errmon->regmap, err_info->warn_l, warn + 1); | |
387 | if (ret) | |
388 | return ret; | |
389 | ||
390 | ret = regmap_read(errmon->regmap, err_info->warn_h, warn); | |
391 | if (ret) | |
392 | return ret; | |
393 | ||
394 | /* clear the warning */ | |
395 | ret = regmap_write(errmon->regmap, err_info->type, BIT(0)); | |
396 | if (ret) | |
397 | return ret; | |
398 | ||
399 | return sysfs_emit(buf, "%*phN\n", (int)sizeof(warn), warn); | |
400 | } | |
401 | ||
402 | #define ERROR_OVERFLOW_RO(_error, _index) \ | |
403 | static ssize_t overflow_##_error##_show(struct device *dev, \ | |
404 | struct device_attribute *da, \ | |
405 | char *buf) \ | |
406 | { \ | |
407 | return smpro_overflow_data_read(dev, da, buf, _index); \ | |
408 | } \ | |
409 | static DEVICE_ATTR_RO(overflow_##_error) | |
410 | ||
411 | ERROR_OVERFLOW_RO(core_ce, CORE_CE_ERR); | |
412 | ERROR_OVERFLOW_RO(core_ue, CORE_UE_ERR); | |
413 | ERROR_OVERFLOW_RO(mem_ce, MEM_CE_ERR); | |
414 | ERROR_OVERFLOW_RO(mem_ue, MEM_UE_ERR); | |
415 | ERROR_OVERFLOW_RO(pcie_ce, PCIE_CE_ERR); | |
416 | ERROR_OVERFLOW_RO(pcie_ue, PCIE_UE_ERR); | |
417 | ERROR_OVERFLOW_RO(other_ce, OTHER_CE_ERR); | |
418 | ERROR_OVERFLOW_RO(other_ue, OTHER_UE_ERR); | |
419 | ||
420 | #define ERROR_RO(_error, _index) \ | |
421 | static ssize_t error_##_error##_show(struct device *dev, \ | |
422 | struct device_attribute *da, \ | |
423 | char *buf) \ | |
424 | { \ | |
425 | return smpro_error_data_read(dev, da, buf, _index); \ | |
426 | } \ | |
427 | static DEVICE_ATTR_RO(error_##_error) | |
428 | ||
429 | ERROR_RO(core_ce, CORE_CE_ERR); | |
430 | ERROR_RO(core_ue, CORE_UE_ERR); | |
431 | ERROR_RO(mem_ce, MEM_CE_ERR); | |
432 | ERROR_RO(mem_ue, MEM_UE_ERR); | |
433 | ERROR_RO(pcie_ce, PCIE_CE_ERR); | |
434 | ERROR_RO(pcie_ue, PCIE_UE_ERR); | |
435 | ERROR_RO(other_ce, OTHER_CE_ERR); | |
436 | ERROR_RO(other_ue, OTHER_UE_ERR); | |
437 | ||
438 | static ssize_t error_smpro_show(struct device *dev, struct device_attribute *da, char *buf) | |
439 | { | |
440 | return smpro_internal_err_read(dev, da, buf, RAS_SMPRO_ERR); | |
441 | } | |
442 | static DEVICE_ATTR_RO(error_smpro); | |
443 | ||
444 | static ssize_t error_pmpro_show(struct device *dev, struct device_attribute *da, char *buf) | |
445 | { | |
446 | return smpro_internal_err_read(dev, da, buf, RAS_PMPRO_ERR); | |
447 | } | |
448 | static DEVICE_ATTR_RO(error_pmpro); | |
449 | ||
450 | static ssize_t warn_smpro_show(struct device *dev, struct device_attribute *da, char *buf) | |
451 | { | |
452 | return smpro_internal_warn_read(dev, da, buf, RAS_SMPRO_ERR); | |
453 | } | |
454 | static DEVICE_ATTR_RO(warn_smpro); | |
455 | ||
456 | static ssize_t warn_pmpro_show(struct device *dev, struct device_attribute *da, char *buf) | |
457 | { | |
458 | return smpro_internal_warn_read(dev, da, buf, RAS_PMPRO_ERR); | |
459 | } | |
460 | static DEVICE_ATTR_RO(warn_pmpro); | |
461 | ||
462 | #define EVENT_RO(_event, _index) \ | |
463 | static ssize_t event_##_event##_show(struct device *dev, \ | |
464 | struct device_attribute *da, \ | |
465 | char *buf) \ | |
466 | { \ | |
467 | return smpro_event_data_read(dev, da, buf, _index); \ | |
468 | } \ | |
469 | static DEVICE_ATTR_RO(event_##_event) | |
470 | ||
471 | EVENT_RO(vrd_warn_fault, VRD_WARN_FAULT_EVENT); | |
472 | EVENT_RO(vrd_hot, VRD_HOT_EVENT); | |
473 | EVENT_RO(dimm_hot, DIMM_HOT_EVENT); | |
b0f64c80 | 474 | EVENT_RO(dimm_2x_refresh, DIMM_2X_REFRESH_EVENT); |
4a4a4e9e | 475 | |
c2c99326 QN |
476 | static ssize_t smpro_dimm_syndrome_read(struct device *dev, struct device_attribute *da, |
477 | char *buf, unsigned int slot) | |
478 | { | |
479 | struct smpro_errmon *errmon = dev_get_drvdata(dev); | |
480 | unsigned int data; | |
481 | int ret; | |
482 | ||
483 | ret = regmap_read(errmon->regmap, BOOTSTAGE, &data); | |
484 | if (ret) | |
485 | return ret; | |
486 | ||
487 | /* check for valid stage */ | |
488 | data = (data >> 8) & 0xff; | |
489 | if (data != DIMM_SYNDROME_STAGE) | |
490 | return ret; | |
491 | ||
492 | /* Write the slot ID to retrieve Error Syndrome */ | |
493 | ret = regmap_write(errmon->regmap, DIMM_SYNDROME_SEL, slot); | |
494 | if (ret) | |
495 | return ret; | |
496 | ||
497 | /* Read the Syndrome error */ | |
498 | ret = regmap_read(errmon->regmap, DIMM_SYNDROME_ERR, &data); | |
499 | if (ret || !data) | |
500 | return ret; | |
501 | ||
502 | return sysfs_emit(buf, "%04x\n", data); | |
503 | } | |
504 | ||
505 | #define EVENT_DIMM_SYNDROME(_slot) \ | |
506 | static ssize_t event_dimm##_slot##_syndrome_show(struct device *dev, \ | |
507 | struct device_attribute *da, \ | |
508 | char *buf) \ | |
509 | { \ | |
510 | return smpro_dimm_syndrome_read(dev, da, buf, _slot); \ | |
511 | } \ | |
512 | static DEVICE_ATTR_RO(event_dimm##_slot##_syndrome) | |
513 | ||
514 | EVENT_DIMM_SYNDROME(0); | |
515 | EVENT_DIMM_SYNDROME(1); | |
516 | EVENT_DIMM_SYNDROME(2); | |
517 | EVENT_DIMM_SYNDROME(3); | |
518 | EVENT_DIMM_SYNDROME(4); | |
519 | EVENT_DIMM_SYNDROME(5); | |
520 | EVENT_DIMM_SYNDROME(6); | |
521 | EVENT_DIMM_SYNDROME(7); | |
522 | EVENT_DIMM_SYNDROME(8); | |
523 | EVENT_DIMM_SYNDROME(9); | |
524 | EVENT_DIMM_SYNDROME(10); | |
525 | EVENT_DIMM_SYNDROME(11); | |
526 | EVENT_DIMM_SYNDROME(12); | |
527 | EVENT_DIMM_SYNDROME(13); | |
528 | EVENT_DIMM_SYNDROME(14); | |
529 | EVENT_DIMM_SYNDROME(15); | |
530 | ||
4a4a4e9e QN |
531 | static struct attribute *smpro_errmon_attrs[] = { |
532 | &dev_attr_overflow_core_ce.attr, | |
533 | &dev_attr_overflow_core_ue.attr, | |
534 | &dev_attr_overflow_mem_ce.attr, | |
535 | &dev_attr_overflow_mem_ue.attr, | |
536 | &dev_attr_overflow_pcie_ce.attr, | |
537 | &dev_attr_overflow_pcie_ue.attr, | |
538 | &dev_attr_overflow_other_ce.attr, | |
539 | &dev_attr_overflow_other_ue.attr, | |
540 | &dev_attr_error_core_ce.attr, | |
541 | &dev_attr_error_core_ue.attr, | |
542 | &dev_attr_error_mem_ce.attr, | |
543 | &dev_attr_error_mem_ue.attr, | |
544 | &dev_attr_error_pcie_ce.attr, | |
545 | &dev_attr_error_pcie_ue.attr, | |
546 | &dev_attr_error_other_ce.attr, | |
547 | &dev_attr_error_other_ue.attr, | |
548 | &dev_attr_error_smpro.attr, | |
549 | &dev_attr_error_pmpro.attr, | |
550 | &dev_attr_warn_smpro.attr, | |
551 | &dev_attr_warn_pmpro.attr, | |
552 | &dev_attr_event_vrd_warn_fault.attr, | |
553 | &dev_attr_event_vrd_hot.attr, | |
554 | &dev_attr_event_dimm_hot.attr, | |
b0f64c80 | 555 | &dev_attr_event_dimm_2x_refresh.attr, |
c2c99326 QN |
556 | &dev_attr_event_dimm0_syndrome.attr, |
557 | &dev_attr_event_dimm1_syndrome.attr, | |
558 | &dev_attr_event_dimm2_syndrome.attr, | |
559 | &dev_attr_event_dimm3_syndrome.attr, | |
560 | &dev_attr_event_dimm4_syndrome.attr, | |
561 | &dev_attr_event_dimm5_syndrome.attr, | |
562 | &dev_attr_event_dimm6_syndrome.attr, | |
563 | &dev_attr_event_dimm7_syndrome.attr, | |
564 | &dev_attr_event_dimm8_syndrome.attr, | |
565 | &dev_attr_event_dimm9_syndrome.attr, | |
566 | &dev_attr_event_dimm10_syndrome.attr, | |
567 | &dev_attr_event_dimm11_syndrome.attr, | |
568 | &dev_attr_event_dimm12_syndrome.attr, | |
569 | &dev_attr_event_dimm13_syndrome.attr, | |
570 | &dev_attr_event_dimm14_syndrome.attr, | |
571 | &dev_attr_event_dimm15_syndrome.attr, | |
4a4a4e9e QN |
572 | NULL |
573 | }; | |
574 | ||
575 | ATTRIBUTE_GROUPS(smpro_errmon); | |
576 | ||
577 | static int smpro_errmon_probe(struct platform_device *pdev) | |
578 | { | |
579 | struct smpro_errmon *errmon; | |
580 | ||
581 | errmon = devm_kzalloc(&pdev->dev, sizeof(struct smpro_errmon), GFP_KERNEL); | |
582 | if (!errmon) | |
583 | return -ENOMEM; | |
584 | ||
585 | platform_set_drvdata(pdev, errmon); | |
586 | ||
587 | errmon->regmap = dev_get_regmap(pdev->dev.parent, NULL); | |
588 | if (!errmon->regmap) | |
589 | return -ENODEV; | |
590 | ||
591 | return 0; | |
592 | } | |
593 | ||
594 | static struct platform_driver smpro_errmon_driver = { | |
595 | .probe = smpro_errmon_probe, | |
596 | .driver = { | |
597 | .name = "smpro-errmon", | |
598 | .dev_groups = smpro_errmon_groups, | |
599 | }, | |
600 | }; | |
601 | ||
602 | module_platform_driver(smpro_errmon_driver); | |
603 | ||
604 | MODULE_AUTHOR("Tung Nguyen <tung.nguyen@amperecomputing.com>"); | |
605 | MODULE_AUTHOR("Thinh Pham <thinh.pham@amperecomputing.com>"); | |
606 | MODULE_AUTHOR("Hoang Nguyen <hnguyen@amperecomputing.com>"); | |
607 | MODULE_AUTHOR("Thu Nguyen <thu@os.amperecomputing.com>"); | |
608 | MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>"); | |
609 | MODULE_DESCRIPTION("Ampere Altra SMpro driver"); | |
610 | MODULE_LICENSE("GPL"); |