bpmp-tegra210.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018, NVIDIA CORPORATION.
  4. */
  5. #include <linux/interrupt.h>
  6. #include <linux/irq.h>
  7. #include <linux/io.h>
  8. #include <linux/of.h>
  9. #include <linux/platform_device.h>
  10. #include <soc/tegra/bpmp.h>
  11. #include "bpmp-private.h"
  12. #define TRIGGER_OFFSET 0x000
  13. #define RESULT_OFFSET(id) (0xc00 + id * 4)
  14. #define TRIGGER_ID_SHIFT 16
  15. #define TRIGGER_CMD_GET 4
  16. #define STA_OFFSET 0
  17. #define SET_OFFSET 4
  18. #define CLR_OFFSET 8
  19. #define CH_MASK(ch) (0x3 << ((ch) * 2))
  20. #define SL_SIGL(ch) (0x0 << ((ch) * 2))
  21. #define SL_QUED(ch) (0x1 << ((ch) * 2))
  22. #define MA_FREE(ch) (0x2 << ((ch) * 2))
  23. #define MA_ACKD(ch) (0x3 << ((ch) * 2))
  24. struct tegra210_bpmp {
  25. void __iomem *atomics;
  26. void __iomem *arb_sema;
  27. struct irq_data *tx_irq_data;
  28. };
  29. static u32 bpmp_channel_status(struct tegra_bpmp *bpmp, unsigned int index)
  30. {
  31. struct tegra210_bpmp *priv = bpmp->priv;
  32. return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(index);
  33. }
  34. static bool tegra210_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
  35. {
  36. unsigned int index = channel->index;
  37. return bpmp_channel_status(channel->bpmp, index) == MA_ACKD(index);
  38. }
  39. static bool tegra210_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
  40. {
  41. unsigned int index = channel->index;
  42. return bpmp_channel_status(channel->bpmp, index) == SL_SIGL(index);
  43. }
  44. static bool
  45. tegra210_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
  46. {
  47. unsigned int index = channel->index;
  48. return bpmp_channel_status(channel->bpmp, index) == MA_FREE(index);
  49. }
  50. static bool
  51. tegra210_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
  52. {
  53. unsigned int index = channel->index;
  54. return bpmp_channel_status(channel->bpmp, index) == SL_QUED(index);
  55. }
  56. static int tegra210_bpmp_post_request(struct tegra_bpmp_channel *channel)
  57. {
  58. struct tegra210_bpmp *priv = channel->bpmp->priv;
  59. __raw_writel(CH_MASK(channel->index), priv->arb_sema + CLR_OFFSET);
  60. return 0;
  61. }
  62. static int tegra210_bpmp_post_response(struct tegra_bpmp_channel *channel)
  63. {
  64. struct tegra210_bpmp *priv = channel->bpmp->priv;
  65. __raw_writel(MA_ACKD(channel->index), priv->arb_sema + SET_OFFSET);
  66. return 0;
  67. }
  68. static int tegra210_bpmp_ack_response(struct tegra_bpmp_channel *channel)
  69. {
  70. struct tegra210_bpmp *priv = channel->bpmp->priv;
  71. __raw_writel(MA_ACKD(channel->index) ^ MA_FREE(channel->index),
  72. priv->arb_sema + CLR_OFFSET);
  73. return 0;
  74. }
  75. static int tegra210_bpmp_ack_request(struct tegra_bpmp_channel *channel)
  76. {
  77. struct tegra210_bpmp *priv = channel->bpmp->priv;
  78. __raw_writel(SL_QUED(channel->index), priv->arb_sema + SET_OFFSET);
  79. return 0;
  80. }
  81. static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
  82. {
  83. struct tegra210_bpmp *priv = bpmp->priv;
  84. struct irq_data *irq_data = priv->tx_irq_data;
  85. /*
  86. * Tegra Legacy Interrupt Controller (LIC) is used to notify BPMP of
  87. * available messages
  88. */
  89. if (irq_data->chip->irq_retrigger)
  90. return irq_data->chip->irq_retrigger(irq_data);
  91. return -EINVAL;
  92. }
  93. static irqreturn_t rx_irq(int irq, void *data)
  94. {
  95. struct tegra_bpmp *bpmp = data;
  96. tegra_bpmp_handle_rx(bpmp);
  97. return IRQ_HANDLED;
  98. }
  99. static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
  100. struct tegra_bpmp *bpmp,
  101. unsigned int index)
  102. {
  103. struct tegra210_bpmp *priv = bpmp->priv;
  104. u32 address;
  105. void *p;
  106. /* Retrieve channel base address from BPMP */
  107. writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
  108. priv->atomics + TRIGGER_OFFSET);
  109. address = readl(priv->atomics + RESULT_OFFSET(index));
  110. p = devm_ioremap(bpmp->dev, address, 0x80);
  111. if (!p)
  112. return -ENOMEM;
  113. channel->ib = p;
  114. channel->ob = p;
  115. channel->index = index;
  116. init_completion(&channel->completion);
  117. channel->bpmp = bpmp;
  118. return 0;
  119. }
  120. static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
  121. {
  122. struct platform_device *pdev = to_platform_device(bpmp->dev);
  123. struct tegra210_bpmp *priv;
  124. unsigned int i;
  125. int err;
  126. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  127. if (!priv)
  128. return -ENOMEM;
  129. bpmp->priv = priv;
  130. priv->atomics = devm_platform_ioremap_resource(pdev, 0);
  131. if (IS_ERR(priv->atomics))
  132. return PTR_ERR(priv->atomics);
  133. priv->arb_sema = devm_platform_ioremap_resource(pdev, 1);
  134. if (IS_ERR(priv->arb_sema))
  135. return PTR_ERR(priv->arb_sema);
  136. err = tegra210_bpmp_channel_init(bpmp->tx_channel, bpmp,
  137. bpmp->soc->channels.cpu_tx.offset);
  138. if (err < 0)
  139. return err;
  140. err = tegra210_bpmp_channel_init(bpmp->rx_channel, bpmp,
  141. bpmp->soc->channels.cpu_rx.offset);
  142. if (err < 0)
  143. return err;
  144. for (i = 0; i < bpmp->threaded.count; i++) {
  145. unsigned int index = bpmp->soc->channels.thread.offset + i;
  146. err = tegra210_bpmp_channel_init(&bpmp->threaded_channels[i],
  147. bpmp, index);
  148. if (err < 0)
  149. return err;
  150. }
  151. err = platform_get_irq_byname(pdev, "tx");
  152. if (err < 0) {
  153. dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
  154. return err;
  155. }
  156. priv->tx_irq_data = irq_get_irq_data(err);
  157. if (!priv->tx_irq_data) {
  158. dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
  159. return -ENOENT;
  160. }
  161. err = platform_get_irq_byname(pdev, "rx");
  162. if (err < 0) {
  163. dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
  164. return err;
  165. }
  166. err = devm_request_irq(&pdev->dev, err, rx_irq,
  167. IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
  168. if (err < 0) {
  169. dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
  170. return err;
  171. }
  172. return 0;
  173. }
  174. const struct tegra_bpmp_ops tegra210_bpmp_ops = {
  175. .init = tegra210_bpmp_init,
  176. .is_response_ready = tegra210_bpmp_is_response_ready,
  177. .is_request_ready = tegra210_bpmp_is_request_ready,
  178. .ack_response = tegra210_bpmp_ack_response,
  179. .ack_request = tegra210_bpmp_ack_request,
  180. .is_response_channel_free = tegra210_bpmp_is_response_channel_free,
  181. .is_request_channel_free = tegra210_bpmp_is_request_channel_free,
  182. .post_response = tegra210_bpmp_post_response,
  183. .post_request = tegra210_bpmp_post_request,
  184. .ring_doorbell = tegra210_bpmp_ring_doorbell,
  185. };