aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1
diff options
context:
space:
mode:
authorG, Manjunath Kondaiah <manjugk@ti.com>2010-12-20 21:27:19 -0500
committerTony Lindgren <tony@atomide.com>2010-12-20 21:38:31 -0500
commitf31cc9622d75c1c6f041d786698daa425c0425c2 (patch)
tree4e52cc4a4d5a6c478823150d263cecbb08271f7b /arch/arm/mach-omap1
parent59de3cf1ce9a961ba9ab657707727db2111e72fa (diff)
OMAP: DMA: Convert DMA library into platform driver
Convert DMA library into DMA platform driver and make use of platform data provided by hwmod data base for OMAP2+ onwards. For OMAP1 processors, the DMA driver in mach-omap uses resource structures for getting platform data. Thanks to Tony Lindgren <tony@atomide.com> for fixing various omap1 issues and testing the same on OSK5912 board. Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com> Tested-by: Kevin Hilman <khilman@deeprootsystems.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r--arch/arm/mach-omap1/Makefile2
-rw-r--r--arch/arm/mach-omap1/dma.c215
2 files changed, 214 insertions, 3 deletions
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 0b1c07ffa2f1..6ee19504845f 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5# Common support 5# Common support
6obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o 6obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o
7obj-y += clock.o clock_data.o opp_data.o 7obj-y += clock.o clock_data.o opp_data.o
8 8
9obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o 9obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 120eff707ab2..d8559344c6e2 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -30,6 +30,57 @@
30#include <plat/irqs.h> 30#include <plat/irqs.h>
31 31
32#define OMAP1_DMA_BASE (0xfffed800) 32#define OMAP1_DMA_BASE (0xfffed800)
33#define OMAP1_LOGICAL_DMA_CH_COUNT 17
34#define OMAP1_DMA_STRIDE 0x40
35
36static u32 errata;
37static u32 enable_1510_mode;
38static u8 dma_stride;
39static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
40
41static u16 reg_map[] = {
42 [GCR] = 0x400,
43 [GSCR] = 0x404,
44 [GRST1] = 0x408,
45 [HW_ID] = 0x442,
46 [PCH2_ID] = 0x444,
47 [PCH0_ID] = 0x446,
48 [PCH1_ID] = 0x448,
49 [PCHG_ID] = 0x44a,
50 [PCHD_ID] = 0x44c,
51 [CAPS_0] = 0x44e,
52 [CAPS_1] = 0x452,
53 [CAPS_2] = 0x456,
54 [CAPS_3] = 0x458,
55 [CAPS_4] = 0x45a,
56 [PCH2_SR] = 0x460,
57 [PCH0_SR] = 0x480,
58 [PCH1_SR] = 0x482,
59 [PCHD_SR] = 0x4c0,
60
61 /* Common Registers */
62 [CSDP] = 0x00,
63 [CCR] = 0x02,
64 [CICR] = 0x04,
65 [CSR] = 0x06,
66 [CEN] = 0x10,
67 [CFN] = 0x12,
68 [CSFI] = 0x14,
69 [CSEI] = 0x16,
70 [CPC] = 0x18, /* 15xx only */
71 [CSAC] = 0x18,
72 [CDAC] = 0x1a,
73 [CDEI] = 0x1c,
74 [CDFI] = 0x1e,
75 [CLNK_CTRL] = 0x28,
76
77 /* Channel specific register offsets */
78 [CSSA] = 0x08,
79 [CDSA] = 0x0c,
80 [COLOR] = 0x20,
81 [CCR2] = 0x24,
82 [LCH_CTRL] = 0x2a,
83};
33 84
34static struct resource res[] __initdata = { 85static struct resource res[] __initdata = {
35 [0] = { 86 [0] = {
@@ -67,6 +118,7 @@ static struct resource res[] __initdata = {
67 .start = INT_DMA_CH5, 118 .start = INT_DMA_CH5,
68 .flags = IORESOURCE_IRQ, 119 .flags = IORESOURCE_IRQ,
69 }, 120 },
121 /* Handled in lcd_dma.c */
70 [7] = { 122 [7] = {
71 .name = "6", 123 .name = "6",
72 .start = INT_1610_DMA_CH6, 124 .start = INT_1610_DMA_CH6,
@@ -125,9 +177,100 @@ static struct resource res[] __initdata = {
125 }, 177 },
126}; 178};
127 179
180static void __iomem *dma_base;
181static inline void dma_write(u32 val, int reg, int lch)
182{
183 u8 stride;
184 u32 offset;
185
186 stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
187 offset = reg_map[reg] + (stride * lch);
188
189 __raw_writew(val, dma_base + offset);
190 if ((reg > CLNK_CTRL && reg < CCEN) ||
191 (reg > PCHD_ID && reg < CAPS_2)) {
192 u32 offset2 = reg_map[reg] + 2 + (stride * lch);
193 __raw_writew(val >> 16, dma_base + offset2);
194 }
195}
196
197static inline u32 dma_read(int reg, int lch)
198{
199 u8 stride;
200 u32 offset, val;
201
202 stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
203 offset = reg_map[reg] + (stride * lch);
204
205 val = __raw_readw(dma_base + offset);
206 if ((reg > CLNK_CTRL && reg < CCEN) ||
207 (reg > PCHD_ID && reg < CAPS_2)) {
208 u16 upper;
209 u32 offset2 = reg_map[reg] + 2 + (stride * lch);
210 upper = __raw_readw(dma_base + offset2);
211 val |= (upper << 16);
212 }
213 return val;
214}
215
216static void omap1_clear_lch_regs(int lch)
217{
218 int i = dma_common_ch_start;
219
220 for (; i <= dma_common_ch_end; i += 1)
221 dma_write(0, i, lch);
222}
223
224static void omap1_clear_dma(int lch)
225{
226 u32 l;
227
228 l = dma_read(CCR, lch);
229 l &= ~OMAP_DMA_CCR_EN;
230 dma_write(l, CCR, lch);
231
232 /* Clear pending interrupts */
233 l = dma_read(CSR, lch);
234}
235
236static void omap1_show_dma_caps(void)
237{
238 if (enable_1510_mode) {
239 printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
240 } else {
241 u16 w;
242 printk(KERN_INFO "OMAP DMA hardware version %d\n",
243 dma_read(HW_ID, 0));
244 printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
245 dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
246 dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
247 dma_read(CAPS_4, 0));
248
249 /* Disable OMAP 3.0/3.1 compatibility mode. */
250 w = dma_read(GSCR, 0);
251 w |= 1 << 3;
252 dma_write(w, GSCR, 0);
253 }
254 return;
255}
256
257static u32 configure_dma_errata(void)
258{
259
260 /*
261 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
262 * read before the DMA controller finished disabling the channel.
263 */
264 if (!cpu_is_omap15xx())
265 SET_DMA_ERRATA(DMA_ERRATA_3_3);
266
267 return errata;
268}
269
128static int __init omap1_system_dma_init(void) 270static int __init omap1_system_dma_init(void)
129{ 271{
130 struct omap_system_dma_plat_info *p; 272 struct omap_system_dma_plat_info *p;
273 struct omap_dma_dev_attr *d;
131 struct platform_device *pdev; 274 struct platform_device *pdev;
132 int ret; 275 int ret;
133 276
@@ -138,6 +281,12 @@ static int __init omap1_system_dma_init(void)
138 return -ENOMEM; 281 return -ENOMEM;
139 } 282 }
140 283
284 dma_base = ioremap(res[0].start, resource_size(&res[0]));
285 if (!dma_base) {
286 pr_err("%s: Unable to ioremap\n", __func__);
287 return -ENODEV;
288 }
289
141 ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); 290 ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
142 if (ret) { 291 if (ret) {
143 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 292 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
@@ -153,22 +302,84 @@ static int __init omap1_system_dma_init(void)
153 goto exit_device_put; 302 goto exit_device_put;
154 } 303 }
155 304
305 d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
306 if (!d) {
307 dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
308 __func__, pdev->name);
309 ret = -ENOMEM;
310 goto exit_release_p;
311 }
312
313 d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
314
315 /* Valid attributes for omap1 plus processors */
316 if (cpu_is_omap15xx())
317 d->dev_caps = ENABLE_1510_MODE;
318 enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
319
320 d->dev_caps |= SRC_PORT;
321 d->dev_caps |= DST_PORT;
322 d->dev_caps |= SRC_INDEX;
323 d->dev_caps |= DST_INDEX;
324 d->dev_caps |= IS_BURST_ONLY4;
325 d->dev_caps |= CLEAR_CSR_ON_READ;
326 d->dev_caps |= IS_WORD_16;
327
328
329 d->chan = kzalloc(sizeof(struct omap_dma_lch) *
330 (d->lch_count), GFP_KERNEL);
331 if (!d->chan) {
332 dev_err(&pdev->dev, "%s: Memory allocation failed"
333 "for d->chan!!!\n", __func__);
334 goto exit_release_d;
335 }
336
337 if (cpu_is_omap15xx())
338 d->chan_count = 9;
339 else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
340 if (!(d->dev_caps & ENABLE_1510_MODE))
341 d->chan_count = 16;
342 else
343 d->chan_count = 9;
344 }
345
346 p->dma_attr = d;
347
348 p->show_dma_caps = omap1_show_dma_caps;
349 p->clear_lch_regs = omap1_clear_lch_regs;
350 p->clear_dma = omap1_clear_dma;
351 p->dma_write = dma_write;
352 p->dma_read = dma_read;
353 p->disable_irq_lch = NULL;
354
355 p->errata = configure_dma_errata();
356
156 ret = platform_device_add_data(pdev, p, sizeof(*p)); 357 ret = platform_device_add_data(pdev, p, sizeof(*p));
157 if (ret) { 358 if (ret) {
158 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 359 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
159 __func__, pdev->name, pdev->id); 360 __func__, pdev->name, pdev->id);
160 goto exit_device_put; 361 goto exit_release_chan;
161 } 362 }
162 363
163 ret = platform_device_add(pdev); 364 ret = platform_device_add(pdev);
164 if (ret) { 365 if (ret) {
165 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 366 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
166 __func__, pdev->name, pdev->id); 367 __func__, pdev->name, pdev->id);
167 goto exit_device_put; 368 goto exit_release_chan;
168 } 369 }
169 370
371 dma_stride = OMAP1_DMA_STRIDE;
372 dma_common_ch_start = CPC;
373 dma_common_ch_end = COLOR;
374
170 return ret; 375 return ret;
171 376
377exit_release_chan:
378 kfree(d->chan);
379exit_release_d:
380 kfree(d);
381exit_release_p:
382 kfree(p);
172exit_device_put: 383exit_device_put:
173 platform_device_put(pdev); 384 platform_device_put(pdev);
174exit_device_del: 385exit_device_del: