Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

York Sun and committed by
Borislav Petkov
339fdff1 4e2c3252

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