emc.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright (c) 2011 The Chromium OS Authors.
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <common.h>
  23. #include <fdtdec.h>
  24. #include <asm/io.h>
  25. #include <asm/arch-tegra/ap.h>
  26. #include <asm/arch/apb_misc.h>
  27. #include <asm/arch/clock.h>
  28. #include <asm/arch/emc.h>
  29. #include <asm/arch/tegra.h>
  30. /*
  31. * The EMC registers have shadow registers. When the EMC clock is updated
  32. * in the clock controller, the shadow registers are copied to the active
  33. * registers, allowing glitchless memory bus frequency changes.
  34. * This function updates the shadow registers for a new clock frequency,
  35. * and relies on the clock lock on the emc clock to avoid races between
  36. * multiple frequency changes
  37. */
  38. /*
  39. * This table defines the ordering of the registers provided to
  40. * tegra_set_mmc()
  41. * TODO: Convert to fdt version once available
  42. */
  43. static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
  44. 0x2c, /* RC */
  45. 0x30, /* RFC */
  46. 0x34, /* RAS */
  47. 0x38, /* RP */
  48. 0x3c, /* R2W */
  49. 0x40, /* W2R */
  50. 0x44, /* R2P */
  51. 0x48, /* W2P */
  52. 0x4c, /* RD_RCD */
  53. 0x50, /* WR_RCD */
  54. 0x54, /* RRD */
  55. 0x58, /* REXT */
  56. 0x5c, /* WDV */
  57. 0x60, /* QUSE */
  58. 0x64, /* QRST */
  59. 0x68, /* QSAFE */
  60. 0x6c, /* RDV */
  61. 0x70, /* REFRESH */
  62. 0x74, /* BURST_REFRESH_NUM */
  63. 0x78, /* PDEX2WR */
  64. 0x7c, /* PDEX2RD */
  65. 0x80, /* PCHG2PDEN */
  66. 0x84, /* ACT2PDEN */
  67. 0x88, /* AR2PDEN */
  68. 0x8c, /* RW2PDEN */
  69. 0x90, /* TXSR */
  70. 0x94, /* TCKE */
  71. 0x98, /* TFAW */
  72. 0x9c, /* TRPAB */
  73. 0xa0, /* TCLKSTABLE */
  74. 0xa4, /* TCLKSTOP */
  75. 0xa8, /* TREFBW */
  76. 0xac, /* QUSE_EXTRA */
  77. 0x114, /* FBIO_CFG6 */
  78. 0xb0, /* ODT_WRITE */
  79. 0xb4, /* ODT_READ */
  80. 0x104, /* FBIO_CFG5 */
  81. 0x2bc, /* CFG_DIG_DLL */
  82. 0x2c0, /* DLL_XFORM_DQS */
  83. 0x2c4, /* DLL_XFORM_QUSE */
  84. 0x2e0, /* ZCAL_REF_CNT */
  85. 0x2e4, /* ZCAL_WAIT_CNT */
  86. 0x2a8, /* AUTO_CAL_INTERVAL */
  87. 0x2d0, /* CFG_CLKTRIM_0 */
  88. 0x2d4, /* CFG_CLKTRIM_1 */
  89. 0x2d8, /* CFG_CLKTRIM_2 */
  90. };
  91. struct emc_ctlr *emc_get_controller(const void *blob)
  92. {
  93. fdt_addr_t addr;
  94. int node;
  95. node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
  96. if (node > 0) {
  97. addr = fdtdec_get_addr(blob, node, "reg");
  98. if (addr != FDT_ADDR_T_NONE)
  99. return (struct emc_ctlr *)addr;
  100. }
  101. return NULL;
  102. }
  103. /* Error codes we use */
  104. enum {
  105. ERR_NO_EMC_NODE = -10,
  106. ERR_NO_EMC_REG,
  107. ERR_NO_FREQ,
  108. ERR_FREQ_NOT_FOUND,
  109. ERR_BAD_REGS,
  110. ERR_NO_RAM_CODE,
  111. ERR_RAM_CODE_NOT_FOUND,
  112. };
  113. /**
  114. * Find EMC tables for the given ram code.
  115. *
  116. * The tegra EMC binding has two options, one using the ram code and one not.
  117. * We detect which is in use by looking for the nvidia,use-ram-code property.
  118. * If this is not present, then the EMC tables are directly below 'node',
  119. * otherwise we select the correct emc-tables subnode based on the 'ram_code'
  120. * value.
  121. *
  122. * @param blob Device tree blob
  123. * @param node EMC node (nvidia,tegra20-emc compatible string)
  124. * @param ram_code RAM code to select (0-3, or -1 if unknown)
  125. * @return 0 if ok, otherwise a -ve ERR_ code (see enum above)
  126. */
  127. static int find_emc_tables(const void *blob, int node, int ram_code)
  128. {
  129. int need_ram_code;
  130. int depth;
  131. int offset;
  132. /* If we are using RAM codes, scan through the tables for our code */
  133. need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code");
  134. if (!need_ram_code)
  135. return node;
  136. if (ram_code == -1) {
  137. debug("%s: RAM code required but not supplied\n", __func__);
  138. return ERR_NO_RAM_CODE;
  139. }
  140. offset = node;
  141. depth = 0;
  142. do {
  143. /*
  144. * Sadly there is no compatible string so we cannot use
  145. * fdtdec_next_compatible_subnode().
  146. */
  147. offset = fdt_next_node(blob, offset, &depth);
  148. if (depth <= 0)
  149. break;
  150. /* Make sure this is a direct subnode */
  151. if (depth != 1)
  152. continue;
  153. if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL)))
  154. continue;
  155. if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1)
  156. == ram_code)
  157. return offset;
  158. } while (1);
  159. debug("%s: Could not find tables for RAM code %d\n", __func__,
  160. ram_code);
  161. return ERR_RAM_CODE_NOT_FOUND;
  162. }
  163. /**
  164. * Decode the EMC node of the device tree, returning a pointer to the emc
  165. * controller and the table to be used for the given rate.
  166. *
  167. * @param blob Device tree blob
  168. * @param rate Clock speed of memory controller in Hz (=2x memory bus rate)
  169. * @param emcp Returns address of EMC controller registers
  170. * @param tablep Returns pointer to table to program into EMC. There are
  171. * TEGRA_EMC_NUM_REGS entries, destined for offsets as per the
  172. * emc_reg_addr array.
  173. * @return 0 if ok, otherwise a -ve error code which will allow someone to
  174. * figure out roughly what went wrong by looking at this code.
  175. */
  176. static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp,
  177. const u32 **tablep)
  178. {
  179. struct apb_misc_pp_ctlr *pp =
  180. (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE;
  181. int ram_code;
  182. int depth;
  183. int node;
  184. ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK)
  185. >> RAM_CODE_SHIFT;
  186. /*
  187. * The EMC clock rate is twice the bus rate, and the bus rate is
  188. * measured in kHz
  189. */
  190. rate = rate / 2 / 1000;
  191. node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
  192. if (node < 0) {
  193. debug("%s: No EMC node found in FDT\n", __func__);
  194. return ERR_NO_EMC_NODE;
  195. }
  196. *emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg");
  197. if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) {
  198. debug("%s: No EMC node reg property\n", __func__);
  199. return ERR_NO_EMC_REG;
  200. }
  201. /* Work out the parent node which contains our EMC tables */
  202. node = find_emc_tables(blob, node, ram_code & 3);
  203. if (node < 0)
  204. return node;
  205. depth = 0;
  206. for (;;) {
  207. int node_rate;
  208. node = fdtdec_next_compatible_subnode(blob, node,
  209. COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth);
  210. if (node < 0)
  211. break;
  212. node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1);
  213. if (node_rate == -1) {
  214. debug("%s: Missing clock-frequency\n", __func__);
  215. return ERR_NO_FREQ; /* we expect this property */
  216. }
  217. if (node_rate == rate)
  218. break;
  219. }
  220. if (node < 0) {
  221. debug("%s: No node found for clock frequency %d\n", __func__,
  222. rate);
  223. return ERR_FREQ_NOT_FOUND;
  224. }
  225. *tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers",
  226. TEGRA_EMC_NUM_REGS);
  227. if (!*tablep) {
  228. debug("%s: node '%s' array missing / wrong size\n", __func__,
  229. fdt_get_name(blob, node, NULL));
  230. return ERR_BAD_REGS;
  231. }
  232. /* All seems well */
  233. return 0;
  234. }
  235. int tegra_set_emc(const void *blob, unsigned rate)
  236. {
  237. struct emc_ctlr *emc;
  238. const u32 *table = NULL;
  239. int err, i;
  240. err = decode_emc(blob, rate, &emc, &table);
  241. if (err) {
  242. debug("Warning: no valid EMC (%d), memory timings unset\n",
  243. err);
  244. return err;
  245. }
  246. debug("%s: Table found, setting EMC values as follows:\n", __func__);
  247. for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) {
  248. u32 value = fdt32_to_cpu(table[i]);
  249. u32 addr = (uintptr_t)emc + emc_reg_addr[i];
  250. debug(" %#x: %#x\n", addr, value);
  251. writel(value, addr);
  252. }
  253. /* trigger emc with new settings */
  254. clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY,
  255. clock_get_rate(CLOCK_ID_MEMORY), NULL);
  256. debug("EMC clock set to %lu\n",
  257. clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY));
  258. return 0;
  259. }