msm_audio_ion.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/init.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/err.h>
  17. #include <linux/delay.h>
  18. #include <linux/slab.h>
  19. #include <linux/mutex.h>
  20. #include <linux/list.h>
  21. #include <linux/dma-mapping.h>
  22. #include <linux/dma-buf.h>
  23. #include <linux/iommu.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/of_device.h>
  26. #include <linux/export.h>
  27. #include <linux/ion_kernel.h>
  28. #include <ipc/apr.h>
  29. #include <asm/dma-iommu.h>
  30. #include <dsp/msm_audio_ion.h>
  31. #define MSM_AUDIO_ION_PROBED (1 << 0)
  32. #define MSM_AUDIO_ION_PHYS_ADDR(alloc_data) \
  33. alloc_data->table->sgl->dma_address
  34. #define MSM_AUDIO_ION_VA_START 0x10000000
  35. #define MSM_AUDIO_ION_VA_LEN 0x0FFFFFFF
  36. #define MSM_AUDIO_SMMU_SID_OFFSET 32
  37. struct msm_audio_ion_private {
  38. bool audioheap_enabled;
  39. struct device *cb_dev;
  40. struct dma_iommu_mapping *mapping;
  41. u8 device_status;
  42. struct list_head alloc_list;
  43. struct mutex list_mutex;
  44. u64 smmu_sid_bits;
  45. u32 smmu_version;
  46. };
  47. struct msm_audio_alloc_data {
  48. size_t len;
  49. void *vaddr;
  50. struct dma_buf *dma_buf;
  51. struct dma_buf_attachment *attach;
  52. struct sg_table *table;
  53. struct list_head list;
  54. };
  55. static struct msm_audio_ion_private msm_audio_ion_data = {0,};
  56. static void msm_audio_ion_add_allocation(
  57. struct msm_audio_ion_private *msm_audio_ion_data,
  58. struct msm_audio_alloc_data *alloc_data)
  59. {
  60. /*
  61. * Since these APIs can be invoked by multiple
  62. * clients, there is need to make sure the list
  63. * of allocations is always protected
  64. */
  65. mutex_lock(&(msm_audio_ion_data->list_mutex));
  66. list_add_tail(&(alloc_data->list),
  67. &(msm_audio_ion_data->alloc_list));
  68. mutex_unlock(&(msm_audio_ion_data->list_mutex));
  69. }
  70. static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
  71. dma_addr_t *addr, size_t *len)
  72. {
  73. struct msm_audio_alloc_data *alloc_data;
  74. struct device *cb_dev;
  75. int rc = 0;
  76. cb_dev = msm_audio_ion_data.cb_dev;
  77. /* Data required per buffer mapping */
  78. alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL);
  79. if (!alloc_data)
  80. return -ENOMEM;
  81. alloc_data->dma_buf = dma_buf;
  82. alloc_data->len = dma_buf->size;
  83. *len = dma_buf->size;
  84. /* Attach the dma_buf to context bank device */
  85. alloc_data->attach = dma_buf_attach(alloc_data->dma_buf,
  86. cb_dev);
  87. if (IS_ERR(alloc_data->attach)) {
  88. rc = PTR_ERR(alloc_data->attach);
  89. dev_err(cb_dev,
  90. "%s: Fail to attach dma_buf to CB, rc = %d\n",
  91. __func__, rc);
  92. goto err_attach;
  93. }
  94. /*
  95. * Get the scatter-gather list.
  96. * There is no info as this is a write buffer or
  97. * read buffer, hence the request is bi-directional
  98. * to accommodate both read and write mappings.
  99. */
  100. alloc_data->table = dma_buf_map_attachment(alloc_data->attach,
  101. DMA_BIDIRECTIONAL);
  102. if (IS_ERR(alloc_data->table)) {
  103. rc = PTR_ERR(alloc_data->table);
  104. dev_err(cb_dev,
  105. "%s: Fail to map attachment, rc = %d\n",
  106. __func__, rc);
  107. goto err_map_attach;
  108. }
  109. /* physical address from mapping */
  110. *addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
  111. msm_audio_ion_add_allocation(&msm_audio_ion_data,
  112. alloc_data);
  113. return rc;
  114. err_map_attach:
  115. dma_buf_detach(alloc_data->dma_buf,
  116. alloc_data->attach);
  117. err_attach:
  118. kfree(alloc_data);
  119. return rc;
  120. }
  121. static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
  122. {
  123. int rc = 0;
  124. struct msm_audio_alloc_data *alloc_data = NULL;
  125. struct list_head *ptr, *next;
  126. struct device *cb_dev = msm_audio_ion_data.cb_dev;
  127. bool found = false;
  128. /*
  129. * Though list_for_each_safe is delete safe, lock
  130. * should be explicitly acquired to avoid race condition
  131. * on adding elements to the list.
  132. */
  133. mutex_lock(&(msm_audio_ion_data.list_mutex));
  134. list_for_each_safe(ptr, next,
  135. &(msm_audio_ion_data.alloc_list)) {
  136. alloc_data = list_entry(ptr, struct msm_audio_alloc_data,
  137. list);
  138. if (alloc_data->dma_buf == dma_buf) {
  139. found = true;
  140. dma_buf_unmap_attachment(alloc_data->attach,
  141. alloc_data->table,
  142. DMA_BIDIRECTIONAL);
  143. dma_buf_detach(alloc_data->dma_buf,
  144. alloc_data->attach);
  145. dma_buf_put(alloc_data->dma_buf);
  146. list_del(&(alloc_data->list));
  147. kfree(alloc_data);
  148. break;
  149. }
  150. }
  151. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  152. if (!found) {
  153. dev_err(cb_dev,
  154. "%s: cannot find allocation, dma_buf %pK",
  155. __func__, dma_buf);
  156. rc = -EINVAL;
  157. }
  158. return rc;
  159. }
  160. static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
  161. dma_addr_t *addr, size_t *len)
  162. {
  163. int rc = 0;
  164. rc = msm_audio_dma_buf_map(dma_buf, addr, len);
  165. if (rc) {
  166. pr_err("%s: failed to map DMA buf, err = %d\n",
  167. __func__, rc);
  168. goto err;
  169. }
  170. /* Append the SMMU SID information to the IOVA address */
  171. *addr |= msm_audio_ion_data.smmu_sid_bits;
  172. pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc);
  173. err:
  174. return rc;
  175. }
  176. static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf)
  177. {
  178. int rc = 0;
  179. void *addr = NULL;
  180. struct msm_audio_alloc_data *alloc_data = NULL;
  181. rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  182. if (rc) {
  183. pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
  184. goto exit;
  185. }
  186. addr = dma_buf_vmap(dma_buf);
  187. if (!addr) {
  188. pr_err("%s: kernel mapping of dma_buf failed\n",
  189. __func__);
  190. goto exit;
  191. }
  192. /*
  193. * TBD: remove the below section once new API
  194. * for mapping kernel virtual address is available.
  195. */
  196. mutex_lock(&(msm_audio_ion_data.list_mutex));
  197. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  198. list) {
  199. if (alloc_data->dma_buf == dma_buf) {
  200. alloc_data->vaddr = addr;
  201. break;
  202. }
  203. }
  204. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  205. exit:
  206. return addr;
  207. }
  208. static void msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
  209. {
  210. int rc = 0;
  211. void *vaddr = NULL;
  212. struct msm_audio_alloc_data *alloc_data = NULL;
  213. struct device *cb_dev = msm_audio_ion_data.cb_dev;
  214. /*
  215. * TBD: remove the below section once new API
  216. * for unmapping kernel virtual address is available.
  217. */
  218. mutex_lock(&(msm_audio_ion_data.list_mutex));
  219. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  220. list) {
  221. if (alloc_data->dma_buf == dma_buf) {
  222. vaddr = alloc_data->vaddr;
  223. break;
  224. }
  225. }
  226. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  227. if (!vaddr) {
  228. dev_err(cb_dev,
  229. "%s: cannot find allocation for dma_buf %pK",
  230. __func__, dma_buf);
  231. goto err;
  232. }
  233. dma_buf_vunmap(dma_buf, vaddr);
  234. rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  235. if (rc) {
  236. dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n",
  237. __func__);
  238. goto err;
  239. }
  240. err:
  241. return;
  242. }
  243. static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
  244. size_t *plen, void **vaddr)
  245. {
  246. int rc = 0;
  247. rc = msm_audio_ion_get_phys(dma_buf, paddr, plen);
  248. if (rc) {
  249. pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
  250. __func__, rc);
  251. goto err;
  252. }
  253. *vaddr = msm_audio_ion_map_kernel(dma_buf);
  254. if (IS_ERR_OR_NULL(*vaddr)) {
  255. pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
  256. rc = -ENOMEM;
  257. goto err;
  258. }
  259. err:
  260. return rc;
  261. }
  262. /**
  263. * msm_audio_ion_alloc -
  264. * Allocs ION memory for given client name
  265. *
  266. * @dma_buf: dma_buf for the ION memory
  267. * @bufsz: buffer size
  268. * @paddr: Physical address to be assigned with allocated region
  269. * @plen: length of allocated region to be assigned
  270. * vaddr: virtual address to be assigned
  271. *
  272. * Returns 0 on success or error on failure
  273. */
  274. int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
  275. dma_addr_t *paddr, size_t *plen, void **vaddr)
  276. {
  277. int rc = -EINVAL;
  278. unsigned long err_ion_ptr = 0;
  279. if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
  280. pr_debug("%s:probe is not done, deferred\n", __func__);
  281. return -EPROBE_DEFER;
  282. }
  283. if (!dma_buf || !paddr || !vaddr || !bufsz || !plen) {
  284. pr_err("%s: Invalid params\n", __func__);
  285. return -EINVAL;
  286. }
  287. *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
  288. if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
  289. if (IS_ERR((void *)(*dma_buf)))
  290. err_ion_ptr = PTR_ERR((int *)(*dma_buf));
  291. pr_err("%s:ION alloc fail err ptr=%ld\n",
  292. __func__, err_ion_ptr);
  293. rc = -ENOMEM;
  294. goto err;
  295. }
  296. rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
  297. if (rc) {
  298. pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
  299. goto err_dma_buf;
  300. }
  301. pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
  302. *vaddr, bufsz);
  303. memset(*vaddr, 0, bufsz);
  304. return rc;
  305. err_dma_buf:
  306. dma_buf_put(*dma_buf);
  307. err:
  308. return rc;
  309. }
  310. EXPORT_SYMBOL(msm_audio_ion_alloc);
  311. /**
  312. * msm_audio_ion_import-
  313. * Import ION buffer with given file descriptor
  314. *
  315. * @dma_buf: dma_buf for the ION memory
  316. * @fd: file descriptor for the ION memory
  317. * @ionflag: flags associated with ION buffer
  318. * @bufsz: buffer size
  319. * @paddr: Physical address to be assigned with allocated region
  320. * @plen: length of allocated region to be assigned
  321. * vaddr: virtual address to be assigned
  322. *
  323. * Returns 0 on success or error on failure
  324. */
  325. int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
  326. unsigned long *ionflag, size_t bufsz,
  327. dma_addr_t *paddr, size_t *plen, void **vaddr)
  328. {
  329. int rc = 0;
  330. if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
  331. pr_debug("%s:probe is not done, deferred\n", __func__);
  332. return -EPROBE_DEFER;
  333. }
  334. if (!dma_buf || !paddr || !vaddr || !plen) {
  335. pr_err("%s: Invalid params\n", __func__);
  336. return -EINVAL;
  337. }
  338. /* bufsz should be 0 and fd shouldn't be 0 as of now */
  339. *dma_buf = dma_buf_get(fd);
  340. pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd);
  341. if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
  342. pr_err("%s: dma_buf_get failed\n", __func__);
  343. rc = -EINVAL;
  344. goto err;
  345. }
  346. if (ionflag != NULL) {
  347. rc = dma_buf_get_flags(*dma_buf, ionflag);
  348. if (rc) {
  349. pr_err("%s: could not get flags for the dma_buf\n",
  350. __func__);
  351. goto err_ion_flag;
  352. }
  353. }
  354. rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
  355. if (rc) {
  356. pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
  357. goto err_ion_flag;
  358. }
  359. pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
  360. *vaddr, bufsz);
  361. return 0;
  362. err_ion_flag:
  363. dma_buf_put(*dma_buf);
  364. err:
  365. *dma_buf = NULL;
  366. return rc;
  367. }
  368. EXPORT_SYMBOL(msm_audio_ion_import);
  369. /**
  370. * msm_audio_ion_free -
  371. * fress ION memory for given client and handle
  372. *
  373. * @dma_buf: dma_buf for the ION memory
  374. *
  375. * Returns 0 on success or error on failure
  376. */
  377. int msm_audio_ion_free(struct dma_buf *dma_buf)
  378. {
  379. if (!dma_buf) {
  380. pr_err("%s: dma_buf invalid\n", __func__);
  381. return -EINVAL;
  382. }
  383. msm_audio_ion_unmap_kernel(dma_buf);
  384. msm_audio_dma_buf_unmap(dma_buf);
  385. return 0;
  386. }
  387. EXPORT_SYMBOL(msm_audio_ion_free);
  388. /**
  389. * msm_audio_ion_mmap -
  390. * Audio ION memory map
  391. *
  392. * @abuff: audio buf pointer
  393. * @vma: virtual mem area
  394. *
  395. * Returns 0 on success or error on failure
  396. */
  397. int msm_audio_ion_mmap(struct audio_buffer *abuff,
  398. struct vm_area_struct *vma)
  399. {
  400. struct msm_audio_alloc_data *alloc_data = NULL;
  401. struct sg_table *table;
  402. unsigned long addr = vma->vm_start;
  403. unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
  404. struct scatterlist *sg;
  405. unsigned int i;
  406. struct page *page;
  407. int ret = 0;
  408. bool found = false;
  409. struct device *cb_dev = msm_audio_ion_data.cb_dev;
  410. mutex_lock(&(msm_audio_ion_data.list_mutex));
  411. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  412. list) {
  413. if (alloc_data->dma_buf == abuff->dma_buf) {
  414. found = true;
  415. table = alloc_data->table;
  416. break;
  417. }
  418. }
  419. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  420. if (!found) {
  421. dev_err(cb_dev,
  422. "%s: cannot find allocation, dma_buf %pK",
  423. __func__, abuff->dma_buf);
  424. return -EINVAL;
  425. }
  426. /* uncached */
  427. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  428. /* We need to check if a page is associated with this sg list because:
  429. * If the allocation came from a carveout we currently don't have
  430. * pages associated with carved out memory. This might change in the
  431. * future and we can remove this check and the else statement.
  432. */
  433. page = sg_page(table->sgl);
  434. if (page) {
  435. pr_debug("%s: page is NOT null\n", __func__);
  436. for_each_sg(table->sgl, sg, table->nents, i) {
  437. unsigned long remainder = vma->vm_end - addr;
  438. unsigned long len = sg->length;
  439. page = sg_page(sg);
  440. if (offset >= len) {
  441. offset -= len;
  442. continue;
  443. } else if (offset) {
  444. page += offset / PAGE_SIZE;
  445. len -= offset;
  446. offset = 0;
  447. }
  448. len = min(len, remainder);
  449. pr_debug("vma=%pK, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%lu\n",
  450. vma, (unsigned int)addr, len,
  451. (unsigned int)vma->vm_start,
  452. (unsigned int)vma->vm_end,
  453. (unsigned long)pgprot_val(vma->vm_page_prot));
  454. remap_pfn_range(vma, addr, page_to_pfn(page), len,
  455. vma->vm_page_prot);
  456. addr += len;
  457. if (addr >= vma->vm_end)
  458. return 0;
  459. }
  460. } else {
  461. pr_debug("%s: page is NULL\n", __func__);
  462. ret = -EINVAL;
  463. }
  464. return ret;
  465. }
  466. EXPORT_SYMBOL(msm_audio_ion_mmap);
  467. /**
  468. * msm_audio_ion_cache_operations-
  469. * Cache operations on cached Audio ION buffers
  470. *
  471. * @abuff: audio buf pointer
  472. * @cache_op: cache operation to be performed
  473. *
  474. * Returns 0 on success or error on failure
  475. */
  476. int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op)
  477. {
  478. unsigned long ionflag = 0;
  479. int rc = 0;
  480. if (!abuff) {
  481. pr_err("%s: Invalid params: %pK\n", __func__, abuff);
  482. return -EINVAL;
  483. }
  484. rc = dma_buf_get_flags(abuff->dma_buf, &ionflag);
  485. if (rc) {
  486. pr_err("%s: dma_buf_get_flags failed: %d\n", __func__, rc);
  487. goto cache_op_failed;
  488. }
  489. /* Has to be CACHED */
  490. if (ionflag & ION_FLAG_CACHED) {
  491. /* MSM_AUDIO_ION_INV_CACHES or MSM_AUDIO_ION_CLEAN_CACHES */
  492. switch (cache_op) {
  493. case MSM_AUDIO_ION_INV_CACHES:
  494. case MSM_AUDIO_ION_CLEAN_CACHES:
  495. dma_buf_begin_cpu_access(abuff->dma_buf,
  496. DMA_BIDIRECTIONAL);
  497. dma_buf_end_cpu_access(abuff->dma_buf,
  498. DMA_BIDIRECTIONAL);
  499. break;
  500. default:
  501. pr_err("%s: Invalid cache operation %d\n",
  502. __func__, cache_op);
  503. }
  504. } else {
  505. pr_err("%s: Cache ops called on uncached buffer: %pK\n",
  506. __func__, abuff->dma_buf);
  507. rc = -EINVAL;
  508. }
  509. cache_op_failed:
  510. return rc;
  511. }
  512. EXPORT_SYMBOL(msm_audio_ion_cache_operations);
  513. /**
  514. * msm_audio_populate_upper_32_bits -
  515. * retrieve upper 32bits of 64bit address
  516. *
  517. * @pa: 64bit physical address
  518. *
  519. */
  520. u32 msm_audio_populate_upper_32_bits(dma_addr_t pa)
  521. {
  522. if (sizeof(dma_addr_t) == sizeof(u32))
  523. return upper_32_bits(msm_audio_ion_data.smmu_sid_bits);
  524. else
  525. return upper_32_bits(pa);
  526. }
  527. EXPORT_SYMBOL(msm_audio_populate_upper_32_bits);
  528. static int msm_audio_smmu_init(struct device *dev)
  529. {
  530. struct dma_iommu_mapping *mapping;
  531. int ret;
  532. mapping = arm_iommu_create_mapping(&platform_bus_type,
  533. MSM_AUDIO_ION_VA_START,
  534. MSM_AUDIO_ION_VA_LEN);
  535. if (IS_ERR(mapping))
  536. return PTR_ERR(mapping);
  537. ret = arm_iommu_attach_device(dev, mapping);
  538. if (ret) {
  539. dev_err(dev, "%s: Attach failed, err = %d\n",
  540. __func__, ret);
  541. goto fail_attach;
  542. }
  543. msm_audio_ion_data.cb_dev = dev;
  544. msm_audio_ion_data.mapping = mapping;
  545. INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
  546. mutex_init(&(msm_audio_ion_data.list_mutex));
  547. return 0;
  548. fail_attach:
  549. arm_iommu_release_mapping(mapping);
  550. return ret;
  551. }
  552. static const struct of_device_id msm_audio_ion_dt_match[] = {
  553. { .compatible = "qcom,msm-audio-ion" },
  554. { }
  555. };
  556. MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
  557. static int msm_audio_ion_probe(struct platform_device *pdev)
  558. {
  559. int rc = 0;
  560. const char *msm_audio_ion_smmu = "qcom,smmu-version";
  561. const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
  562. enum apr_subsys_state q6_state;
  563. struct device *dev = &pdev->dev;
  564. u64 smmu_sid = 0;
  565. u64 smmu_sid_mask = 0;
  566. struct of_phandle_args iommuspec;
  567. if (dev->of_node == NULL) {
  568. dev_err(dev,
  569. "%s: device tree is not found\n",
  570. __func__);
  571. return 0;
  572. }
  573. rc = of_property_read_u32(dev->of_node,
  574. msm_audio_ion_smmu,
  575. &msm_audio_ion_data.smmu_version);
  576. if (rc) {
  577. dev_err(dev,
  578. "%s: qcom,smmu_version missing in DT node\n",
  579. __func__);
  580. return rc;
  581. }
  582. dev_dbg(dev, "%s: SMMU version is (%d)", __func__,
  583. msm_audio_ion_data.smmu_version);
  584. q6_state = apr_get_q6_state();
  585. if (q6_state == APR_SUBSYS_DOWN) {
  586. dev_dbg(dev,
  587. "defering %s, adsp_state %d\n",
  588. __func__, q6_state);
  589. return -EPROBE_DEFER;
  590. }
  591. dev_dbg(dev, "%s: adsp is ready\n", __func__);
  592. /* Get SMMU SID information from Devicetree */
  593. rc = of_property_read_u64(dev->of_node,
  594. msm_audio_ion_smmu_sid_mask,
  595. &smmu_sid_mask);
  596. if (rc) {
  597. dev_err(dev,
  598. "%s: qcom,smmu-sid-mask missing in DT node, using default\n",
  599. __func__);
  600. smmu_sid_mask = 0xFFFFFFFFFFFFFFFF;
  601. }
  602. rc = of_parse_phandle_with_args(dev->of_node, "iommus",
  603. "#iommu-cells", 0, &iommuspec);
  604. if (rc)
  605. dev_err(dev, "%s: could not get smmu SID, ret = %d\n",
  606. __func__, rc);
  607. else
  608. smmu_sid = (iommuspec.args[0] & smmu_sid_mask);
  609. msm_audio_ion_data.smmu_sid_bits =
  610. smmu_sid << MSM_AUDIO_SMMU_SID_OFFSET;
  611. if (msm_audio_ion_data.smmu_version == 0x2) {
  612. rc = msm_audio_smmu_init(dev);
  613. } else {
  614. dev_err(dev, "%s: smmu version invalid %d\n",
  615. __func__, msm_audio_ion_data.smmu_version);
  616. rc = -EINVAL;
  617. }
  618. if (rc)
  619. dev_err(dev, "%s: smmu init failed, err = %d\n",
  620. __func__, rc);
  621. if (!rc)
  622. msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED;
  623. return rc;
  624. }
  625. static int msm_audio_ion_remove(struct platform_device *pdev)
  626. {
  627. struct dma_iommu_mapping *mapping;
  628. struct device *audio_cb_dev;
  629. mapping = msm_audio_ion_data.mapping;
  630. audio_cb_dev = msm_audio_ion_data.cb_dev;
  631. if (audio_cb_dev && mapping) {
  632. arm_iommu_detach_device(audio_cb_dev);
  633. arm_iommu_release_mapping(mapping);
  634. }
  635. msm_audio_ion_data.device_status = 0;
  636. return 0;
  637. }
  638. static struct platform_driver msm_audio_ion_driver = {
  639. .driver = {
  640. .name = "msm-audio-ion",
  641. .owner = THIS_MODULE,
  642. .of_match_table = msm_audio_ion_dt_match,
  643. },
  644. .probe = msm_audio_ion_probe,
  645. .remove = msm_audio_ion_remove,
  646. };
  647. int __init msm_audio_ion_init(void)
  648. {
  649. return platform_driver_register(&msm_audio_ion_driver);
  650. }
  651. void msm_audio_ion_exit(void)
  652. {
  653. platform_driver_unregister(&msm_audio_ion_driver);
  654. }
  655. MODULE_DESCRIPTION("MSM Audio ION module");
  656. MODULE_LICENSE("GPL v2");