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/module.h>
8 #include <linux/kernel.h>
9 #include <linux/types.h>
10 #include <linux/init.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 
__ebus_dma_reset(struct ebus_dma_info * p,int no_drain)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 
ebus_dma_irq(int irq,void * dev_id)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 
ebus_dma_register(struct ebus_dma_info * p)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 
ebus_dma_irq_enable(struct ebus_dma_info * p,int on)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 
ebus_dma_unregister(struct ebus_dma_info * p)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 
ebus_dma_request(struct ebus_dma_info * p,dma_addr_t bus_addr,size_t len)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 
ebus_dma_prepare(struct ebus_dma_info * p,int write)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 
ebus_dma_residue(struct ebus_dma_info * p)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 
ebus_dma_addr(struct ebus_dma_info * p)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 
ebus_dma_enable(struct ebus_dma_info * p,int on)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