0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/err.h>
0019 #include <linux/slab.h>
0020 #include <linux/module.h>
0021 #include <linux/init.h>
0022 #include <linux/device.h>
0023 #include <linux/io.h>
0024 #include <linux/dma-mapping.h>
0025 #include <linux/dmaengine.h>
0026 #include <linux/omap-dma.h>
0027 #include "tc.h"
0028
0029 #include "soc.h"
0030
0031 #define OMAP1_DMA_BASE (0xfffed800)
0032
0033 static u32 enable_1510_mode;
0034
0035 static const struct omap_dma_reg reg_map[] = {
0036 [GCR] = { 0x0400, 0x00, OMAP_DMA_REG_16BIT },
0037 [GSCR] = { 0x0404, 0x00, OMAP_DMA_REG_16BIT },
0038 [GRST1] = { 0x0408, 0x00, OMAP_DMA_REG_16BIT },
0039 [HW_ID] = { 0x0442, 0x00, OMAP_DMA_REG_16BIT },
0040 [PCH2_ID] = { 0x0444, 0x00, OMAP_DMA_REG_16BIT },
0041 [PCH0_ID] = { 0x0446, 0x00, OMAP_DMA_REG_16BIT },
0042 [PCH1_ID] = { 0x0448, 0x00, OMAP_DMA_REG_16BIT },
0043 [PCHG_ID] = { 0x044a, 0x00, OMAP_DMA_REG_16BIT },
0044 [PCHD_ID] = { 0x044c, 0x00, OMAP_DMA_REG_16BIT },
0045 [CAPS_0] = { 0x044e, 0x00, OMAP_DMA_REG_2X16BIT },
0046 [CAPS_1] = { 0x0452, 0x00, OMAP_DMA_REG_2X16BIT },
0047 [CAPS_2] = { 0x0456, 0x00, OMAP_DMA_REG_16BIT },
0048 [CAPS_3] = { 0x0458, 0x00, OMAP_DMA_REG_16BIT },
0049 [CAPS_4] = { 0x045a, 0x00, OMAP_DMA_REG_16BIT },
0050 [PCH2_SR] = { 0x0460, 0x00, OMAP_DMA_REG_16BIT },
0051 [PCH0_SR] = { 0x0480, 0x00, OMAP_DMA_REG_16BIT },
0052 [PCH1_SR] = { 0x0482, 0x00, OMAP_DMA_REG_16BIT },
0053 [PCHD_SR] = { 0x04c0, 0x00, OMAP_DMA_REG_16BIT },
0054
0055
0056 [CSDP] = { 0x0000, 0x40, OMAP_DMA_REG_16BIT },
0057 [CCR] = { 0x0002, 0x40, OMAP_DMA_REG_16BIT },
0058 [CICR] = { 0x0004, 0x40, OMAP_DMA_REG_16BIT },
0059 [CSR] = { 0x0006, 0x40, OMAP_DMA_REG_16BIT },
0060 [CEN] = { 0x0010, 0x40, OMAP_DMA_REG_16BIT },
0061 [CFN] = { 0x0012, 0x40, OMAP_DMA_REG_16BIT },
0062 [CSFI] = { 0x0014, 0x40, OMAP_DMA_REG_16BIT },
0063 [CSEI] = { 0x0016, 0x40, OMAP_DMA_REG_16BIT },
0064 [CPC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT },
0065 [CSAC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT },
0066 [CDAC] = { 0x001a, 0x40, OMAP_DMA_REG_16BIT },
0067 [CDEI] = { 0x001c, 0x40, OMAP_DMA_REG_16BIT },
0068 [CDFI] = { 0x001e, 0x40, OMAP_DMA_REG_16BIT },
0069 [CLNK_CTRL] = { 0x0028, 0x40, OMAP_DMA_REG_16BIT },
0070
0071
0072 [CSSA] = { 0x0008, 0x40, OMAP_DMA_REG_2X16BIT },
0073 [CDSA] = { 0x000c, 0x40, OMAP_DMA_REG_2X16BIT },
0074 [COLOR] = { 0x0020, 0x40, OMAP_DMA_REG_2X16BIT },
0075 [CCR2] = { 0x0024, 0x40, OMAP_DMA_REG_16BIT },
0076 [LCH_CTRL] = { 0x002a, 0x40, OMAP_DMA_REG_16BIT },
0077 };
0078
0079 static struct resource res[] __initdata = {
0080 [0] = {
0081 .start = OMAP1_DMA_BASE,
0082 .end = OMAP1_DMA_BASE + SZ_2K - 1,
0083 .flags = IORESOURCE_MEM,
0084 },
0085 [1] = {
0086 .name = "0",
0087 .start = INT_DMA_CH0_6,
0088 .flags = IORESOURCE_IRQ,
0089 },
0090 [2] = {
0091 .name = "1",
0092 .start = INT_DMA_CH1_7,
0093 .flags = IORESOURCE_IRQ,
0094 },
0095 [3] = {
0096 .name = "2",
0097 .start = INT_DMA_CH2_8,
0098 .flags = IORESOURCE_IRQ,
0099 },
0100 [4] = {
0101 .name = "3",
0102 .start = INT_DMA_CH3,
0103 .flags = IORESOURCE_IRQ,
0104 },
0105 [5] = {
0106 .name = "4",
0107 .start = INT_DMA_CH4,
0108 .flags = IORESOURCE_IRQ,
0109 },
0110 [6] = {
0111 .name = "5",
0112 .start = INT_DMA_CH5,
0113 .flags = IORESOURCE_IRQ,
0114 },
0115
0116 [7] = {
0117 .name = "6",
0118 .start = INT_1610_DMA_CH6,
0119 .flags = IORESOURCE_IRQ,
0120 },
0121
0122 [8] = {
0123 .name = "7",
0124 .start = INT_1610_DMA_CH7,
0125 .flags = IORESOURCE_IRQ,
0126 },
0127 [9] = {
0128 .name = "8",
0129 .start = INT_1610_DMA_CH8,
0130 .flags = IORESOURCE_IRQ,
0131 },
0132 [10] = {
0133 .name = "9",
0134 .start = INT_1610_DMA_CH9,
0135 .flags = IORESOURCE_IRQ,
0136 },
0137 [11] = {
0138 .name = "10",
0139 .start = INT_1610_DMA_CH10,
0140 .flags = IORESOURCE_IRQ,
0141 },
0142 [12] = {
0143 .name = "11",
0144 .start = INT_1610_DMA_CH11,
0145 .flags = IORESOURCE_IRQ,
0146 },
0147 [13] = {
0148 .name = "12",
0149 .start = INT_1610_DMA_CH12,
0150 .flags = IORESOURCE_IRQ,
0151 },
0152 [14] = {
0153 .name = "13",
0154 .start = INT_1610_DMA_CH13,
0155 .flags = IORESOURCE_IRQ,
0156 },
0157 [15] = {
0158 .name = "14",
0159 .start = INT_1610_DMA_CH14,
0160 .flags = IORESOURCE_IRQ,
0161 },
0162 [16] = {
0163 .name = "15",
0164 .start = INT_1610_DMA_CH15,
0165 .flags = IORESOURCE_IRQ,
0166 },
0167 [17] = {
0168 .name = "16",
0169 .start = INT_DMA_LCD,
0170 .flags = IORESOURCE_IRQ,
0171 },
0172 };
0173
0174 static void __iomem *dma_base;
0175 static inline void dma_write(u32 val, int reg, int lch)
0176 {
0177 void __iomem *addr = dma_base;
0178
0179 addr += reg_map[reg].offset;
0180 addr += reg_map[reg].stride * lch;
0181
0182 __raw_writew(val, addr);
0183 if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
0184 __raw_writew(val >> 16, addr + 2);
0185 }
0186
0187 static inline u32 dma_read(int reg, int lch)
0188 {
0189 void __iomem *addr = dma_base;
0190 uint32_t val;
0191
0192 addr += reg_map[reg].offset;
0193 addr += reg_map[reg].stride * lch;
0194
0195 val = __raw_readw(addr);
0196 if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
0197 val |= __raw_readw(addr + 2) << 16;
0198
0199 return val;
0200 }
0201
0202 static void omap1_clear_lch_regs(int lch)
0203 {
0204 int i;
0205
0206 for (i = CPC; i <= COLOR; i += 1)
0207 dma_write(0, i, lch);
0208 }
0209
0210 static void omap1_clear_dma(int lch)
0211 {
0212 u32 l;
0213
0214 l = dma_read(CCR, lch);
0215 l &= ~OMAP_DMA_CCR_EN;
0216 dma_write(l, CCR, lch);
0217
0218
0219 l = dma_read(CSR, lch);
0220 }
0221
0222 static void omap1_show_dma_caps(void)
0223 {
0224 if (enable_1510_mode) {
0225 printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
0226 } else {
0227 u16 w;
0228 printk(KERN_INFO "OMAP DMA hardware version %d\n",
0229 dma_read(HW_ID, 0));
0230 printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
0231 dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
0232 dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
0233 dma_read(CAPS_4, 0));
0234
0235
0236 w = dma_read(GSCR, 0);
0237 w |= 1 << 3;
0238 dma_write(w, GSCR, 0);
0239 }
0240 }
0241
0242 static unsigned configure_dma_errata(void)
0243 {
0244 unsigned errata = 0;
0245
0246
0247
0248
0249
0250 if (!cpu_is_omap15xx())
0251 SET_DMA_ERRATA(DMA_ERRATA_3_3);
0252
0253 return errata;
0254 }
0255
0256 static const struct platform_device_info omap_dma_dev_info = {
0257 .name = "omap-dma-engine",
0258 .id = -1,
0259 .dma_mask = DMA_BIT_MASK(32),
0260 .res = res,
0261 .num_res = 1,
0262 };
0263
0264
0265 static const struct dma_slave_map omap7xx_sdma_map[] = {
0266 { "omap-mcbsp.1", "tx", SDMA_FILTER_PARAM(8) },
0267 { "omap-mcbsp.1", "rx", SDMA_FILTER_PARAM(9) },
0268 { "omap-mcbsp.2", "tx", SDMA_FILTER_PARAM(10) },
0269 { "omap-mcbsp.2", "rx", SDMA_FILTER_PARAM(11) },
0270 { "mmci-omap.0", "tx", SDMA_FILTER_PARAM(21) },
0271 { "mmci-omap.0", "rx", SDMA_FILTER_PARAM(22) },
0272 { "omap_udc", "rx0", SDMA_FILTER_PARAM(26) },
0273 { "omap_udc", "rx1", SDMA_FILTER_PARAM(27) },
0274 { "omap_udc", "rx2", SDMA_FILTER_PARAM(28) },
0275 { "omap_udc", "tx0", SDMA_FILTER_PARAM(29) },
0276 { "omap_udc", "tx1", SDMA_FILTER_PARAM(30) },
0277 { "omap_udc", "tx2", SDMA_FILTER_PARAM(31) },
0278 };
0279
0280
0281 static const struct dma_slave_map omap1xxx_sdma_map[] = {
0282 { "omap-mcbsp.1", "tx", SDMA_FILTER_PARAM(8) },
0283 { "omap-mcbsp.1", "rx", SDMA_FILTER_PARAM(9) },
0284 { "omap-mcbsp.3", "tx", SDMA_FILTER_PARAM(10) },
0285 { "omap-mcbsp.3", "rx", SDMA_FILTER_PARAM(11) },
0286 { "omap-mcbsp.2", "tx", SDMA_FILTER_PARAM(16) },
0287 { "omap-mcbsp.2", "rx", SDMA_FILTER_PARAM(17) },
0288 { "mmci-omap.0", "tx", SDMA_FILTER_PARAM(21) },
0289 { "mmci-omap.0", "rx", SDMA_FILTER_PARAM(22) },
0290 { "omap_udc", "rx0", SDMA_FILTER_PARAM(26) },
0291 { "omap_udc", "rx1", SDMA_FILTER_PARAM(27) },
0292 { "omap_udc", "rx2", SDMA_FILTER_PARAM(28) },
0293 { "omap_udc", "tx0", SDMA_FILTER_PARAM(29) },
0294 { "omap_udc", "tx1", SDMA_FILTER_PARAM(30) },
0295 { "omap_udc", "tx2", SDMA_FILTER_PARAM(31) },
0296 { "mmci-omap.1", "tx", SDMA_FILTER_PARAM(54) },
0297 { "mmci-omap.1", "rx", SDMA_FILTER_PARAM(55) },
0298 };
0299
0300 static struct omap_system_dma_plat_info dma_plat_info __initdata = {
0301 .reg_map = reg_map,
0302 .channel_stride = 0x40,
0303 .show_dma_caps = omap1_show_dma_caps,
0304 .clear_lch_regs = omap1_clear_lch_regs,
0305 .clear_dma = omap1_clear_dma,
0306 .dma_write = dma_write,
0307 .dma_read = dma_read,
0308 };
0309
0310 static int __init omap1_system_dma_init(void)
0311 {
0312 struct omap_system_dma_plat_info p;
0313 struct omap_dma_dev_attr *d;
0314 struct platform_device *pdev, *dma_pdev;
0315 int ret;
0316
0317 pdev = platform_device_alloc("omap_dma_system", 0);
0318 if (!pdev) {
0319 pr_err("%s: Unable to device alloc for dma\n",
0320 __func__);
0321 return -ENOMEM;
0322 }
0323
0324 dma_base = ioremap(res[0].start, resource_size(&res[0]));
0325 if (!dma_base) {
0326 pr_err("%s: Unable to ioremap\n", __func__);
0327 ret = -ENODEV;
0328 goto exit_device_put;
0329 }
0330
0331 ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
0332 if (ret) {
0333 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
0334 __func__, pdev->name, pdev->id);
0335 goto exit_iounmap;
0336 }
0337
0338 d = kzalloc(sizeof(*d), GFP_KERNEL);
0339 if (!d) {
0340 ret = -ENOMEM;
0341 goto exit_iounmap;
0342 }
0343
0344
0345 if (cpu_is_omap15xx())
0346 d->dev_caps = ENABLE_1510_MODE;
0347 enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
0348
0349 if (cpu_is_omap16xx())
0350 d->dev_caps = ENABLE_16XX_MODE;
0351
0352 d->dev_caps |= SRC_PORT;
0353 d->dev_caps |= DST_PORT;
0354 d->dev_caps |= SRC_INDEX;
0355 d->dev_caps |= DST_INDEX;
0356 d->dev_caps |= IS_BURST_ONLY4;
0357 d->dev_caps |= CLEAR_CSR_ON_READ;
0358 d->dev_caps |= IS_WORD_16;
0359
0360
0361 if (cpu_is_omap15xx()) {
0362 d->lch_count = 9;
0363 } else {
0364 if (d->dev_caps & ENABLE_1510_MODE)
0365 d->lch_count = 9;
0366 else
0367 d->lch_count = 16;
0368 }
0369
0370 p = dma_plat_info;
0371 p.dma_attr = d;
0372 p.errata = configure_dma_errata();
0373
0374 if (cpu_is_omap7xx()) {
0375 p.slave_map = omap7xx_sdma_map;
0376 p.slavecnt = ARRAY_SIZE(omap7xx_sdma_map);
0377 } else {
0378 p.slave_map = omap1xxx_sdma_map;
0379 p.slavecnt = ARRAY_SIZE(omap1xxx_sdma_map);
0380 }
0381
0382 ret = platform_device_add_data(pdev, &p, sizeof(p));
0383 if (ret) {
0384 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
0385 __func__, pdev->name, pdev->id);
0386 goto exit_release_d;
0387 }
0388
0389 ret = platform_device_add(pdev);
0390 if (ret) {
0391 dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
0392 __func__, pdev->name, pdev->id);
0393 goto exit_release_d;
0394 }
0395
0396 dma_pdev = platform_device_register_full(&omap_dma_dev_info);
0397 if (IS_ERR(dma_pdev)) {
0398 ret = PTR_ERR(dma_pdev);
0399 goto exit_release_pdev;
0400 }
0401
0402 return ret;
0403
0404 exit_release_pdev:
0405 platform_device_del(pdev);
0406 exit_release_d:
0407 kfree(d);
0408 exit_iounmap:
0409 iounmap(dma_base);
0410 exit_device_put:
0411 platform_device_put(pdev);
0412
0413 return ret;
0414 }
0415 arch_initcall(omap1_system_dma_init);