dma-swiotlb.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Contains routines needed to support swiotlb for ppc.
  3. *
  4. * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version.
  10. *
  11. */
  12. #include <linux/dma-mapping.h>
  13. #include <linux/pfn.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/pci.h>
  17. #include <asm/machdep.h>
  18. #include <asm/swiotlb.h>
  19. #include <asm/dma.h>
  20. #include <asm/abs_addr.h>
  21. int swiotlb __read_mostly;
  22. unsigned int ppc_swiotlb_enable;
  23. dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
  24. {
  25. return paddr + get_dma_direct_offset(hwdev);
  26. }
  27. phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
  28. {
  29. return baddr - get_dma_direct_offset(hwdev);
  30. }
  31. /*
  32. * Determine if an address is reachable by a pci device, or if we must bounce.
  33. */
  34. static int
  35. swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
  36. {
  37. dma_addr_t max;
  38. struct pci_controller *hose;
  39. struct pci_dev *pdev = to_pci_dev(hwdev);
  40. hose = pci_bus_to_host(pdev->bus);
  41. max = hose->dma_window_base_cur + hose->dma_window_size;
  42. /* check that we're within mapped pci window space */
  43. if ((addr + size > max) | (addr < hose->dma_window_base_cur))
  44. return 1;
  45. return 0;
  46. }
  47. /*
  48. * At the moment, all platforms that use this code only require
  49. * swiotlb to be used if we're operating on HIGHMEM. Since
  50. * we don't ever call anything other than map_sg, unmap_sg,
  51. * map_page, and unmap_page on highmem, use normal dma_ops
  52. * for everything else.
  53. */
  54. struct dma_mapping_ops swiotlb_dma_ops = {
  55. .alloc_coherent = dma_direct_alloc_coherent,
  56. .free_coherent = dma_direct_free_coherent,
  57. .map_sg = swiotlb_map_sg_attrs,
  58. .unmap_sg = swiotlb_unmap_sg_attrs,
  59. .dma_supported = swiotlb_dma_supported,
  60. .map_page = swiotlb_map_page,
  61. .unmap_page = swiotlb_unmap_page,
  62. .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
  63. .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
  64. .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
  65. .sync_sg_for_device = swiotlb_sync_sg_for_device
  66. };
  67. struct dma_mapping_ops swiotlb_pci_dma_ops = {
  68. .alloc_coherent = dma_direct_alloc_coherent,
  69. .free_coherent = dma_direct_free_coherent,
  70. .map_sg = swiotlb_map_sg_attrs,
  71. .unmap_sg = swiotlb_unmap_sg_attrs,
  72. .dma_supported = swiotlb_dma_supported,
  73. .map_page = swiotlb_map_page,
  74. .unmap_page = swiotlb_unmap_page,
  75. .addr_needs_map = swiotlb_pci_addr_needs_map,
  76. .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
  77. .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
  78. .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
  79. .sync_sg_for_device = swiotlb_sync_sg_for_device
  80. };
  81. static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
  82. unsigned long action, void *data)
  83. {
  84. struct device *dev = data;
  85. /* We are only intereted in device addition */
  86. if (action != BUS_NOTIFY_ADD_DEVICE)
  87. return 0;
  88. /* May need to bounce if the device can't address all of DRAM */
  89. if (dma_get_mask(dev) < lmb_end_of_DRAM())
  90. set_dma_ops(dev, &swiotlb_dma_ops);
  91. return NOTIFY_DONE;
  92. }
  93. static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
  94. .notifier_call = ppc_swiotlb_bus_notify,
  95. .priority = 0,
  96. };
  97. static struct notifier_block ppc_swiotlb_of_bus_notifier = {
  98. .notifier_call = ppc_swiotlb_bus_notify,
  99. .priority = 0,
  100. };
  101. int __init swiotlb_setup_bus_notifier(void)
  102. {
  103. bus_register_notifier(&platform_bus_type,
  104. &ppc_swiotlb_plat_bus_notifier);
  105. bus_register_notifier(&of_platform_bus_type,
  106. &ppc_swiotlb_of_bus_notifier);
  107. return 0;
  108. }