ipa_smp2p.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  3. * Copyright (C) 2019-2024 Linaro Ltd.
  4. */
  5. #include <linux/interrupt.h>
  6. #include <linux/notifier.h>
  7. #include <linux/panic_notifier.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/pm_runtime.h>
  10. #include <linux/types.h>
  11. #include <linux/soc/qcom/smem_state.h>
  12. #include "ipa.h"
  13. #include "ipa_smp2p.h"
  14. #include "ipa_uc.h"
  15. /**
  16. * DOC: IPA SMP2P communication with the modem
  17. *
  18. * SMP2P is a primitive communication mechanism available between the AP and
  19. * the modem. The IPA driver uses this for two purposes: to enable the modem
  20. * to state that the GSI hardware is ready to use; and to communicate the
  21. * state of IPA power in the event of a crash.
  22. *
  23. * GSI needs to have early initialization completed before it can be used.
  24. * This initialization is done either by Trust Zone or by the modem. In the
  25. * latter case, the modem uses an SMP2P interrupt to tell the AP IPA driver
  26. * when the GSI is ready to use.
  27. *
  28. * The modem is also able to inquire about the current state of IPA
  29. * power by trigging another SMP2P interrupt to the AP. We communicate
  30. * whether power is enabled using two SMP2P state bits--one to indicate
  31. * the power state (on or off), and a second to indicate the power state
  32. * bit is valid. The modem will poll the valid bit until it is set, and
  33. * at that time records whether the AP has IPA power enabled.
  34. *
  35. * Finally, if the AP kernel panics, we update the SMP2P state bits even if
  36. * we never receive an interrupt from the modem requesting this.
  37. */
  38. /**
  39. * struct ipa_smp2p - IPA SMP2P information
  40. * @ipa: IPA pointer
  41. * @valid_state: SMEM state indicating enabled state is valid
  42. * @enabled_state: SMEM state to indicate power is enabled
  43. * @valid_bit: Valid bit in 32-bit SMEM state mask
  44. * @enabled_bit: Enabled bit in 32-bit SMEM state mask
  45. * @enabled_bit: Enabled bit in 32-bit SMEM state mask
  46. * @clock_query_irq: IPA interrupt triggered by modem for power query
  47. * @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready
  48. * @power_on: Whether IPA power is on
  49. * @notified: Whether modem has been notified of power state
  50. * @setup_disabled: Whether setup ready interrupt handler is disabled
  51. * @mutex: Mutex protecting ready-interrupt/shutdown interlock
  52. * @panic_notifier: Panic notifier structure
  53. */
  54. struct ipa_smp2p {
  55. struct ipa *ipa;
  56. struct qcom_smem_state *valid_state;
  57. struct qcom_smem_state *enabled_state;
  58. u32 valid_bit;
  59. u32 enabled_bit;
  60. u32 clock_query_irq;
  61. u32 setup_ready_irq;
  62. bool power_on;
  63. bool notified;
  64. bool setup_disabled;
  65. struct mutex mutex;
  66. struct notifier_block panic_notifier;
  67. };
  68. /**
  69. * ipa_smp2p_notify() - use SMP2P to tell modem about IPA power state
  70. * @smp2p: SMP2P information
  71. *
  72. * This is called either when the modem has requested it (by triggering
  73. * the modem power query IPA interrupt) or whenever the AP is shutting down
  74. * (via a panic notifier). It sets the two SMP2P state bits--one saying
  75. * whether the IPA power is on, and the other indicating the first bit
  76. * is valid.
  77. */
  78. static void ipa_smp2p_notify(struct ipa_smp2p *smp2p)
  79. {
  80. u32 value;
  81. u32 mask;
  82. if (smp2p->notified)
  83. return;
  84. smp2p->power_on = pm_runtime_get_if_active(smp2p->ipa->dev) > 0;
  85. /* Signal whether the IPA power is enabled */
  86. mask = BIT(smp2p->enabled_bit);
  87. value = smp2p->power_on ? mask : 0;
  88. qcom_smem_state_update_bits(smp2p->enabled_state, mask, value);
  89. /* Now indicate that the enabled flag is valid */
  90. mask = BIT(smp2p->valid_bit);
  91. value = mask;
  92. qcom_smem_state_update_bits(smp2p->valid_state, mask, value);
  93. smp2p->notified = true;
  94. }
  95. /* Threaded IRQ handler for modem "ipa-clock-query" SMP2P interrupt */
  96. static irqreturn_t ipa_smp2p_modem_clk_query_isr(int irq, void *dev_id)
  97. {
  98. struct ipa_smp2p *smp2p = dev_id;
  99. ipa_smp2p_notify(smp2p);
  100. return IRQ_HANDLED;
  101. }
  102. static int ipa_smp2p_panic_notifier(struct notifier_block *nb,
  103. unsigned long action, void *data)
  104. {
  105. struct ipa_smp2p *smp2p;
  106. smp2p = container_of(nb, struct ipa_smp2p, panic_notifier);
  107. ipa_smp2p_notify(smp2p);
  108. if (smp2p->power_on)
  109. ipa_uc_panic_notifier(smp2p->ipa);
  110. return NOTIFY_DONE;
  111. }
  112. static int ipa_smp2p_panic_notifier_register(struct ipa_smp2p *smp2p)
  113. {
  114. /* IPA panic handler needs to run before modem shuts down */
  115. smp2p->panic_notifier.notifier_call = ipa_smp2p_panic_notifier;
  116. smp2p->panic_notifier.priority = INT_MAX; /* Do it early */
  117. return atomic_notifier_chain_register(&panic_notifier_list,
  118. &smp2p->panic_notifier);
  119. }
  120. static void ipa_smp2p_panic_notifier_unregister(struct ipa_smp2p *smp2p)
  121. {
  122. atomic_notifier_chain_unregister(&panic_notifier_list,
  123. &smp2p->panic_notifier);
  124. }
  125. /* Threaded IRQ handler for modem "ipa-setup-ready" SMP2P interrupt */
  126. static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id)
  127. {
  128. struct ipa_smp2p *smp2p = dev_id;
  129. struct ipa *ipa = smp2p->ipa;
  130. struct device *dev;
  131. int ret;
  132. /* Ignore any (spurious) interrupts received after the first */
  133. if (ipa->setup_complete)
  134. return IRQ_HANDLED;
  135. /* Power needs to be active for setup */
  136. dev = ipa->dev;
  137. ret = pm_runtime_get_sync(dev);
  138. if (ret < 0) {
  139. dev_err(dev, "error %d getting power for setup\n", ret);
  140. goto out_power_put;
  141. }
  142. /* An error here won't cause driver shutdown, so warn if one occurs */
  143. ret = ipa_setup(ipa);
  144. WARN(ret != 0, "error %d from ipa_setup()\n", ret);
  145. out_power_put:
  146. (void)pm_runtime_put_autosuspend(dev);
  147. return IRQ_HANDLED;
  148. }
  149. /* Initialize SMP2P interrupts */
  150. static int ipa_smp2p_irq_init(struct ipa_smp2p *smp2p,
  151. struct platform_device *pdev,
  152. const char *name, irq_handler_t handler)
  153. {
  154. struct device *dev = &pdev->dev;
  155. unsigned int irq;
  156. int ret;
  157. ret = platform_get_irq_byname(pdev, name);
  158. if (ret <= 0)
  159. return ret ? : -EINVAL;
  160. irq = ret;
  161. ret = request_threaded_irq(irq, NULL, handler, 0, name, smp2p);
  162. if (ret) {
  163. dev_err(dev, "error %d requesting \"%s\" IRQ\n", ret, name);
  164. return ret;
  165. }
  166. return irq;
  167. }
  168. static void ipa_smp2p_irq_exit(struct ipa_smp2p *smp2p, u32 irq)
  169. {
  170. free_irq(irq, smp2p);
  171. }
  172. /* Drop the power reference if it was taken in ipa_smp2p_notify() */
  173. static void ipa_smp2p_power_release(struct ipa *ipa)
  174. {
  175. struct device *dev = ipa->dev;
  176. if (!ipa->smp2p->power_on)
  177. return;
  178. (void)pm_runtime_put_autosuspend(dev);
  179. ipa->smp2p->power_on = false;
  180. }
  181. /* Initialize the IPA SMP2P subsystem */
  182. int
  183. ipa_smp2p_init(struct ipa *ipa, struct platform_device *pdev, bool modem_init)
  184. {
  185. struct qcom_smem_state *enabled_state;
  186. struct device *dev = &pdev->dev;
  187. struct qcom_smem_state *valid_state;
  188. struct ipa_smp2p *smp2p;
  189. u32 enabled_bit;
  190. u32 valid_bit;
  191. int ret;
  192. valid_state = qcom_smem_state_get(dev, "ipa-clock-enabled-valid",
  193. &valid_bit);
  194. if (IS_ERR(valid_state))
  195. return PTR_ERR(valid_state);
  196. if (valid_bit >= 32) /* BITS_PER_U32 */
  197. return -EINVAL;
  198. enabled_state = qcom_smem_state_get(dev, "ipa-clock-enabled",
  199. &enabled_bit);
  200. if (IS_ERR(enabled_state))
  201. return PTR_ERR(enabled_state);
  202. if (enabled_bit >= 32) /* BITS_PER_U32 */
  203. return -EINVAL;
  204. smp2p = kzalloc_obj(*smp2p);
  205. if (!smp2p)
  206. return -ENOMEM;
  207. smp2p->ipa = ipa;
  208. /* These fields are needed by the power query interrupt
  209. * handler, so initialize them now.
  210. */
  211. mutex_init(&smp2p->mutex);
  212. smp2p->valid_state = valid_state;
  213. smp2p->valid_bit = valid_bit;
  214. smp2p->enabled_state = enabled_state;
  215. smp2p->enabled_bit = enabled_bit;
  216. /* We have enough information saved to handle notifications */
  217. ipa->smp2p = smp2p;
  218. ret = ipa_smp2p_irq_init(smp2p, pdev, "ipa-clock-query",
  219. ipa_smp2p_modem_clk_query_isr);
  220. if (ret < 0)
  221. goto err_null_smp2p;
  222. smp2p->clock_query_irq = ret;
  223. ret = ipa_smp2p_panic_notifier_register(smp2p);
  224. if (ret)
  225. goto err_irq_exit;
  226. if (modem_init) {
  227. /* Result will be non-zero (negative for error) */
  228. ret = ipa_smp2p_irq_init(smp2p, pdev, "ipa-setup-ready",
  229. ipa_smp2p_modem_setup_ready_isr);
  230. if (ret < 0)
  231. goto err_notifier_unregister;
  232. smp2p->setup_ready_irq = ret;
  233. }
  234. return 0;
  235. err_notifier_unregister:
  236. ipa_smp2p_panic_notifier_unregister(smp2p);
  237. err_irq_exit:
  238. ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq);
  239. err_null_smp2p:
  240. ipa->smp2p = NULL;
  241. mutex_destroy(&smp2p->mutex);
  242. kfree(smp2p);
  243. return ret;
  244. }
  245. void ipa_smp2p_exit(struct ipa *ipa)
  246. {
  247. struct ipa_smp2p *smp2p = ipa->smp2p;
  248. if (smp2p->setup_ready_irq)
  249. ipa_smp2p_irq_exit(smp2p, smp2p->setup_ready_irq);
  250. ipa_smp2p_panic_notifier_unregister(smp2p);
  251. ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq);
  252. /* We won't get notified any more; drop power reference (if any) */
  253. ipa_smp2p_power_release(ipa);
  254. ipa->smp2p = NULL;
  255. mutex_destroy(&smp2p->mutex);
  256. kfree(smp2p);
  257. }
  258. void ipa_smp2p_irq_disable_setup(struct ipa *ipa)
  259. {
  260. struct ipa_smp2p *smp2p = ipa->smp2p;
  261. if (!smp2p->setup_ready_irq)
  262. return;
  263. mutex_lock(&smp2p->mutex);
  264. if (!smp2p->setup_disabled) {
  265. disable_irq(smp2p->setup_ready_irq);
  266. smp2p->setup_disabled = true;
  267. }
  268. mutex_unlock(&smp2p->mutex);
  269. }
  270. /* Reset state tracking whether we have notified the modem */
  271. void ipa_smp2p_notify_reset(struct ipa *ipa)
  272. {
  273. struct ipa_smp2p *smp2p = ipa->smp2p;
  274. u32 mask;
  275. if (!smp2p->notified)
  276. return;
  277. ipa_smp2p_power_release(ipa);
  278. /* Reset the power enabled valid flag */
  279. mask = BIT(smp2p->valid_bit);
  280. qcom_smem_state_update_bits(smp2p->valid_state, mask, 0);
  281. /* Mark the power disabled for good measure... */
  282. mask = BIT(smp2p->enabled_bit);
  283. qcom_smem_state_update_bits(smp2p->enabled_state, mask, 0);
  284. smp2p->notified = false;
  285. }