dma-swiotlb.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/mm.h>
  3. #include <linux/init.h>
  4. #include <linux/dma-mapping.h>
  5. #include <linux/scatterlist.h>
  6. #include <linux/swiotlb.h>
  7. #include <linux/bootmem.h>
  8. #include <asm/bootinfo.h>
  9. #include <boot_param.h>
  10. #include <dma-coherence.h>
  11. static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
  12. dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
  13. {
  14. void *ret = swiotlb_alloc(dev, size, dma_handle, gfp, attrs);
  15. mb();
  16. return ret;
  17. }
  18. static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
  19. unsigned long offset, size_t size,
  20. enum dma_data_direction dir,
  21. unsigned long attrs)
  22. {
  23. dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
  24. dir, attrs);
  25. mb();
  26. return daddr;
  27. }
  28. static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
  29. int nents, enum dma_data_direction dir,
  30. unsigned long attrs)
  31. {
  32. int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, attrs);
  33. mb();
  34. return r;
  35. }
  36. static void loongson_dma_sync_single_for_device(struct device *dev,
  37. dma_addr_t dma_handle, size_t size,
  38. enum dma_data_direction dir)
  39. {
  40. swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
  41. mb();
  42. }
  43. static void loongson_dma_sync_sg_for_device(struct device *dev,
  44. struct scatterlist *sg, int nents,
  45. enum dma_data_direction dir)
  46. {
  47. swiotlb_sync_sg_for_device(dev, sg, nents, dir);
  48. mb();
  49. }
  50. dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
  51. {
  52. long nid;
  53. #ifdef CONFIG_PHYS48_TO_HT40
  54. /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
  55. * Loongson-3's 48bit address space and embed it into 40bit */
  56. nid = (paddr >> 44) & 0x3;
  57. paddr = ((nid << 44) ^ paddr) | (nid << 37);
  58. #endif
  59. return paddr;
  60. }
  61. phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
  62. {
  63. long nid;
  64. #ifdef CONFIG_PHYS48_TO_HT40
  65. /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
  66. * Loongson-3's 48bit address space and embed it into 40bit */
  67. nid = (daddr >> 37) & 0x3;
  68. daddr = ((nid << 37) ^ daddr) | (nid << 44);
  69. #endif
  70. return daddr;
  71. }
  72. static const struct dma_map_ops loongson_dma_map_ops = {
  73. .alloc = loongson_dma_alloc_coherent,
  74. .free = swiotlb_free,
  75. .map_page = loongson_dma_map_page,
  76. .unmap_page = swiotlb_unmap_page,
  77. .map_sg = loongson_dma_map_sg,
  78. .unmap_sg = swiotlb_unmap_sg_attrs,
  79. .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
  80. .sync_single_for_device = loongson_dma_sync_single_for_device,
  81. .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
  82. .sync_sg_for_device = loongson_dma_sync_sg_for_device,
  83. .mapping_error = swiotlb_dma_mapping_error,
  84. .dma_supported = swiotlb_dma_supported,
  85. };
  86. void __init plat_swiotlb_setup(void)
  87. {
  88. swiotlb_init(1);
  89. mips_dma_map_ops = &loongson_dma_map_ops;
  90. }