^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/plat-omap/dma.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2003 - 2008 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Juha Yrjölä <juha.yrjola@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Graphics DMA and LCD DMA graphics tranformations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * by Imre Deak <imre.deak@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2009 Texas Instruments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Support functions for the OMAP internal DMA channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Converted DMA library into DMA platform driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * - G, Manjunath Kondaiah <manjugk@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/omap-dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #ifdef CONFIG_ARCH_OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <mach/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * MAX_LOGICAL_DMA_CH_COUNT: the maximum number of logical DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * channels that an instance of the SDMA IP block can support. Used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * to size arrays. (The actual maximum on a particular SoC may be less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * than this -- for example, OMAP1 SDMA instances only support 17 logical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * DMA channels.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MAX_LOGICAL_DMA_CH_COUNT 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifndef CONFIG_ARCH_OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define OMAP_DMA_ACTIVE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define OMAP2_DMA_CSR_CLEAR_MASK 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct omap_system_dma_plat_info *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static struct omap_dma_dev_attr *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void omap_clear_dma(int lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int enable_1510_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static u32 errata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct dma_link_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int *linked_dmach_q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int no_of_lchs_linked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int q_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int q_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int q_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int chain_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int chain_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int dma_lch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int dma_chan_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int omap_dma_reserve_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static spinlock_t dma_chan_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct omap_dma_lch *dma_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static inline void disable_lnk(int lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void omap_disable_channel_irq(int lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static inline void omap_enable_channel_irq(int lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #ifdef CONFIG_ARCH_OMAP15XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int omap_dma_in_1510_mode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return enable_1510_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define omap_dma_in_1510_mode() 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #ifdef CONFIG_ARCH_OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static inline void set_gdma_dev(int req, int dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int shift = ((req - 1) % 5) * 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) l = omap_readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) l &= ~(0x3f << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) l |= (dev - 1) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) omap_writel(l, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define set_gdma_dev(req, dev) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define omap_readl(reg) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define omap_writel(val, reg) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #ifdef CONFIG_ARCH_OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) void omap_set_dma_priority(int lch, int dst_port, int priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) switch (dst_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) reg = OMAP_TC_OCPT1_PRIOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) reg = OMAP_TC_OCPT2_PRIOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) reg = OMAP_TC_EMIFF_PRIOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) reg = OMAP_TC_EMIFS_PRIOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) l = omap_readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) l &= ~(0xf << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) l |= (priority & 0xf) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) omap_writel(l, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #ifdef CONFIG_ARCH_OMAP2PLUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) void omap_set_dma_priority(int lch, int dst_port, int priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u32 ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ccr = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ccr |= (1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ccr &= ~(1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) p->dma_write(ccr, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) EXPORT_SYMBOL(omap_set_dma_priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int frame_count, int sync_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int dma_trigger, int src_or_dst_synch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) l &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) l |= data_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u16 ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ccr = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ccr &= ~(1 << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (sync_mode == OMAP_DMA_SYNC_FRAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ccr |= 1 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) p->dma_write(ccr, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ccr = p->dma_read(CCR2, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ccr &= ~(1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (sync_mode == OMAP_DMA_SYNC_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ccr |= 1 << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) p->dma_write(ccr, CCR2, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (dma_omap2plus() && dma_trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) val = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) val &= ~((1 << 23) | (3 << 19) | 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) val |= (dma_trigger & ~0x1f) << 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) val |= dma_trigger & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (sync_mode & OMAP_DMA_SYNC_FRAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) val |= 1 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) val &= ~(1 << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (sync_mode & OMAP_DMA_SYNC_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) val |= 1 << 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) val &= ~(1 << 18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) val &= ~(1 << 24); /* dest synch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) val |= (1 << 23); /* Prefetch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) } else if (src_or_dst_synch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) val |= 1 << 24; /* source synch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) val &= ~(1 << 24); /* dest synch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) p->dma_write(val, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) p->dma_write(elem_count, CEN, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) p->dma_write(frame_count, CFN, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL(omap_set_dma_transfer_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (dma_omap1() && !dma_omap15xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) l = p->dma_read(LCH_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) l &= ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) l |= mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) p->dma_write(l, LCH_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) EXPORT_SYMBOL(omap_set_dma_channel_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* Note that src_port is only for omap1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) void omap_set_dma_src_params(int lch, int src_port, int src_amode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned long src_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int src_ei, int src_fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u16 w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) w = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) w &= ~(0x1f << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) w |= src_port << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) p->dma_write(w, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) l &= ~(0x03 << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) l |= src_amode << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) p->dma_write(l, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) p->dma_write(src_start, CSSA, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) p->dma_write(src_ei, CSEI, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) p->dma_write(src_fi, CSFI, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) EXPORT_SYMBOL(omap_set_dma_src_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) void omap_set_dma_src_data_pack(int lch, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) l &= ~(1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) l |= (1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) EXPORT_SYMBOL(omap_set_dma_src_data_pack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned int burst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) l &= ~(0x03 << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) switch (burst_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case OMAP_DMA_DATA_BURST_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case OMAP_DMA_DATA_BURST_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (dma_omap2plus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) burst = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) burst = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case OMAP_DMA_DATA_BURST_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (dma_omap2plus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) burst = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * not supported by current hardware on OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * w |= (0x03 << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case OMAP_DMA_DATA_BURST_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (dma_omap2plus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) burst = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* OMAP1 don't support burst 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) l |= (burst << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Note that dest_port is only for OMAP1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) unsigned long dest_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int dst_ei, int dst_fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) l &= ~(0x1f << 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) l |= dest_port << 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) l &= ~(0x03 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) l |= dest_amode << 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) p->dma_write(l, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) p->dma_write(dest_start, CDSA, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) p->dma_write(dst_ei, CDEI, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) p->dma_write(dst_fi, CDFI, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) EXPORT_SYMBOL(omap_set_dma_dest_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) void omap_set_dma_dest_data_pack(int lch, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) l &= ~(1 << 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) l |= 1 << 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) unsigned int burst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) l = p->dma_read(CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) l &= ~(0x03 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) switch (burst_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case OMAP_DMA_DATA_BURST_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case OMAP_DMA_DATA_BURST_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (dma_omap2plus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) burst = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) burst = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case OMAP_DMA_DATA_BURST_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (dma_omap2plus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) burst = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) burst = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case OMAP_DMA_DATA_BURST_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (dma_omap2plus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) burst = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* OMAP1 don't support burst 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) printk(KERN_ERR "Invalid DMA burst mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) l |= (burst << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) p->dma_write(l, CSDP, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static inline void omap_enable_channel_irq(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* Clear CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) p->dma_read(CSR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* Enable some nice interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static inline void omap_disable_channel_irq(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* disable channel interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) p->dma_write(0, CICR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* Clear CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) p->dma_read(CSR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) void omap_disable_dma_irq(int lch, u16 bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dma_chan[lch].enabled_irqs &= ~bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) EXPORT_SYMBOL(omap_disable_dma_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static inline void enable_lnk(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) l = p->dma_read(CLNK_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) l &= ~(1 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* Set the ENABLE_LNK bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (dma_chan[lch].next_lch != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) l = dma_chan[lch].next_lch | (1 << 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) p->dma_write(l, CLNK_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static inline void disable_lnk(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) l = p->dma_read(CLNK_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) omap_disable_channel_irq(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* Set the STOP_LNK bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) l |= 1 << 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (dma_omap2plus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Clear the ENABLE_LNK bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) l &= ~(1 << 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) p->dma_write(l, CLNK_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int omap_request_dma(int dev_id, const char *dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) void (*callback)(int lch, u16 ch_status, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) void *data, int *dma_ch_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int ch, free_ch = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct omap_dma_lch *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) WARN(strcmp(dev_name, "DMA engine"), "Using deprecated platform DMA API - please update to DMA engine");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) spin_lock_irqsave(&dma_chan_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) for (ch = 0; ch < dma_chan_count; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) free_ch = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Exit after first free channel found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (free_ch == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) spin_unlock_irqrestore(&dma_chan_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) chan = dma_chan + free_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) chan->dev_id = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (p->clear_lch_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) p->clear_lch_regs(free_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) spin_unlock_irqrestore(&dma_chan_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) chan->dev_name = dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) chan->callback = callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) chan->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) chan->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (dma_omap16xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* If the sync device is set, configure it dynamically. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (dev_id != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) set_gdma_dev(free_ch + 1, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) dev_id = free_ch + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * Disable the 1510 compatibility mode and set the sync device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) p->dma_write(dev_id | (1 << 10), CCR, free_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) } else if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) p->dma_write(dev_id, CCR, free_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *dma_ch_out = free_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) EXPORT_SYMBOL(omap_request_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) void omap_free_dma(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (dma_chan[lch].dev_id == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Disable all DMA interrupts for the channel. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) omap_disable_channel_irq(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /* Make sure the DMA transfer is stopped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) p->dma_write(0, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) spin_lock_irqsave(&dma_chan_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dma_chan[lch].dev_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dma_chan[lch].next_lch = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) dma_chan[lch].callback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) spin_unlock_irqrestore(&dma_chan_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) EXPORT_SYMBOL(omap_free_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * Clears any DMA state so the DMA engine is ready to restart with new buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * through omap_start_dma(). Any buffers in flight are discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static void omap_clear_dma(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) p->clear_dma(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) void omap_start_dma(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * The CPC/CDAC register needs to be initialized to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * before starting dma transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (dma_omap15xx())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) p->dma_write(0, CPC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) p->dma_write(0, CDAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int next_lch, cur_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) char dma_chan_link_map[MAX_LOGICAL_DMA_CH_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* Set the link register of the first channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) enable_lnk(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dma_chan_link_map[lch] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) cur_lch = dma_chan[lch].next_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) next_lch = dma_chan[cur_lch].next_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* The loop case: we've been here already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (dma_chan_link_map[cur_lch])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* Mark the current channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dma_chan_link_map[cur_lch] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) enable_lnk(cur_lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) omap_enable_channel_irq(cur_lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) cur_lch = next_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) } while (next_lch != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) p->dma_write(lch, CLNK_CTRL, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) omap_enable_channel_irq(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) l |= OMAP_DMA_CCR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * As dma_write() uses IO accessors which are weakly ordered, there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * is no guarantee that data in coherent DMA memory will be visible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * to the DMA device. Add a memory barrier here to ensure that any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * such data is visible prior to enabling DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) p->dma_write(l, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) EXPORT_SYMBOL(omap_start_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) void omap_stop_dma(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* Disable all interrupts on the channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) omap_disable_channel_irq(lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) u32 sys_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* Configure No-Standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) l = p->dma_read(OCP_SYSCONFIG, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) sys_cf = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) p->dma_write(l , OCP_SYSCONFIG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) l &= ~OMAP_DMA_CCR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) p->dma_write(l, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* Wait for sDMA FIFO drain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) OMAP_DMA_CCR_WR_ACTIVE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) l = p->dma_read(CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (i >= 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pr_err("DMA drain did not complete on lch %d\n", lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* Restore OCP_SYSCONFIG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) l &= ~OMAP_DMA_CCR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) p->dma_write(l, CCR, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * Ensure that data transferred by DMA is visible to any access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * after DMA has been disabled. This is important for coherent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * DMA regions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int next_lch, cur_lch = lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) char dma_chan_link_map[MAX_LOGICAL_DMA_CH_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* The loop case: we've been here already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (dma_chan_link_map[cur_lch])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Mark the current channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) dma_chan_link_map[cur_lch] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) disable_lnk(cur_lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) next_lch = dma_chan[cur_lch].next_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) cur_lch = next_lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) } while (next_lch != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) EXPORT_SYMBOL(omap_stop_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * Allows changing the DMA callback function or data. This may be needed if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * the driver shares a single DMA channel for multiple dma triggers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * Returns current physical source address for the given DMA channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * If the channel is running the caller must disable interrupts prior calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * this function and process the returned value before re-enabling interrupt to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * prevent races with the interrupt handler. Note that in continuous mode there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * is a chance for CSSA_L register overflow between the two reads resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * in incorrect return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dma_addr_t omap_get_dma_src_pos(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) dma_addr_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (dma_omap15xx())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) offset = p->dma_read(CPC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) offset = p->dma_read(CSAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) offset = p->dma_read(CSAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (!dma_omap15xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * CDAC == 0 indicates that the DMA transfer on the channel has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * not been started (no data has been transferred so far).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * Return the programmed source start address in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (likely(p->dma_read(CDAC, lch)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) offset = p->dma_read(CSAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) offset = p->dma_read(CSSA, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) EXPORT_SYMBOL(omap_get_dma_src_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Returns current physical destination address for the given DMA channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * If the channel is running the caller must disable interrupts prior calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * this function and process the returned value before re-enabling interrupt to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * prevent races with the interrupt handler. Note that in continuous mode there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * is a chance for CDSA_L register overflow between the two reads resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * in incorrect return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) dma_addr_t omap_get_dma_dst_pos(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dma_addr_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (dma_omap15xx())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) offset = p->dma_read(CPC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) offset = p->dma_read(CDAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * read before the DMA controller finished disabling the channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (!dma_omap15xx() && offset == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) offset = p->dma_read(CDAC, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * CDAC == 0 indicates that the DMA transfer on the channel has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * not been started (no data has been transferred so far).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * Return the programmed destination start address in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (unlikely(!offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) offset = p->dma_read(CDSA, lch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) EXPORT_SYMBOL(omap_get_dma_dst_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int omap_get_dma_active_status(int lch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) EXPORT_SYMBOL(omap_get_dma_active_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) int omap_dma_running(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) int lch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (dma_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (omap_lcd_dma_running())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) for (lch = 0; lch < dma_chan_count; lch++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /*----------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) #ifdef CONFIG_ARCH_OMAP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static int omap1_dma_handle_ch(int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) u32 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (enable_1510_mode && ch >= 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) csr = dma_chan[ch].saved_csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dma_chan[ch].saved_csr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) csr = p->dma_read(CSR, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dma_chan[ch + 6].saved_csr = csr >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) csr &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if ((csr & 0x3f) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (unlikely(dma_chan[ch].dev_id == -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pr_warn("Spurious interrupt from DMA channel %d (CSR %04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ch, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) pr_warn("DMA timeout with device %d\n", dma_chan[ch].dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (unlikely(csr & OMAP_DMA_DROP_IRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) pr_warn("DMA synchronization event drop occurred with device %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dma_chan[ch].dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (likely(csr & OMAP_DMA_BLOCK_IRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (likely(dma_chan[ch].callback != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) int ch = ((int) dev_id) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int handled_now = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) handled_now += omap1_dma_handle_ch(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) handled_now += omap1_dma_handle_ch(ch + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (!handled_now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) handled += handled_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return handled ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) #define omap1_dma_irq_handler NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct omap_system_dma_plat_info *omap_get_plat_info(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) EXPORT_SYMBOL_GPL(omap_get_plat_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static int omap_system_dma_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) int ch, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) int dma_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) char irq_name[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) p = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) "%s: System DMA initialized without platform data\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) d = p->dma_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) errata = p->errata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) && (omap_dma_reserve_channels < d->lch_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) d->lch_count = omap_dma_reserve_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dma_lch_count = d->lch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dma_chan_count = dma_lch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dma_chan = devm_kcalloc(&pdev->dev, dma_lch_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) sizeof(*dma_chan), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (!dma_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) spin_lock_init(&dma_chan_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) for (ch = 0; ch < dma_chan_count; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) omap_clear_dma(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) dma_chan[ch].dev_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) dma_chan[ch].next_lch = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (ch >= 6 && enable_1510_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (dma_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * request_irq() doesn't like dev_id (ie. ch) being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * zero, so we have to kludge around this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) sprintf(&irq_name[0], "%d", ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) dma_irq = platform_get_irq_byname(pdev, irq_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (dma_irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ret = dma_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) goto exit_dma_irq_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /* INT_DMA_LCD is handled in lcd_dma.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (dma_irq == INT_DMA_LCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ret = request_irq(dma_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) omap1_dma_irq_handler, 0, "DMA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) (void *) (ch + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) goto exit_dma_irq_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* reserve dma channels 0 and 1 in high security devices on 34xx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (d->dev_caps & HS_CHANNELS_RESERVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) dma_chan[0].dev_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) dma_chan[1].dev_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) p->show_dma_caps();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) exit_dma_irq_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static int omap_system_dma_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) int dma_irq, irq_rel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (dma_omap2plus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) for ( ; irq_rel < dma_chan_count; irq_rel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) dma_irq = platform_get_irq(pdev, irq_rel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) free_irq(dma_irq, (void *)(irq_rel + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static struct platform_driver omap_system_dma_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .probe = omap_system_dma_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .remove = omap_system_dma_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .name = "omap_dma_system"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) static int __init omap_system_dma_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return platform_driver_register(&omap_system_dma_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) arch_initcall(omap_system_dma_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static void __exit omap_system_dma_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) platform_driver_unregister(&omap_system_dma_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) MODULE_AUTHOR("Texas Instruments Inc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * Reserve the omap SDMA channels using cmdline bootarg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * "omap_dma_reserve_ch=". The valid range is 1 to 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static int __init omap_dma_cmdline_reserve_ch(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (get_option(&str, &omap_dma_reserve_channels) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) omap_dma_reserve_channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) __setup("omap_dma_reserve_ch=", omap_dma_cmdline_reserve_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)