1/* 2 * 3 * BRIEF MODULE DESCRIPTION 4 * A DMA channel allocator for Au1000. API is modeled loosely off of 5 * linux/kernel/dma.c. 6 * 7 * Copyright 2000 MontaVista Software Inc. 8 * Author: MontaVista Software, Inc. 9 * stevel@mvista.com or source@mvista.com 10 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 * 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * You should have received a copy of the GNU General Public License along 29 * with this program; if not, write to the Free Software Foundation, Inc., 30 * 675 Mass Ave, Cambridge, MA 02139, USA. 31 * 32 */ 33#include <linux/module.h> 34#include <linux/kernel.h> 35#include <linux/errno.h> 36#include <linux/sched.h> 37#include <linux/spinlock.h> 38#include <linux/string.h> 39#include <linux/delay.h> 40#include <linux/interrupt.h> 41#include <asm/system.h> 42#include <asm/mach-au1x00/au1000.h> 43#include <asm/mach-au1x00/au1000_dma.h> 44 45#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \ 46 defined(CONFIG_SOC_AU1100) 47/* 48 * A note on resource allocation: 49 * 50 * All drivers needing DMA channels, should allocate and release them 51 * through the public routines `request_dma()' and `free_dma()'. 52 * 53 * In order to avoid problems, all processes should allocate resources in 54 * the same sequence and release them in the reverse order. 55 * 56 * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. 57 * When releasing them, first release the IRQ, then release the DMA. The 58 * main reason for this order is that, if you are requesting the DMA buffer 59 * done interrupt, you won't know the irq number until the DMA channel is 60 * returned from request_dma. 61 */ 62 63 64DEFINE_SPINLOCK(au1000_dma_spin_lock); 65 66struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = { 67 {.dev_id = -1,}, 68 {.dev_id = -1,}, 69 {.dev_id = -1,}, 70 {.dev_id = -1,}, 71 {.dev_id = -1,}, 72 {.dev_id = -1,}, 73 {.dev_id = -1,}, 74 {.dev_id = -1,} 75}; 76EXPORT_SYMBOL(au1000_dma_table); 77 78// Device FIFO addresses and default DMA modes 79static const struct dma_dev { 80 unsigned int fifo_addr; 81 unsigned int dma_mode; 82} dma_dev_table[DMA_NUM_DEV] = { 83 {UART0_ADDR + UART_TX, 0}, 84 {UART0_ADDR + UART_RX, 0}, 85 {0, 0}, 86 {0, 0}, 87 {AC97C_DATA, DMA_DW16 }, // coherent 88 {AC97C_DATA, DMA_DR | DMA_DW16 }, // coherent 89 {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC}, 90 {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC}, 91 {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC}, 92 {USBD_EP0WR, DMA_DW8 | DMA_NC}, 93 {USBD_EP2WR, DMA_DW8 | DMA_NC}, 94 {USBD_EP3WR, DMA_DW8 | DMA_NC}, 95 {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC}, 96 {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC}, 97 {I2S_DATA, DMA_DW32 | DMA_NC}, 98 {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC} 99}; 100 101int au1000_dma_read_proc(char *buf, char **start, off_t fpos, 102 int length, int *eof, void *data) 103{ 104 int i, len = 0; 105 struct dma_chan *chan; 106 107 for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { 108 if ((chan = get_dma_chan(i)) != NULL) { 109 len += sprintf(buf + len, "%2d: %s\n", 110 i, chan->dev_str); 111 } 112 } 113 114 if (fpos >= len) { 115 *start = buf; 116 *eof = 1; 117 return 0; 118 } 119 *start = buf + fpos; 120 if ((len -= fpos) > length) 121 return length; 122 *eof = 1; 123 return len; 124} 125 126// Device FIFO addresses and default DMA modes - 2nd bank 127static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = { 128 {SD0_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent 129 {SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8}, // coherent 130 {SD1_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent 131 {SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8} // coherent 132}; 133 134void dump_au1000_dma_channel(unsigned int dmanr) 135{ 136 struct dma_chan *chan; 137 138 if (dmanr >= NUM_AU1000_DMA_CHANNELS) 139 return; 140 chan = &au1000_dma_table[dmanr]; 141 142 printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); 143 printk(KERN_INFO " mode = 0x%08x\n", 144 au_readl(chan->io + DMA_MODE_SET)); 145 printk(KERN_INFO " addr = 0x%08x\n", 146 au_readl(chan->io + DMA_PERIPHERAL_ADDR)); 147 printk(KERN_INFO " start0 = 0x%08x\n", 148 au_readl(chan->io + DMA_BUFFER0_START)); 149 printk(KERN_INFO " start1 = 0x%08x\n", 150 au_readl(chan->io + DMA_BUFFER1_START)); 151 printk(KERN_INFO " count0 = 0x%08x\n", 152 au_readl(chan->io + DMA_BUFFER0_COUNT)); 153 printk(KERN_INFO " count1 = 0x%08x\n", 154 au_readl(chan->io + DMA_BUFFER1_COUNT)); 155} 156 157 158/* 159 * Finds a free channel, and binds the requested device to it. 160 * Returns the allocated channel number, or negative on error. 161 * Requests the DMA done IRQ if irqhandler != NULL. 162 */ 163int request_au1000_dma(int dev_id, const char *dev_str, 164 irq_handler_t irqhandler, 165 unsigned long irqflags, 166 void *irq_dev_id) 167{ 168 struct dma_chan *chan; 169 const struct dma_dev *dev; 170 int i, ret; 171 172#if defined(CONFIG_SOC_AU1100) 173 if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2)) 174 return -EINVAL; 175#else 176 if (dev_id < 0 || dev_id >= DMA_NUM_DEV) 177 return -EINVAL; 178#endif 179 180 for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { 181 if (au1000_dma_table[i].dev_id < 0) 182 break; 183 } 184 if (i == NUM_AU1000_DMA_CHANNELS) 185 return -ENODEV; 186 187 chan = &au1000_dma_table[i]; 188 189 if (dev_id >= DMA_NUM_DEV) { 190 dev_id -= DMA_NUM_DEV; 191 dev = &dma_dev_table_bank2[dev_id]; 192 } else { 193 dev = &dma_dev_table[dev_id]; 194 } 195 196 if (irqhandler) { 197 chan->irq = AU1000_DMA_INT_BASE + i; 198 chan->irq_dev = irq_dev_id; 199 if ((ret = request_irq(chan->irq, irqhandler, irqflags, 200 dev_str, chan->irq_dev))) { 201 chan->irq = 0; 202 chan->irq_dev = NULL; 203 return ret; 204 } 205 } else { 206 chan->irq = 0; 207 chan->irq_dev = NULL; 208 } 209 210 // fill it in 211 chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN; 212 chan->dev_id = dev_id; 213 chan->dev_str = dev_str; 214 chan->fifo_addr = dev->fifo_addr; 215 chan->mode = dev->dma_mode; 216 217 /* initialize the channel before returning */ 218 init_dma(i); 219 220 return i; 221} 222EXPORT_SYMBOL(request_au1000_dma); 223 224void free_au1000_dma(unsigned int dmanr) 225{ 226 struct dma_chan *chan = get_dma_chan(dmanr); 227 if (!chan) { 228 printk("Trying to free DMA%d\n", dmanr); 229 return; 230 } 231 232 disable_dma(dmanr); 233 if (chan->irq) 234 free_irq(chan->irq, chan->irq_dev); 235 236 chan->irq = 0; 237 chan->irq_dev = NULL; 238 chan->dev_id = -1; 239} 240EXPORT_SYMBOL(free_au1000_dma); 241 242#endif // AU1000 AU1500 AU1100 243