ti-emif-pm.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * TI AM33XX SRAM EMIF Driver
  3. *
  4. * Copyright (C) 2016-2017 Texas Instruments Inc.
  5. * Dave Gerlach
  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
  9. * version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/err.h>
  17. #include <linux/genalloc.h>
  18. #include <linux/io.h>
  19. #include <linux/kernel.h>
  20. #include <linux/module.h>
  21. #include <linux/of.h>
  22. #include <linux/of_platform.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/sram.h>
  25. #include <linux/ti-emif-sram.h>
  26. #include "emif.h"
  27. #define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \
  28. (unsigned long)&ti_emif_sram)
  29. #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0
  30. struct ti_emif_data {
  31. phys_addr_t ti_emif_sram_phys;
  32. phys_addr_t ti_emif_sram_data_phys;
  33. unsigned long ti_emif_sram_virt;
  34. unsigned long ti_emif_sram_data_virt;
  35. struct gen_pool *sram_pool_code;
  36. struct gen_pool *sram_pool_data;
  37. struct ti_emif_pm_data pm_data;
  38. struct ti_emif_pm_functions pm_functions;
  39. };
  40. static struct ti_emif_data *emif_instance;
  41. static u32 sram_suspend_address(struct ti_emif_data *emif_data,
  42. unsigned long addr)
  43. {
  44. return (emif_data->ti_emif_sram_virt +
  45. TI_EMIF_SRAM_SYMBOL_OFFSET(addr));
  46. }
  47. static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data,
  48. unsigned long addr)
  49. {
  50. return ((unsigned long)emif_data->ti_emif_sram_phys +
  51. TI_EMIF_SRAM_SYMBOL_OFFSET(addr));
  52. }
  53. static void ti_emif_free_sram(struct ti_emif_data *emif_data)
  54. {
  55. gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt,
  56. ti_emif_sram_sz);
  57. gen_pool_free(emif_data->sram_pool_data,
  58. emif_data->ti_emif_sram_data_virt,
  59. sizeof(struct emif_regs_amx3));
  60. }
  61. static int ti_emif_alloc_sram(struct device *dev,
  62. struct ti_emif_data *emif_data)
  63. {
  64. struct device_node *np = dev->of_node;
  65. int ret;
  66. emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0);
  67. if (!emif_data->sram_pool_code) {
  68. dev_err(dev, "Unable to get sram pool for ocmcram code\n");
  69. return -ENODEV;
  70. }
  71. emif_data->ti_emif_sram_virt =
  72. gen_pool_alloc(emif_data->sram_pool_code,
  73. ti_emif_sram_sz);
  74. if (!emif_data->ti_emif_sram_virt) {
  75. dev_err(dev, "Unable to allocate code memory from ocmcram\n");
  76. return -ENOMEM;
  77. }
  78. /* Save physical address to calculate resume offset during pm init */
  79. emif_data->ti_emif_sram_phys =
  80. gen_pool_virt_to_phys(emif_data->sram_pool_code,
  81. emif_data->ti_emif_sram_virt);
  82. /* Get sram pool for data section and allocate space */
  83. emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1);
  84. if (!emif_data->sram_pool_data) {
  85. dev_err(dev, "Unable to get sram pool for ocmcram data\n");
  86. ret = -ENODEV;
  87. goto err_free_sram_code;
  88. }
  89. emif_data->ti_emif_sram_data_virt =
  90. gen_pool_alloc(emif_data->sram_pool_data,
  91. sizeof(struct emif_regs_amx3));
  92. if (!emif_data->ti_emif_sram_data_virt) {
  93. dev_err(dev, "Unable to allocate data memory from ocmcram\n");
  94. ret = -ENOMEM;
  95. goto err_free_sram_code;
  96. }
  97. /* Save physical address to calculate resume offset during pm init */
  98. emif_data->ti_emif_sram_data_phys =
  99. gen_pool_virt_to_phys(emif_data->sram_pool_data,
  100. emif_data->ti_emif_sram_data_virt);
  101. /*
  102. * These functions are called during suspend path while MMU is
  103. * still on so add virtual base to offset for absolute address
  104. */
  105. emif_data->pm_functions.save_context =
  106. sram_suspend_address(emif_data,
  107. (unsigned long)ti_emif_save_context);
  108. emif_data->pm_functions.enter_sr =
  109. sram_suspend_address(emif_data,
  110. (unsigned long)ti_emif_enter_sr);
  111. emif_data->pm_functions.abort_sr =
  112. sram_suspend_address(emif_data,
  113. (unsigned long)ti_emif_abort_sr);
  114. /*
  115. * These are called during resume path when MMU is not enabled
  116. * so physical address is used instead
  117. */
  118. emif_data->pm_functions.restore_context =
  119. sram_resume_address(emif_data,
  120. (unsigned long)ti_emif_restore_context);
  121. emif_data->pm_functions.exit_sr =
  122. sram_resume_address(emif_data,
  123. (unsigned long)ti_emif_exit_sr);
  124. emif_data->pm_functions.run_hw_leveling =
  125. sram_resume_address(emif_data,
  126. (unsigned long)ti_emif_run_hw_leveling);
  127. emif_data->pm_data.regs_virt =
  128. (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt;
  129. emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys;
  130. return 0;
  131. err_free_sram_code:
  132. gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt,
  133. ti_emif_sram_sz);
  134. return ret;
  135. }
  136. static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data)
  137. {
  138. void *copy_addr;
  139. u32 data_addr;
  140. copy_addr = sram_exec_copy(emif_data->sram_pool_code,
  141. (void *)emif_data->ti_emif_sram_virt,
  142. &ti_emif_sram, ti_emif_sram_sz);
  143. if (!copy_addr) {
  144. dev_err(dev, "Cannot copy emif code to sram\n");
  145. return -ENODEV;
  146. }
  147. data_addr = sram_suspend_address(emif_data,
  148. (unsigned long)&ti_emif_pm_sram_data);
  149. copy_addr = sram_exec_copy(emif_data->sram_pool_code,
  150. (void *)data_addr,
  151. &emif_data->pm_data,
  152. sizeof(emif_data->pm_data));
  153. if (!copy_addr) {
  154. dev_err(dev, "Cannot copy emif data to code sram\n");
  155. return -ENODEV;
  156. }
  157. return 0;
  158. }
  159. /*
  160. * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum
  161. * Self-Refresh Command Limit" found in AM335x Silicon Errata
  162. * (Document SPRZ360F Revised November 2013) we must configure
  163. * the self refresh delay timer to 0xA (8192 cycles) to avoid
  164. * generating too many refresh command from the EMIF.
  165. */
  166. static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data)
  167. {
  168. writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES,
  169. (emif_data->pm_data.ti_emif_base_addr_virt +
  170. EMIF_POWER_MANAGEMENT_CONTROL));
  171. writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES,
  172. (emif_data->pm_data.ti_emif_base_addr_virt +
  173. EMIF_POWER_MANAGEMENT_CTRL_SHDW));
  174. }
  175. /**
  176. * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram
  177. * @sram_pool: pointer to struct gen_pool where dst resides
  178. * @dst: void * to address that table should be copied
  179. *
  180. * Returns 0 if success other error code if table is not available
  181. */
  182. int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst)
  183. {
  184. void *copy_addr;
  185. if (!emif_instance)
  186. return -ENODEV;
  187. copy_addr = sram_exec_copy(sram_pool, dst,
  188. &emif_instance->pm_functions,
  189. sizeof(emif_instance->pm_functions));
  190. if (!copy_addr)
  191. return -ENODEV;
  192. return 0;
  193. }
  194. EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table);
  195. /**
  196. * ti_emif_get_mem_type - return type for memory type in use
  197. *
  198. * Returns memory type value read from EMIF or error code if fails
  199. */
  200. int ti_emif_get_mem_type(void)
  201. {
  202. unsigned long temp;
  203. if (!emif_instance)
  204. return -ENODEV;
  205. temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt +
  206. EMIF_SDRAM_CONFIG);
  207. temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
  208. return temp;
  209. }
  210. EXPORT_SYMBOL_GPL(ti_emif_get_mem_type);
  211. static const struct of_device_id ti_emif_of_match[] = {
  212. { .compatible = "ti,emif-am3352", .data =
  213. (void *)EMIF_SRAM_AM33_REG_LAYOUT, },
  214. { .compatible = "ti,emif-am4372", .data =
  215. (void *)EMIF_SRAM_AM43_REG_LAYOUT, },
  216. {},
  217. };
  218. MODULE_DEVICE_TABLE(of, ti_emif_of_match);
  219. #ifdef CONFIG_PM_SLEEP
  220. static int ti_emif_resume(struct device *dev)
  221. {
  222. unsigned long tmp =
  223. __raw_readl((void *)emif_instance->ti_emif_sram_virt);
  224. /*
  225. * Check to see if what we are copying is already present in the
  226. * first byte at the destination, only copy if it is not which
  227. * indicates we have lost context and sram no longer contains
  228. * the PM code
  229. */
  230. if (tmp != ti_emif_sram)
  231. ti_emif_push_sram(dev, emif_instance);
  232. return 0;
  233. }
  234. static int ti_emif_suspend(struct device *dev)
  235. {
  236. /*
  237. * The contents will be present in DDR hence no need to
  238. * explicitly save
  239. */
  240. return 0;
  241. }
  242. #endif /* CONFIG_PM_SLEEP */
  243. static int ti_emif_probe(struct platform_device *pdev)
  244. {
  245. int ret;
  246. struct resource *res;
  247. struct device *dev = &pdev->dev;
  248. const struct of_device_id *match;
  249. struct ti_emif_data *emif_data;
  250. emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL);
  251. if (!emif_data)
  252. return -ENOMEM;
  253. match = of_match_device(ti_emif_of_match, &pdev->dev);
  254. if (!match)
  255. return -ENODEV;
  256. emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data;
  257. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  258. emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev,
  259. res);
  260. if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) {
  261. ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt);
  262. return ret;
  263. }
  264. emif_data->pm_data.ti_emif_base_addr_phys = res->start;
  265. ti_emif_configure_sr_delay(emif_data);
  266. ret = ti_emif_alloc_sram(dev, emif_data);
  267. if (ret)
  268. return ret;
  269. ret = ti_emif_push_sram(dev, emif_data);
  270. if (ret)
  271. goto fail_free_sram;
  272. emif_instance = emif_data;
  273. return 0;
  274. fail_free_sram:
  275. ti_emif_free_sram(emif_data);
  276. return ret;
  277. }
  278. static int ti_emif_remove(struct platform_device *pdev)
  279. {
  280. struct ti_emif_data *emif_data = emif_instance;
  281. emif_instance = NULL;
  282. ti_emif_free_sram(emif_data);
  283. return 0;
  284. }
  285. static const struct dev_pm_ops ti_emif_pm_ops = {
  286. SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
  287. };
  288. static struct platform_driver ti_emif_driver = {
  289. .probe = ti_emif_probe,
  290. .remove = ti_emif_remove,
  291. .driver = {
  292. .name = KBUILD_MODNAME,
  293. .of_match_table = of_match_ptr(ti_emif_of_match),
  294. .pm = &ti_emif_pm_ops,
  295. },
  296. };
  297. module_platform_driver(ti_emif_driver);
  298. MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
  299. MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver");
  300. MODULE_LICENSE("GPL v2");