ocram.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright Altera Corporation (C) 2016. All rights reserved.
  4. */
  5. #include <linux/delay.h>
  6. #include <linux/io.h>
  7. #include <linux/of.h>
  8. #include <linux/of_address.h>
  9. #include "core.h"
  10. #define ALTR_OCRAM_CLEAR_ECC 0x00000018
  11. #define ALTR_OCRAM_ECC_EN 0x00000019
  12. void socfpga_init_ocram_ecc(void)
  13. {
  14. struct device_node *np;
  15. void __iomem *mapped_ocr_edac_addr;
  16. /* Find the OCRAM EDAC device tree node */
  17. np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
  18. if (!np) {
  19. pr_err("Unable to find socfpga-ocram-ecc\n");
  20. return;
  21. }
  22. mapped_ocr_edac_addr = of_iomap(np, 0);
  23. of_node_put(np);
  24. if (!mapped_ocr_edac_addr) {
  25. pr_err("Unable to map OCRAM ecc regs.\n");
  26. return;
  27. }
  28. /* Clear any pending OCRAM ECC interrupts, then enable ECC */
  29. writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr);
  30. writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr);
  31. iounmap(mapped_ocr_edac_addr);
  32. }
  33. /* Arria10 OCRAM Section */
  34. #define ALTR_A10_ECC_CTRL_OFST 0x08
  35. #define ALTR_A10_OCRAM_ECC_EN_CTL (BIT(1) | BIT(0))
  36. #define ALTR_A10_ECC_INITA BIT(16)
  37. #define ALTR_A10_ECC_INITSTAT_OFST 0x0C
  38. #define ALTR_A10_ECC_INITCOMPLETEA BIT(0)
  39. #define ALTR_A10_ECC_INITCOMPLETEB BIT(8)
  40. #define ALTR_A10_ECC_ERRINTEN_OFST 0x10
  41. #define ALTR_A10_ECC_SERRINTEN BIT(0)
  42. #define ALTR_A10_ECC_INTSTAT_OFST 0x20
  43. #define ALTR_A10_ECC_SERRPENA BIT(0)
  44. #define ALTR_A10_ECC_DERRPENA BIT(8)
  45. #define ALTR_A10_ECC_ERRPENA_MASK (ALTR_A10_ECC_SERRPENA | \
  46. ALTR_A10_ECC_DERRPENA)
  47. /* ECC Manager Defines */
  48. #define A10_SYSMGR_ECC_INTMASK_SET_OFST 0x94
  49. #define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98
  50. #define A10_SYSMGR_ECC_INTMASK_OCRAM BIT(1)
  51. #define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000
  52. static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr)
  53. {
  54. u32 value = readl(ioaddr);
  55. value |= bit_mask;
  56. writel(value, ioaddr);
  57. }
  58. static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr)
  59. {
  60. u32 value = readl(ioaddr);
  61. value &= ~bit_mask;
  62. writel(value, ioaddr);
  63. }
  64. static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr)
  65. {
  66. u32 value = readl(ioaddr);
  67. return (value & bit_mask) ? 1 : 0;
  68. }
  69. /*
  70. * This function uses the memory initialization block in the Arria10 ECC
  71. * controller to initialize/clear the entire memory data and ECC data.
  72. */
  73. static int altr_init_memory_port(void __iomem *ioaddr)
  74. {
  75. int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US;
  76. ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
  77. while (limit--) {
  78. if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
  79. (ioaddr + ALTR_A10_ECC_INITSTAT_OFST)))
  80. break;
  81. udelay(1);
  82. }
  83. if (limit < 0)
  84. return -EBUSY;
  85. /* Clear any pending ECC interrupts */
  86. writel(ALTR_A10_ECC_ERRPENA_MASK,
  87. (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
  88. return 0;
  89. }
  90. void socfpga_init_arria10_ocram_ecc(void)
  91. {
  92. struct device_node *np;
  93. int ret = 0;
  94. void __iomem *ecc_block_base;
  95. if (!sys_manager_base_addr) {
  96. pr_err("SOCFPGA: sys-mgr is not initialized\n");
  97. return;
  98. }
  99. /* Find the OCRAM EDAC device tree node */
  100. np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc");
  101. if (!np) {
  102. pr_err("Unable to find socfpga-a10-ocram-ecc\n");
  103. return;
  104. }
  105. /* Map the ECC Block */
  106. ecc_block_base = of_iomap(np, 0);
  107. of_node_put(np);
  108. if (!ecc_block_base) {
  109. pr_err("Unable to map OCRAM ECC block\n");
  110. return;
  111. }
  112. /* Disable ECC */
  113. writel(ALTR_A10_OCRAM_ECC_EN_CTL,
  114. sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST);
  115. ecc_clear_bits(ALTR_A10_ECC_SERRINTEN,
  116. (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
  117. ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
  118. (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
  119. /* Ensure all writes complete */
  120. wmb();
  121. /* Use HW initialization block to initialize memory for ECC */
  122. ret = altr_init_memory_port(ecc_block_base);
  123. if (ret) {
  124. pr_err("ECC: cannot init OCRAM PORTA memory\n");
  125. goto exit;
  126. }
  127. /* Enable ECC */
  128. ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
  129. (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
  130. ecc_set_bits(ALTR_A10_ECC_SERRINTEN,
  131. (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
  132. writel(ALTR_A10_OCRAM_ECC_EN_CTL,
  133. sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST);
  134. /* Ensure all writes complete */
  135. wmb();
  136. exit:
  137. iounmap(ecc_block_base);
  138. }