nvme_apple.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <mailbox.h>
  8. #include <mapmem.h>
  9. #include "nvme.h"
  10. #include <reset.h>
  11. #include <asm/io.h>
  12. #include <asm/arch/rtkit.h>
  13. #include <asm/arch/sart.h>
  14. #include <linux/iopoll.h>
  15. /* ASC registers */
  16. #define REG_CPU_CTRL 0x0044
  17. #define REG_CPU_CTRL_RUN BIT(4)
  18. /* Apple NVMe registers */
  19. #define ANS_MAX_PEND_CMDS_CTRL 0x01210
  20. #define ANS_MAX_QUEUE_DEPTH 64
  21. #define ANS_BOOT_STATUS 0x01300
  22. #define ANS_BOOT_STATUS_OK 0xde71ce55
  23. #define ANS_MODESEL 0x01304
  24. #define ANS_UNKNOWN_CTRL 0x24008
  25. #define ANS_PRP_NULL_CHECK (1 << 11)
  26. #define ANS_LINEAR_SQ_CTRL 0x24908
  27. #define ANS_LINEAR_SQ_CTRL_EN (1 << 0)
  28. #define ANS_ASQ_DB 0x2490c
  29. #define ANS_IOSQ_DB 0x24910
  30. #define ANS_NVMMU_NUM 0x28100
  31. #define ANS_NVMMU_BASE_ASQ 0x28108
  32. #define ANS_NVMMU_BASE_IOSQ 0x28110
  33. #define ANS_NVMMU_TCB_INVAL 0x28118
  34. #define ANS_NVMMU_TCB_STAT 0x28120
  35. #define ANS_NVMMU_TCB_SIZE 0x4000
  36. #define ANS_NVMMU_TCB_PITCH 0x80
  37. /*
  38. * The Apple NVMe controller includes an IOMMU known as NVMMU. The
  39. * NVMMU is programmed through an array of TCBs. These TCBs are paired
  40. * with the corresponding slot in the submission queues and need to be
  41. * configured with the command details before a command is allowed to
  42. * execute. This is necessary even for commands that don't do DMA.
  43. */
  44. struct ans_nvmmu_tcb {
  45. u8 opcode;
  46. u8 flags;
  47. u8 slot;
  48. u8 pad0;
  49. u32 prpl_len;
  50. u8 pad1[16];
  51. u64 prp1;
  52. u64 prp2;
  53. };
  54. #define ANS_NVMMU_TCB_WRITE BIT(0)
  55. #define ANS_NVMMU_TCB_READ BIT(1)
  56. struct apple_nvme_priv {
  57. struct nvme_dev ndev;
  58. void *base; /* NVMe registers */
  59. void *asc; /* ASC registers */
  60. struct reset_ctl_bulk resets; /* ASC reset */
  61. struct mbox_chan chan;
  62. struct apple_sart *sart;
  63. struct apple_rtkit *rtk;
  64. struct ans_nvmmu_tcb *tcbs[NVME_Q_NUM]; /* Submission queue TCBs */
  65. u32 __iomem *q_db[NVME_Q_NUM]; /* Submission queue doorbell */
  66. };
  67. static int apple_nvme_setup_queue(struct nvme_queue *nvmeq)
  68. {
  69. struct apple_nvme_priv *priv =
  70. container_of(nvmeq->dev, struct apple_nvme_priv, ndev);
  71. struct nvme_dev *dev = nvmeq->dev;
  72. switch (nvmeq->qid) {
  73. case NVME_ADMIN_Q:
  74. case NVME_IO_Q:
  75. break;
  76. default:
  77. return -EINVAL;
  78. }
  79. priv->tcbs[nvmeq->qid] = (void *)memalign(4096, ANS_NVMMU_TCB_SIZE);
  80. memset((void *)priv->tcbs[nvmeq->qid], 0, ANS_NVMMU_TCB_SIZE);
  81. switch (nvmeq->qid) {
  82. case NVME_ADMIN_Q:
  83. priv->q_db[nvmeq->qid] =
  84. ((void __iomem *)dev->bar) + ANS_ASQ_DB;
  85. nvme_writeq((ulong)priv->tcbs[nvmeq->qid],
  86. ((void __iomem *)dev->bar) + ANS_NVMMU_BASE_ASQ);
  87. break;
  88. case NVME_IO_Q:
  89. priv->q_db[nvmeq->qid] =
  90. ((void __iomem *)dev->bar) + ANS_IOSQ_DB;
  91. nvme_writeq((ulong)priv->tcbs[nvmeq->qid],
  92. ((void __iomem *)dev->bar) + ANS_NVMMU_BASE_IOSQ);
  93. break;
  94. }
  95. return 0;
  96. }
  97. static void apple_nvme_submit_cmd(struct nvme_queue *nvmeq,
  98. struct nvme_command *cmd)
  99. {
  100. struct apple_nvme_priv *priv =
  101. container_of(nvmeq->dev, struct apple_nvme_priv, ndev);
  102. struct ans_nvmmu_tcb *tcb;
  103. u16 tail = nvmeq->sq_tail;
  104. tcb = ((void *)priv->tcbs[nvmeq->qid]) + tail * ANS_NVMMU_TCB_PITCH;
  105. memset(tcb, 0, sizeof(*tcb));
  106. tcb->opcode = cmd->common.opcode;
  107. tcb->flags = ANS_NVMMU_TCB_WRITE | ANS_NVMMU_TCB_READ;
  108. tcb->slot = tail;
  109. tcb->prpl_len = cmd->rw.length;
  110. tcb->prp1 = cmd->common.prp1;
  111. tcb->prp2 = cmd->common.prp2;
  112. writel(tail, priv->q_db[nvmeq->qid]);
  113. }
  114. static void apple_nvme_complete_cmd(struct nvme_queue *nvmeq,
  115. struct nvme_command *cmd)
  116. {
  117. struct apple_nvme_priv *priv =
  118. container_of(nvmeq->dev, struct apple_nvme_priv, ndev);
  119. struct ans_nvmmu_tcb *tcb;
  120. u16 tail = nvmeq->sq_tail;
  121. tcb = ((void *)priv->tcbs[nvmeq->qid]) + tail * ANS_NVMMU_TCB_PITCH;
  122. memset(tcb, 0, sizeof(*tcb));
  123. writel(tail, ((void __iomem *)nvmeq->dev->bar) + ANS_NVMMU_TCB_INVAL);
  124. readl(((void __iomem *)nvmeq->dev->bar) + ANS_NVMMU_TCB_STAT);
  125. if (++tail == nvmeq->q_depth)
  126. tail = 0;
  127. nvmeq->sq_tail = tail;
  128. }
  129. static int nvme_shmem_setup(void *cookie, struct apple_rtkit_buffer *buf)
  130. {
  131. struct apple_nvme_priv *priv = (struct apple_nvme_priv *)cookie;
  132. if (!buf || buf->dva || !buf->size)
  133. return -1;
  134. buf->buffer = memalign(SZ_16K, ALIGN(buf->size, SZ_16K));
  135. if (!buf->buffer)
  136. return -ENOMEM;
  137. if (!sart_add_allowed_region(priv->sart, buf->buffer, buf->size)) {
  138. free(buf->buffer);
  139. buf->buffer = NULL;
  140. buf->size = 0;
  141. return -1;
  142. }
  143. buf->dva = (u64)buf->buffer;
  144. return 0;
  145. }
  146. static void nvme_shmem_destroy(void *cookie, struct apple_rtkit_buffer *buf)
  147. {
  148. struct apple_nvme_priv *priv = (struct apple_nvme_priv *)cookie;
  149. if (!buf)
  150. return;
  151. if (buf->buffer) {
  152. sart_remove_allowed_region(priv->sart, buf->buffer, buf->size);
  153. free(buf->buffer);
  154. buf->buffer = NULL;
  155. buf->size = 0;
  156. buf->dva = 0;
  157. }
  158. }
  159. static int apple_nvme_probe(struct udevice *dev)
  160. {
  161. struct apple_nvme_priv *priv = dev_get_priv(dev);
  162. fdt_addr_t addr;
  163. ofnode of_sart;
  164. u32 ctrl, stat, phandle;
  165. int ret;
  166. priv->base = dev_read_addr_ptr(dev);
  167. if (!priv->base)
  168. return -EINVAL;
  169. addr = dev_read_addr_index(dev, 1);
  170. if (addr == FDT_ADDR_T_NONE)
  171. return -EINVAL;
  172. priv->asc = map_sysmem(addr, 0);
  173. ret = reset_get_bulk(dev, &priv->resets);
  174. if (ret < 0)
  175. return ret;
  176. ret = mbox_get_by_index(dev, 0, &priv->chan);
  177. if (ret < 0)
  178. return ret;
  179. ret = dev_read_u32(dev, "apple,sart", &phandle);
  180. if (ret < 0)
  181. return ret;
  182. of_sart = ofnode_get_by_phandle(phandle);
  183. priv->sart = sart_init(of_sart);
  184. if (!priv->sart)
  185. return -EINVAL;
  186. ctrl = readl(priv->asc + REG_CPU_CTRL);
  187. writel(ctrl | REG_CPU_CTRL_RUN, priv->asc + REG_CPU_CTRL);
  188. priv->rtk = apple_rtkit_init(&priv->chan, priv, nvme_shmem_setup, nvme_shmem_destroy);
  189. if (!priv->rtk)
  190. return -ENOMEM;
  191. ret = apple_rtkit_boot(priv->rtk);
  192. if (ret < 0) {
  193. printf("%s: NVMe apple_rtkit_boot returned: %d\n", __func__, ret);
  194. return ret;
  195. }
  196. ret = readl_poll_sleep_timeout(priv->base + ANS_BOOT_STATUS, stat,
  197. (stat == ANS_BOOT_STATUS_OK), 100,
  198. 500000);
  199. if (ret < 0) {
  200. printf("%s: NVMe firmware didn't boot\n", __func__);
  201. return -ETIMEDOUT;
  202. }
  203. writel(ANS_LINEAR_SQ_CTRL_EN, priv->base + ANS_LINEAR_SQ_CTRL);
  204. writel(((ANS_MAX_QUEUE_DEPTH << 16) | ANS_MAX_QUEUE_DEPTH),
  205. priv->base + ANS_MAX_PEND_CMDS_CTRL);
  206. writel(readl(priv->base + ANS_UNKNOWN_CTRL) & ~ANS_PRP_NULL_CHECK,
  207. priv->base + ANS_UNKNOWN_CTRL);
  208. strcpy(priv->ndev.vendor, "Apple");
  209. writel((ANS_NVMMU_TCB_SIZE / ANS_NVMMU_TCB_PITCH) - 1,
  210. priv->base + ANS_NVMMU_NUM);
  211. writel(0, priv->base + ANS_MODESEL);
  212. priv->ndev.bar = priv->base;
  213. return nvme_init(dev);
  214. }
  215. static int apple_nvme_remove(struct udevice *dev)
  216. {
  217. struct apple_nvme_priv *priv = dev_get_priv(dev);
  218. u32 ctrl;
  219. nvme_shutdown(dev);
  220. apple_rtkit_shutdown(priv->rtk, APPLE_RTKIT_PWR_STATE_SLEEP);
  221. ctrl = readl(priv->asc + REG_CPU_CTRL);
  222. writel(ctrl & ~REG_CPU_CTRL_RUN, priv->asc + REG_CPU_CTRL);
  223. apple_rtkit_free(priv->rtk);
  224. priv->rtk = NULL;
  225. sart_free(priv->sart);
  226. priv->sart = NULL;
  227. reset_assert_bulk(&priv->resets);
  228. reset_deassert_bulk(&priv->resets);
  229. return 0;
  230. }
  231. static const struct nvme_ops apple_nvme_ops = {
  232. .setup_queue = apple_nvme_setup_queue,
  233. .submit_cmd = apple_nvme_submit_cmd,
  234. .complete_cmd = apple_nvme_complete_cmd,
  235. };
  236. static const struct udevice_id apple_nvme_ids[] = {
  237. { .compatible = "apple,nvme-ans2" },
  238. { /* sentinel */ }
  239. };
  240. U_BOOT_DRIVER(apple_nvme) = {
  241. .name = "apple_nvme",
  242. .id = UCLASS_NVME,
  243. .of_match = apple_nvme_ids,
  244. .priv_auto = sizeof(struct apple_nvme_priv),
  245. .probe = apple_nvme_probe,
  246. .remove = apple_nvme_remove,
  247. .ops = &apple_nvme_ops,
  248. .flags = DM_FLAG_OS_PREPARE,
  249. };