~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/kernel/ebus.c

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp