]>
Commit | Line | Data |
---|---|---|
ae9b56e3 PCK |
1 | /* |
2 | * Synopsys DDR ECC Driver | |
3 | * This driver is based on ppc4xx_edac.c drivers | |
4 | * | |
5 | * Copyright (C) 2012 - 2014 Xilinx, Inc. | |
6 | * | |
7 | * This program is free software: you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation, either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * This file is subject to the terms and conditions of the GNU General Public | |
18 | * License. See the file "COPYING" in the main directory of this archive | |
19 | * for more details | |
20 | */ | |
21 | ||
22 | #include <linux/edac.h> | |
23 | #include <linux/module.h> | |
24 | #include <linux/platform_device.h> | |
25 | ||
78d88e8a | 26 | #include "edac_module.h" |
ae9b56e3 PCK |
27 | |
28 | /* Number of cs_rows needed per memory controller */ | |
29 | #define SYNPS_EDAC_NR_CSROWS 1 | |
30 | ||
31 | /* Number of channels per memory controller */ | |
32 | #define SYNPS_EDAC_NR_CHANS 1 | |
33 | ||
34 | /* Granularity of reported error in bytes */ | |
35 | #define SYNPS_EDAC_ERR_GRAIN 1 | |
36 | ||
37 | #define SYNPS_EDAC_MSG_SIZE 256 | |
38 | ||
39 | #define SYNPS_EDAC_MOD_STRING "synps_edac" | |
40 | #define SYNPS_EDAC_MOD_VER "1" | |
41 | ||
42 | /* Synopsys DDR memory controller registers that are relevant to ECC */ | |
43 | #define CTRL_OFST 0x0 | |
44 | #define T_ZQ_OFST 0xA4 | |
45 | ||
46 | /* ECC control register */ | |
47 | #define ECC_CTRL_OFST 0xC4 | |
48 | /* ECC log register */ | |
49 | #define CE_LOG_OFST 0xC8 | |
50 | /* ECC address register */ | |
51 | #define CE_ADDR_OFST 0xCC | |
52 | /* ECC data[31:0] register */ | |
53 | #define CE_DATA_31_0_OFST 0xD0 | |
54 | ||
55 | /* Uncorrectable error info registers */ | |
56 | #define UE_LOG_OFST 0xDC | |
57 | #define UE_ADDR_OFST 0xE0 | |
58 | #define UE_DATA_31_0_OFST 0xE4 | |
59 | ||
60 | #define STAT_OFST 0xF0 | |
61 | #define SCRUB_OFST 0xF4 | |
62 | ||
63 | /* Control register bit field definitions */ | |
64 | #define CTRL_BW_MASK 0xC | |
65 | #define CTRL_BW_SHIFT 2 | |
66 | ||
67 | #define DDRCTL_WDTH_16 1 | |
68 | #define DDRCTL_WDTH_32 0 | |
69 | ||
70 | /* ZQ register bit field definitions */ | |
71 | #define T_ZQ_DDRMODE_MASK 0x2 | |
72 | ||
73 | /* ECC control register bit field definitions */ | |
74 | #define ECC_CTRL_CLR_CE_ERR 0x2 | |
75 | #define ECC_CTRL_CLR_UE_ERR 0x1 | |
76 | ||
77 | /* ECC correctable/uncorrectable error log register definitions */ | |
78 | #define LOG_VALID 0x1 | |
79 | #define CE_LOG_BITPOS_MASK 0xFE | |
80 | #define CE_LOG_BITPOS_SHIFT 1 | |
81 | ||
82 | /* ECC correctable/uncorrectable error address register definitions */ | |
83 | #define ADDR_COL_MASK 0xFFF | |
84 | #define ADDR_ROW_MASK 0xFFFF000 | |
85 | #define ADDR_ROW_SHIFT 12 | |
86 | #define ADDR_BANK_MASK 0x70000000 | |
87 | #define ADDR_BANK_SHIFT 28 | |
88 | ||
89 | /* ECC statistic register definitions */ | |
90 | #define STAT_UECNT_MASK 0xFF | |
91 | #define STAT_CECNT_MASK 0xFF00 | |
92 | #define STAT_CECNT_SHIFT 8 | |
93 | ||
94 | /* ECC scrub register definitions */ | |
95 | #define SCRUB_MODE_MASK 0x7 | |
96 | #define SCRUB_MODE_SECDED 0x4 | |
97 | ||
98 | /** | |
99 | * struct ecc_error_info - ECC error log information | |
100 | * @row: Row number | |
101 | * @col: Column number | |
102 | * @bank: Bank number | |
103 | * @bitpos: Bit position | |
104 | * @data: Data causing the error | |
105 | */ | |
106 | struct ecc_error_info { | |
107 | u32 row; | |
108 | u32 col; | |
109 | u32 bank; | |
110 | u32 bitpos; | |
111 | u32 data; | |
112 | }; | |
113 | ||
114 | /** | |
115 | * struct synps_ecc_status - ECC status information to report | |
116 | * @ce_cnt: Correctable error count | |
117 | * @ue_cnt: Uncorrectable error count | |
118 | * @ceinfo: Correctable error log information | |
119 | * @ueinfo: Uncorrectable error log information | |
120 | */ | |
121 | struct synps_ecc_status { | |
122 | u32 ce_cnt; | |
123 | u32 ue_cnt; | |
124 | struct ecc_error_info ceinfo; | |
125 | struct ecc_error_info ueinfo; | |
126 | }; | |
127 | ||
128 | /** | |
129 | * struct synps_edac_priv - DDR memory controller private instance data | |
130 | * @baseaddr: Base address of the DDR controller | |
131 | * @message: Buffer for framing the event specific info | |
132 | * @stat: ECC status information | |
133 | * @ce_cnt: Correctable Error count | |
134 | * @ue_cnt: Uncorrectable Error count | |
135 | */ | |
136 | struct synps_edac_priv { | |
137 | void __iomem *baseaddr; | |
138 | char message[SYNPS_EDAC_MSG_SIZE]; | |
139 | struct synps_ecc_status stat; | |
140 | u32 ce_cnt; | |
141 | u32 ue_cnt; | |
142 | }; | |
143 | ||
144 | /** | |
145 | * synps_edac_geterror_info - Get the current ecc error info | |
146 | * @base: Pointer to the base address of the ddr memory controller | |
147 | * @p: Pointer to the synopsys ecc status structure | |
148 | * | |
149 | * Determines there is any ecc error or not | |
150 | * | |
151 | * Return: one if there is no error otherwise returns zero | |
152 | */ | |
153 | static int synps_edac_geterror_info(void __iomem *base, | |
154 | struct synps_ecc_status *p) | |
155 | { | |
156 | u32 regval, clearval = 0; | |
157 | ||
158 | regval = readl(base + STAT_OFST); | |
159 | if (!regval) | |
160 | return 1; | |
161 | ||
162 | p->ce_cnt = (regval & STAT_CECNT_MASK) >> STAT_CECNT_SHIFT; | |
163 | p->ue_cnt = regval & STAT_UECNT_MASK; | |
164 | ||
165 | regval = readl(base + CE_LOG_OFST); | |
166 | if (!(p->ce_cnt && (regval & LOG_VALID))) | |
167 | goto ue_err; | |
168 | ||
169 | p->ceinfo.bitpos = (regval & CE_LOG_BITPOS_MASK) >> CE_LOG_BITPOS_SHIFT; | |
170 | regval = readl(base + CE_ADDR_OFST); | |
171 | p->ceinfo.row = (regval & ADDR_ROW_MASK) >> ADDR_ROW_SHIFT; | |
172 | p->ceinfo.col = regval & ADDR_COL_MASK; | |
173 | p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT; | |
174 | p->ceinfo.data = readl(base + CE_DATA_31_0_OFST); | |
175 | edac_dbg(3, "ce bit position: %d data: %d\n", p->ceinfo.bitpos, | |
176 | p->ceinfo.data); | |
177 | clearval = ECC_CTRL_CLR_CE_ERR; | |
178 | ||
179 | ue_err: | |
180 | regval = readl(base + UE_LOG_OFST); | |
181 | if (!(p->ue_cnt && (regval & LOG_VALID))) | |
182 | goto out; | |
183 | ||
184 | regval = readl(base + UE_ADDR_OFST); | |
185 | p->ueinfo.row = (regval & ADDR_ROW_MASK) >> ADDR_ROW_SHIFT; | |
186 | p->ueinfo.col = regval & ADDR_COL_MASK; | |
187 | p->ueinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT; | |
188 | p->ueinfo.data = readl(base + UE_DATA_31_0_OFST); | |
189 | clearval |= ECC_CTRL_CLR_UE_ERR; | |
190 | ||
191 | out: | |
192 | writel(clearval, base + ECC_CTRL_OFST); | |
193 | writel(0x0, base + ECC_CTRL_OFST); | |
194 | ||
195 | return 0; | |
196 | } | |
197 | ||
198 | /** | |
199 | * synps_edac_handle_error - Handle controller error types CE and UE | |
200 | * @mci: Pointer to the edac memory controller instance | |
201 | * @p: Pointer to the synopsys ecc status structure | |
202 | * | |
203 | * Handles the controller ECC correctable and un correctable error. | |
204 | */ | |
205 | static void synps_edac_handle_error(struct mem_ctl_info *mci, | |
206 | struct synps_ecc_status *p) | |
207 | { | |
208 | struct synps_edac_priv *priv = mci->pvt_info; | |
209 | struct ecc_error_info *pinf; | |
210 | ||
211 | if (p->ce_cnt) { | |
212 | pinf = &p->ceinfo; | |
213 | snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, | |
214 | "DDR ECC error type :%s Row %d Bank %d Col %d ", | |
215 | "CE", pinf->row, pinf->bank, pinf->col); | |
216 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, | |
217 | p->ce_cnt, 0, 0, 0, 0, 0, -1, | |
218 | priv->message, ""); | |
219 | } | |
220 | ||
221 | if (p->ue_cnt) { | |
222 | pinf = &p->ueinfo; | |
223 | snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, | |
224 | "DDR ECC error type :%s Row %d Bank %d Col %d ", | |
225 | "UE", pinf->row, pinf->bank, pinf->col); | |
226 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, | |
227 | p->ue_cnt, 0, 0, 0, 0, 0, -1, | |
228 | priv->message, ""); | |
229 | } | |
230 | ||
231 | memset(p, 0, sizeof(*p)); | |
232 | } | |
233 | ||
234 | /** | |
235 | * synps_edac_check - Check controller for ECC errors | |
236 | * @mci: Pointer to the edac memory controller instance | |
237 | * | |
238 | * Used to check and post ECC errors. Called by the polling thread | |
239 | */ | |
240 | static void synps_edac_check(struct mem_ctl_info *mci) | |
241 | { | |
242 | struct synps_edac_priv *priv = mci->pvt_info; | |
243 | int status; | |
244 | ||
245 | status = synps_edac_geterror_info(priv->baseaddr, &priv->stat); | |
246 | if (status) | |
247 | return; | |
248 | ||
249 | priv->ce_cnt += priv->stat.ce_cnt; | |
250 | priv->ue_cnt += priv->stat.ue_cnt; | |
251 | synps_edac_handle_error(mci, &priv->stat); | |
252 | ||
253 | edac_dbg(3, "Total error count ce %d ue %d\n", | |
254 | priv->ce_cnt, priv->ue_cnt); | |
255 | } | |
256 | ||
257 | /** | |
258 | * synps_edac_get_dtype - Return the controller memory width | |
259 | * @base: Pointer to the ddr memory controller base address | |
260 | * | |
261 | * Get the EDAC device type width appropriate for the current controller | |
262 | * configuration. | |
263 | * | |
264 | * Return: a device type width enumeration. | |
265 | */ | |
266 | static enum dev_type synps_edac_get_dtype(const void __iomem *base) | |
267 | { | |
268 | enum dev_type dt; | |
269 | u32 width; | |
270 | ||
271 | width = readl(base + CTRL_OFST); | |
272 | width = (width & CTRL_BW_MASK) >> CTRL_BW_SHIFT; | |
273 | ||
274 | switch (width) { | |
275 | case DDRCTL_WDTH_16: | |
276 | dt = DEV_X2; | |
277 | break; | |
278 | case DDRCTL_WDTH_32: | |
279 | dt = DEV_X4; | |
280 | break; | |
281 | default: | |
282 | dt = DEV_UNKNOWN; | |
283 | } | |
284 | ||
285 | return dt; | |
286 | } | |
287 | ||
288 | /** | |
289 | * synps_edac_get_eccstate - Return the controller ecc enable/disable status | |
290 | * @base: Pointer to the ddr memory controller base address | |
291 | * | |
292 | * Get the ECC enable/disable status for the controller | |
293 | * | |
294 | * Return: a ecc status boolean i.e true/false - enabled/disabled. | |
295 | */ | |
296 | static bool synps_edac_get_eccstate(void __iomem *base) | |
297 | { | |
298 | enum dev_type dt; | |
299 | u32 ecctype; | |
300 | bool state = false; | |
301 | ||
302 | dt = synps_edac_get_dtype(base); | |
303 | if (dt == DEV_UNKNOWN) | |
304 | return state; | |
305 | ||
306 | ecctype = readl(base + SCRUB_OFST) & SCRUB_MODE_MASK; | |
307 | if ((ecctype == SCRUB_MODE_SECDED) && (dt == DEV_X2)) | |
308 | state = true; | |
309 | ||
310 | return state; | |
311 | } | |
312 | ||
313 | /** | |
314 | * synps_edac_get_memsize - reads the size of the attached memory device | |
315 | * | |
316 | * Return: the memory size in bytes | |
317 | */ | |
318 | static u32 synps_edac_get_memsize(void) | |
319 | { | |
320 | struct sysinfo inf; | |
321 | ||
322 | si_meminfo(&inf); | |
323 | ||
324 | return inf.totalram * inf.mem_unit; | |
325 | } | |
326 | ||
327 | /** | |
328 | * synps_edac_get_mtype - Returns controller memory type | |
329 | * @base: pointer to the synopsys ecc status structure | |
330 | * | |
331 | * Get the EDAC memory type appropriate for the current controller | |
332 | * configuration. | |
333 | * | |
334 | * Return: a memory type enumeration. | |
335 | */ | |
336 | static enum mem_type synps_edac_get_mtype(const void __iomem *base) | |
337 | { | |
338 | enum mem_type mt; | |
339 | u32 memtype; | |
340 | ||
341 | memtype = readl(base + T_ZQ_OFST); | |
342 | ||
343 | if (memtype & T_ZQ_DDRMODE_MASK) | |
344 | mt = MEM_DDR3; | |
345 | else | |
346 | mt = MEM_DDR2; | |
347 | ||
348 | return mt; | |
349 | } | |
350 | ||
351 | /** | |
352 | * synps_edac_init_csrows - Initialize the cs row data | |
353 | * @mci: Pointer to the edac memory controller instance | |
354 | * | |
355 | * Initializes the chip select rows associated with the EDAC memory | |
356 | * controller instance | |
357 | * | |
358 | * Return: Unconditionally 0. | |
359 | */ | |
360 | static int synps_edac_init_csrows(struct mem_ctl_info *mci) | |
361 | { | |
362 | struct csrow_info *csi; | |
363 | struct dimm_info *dimm; | |
364 | struct synps_edac_priv *priv = mci->pvt_info; | |
365 | u32 size; | |
366 | int row, j; | |
367 | ||
368 | for (row = 0; row < mci->nr_csrows; row++) { | |
369 | csi = mci->csrows[row]; | |
370 | size = synps_edac_get_memsize(); | |
371 | ||
372 | for (j = 0; j < csi->nr_channels; j++) { | |
373 | dimm = csi->channels[j]->dimm; | |
374 | dimm->edac_mode = EDAC_FLAG_SECDED; | |
375 | dimm->mtype = synps_edac_get_mtype(priv->baseaddr); | |
376 | dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels; | |
377 | dimm->grain = SYNPS_EDAC_ERR_GRAIN; | |
378 | dimm->dtype = synps_edac_get_dtype(priv->baseaddr); | |
379 | } | |
380 | } | |
381 | ||
382 | return 0; | |
383 | } | |
384 | ||
385 | /** | |
386 | * synps_edac_mc_init - Initialize driver instance | |
387 | * @mci: Pointer to the edac memory controller instance | |
388 | * @pdev: Pointer to the platform_device struct | |
389 | * | |
390 | * Performs initialization of the EDAC memory controller instance and | |
391 | * related driver-private data associated with the memory controller the | |
392 | * instance is bound to. | |
393 | * | |
394 | * Return: Always zero. | |
395 | */ | |
396 | static int synps_edac_mc_init(struct mem_ctl_info *mci, | |
397 | struct platform_device *pdev) | |
398 | { | |
399 | int status; | |
400 | struct synps_edac_priv *priv; | |
401 | ||
402 | mci->pdev = &pdev->dev; | |
403 | priv = mci->pvt_info; | |
404 | platform_set_drvdata(pdev, mci); | |
405 | ||
406 | /* Initialize controller capabilities and configuration */ | |
407 | mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR2; | |
408 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | |
409 | mci->scrub_cap = SCRUB_HW_SRC; | |
410 | mci->scrub_mode = SCRUB_NONE; | |
411 | ||
412 | mci->edac_cap = EDAC_FLAG_SECDED; | |
413 | mci->ctl_name = "synps_ddr_controller"; | |
414 | mci->dev_name = SYNPS_EDAC_MOD_STRING; | |
415 | mci->mod_name = SYNPS_EDAC_MOD_VER; | |
ae9b56e3 PCK |
416 | |
417 | edac_op_state = EDAC_OPSTATE_POLL; | |
418 | mci->edac_check = synps_edac_check; | |
419 | mci->ctl_page_to_phys = NULL; | |
420 | ||
421 | status = synps_edac_init_csrows(mci); | |
422 | ||
423 | return status; | |
424 | } | |
425 | ||
426 | /** | |
427 | * synps_edac_mc_probe - Check controller and bind driver | |
428 | * @pdev: Pointer to the platform_device struct | |
429 | * | |
430 | * Probes a specific controller instance for binding with the driver. | |
431 | * | |
432 | * Return: 0 if the controller instance was successfully bound to the | |
433 | * driver; otherwise, < 0 on error. | |
434 | */ | |
435 | static int synps_edac_mc_probe(struct platform_device *pdev) | |
436 | { | |
437 | struct mem_ctl_info *mci; | |
438 | struct edac_mc_layer layers[2]; | |
439 | struct synps_edac_priv *priv; | |
440 | int rc; | |
441 | struct resource *res; | |
442 | void __iomem *baseaddr; | |
443 | ||
444 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
445 | baseaddr = devm_ioremap_resource(&pdev->dev, res); | |
446 | if (IS_ERR(baseaddr)) | |
447 | return PTR_ERR(baseaddr); | |
448 | ||
449 | if (!synps_edac_get_eccstate(baseaddr)) { | |
450 | edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); | |
451 | return -ENXIO; | |
452 | } | |
453 | ||
454 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; | |
455 | layers[0].size = SYNPS_EDAC_NR_CSROWS; | |
456 | layers[0].is_virt_csrow = true; | |
457 | layers[1].type = EDAC_MC_LAYER_CHANNEL; | |
458 | layers[1].size = SYNPS_EDAC_NR_CHANS; | |
459 | layers[1].is_virt_csrow = false; | |
460 | ||
461 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, | |
462 | sizeof(struct synps_edac_priv)); | |
463 | if (!mci) { | |
464 | edac_printk(KERN_ERR, EDAC_MC, | |
465 | "Failed memory allocation for mc instance\n"); | |
466 | return -ENOMEM; | |
467 | } | |
468 | ||
469 | priv = mci->pvt_info; | |
470 | priv->baseaddr = baseaddr; | |
471 | rc = synps_edac_mc_init(mci, pdev); | |
472 | if (rc) { | |
473 | edac_printk(KERN_ERR, EDAC_MC, | |
474 | "Failed to initialize instance\n"); | |
475 | goto free_edac_mc; | |
476 | } | |
477 | ||
478 | rc = edac_mc_add_mc(mci); | |
479 | if (rc) { | |
480 | edac_printk(KERN_ERR, EDAC_MC, | |
481 | "Failed to register with EDAC core\n"); | |
482 | goto free_edac_mc; | |
483 | } | |
484 | ||
485 | /* | |
486 | * Start capturing the correctable and uncorrectable errors. A write of | |
487 | * 0 starts the counters. | |
488 | */ | |
489 | writel(0x0, baseaddr + ECC_CTRL_OFST); | |
490 | return rc; | |
491 | ||
492 | free_edac_mc: | |
493 | edac_mc_free(mci); | |
494 | ||
495 | return rc; | |
496 | } | |
497 | ||
498 | /** | |
499 | * synps_edac_mc_remove - Unbind driver from controller | |
500 | * @pdev: Pointer to the platform_device struct | |
501 | * | |
502 | * Return: Unconditionally 0 | |
503 | */ | |
504 | static int synps_edac_mc_remove(struct platform_device *pdev) | |
505 | { | |
506 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); | |
507 | ||
508 | edac_mc_del_mc(&pdev->dev); | |
509 | edac_mc_free(mci); | |
510 | ||
511 | return 0; | |
512 | } | |
513 | ||
1afaa055 | 514 | static const struct of_device_id synps_edac_match[] = { |
ae9b56e3 PCK |
515 | { .compatible = "xlnx,zynq-ddrc-a05", }, |
516 | { /* end of table */ } | |
517 | }; | |
518 | ||
519 | MODULE_DEVICE_TABLE(of, synps_edac_match); | |
520 | ||
521 | static struct platform_driver synps_edac_mc_driver = { | |
522 | .driver = { | |
523 | .name = "synopsys-edac", | |
524 | .of_match_table = synps_edac_match, | |
525 | }, | |
526 | .probe = synps_edac_mc_probe, | |
527 | .remove = synps_edac_mc_remove, | |
528 | }; | |
529 | ||
530 | module_platform_driver(synps_edac_mc_driver); | |
531 | ||
532 | MODULE_AUTHOR("Xilinx Inc"); | |
533 | MODULE_DESCRIPTION("Synopsys DDR ECC driver"); | |
534 | MODULE_LICENSE("GPL v2"); |