1 /* 2 * OMAP1/OMAP7xx - specific DMA driver 3 * 4 * Copyright (C) 2003 - 2008 Nokia Corporation 5 * Author: Juha Yrjölä <juha.yrjola@nokia.com> 6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> 7 * Graphics DMA and LCD DMA graphics tranformations 8 * by Imre Deak <imre.deak@nokia.com> 9 * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. 10 * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. 11 * 12 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 13 * Converted DMA library into platform driver 14 * - G, Manjunath Kondaiah <manjugk@ti.com> 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License version 2 as 18 * published by the Free Software Foundation. 19 */ 20 21 #include <linux/err.h> 22 #include <linux/io.h> 23 #include <linux/slab.h> 24 #include <linux/module.h> 25 #include <linux/init.h> 26 #include <linux/device.h> 27 28 #include <plat/dma.h> 29 #include <plat/tc.h> 30 #include <plat/irqs.h> 31 32 #define OMAP1_DMA_BASE (0xfffed800) 33 #define OMAP1_LOGICAL_DMA_CH_COUNT 17 34 #define OMAP1_DMA_STRIDE 0x40 35 36 static u32 errata; 37 static u32 enable_1510_mode; 38 static u8 dma_stride; 39 static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; 40 41 static 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 }; 84 85 static struct resource res[] __initdata = { 86 [0] = { 87 .start = OMAP1_DMA_BASE, 88 .end = OMAP1_DMA_BASE + SZ_2K - 1, 89 .flags = IORESOURCE_MEM, 90 }, 91 [1] = { 92 .name = "0", 93 .start = INT_DMA_CH0_6, 94 .flags = IORESOURCE_IRQ, 95 }, 96 [2] = { 97 .name = "1", 98 .start = INT_DMA_CH1_7, 99 .flags = IORESOURCE_IRQ, 100 }, 101 [3] = { 102 .name = "2", 103 .start = INT_DMA_CH2_8, 104 .flags = IORESOURCE_IRQ, 105 }, 106 [4] = { 107 .name = "3", 108 .start = INT_DMA_CH3, 109 .flags = IORESOURCE_IRQ, 110 }, 111 [5] = { 112 .name = "4", 113 .start = INT_DMA_CH4, 114 .flags = IORESOURCE_IRQ, 115 }, 116 [6] = { 117 .name = "5", 118 .start = INT_DMA_CH5, 119 .flags = IORESOURCE_IRQ, 120 }, 121 /* Handled in lcd_dma.c */ 122 [7] = { 123 .name = "6", 124 .start = INT_1610_DMA_CH6, 125 .flags = IORESOURCE_IRQ, 126 }, 127 /* irq's for omap16xx and omap7xx */ 128 [8] = { 129 .name = "7", 130 .start = INT_1610_DMA_CH7, 131 .flags = IORESOURCE_IRQ, 132 }, 133 [9] = { 134 .name = "8", 135 .start = INT_1610_DMA_CH8, 136 .flags = IORESOURCE_IRQ, 137 }, 138 [10] = { 139 .name = "9", 140 .start = INT_1610_DMA_CH9, 141 .flags = IORESOURCE_IRQ, 142 }, 143 [11] = { 144 .name = "10", 145 .start = INT_1610_DMA_CH10, 146 .flags = IORESOURCE_IRQ, 147 }, 148 [12] = { 149 .name = "11", 150 .start = INT_1610_DMA_CH11, 151 .flags = IORESOURCE_IRQ, 152 }, 153 [13] = { 154 .name = "12", 155 .start = INT_1610_DMA_CH12, 156 .flags = IORESOURCE_IRQ, 157 }, 158 [14] = { 159 .name = "13", 160 .start = INT_1610_DMA_CH13, 161 .flags = IORESOURCE_IRQ, 162 }, 163 [15] = { 164 .name = "14", 165 .start = INT_1610_DMA_CH14, 166 .flags = IORESOURCE_IRQ, 167 }, 168 [16] = { 169 .name = "15", 170 .start = INT_1610_DMA_CH15, 171 .flags = IORESOURCE_IRQ, 172 }, 173 [17] = { 174 .name = "16", 175 .start = INT_DMA_LCD, 176 .flags = IORESOURCE_IRQ, 177 }, 178 }; 179 180 static void __iomem *dma_base; 181 static 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 197 static 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 216 static 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 224 static 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 236 static 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 257 static 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 270 static int __init omap1_system_dma_init(void) 271 { 272 struct omap_system_dma_plat_info *p; 273 struct omap_dma_dev_attr *d; 274 struct platform_device *pdev; 275 int ret; 276 277 pdev = platform_device_alloc("omap_dma_system", 0); 278 if (!pdev) { 279 pr_err("%s: Unable to device alloc for dma\n", 280 __func__); 281 return -ENOMEM; 282 } 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 ret = -ENODEV; 288 goto exit_device_put; 289 } 290 291 ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); 292 if (ret) { 293 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 294 __func__, pdev->name, pdev->id); 295 goto exit_device_put; 296 } 297 298 p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); 299 if (!p) { 300 dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", 301 __func__, pdev->name); 302 ret = -ENOMEM; 303 goto exit_device_del; 304 } 305 306 d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); 307 if (!d) { 308 dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", 309 __func__, pdev->name); 310 ret = -ENOMEM; 311 goto exit_release_p; 312 } 313 314 d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; 315 316 /* Valid attributes for omap1 plus processors */ 317 if (cpu_is_omap15xx()) 318 d->dev_caps = ENABLE_1510_MODE; 319 enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; 320 321 d->dev_caps |= SRC_PORT; 322 d->dev_caps |= DST_PORT; 323 d->dev_caps |= SRC_INDEX; 324 d->dev_caps |= DST_INDEX; 325 d->dev_caps |= IS_BURST_ONLY4; 326 d->dev_caps |= CLEAR_CSR_ON_READ; 327 d->dev_caps |= IS_WORD_16; 328 329 330 d->chan = kzalloc(sizeof(struct omap_dma_lch) * 331 (d->lch_count), GFP_KERNEL); 332 if (!d->chan) { 333 dev_err(&pdev->dev, "%s: Memory allocation failed" 334 "for d->chan!!!\n", __func__); 335 goto exit_release_d; 336 } 337 338 if (cpu_is_omap15xx()) 339 d->chan_count = 9; 340 else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { 341 if (!(d->dev_caps & ENABLE_1510_MODE)) 342 d->chan_count = 16; 343 else 344 d->chan_count = 9; 345 } 346 347 p->dma_attr = d; 348 349 p->show_dma_caps = omap1_show_dma_caps; 350 p->clear_lch_regs = omap1_clear_lch_regs; 351 p->clear_dma = omap1_clear_dma; 352 p->dma_write = dma_write; 353 p->dma_read = dma_read; 354 p->disable_irq_lch = NULL; 355 356 p->errata = configure_dma_errata(); 357 358 ret = platform_device_add_data(pdev, p, sizeof(*p)); 359 if (ret) { 360 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 361 __func__, pdev->name, pdev->id); 362 goto exit_release_chan; 363 } 364 365 ret = platform_device_add(pdev); 366 if (ret) { 367 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", 368 __func__, pdev->name, pdev->id); 369 goto exit_release_chan; 370 } 371 372 dma_stride = OMAP1_DMA_STRIDE; 373 dma_common_ch_start = CPC; 374 dma_common_ch_end = COLOR; 375 376 return ret; 377 378 exit_release_chan: 379 kfree(d->chan); 380 exit_release_d: 381 kfree(d); 382 exit_release_p: 383 kfree(p); 384 exit_device_del: 385 platform_device_del(pdev); 386 exit_device_put: 387 platform_device_put(pdev); 388 389 return ret; 390 } 391 arch_initcall(omap1_system_dma_init); 392