mtk-cmdq-mailbox.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2018 MediaTek Inc.
  4. #include <linux/bitops.h>
  5. #include <linux/clk.h>
  6. #include <linux/clk-provider.h>
  7. #include <linux/dma-mapping.h>
  8. #include <linux/errno.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/io.h>
  11. #include <linux/iopoll.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/pm_runtime.h>
  16. #include <linux/sizes.h>
  17. #include <linux/mailbox_controller.h>
  18. #include <linux/mailbox/mtk-cmdq-mailbox.h>
  19. #include <linux/of.h>
  20. #define CMDQ_MBOX_AUTOSUSPEND_DELAY_MS 100
  21. #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
  22. #define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
  23. #define CMDQ_CURR_IRQ_STATUS 0x10
  24. #define CMDQ_SYNC_TOKEN_UPDATE 0x68
  25. #define CMDQ_THR_SLOT_CYCLES 0x30
  26. #define CMDQ_THR_BASE 0x100
  27. #define CMDQ_THR_SIZE 0x80
  28. #define CMDQ_THR_WARM_RESET 0x00
  29. #define CMDQ_THR_ENABLE_TASK 0x04
  30. #define CMDQ_THR_SUSPEND_TASK 0x08
  31. #define CMDQ_THR_CURR_STATUS 0x0c
  32. #define CMDQ_THR_IRQ_STATUS 0x10
  33. #define CMDQ_THR_IRQ_ENABLE 0x14
  34. #define CMDQ_THR_CURR_ADDR 0x20
  35. #define CMDQ_THR_END_ADDR 0x24
  36. #define CMDQ_THR_WAIT_TOKEN 0x30
  37. #define CMDQ_THR_PRIORITY 0x40
  38. #define GCE_GCTL_VALUE 0x48
  39. #define GCE_CTRL_BY_SW GENMASK(2, 0)
  40. #define GCE_DDR_EN GENMASK(18, 16)
  41. #define GCE_VM_ID_MAP(n) (0x5018 + (n) / 10 * 4)
  42. #define GCE_VM_ID_MAP_THR_FLD_SHIFT(n) ((n) % 10 * 3)
  43. #define GCE_VM_ID_MAP_HOST_VM GENMASK(2, 0)
  44. #define GCE_VM_CPR_GSIZE 0x50c4
  45. #define GCE_VM_CPR_GSIZE_FLD_SHIFT(vm_id) ((vm_id) * 4)
  46. #define GCE_VM_CPR_GSIZE_MAX GENMASK(3, 0)
  47. #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
  48. #define CMDQ_THR_ENABLED 0x1
  49. #define CMDQ_THR_DISABLED 0x0
  50. #define CMDQ_THR_SUSPEND 0x1
  51. #define CMDQ_THR_RESUME 0x0
  52. #define CMDQ_THR_STATUS_SUSPENDED BIT(1)
  53. #define CMDQ_THR_DO_WARM_RESET BIT(0)
  54. #define CMDQ_THR_IRQ_DONE 0x1
  55. #define CMDQ_THR_IRQ_ERROR 0x12
  56. #define CMDQ_THR_IRQ_EN (CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE)
  57. #define CMDQ_THR_IS_WAITING BIT(31)
  58. #define CMDQ_JUMP_BY_OFFSET 0x10000000
  59. #define CMDQ_JUMP_BY_PA 0x10000001
  60. struct cmdq_thread {
  61. struct mbox_chan *chan;
  62. void __iomem *base;
  63. struct list_head task_busy_list;
  64. u32 priority;
  65. };
  66. struct cmdq_task {
  67. struct cmdq *cmdq;
  68. struct list_head list_entry;
  69. dma_addr_t pa_base;
  70. struct cmdq_thread *thread;
  71. struct cmdq_pkt *pkt; /* the packet sent from mailbox client */
  72. };
  73. struct cmdq {
  74. struct mbox_controller mbox;
  75. void __iomem *base;
  76. int irq;
  77. u32 irq_mask;
  78. const struct gce_plat *pdata;
  79. struct cmdq_thread *thread;
  80. struct clk_bulk_data *clocks;
  81. bool suspended;
  82. };
  83. struct gce_plat {
  84. u32 thread_nr;
  85. u8 shift;
  86. dma_addr_t mminfra_offset;
  87. bool control_by_sw;
  88. bool sw_ddr_en;
  89. bool gce_vm;
  90. u32 gce_num;
  91. };
  92. static inline u32 cmdq_convert_gce_addr(dma_addr_t addr, const struct gce_plat *pdata)
  93. {
  94. /* Convert DMA addr (PA or IOVA) to GCE readable addr */
  95. return (addr + pdata->mminfra_offset) >> pdata->shift;
  96. }
  97. static inline dma_addr_t cmdq_revert_gce_addr(u32 addr, const struct gce_plat *pdata)
  98. {
  99. /* Revert GCE readable addr to DMA addr (PA or IOVA) */
  100. return ((dma_addr_t)addr << pdata->shift) - pdata->mminfra_offset;
  101. }
  102. void cmdq_get_mbox_priv(struct mbox_chan *chan, struct cmdq_mbox_priv *priv)
  103. {
  104. struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
  105. priv->shift_pa = cmdq->pdata->shift;
  106. priv->mminfra_offset = cmdq->pdata->mminfra_offset;
  107. }
  108. EXPORT_SYMBOL(cmdq_get_mbox_priv);
  109. u8 cmdq_get_shift_pa(struct mbox_chan *chan)
  110. {
  111. struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
  112. return cmdq->pdata->shift;
  113. }
  114. EXPORT_SYMBOL(cmdq_get_shift_pa);
  115. static void cmdq_vm_init(struct cmdq *cmdq)
  116. {
  117. int i;
  118. u32 vm_cpr_gsize = 0, vm_id_map = 0;
  119. u32 *vm_map = NULL;
  120. if (!cmdq->pdata->gce_vm)
  121. return;
  122. vm_map = kcalloc(cmdq->pdata->thread_nr, sizeof(*vm_map), GFP_KERNEL);
  123. if (!vm_map)
  124. return;
  125. /* only configure the max CPR SRAM size to host vm (vm_id = 0) currently */
  126. vm_cpr_gsize = GCE_VM_CPR_GSIZE_MAX << GCE_VM_CPR_GSIZE_FLD_SHIFT(0);
  127. /* set all thread mapping to host vm currently */
  128. for (i = 0; i < cmdq->pdata->thread_nr; i++)
  129. vm_map[i] = GCE_VM_ID_MAP_HOST_VM << GCE_VM_ID_MAP_THR_FLD_SHIFT(i);
  130. /* set the amount of CPR SRAM to allocate to each VM */
  131. writel(vm_cpr_gsize, cmdq->base + GCE_VM_CPR_GSIZE);
  132. /* config CPR_GSIZE before setting VM_ID_MAP to avoid data leakage */
  133. for (i = 0; i < cmdq->pdata->thread_nr; i++) {
  134. vm_id_map |= vm_map[i];
  135. /* config every 10 threads, e.g., thread id=0~9, 10~19, ..., into one register */
  136. if ((i + 1) % 10 == 0) {
  137. writel(vm_id_map, cmdq->base + GCE_VM_ID_MAP(i));
  138. vm_id_map = 0;
  139. }
  140. }
  141. /* config remaining threads settings */
  142. if (cmdq->pdata->thread_nr % 10 != 0)
  143. writel(vm_id_map, cmdq->base + GCE_VM_ID_MAP(cmdq->pdata->thread_nr - 1));
  144. kfree(vm_map);
  145. }
  146. static void cmdq_gctl_value_toggle(struct cmdq *cmdq, bool ddr_enable)
  147. {
  148. u32 val = cmdq->pdata->control_by_sw ? GCE_CTRL_BY_SW : 0;
  149. if (!cmdq->pdata->control_by_sw && !cmdq->pdata->sw_ddr_en)
  150. return;
  151. if (cmdq->pdata->sw_ddr_en && ddr_enable)
  152. val |= GCE_DDR_EN;
  153. writel(val, cmdq->base + GCE_GCTL_VALUE);
  154. }
  155. static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
  156. {
  157. u32 status;
  158. writel(CMDQ_THR_SUSPEND, thread->base + CMDQ_THR_SUSPEND_TASK);
  159. /* If already disabled, treat as suspended successful. */
  160. if (!(readl(thread->base + CMDQ_THR_ENABLE_TASK) & CMDQ_THR_ENABLED))
  161. return 0;
  162. if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
  163. status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
  164. dev_err(cmdq->mbox.dev, "suspend GCE thread 0x%x failed\n",
  165. (u32)(thread->base - cmdq->base));
  166. return -EFAULT;
  167. }
  168. return 0;
  169. }
  170. static void cmdq_thread_resume(struct cmdq_thread *thread)
  171. {
  172. writel(CMDQ_THR_RESUME, thread->base + CMDQ_THR_SUSPEND_TASK);
  173. }
  174. static void cmdq_init(struct cmdq *cmdq)
  175. {
  176. int i;
  177. WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
  178. cmdq_vm_init(cmdq);
  179. cmdq_gctl_value_toggle(cmdq, true);
  180. writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
  181. for (i = 0; i <= CMDQ_MAX_EVENT; i++)
  182. writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE);
  183. clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
  184. }
  185. static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
  186. {
  187. u32 warm_reset;
  188. writel(CMDQ_THR_DO_WARM_RESET, thread->base + CMDQ_THR_WARM_RESET);
  189. if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
  190. warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
  191. 0, 10)) {
  192. dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x failed\n",
  193. (u32)(thread->base - cmdq->base));
  194. return -EFAULT;
  195. }
  196. return 0;
  197. }
  198. static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
  199. {
  200. cmdq_thread_reset(cmdq, thread);
  201. writel(CMDQ_THR_DISABLED, thread->base + CMDQ_THR_ENABLE_TASK);
  202. }
  203. /* notify GCE to re-fetch commands by setting GCE thread PC */
  204. static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
  205. {
  206. writel(readl(thread->base + CMDQ_THR_CURR_ADDR),
  207. thread->base + CMDQ_THR_CURR_ADDR);
  208. }
  209. static void cmdq_task_insert_into_thread(struct cmdq_task *task)
  210. {
  211. struct device *dev = task->cmdq->mbox.dev;
  212. struct cmdq_thread *thread = task->thread;
  213. struct cmdq_task *prev_task = list_last_entry(
  214. &thread->task_busy_list, typeof(*task), list_entry);
  215. u64 *prev_task_base = prev_task->pkt->va_base;
  216. u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata);
  217. /* let previous task jump to this task */
  218. dma_sync_single_for_cpu(dev, prev_task->pa_base,
  219. prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
  220. prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr;
  221. dma_sync_single_for_device(dev, prev_task->pa_base,
  222. prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
  223. cmdq_thread_invalidate_fetched_data(thread);
  224. }
  225. static bool cmdq_thread_is_in_wfe(struct cmdq_thread *thread)
  226. {
  227. return readl(thread->base + CMDQ_THR_WAIT_TOKEN) & CMDQ_THR_IS_WAITING;
  228. }
  229. static void cmdq_task_exec_done(struct cmdq_task *task, int sta)
  230. {
  231. struct cmdq_cb_data data;
  232. data.sta = sta;
  233. data.pkt = task->pkt;
  234. mbox_chan_received_data(task->thread->chan, &data);
  235. list_del(&task->list_entry);
  236. }
  237. static void cmdq_task_handle_error(struct cmdq_task *task)
  238. {
  239. struct cmdq_thread *thread = task->thread;
  240. struct cmdq_task *next_task;
  241. struct cmdq *cmdq = task->cmdq;
  242. dev_err(cmdq->mbox.dev, "task 0x%p error\n", task);
  243. WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
  244. next_task = list_first_entry_or_null(&thread->task_busy_list,
  245. struct cmdq_task, list_entry);
  246. if (next_task)
  247. writel(next_task->pa_base >> cmdq->pdata->shift,
  248. thread->base + CMDQ_THR_CURR_ADDR);
  249. cmdq_thread_resume(thread);
  250. }
  251. static void cmdq_thread_irq_handler(struct cmdq *cmdq,
  252. struct cmdq_thread *thread)
  253. {
  254. struct cmdq_task *task, *tmp, *curr_task = NULL;
  255. u32 irq_flag, gce_addr;
  256. dma_addr_t curr_pa, task_end_pa;
  257. bool err;
  258. irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS);
  259. writel(~irq_flag, thread->base + CMDQ_THR_IRQ_STATUS);
  260. /*
  261. * When ISR call this function, another CPU core could run
  262. * "release task" right before we acquire the spin lock, and thus
  263. * reset / disable this GCE thread, so we need to check the enable
  264. * bit of this GCE thread.
  265. */
  266. if (!(readl(thread->base + CMDQ_THR_ENABLE_TASK) & CMDQ_THR_ENABLED))
  267. return;
  268. if (irq_flag & CMDQ_THR_IRQ_ERROR)
  269. err = true;
  270. else if (irq_flag & CMDQ_THR_IRQ_DONE)
  271. err = false;
  272. else
  273. return;
  274. gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR);
  275. curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
  276. list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
  277. list_entry) {
  278. task_end_pa = task->pa_base + task->pkt->cmd_buf_size;
  279. if (curr_pa >= task->pa_base && curr_pa < task_end_pa)
  280. curr_task = task;
  281. if (!curr_task || curr_pa == task_end_pa - CMDQ_INST_SIZE) {
  282. cmdq_task_exec_done(task, 0);
  283. kfree(task);
  284. } else if (err) {
  285. cmdq_task_exec_done(task, -ENOEXEC);
  286. cmdq_task_handle_error(curr_task);
  287. kfree(task);
  288. }
  289. if (curr_task)
  290. break;
  291. }
  292. if (list_empty(&thread->task_busy_list))
  293. cmdq_thread_disable(cmdq, thread);
  294. }
  295. static irqreturn_t cmdq_irq_handler(int irq, void *dev)
  296. {
  297. struct cmdq *cmdq = dev;
  298. unsigned long irq_status, flags = 0L;
  299. int bit;
  300. irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & cmdq->irq_mask;
  301. if (!(irq_status ^ cmdq->irq_mask))
  302. return IRQ_NONE;
  303. for_each_clear_bit(bit, &irq_status, cmdq->pdata->thread_nr) {
  304. struct cmdq_thread *thread = &cmdq->thread[bit];
  305. spin_lock_irqsave(&thread->chan->lock, flags);
  306. cmdq_thread_irq_handler(cmdq, thread);
  307. spin_unlock_irqrestore(&thread->chan->lock, flags);
  308. }
  309. pm_runtime_mark_last_busy(cmdq->mbox.dev);
  310. return IRQ_HANDLED;
  311. }
  312. static int cmdq_runtime_resume(struct device *dev)
  313. {
  314. struct cmdq *cmdq = dev_get_drvdata(dev);
  315. int ret;
  316. ret = clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks);
  317. if (ret)
  318. return ret;
  319. cmdq_gctl_value_toggle(cmdq, true);
  320. return 0;
  321. }
  322. static int cmdq_runtime_suspend(struct device *dev)
  323. {
  324. struct cmdq *cmdq = dev_get_drvdata(dev);
  325. cmdq_gctl_value_toggle(cmdq, false);
  326. clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
  327. return 0;
  328. }
  329. static int cmdq_suspend(struct device *dev)
  330. {
  331. struct cmdq *cmdq = dev_get_drvdata(dev);
  332. struct cmdq_thread *thread;
  333. int i;
  334. bool task_running = false;
  335. cmdq->suspended = true;
  336. for (i = 0; i < cmdq->pdata->thread_nr; i++) {
  337. thread = &cmdq->thread[i];
  338. if (!list_empty(&thread->task_busy_list)) {
  339. task_running = true;
  340. break;
  341. }
  342. }
  343. if (task_running)
  344. dev_warn(dev, "exist running task(s) in suspend\n");
  345. return pm_runtime_force_suspend(dev);
  346. }
  347. static int cmdq_resume(struct device *dev)
  348. {
  349. struct cmdq *cmdq = dev_get_drvdata(dev);
  350. WARN_ON(pm_runtime_force_resume(dev));
  351. cmdq->suspended = false;
  352. return 0;
  353. }
  354. static void cmdq_remove(struct platform_device *pdev)
  355. {
  356. struct cmdq *cmdq = platform_get_drvdata(pdev);
  357. if (!IS_ENABLED(CONFIG_PM))
  358. cmdq_runtime_suspend(&pdev->dev);
  359. clk_bulk_unprepare(cmdq->pdata->gce_num, cmdq->clocks);
  360. }
  361. static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
  362. {
  363. struct cmdq_pkt *pkt = (struct cmdq_pkt *)data;
  364. struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
  365. struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
  366. struct cmdq_task *task;
  367. u32 gce_addr;
  368. dma_addr_t curr_pa, end_pa;
  369. /* Client should not flush new tasks if suspended. */
  370. WARN_ON(cmdq->suspended);
  371. task = kzalloc_obj(*task, GFP_ATOMIC);
  372. if (!task)
  373. return -ENOMEM;
  374. task->cmdq = cmdq;
  375. INIT_LIST_HEAD(&task->list_entry);
  376. task->pa_base = pkt->pa_base;
  377. task->thread = thread;
  378. task->pkt = pkt;
  379. if (list_empty(&thread->task_busy_list)) {
  380. /*
  381. * The thread reset will clear thread related register to 0,
  382. * including pc, end, priority, irq, suspend and enable. Thus
  383. * set CMDQ_THR_ENABLED to CMDQ_THR_ENABLE_TASK will enable
  384. * thread and make it running.
  385. */
  386. WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
  387. gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata);
  388. writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR);
  389. gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata);
  390. writel(gce_addr, thread->base + CMDQ_THR_END_ADDR);
  391. writel(thread->priority, thread->base + CMDQ_THR_PRIORITY);
  392. writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE);
  393. writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK);
  394. } else {
  395. WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
  396. gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR);
  397. curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
  398. gce_addr = readl(thread->base + CMDQ_THR_END_ADDR);
  399. end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
  400. /* check boundary */
  401. if (curr_pa == end_pa - CMDQ_INST_SIZE ||
  402. curr_pa == end_pa) {
  403. /* set to this task directly */
  404. writel(task->pa_base >> cmdq->pdata->shift,
  405. thread->base + CMDQ_THR_CURR_ADDR);
  406. } else {
  407. cmdq_task_insert_into_thread(task);
  408. smp_mb(); /* modify jump before enable thread */
  409. }
  410. writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift,
  411. thread->base + CMDQ_THR_END_ADDR);
  412. cmdq_thread_resume(thread);
  413. }
  414. list_move_tail(&task->list_entry, &thread->task_busy_list);
  415. return 0;
  416. }
  417. static int cmdq_mbox_startup(struct mbox_chan *chan)
  418. {
  419. return 0;
  420. }
  421. static void cmdq_mbox_shutdown(struct mbox_chan *chan)
  422. {
  423. struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
  424. struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
  425. struct cmdq_task *task, *tmp;
  426. unsigned long flags;
  427. WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev) < 0);
  428. spin_lock_irqsave(&thread->chan->lock, flags);
  429. if (list_empty(&thread->task_busy_list))
  430. goto done;
  431. WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
  432. /* make sure executed tasks have success callback */
  433. cmdq_thread_irq_handler(cmdq, thread);
  434. if (list_empty(&thread->task_busy_list))
  435. goto done;
  436. list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
  437. list_entry) {
  438. cmdq_task_exec_done(task, -ECONNABORTED);
  439. kfree(task);
  440. }
  441. cmdq_thread_disable(cmdq, thread);
  442. done:
  443. /*
  444. * The thread->task_busy_list empty means thread already disable. The
  445. * cmdq_mbox_send_data() always reset thread which clear disable and
  446. * suspend statue when first pkt send to channel, so there is no need
  447. * to do any operation here, only unlock and leave.
  448. */
  449. spin_unlock_irqrestore(&thread->chan->lock, flags);
  450. pm_runtime_mark_last_busy(cmdq->mbox.dev);
  451. pm_runtime_put_autosuspend(cmdq->mbox.dev);
  452. }
  453. static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
  454. {
  455. struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
  456. struct cmdq_cb_data data;
  457. struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
  458. struct cmdq_task *task, *tmp;
  459. unsigned long flags;
  460. u32 enable;
  461. int ret;
  462. ret = pm_runtime_get_sync(cmdq->mbox.dev);
  463. if (ret < 0)
  464. return ret;
  465. spin_lock_irqsave(&thread->chan->lock, flags);
  466. if (list_empty(&thread->task_busy_list))
  467. goto out;
  468. WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
  469. if (!cmdq_thread_is_in_wfe(thread))
  470. goto wait;
  471. list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
  472. list_entry) {
  473. data.sta = -ECONNABORTED;
  474. data.pkt = task->pkt;
  475. mbox_chan_received_data(task->thread->chan, &data);
  476. list_del(&task->list_entry);
  477. kfree(task);
  478. }
  479. cmdq_thread_resume(thread);
  480. cmdq_thread_disable(cmdq, thread);
  481. out:
  482. spin_unlock_irqrestore(&thread->chan->lock, flags);
  483. pm_runtime_mark_last_busy(cmdq->mbox.dev);
  484. pm_runtime_put_autosuspend(cmdq->mbox.dev);
  485. return 0;
  486. wait:
  487. cmdq_thread_resume(thread);
  488. spin_unlock_irqrestore(&thread->chan->lock, flags);
  489. if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_ENABLE_TASK,
  490. enable, enable == 0, 1, timeout)) {
  491. dev_err(cmdq->mbox.dev, "Fail to wait GCE thread 0x%x done\n",
  492. (u32)(thread->base - cmdq->base));
  493. return -EFAULT;
  494. }
  495. pm_runtime_mark_last_busy(cmdq->mbox.dev);
  496. pm_runtime_put_autosuspend(cmdq->mbox.dev);
  497. return 0;
  498. }
  499. static const struct mbox_chan_ops cmdq_mbox_chan_ops = {
  500. .send_data = cmdq_mbox_send_data,
  501. .startup = cmdq_mbox_startup,
  502. .shutdown = cmdq_mbox_shutdown,
  503. .flush = cmdq_mbox_flush,
  504. };
  505. static struct mbox_chan *cmdq_xlate(struct mbox_controller *mbox,
  506. const struct of_phandle_args *sp)
  507. {
  508. int ind = sp->args[0];
  509. struct cmdq_thread *thread;
  510. if (ind >= mbox->num_chans)
  511. return ERR_PTR(-EINVAL);
  512. thread = (struct cmdq_thread *)mbox->chans[ind].con_priv;
  513. thread->priority = sp->args[1];
  514. thread->chan = &mbox->chans[ind];
  515. return &mbox->chans[ind];
  516. }
  517. static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
  518. {
  519. static const char * const gce_name = "gce";
  520. struct device_node *parent = dev->of_node->parent;
  521. struct clk_bulk_data *clks;
  522. cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num,
  523. sizeof(*cmdq->clocks), GFP_KERNEL);
  524. if (!cmdq->clocks)
  525. return -ENOMEM;
  526. if (cmdq->pdata->gce_num == 1) {
  527. clks = &cmdq->clocks[0];
  528. clks->id = gce_name;
  529. clks->clk = devm_clk_get(dev, NULL);
  530. if (IS_ERR(clks->clk))
  531. return dev_err_probe(dev, PTR_ERR(clks->clk),
  532. "failed to get gce clock\n");
  533. return 0;
  534. }
  535. /*
  536. * If there is more than one GCE, get the clocks for the others too,
  537. * as the clock of the main GCE must be enabled for additional IPs
  538. * to be reachable.
  539. */
  540. for_each_child_of_node_scoped(parent, node) {
  541. int alias_id = of_alias_get_id(node, gce_name);
  542. if (alias_id < 0 || alias_id >= cmdq->pdata->gce_num)
  543. continue;
  544. clks = &cmdq->clocks[alias_id];
  545. clks->id = devm_kasprintf(dev, GFP_KERNEL, "gce%d", alias_id);
  546. if (!clks->id)
  547. return -ENOMEM;
  548. clks->clk = of_clk_get(node, 0);
  549. if (IS_ERR(clks->clk))
  550. return dev_err_probe(dev, PTR_ERR(clks->clk),
  551. "failed to get gce%d clock\n", alias_id);
  552. }
  553. return 0;
  554. }
  555. static int cmdq_probe(struct platform_device *pdev)
  556. {
  557. struct device *dev = &pdev->dev;
  558. struct cmdq *cmdq;
  559. int err, i;
  560. cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
  561. if (!cmdq)
  562. return -ENOMEM;
  563. cmdq->base = devm_platform_ioremap_resource(pdev, 0);
  564. if (IS_ERR(cmdq->base))
  565. return PTR_ERR(cmdq->base);
  566. cmdq->irq = platform_get_irq(pdev, 0);
  567. if (cmdq->irq < 0)
  568. return cmdq->irq;
  569. cmdq->pdata = device_get_match_data(dev);
  570. if (!cmdq->pdata) {
  571. dev_err(dev, "failed to get match data\n");
  572. return -EINVAL;
  573. }
  574. cmdq->irq_mask = GENMASK(cmdq->pdata->thread_nr - 1, 0);
  575. dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
  576. dev, cmdq->base, cmdq->irq);
  577. err = cmdq_get_clocks(dev, cmdq);
  578. if (err)
  579. return err;
  580. dma_set_coherent_mask(dev,
  581. DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift));
  582. cmdq->mbox.dev = dev;
  583. cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr,
  584. sizeof(*cmdq->mbox.chans), GFP_KERNEL);
  585. if (!cmdq->mbox.chans)
  586. return -ENOMEM;
  587. cmdq->mbox.num_chans = cmdq->pdata->thread_nr;
  588. cmdq->mbox.ops = &cmdq_mbox_chan_ops;
  589. cmdq->mbox.of_xlate = cmdq_xlate;
  590. /* make use of TXDONE_BY_ACK */
  591. cmdq->mbox.txdone_irq = false;
  592. cmdq->mbox.txdone_poll = false;
  593. cmdq->thread = devm_kcalloc(dev, cmdq->pdata->thread_nr,
  594. sizeof(*cmdq->thread), GFP_KERNEL);
  595. if (!cmdq->thread)
  596. return -ENOMEM;
  597. for (i = 0; i < cmdq->pdata->thread_nr; i++) {
  598. cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
  599. CMDQ_THR_SIZE * i;
  600. INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
  601. cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i];
  602. }
  603. platform_set_drvdata(pdev, cmdq);
  604. WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks));
  605. cmdq_init(cmdq);
  606. err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
  607. "mtk_cmdq", cmdq);
  608. if (err < 0) {
  609. dev_err(dev, "failed to register ISR (%d)\n", err);
  610. return err;
  611. }
  612. /* If Runtime PM is not available enable the clocks now. */
  613. if (!IS_ENABLED(CONFIG_PM)) {
  614. err = cmdq_runtime_resume(dev);
  615. if (err)
  616. return err;
  617. }
  618. err = devm_pm_runtime_enable(dev);
  619. if (err)
  620. return err;
  621. pm_runtime_set_autosuspend_delay(dev, CMDQ_MBOX_AUTOSUSPEND_DELAY_MS);
  622. pm_runtime_use_autosuspend(dev);
  623. err = devm_mbox_controller_register(dev, &cmdq->mbox);
  624. if (err < 0) {
  625. dev_err(dev, "failed to register mailbox: %d\n", err);
  626. return err;
  627. }
  628. return 0;
  629. }
  630. static const struct dev_pm_ops cmdq_pm_ops = {
  631. .suspend = cmdq_suspend,
  632. .resume = cmdq_resume,
  633. SET_RUNTIME_PM_OPS(cmdq_runtime_suspend,
  634. cmdq_runtime_resume, NULL)
  635. };
  636. static const struct gce_plat gce_plat_mt6779 = {
  637. .thread_nr = 24,
  638. .shift = 3,
  639. .control_by_sw = false,
  640. .gce_num = 1
  641. };
  642. static const struct gce_plat gce_plat_mt8173 = {
  643. .thread_nr = 16,
  644. .shift = 0,
  645. .control_by_sw = false,
  646. .gce_num = 1
  647. };
  648. static const struct gce_plat gce_plat_mt8183 = {
  649. .thread_nr = 24,
  650. .shift = 0,
  651. .control_by_sw = false,
  652. .gce_num = 1
  653. };
  654. static const struct gce_plat gce_plat_mt8186 = {
  655. .thread_nr = 24,
  656. .shift = 3,
  657. .control_by_sw = true,
  658. .sw_ddr_en = true,
  659. .gce_num = 1
  660. };
  661. static const struct gce_plat gce_plat_mt8188 = {
  662. .thread_nr = 32,
  663. .shift = 3,
  664. .control_by_sw = true,
  665. .gce_num = 2
  666. };
  667. static const struct gce_plat gce_plat_mt8192 = {
  668. .thread_nr = 24,
  669. .shift = 3,
  670. .control_by_sw = true,
  671. .gce_num = 1
  672. };
  673. static const struct gce_plat gce_plat_mt8195 = {
  674. .thread_nr = 24,
  675. .shift = 3,
  676. .control_by_sw = true,
  677. .gce_num = 2
  678. };
  679. static const struct gce_plat gce_plat_mt8196 = {
  680. .thread_nr = 32,
  681. .shift = 3,
  682. .mminfra_offset = SZ_2G,
  683. .control_by_sw = true,
  684. .sw_ddr_en = true,
  685. .gce_vm = true,
  686. .gce_num = 2
  687. };
  688. static const struct of_device_id cmdq_of_ids[] = {
  689. {.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_mt6779},
  690. {.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_mt8173},
  691. {.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_mt8183},
  692. {.compatible = "mediatek,mt8186-gce", .data = (void *)&gce_plat_mt8186},
  693. {.compatible = "mediatek,mt8188-gce", .data = (void *)&gce_plat_mt8188},
  694. {.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_mt8192},
  695. {.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_mt8195},
  696. {.compatible = "mediatek,mt8196-gce", .data = (void *)&gce_plat_mt8196},
  697. {}
  698. };
  699. MODULE_DEVICE_TABLE(of, cmdq_of_ids);
  700. static struct platform_driver cmdq_drv = {
  701. .probe = cmdq_probe,
  702. .remove = cmdq_remove,
  703. .driver = {
  704. .name = "mtk_cmdq",
  705. .pm = &cmdq_pm_ops,
  706. .of_match_table = cmdq_of_ids,
  707. }
  708. };
  709. static int __init cmdq_drv_init(void)
  710. {
  711. return platform_driver_register(&cmdq_drv);
  712. }
  713. static void __exit cmdq_drv_exit(void)
  714. {
  715. platform_driver_unregister(&cmdq_drv);
  716. }
  717. subsys_initcall(cmdq_drv_init);
  718. module_exit(cmdq_drv_exit);
  719. MODULE_DESCRIPTION("Mediatek Command Queue(CMDQ) Mailbox driver");
  720. MODULE_LICENSE("GPL v2");