2 * Copyright (C) 2011 Texas Instruments Incorporated
3 * Author: Mark Salter <msalter@redhat.com>
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.
9 #include <linux/module.h>
10 #include <linux/dma-mapping.h>
12 #include <linux/mm_types.h>
13 #include <linux/scatterlist.h>
15 #include <asm/cacheflush.h>
17 static void c6x_dma_sync(dma_addr_t handle
, size_t size
,
18 enum dma_data_direction dir
)
20 unsigned long paddr
= handle
;
22 BUG_ON(!valid_dma_direction(dir
));
26 L2_cache_block_invalidate(paddr
, paddr
+ size
);
29 L2_cache_block_writeback(paddr
, paddr
+ size
);
31 case DMA_BIDIRECTIONAL
:
32 L2_cache_block_writeback_invalidate(paddr
, paddr
+ size
);
39 static dma_addr_t
c6x_dma_map_page(struct device
*dev
, struct page
*page
,
40 unsigned long offset
, size_t size
, enum dma_data_direction dir
,
43 dma_addr_t handle
= virt_to_phys(page_address(page
) + offset
);
45 c6x_dma_sync(handle
, size
, dir
);
49 static void c6x_dma_unmap_page(struct device
*dev
, dma_addr_t handle
,
50 size_t size
, enum dma_data_direction dir
, unsigned long attrs
)
52 c6x_dma_sync(handle
, size
, dir
);
55 static int c6x_dma_map_sg(struct device
*dev
, struct scatterlist
*sglist
,
56 int nents
, enum dma_data_direction dir
, unsigned long attrs
)
58 struct scatterlist
*sg
;
61 for_each_sg(sglist
, sg
, nents
, i
) {
62 sg
->dma_address
= sg_phys(sg
);
63 c6x_dma_sync(sg
->dma_address
, sg
->length
, dir
);
69 static void c6x_dma_unmap_sg(struct device
*dev
, struct scatterlist
*sglist
,
70 int nents
, enum dma_data_direction dir
, unsigned long attrs
)
72 struct scatterlist
*sg
;
75 for_each_sg(sglist
, sg
, nents
, i
)
76 c6x_dma_sync(sg_dma_address(sg
), sg
->length
, dir
);
80 static void c6x_dma_sync_single_for_cpu(struct device
*dev
, dma_addr_t handle
,
81 size_t size
, enum dma_data_direction dir
)
83 c6x_dma_sync(handle
, size
, dir
);
87 static void c6x_dma_sync_single_for_device(struct device
*dev
,
88 dma_addr_t handle
, size_t size
, enum dma_data_direction dir
)
90 c6x_dma_sync(handle
, size
, dir
);
94 static void c6x_dma_sync_sg_for_cpu(struct device
*dev
,
95 struct scatterlist
*sglist
, int nents
,
96 enum dma_data_direction dir
)
98 struct scatterlist
*sg
;
101 for_each_sg(sglist
, sg
, nents
, i
)
102 c6x_dma_sync_single_for_cpu(dev
, sg_dma_address(sg
),
107 static void c6x_dma_sync_sg_for_device(struct device
*dev
,
108 struct scatterlist
*sglist
, int nents
,
109 enum dma_data_direction dir
)
111 struct scatterlist
*sg
;
114 for_each_sg(sglist
, sg
, nents
, i
)
115 c6x_dma_sync_single_for_device(dev
, sg_dma_address(sg
),
120 struct dma_map_ops c6x_dma_ops
= {
121 .alloc
= c6x_dma_alloc
,
122 .free
= c6x_dma_free
,
123 .map_page
= c6x_dma_map_page
,
124 .unmap_page
= c6x_dma_unmap_page
,
125 .map_sg
= c6x_dma_map_sg
,
126 .unmap_sg
= c6x_dma_unmap_sg
,
127 .sync_single_for_device
= c6x_dma_sync_single_for_device
,
128 .sync_single_for_cpu
= c6x_dma_sync_single_for_cpu
,
129 .sync_sg_for_device
= c6x_dma_sync_sg_for_device
,
130 .sync_sg_for_cpu
= c6x_dma_sync_sg_for_cpu
,
132 EXPORT_SYMBOL(c6x_dma_ops
);
134 /* Number of entries preallocated for DMA-API debugging */
135 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
137 static int __init
dma_init(void)
139 dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES
);
143 fs_initcall(dma_init
);