qcom_pil_info.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2019-2020 Linaro Ltd.
  4. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/mutex.h>
  9. #include <linux/of_address.h>
  10. #include "qcom_pil_info.h"
  11. #include <linux/syscore_ops.h>
  12. /*
  13. * The PIL relocation information region is used to communicate memory regions
  14. * occupied by co-processor firmware for post mortem crash analysis.
  15. *
  16. * It consists of an array of entries with an 8 byte textual identifier of the
  17. * region followed by a 64 bit base address and 32 bit size, both little
  18. * endian.
  19. */
  20. #define PIL_RELOC_NAME_LEN 8
  21. #define PIL_RELOC_ENTRY_SIZE (PIL_RELOC_NAME_LEN + sizeof(__le64) + sizeof(__le32))
  22. struct pil_reloc {
  23. void __iomem *base;
  24. size_t num_entries;
  25. };
  26. static struct pil_reloc _reloc __read_mostly;
  27. static DEFINE_MUTEX(pil_reloc_lock);
  28. static bool timeouts_disabled;
  29. #ifdef CONFIG_HIBERNATION
  30. static bool hibernation;
  31. #endif
  32. /**
  33. * qcom_pil_timeouts_disabled() - Check if pil timeouts are disabled in imem
  34. *
  35. * Return: true if the value 0x53444247 is set in the disable timeout pil
  36. * imem region, false otherwise.
  37. */
  38. bool qcom_pil_timeouts_disabled(void)
  39. {
  40. struct device_node *np;
  41. struct resource imem;
  42. void __iomem *base;
  43. int ret;
  44. const char *prop = "qcom,msm-imem-pil-disable-timeout";
  45. np = of_find_compatible_node(NULL, NULL, prop);
  46. if (!np) {
  47. pr_err("%s entry missing!\n", prop);
  48. goto out;
  49. }
  50. ret = of_address_to_resource(np, 0, &imem);
  51. of_node_put(np);
  52. if (ret < 0) {
  53. pr_err("address to resource conversion failed for %s\n", prop);
  54. goto out;
  55. }
  56. base = ioremap(imem.start, resource_size(&imem));
  57. if (!base) {
  58. pr_err("failed to map PIL disable timeouts region\n");
  59. goto out;
  60. }
  61. if (__raw_readl(base) == 0x53444247) {
  62. pr_info("pil-imem set to disable pil timeouts\n");
  63. timeouts_disabled = true;
  64. } else
  65. timeouts_disabled = false;
  66. iounmap(base);
  67. out:
  68. return timeouts_disabled;
  69. }
  70. EXPORT_SYMBOL(qcom_pil_timeouts_disabled);
  71. #ifdef CONFIG_HIBERNATION
  72. static void pil_reloc_restore_syscore_resume(void)
  73. {
  74. if (_reloc.base) {
  75. mutex_lock(&pil_reloc_lock);
  76. iounmap(_reloc.base);
  77. _reloc.base = NULL;
  78. mutex_unlock(&pil_reloc_lock);
  79. } else
  80. pr_info("The PIL relocation information region is not mapped\n");
  81. }
  82. static struct syscore_ops pil_reloc_restore_syscore_ops = {
  83. .resume = pil_reloc_restore_syscore_resume,
  84. };
  85. #endif
  86. static int qcom_pil_info_init(void)
  87. {
  88. struct device_node *np;
  89. struct resource imem;
  90. void __iomem *base;
  91. int ret;
  92. #ifdef CONFIG_HIBERNATION
  93. if (!hibernation) {
  94. register_syscore_ops(&pil_reloc_restore_syscore_ops);
  95. hibernation = true;
  96. }
  97. #endif
  98. /* Already initialized? */
  99. if (_reloc.base)
  100. return 0;
  101. np = of_find_compatible_node(NULL, NULL, "qcom,pil-reloc-info");
  102. if (!np)
  103. return -ENOENT;
  104. ret = of_address_to_resource(np, 0, &imem);
  105. of_node_put(np);
  106. if (ret < 0)
  107. return ret;
  108. base = ioremap(imem.start, resource_size(&imem));
  109. if (!base) {
  110. pr_err("failed to map PIL relocation info region\n");
  111. return -ENOMEM;
  112. }
  113. memset_io(base, 0, resource_size(&imem));
  114. _reloc.base = base;
  115. _reloc.num_entries = (u32)resource_size(&imem) / PIL_RELOC_ENTRY_SIZE;
  116. return 0;
  117. }
  118. /**
  119. * qcom_pil_info_store() - store PIL information of image in IMEM
  120. * @image: name of the image
  121. * @base: base address of the loaded image
  122. * @size: size of the loaded image
  123. *
  124. * Return: 0 on success, negative errno on failure
  125. */
  126. int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size)
  127. {
  128. char buf[PIL_RELOC_NAME_LEN];
  129. void __iomem *entry;
  130. size_t entry_size;
  131. int ret;
  132. int i;
  133. mutex_lock(&pil_reloc_lock);
  134. ret = qcom_pil_info_init();
  135. if (ret < 0) {
  136. mutex_unlock(&pil_reloc_lock);
  137. return ret;
  138. }
  139. for (i = 0; i < _reloc.num_entries; i++) {
  140. entry = _reloc.base + i * PIL_RELOC_ENTRY_SIZE;
  141. memcpy_fromio(buf, entry, PIL_RELOC_NAME_LEN);
  142. /*
  143. * An empty record means we didn't find it, given that the
  144. * records are packed.
  145. */
  146. if (!buf[0])
  147. goto found_unused;
  148. if (!strncmp(buf, image, PIL_RELOC_NAME_LEN))
  149. goto found_existing;
  150. }
  151. pr_warn("insufficient PIL info slots\n");
  152. mutex_unlock(&pil_reloc_lock);
  153. return -ENOMEM;
  154. found_unused:
  155. entry_size = min(strlen(image), PIL_RELOC_ENTRY_SIZE - 1);
  156. memcpy_toio(entry, image, entry_size);
  157. found_existing:
  158. /* Use two writel() as base is only aligned to 4 bytes on odd entries */
  159. writel(base, entry + PIL_RELOC_NAME_LEN);
  160. writel((u64)base >> 32, entry + PIL_RELOC_NAME_LEN + 4);
  161. writel(size, entry + PIL_RELOC_NAME_LEN + sizeof(__le64));
  162. mutex_unlock(&pil_reloc_lock);
  163. return 0;
  164. }
  165. EXPORT_SYMBOL_GPL(qcom_pil_info_store);
  166. static void __exit pil_reloc_exit(void)
  167. {
  168. mutex_lock(&pil_reloc_lock);
  169. iounmap(_reloc.base);
  170. _reloc.base = NULL;
  171. mutex_unlock(&pil_reloc_lock);
  172. }
  173. module_exit(pil_reloc_exit);
  174. MODULE_DESCRIPTION("Qualcomm PIL relocation info");
  175. MODULE_LICENSE("GPL v2");