1 /* ebus.c: EBUS DMA library code. 2 * 3 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 4 * Copyright (C) 1999 David S. Miller (davem@redhat.com) 5 */ 6 7 #include <linux/export.h> 8 #include <linux/kernel.h> 9 #include <linux/types.h> 10 #include <linux/interrupt.h> 11 #include <linux/delay.h> 12 13 #include <asm/ebus_dma.h> 14 #include <asm/io.h> 15 16 #define EBDMA_CSR 0x00UL /* Control/Status */ 17 #define EBDMA_ADDR 0x04UL /* DMA Address */ 18 #define EBDMA_COUNT 0x08UL /* DMA Count */ 19 20 #define EBDMA_CSR_INT_PEND 0x00000001 21 #define EBDMA_CSR_ERR_PEND 0x00000002 22 #define EBDMA_CSR_DRAIN 0x00000004 23 #define EBDMA_CSR_INT_EN 0x00000010 24 #define EBDMA_CSR_RESET 0x00000080 25 #define EBDMA_CSR_WRITE 0x00000100 26 #define EBDMA_CSR_EN_DMA 0x00000200 27 #define EBDMA_CSR_CYC_PEND 0x00000400 28 #define EBDMA_CSR_DIAG_RD_DONE 0x00000800 29 #define EBDMA_CSR_DIAG_WR_DONE 0x00001000 30 #define EBDMA_CSR_EN_CNT 0x00002000 31 #define EBDMA_CSR_TC 0x00004000 32 #define EBDMA_CSR_DIS_CSR_DRN 0x00010000 33 #define EBDMA_CSR_BURST_SZ_MASK 0x000c0000 34 #define EBDMA_CSR_BURST_SZ_1 0x00080000 35 #define EBDMA_CSR_BURST_SZ_4 0x00000000 36 #define EBDMA_CSR_BURST_SZ_8 0x00040000 37 #define EBDMA_CSR_BURST_SZ_16 0x000c0000 38 #define EBDMA_CSR_DIAG_EN 0x00100000 39 #define EBDMA_CSR_DIS_ERR_PEND 0x00400000 40 #define EBDMA_CSR_TCI_DIS 0x00800000 41 #define EBDMA_CSR_EN_NEXT 0x01000000 42 #define EBDMA_CSR_DMA_ON 0x02000000 43 #define EBDMA_CSR_A_LOADED 0x04000000 44 #define EBDMA_CSR_NA_LOADED 0x08000000 45 #define EBDMA_CSR_DEV_ID_MASK 0xf0000000 46 47 #define EBUS_DMA_RESET_TIMEOUT 10000 48 49 static void __ebus_dma_reset(struct ebus_dma_info *p, int no_drain) 50 { 51 int i; 52 u32 val = 0; 53 54 writel(EBDMA_CSR_RESET, p->regs + EBDMA_CSR); 55 udelay(1); 56 57 if (no_drain) 58 return; 59 60 for (i = EBUS_DMA_RESET_TIMEOUT; i > 0; i--) { 61 val = readl(p->regs + EBDMA_CSR); 62 63 if (!(val & (EBDMA_CSR_DRAIN | EBDMA_CSR_CYC_PEND))) 64 break; 65 udelay(10); 66 } 67 } 68 69 static irqreturn_t ebus_dma_irq(int irq, void *dev_id) 70 { 71 struct ebus_dma_info *p = dev_id; 72 unsigned long flags; 73 u32 csr = 0; 74 75 spin_lock_irqsave(&p->lock, flags); 76 csr = readl(p->regs + EBDMA_CSR); 77 writel(csr, p->regs + EBDMA_CSR); 78 spin_unlock_irqrestore(&p->lock, flags); 79 80 if (csr & EBDMA_CSR_ERR_PEND) { 81 printk(KERN_CRIT "ebus_dma(%s): DMA error!\n", p->name); 82 p->callback(p, EBUS_DMA_EVENT_ERROR, p->client_cookie); 83 return IRQ_HANDLED; 84 } else if (csr & EBDMA_CSR_INT_PEND) { 85 p->callback(p, 86 (csr & EBDMA_CSR_TC) ? 87 EBUS_DMA_EVENT_DMA : EBUS_DMA_EVENT_DEVICE, 88 p->client_cookie); 89 return IRQ_HANDLED; 90 } 91 92 return IRQ_NONE; 93 94 } 95 96 int ebus_dma_register(struct ebus_dma_info *p) 97 { 98 u32 csr; 99 100 if (!p->regs) 101 return -EINVAL; 102 if (p->flags & ~(EBUS_DMA_FLAG_USE_EBDMA_HANDLER | 103 EBUS_DMA_FLAG_TCI_DISABLE)) 104 return -EINVAL; 105 if ((p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) && !p->callback) 106 return -EINVAL; 107 if (!strlen(p->name)) 108 return -EINVAL; 109 110 __ebus_dma_reset(p, 1); 111 112 csr = EBDMA_CSR_BURST_SZ_16 | EBDMA_CSR_EN_CNT; 113 114 if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE) 115 csr |= EBDMA_CSR_TCI_DIS; 116 117 writel(csr, p->regs + EBDMA_CSR); 118 119 return 0; 120 } 121 EXPORT_SYMBOL(ebus_dma_register); 122 123 int ebus_dma_irq_enable(struct ebus_dma_info *p, int on) 124 { 125 unsigned long flags; 126 u32 csr; 127 128 if (on) { 129 if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) { 130 if (request_irq(p->irq, ebus_dma_irq, IRQF_SHARED, p->name, p)) 131 return -EBUSY; 132 } 133 134 spin_lock_irqsave(&p->lock, flags); 135 csr = readl(p->regs + EBDMA_CSR); 136 csr |= EBDMA_CSR_INT_EN; 137 writel(csr, p->regs + EBDMA_CSR); 138 spin_unlock_irqrestore(&p->lock, flags); 139 } else { 140 spin_lock_irqsave(&p->lock, flags); 141 csr = readl(p->regs + EBDMA_CSR); 142 csr &= ~EBDMA_CSR_INT_EN; 143 writel(csr, p->regs + EBDMA_CSR); 144 spin_unlock_irqrestore(&p->lock, flags); 145 146 if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) { 147 free_irq(p->irq, p); 148 } 149 } 150 151 return 0; 152 } 153 EXPORT_SYMBOL(ebus_dma_irq_enable); 154 155 void ebus_dma_unregister(struct ebus_dma_info *p) 156 { 157 unsigned long flags; 158 u32 csr; 159 int irq_on = 0; 160 161 spin_lock_irqsave(&p->lock, flags); 162 csr = readl(p->regs + EBDMA_CSR); 163 if (csr & EBDMA_CSR_INT_EN) { 164 csr &= ~EBDMA_CSR_INT_EN; 165 writel(csr, p->regs + EBDMA_CSR); 166 irq_on = 1; 167 } 168 spin_unlock_irqrestore(&p->lock, flags); 169 170 if (irq_on) 171 free_irq(p->irq, p); 172 } 173 EXPORT_SYMBOL(ebus_dma_unregister); 174 175 int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, size_t len) 176 { 177 unsigned long flags; 178 u32 csr; 179 int err; 180 181 if (len >= (1 << 24)) 182 return -EINVAL; 183 184 spin_lock_irqsave(&p->lock, flags); 185 csr = readl(p->regs + EBDMA_CSR); 186 err = -EINVAL; 187 if (!(csr & EBDMA_CSR_EN_DMA)) 188 goto out; 189 err = -EBUSY; 190 if (csr & EBDMA_CSR_NA_LOADED) 191 goto out; 192 193 writel(len, p->regs + EBDMA_COUNT); 194 writel(bus_addr, p->regs + EBDMA_ADDR); 195 err = 0; 196 197 out: 198 spin_unlock_irqrestore(&p->lock, flags); 199 200 return err; 201 } 202 EXPORT_SYMBOL(ebus_dma_request); 203 204 void ebus_dma_prepare(struct ebus_dma_info *p, int write) 205 { 206 unsigned long flags; 207 u32 csr; 208 209 spin_lock_irqsave(&p->lock, flags); 210 __ebus_dma_reset(p, 0); 211 212 csr = (EBDMA_CSR_INT_EN | 213 EBDMA_CSR_EN_CNT | 214 EBDMA_CSR_BURST_SZ_16 | 215 EBDMA_CSR_EN_NEXT); 216 217 if (write) 218 csr |= EBDMA_CSR_WRITE; 219 if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE) 220 csr |= EBDMA_CSR_TCI_DIS; 221 222 writel(csr, p->regs + EBDMA_CSR); 223 224 spin_unlock_irqrestore(&p->lock, flags); 225 } 226 EXPORT_SYMBOL(ebus_dma_prepare); 227 228 unsigned int ebus_dma_residue(struct ebus_dma_info *p) 229 { 230 return readl(p->regs + EBDMA_COUNT); 231 } 232 EXPORT_SYMBOL(ebus_dma_residue); 233 234 unsigned int ebus_dma_addr(struct ebus_dma_info *p) 235 { 236 return readl(p->regs + EBDMA_ADDR); 237 } 238 EXPORT_SYMBOL(ebus_dma_addr); 239 240 void ebus_dma_enable(struct ebus_dma_info *p, int on) 241 { 242 unsigned long flags; 243 u32 orig_csr, csr; 244 245 spin_lock_irqsave(&p->lock, flags); 246 orig_csr = csr = readl(p->regs + EBDMA_CSR); 247 if (on) 248 csr |= EBDMA_CSR_EN_DMA; 249 else 250 csr &= ~EBDMA_CSR_EN_DMA; 251 if ((orig_csr & EBDMA_CSR_EN_DMA) != 252 (csr & EBDMA_CSR_EN_DMA)) 253 writel(csr, p->regs + EBDMA_CSR); 254 spin_unlock_irqrestore(&p->lock, flags); 255 } 256 EXPORT_SYMBOL(ebus_dma_enable); 257