1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017 Pengutronix, Jan Luebbe <kernel@pengutronix.de>
6 #include <linux/kernel.h>
7 #include <linux/edac.h>
9 #include <linux/of_device.h>
10 #include <linux/platform_device.h>
12 #include <asm/hardware/cache-l2x0.h>
13 #include <asm/hardware/cache-aurora-l2.h>
16 #include "edac_device.h"
17 #include "edac_module.h"
19 /************************ EDAC MC (DDR RAM) ********************************/
21 #define SDRAM_NUM_CS 4
23 #define SDRAM_CONFIG_REG 0x0
24 #define SDRAM_CONFIG_ECC_MASK BIT(18)
25 #define SDRAM_CONFIG_REGISTERED_MASK BIT(17)
26 #define SDRAM_CONFIG_BUS_WIDTH_MASK BIT(15)
28 #define SDRAM_ADDR_CTRL_REG 0x10
29 #define SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs) (20+cs)
30 #define SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(cs) (0x1 << SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs))
31 #define SDRAM_ADDR_CTRL_ADDR_SEL_MASK(cs) BIT(16+cs)
32 #define SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs) (cs*4+2)
33 #define SDRAM_ADDR_CTRL_SIZE_LOW_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs))
34 #define SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs) (cs*4)
35 #define SDRAM_ADDR_CTRL_STRUCT_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs))
37 #define SDRAM_ERR_DATA_H_REG 0x40
38 #define SDRAM_ERR_DATA_L_REG 0x44
40 #define SDRAM_ERR_RECV_ECC_REG 0x48
41 #define SDRAM_ERR_RECV_ECC_VALUE_MASK 0xff
43 #define SDRAM_ERR_CALC_ECC_REG 0x4c
44 #define SDRAM_ERR_CALC_ECC_ROW_OFFSET 8
45 #define SDRAM_ERR_CALC_ECC_ROW_MASK (0xffff << SDRAM_ERR_CALC_ECC_ROW_OFFSET)
46 #define SDRAM_ERR_CALC_ECC_VALUE_MASK 0xff
48 #define SDRAM_ERR_ADDR_REG 0x50
49 #define SDRAM_ERR_ADDR_BANK_OFFSET 23
50 #define SDRAM_ERR_ADDR_BANK_MASK (0x7 << SDRAM_ERR_ADDR_BANK_OFFSET)
51 #define SDRAM_ERR_ADDR_COL_OFFSET 8
52 #define SDRAM_ERR_ADDR_COL_MASK (0x7fff << SDRAM_ERR_ADDR_COL_OFFSET)
53 #define SDRAM_ERR_ADDR_CS_OFFSET 1
54 #define SDRAM_ERR_ADDR_CS_MASK (0x3 << SDRAM_ERR_ADDR_CS_OFFSET)
55 #define SDRAM_ERR_ADDR_TYPE_MASK BIT(0)
57 #define SDRAM_ERR_CTRL_REG 0x54
58 #define SDRAM_ERR_CTRL_THR_OFFSET 16
59 #define SDRAM_ERR_CTRL_THR_MASK (0xff << SDRAM_ERR_CTRL_THR_OFFSET)
60 #define SDRAM_ERR_CTRL_PROP_MASK BIT(9)
62 #define SDRAM_ERR_SBE_COUNT_REG 0x58
63 #define SDRAM_ERR_DBE_COUNT_REG 0x5c
65 #define SDRAM_ERR_CAUSE_ERR_REG 0xd0
66 #define SDRAM_ERR_CAUSE_MSG_REG 0xd8
67 #define SDRAM_ERR_CAUSE_DBE_MASK BIT(1)
68 #define SDRAM_ERR_CAUSE_SBE_MASK BIT(0)
70 #define SDRAM_RANK_CTRL_REG 0x1e0
71 #define SDRAM_RANK_CTRL_EXIST_MASK(cs) BIT(cs)
73 struct axp_mc_drvdata
{
77 /* bank interleaving */
78 bool cs_addr_sel
[SDRAM_NUM_CS
];
83 /* derived from "DRAM Address Multiplexing" in the ARMADA XP Functional Spec */
84 static uint32_t axp_mc_calc_address(struct axp_mc_drvdata
*drvdata
,
85 uint8_t cs
, uint8_t bank
, uint16_t row
,
88 if (drvdata
->width
== 8) {
90 if (drvdata
->cs_addr_sel
[cs
])
91 /* bank interleaved */
92 return (((row
& 0xfff8) << 16) |
93 ((bank
& 0x7) << 16) |
95 ((col
& 0x3ff) << 3));
97 return (((row
& 0xffff << 16) |
98 ((bank
& 0x7) << 13) |
99 ((col
& 0x3ff)) << 3));
100 } else if (drvdata
->width
== 4) {
102 if (drvdata
->cs_addr_sel
[cs
])
103 /* bank interleaved */
104 return (((row
& 0xfff0) << 15) |
105 ((bank
& 0x7) << 16) |
106 ((row
& 0xf) << 12) |
107 ((col
& 0x3ff) << 2));
109 return (((row
& 0xffff << 15) |
110 ((bank
& 0x7) << 12) |
111 ((col
& 0x3ff)) << 2));
114 if (drvdata
->cs_addr_sel
[cs
])
115 /* bank interleaved */
116 return (((row
& 0xffe0) << 14) |
117 ((bank
& 0x7) << 16) |
118 ((row
& 0x1f) << 11) |
119 ((col
& 0x3ff) << 1));
121 return (((row
& 0xffff << 14) |
122 ((bank
& 0x7) << 11) |
123 ((col
& 0x3ff)) << 1));
127 static void axp_mc_check(struct mem_ctl_info
*mci
)
129 struct axp_mc_drvdata
*drvdata
= mci
->pvt_info
;
130 uint32_t data_h
, data_l
, recv_ecc
, calc_ecc
, addr
;
131 uint32_t cnt_sbe
, cnt_dbe
, cause_err
, cause_msg
;
132 uint32_t row_val
, col_val
, bank_val
, addr_val
;
133 uint8_t syndrome_val
, cs_val
;
134 char *msg
= drvdata
->msg
;
136 data_h
= readl(drvdata
->base
+ SDRAM_ERR_DATA_H_REG
);
137 data_l
= readl(drvdata
->base
+ SDRAM_ERR_DATA_L_REG
);
138 recv_ecc
= readl(drvdata
->base
+ SDRAM_ERR_RECV_ECC_REG
);
139 calc_ecc
= readl(drvdata
->base
+ SDRAM_ERR_CALC_ECC_REG
);
140 addr
= readl(drvdata
->base
+ SDRAM_ERR_ADDR_REG
);
141 cnt_sbe
= readl(drvdata
->base
+ SDRAM_ERR_SBE_COUNT_REG
);
142 cnt_dbe
= readl(drvdata
->base
+ SDRAM_ERR_DBE_COUNT_REG
);
143 cause_err
= readl(drvdata
->base
+ SDRAM_ERR_CAUSE_ERR_REG
);
144 cause_msg
= readl(drvdata
->base
+ SDRAM_ERR_CAUSE_MSG_REG
);
146 /* clear cause registers */
147 writel(~(SDRAM_ERR_CAUSE_DBE_MASK
| SDRAM_ERR_CAUSE_SBE_MASK
),
148 drvdata
->base
+ SDRAM_ERR_CAUSE_ERR_REG
);
149 writel(~(SDRAM_ERR_CAUSE_DBE_MASK
| SDRAM_ERR_CAUSE_SBE_MASK
),
150 drvdata
->base
+ SDRAM_ERR_CAUSE_MSG_REG
);
152 /* clear error counter registers */
154 writel(0, drvdata
->base
+ SDRAM_ERR_SBE_COUNT_REG
);
156 writel(0, drvdata
->base
+ SDRAM_ERR_DBE_COUNT_REG
);
158 if (!cnt_sbe
&& !cnt_dbe
)
161 if (!(addr
& SDRAM_ERR_ADDR_TYPE_MASK
)) {
165 dev_warn(mci
->pdev
, "inconsistent SBE count detected\n");
170 dev_warn(mci
->pdev
, "inconsistent DBE count detected\n");
173 /* report earlier errors */
175 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED
, mci
,
176 cnt_sbe
, /* error count */
177 0, 0, 0, /* pfn, offset, syndrome */
178 -1, -1, -1, /* top, mid, low layer */
180 "details unavailable (multiple errors)");
182 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED
, mci
,
183 cnt_dbe
, /* error count */
184 0, 0, 0, /* pfn, offset, syndrome */
185 -1, -1, -1, /* top, mid, low layer */
187 "details unavailable (multiple errors)");
189 /* report details for most recent error */
190 cs_val
= (addr
& SDRAM_ERR_ADDR_CS_MASK
) >> SDRAM_ERR_ADDR_CS_OFFSET
;
191 bank_val
= (addr
& SDRAM_ERR_ADDR_BANK_MASK
) >> SDRAM_ERR_ADDR_BANK_OFFSET
;
192 row_val
= (calc_ecc
& SDRAM_ERR_CALC_ECC_ROW_MASK
) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET
;
193 col_val
= (addr
& SDRAM_ERR_ADDR_COL_MASK
) >> SDRAM_ERR_ADDR_COL_OFFSET
;
194 syndrome_val
= (recv_ecc
^ calc_ecc
) & 0xff;
195 addr_val
= axp_mc_calc_address(drvdata
, cs_val
, bank_val
, row_val
,
197 msg
+= sprintf(msg
, "row=0x%04x ", row_val
); /* 11 chars */
198 msg
+= sprintf(msg
, "bank=0x%x ", bank_val
); /* 9 chars */
199 msg
+= sprintf(msg
, "col=0x%04x ", col_val
); /* 11 chars */
200 msg
+= sprintf(msg
, "cs=%d", cs_val
); /* 4 chars */
202 if (!(addr
& SDRAM_ERR_ADDR_TYPE_MASK
)) {
203 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED
, mci
,
205 addr_val
>> PAGE_SHIFT
,
206 addr_val
& ~PAGE_MASK
,
208 cs_val
, -1, -1, /* top, mid, low layer */
209 mci
->ctl_name
, drvdata
->msg
);
211 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED
, mci
,
213 addr_val
>> PAGE_SHIFT
,
214 addr_val
& ~PAGE_MASK
,
216 cs_val
, -1, -1, /* top, mid, low layer */
217 mci
->ctl_name
, drvdata
->msg
);
221 static void axp_mc_read_config(struct mem_ctl_info
*mci
)
223 struct axp_mc_drvdata
*drvdata
= mci
->pvt_info
;
224 uint32_t config
, addr_ctrl
, rank_ctrl
;
225 unsigned int i
, cs_struct
, cs_size
;
226 struct dimm_info
*dimm
;
228 config
= readl(drvdata
->base
+ SDRAM_CONFIG_REG
);
229 if (config
& SDRAM_CONFIG_BUS_WIDTH_MASK
)
236 addr_ctrl
= readl(drvdata
->base
+ SDRAM_ADDR_CTRL_REG
);
237 rank_ctrl
= readl(drvdata
->base
+ SDRAM_RANK_CTRL_REG
);
238 for (i
= 0; i
< SDRAM_NUM_CS
; i
++) {
239 dimm
= mci
->dimms
[i
];
241 if (!(rank_ctrl
& SDRAM_RANK_CTRL_EXIST_MASK(i
)))
244 drvdata
->cs_addr_sel
[i
] =
245 !!(addr_ctrl
& SDRAM_ADDR_CTRL_ADDR_SEL_MASK(i
));
247 cs_struct
= (addr_ctrl
& SDRAM_ADDR_CTRL_STRUCT_MASK(i
)) >> SDRAM_ADDR_CTRL_STRUCT_OFFSET(i
);
248 cs_size
= ((addr_ctrl
& SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(i
)) >> (SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(i
) - 2) |
249 ((addr_ctrl
& SDRAM_ADDR_CTRL_SIZE_LOW_MASK(i
)) >> SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(i
)));
253 dimm
->nr_pages
= 524288;
255 case 1: /* 256MBit */
256 dimm
->nr_pages
= 65536;
258 case 2: /* 512MBit */
259 dimm
->nr_pages
= 131072;
262 dimm
->nr_pages
= 262144;
265 dimm
->nr_pages
= 1048576;
268 dimm
->nr_pages
= 2097152;
272 dimm
->dtype
= cs_struct
? DEV_X16
: DEV_X8
;
273 dimm
->mtype
= (config
& SDRAM_CONFIG_REGISTERED_MASK
) ?
274 MEM_RDDR3
: MEM_DDR3
;
275 dimm
->edac_mode
= EDAC_SECDED
;
279 static const struct of_device_id axp_mc_of_match
[] = {
280 {.compatible
= "marvell,armada-xp-sdram-controller",},
283 MODULE_DEVICE_TABLE(of
, axp_mc_of_match
);
285 static int axp_mc_probe(struct platform_device
*pdev
)
287 struct axp_mc_drvdata
*drvdata
;
288 struct edac_mc_layer layers
[1];
289 const struct of_device_id
*id
;
290 struct mem_ctl_info
*mci
;
294 base
= devm_platform_ioremap_resource(pdev
, 0);
296 dev_err(&pdev
->dev
, "Unable to map regs\n");
297 return PTR_ERR(base
);
300 config
= readl(base
+ SDRAM_CONFIG_REG
);
301 if (!(config
& SDRAM_CONFIG_ECC_MASK
)) {
302 dev_warn(&pdev
->dev
, "SDRAM ECC is not enabled\n");
306 layers
[0].type
= EDAC_MC_LAYER_CHIP_SELECT
;
307 layers
[0].size
= SDRAM_NUM_CS
;
308 layers
[0].is_virt_csrow
= true;
310 mci
= edac_mc_alloc(0, ARRAY_SIZE(layers
), layers
, sizeof(*drvdata
));
314 drvdata
= mci
->pvt_info
;
315 drvdata
->base
= base
;
316 mci
->pdev
= &pdev
->dev
;
317 platform_set_drvdata(pdev
, mci
);
319 id
= of_match_device(axp_mc_of_match
, &pdev
->dev
);
320 mci
->edac_check
= axp_mc_check
;
321 mci
->mtype_cap
= MEM_FLAG_DDR3
;
322 mci
->edac_cap
= EDAC_FLAG_SECDED
;
323 mci
->mod_name
= pdev
->dev
.driver
->name
;
324 mci
->ctl_name
= id
? id
->compatible
: "unknown";
325 mci
->dev_name
= dev_name(&pdev
->dev
);
326 mci
->scrub_mode
= SCRUB_NONE
;
328 axp_mc_read_config(mci
);
330 /* These SoCs have a reduced width bus */
331 if (of_machine_is_compatible("marvell,armada380") ||
332 of_machine_is_compatible("marvell,armadaxp-98dx3236"))
335 /* configure SBE threshold */
336 /* it seems that SBEs are not captured otherwise */
337 writel(1 << SDRAM_ERR_CTRL_THR_OFFSET
, drvdata
->base
+ SDRAM_ERR_CTRL_REG
);
339 /* clear cause registers */
340 writel(~(SDRAM_ERR_CAUSE_DBE_MASK
| SDRAM_ERR_CAUSE_SBE_MASK
), drvdata
->base
+ SDRAM_ERR_CAUSE_ERR_REG
);
341 writel(~(SDRAM_ERR_CAUSE_DBE_MASK
| SDRAM_ERR_CAUSE_SBE_MASK
), drvdata
->base
+ SDRAM_ERR_CAUSE_MSG_REG
);
343 /* clear counter registers */
344 writel(0, drvdata
->base
+ SDRAM_ERR_SBE_COUNT_REG
);
345 writel(0, drvdata
->base
+ SDRAM_ERR_DBE_COUNT_REG
);
347 if (edac_mc_add_mc(mci
)) {
351 edac_op_state
= EDAC_OPSTATE_POLL
;
356 static void axp_mc_remove(struct platform_device
*pdev
)
358 struct mem_ctl_info
*mci
= platform_get_drvdata(pdev
);
360 edac_mc_del_mc(&pdev
->dev
);
362 platform_set_drvdata(pdev
, NULL
);
365 static struct platform_driver axp_mc_driver
= {
366 .probe
= axp_mc_probe
,
367 .remove
= axp_mc_remove
,
369 .name
= "armada_xp_mc_edac",
370 .of_match_table
= of_match_ptr(axp_mc_of_match
),
374 /************************ EDAC Device (L2 Cache) ***************************/
376 struct aurora_l2_drvdata
{
381 /* error injection via debugfs */
382 uint32_t inject_addr
;
383 uint32_t inject_mask
;
386 struct dentry
*debugfs
;
389 #ifdef CONFIG_EDAC_DEBUG
390 static void aurora_l2_inject(struct aurora_l2_drvdata
*drvdata
)
392 drvdata
->inject_addr
&= AURORA_ERR_INJECT_CTL_ADDR_MASK
;
393 drvdata
->inject_ctl
&= AURORA_ERR_INJECT_CTL_EN_MASK
;
394 writel(0, drvdata
->base
+ AURORA_ERR_INJECT_CTL_REG
);
395 writel(drvdata
->inject_mask
, drvdata
->base
+ AURORA_ERR_INJECT_MASK_REG
);
396 writel(drvdata
->inject_addr
| drvdata
->inject_ctl
, drvdata
->base
+ AURORA_ERR_INJECT_CTL_REG
);
400 static void aurora_l2_check(struct edac_device_ctl_info
*dci
)
402 struct aurora_l2_drvdata
*drvdata
= dci
->pvt_info
;
403 uint32_t cnt
, src
, txn
, err
, attr_cap
, addr_cap
, way_cap
;
404 unsigned int cnt_ce
, cnt_ue
;
405 char *msg
= drvdata
->msg
;
406 size_t size
= sizeof(drvdata
->msg
);
409 cnt
= readl(drvdata
->base
+ AURORA_ERR_CNT_REG
);
410 attr_cap
= readl(drvdata
->base
+ AURORA_ERR_ATTR_CAP_REG
);
411 addr_cap
= readl(drvdata
->base
+ AURORA_ERR_ADDR_CAP_REG
);
412 way_cap
= readl(drvdata
->base
+ AURORA_ERR_WAY_CAP_REG
);
414 cnt_ce
= (cnt
& AURORA_ERR_CNT_CE_MASK
) >> AURORA_ERR_CNT_CE_OFFSET
;
415 cnt_ue
= (cnt
& AURORA_ERR_CNT_UE_MASK
) >> AURORA_ERR_CNT_UE_OFFSET
;
416 /* clear error counter registers */
417 if (cnt_ce
|| cnt_ue
)
418 writel(AURORA_ERR_CNT_CLR
, drvdata
->base
+ AURORA_ERR_CNT_REG
);
420 if (!(attr_cap
& AURORA_ERR_ATTR_CAP_VALID
))
421 goto clear_remaining
;
423 src
= (attr_cap
& AURORA_ERR_ATTR_SRC_MSK
) >> AURORA_ERR_ATTR_SRC_OFF
;
425 len
+= scnprintf(msg
+len
, size
-len
, "src=CPU%d ", src
);
427 len
+= scnprintf(msg
+len
, size
-len
, "src=IO ");
429 txn
= (attr_cap
& AURORA_ERR_ATTR_TXN_MSK
) >> AURORA_ERR_ATTR_TXN_OFF
;
432 len
+= scnprintf(msg
+len
, size
-len
, "txn=Data-Read ");
435 len
+= scnprintf(msg
+len
, size
-len
, "txn=Isn-Read ");
438 len
+= scnprintf(msg
+len
, size
-len
, "txn=Clean-Flush ");
441 len
+= scnprintf(msg
+len
, size
-len
, "txn=Eviction ");
444 len
+= scnprintf(msg
+len
, size
-len
,
445 "txn=Read-Modify-Write ");
449 err
= (attr_cap
& AURORA_ERR_ATTR_ERR_MSK
) >> AURORA_ERR_ATTR_ERR_OFF
;
452 len
+= scnprintf(msg
+len
, size
-len
, "err=CorrECC ");
455 len
+= scnprintf(msg
+len
, size
-len
, "err=UnCorrECC ");
458 len
+= scnprintf(msg
+len
, size
-len
, "err=TagParity ");
462 len
+= scnprintf(msg
+len
, size
-len
, "addr=0x%x ", addr_cap
& AURORA_ERR_ADDR_CAP_ADDR_MASK
);
463 len
+= scnprintf(msg
+len
, size
-len
, "index=0x%x ", (way_cap
& AURORA_ERR_WAY_IDX_MSK
) >> AURORA_ERR_WAY_IDX_OFF
);
464 len
+= scnprintf(msg
+len
, size
-len
, "way=0x%x", (way_cap
& AURORA_ERR_WAY_CAP_WAY_MASK
) >> AURORA_ERR_WAY_CAP_WAY_OFFSET
);
466 /* clear error capture registers */
467 writel(AURORA_ERR_ATTR_CAP_VALID
, drvdata
->base
+ AURORA_ERR_ATTR_CAP_REG
);
469 /* UnCorrECC or TagParity */
472 edac_device_handle_ue(dci
, 0, 0, drvdata
->msg
);
476 edac_device_handle_ce(dci
, 0, 0, drvdata
->msg
);
480 /* report remaining errors */
482 edac_device_handle_ue(dci
, 0, 0, "details unavailable (multiple errors)");
484 edac_device_handle_ue(dci
, 0, 0, "details unavailable (multiple errors)");
487 static void aurora_l2_poll(struct edac_device_ctl_info
*dci
)
489 #ifdef CONFIG_EDAC_DEBUG
490 struct aurora_l2_drvdata
*drvdata
= dci
->pvt_info
;
493 aurora_l2_check(dci
);
494 #ifdef CONFIG_EDAC_DEBUG
495 aurora_l2_inject(drvdata
);
499 static const struct of_device_id aurora_l2_of_match
[] = {
500 {.compatible
= "marvell,aurora-system-cache",},
503 MODULE_DEVICE_TABLE(of
, aurora_l2_of_match
);
505 static int aurora_l2_probe(struct platform_device
*pdev
)
507 struct aurora_l2_drvdata
*drvdata
;
508 struct edac_device_ctl_info
*dci
;
509 const struct of_device_id
*id
;
510 uint32_t l2x0_aux_ctrl
;
513 base
= devm_platform_ioremap_resource(pdev
, 0);
515 dev_err(&pdev
->dev
, "Unable to map regs\n");
516 return PTR_ERR(base
);
519 l2x0_aux_ctrl
= readl(base
+ L2X0_AUX_CTRL
);
520 if (!(l2x0_aux_ctrl
& AURORA_ACR_PARITY_EN
))
521 dev_warn(&pdev
->dev
, "tag parity is not enabled\n");
522 if (!(l2x0_aux_ctrl
& AURORA_ACR_ECC_EN
))
523 dev_warn(&pdev
->dev
, "data ECC is not enabled\n");
525 dci
= edac_device_alloc_ctl_info(sizeof(*drvdata
),
526 "cpu", 1, "L", 1, 2, 0);
530 drvdata
= dci
->pvt_info
;
531 drvdata
->base
= base
;
532 dci
->dev
= &pdev
->dev
;
533 platform_set_drvdata(pdev
, dci
);
535 id
= of_match_device(aurora_l2_of_match
, &pdev
->dev
);
536 dci
->edac_check
= aurora_l2_poll
;
537 dci
->mod_name
= pdev
->dev
.driver
->name
;
538 dci
->ctl_name
= id
? id
->compatible
: "unknown";
539 dci
->dev_name
= dev_name(&pdev
->dev
);
541 /* clear registers */
542 writel(AURORA_ERR_CNT_CLR
, drvdata
->base
+ AURORA_ERR_CNT_REG
);
543 writel(AURORA_ERR_ATTR_CAP_VALID
, drvdata
->base
+ AURORA_ERR_ATTR_CAP_REG
);
545 if (edac_device_add_device(dci
)) {
546 edac_device_free_ctl_info(dci
);
550 #ifdef CONFIG_EDAC_DEBUG
551 drvdata
->debugfs
= edac_debugfs_create_dir(dev_name(&pdev
->dev
));
552 if (drvdata
->debugfs
) {
553 edac_debugfs_create_x32("inject_addr", 0644,
555 &drvdata
->inject_addr
);
556 edac_debugfs_create_x32("inject_mask", 0644,
558 &drvdata
->inject_mask
);
559 edac_debugfs_create_x8("inject_ctl", 0644,
560 drvdata
->debugfs
, &drvdata
->inject_ctl
);
567 static void aurora_l2_remove(struct platform_device
*pdev
)
569 struct edac_device_ctl_info
*dci
= platform_get_drvdata(pdev
);
570 #ifdef CONFIG_EDAC_DEBUG
571 struct aurora_l2_drvdata
*drvdata
= dci
->pvt_info
;
573 edac_debugfs_remove_recursive(drvdata
->debugfs
);
575 edac_device_del_device(&pdev
->dev
);
576 edac_device_free_ctl_info(dci
);
577 platform_set_drvdata(pdev
, NULL
);
580 static struct platform_driver aurora_l2_driver
= {
581 .probe
= aurora_l2_probe
,
582 .remove
= aurora_l2_remove
,
584 .name
= "aurora_l2_edac",
585 .of_match_table
= of_match_ptr(aurora_l2_of_match
),
589 /************************ Driver registration ******************************/
591 static struct platform_driver
* const drivers
[] = {
596 static int __init
armada_xp_edac_init(void)
600 if (ghes_get_devices())
603 /* only polling is supported */
604 edac_op_state
= EDAC_OPSTATE_POLL
;
606 res
= platform_register_drivers(drivers
, ARRAY_SIZE(drivers
));
608 pr_warn("Armada XP EDAC drivers fail to register\n");
612 module_init(armada_xp_edac_init
);
614 static void __exit
armada_xp_edac_exit(void)
616 platform_unregister_drivers(drivers
, ARRAY_SIZE(drivers
));
618 module_exit(armada_xp_edac_exit
);
620 MODULE_LICENSE("GPL v2");
621 MODULE_AUTHOR("Pengutronix");
622 MODULE_DESCRIPTION("EDAC Drivers for Marvell Armada XP SDRAM and L2 Cache Controller");