sprd-iommu.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Unisoc IOMMU driver
  4. *
  5. * Copyright (C) 2020 Unisoc, Inc.
  6. * Author: Chunyan Zhang <chunyan.zhang@unisoc.com>
  7. */
  8. #include <linux/clk.h>
  9. #include <linux/device.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/errno.h>
  12. #include <linux/iommu.h>
  13. #include <linux/mfd/syscon.h>
  14. #include <linux/module.h>
  15. #include <linux/of_platform.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/regmap.h>
  18. #include <linux/slab.h>
  19. #define SPRD_IOMMU_PAGE_SHIFT 12
  20. #define SPRD_IOMMU_PAGE_SIZE SZ_4K
  21. #define SPRD_EX_CFG 0x0
  22. #define SPRD_IOMMU_VAOR_BYPASS BIT(4)
  23. #define SPRD_IOMMU_GATE_EN BIT(1)
  24. #define SPRD_IOMMU_EN BIT(0)
  25. #define SPRD_EX_UPDATE 0x4
  26. #define SPRD_EX_FIRST_VPN 0x8
  27. #define SPRD_EX_VPN_RANGE 0xc
  28. #define SPRD_EX_FIRST_PPN 0x10
  29. #define SPRD_EX_DEFAULT_PPN 0x14
  30. #define SPRD_IOMMU_VERSION 0x0
  31. #define SPRD_VERSION_MASK GENMASK(15, 8)
  32. #define SPRD_VERSION_SHIFT 0x8
  33. #define SPRD_VAU_CFG 0x4
  34. #define SPRD_VAU_UPDATE 0x8
  35. #define SPRD_VAU_AUTH_CFG 0xc
  36. #define SPRD_VAU_FIRST_PPN 0x10
  37. #define SPRD_VAU_DEFAULT_PPN_RD 0x14
  38. #define SPRD_VAU_DEFAULT_PPN_WR 0x18
  39. #define SPRD_VAU_FIRST_VPN 0x1c
  40. #define SPRD_VAU_VPN_RANGE 0x20
  41. enum sprd_iommu_version {
  42. SPRD_IOMMU_EX,
  43. SPRD_IOMMU_VAU,
  44. };
  45. /*
  46. * struct sprd_iommu_device - high-level sprd IOMMU device representation,
  47. * including hardware information and configuration, also driver data, etc
  48. *
  49. * @ver: sprd IOMMU IP version
  50. * @prot_page_va: protect page base virtual address
  51. * @prot_page_pa: protect page base physical address, data would be
  52. * written to here while translation fault
  53. * @base: mapped base address for accessing registers
  54. * @dev: pointer to basic device structure
  55. * @iommu: IOMMU core representation
  56. * @group: IOMMU group
  57. * @eb: gate clock which controls IOMMU access
  58. */
  59. struct sprd_iommu_device {
  60. struct sprd_iommu_domain *dom;
  61. enum sprd_iommu_version ver;
  62. u32 *prot_page_va;
  63. dma_addr_t prot_page_pa;
  64. void __iomem *base;
  65. struct device *dev;
  66. struct iommu_device iommu;
  67. struct clk *eb;
  68. };
  69. struct sprd_iommu_domain {
  70. spinlock_t pgtlock; /* lock for page table */
  71. struct iommu_domain domain;
  72. u32 *pgt_va; /* page table virtual address base */
  73. dma_addr_t pgt_pa; /* page table physical address base */
  74. struct sprd_iommu_device *sdev;
  75. };
  76. static const struct iommu_ops sprd_iommu_ops;
  77. static struct sprd_iommu_domain *to_sprd_domain(struct iommu_domain *dom)
  78. {
  79. return container_of(dom, struct sprd_iommu_domain, domain);
  80. }
  81. static inline void
  82. sprd_iommu_write(struct sprd_iommu_device *sdev, unsigned int reg, u32 val)
  83. {
  84. writel_relaxed(val, sdev->base + reg);
  85. }
  86. static inline u32
  87. sprd_iommu_read(struct sprd_iommu_device *sdev, unsigned int reg)
  88. {
  89. return readl_relaxed(sdev->base + reg);
  90. }
  91. static inline void
  92. sprd_iommu_update_bits(struct sprd_iommu_device *sdev, unsigned int reg,
  93. u32 mask, u32 shift, u32 val)
  94. {
  95. u32 t = sprd_iommu_read(sdev, reg);
  96. t = (t & (~(mask << shift))) | ((val & mask) << shift);
  97. sprd_iommu_write(sdev, reg, t);
  98. }
  99. static inline int
  100. sprd_iommu_get_version(struct sprd_iommu_device *sdev)
  101. {
  102. int ver = (sprd_iommu_read(sdev, SPRD_IOMMU_VERSION) &
  103. SPRD_VERSION_MASK) >> SPRD_VERSION_SHIFT;
  104. switch (ver) {
  105. case SPRD_IOMMU_EX:
  106. case SPRD_IOMMU_VAU:
  107. return ver;
  108. default:
  109. return -EINVAL;
  110. }
  111. }
  112. static size_t
  113. sprd_iommu_pgt_size(struct iommu_domain *domain)
  114. {
  115. return ((domain->geometry.aperture_end -
  116. domain->geometry.aperture_start + 1) >>
  117. SPRD_IOMMU_PAGE_SHIFT) * sizeof(u32);
  118. }
  119. static struct iommu_domain *sprd_iommu_domain_alloc_paging(struct device *dev)
  120. {
  121. struct sprd_iommu_domain *dom;
  122. dom = kzalloc(sizeof(*dom), GFP_KERNEL);
  123. if (!dom)
  124. return NULL;
  125. spin_lock_init(&dom->pgtlock);
  126. dom->domain.geometry.aperture_start = 0;
  127. dom->domain.geometry.aperture_end = SZ_256M - 1;
  128. dom->domain.geometry.force_aperture = true;
  129. return &dom->domain;
  130. }
  131. static void sprd_iommu_first_vpn(struct sprd_iommu_domain *dom)
  132. {
  133. struct sprd_iommu_device *sdev = dom->sdev;
  134. u32 val;
  135. unsigned int reg;
  136. if (sdev->ver == SPRD_IOMMU_EX)
  137. reg = SPRD_EX_FIRST_VPN;
  138. else
  139. reg = SPRD_VAU_FIRST_VPN;
  140. val = dom->domain.geometry.aperture_start >> SPRD_IOMMU_PAGE_SHIFT;
  141. sprd_iommu_write(sdev, reg, val);
  142. }
  143. static void sprd_iommu_vpn_range(struct sprd_iommu_domain *dom)
  144. {
  145. struct sprd_iommu_device *sdev = dom->sdev;
  146. u32 val;
  147. unsigned int reg;
  148. if (sdev->ver == SPRD_IOMMU_EX)
  149. reg = SPRD_EX_VPN_RANGE;
  150. else
  151. reg = SPRD_VAU_VPN_RANGE;
  152. val = (dom->domain.geometry.aperture_end -
  153. dom->domain.geometry.aperture_start) >> SPRD_IOMMU_PAGE_SHIFT;
  154. sprd_iommu_write(sdev, reg, val);
  155. }
  156. static void sprd_iommu_first_ppn(struct sprd_iommu_domain *dom)
  157. {
  158. u32 val = dom->pgt_pa >> SPRD_IOMMU_PAGE_SHIFT;
  159. struct sprd_iommu_device *sdev = dom->sdev;
  160. unsigned int reg;
  161. if (sdev->ver == SPRD_IOMMU_EX)
  162. reg = SPRD_EX_FIRST_PPN;
  163. else
  164. reg = SPRD_VAU_FIRST_PPN;
  165. sprd_iommu_write(sdev, reg, val);
  166. }
  167. static void sprd_iommu_default_ppn(struct sprd_iommu_device *sdev)
  168. {
  169. u32 val = sdev->prot_page_pa >> SPRD_IOMMU_PAGE_SHIFT;
  170. if (sdev->ver == SPRD_IOMMU_EX) {
  171. sprd_iommu_write(sdev, SPRD_EX_DEFAULT_PPN, val);
  172. } else if (sdev->ver == SPRD_IOMMU_VAU) {
  173. sprd_iommu_write(sdev, SPRD_VAU_DEFAULT_PPN_RD, val);
  174. sprd_iommu_write(sdev, SPRD_VAU_DEFAULT_PPN_WR, val);
  175. }
  176. }
  177. static void sprd_iommu_hw_en(struct sprd_iommu_device *sdev, bool en)
  178. {
  179. unsigned int reg_cfg;
  180. u32 mask, val;
  181. if (sdev->ver == SPRD_IOMMU_EX)
  182. reg_cfg = SPRD_EX_CFG;
  183. else
  184. reg_cfg = SPRD_VAU_CFG;
  185. mask = SPRD_IOMMU_EN | SPRD_IOMMU_GATE_EN;
  186. val = en ? mask : 0;
  187. sprd_iommu_update_bits(sdev, reg_cfg, mask, 0, val);
  188. }
  189. static void sprd_iommu_cleanup(struct sprd_iommu_domain *dom)
  190. {
  191. size_t pgt_size;
  192. /* Nothing need to do if the domain hasn't been attached */
  193. if (!dom->sdev)
  194. return;
  195. pgt_size = sprd_iommu_pgt_size(&dom->domain);
  196. dma_free_coherent(dom->sdev->dev, pgt_size, dom->pgt_va, dom->pgt_pa);
  197. sprd_iommu_hw_en(dom->sdev, false);
  198. dom->sdev = NULL;
  199. }
  200. static void sprd_iommu_domain_free(struct iommu_domain *domain)
  201. {
  202. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  203. sprd_iommu_cleanup(dom);
  204. kfree(dom);
  205. }
  206. static int sprd_iommu_attach_device(struct iommu_domain *domain,
  207. struct device *dev)
  208. {
  209. struct sprd_iommu_device *sdev = dev_iommu_priv_get(dev);
  210. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  211. size_t pgt_size = sprd_iommu_pgt_size(domain);
  212. /* The device is attached to this domain */
  213. if (sdev->dom == dom)
  214. return 0;
  215. /* The first time that domain is attaching to a device */
  216. if (!dom->pgt_va) {
  217. dom->pgt_va = dma_alloc_coherent(sdev->dev, pgt_size, &dom->pgt_pa, GFP_KERNEL);
  218. if (!dom->pgt_va)
  219. return -ENOMEM;
  220. dom->sdev = sdev;
  221. }
  222. sdev->dom = dom;
  223. /*
  224. * One sprd IOMMU serves one client device only, disabled it before
  225. * configure mapping table to avoid access conflict in case other
  226. * mapping table is stored in.
  227. */
  228. sprd_iommu_hw_en(sdev, false);
  229. sprd_iommu_first_ppn(dom);
  230. sprd_iommu_first_vpn(dom);
  231. sprd_iommu_vpn_range(dom);
  232. sprd_iommu_default_ppn(sdev);
  233. sprd_iommu_hw_en(sdev, true);
  234. return 0;
  235. }
  236. static int sprd_iommu_map(struct iommu_domain *domain, unsigned long iova,
  237. phys_addr_t paddr, size_t pgsize, size_t pgcount,
  238. int prot, gfp_t gfp, size_t *mapped)
  239. {
  240. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  241. size_t size = pgcount * SPRD_IOMMU_PAGE_SIZE;
  242. unsigned long flags;
  243. unsigned int i;
  244. u32 *pgt_base_iova;
  245. u32 pabase = (u32)paddr;
  246. unsigned long start = domain->geometry.aperture_start;
  247. unsigned long end = domain->geometry.aperture_end;
  248. if (!dom->sdev) {
  249. pr_err("No sprd_iommu_device attached to the domain\n");
  250. return -EINVAL;
  251. }
  252. if (iova < start || (iova + size) > (end + 1)) {
  253. dev_err(dom->sdev->dev, "(iova(0x%lx) + size(%zx)) are not in the range!\n",
  254. iova, size);
  255. return -EINVAL;
  256. }
  257. pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT);
  258. spin_lock_irqsave(&dom->pgtlock, flags);
  259. for (i = 0; i < pgcount; i++) {
  260. pgt_base_iova[i] = pabase >> SPRD_IOMMU_PAGE_SHIFT;
  261. pabase += SPRD_IOMMU_PAGE_SIZE;
  262. }
  263. spin_unlock_irqrestore(&dom->pgtlock, flags);
  264. *mapped = size;
  265. return 0;
  266. }
  267. static size_t sprd_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
  268. size_t pgsize, size_t pgcount,
  269. struct iommu_iotlb_gather *iotlb_gather)
  270. {
  271. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  272. unsigned long flags;
  273. u32 *pgt_base_iova;
  274. size_t size = pgcount * SPRD_IOMMU_PAGE_SIZE;
  275. unsigned long start = domain->geometry.aperture_start;
  276. unsigned long end = domain->geometry.aperture_end;
  277. if (iova < start || (iova + size) > (end + 1))
  278. return 0;
  279. pgt_base_iova = dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT);
  280. spin_lock_irqsave(&dom->pgtlock, flags);
  281. memset(pgt_base_iova, 0, pgcount * sizeof(u32));
  282. spin_unlock_irqrestore(&dom->pgtlock, flags);
  283. return size;
  284. }
  285. static int sprd_iommu_sync_map(struct iommu_domain *domain,
  286. unsigned long iova, size_t size)
  287. {
  288. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  289. unsigned int reg;
  290. if (dom->sdev->ver == SPRD_IOMMU_EX)
  291. reg = SPRD_EX_UPDATE;
  292. else
  293. reg = SPRD_VAU_UPDATE;
  294. /* clear IOMMU TLB buffer after page table updated */
  295. sprd_iommu_write(dom->sdev, reg, 0xffffffff);
  296. return 0;
  297. }
  298. static void sprd_iommu_sync(struct iommu_domain *domain,
  299. struct iommu_iotlb_gather *iotlb_gather)
  300. {
  301. sprd_iommu_sync_map(domain, 0, 0);
  302. }
  303. static phys_addr_t sprd_iommu_iova_to_phys(struct iommu_domain *domain,
  304. dma_addr_t iova)
  305. {
  306. struct sprd_iommu_domain *dom = to_sprd_domain(domain);
  307. unsigned long flags;
  308. phys_addr_t pa;
  309. unsigned long start = domain->geometry.aperture_start;
  310. unsigned long end = domain->geometry.aperture_end;
  311. if (WARN_ON(iova < start || iova > end))
  312. return 0;
  313. spin_lock_irqsave(&dom->pgtlock, flags);
  314. pa = *(dom->pgt_va + ((iova - start) >> SPRD_IOMMU_PAGE_SHIFT));
  315. pa = (pa << SPRD_IOMMU_PAGE_SHIFT) + ((iova - start) & (SPRD_IOMMU_PAGE_SIZE - 1));
  316. spin_unlock_irqrestore(&dom->pgtlock, flags);
  317. return pa;
  318. }
  319. static struct iommu_device *sprd_iommu_probe_device(struct device *dev)
  320. {
  321. struct sprd_iommu_device *sdev = dev_iommu_priv_get(dev);
  322. return &sdev->iommu;
  323. }
  324. static int sprd_iommu_of_xlate(struct device *dev,
  325. const struct of_phandle_args *args)
  326. {
  327. struct platform_device *pdev;
  328. if (!dev_iommu_priv_get(dev)) {
  329. pdev = of_find_device_by_node(args->np);
  330. dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
  331. platform_device_put(pdev);
  332. }
  333. return 0;
  334. }
  335. static const struct iommu_ops sprd_iommu_ops = {
  336. .domain_alloc_paging = sprd_iommu_domain_alloc_paging,
  337. .probe_device = sprd_iommu_probe_device,
  338. .device_group = generic_single_device_group,
  339. .of_xlate = sprd_iommu_of_xlate,
  340. .pgsize_bitmap = SPRD_IOMMU_PAGE_SIZE,
  341. .owner = THIS_MODULE,
  342. .default_domain_ops = &(const struct iommu_domain_ops) {
  343. .attach_dev = sprd_iommu_attach_device,
  344. .map_pages = sprd_iommu_map,
  345. .unmap_pages = sprd_iommu_unmap,
  346. .iotlb_sync_map = sprd_iommu_sync_map,
  347. .iotlb_sync = sprd_iommu_sync,
  348. .iova_to_phys = sprd_iommu_iova_to_phys,
  349. .free = sprd_iommu_domain_free,
  350. }
  351. };
  352. static const struct of_device_id sprd_iommu_of_match[] = {
  353. { .compatible = "sprd,iommu-v1" },
  354. { },
  355. };
  356. MODULE_DEVICE_TABLE(of, sprd_iommu_of_match);
  357. /*
  358. * Clock is not required, access to some of IOMMUs is controlled by gate
  359. * clk, enabled clocks for that kind of IOMMUs before accessing.
  360. * Return 0 for success or no clocks found.
  361. */
  362. static int sprd_iommu_clk_enable(struct sprd_iommu_device *sdev)
  363. {
  364. struct clk *eb;
  365. eb = devm_clk_get_optional(sdev->dev, NULL);
  366. if (!eb)
  367. return 0;
  368. if (IS_ERR(eb))
  369. return PTR_ERR(eb);
  370. sdev->eb = eb;
  371. return clk_prepare_enable(eb);
  372. }
  373. static void sprd_iommu_clk_disable(struct sprd_iommu_device *sdev)
  374. {
  375. if (sdev->eb)
  376. clk_disable_unprepare(sdev->eb);
  377. }
  378. static int sprd_iommu_probe(struct platform_device *pdev)
  379. {
  380. struct sprd_iommu_device *sdev;
  381. struct device *dev = &pdev->dev;
  382. void __iomem *base;
  383. int ret;
  384. sdev = devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL);
  385. if (!sdev)
  386. return -ENOMEM;
  387. base = devm_platform_ioremap_resource(pdev, 0);
  388. if (IS_ERR(base)) {
  389. dev_err(dev, "Failed to get ioremap resource.\n");
  390. return PTR_ERR(base);
  391. }
  392. sdev->base = base;
  393. sdev->prot_page_va = dma_alloc_coherent(dev, SPRD_IOMMU_PAGE_SIZE,
  394. &sdev->prot_page_pa, GFP_KERNEL);
  395. if (!sdev->prot_page_va)
  396. return -ENOMEM;
  397. platform_set_drvdata(pdev, sdev);
  398. sdev->dev = dev;
  399. ret = iommu_device_sysfs_add(&sdev->iommu, dev, NULL, dev_name(dev));
  400. if (ret)
  401. goto free_page;
  402. ret = iommu_device_register(&sdev->iommu, &sprd_iommu_ops, dev);
  403. if (ret)
  404. goto remove_sysfs;
  405. ret = sprd_iommu_clk_enable(sdev);
  406. if (ret)
  407. goto unregister_iommu;
  408. ret = sprd_iommu_get_version(sdev);
  409. if (ret < 0) {
  410. dev_err(dev, "IOMMU version(%d) is invalid.\n", ret);
  411. goto disable_clk;
  412. }
  413. sdev->ver = ret;
  414. return 0;
  415. disable_clk:
  416. sprd_iommu_clk_disable(sdev);
  417. unregister_iommu:
  418. iommu_device_unregister(&sdev->iommu);
  419. remove_sysfs:
  420. iommu_device_sysfs_remove(&sdev->iommu);
  421. free_page:
  422. dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa);
  423. return ret;
  424. }
  425. static void sprd_iommu_remove(struct platform_device *pdev)
  426. {
  427. struct sprd_iommu_device *sdev = platform_get_drvdata(pdev);
  428. dma_free_coherent(sdev->dev, SPRD_IOMMU_PAGE_SIZE, sdev->prot_page_va, sdev->prot_page_pa);
  429. platform_set_drvdata(pdev, NULL);
  430. iommu_device_sysfs_remove(&sdev->iommu);
  431. iommu_device_unregister(&sdev->iommu);
  432. }
  433. static struct platform_driver sprd_iommu_driver = {
  434. .driver = {
  435. .name = "sprd-iommu",
  436. .of_match_table = sprd_iommu_of_match,
  437. .suppress_bind_attrs = true,
  438. },
  439. .probe = sprd_iommu_probe,
  440. .remove_new = sprd_iommu_remove,
  441. };
  442. module_platform_driver(sprd_iommu_driver);
  443. MODULE_DESCRIPTION("IOMMU driver for Unisoc SoCs");
  444. MODULE_ALIAS("platform:sprd-iommu");
  445. MODULE_LICENSE("GPL");