pvr_vm_mips.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #include "pvr_device.h"
  4. #include "pvr_fw_mips.h"
  5. #include "pvr_gem.h"
  6. #include "pvr_mmu.h"
  7. #include "pvr_rogue_mips.h"
  8. #include "pvr_vm.h"
  9. #include "pvr_vm_mips.h"
  10. #include <drm/drm_managed.h>
  11. #include <linux/dma-mapping.h>
  12. #include <linux/err.h>
  13. #include <linux/slab.h>
  14. #include <linux/types.h>
  15. #include <linux/vmalloc.h>
  16. /**
  17. * pvr_vm_mips_init() - Initialise MIPS FW pagetable
  18. * @pvr_dev: Target PowerVR device.
  19. *
  20. * Returns:
  21. * * 0 on success,
  22. * * -%EINVAL,
  23. * * Any error returned by pvr_gem_object_create(), or
  24. * * And error returned by pvr_gem_object_vmap().
  25. */
  26. int
  27. pvr_vm_mips_init(struct pvr_device *pvr_dev)
  28. {
  29. u32 pt_size = 1 << ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
  30. struct device *dev = from_pvr_device(pvr_dev)->dev;
  31. struct pvr_fw_mips_data *mips_data;
  32. u32 phys_bus_width;
  33. int page_nr;
  34. int err;
  35. /* Page table size must be at most ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * 4k pages. */
  36. if (pt_size > ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * SZ_4K)
  37. return -EINVAL;
  38. if (PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width))
  39. return -EINVAL;
  40. mips_data = drmm_kzalloc(from_pvr_device(pvr_dev), sizeof(*mips_data), GFP_KERNEL);
  41. if (!mips_data)
  42. return -ENOMEM;
  43. for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) {
  44. mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
  45. if (!mips_data->pt_pages[page_nr]) {
  46. err = -ENOMEM;
  47. goto err_free_pages;
  48. }
  49. mips_data->pt_dma_addr[page_nr] = dma_map_page(dev, mips_data->pt_pages[page_nr], 0,
  50. PAGE_SIZE, DMA_TO_DEVICE);
  51. if (dma_mapping_error(dev, mips_data->pt_dma_addr[page_nr])) {
  52. err = -ENOMEM;
  53. __free_page(mips_data->pt_pages[page_nr]);
  54. goto err_free_pages;
  55. }
  56. }
  57. mips_data->pt = vmap(mips_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
  58. pgprot_writecombine(PAGE_KERNEL));
  59. if (!mips_data->pt) {
  60. err = -ENOMEM;
  61. goto err_free_pages;
  62. }
  63. mips_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
  64. ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
  65. mips_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
  66. ROGUE_MIPSFW_CACHED_POLICY;
  67. pvr_dev->fw_dev.processor_data.mips_data = mips_data;
  68. return 0;
  69. err_free_pages:
  70. while (--page_nr >= 0) {
  71. dma_unmap_page(from_pvr_device(pvr_dev)->dev,
  72. mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
  73. __free_page(mips_data->pt_pages[page_nr]);
  74. }
  75. return err;
  76. }
  77. /**
  78. * pvr_vm_mips_fini() - Release MIPS FW pagetable
  79. * @pvr_dev: Target PowerVR device.
  80. */
  81. void
  82. pvr_vm_mips_fini(struct pvr_device *pvr_dev)
  83. {
  84. struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
  85. struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
  86. int page_nr;
  87. vunmap(mips_data->pt);
  88. for (page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) {
  89. dma_unmap_page(from_pvr_device(pvr_dev)->dev,
  90. mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
  91. __free_page(mips_data->pt_pages[page_nr]);
  92. }
  93. fw_dev->processor_data.mips_data = NULL;
  94. }
  95. static u32
  96. get_mips_pte_flags(bool read, bool write, u32 cache_policy)
  97. {
  98. u32 flags = 0;
  99. if (read && write) /* Read/write. */
  100. flags |= ROGUE_MIPSFW_ENTRYLO_DIRTY_EN;
  101. else if (write) /* Write only. */
  102. flags |= ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
  103. else
  104. WARN_ON(!read);
  105. flags |= cache_policy << ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
  106. flags |= ROGUE_MIPSFW_ENTRYLO_VALID_EN | ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN;
  107. return flags;
  108. }
  109. /**
  110. * pvr_vm_mips_map() - Map a FW object into MIPS address space
  111. * @pvr_dev: Target PowerVR device.
  112. * @fw_obj: FW object to map.
  113. *
  114. * Returns:
  115. * * 0 on success,
  116. * * -%EINVAL if object does not reside within FW address space, or
  117. * * Any error returned by pvr_fw_object_get_dma_addr().
  118. */
  119. int
  120. pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
  121. {
  122. struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
  123. struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
  124. struct pvr_gem_object *pvr_obj = fw_obj->gem;
  125. const u64 start = fw_obj->fw_mm_node.start;
  126. const u64 size = fw_obj->fw_mm_node.size;
  127. u64 end;
  128. u32 cache_policy;
  129. u32 pte_flags;
  130. s32 start_pfn;
  131. s32 end_pfn;
  132. s32 pfn;
  133. int err;
  134. if (check_add_overflow(start, size - 1, &end))
  135. return -EINVAL;
  136. if (start < ROGUE_FW_HEAP_BASE ||
  137. start >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
  138. end < ROGUE_FW_HEAP_BASE ||
  139. end >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
  140. (start & ROGUE_MIPSFW_PAGE_MASK_4K) ||
  141. ((end + 1) & ROGUE_MIPSFW_PAGE_MASK_4K))
  142. return -EINVAL;
  143. start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
  144. end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
  145. if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
  146. cache_policy = ROGUE_MIPSFW_UNCACHED_CACHE_POLICY;
  147. else
  148. cache_policy = mips_data->cache_policy;
  149. pte_flags = get_mips_pte_flags(true, true, cache_policy);
  150. for (pfn = start_pfn; pfn <= end_pfn; pfn++) {
  151. dma_addr_t dma_addr;
  152. u32 pte;
  153. err = pvr_fw_object_get_dma_addr(fw_obj,
  154. (pfn - start_pfn) <<
  155. ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K,
  156. &dma_addr);
  157. if (err)
  158. goto err_unmap_pages;
  159. pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
  160. << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & mips_data->pfn_mask;
  161. pte |= pte_flags;
  162. WRITE_ONCE(mips_data->pt[pfn], pte);
  163. }
  164. pvr_mmu_flush_request_all(pvr_dev);
  165. return 0;
  166. err_unmap_pages:
  167. while (--pfn >= start_pfn)
  168. WRITE_ONCE(mips_data->pt[pfn], 0);
  169. pvr_mmu_flush_request_all(pvr_dev);
  170. WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
  171. return err;
  172. }
  173. /**
  174. * pvr_vm_mips_unmap() - Unmap a FW object into MIPS address space
  175. * @pvr_dev: Target PowerVR device.
  176. * @fw_obj: FW object to unmap.
  177. */
  178. void
  179. pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
  180. {
  181. struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
  182. struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
  183. const u64 start = fw_obj->fw_mm_node.start;
  184. const u64 size = fw_obj->fw_mm_node.size;
  185. const u64 end = start + size;
  186. const u32 start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >>
  187. ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
  188. const u32 end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >>
  189. ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
  190. for (u32 pfn = start_pfn; pfn < end_pfn; pfn++)
  191. WRITE_ONCE(mips_data->pt[pfn], 0);
  192. pvr_mmu_flush_request_all(pvr_dev);
  193. WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
  194. }