diff options
-rw-r--r-- | arch/sparc/include/asm/dma-mapping_32.h | 59 | ||||
-rw-r--r-- | arch/sparc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/dma.c | 227 | ||||
-rw-r--r-- | arch/sparc/kernel/dma.h | 14 | ||||
-rw-r--r-- | arch/sparc/kernel/ioport.c | 2 |
5 files changed, 298 insertions, 6 deletions
diff --git a/arch/sparc/include/asm/dma-mapping_32.h b/arch/sparc/include/asm/dma-mapping_32.h index f3a641e6b2c8..8a57ea0573e6 100644 --- a/arch/sparc/include/asm/dma-mapping_32.h +++ b/arch/sparc/include/asm/dma-mapping_32.h | |||
@@ -1,11 +1,60 @@ | |||
1 | #ifndef _ASM_SPARC_DMA_MAPPING_H | 1 | #ifndef _ASM_SPARC_DMA_MAPPING_H |
2 | #define _ASM_SPARC_DMA_MAPPING_H | 2 | #define _ASM_SPARC_DMA_MAPPING_H |
3 | 3 | ||
4 | #include <linux/types.h> | ||
4 | 5 | ||
5 | #ifdef CONFIG_PCI | 6 | struct device; |
6 | #include <asm-generic/dma-mapping.h> | 7 | struct scatterlist; |
7 | #else | 8 | struct page; |
8 | #include <asm-generic/dma-mapping-broken.h> | 9 | |
9 | #endif /* PCI */ | 10 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) |
11 | |||
12 | extern int dma_supported(struct device *dev, u64 mask); | ||
13 | extern int dma_set_mask(struct device *dev, u64 dma_mask); | ||
14 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | ||
15 | dma_addr_t *dma_handle, gfp_t flag); | ||
16 | extern void dma_free_coherent(struct device *dev, size_t size, | ||
17 | void *cpu_addr, dma_addr_t dma_handle); | ||
18 | extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
19 | size_t size, | ||
20 | enum dma_data_direction direction); | ||
21 | extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
22 | size_t size, | ||
23 | enum dma_data_direction direction); | ||
24 | extern dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
25 | unsigned long offset, size_t size, | ||
26 | enum dma_data_direction direction); | ||
27 | extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
28 | size_t size, enum dma_data_direction direction); | ||
29 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
30 | int nents, enum dma_data_direction direction); | ||
31 | extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
32 | int nents, enum dma_data_direction direction); | ||
33 | extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
34 | size_t size, | ||
35 | enum dma_data_direction direction); | ||
36 | extern void dma_sync_single_for_device(struct device *dev, | ||
37 | dma_addr_t dma_handle, | ||
38 | size_t size, | ||
39 | enum dma_data_direction direction); | ||
40 | extern void dma_sync_single_range_for_cpu(struct device *dev, | ||
41 | dma_addr_t dma_handle, | ||
42 | unsigned long offset, | ||
43 | size_t size, | ||
44 | enum dma_data_direction direction); | ||
45 | extern void dma_sync_single_range_for_device(struct device *dev, | ||
46 | dma_addr_t dma_handle, | ||
47 | unsigned long offset, size_t size, | ||
48 | enum dma_data_direction direction); | ||
49 | extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
50 | int nelems, enum dma_data_direction direction); | ||
51 | extern void dma_sync_sg_for_device(struct device *dev, | ||
52 | struct scatterlist *sg, int nelems, | ||
53 | enum dma_data_direction direction); | ||
54 | extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); | ||
55 | extern int dma_get_cache_alignment(void); | ||
56 | |||
57 | #define dma_alloc_noncoherent dma_alloc_coherent | ||
58 | #define dma_free_noncoherent dma_free_coherent | ||
10 | 59 | ||
11 | #endif /* _ASM_SPARC_DMA_MAPPING_H */ | 60 | #endif /* _ASM_SPARC_DMA_MAPPING_H */ |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 6e03a2a7863c..eaf7cf4296ab 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
@@ -13,7 +13,7 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ | |||
13 | time.o windows.o cpu.o devices.o \ | 13 | time.o windows.o cpu.o devices.o \ |
14 | tadpole.o tick14.o ptrace.o \ | 14 | tadpole.o tick14.o ptrace.o \ |
15 | unaligned.o una_asm.o muldiv.o \ | 15 | unaligned.o una_asm.o muldiv.o \ |
16 | prom.o of_device.o devres.o | 16 | prom.o of_device.o devres.o dma.o |
17 | 17 | ||
18 | devres-y = ../../../kernel/irq/devres.o | 18 | devres-y = ../../../kernel/irq/devres.o |
19 | 19 | ||
diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c new file mode 100644 index 000000000000..ebc8403b035e --- /dev/null +++ b/arch/sparc/kernel/dma.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* dma.c: PCI and SBUS DMA accessors for 32-bit sparc. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/dma-mapping.h> | ||
9 | #include <linux/scatterlist.h> | ||
10 | #include <linux/mm.h> | ||
11 | |||
12 | #ifdef CONFIG_PCI | ||
13 | #include <linux/pci.h> | ||
14 | #endif | ||
15 | |||
16 | #include "dma.h" | ||
17 | |||
18 | int dma_supported(struct device *dev, u64 mask) | ||
19 | { | ||
20 | #ifdef CONFIG_PCI | ||
21 | if (dev->bus == &pci_bus_type) | ||
22 | return pci_dma_supported(to_pci_dev(dev), mask); | ||
23 | #endif | ||
24 | return 0; | ||
25 | } | ||
26 | EXPORT_SYMBOL(dma_supported); | ||
27 | |||
28 | int dma_set_mask(struct device *dev, u64 dma_mask) | ||
29 | { | ||
30 | #ifdef CONFIG_PCI | ||
31 | if (dev->bus == &pci_bus_type) | ||
32 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
33 | #endif | ||
34 | return -EOPNOTSUPP; | ||
35 | } | ||
36 | EXPORT_SYMBOL(dma_set_mask); | ||
37 | |||
38 | void *dma_alloc_coherent(struct device *dev, size_t size, | ||
39 | dma_addr_t *dma_handle, gfp_t flag) | ||
40 | { | ||
41 | #ifdef CONFIG_PCI | ||
42 | if (dev->bus == &pci_bus_type) | ||
43 | return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); | ||
44 | #endif | ||
45 | return sbus_alloc_consistent(dev, size, dma_handle); | ||
46 | } | ||
47 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
48 | |||
49 | void dma_free_coherent(struct device *dev, size_t size, | ||
50 | void *cpu_addr, dma_addr_t dma_handle) | ||
51 | { | ||
52 | #ifdef CONFIG_PCI | ||
53 | if (dev->bus == &pci_bus_type) { | ||
54 | pci_free_consistent(to_pci_dev(dev), size, | ||
55 | cpu_addr, dma_handle); | ||
56 | return; | ||
57 | } | ||
58 | #endif | ||
59 | sbus_free_consistent(dev, size, cpu_addr, dma_handle); | ||
60 | } | ||
61 | EXPORT_SYMBOL(dma_free_coherent); | ||
62 | |||
63 | dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
64 | size_t size, enum dma_data_direction direction) | ||
65 | { | ||
66 | #ifdef CONFIG_PCI | ||
67 | if (dev->bus == &pci_bus_type) | ||
68 | return pci_map_single(to_pci_dev(dev), cpu_addr, | ||
69 | size, (int)direction); | ||
70 | #endif | ||
71 | return sbus_map_single(dev, cpu_addr, size, (int)direction); | ||
72 | } | ||
73 | EXPORT_SYMBOL(dma_map_single); | ||
74 | |||
75 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
76 | size_t size, | ||
77 | enum dma_data_direction direction) | ||
78 | { | ||
79 | #ifdef CONFIG_PCI | ||
80 | if (dev->bus == &pci_bus_type) { | ||
81 | pci_unmap_single(to_pci_dev(dev), dma_addr, | ||
82 | size, (int)direction); | ||
83 | return; | ||
84 | } | ||
85 | #endif | ||
86 | sbus_unmap_single(dev, dma_addr, size, (int)direction); | ||
87 | } | ||
88 | EXPORT_SYMBOL(dma_unmap_single); | ||
89 | |||
90 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
91 | unsigned long offset, size_t size, | ||
92 | enum dma_data_direction direction) | ||
93 | { | ||
94 | #ifdef CONFIG_PCI | ||
95 | if (dev->bus == &pci_bus_type) | ||
96 | return pci_map_page(to_pci_dev(dev), page, offset, | ||
97 | size, (int)direction); | ||
98 | #endif | ||
99 | return sbus_map_single(dev, page_address(page) + offset, | ||
100 | size, (int)direction); | ||
101 | } | ||
102 | EXPORT_SYMBOL(dma_map_page); | ||
103 | |||
104 | void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
105 | size_t size, enum dma_data_direction direction) | ||
106 | { | ||
107 | #ifdef CONFIG_PCI | ||
108 | if (dev->bus == &pci_bus_type) { | ||
109 | pci_unmap_page(to_pci_dev(dev), dma_address, | ||
110 | size, (int)direction); | ||
111 | return; | ||
112 | } | ||
113 | #endif | ||
114 | sbus_unmap_single(dev, dma_address, size, (int)direction); | ||
115 | } | ||
116 | EXPORT_SYMBOL(dma_unmap_page); | ||
117 | |||
118 | int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
119 | int nents, enum dma_data_direction direction) | ||
120 | { | ||
121 | #ifdef CONFIG_PCI | ||
122 | if (dev->bus == &pci_bus_type) | ||
123 | return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); | ||
124 | #endif | ||
125 | return sbus_map_sg(dev, sg, nents, direction); | ||
126 | } | ||
127 | EXPORT_SYMBOL(dma_map_sg); | ||
128 | |||
129 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
130 | int nents, enum dma_data_direction direction) | ||
131 | { | ||
132 | #ifdef CONFIG_PCI | ||
133 | if (dev->bus == &pci_bus_type) { | ||
134 | pci_unmap_sg(to_pci_dev(dev), sg, nents, (int)direction); | ||
135 | return; | ||
136 | } | ||
137 | #endif | ||
138 | sbus_unmap_sg(dev, sg, nents, (int)direction); | ||
139 | } | ||
140 | EXPORT_SYMBOL(dma_unmap_sg); | ||
141 | |||
142 | void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
143 | size_t size, enum dma_data_direction direction) | ||
144 | { | ||
145 | #ifdef CONFIG_PCI | ||
146 | if (dev->bus == &pci_bus_type) { | ||
147 | pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, | ||
148 | size, (int)direction); | ||
149 | return; | ||
150 | } | ||
151 | #endif | ||
152 | sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction); | ||
153 | } | ||
154 | EXPORT_SYMBOL(dma_sync_single_for_cpu); | ||
155 | |||
156 | void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
157 | size_t size, enum dma_data_direction direction) | ||
158 | { | ||
159 | #ifdef CONFIG_PCI | ||
160 | if (dev->bus == &pci_bus_type) { | ||
161 | pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, | ||
162 | size, (int)direction); | ||
163 | return; | ||
164 | } | ||
165 | #endif | ||
166 | sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction); | ||
167 | } | ||
168 | EXPORT_SYMBOL(dma_sync_single_for_device); | ||
169 | |||
170 | void dma_sync_single_range_for_cpu(struct device *dev, | ||
171 | dma_addr_t dma_handle, | ||
172 | unsigned long offset, | ||
173 | size_t size, | ||
174 | enum dma_data_direction direction) | ||
175 | { | ||
176 | dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); | ||
177 | } | ||
178 | EXPORT_SYMBOL(dma_sync_single_range_for_cpu); | ||
179 | |||
180 | void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
181 | unsigned long offset, size_t size, | ||
182 | enum dma_data_direction direction) | ||
183 | { | ||
184 | dma_sync_single_for_device(dev, dma_handle+offset, size, direction); | ||
185 | } | ||
186 | EXPORT_SYMBOL(dma_sync_single_range_for_device); | ||
187 | |||
188 | void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
189 | int nelems, enum dma_data_direction direction) | ||
190 | { | ||
191 | #ifdef CONFIG_PCI | ||
192 | if (dev->bus == &pci_bus_type) { | ||
193 | pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, | ||
194 | nelems, (int)direction); | ||
195 | return; | ||
196 | } | ||
197 | #endif | ||
198 | BUG(); | ||
199 | } | ||
200 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); | ||
201 | |||
202 | void dma_sync_sg_for_device(struct device *dev, | ||
203 | struct scatterlist *sg, int nelems, | ||
204 | enum dma_data_direction direction) | ||
205 | { | ||
206 | #ifdef CONFIG_PCI | ||
207 | if (dev->bus == &pci_bus_type) { | ||
208 | pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, | ||
209 | nelems, (int)direction); | ||
210 | return; | ||
211 | } | ||
212 | #endif | ||
213 | BUG(); | ||
214 | } | ||
215 | EXPORT_SYMBOL(dma_sync_sg_for_device); | ||
216 | |||
217 | int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
218 | { | ||
219 | return (dma_addr == DMA_ERROR_CODE); | ||
220 | } | ||
221 | EXPORT_SYMBOL(dma_mapping_error); | ||
222 | |||
223 | int dma_get_cache_alignment(void) | ||
224 | { | ||
225 | return 32; | ||
226 | } | ||
227 | EXPORT_SYMBOL(dma_get_cache_alignment); | ||
diff --git a/arch/sparc/kernel/dma.h b/arch/sparc/kernel/dma.h new file mode 100644 index 000000000000..f8d8951adb53 --- /dev/null +++ b/arch/sparc/kernel/dma.h | |||
@@ -0,0 +1,14 @@ | |||
1 | void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp); | ||
2 | void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba); | ||
3 | dma_addr_t sbus_map_single(struct device *dev, void *va, | ||
4 | size_t len, int direction); | ||
5 | void sbus_unmap_single(struct device *dev, dma_addr_t ba, | ||
6 | size_t n, int direction); | ||
7 | int sbus_map_sg(struct device *dev, struct scatterlist *sg, | ||
8 | int n, int direction); | ||
9 | void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
10 | int n, int direction); | ||
11 | void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, | ||
12 | size_t size, int direction); | ||
13 | void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, | ||
14 | size_t size, int direction); | ||
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 11dccf945153..0b3035978e0d 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -49,6 +49,8 @@ | |||
49 | #include <asm/iommu.h> | 49 | #include <asm/iommu.h> |
50 | #include <asm/io-unit.h> | 50 | #include <asm/io-unit.h> |
51 | 51 | ||
52 | #include "dma.h" | ||
53 | |||
52 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ | 54 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ |
53 | 55 | ||
54 | static struct resource *_sparc_find_resource(struct resource *r, | 56 | static struct resource *_sparc_find_resource(struct resource *r, |