dma.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2011 Texas Instruments Incorporated
  3. * Author: Mark Salter <msalter@redhat.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/module.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/mm.h>
  12. #include <linux/mm_types.h>
  13. #include <linux/scatterlist.h>
  14. #include <asm/cacheflush.h>
  15. static void c6x_dma_sync(dma_addr_t handle, size_t size,
  16. enum dma_data_direction dir)
  17. {
  18. unsigned long paddr = handle;
  19. BUG_ON(!valid_dma_direction(dir));
  20. switch (dir) {
  21. case DMA_FROM_DEVICE:
  22. L2_cache_block_invalidate(paddr, paddr + size);
  23. break;
  24. case DMA_TO_DEVICE:
  25. L2_cache_block_writeback(paddr, paddr + size);
  26. break;
  27. case DMA_BIDIRECTIONAL:
  28. L2_cache_block_writeback_invalidate(paddr, paddr + size);
  29. break;
  30. default:
  31. break;
  32. }
  33. }
  34. dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
  35. enum dma_data_direction dir)
  36. {
  37. dma_addr_t addr = virt_to_phys(ptr);
  38. c6x_dma_sync(addr, size, dir);
  39. debug_dma_map_page(dev, virt_to_page(ptr),
  40. (unsigned long)ptr & ~PAGE_MASK, size,
  41. dir, addr, true);
  42. return addr;
  43. }
  44. EXPORT_SYMBOL(dma_map_single);
  45. void dma_unmap_single(struct device *dev, dma_addr_t handle,
  46. size_t size, enum dma_data_direction dir)
  47. {
  48. c6x_dma_sync(handle, size, dir);
  49. debug_dma_unmap_page(dev, handle, size, dir, true);
  50. }
  51. EXPORT_SYMBOL(dma_unmap_single);
  52. int dma_map_sg(struct device *dev, struct scatterlist *sglist,
  53. int nents, enum dma_data_direction dir)
  54. {
  55. struct scatterlist *sg;
  56. int i;
  57. for_each_sg(sglist, sg, nents, i)
  58. sg->dma_address = dma_map_single(dev, sg_virt(sg), sg->length,
  59. dir);
  60. debug_dma_map_sg(dev, sglist, nents, nents, dir);
  61. return nents;
  62. }
  63. EXPORT_SYMBOL(dma_map_sg);
  64. void dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
  65. int nents, enum dma_data_direction dir)
  66. {
  67. struct scatterlist *sg;
  68. int i;
  69. for_each_sg(sglist, sg, nents, i)
  70. dma_unmap_single(dev, sg_dma_address(sg), sg->length, dir);
  71. debug_dma_unmap_sg(dev, sglist, nents, dir);
  72. }
  73. EXPORT_SYMBOL(dma_unmap_sg);
  74. void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
  75. size_t size, enum dma_data_direction dir)
  76. {
  77. c6x_dma_sync(handle, size, dir);
  78. debug_dma_sync_single_for_cpu(dev, handle, size, dir);
  79. }
  80. EXPORT_SYMBOL(dma_sync_single_for_cpu);
  81. void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
  82. size_t size, enum dma_data_direction dir)
  83. {
  84. c6x_dma_sync(handle, size, dir);
  85. debug_dma_sync_single_for_device(dev, handle, size, dir);
  86. }
  87. EXPORT_SYMBOL(dma_sync_single_for_device);
  88. void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
  89. int nents, enum dma_data_direction dir)
  90. {
  91. struct scatterlist *sg;
  92. int i;
  93. for_each_sg(sglist, sg, nents, i)
  94. dma_sync_single_for_cpu(dev, sg_dma_address(sg),
  95. sg->length, dir);
  96. debug_dma_sync_sg_for_cpu(dev, sglist, nents, dir);
  97. }
  98. EXPORT_SYMBOL(dma_sync_sg_for_cpu);
  99. void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
  100. int nents, enum dma_data_direction dir)
  101. {
  102. struct scatterlist *sg;
  103. int i;
  104. for_each_sg(sglist, sg, nents, i)
  105. dma_sync_single_for_device(dev, sg_dma_address(sg),
  106. sg->length, dir);
  107. debug_dma_sync_sg_for_device(dev, sglist, nents, dir);
  108. }
  109. EXPORT_SYMBOL(dma_sync_sg_for_device);
  110. /* Number of entries preallocated for DMA-API debugging */
  111. #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
  112. static int __init dma_init(void)
  113. {
  114. dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
  115. return 0;
  116. }
  117. fs_initcall(dma_init);