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
,
41 struct dma_attrs
*attrs
)
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
, struct dma_attrs
*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
, struct dma_attrs
*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
,
71 struct dma_attrs
*attrs
)
73 struct scatterlist
*sg
;
76 for_each_sg(sglist
, sg
, nents
, i
)
77 c6x_dma_sync(sg_dma_address(sg
), sg
->length
, dir
);
81 static void c6x_dma_sync_single_for_cpu(struct device
*dev
, dma_addr_t handle
,
82 size_t size
, enum dma_data_direction dir
)
84 c6x_dma_sync(handle
, size
, dir
);
88 static void c6x_dma_sync_single_for_device(struct device
*dev
,
89 dma_addr_t handle
, size_t size
, enum dma_data_direction dir
)
91 c6x_dma_sync(handle
, size
, dir
);
95 static void c6x_dma_sync_sg_for_cpu(struct device
*dev
,
96 struct scatterlist
*sglist
, int nents
,
97 enum dma_data_direction dir
)
99 struct scatterlist
*sg
;
102 for_each_sg(sglist
, sg
, nents
, i
)
103 c6x_dma_sync_single_for_cpu(dev
, sg_dma_address(sg
),
108 static void c6x_dma_sync_sg_for_device(struct device
*dev
,
109 struct scatterlist
*sglist
, int nents
,
110 enum dma_data_direction dir
)
112 struct scatterlist
*sg
;
115 for_each_sg(sglist
, sg
, nents
, i
)
116 c6x_dma_sync_single_for_device(dev
, sg_dma_address(sg
),
121 struct dma_map_ops c6x_dma_ops
= {
122 .alloc
= c6x_dma_alloc
,
123 .free
= c6x_dma_free
,
124 .map_page
= c6x_dma_map_page
,
125 .unmap_page
= c6x_dma_unmap_page
,
126 .map_sg
= c6x_dma_map_sg
,
127 .unmap_sg
= c6x_dma_unmap_sg
,
128 .sync_single_for_device
= c6x_dma_sync_single_for_device
,
129 .sync_single_for_cpu
= c6x_dma_sync_single_for_cpu
,
130 .sync_sg_for_device
= c6x_dma_sync_sg_for_device
,
131 .sync_sg_for_cpu
= c6x_dma_sync_sg_for_cpu
,
133 EXPORT_SYMBOL(c6x_dma_ops
);
135 /* Number of entries preallocated for DMA-API debugging */
136 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
138 static int __init
dma_init(void)
140 dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES
);
144 fs_initcall(dma_init
);