aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYork Sun <york.sun@nxp.com>2016-08-09 17:55:43 -0400
committerBorislav Petkov <bp@suse.de>2016-09-01 04:28:02 -0400
commit339fdff14c1ed34acc9c3368e01b56f80692cf83 (patch)
tree390b7ae614e13a47f61dfda06939d6b1923b938b
parent4e2c3252d2426cd05286e38650365f215571d3c6 (diff)
EDAC, fsl_ddr: Add support for little endian
Get endianness from device tree. Both big endian and little endian are supported. Default to big endian for backwards compatibility to MPC85xx. Signed-off-by: York Sun <york.sun@nxp.com> Acked-by: Rob Herring <robh+dt@kernel.org> Cc: devicetree@vger.kernel.org Cc: linux-edac <linux-edac@vger.kernel.org> Cc: morbidrsa@gmail.com Cc: oss@buserror.net Cc: stuart.yoder@nxp.com Link: http://lkml.kernel.org/r/1470779760-16483-7-git-send-email-york.sun@nxp.com Signed-off-by: Borislav Petkov <bp@suse.de>
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/fsl/ddr.txt (renamed from Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt)2
-rw-r--r--drivers/edac/fsl_ddr_edac.c96
2 files changed, 58 insertions, 40 deletions
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt b/Documentation/devicetree/bindings/memory-controllers/fsl/ddr.txt
index f87856faf1ab..dde6d837083a 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/fsl/ddr.txt
@@ -7,6 +7,8 @@ Properties:
7 "fsl,qoriq-memory-controller". 7 "fsl,qoriq-memory-controller".
8- reg : Address and size of DDR controller registers 8- reg : Address and size of DDR controller registers
9- interrupts : Error interrupt of DDR controller 9- interrupts : Error interrupt of DDR controller
10- little-endian : Specifies little-endian access to registers
11 If omitted, big-endian will be used.
10 12
11Example 1: 13Example 1:
12 14
diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index 46b00e15e442..6d4dd84a9d48 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -13,7 +13,6 @@
13 * the terms of the GNU General Public License version 2. This program 13 * the terms of the GNU General Public License version 2. This program
14 * is licensed "as is" without any warranty of any kind, whether express 14 * is licensed "as is" without any warranty of any kind, whether express
15 * or implied. 15 * or implied.
16 *
17 */ 16 */
18#include <linux/module.h> 17#include <linux/module.h>
19#include <linux/init.h> 18#include <linux/init.h>
@@ -37,6 +36,20 @@ static int edac_mc_idx;
37 36
38static u32 orig_ddr_err_disable; 37static u32 orig_ddr_err_disable;
39static u32 orig_ddr_err_sbe; 38static u32 orig_ddr_err_sbe;
39static bool little_endian;
40
41static inline u32 ddr_in32(void __iomem *addr)
42{
43 return little_endian ? ioread32(addr) : ioread32be(addr);
44}
45
46static inline void ddr_out32(void __iomem *addr, u32 value)
47{
48 if (little_endian)
49 iowrite32(value, addr);
50 else
51 iowrite32be(value, addr);
52}
40 53
41/************************ MC SYSFS parts ***********************************/ 54/************************ MC SYSFS parts ***********************************/
42 55
@@ -49,8 +62,7 @@ static ssize_t fsl_mc_inject_data_hi_show(struct device *dev,
49 struct mem_ctl_info *mci = to_mci(dev); 62 struct mem_ctl_info *mci = to_mci(dev);
50 struct fsl_mc_pdata *pdata = mci->pvt_info; 63 struct fsl_mc_pdata *pdata = mci->pvt_info;
51 return sprintf(data, "0x%08x", 64 return sprintf(data, "0x%08x",
52 in_be32(pdata->mc_vbase + 65 ddr_in32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI));
53 FSL_MC_DATA_ERR_INJECT_HI));
54} 66}
55 67
56static ssize_t fsl_mc_inject_data_lo_show(struct device *dev, 68static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
@@ -60,8 +72,7 @@ static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
60 struct mem_ctl_info *mci = to_mci(dev); 72 struct mem_ctl_info *mci = to_mci(dev);
61 struct fsl_mc_pdata *pdata = mci->pvt_info; 73 struct fsl_mc_pdata *pdata = mci->pvt_info;
62 return sprintf(data, "0x%08x", 74 return sprintf(data, "0x%08x",
63 in_be32(pdata->mc_vbase + 75 ddr_in32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO));
64 FSL_MC_DATA_ERR_INJECT_LO));
65} 76}
66 77
67static ssize_t fsl_mc_inject_ctrl_show(struct device *dev, 78static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
@@ -71,7 +82,7 @@ static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
71 struct mem_ctl_info *mci = to_mci(dev); 82 struct mem_ctl_info *mci = to_mci(dev);
72 struct fsl_mc_pdata *pdata = mci->pvt_info; 83 struct fsl_mc_pdata *pdata = mci->pvt_info;
73 return sprintf(data, "0x%08x", 84 return sprintf(data, "0x%08x",
74 in_be32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT)); 85 ddr_in32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT));
75} 86}
76 87
77static ssize_t fsl_mc_inject_data_hi_store(struct device *dev, 88static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
@@ -81,8 +92,8 @@ static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
81 struct mem_ctl_info *mci = to_mci(dev); 92 struct mem_ctl_info *mci = to_mci(dev);
82 struct fsl_mc_pdata *pdata = mci->pvt_info; 93 struct fsl_mc_pdata *pdata = mci->pvt_info;
83 if (isdigit(*data)) { 94 if (isdigit(*data)) {
84 out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI, 95 ddr_out32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI,
85 simple_strtoul(data, NULL, 0)); 96 simple_strtoul(data, NULL, 0));
86 return count; 97 return count;
87 } 98 }
88 return 0; 99 return 0;
@@ -95,8 +106,8 @@ static ssize_t fsl_mc_inject_data_lo_store(struct device *dev,
95 struct mem_ctl_info *mci = to_mci(dev); 106 struct mem_ctl_info *mci = to_mci(dev);
96 struct fsl_mc_pdata *pdata = mci->pvt_info; 107 struct fsl_mc_pdata *pdata = mci->pvt_info;
97 if (isdigit(*data)) { 108 if (isdigit(*data)) {
98 out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO, 109 ddr_out32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO,
99 simple_strtoul(data, NULL, 0)); 110 simple_strtoul(data, NULL, 0));
100 return count; 111 return count;
101 } 112 }
102 return 0; 113 return 0;
@@ -109,8 +120,8 @@ static ssize_t fsl_mc_inject_ctrl_store(struct device *dev,
109 struct mem_ctl_info *mci = to_mci(dev); 120 struct mem_ctl_info *mci = to_mci(dev);
110 struct fsl_mc_pdata *pdata = mci->pvt_info; 121 struct fsl_mc_pdata *pdata = mci->pvt_info;
111 if (isdigit(*data)) { 122 if (isdigit(*data)) {
112 out_be32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT, 123 ddr_out32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT,
113 simple_strtoul(data, NULL, 0)); 124 simple_strtoul(data, NULL, 0));
114 return count; 125 return count;
115 } 126 }
116 return 0; 127 return 0;
@@ -256,7 +267,7 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
256 int bad_data_bit; 267 int bad_data_bit;
257 int bad_ecc_bit; 268 int bad_ecc_bit;
258 269
259 err_detect = in_be32(pdata->mc_vbase + FSL_MC_ERR_DETECT); 270 err_detect = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DETECT);
260 if (!err_detect) 271 if (!err_detect)
261 return; 272 return;
262 273
@@ -265,23 +276,23 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
265 276
266 /* no more processing if not ECC bit errors */ 277 /* no more processing if not ECC bit errors */
267 if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) { 278 if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) {
268 out_be32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect); 279 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect);
269 return; 280 return;
270 } 281 }
271 282
272 syndrome = in_be32(pdata->mc_vbase + FSL_MC_CAPTURE_ECC); 283 syndrome = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_ECC);
273 284
274 /* Mask off appropriate bits of syndrome based on bus width */ 285 /* Mask off appropriate bits of syndrome based on bus width */
275 bus_width = (in_be32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG) & 286 bus_width = (ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG) &
276 DSC_DBW_MASK) ? 32 : 64; 287 DSC_DBW_MASK) ? 32 : 64;
277 if (bus_width == 64) 288 if (bus_width == 64)
278 syndrome &= 0xff; 289 syndrome &= 0xff;
279 else 290 else
280 syndrome &= 0xffff; 291 syndrome &= 0xffff;
281 292
282 err_addr = make64( 293 err_addr = make64(
283 in_be32(pdata->mc_vbase + FSL_MC_CAPTURE_EXT_ADDRESS), 294 ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_EXT_ADDRESS),
284 in_be32(pdata->mc_vbase + FSL_MC_CAPTURE_ADDRESS)); 295 ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_ADDRESS));
285 pfn = err_addr >> PAGE_SHIFT; 296 pfn = err_addr >> PAGE_SHIFT;
286 297
287 for (row_index = 0; row_index < mci->nr_csrows; row_index++) { 298 for (row_index = 0; row_index < mci->nr_csrows; row_index++) {
@@ -290,8 +301,8 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
290 break; 301 break;
291 } 302 }
292 303
293 cap_high = in_be32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_HI); 304 cap_high = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_HI);
294 cap_low = in_be32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_LO); 305 cap_low = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_LO);
295 306
296 /* 307 /*
297 * Analyze single-bit errors on 64-bit wide buses 308 * Analyze single-bit errors on 64-bit wide buses
@@ -337,7 +348,7 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
337 row_index, 0, -1, 348 row_index, 0, -1,
338 mci->ctl_name, ""); 349 mci->ctl_name, "");
339 350
340 out_be32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect); 351 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect);
341} 352}
342 353
343static irqreturn_t fsl_mc_isr(int irq, void *dev_id) 354static irqreturn_t fsl_mc_isr(int irq, void *dev_id)
@@ -346,7 +357,7 @@ static irqreturn_t fsl_mc_isr(int irq, void *dev_id)
346 struct fsl_mc_pdata *pdata = mci->pvt_info; 357 struct fsl_mc_pdata *pdata = mci->pvt_info;
347 u32 err_detect; 358 u32 err_detect;
348 359
349 err_detect = in_be32(pdata->mc_vbase + FSL_MC_ERR_DETECT); 360 err_detect = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DETECT);
350 if (!err_detect) 361 if (!err_detect)
351 return IRQ_NONE; 362 return IRQ_NONE;
352 363
@@ -366,7 +377,7 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
366 u32 cs_bnds; 377 u32 cs_bnds;
367 int index; 378 int index;
368 379
369 sdram_ctl = in_be32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG); 380 sdram_ctl = ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG);
370 381
371 sdtype = sdram_ctl & DSC_SDTYPE_MASK; 382 sdtype = sdram_ctl & DSC_SDTYPE_MASK;
372 if (sdram_ctl & DSC_RD_EN) { 383 if (sdram_ctl & DSC_RD_EN) {
@@ -414,8 +425,8 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
414 csrow = mci->csrows[index]; 425 csrow = mci->csrows[index];
415 dimm = csrow->channels[0]->dimm; 426 dimm = csrow->channels[0]->dimm;
416 427
417 cs_bnds = in_be32(pdata->mc_vbase + FSL_MC_CS_BNDS_0 + 428 cs_bnds = ddr_in32(pdata->mc_vbase + FSL_MC_CS_BNDS_0 +
418 (index * FSL_MC_CS_BNDS_OFS)); 429 (index * FSL_MC_CS_BNDS_OFS));
419 430
420 start = (cs_bnds & 0xffff0000) >> 16; 431 start = (cs_bnds & 0xffff0000) >> 16;
421 end = (cs_bnds & 0x0000ffff); 432 end = (cs_bnds & 0x0000ffff);
@@ -474,6 +485,12 @@ int fsl_mc_err_probe(struct platform_device *op)
474 mci->ctl_name = pdata->name; 485 mci->ctl_name = pdata->name;
475 mci->dev_name = pdata->name; 486 mci->dev_name = pdata->name;
476 487
488 /*
489 * Get the endianness of DDR controller registers.
490 * Default is big endian.
491 */
492 little_endian = of_property_read_bool(op->dev.of_node, "little-endian");
493
477 res = of_address_to_resource(op->dev.of_node, 0, &r); 494 res = of_address_to_resource(op->dev.of_node, 0, &r);
478 if (res) { 495 if (res) {
479 pr_err("%s: Unable to get resource for MC err regs\n", 496 pr_err("%s: Unable to get resource for MC err regs\n",
@@ -496,7 +513,7 @@ int fsl_mc_err_probe(struct platform_device *op)
496 goto err; 513 goto err;
497 } 514 }
498 515
499 sdram_ctl = in_be32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG); 516 sdram_ctl = ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG);
500 if (!(sdram_ctl & DSC_ECC_EN)) { 517 if (!(sdram_ctl & DSC_ECC_EN)) {
501 /* no ECC */ 518 /* no ECC */
502 pr_warn("%s: No ECC DIMMs discovered\n", __func__); 519 pr_warn("%s: No ECC DIMMs discovered\n", __func__);
@@ -523,12 +540,11 @@ int fsl_mc_err_probe(struct platform_device *op)
523 fsl_ddr_init_csrows(mci); 540 fsl_ddr_init_csrows(mci);
524 541
525 /* store the original error disable bits */ 542 /* store the original error disable bits */
526 orig_ddr_err_disable = 543 orig_ddr_err_disable = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DISABLE);
527 in_be32(pdata->mc_vbase + FSL_MC_ERR_DISABLE); 544 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DISABLE, 0);
528 out_be32(pdata->mc_vbase + FSL_MC_ERR_DISABLE, 0);
529 545
530 /* clear all error bits */ 546 /* clear all error bits */
531 out_be32(pdata->mc_vbase + FSL_MC_ERR_DETECT, ~0); 547 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, ~0);
532 548
533 if (edac_mc_add_mc_with_groups(mci, fsl_ddr_dev_groups)) { 549 if (edac_mc_add_mc_with_groups(mci, fsl_ddr_dev_groups)) {
534 edac_dbg(3, "failed edac_mc_add_mc()\n"); 550 edac_dbg(3, "failed edac_mc_add_mc()\n");
@@ -536,15 +552,15 @@ int fsl_mc_err_probe(struct platform_device *op)
536 } 552 }
537 553
538 if (edac_op_state == EDAC_OPSTATE_INT) { 554 if (edac_op_state == EDAC_OPSTATE_INT) {
539 out_be32(pdata->mc_vbase + FSL_MC_ERR_INT_EN, 555 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_INT_EN,
540 DDR_EIE_MBEE | DDR_EIE_SBEE); 556 DDR_EIE_MBEE | DDR_EIE_SBEE);
541 557
542 /* store the original error management threshold */ 558 /* store the original error management threshold */
543 orig_ddr_err_sbe = in_be32(pdata->mc_vbase + 559 orig_ddr_err_sbe = ddr_in32(pdata->mc_vbase +
544 FSL_MC_ERR_SBE) & 0xff0000; 560 FSL_MC_ERR_SBE) & 0xff0000;
545 561
546 /* set threshold to 1 error per interrupt */ 562 /* set threshold to 1 error per interrupt */
547 out_be32(pdata->mc_vbase + FSL_MC_ERR_SBE, 0x10000); 563 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_SBE, 0x10000);
548 564
549 /* register interrupts */ 565 /* register interrupts */
550 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0); 566 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
@@ -586,13 +602,13 @@ int fsl_mc_err_remove(struct platform_device *op)
586 edac_dbg(0, "\n"); 602 edac_dbg(0, "\n");
587 603
588 if (edac_op_state == EDAC_OPSTATE_INT) { 604 if (edac_op_state == EDAC_OPSTATE_INT) {
589 out_be32(pdata->mc_vbase + FSL_MC_ERR_INT_EN, 0);
590 irq_dispose_mapping(pdata->irq); 605 irq_dispose_mapping(pdata->irq);
606 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_INT_EN, 0);
591 } 607 }
592 608
593 out_be32(pdata->mc_vbase + FSL_MC_ERR_DISABLE, 609 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DISABLE,
594 orig_ddr_err_disable); 610 orig_ddr_err_disable);
595 out_be32(pdata->mc_vbase + FSL_MC_ERR_SBE, orig_ddr_err_sbe); 611 ddr_out32(pdata->mc_vbase + FSL_MC_ERR_SBE, orig_ddr_err_sbe);
596 612
597 edac_mc_del_mc(&op->dev); 613 edac_mc_del_mc(&op->dev);
598 edac_mc_free(mci); 614 edac_mc_free(mci);