ocram.c 4.4 KB

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