ocram.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright Altera Corporation (C) 2016. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along with
  14. * this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <linux/delay.h>
  17. #include <linux/io.h>
  18. #include <linux/genalloc.h>
  19. #include <linux/module.h>
  20. #include <linux/of_address.h>
  21. #include <linux/of_platform.h>
  22. #include "core.h"
  23. #define ALTR_OCRAM_CLEAR_ECC 0x00000018
  24. #define ALTR_OCRAM_ECC_EN 0x00000019
  25. void socfpga_init_ocram_ecc(void)
  26. {
  27. struct device_node *np;
  28. void __iomem *mapped_ocr_edac_addr;
  29. /* Find the OCRAM EDAC device tree node */
  30. np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
  31. if (!np) {
  32. pr_err("Unable to find socfpga-ocram-ecc\n");
  33. return;
  34. }
  35. mapped_ocr_edac_addr = of_iomap(np, 0);
  36. of_node_put(np);
  37. if (!mapped_ocr_edac_addr) {
  38. pr_err("Unable to map OCRAM ecc regs.\n");
  39. return;
  40. }
  41. /* Clear any pending OCRAM ECC interrupts, then enable ECC */
  42. writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr);
  43. writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr);
  44. iounmap(mapped_ocr_edac_addr);
  45. }
  46. /* Arria10 OCRAM Section */
  47. #define ALTR_A10_ECC_CTRL_OFST 0x08
  48. #define ALTR_A10_OCRAM_ECC_EN_CTL (BIT(1) | BIT(0))
  49. #define ALTR_A10_ECC_INITA BIT(16)
  50. #define ALTR_A10_ECC_INITSTAT_OFST 0x0C
  51. #define ALTR_A10_ECC_INITCOMPLETEA BIT(0)
  52. #define ALTR_A10_ECC_INITCOMPLETEB BIT(8)
  53. #define ALTR_A10_ECC_ERRINTEN_OFST 0x10
  54. #define ALTR_A10_ECC_SERRINTEN BIT(0)
  55. #define ALTR_A10_ECC_INTSTAT_OFST 0x20
  56. #define ALTR_A10_ECC_SERRPENA BIT(0)
  57. #define ALTR_A10_ECC_DERRPENA BIT(8)
  58. #define ALTR_A10_ECC_ERRPENA_MASK (ALTR_A10_ECC_SERRPENA | \
  59. ALTR_A10_ECC_DERRPENA)
  60. /* ECC Manager Defines */
  61. #define A10_SYSMGR_ECC_INTMASK_SET_OFST 0x94
  62. #define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98
  63. #define A10_SYSMGR_ECC_INTMASK_OCRAM BIT(1)
  64. #define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000
  65. static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr)
  66. {
  67. u32 value = readl(ioaddr);
  68. value |= bit_mask;
  69. writel(value, ioaddr);
  70. }
  71. static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr)
  72. {
  73. u32 value = readl(ioaddr);
  74. value &= ~bit_mask;
  75. writel(value, ioaddr);
  76. }
  77. static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr)
  78. {
  79. u32 value = readl(ioaddr);
  80. return (value & bit_mask) ? 1 : 0;
  81. }
  82. /*
  83. * This function uses the memory initialization block in the Arria10 ECC
  84. * controller to initialize/clear the entire memory data and ECC data.
  85. */
  86. static int altr_init_memory_port(void __iomem *ioaddr)
  87. {
  88. int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US;
  89. ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
  90. while (limit--) {
  91. if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
  92. (ioaddr + ALTR_A10_ECC_INITSTAT_OFST)))
  93. break;
  94. udelay(1);
  95. }
  96. if (limit < 0)
  97. return -EBUSY;
  98. /* Clear any pending ECC interrupts */
  99. writel(ALTR_A10_ECC_ERRPENA_MASK,
  100. (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
  101. return 0;
  102. }
  103. void socfpga_init_arria10_ocram_ecc(void)
  104. {
  105. struct device_node *np;
  106. int ret = 0;
  107. void __iomem *ecc_block_base;
  108. if (!sys_manager_base_addr) {
  109. pr_err("SOCFPGA: sys-mgr is not initialized\n");
  110. return;
  111. }
  112. /* Find the OCRAM EDAC device tree node */
  113. np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc");
  114. if (!np) {
  115. pr_err("Unable to find socfpga-a10-ocram-ecc\n");
  116. return;
  117. }
  118. /* Map the ECC Block */
  119. ecc_block_base = of_iomap(np, 0);
  120. of_node_put(np);
  121. if (!ecc_block_base) {
  122. pr_err("Unable to map OCRAM ECC block\n");
  123. return;
  124. }
  125. /* Disable ECC */
  126. writel(ALTR_A10_OCRAM_ECC_EN_CTL,
  127. sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST);
  128. ecc_clear_bits(ALTR_A10_ECC_SERRINTEN,
  129. (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
  130. ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
  131. (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
  132. /* Ensure all writes complete */
  133. wmb();
  134. /* Use HW initialization block to initialize memory for ECC */
  135. ret = altr_init_memory_port(ecc_block_base);
  136. if (ret) {
  137. pr_err("ECC: cannot init OCRAM PORTA memory\n");
  138. goto exit;
  139. }
  140. /* Enable ECC */
  141. ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
  142. (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
  143. ecc_set_bits(ALTR_A10_ECC_SERRINTEN,
  144. (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
  145. writel(ALTR_A10_OCRAM_ECC_EN_CTL,
  146. sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST);
  147. /* Ensure all writes complete */
  148. wmb();
  149. exit:
  150. iounmap(ecc_block_base);
  151. }