msm_audio_ion.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  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 i = 0;
  179. int rc = 0;
  180. void *addr = NULL;
  181. unsigned int pg_cnt = 0;
  182. struct msm_audio_alloc_data *alloc_data = NULL;
  183. rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  184. if (rc) {
  185. pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
  186. goto exit;
  187. }
  188. pg_cnt = dma_buf->size / PAGE_SIZE;
  189. if (dma_buf->size % PAGE_SIZE)
  190. pg_cnt++;
  191. if (pg_cnt == 0) {
  192. pr_err("%s: Page count is NULL\n", __func__);
  193. goto exit;
  194. }
  195. /* Map the first page, and store the address to addr */
  196. addr = dma_buf_kmap(dma_buf, 0);
  197. if (!addr) {
  198. pr_err("%s: mapping kernel buffer failed for page 0\n",
  199. __func__);
  200. goto exit;
  201. }
  202. /* Map remaining pages */
  203. for (i = 1; i < pg_cnt; i++) {
  204. if (!dma_buf_kmap(dma_buf, i)) {
  205. pr_err("%s: mapping kernel buffer failed for page %d\n",
  206. __func__, i);
  207. goto err;
  208. }
  209. }
  210. /*
  211. * TBD: remove the below section once new API
  212. * for mapping kernel virtual address is available.
  213. */
  214. mutex_lock(&(msm_audio_ion_data.list_mutex));
  215. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  216. list) {
  217. if (alloc_data->dma_buf == dma_buf) {
  218. alloc_data->vaddr = addr;
  219. break;
  220. }
  221. }
  222. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  223. return addr;
  224. err:
  225. for (; i > 0; i--)
  226. dma_buf_kunmap(dma_buf, i - 1, addr);
  227. addr = NULL;
  228. exit:
  229. return addr;
  230. }
  231. static void msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
  232. {
  233. int i, rc = 0;
  234. unsigned int pg_cnt = 0;
  235. void *vaddr = NULL;
  236. struct msm_audio_alloc_data *alloc_data = NULL;
  237. struct device *cb_dev = msm_audio_ion_data.cb_dev;
  238. /*
  239. * TBD: remove the below section once new API
  240. * for unmapping kernel virtual address is available.
  241. */
  242. mutex_lock(&(msm_audio_ion_data.list_mutex));
  243. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  244. list) {
  245. if (alloc_data->dma_buf == dma_buf) {
  246. vaddr = alloc_data->vaddr;
  247. break;
  248. }
  249. }
  250. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  251. if (!vaddr) {
  252. dev_err(cb_dev,
  253. "%s: cannot find allocation for dma_buf %pK",
  254. __func__, dma_buf);
  255. goto err;
  256. }
  257. pg_cnt = dma_buf->size / PAGE_SIZE;
  258. if (dma_buf->size % PAGE_SIZE)
  259. pg_cnt++;
  260. for (i = 0; i < pg_cnt; i++)
  261. dma_buf_kunmap(dma_buf, i, vaddr);
  262. rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  263. if (rc) {
  264. dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n",
  265. __func__);
  266. goto err;
  267. }
  268. err:
  269. return;
  270. }
  271. static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
  272. size_t *plen, void *vaddr)
  273. {
  274. int rc = 0;
  275. rc = msm_audio_ion_get_phys(dma_buf, paddr, plen);
  276. if (rc) {
  277. pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
  278. __func__, rc);
  279. goto err;
  280. }
  281. vaddr = msm_audio_ion_map_kernel(dma_buf);
  282. if (IS_ERR_OR_NULL((void *)vaddr)) {
  283. pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
  284. rc = -ENOMEM;
  285. goto err;
  286. }
  287. err:
  288. return rc;
  289. }
  290. /**
  291. * msm_audio_ion_alloc -
  292. * Allocs ION memory for given client name
  293. *
  294. * @dma_buf: dma_buf for the ION memory
  295. * @bufsz: buffer size
  296. * @paddr: Physical address to be assigned with allocated region
  297. * @plen: length of allocated region to be assigned
  298. * vaddr: virtual address to be assigned
  299. *
  300. * Returns 0 on success or error on failure
  301. */
  302. int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
  303. dma_addr_t *paddr, size_t *plen, void **vaddr)
  304. {
  305. int rc = -EINVAL;
  306. unsigned long err_ion_ptr = 0;
  307. if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
  308. pr_debug("%s:probe is not done, deferred\n", __func__);
  309. return -EPROBE_DEFER;
  310. }
  311. if (!dma_buf || !paddr || !vaddr || !bufsz || !plen) {
  312. pr_err("%s: Invalid params\n", __func__);
  313. return -EINVAL;
  314. }
  315. *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
  316. if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
  317. if (IS_ERR((void *)(*dma_buf)))
  318. err_ion_ptr = PTR_ERR((int *)(*dma_buf));
  319. pr_err("%s:ION alloc fail err ptr=%ld\n",
  320. __func__, err_ion_ptr);
  321. rc = -ENOMEM;
  322. goto err;
  323. }
  324. rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, *vaddr);
  325. if (rc) {
  326. pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
  327. goto err_dma_buf;
  328. }
  329. pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
  330. *vaddr, bufsz);
  331. memset((void *)*vaddr, 0, bufsz);
  332. return rc;
  333. err_dma_buf:
  334. dma_buf_put(*dma_buf);
  335. err:
  336. return rc;
  337. }
  338. EXPORT_SYMBOL(msm_audio_ion_alloc);
  339. /**
  340. * msm_audio_ion_import-
  341. * Import ION buffer with given file descriptor
  342. *
  343. * @dma_buf: dma_buf for the ION memory
  344. * @fd: file descriptor for the ION memory
  345. * @ionflag: flags associated with ION buffer
  346. * @bufsz: buffer size
  347. * @paddr: Physical address to be assigned with allocated region
  348. * @plen: length of allocated region to be assigned
  349. * vaddr: virtual address to be assigned
  350. *
  351. * Returns 0 on success or error on failure
  352. */
  353. int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
  354. unsigned long *ionflag, size_t bufsz,
  355. dma_addr_t *paddr, size_t *plen, void **vaddr)
  356. {
  357. int rc = 0;
  358. if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
  359. pr_debug("%s:probe is not done, deferred\n", __func__);
  360. return -EPROBE_DEFER;
  361. }
  362. if (!dma_buf || !paddr || !vaddr || !plen) {
  363. pr_err("%s: Invalid params\n", __func__);
  364. rc = -EINVAL;
  365. goto err;
  366. }
  367. /* bufsz should be 0 and fd shouldn't be 0 as of now */
  368. *dma_buf = dma_buf_get(fd);
  369. pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd);
  370. if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
  371. pr_err("%s: dma_buf_get failed\n", __func__);
  372. rc = -EINVAL;
  373. goto err;
  374. }
  375. if (ionflag != NULL) {
  376. pr_err("%s: could not get flags for the dma_buf\n",
  377. __func__);
  378. rc = -EOPNOTSUPP;
  379. goto err_ion_flag;
  380. }
  381. rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, *vaddr);
  382. if (rc) {
  383. pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
  384. goto err_ion_flag;
  385. }
  386. pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
  387. *vaddr, bufsz);
  388. return 0;
  389. err_ion_flag:
  390. dma_buf_put(*dma_buf);
  391. err:
  392. *dma_buf = NULL;
  393. return rc;
  394. }
  395. EXPORT_SYMBOL(msm_audio_ion_import);
  396. /**
  397. * msm_audio_ion_free -
  398. * fress ION memory for given client and handle
  399. *
  400. * @dma_buf: dma_buf for the ION memory
  401. *
  402. * Returns 0 on success or error on failure
  403. */
  404. int msm_audio_ion_free(struct dma_buf *dma_buf)
  405. {
  406. if (!dma_buf) {
  407. pr_err("%s: dma_buf invalid\n", __func__);
  408. return -EINVAL;
  409. }
  410. msm_audio_ion_unmap_kernel(dma_buf);
  411. msm_audio_dma_buf_unmap(dma_buf);
  412. return 0;
  413. }
  414. EXPORT_SYMBOL(msm_audio_ion_free);
  415. /**
  416. * msm_audio_ion_mmap -
  417. * Audio ION memory map
  418. *
  419. * @abuff: audio buf pointer
  420. * @vma: virtual mem area
  421. *
  422. * Returns 0 on success or error on failure
  423. */
  424. int msm_audio_ion_mmap(struct audio_buffer *abuff,
  425. struct vm_area_struct *vma)
  426. {
  427. struct msm_audio_alloc_data *alloc_data = NULL;
  428. struct sg_table *table;
  429. unsigned long addr = vma->vm_start;
  430. unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
  431. struct scatterlist *sg;
  432. unsigned int i;
  433. struct page *page;
  434. int ret = 0;
  435. bool found = false;
  436. struct device *cb_dev = msm_audio_ion_data.cb_dev;
  437. mutex_lock(&(msm_audio_ion_data.list_mutex));
  438. list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
  439. list) {
  440. if (alloc_data->dma_buf == abuff->dma_buf) {
  441. found = true;
  442. table = alloc_data->table;
  443. break;
  444. }
  445. }
  446. mutex_unlock(&(msm_audio_ion_data.list_mutex));
  447. if (!found) {
  448. dev_err(cb_dev,
  449. "%s: cannot find allocation, dma_buf %pK",
  450. __func__, abuff->dma_buf);
  451. return -EINVAL;
  452. }
  453. /* uncached */
  454. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  455. /* We need to check if a page is associated with this sg list because:
  456. * If the allocation came from a carveout we currently don't have
  457. * pages associated with carved out memory. This might change in the
  458. * future and we can remove this check and the else statement.
  459. */
  460. page = sg_page(table->sgl);
  461. if (page) {
  462. pr_debug("%s: page is NOT null\n", __func__);
  463. for_each_sg(table->sgl, sg, table->nents, i) {
  464. unsigned long remainder = vma->vm_end - addr;
  465. unsigned long len = sg->length;
  466. page = sg_page(sg);
  467. if (offset >= len) {
  468. offset -= len;
  469. continue;
  470. } else if (offset) {
  471. page += offset / PAGE_SIZE;
  472. len -= offset;
  473. offset = 0;
  474. }
  475. len = min(len, remainder);
  476. pr_debug("vma=%pK, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%lu\n",
  477. vma, (unsigned int)addr, len,
  478. (unsigned int)vma->vm_start,
  479. (unsigned int)vma->vm_end,
  480. (unsigned long)pgprot_val(vma->vm_page_prot));
  481. remap_pfn_range(vma, addr, page_to_pfn(page), len,
  482. vma->vm_page_prot);
  483. addr += len;
  484. if (addr >= vma->vm_end)
  485. return 0;
  486. }
  487. } else {
  488. pr_debug("%s: page is NULL\n", __func__);
  489. ret = -EINVAL;
  490. }
  491. return ret;
  492. }
  493. EXPORT_SYMBOL(msm_audio_ion_mmap);
  494. /**
  495. * msm_audio_populate_upper_32_bits -
  496. * retrieve upper 32bits of 64bit address
  497. *
  498. * @pa: 64bit physical address
  499. *
  500. */
  501. u32 msm_audio_populate_upper_32_bits(dma_addr_t pa)
  502. {
  503. if (sizeof(dma_addr_t) == sizeof(u32))
  504. return upper_32_bits(msm_audio_ion_data.smmu_sid_bits);
  505. else
  506. return upper_32_bits(pa);
  507. }
  508. EXPORT_SYMBOL(msm_audio_populate_upper_32_bits);
  509. static int msm_audio_smmu_init(struct device *dev)
  510. {
  511. struct dma_iommu_mapping *mapping;
  512. int ret;
  513. mapping = arm_iommu_create_mapping(&platform_bus_type,
  514. MSM_AUDIO_ION_VA_START,
  515. MSM_AUDIO_ION_VA_LEN);
  516. if (IS_ERR(mapping))
  517. return PTR_ERR(mapping);
  518. ret = arm_iommu_attach_device(dev, mapping);
  519. if (ret) {
  520. dev_err(dev, "%s: Attach failed, err = %d\n",
  521. __func__, ret);
  522. goto fail_attach;
  523. }
  524. msm_audio_ion_data.cb_dev = dev;
  525. msm_audio_ion_data.mapping = mapping;
  526. INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
  527. mutex_init(&(msm_audio_ion_data.list_mutex));
  528. return 0;
  529. fail_attach:
  530. arm_iommu_release_mapping(mapping);
  531. return ret;
  532. }
  533. static const struct of_device_id msm_audio_ion_dt_match[] = {
  534. { .compatible = "qcom,msm-audio-ion" },
  535. { }
  536. };
  537. MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
  538. static int msm_audio_ion_probe(struct platform_device *pdev)
  539. {
  540. int rc = 0;
  541. const char *msm_audio_ion_smmu = "qcom,smmu-version";
  542. const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
  543. enum apr_subsys_state q6_state;
  544. struct device *dev = &pdev->dev;
  545. u64 smmu_sid = 0;
  546. u64 smmu_sid_mask = 0;
  547. struct of_phandle_args iommuspec;
  548. if (dev->of_node == NULL) {
  549. dev_err(dev,
  550. "%s: device tree is not found\n",
  551. __func__);
  552. return 0;
  553. }
  554. rc = of_property_read_u32(dev->of_node,
  555. msm_audio_ion_smmu,
  556. &msm_audio_ion_data.smmu_version);
  557. if (rc) {
  558. dev_err(dev,
  559. "%s: qcom,smmu_version missing in DT node\n",
  560. __func__);
  561. return rc;
  562. }
  563. dev_dbg(dev, "%s: SMMU version is (%d)", __func__,
  564. msm_audio_ion_data.smmu_version);
  565. q6_state = apr_get_q6_state();
  566. if (q6_state == APR_SUBSYS_DOWN) {
  567. dev_dbg(dev,
  568. "defering %s, adsp_state %d\n",
  569. __func__, q6_state);
  570. return -EPROBE_DEFER;
  571. }
  572. dev_dbg(dev, "%s: adsp is ready\n", __func__);
  573. /* Get SMMU SID information from Devicetree */
  574. rc = of_property_read_u64(dev->of_node,
  575. msm_audio_ion_smmu_sid_mask,
  576. &smmu_sid_mask);
  577. if (rc) {
  578. dev_err(dev,
  579. "%s: qcom,smmu-sid-mask missing in DT node, using default\n",
  580. __func__);
  581. smmu_sid_mask = 0xFFFFFFFFFFFFFFFF;
  582. }
  583. rc = of_parse_phandle_with_args(dev->of_node, "iommus",
  584. "#iommu-cells", 0, &iommuspec);
  585. if (rc)
  586. dev_err(dev, "%s: could not get smmu SID, ret = %d\n",
  587. __func__, rc);
  588. else
  589. smmu_sid = (iommuspec.args[0] & smmu_sid_mask);
  590. msm_audio_ion_data.smmu_sid_bits =
  591. smmu_sid << MSM_AUDIO_SMMU_SID_OFFSET;
  592. if (msm_audio_ion_data.smmu_version == 0x2) {
  593. rc = msm_audio_smmu_init(dev);
  594. } else {
  595. dev_err(dev, "%s: smmu version invalid %d\n",
  596. __func__, msm_audio_ion_data.smmu_version);
  597. rc = -EINVAL;
  598. }
  599. if (rc)
  600. dev_err(dev, "%s: smmu init failed, err = %d\n",
  601. __func__, rc);
  602. if (!rc)
  603. msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED;
  604. return rc;
  605. }
  606. static int msm_audio_ion_remove(struct platform_device *pdev)
  607. {
  608. struct dma_iommu_mapping *mapping;
  609. struct device *audio_cb_dev;
  610. mapping = msm_audio_ion_data.mapping;
  611. audio_cb_dev = msm_audio_ion_data.cb_dev;
  612. if (audio_cb_dev && mapping) {
  613. arm_iommu_detach_device(audio_cb_dev);
  614. arm_iommu_release_mapping(mapping);
  615. }
  616. msm_audio_ion_data.device_status = 0;
  617. return 0;
  618. }
  619. static struct platform_driver msm_audio_ion_driver = {
  620. .driver = {
  621. .name = "msm-audio-ion",
  622. .owner = THIS_MODULE,
  623. .of_match_table = msm_audio_ion_dt_match,
  624. },
  625. .probe = msm_audio_ion_probe,
  626. .remove = msm_audio_ion_remove,
  627. };
  628. int __init msm_audio_ion_init(void)
  629. {
  630. return platform_driver_register(&msm_audio_ion_driver);
  631. }
  632. void msm_audio_ion_exit(void)
  633. {
  634. platform_driver_unregister(&msm_audio_ion_driver);
  635. }
  636. MODULE_DESCRIPTION("MSM Audio ION module");
  637. MODULE_LICENSE("GPL v2");