201-mips-bmips-automatically-detect-RAM-size.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. From f9ee3f28ecb979c77423be965ef9dd313bdb9e9b Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <[email protected]>
  3. Date: Mon, 8 Mar 2021 16:58:34 +0100
  4. Subject: [PATCH] mips: bmips: automatically detect RAM size
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. Some devices have different amounts of RAM installed depending on HW revision.
  9. Signed-off-by: Álvaro Fernández Rojas <[email protected]>
  10. ---
  11. arch/mips/bmips/setup.c | 119 ++++++++++++++++++++++++++++++++++++++++
  12. 1 file changed, 119 insertions(+)
  13. --- a/arch/mips/bmips/setup.c
  14. +++ b/arch/mips/bmips/setup.c
  15. @@ -18,6 +18,7 @@
  16. #include <linux/of_fdt.h>
  17. #include <linux/libfdt.h>
  18. #include <linux/smp.h>
  19. +#include <linux/types.h>
  20. #include <asm/addrspace.h>
  21. #include <asm/bmips.h>
  22. #include <asm/bootinfo.h>
  23. @@ -34,13 +35,16 @@
  24. #define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900))
  25. #define BCM6318_FREQ_SHIFT 23
  26. #define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT)
  27. +#define BCM6318_SDRAM_ADDR ((void __iomem *)CKSEG1ADDR(0x10004000))
  28. #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c))
  29. #define BCM6328_TP1_DISABLED BIT(9)
  30. #define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40))
  31. #define BCM6328_FCVO_SHIFT 7
  32. #define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT)
  33. +#define BCM6328_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000))
  34. +#define BCM6358_MEMC_ADDR ((void __iomem *)0xfffe1200)
  35. #define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8)
  36. #define BCM6358_PLLC_M1_SHIFT 0
  37. #define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT)
  38. @@ -52,7 +56,9 @@
  39. #define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814))
  40. #define BCM6362_FCVO_SHIFT 1
  41. #define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT)
  42. +#define BCM6362_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000))
  43. +#define BCM6368_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10001200))
  44. #define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0))
  45. #define BCM6368_PLLC_P1_SHIFT 0
  46. #define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT)
  47. @@ -67,6 +73,21 @@
  48. #define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814))
  49. #define BCM63268_FCVO_SHIFT 21
  50. #define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT)
  51. +#define BCM63268_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000))
  52. +
  53. +#define SDRAM_CFG_REG 0x0
  54. +#define SDRAM_SPACE_SHIFT 4
  55. +#define SDRAM_SPACE_MASK (0xf << SDRAM_SPACE_SHIFT)
  56. +
  57. +#define MEMC_CFG_REG 0x4
  58. +#define MEMC_CFG_32B_SHIFT 1
  59. +#define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT)
  60. +#define MEMC_CFG_COL_SHIFT 3
  61. +#define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT)
  62. +#define MEMC_CFG_ROW_SHIFT 6
  63. +#define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT)
  64. +
  65. +#define DDR_CSEND_REG 0x8
  66. /*
  67. * CBR addr doesn't change and we can cache it.
  68. @@ -84,6 +105,11 @@ struct bmips_cpufreq {
  69. u32 (*cpu_freq)(void);
  70. };
  71. +struct bmips_memsize {
  72. + const char *compatible;
  73. + phys_addr_t (*mem_size)(void);
  74. +};
  75. +
  76. struct bmips_quirk {
  77. const char *compatible;
  78. void (*quirk_fn)(void);
  79. @@ -361,9 +387,90 @@ void __init plat_time_init(void)
  80. mips_hpt_frequency = freq;
  81. }
  82. +static inline phys_addr_t bmips_dram_size(unsigned int cols,
  83. + unsigned int rows,
  84. + unsigned int is_32b,
  85. + unsigned int banks)
  86. +{
  87. + rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
  88. + cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
  89. + is_32b += 1;
  90. +
  91. + return 1 << (cols + rows + is_32b + banks);
  92. +}
  93. +
  94. +static phys_addr_t _bcm6318_memsize(void __iomem *addr)
  95. +{
  96. + u32 val;
  97. +
  98. + val = __raw_readl(addr + SDRAM_CFG_REG);
  99. + val = (val & SDRAM_SPACE_MASK) >> SDRAM_SPACE_SHIFT;
  100. +
  101. + return (1 << (val + 20));
  102. +}
  103. +
  104. +static phys_addr_t _bcm6328_memsize(void __iomem *addr)
  105. +{
  106. + return __raw_readl(addr + DDR_CSEND_REG) << 24;
  107. +}
  108. +
  109. +static phys_addr_t _bcm6358_memsize(void __iomem *addr)
  110. +{
  111. + unsigned int cols, rows, is_32b;
  112. + u32 val;
  113. +
  114. + val = __raw_readl(addr + MEMC_CFG_REG);
  115. + rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
  116. + cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
  117. + is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
  118. +
  119. + return bmips_dram_size(cols, rows, is_32b, 2);
  120. +}
  121. +
  122. +static phys_addr_t bcm6318_memsize(void)
  123. +{
  124. + return _bcm6318_memsize(BCM6318_SDRAM_ADDR);
  125. +}
  126. +
  127. +static phys_addr_t bcm6328_memsize(void)
  128. +{
  129. + return _bcm6328_memsize(BCM6328_MEMC_ADDR);
  130. +}
  131. +
  132. +static phys_addr_t bcm6358_memsize(void)
  133. +{
  134. + return _bcm6358_memsize(BCM6358_MEMC_ADDR);
  135. +}
  136. +
  137. +static phys_addr_t bcm6362_memsize(void)
  138. +{
  139. + return _bcm6328_memsize(BCM6362_MEMC_ADDR);
  140. +}
  141. +
  142. +static phys_addr_t bcm6368_memsize(void)
  143. +{
  144. + return _bcm6358_memsize(BCM6368_MEMC_ADDR);
  145. +}
  146. +
  147. +static phys_addr_t bcm63268_memsize(void)
  148. +{
  149. + return _bcm6328_memsize(BCM63268_MEMC_ADDR);
  150. +}
  151. +
  152. +static const struct bmips_memsize bmips_memsize_list[] = {
  153. + { "brcm,bcm6318", &bcm6318_memsize },
  154. + { "brcm,bcm6328", &bcm6328_memsize },
  155. + { "brcm,bcm6358", &bcm6358_memsize },
  156. + { "brcm,bcm6362", &bcm6362_memsize },
  157. + { "brcm,bcm6368", &bcm6368_memsize },
  158. + { "brcm,bcm63268", &bcm63268_memsize },
  159. + { /* sentinel */ }
  160. +};
  161. +
  162. void __init plat_mem_setup(void)
  163. {
  164. void *dtb;
  165. + const struct bmips_memsize *ms;
  166. const struct bmips_quirk *q;
  167. set_io_port_base(0);
  168. @@ -384,6 +491,18 @@ void __init plat_mem_setup(void)
  169. __dt_setup_arch(dtb);
  170. + for (ms = bmips_memsize_list; ms->mem_size; ms++) {
  171. + if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
  172. + ms->compatible)) {
  173. + phys_addr_t mem = ms->mem_size();
  174. + if (mem) {
  175. + memblock_add(0, mem);
  176. + printk("%uMB of RAM installed\n", mem >> 20);
  177. + break;
  178. + }
  179. + }
  180. + }
  181. +
  182. for (q = bmips_quirk_list; q->quirk_fn; q++) {
  183. if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
  184. q->compatible)) {