tegra-hsp.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016, NVIDIA CORPORATION.
  4. */
  5. #include <common.h>
  6. #include <asm/io.h>
  7. #include <dm.h>
  8. #include <mailbox-uclass.h>
  9. #include <dt-bindings/mailbox/tegra186-hsp.h>
  10. #define TEGRA_HSP_INT_DIMENSIONING 0x380
  11. #define TEGRA_HSP_INT_DIMENSIONING_NSI_SHIFT 16
  12. #define TEGRA_HSP_INT_DIMENSIONING_NSI_MASK 0xf
  13. #define TEGRA_HSP_INT_DIMENSIONING_NDB_SHIFT 12
  14. #define TEGRA_HSP_INT_DIMENSIONING_NDB_MASK 0xf
  15. #define TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT 8
  16. #define TEGRA_HSP_INT_DIMENSIONING_NAS_MASK 0xf
  17. #define TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT 4
  18. #define TEGRA_HSP_INT_DIMENSIONING_NSS_MASK 0xf
  19. #define TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT 0
  20. #define TEGRA_HSP_INT_DIMENSIONING_NSM_MASK 0xf
  21. #define TEGRA_HSP_DB_REG_TRIGGER 0x0
  22. #define TEGRA_HSP_DB_REG_ENABLE 0x4
  23. #define TEGRA_HSP_DB_REG_RAW 0x8
  24. #define TEGRA_HSP_DB_REG_PENDING 0xc
  25. #define TEGRA_HSP_DB_ID_CCPLEX 1
  26. #define TEGRA_HSP_DB_ID_BPMP 3
  27. #define TEGRA_HSP_DB_ID_NUM 7
  28. struct tegra_hsp {
  29. fdt_addr_t regs;
  30. uint32_t db_base;
  31. };
  32. static uint32_t *tegra_hsp_reg(struct tegra_hsp *thsp, uint32_t db_id,
  33. uint32_t reg)
  34. {
  35. return (uint32_t *)(thsp->regs + thsp->db_base + (db_id * 0x100) + reg);
  36. }
  37. static uint32_t tegra_hsp_readl(struct tegra_hsp *thsp, uint32_t db_id,
  38. uint32_t reg)
  39. {
  40. uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
  41. return readl(r);
  42. }
  43. static void tegra_hsp_writel(struct tegra_hsp *thsp, uint32_t val,
  44. uint32_t db_id, uint32_t reg)
  45. {
  46. uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
  47. writel(val, r);
  48. readl(r);
  49. }
  50. static int tegra_hsp_db_id(ulong chan_id)
  51. {
  52. switch (chan_id) {
  53. case (HSP_MBOX_TYPE_DB << 16) | HSP_DB_MASTER_BPMP:
  54. return TEGRA_HSP_DB_ID_BPMP;
  55. default:
  56. debug("Invalid channel ID\n");
  57. return -EINVAL;
  58. }
  59. }
  60. static int tegra_hsp_of_xlate(struct mbox_chan *chan,
  61. struct ofnode_phandle_args *args)
  62. {
  63. debug("%s(chan=%p)\n", __func__, chan);
  64. if (args->args_count != 2) {
  65. debug("Invaild args_count: %d\n", args->args_count);
  66. return -EINVAL;
  67. }
  68. chan->id = (args->args[0] << 16) | args->args[1];
  69. return 0;
  70. }
  71. static int tegra_hsp_request(struct mbox_chan *chan)
  72. {
  73. int db_id;
  74. debug("%s(chan=%p)\n", __func__, chan);
  75. db_id = tegra_hsp_db_id(chan->id);
  76. if (db_id < 0) {
  77. debug("tegra_hsp_db_id() failed: %d\n", db_id);
  78. return -EINVAL;
  79. }
  80. return 0;
  81. }
  82. static int tegra_hsp_free(struct mbox_chan *chan)
  83. {
  84. debug("%s(chan=%p)\n", __func__, chan);
  85. return 0;
  86. }
  87. static int tegra_hsp_send(struct mbox_chan *chan, const void *data)
  88. {
  89. struct tegra_hsp *thsp = dev_get_priv(chan->dev);
  90. int db_id;
  91. debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
  92. db_id = tegra_hsp_db_id(chan->id);
  93. tegra_hsp_writel(thsp, 1, db_id, TEGRA_HSP_DB_REG_TRIGGER);
  94. return 0;
  95. }
  96. static int tegra_hsp_recv(struct mbox_chan *chan, void *data)
  97. {
  98. struct tegra_hsp *thsp = dev_get_priv(chan->dev);
  99. uint32_t db_id = TEGRA_HSP_DB_ID_CCPLEX;
  100. uint32_t val;
  101. debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
  102. val = tegra_hsp_readl(thsp, db_id, TEGRA_HSP_DB_REG_RAW);
  103. if (!(val & BIT(chan->id)))
  104. return -ENODATA;
  105. tegra_hsp_writel(thsp, BIT(chan->id), db_id, TEGRA_HSP_DB_REG_RAW);
  106. return 0;
  107. }
  108. static int tegra_hsp_bind(struct udevice *dev)
  109. {
  110. debug("%s(dev=%p)\n", __func__, dev);
  111. return 0;
  112. }
  113. static int tegra_hsp_probe(struct udevice *dev)
  114. {
  115. struct tegra_hsp *thsp = dev_get_priv(dev);
  116. u32 val;
  117. int nr_sm, nr_ss, nr_as;
  118. debug("%s(dev=%p)\n", __func__, dev);
  119. thsp->regs = devfdt_get_addr(dev);
  120. if (thsp->regs == FDT_ADDR_T_NONE)
  121. return -ENODEV;
  122. val = readl(thsp->regs + TEGRA_HSP_INT_DIMENSIONING);
  123. nr_sm = (val >> TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT) &
  124. TEGRA_HSP_INT_DIMENSIONING_NSM_MASK;
  125. nr_ss = (val >> TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT) &
  126. TEGRA_HSP_INT_DIMENSIONING_NSS_MASK;
  127. nr_as = (val >> TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT) &
  128. TEGRA_HSP_INT_DIMENSIONING_NAS_MASK;
  129. thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16;
  130. return 0;
  131. }
  132. static const struct udevice_id tegra_hsp_ids[] = {
  133. { .compatible = "nvidia,tegra186-hsp" },
  134. { }
  135. };
  136. struct mbox_ops tegra_hsp_mbox_ops = {
  137. .of_xlate = tegra_hsp_of_xlate,
  138. .request = tegra_hsp_request,
  139. .rfree = tegra_hsp_free,
  140. .send = tegra_hsp_send,
  141. .recv = tegra_hsp_recv,
  142. };
  143. U_BOOT_DRIVER(tegra_hsp) = {
  144. .name = "tegra-hsp",
  145. .id = UCLASS_MAILBOX,
  146. .of_match = tegra_hsp_ids,
  147. .bind = tegra_hsp_bind,
  148. .probe = tegra_hsp_probe,
  149. .priv_auto_alloc_size = sizeof(struct tegra_hsp),
  150. .ops = &tegra_hsp_mbox_ops,
  151. };