]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/usb/musb/musbhsdma.c
Merge omap-drivers
[linux-2.6-omap-h63xx.git] / drivers / usb / musb / musbhsdma.c
1 /******************************************************************
2  * Copyright 2005 Mentor Graphics Corporation
3  * Copyright (C) 2005-2006 by Texas Instruments
4  *
5  * This file is part of the Inventra Controller Driver for Linux.
6  *
7  * The Inventra Controller Driver for Linux is free software; you
8  * can redistribute it and/or modify it under the terms of the GNU
9  * General Public License version 2 as published by the Free Software
10  * Foundation.
11  *
12  * The Inventra Controller Driver for Linux is distributed in
13  * the hope that it will be useful, but WITHOUT ANY WARRANTY;
14  * without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with The Inventra Controller Driver for Linux ; if not,
20  * write to the Free Software Foundation, Inc., 59 Temple Place,
21  * Suite 330, Boston, MA  02111-1307  USA
22  *
23  * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
24  * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
25  * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
26  * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
27  * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
28  * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
29  * NON-INFRINGEMENT.  MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
30  * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
31  * GRAPHICS SUPPORT CUSTOMER.
32  ******************************************************************/
33
34 /*
35  * Interface to Mentor's DMA engine
36  */
37
38 #include <linux/platform_device.h>
39
40 #include "musbdefs.h"
41
42
43 /****************************** CONSTANTS ********************************/
44
45 #define MGC_O_HSDMA_BASE    0x200
46 #define MGC_O_HSDMA_INTR    0x200
47
48 #define MGC_O_HSDMA_CONTROL 4
49 #define MGC_O_HSDMA_ADDRESS 8
50 #define MGC_O_HSDMA_COUNT   0xc
51
52 #define MGC_HSDMA_CHANNEL_OFFSET(_bChannel, _bOffset)           \
53                 (MGC_O_HSDMA_BASE + (_bChannel << 4) + _bOffset)
54
55 /* control register (16-bit): */
56 #define MGC_S_HSDMA_ENABLE      0
57 #define MGC_S_HSDMA_TRANSMIT    1
58 #define MGC_S_HSDMA_MODE1       2
59 #define MGC_S_HSDMA_IRQENABLE   3
60 #define MGC_S_HSDMA_ENDPOINT    4
61 #define MGC_S_HSDMA_BUSERROR    8
62 #define MGC_S_HSDMA_BURSTMODE   9
63 #define MGC_M_HSDMA_BURSTMODE   (3 << MGC_S_HSDMA_BURSTMODE)
64 #define MGC_HSDMA_BURSTMODE_UNSPEC  0
65 #define MGC_HSDMA_BURSTMODE_INCR4   1
66 #define MGC_HSDMA_BURSTMODE_INCR8   2
67 #define MGC_HSDMA_BURSTMODE_INCR16  3
68
69 #define MGC_HSDMA_CHANNELS 8
70
71 /******************************* Types ********************************/
72
73 struct hsdma_channel {
74         struct dma_channel Channel;
75         struct hsdma *pController;
76         u32 dwStartAddress;
77         u32 dwCount;
78         u8 bIndex;
79         u8 bEnd;
80         u8 bTransmit;
81 };
82
83 struct hsdma {
84         struct dma_controller Controller;
85         struct hsdma_channel aChannel[MGC_HSDMA_CHANNELS];
86         void *pDmaPrivate;
87         void __iomem *pCoreBase;
88         u8 bChannelCount;
89         u8 bmUsedChannels;
90 };
91
92 /****************************** FUNCTIONS ********************************/
93
94 static int hsdma_start(struct dma_controller *c)
95 {
96         /* nothing to do */
97         return 0;
98 }
99
100 static int hsdma_stop(struct dma_controller *c)
101 {
102         /* nothing to do */
103         return 0;
104 }
105
106 static struct dma_channel *
107 hsdma_channel_alloc(struct dma_controller *c,
108                 struct musb_hw_ep *hw_ep,
109                 u8 bTransmit)
110 {
111         u8 bBit;
112         struct dma_channel *pChannel = NULL;
113         struct hsdma_channel *pImplChannel = NULL;
114         struct hsdma *pController;
115
116         pController = container_of(c, struct hsdma, Controller);
117         for (bBit = 0; bBit < MGC_HSDMA_CHANNELS; bBit++) {
118                 if (!(pController->bmUsedChannels & (1 << bBit))) {
119                         pController->bmUsedChannels |= (1 << bBit);
120                         pImplChannel = &(pController->aChannel[bBit]);
121                         pImplChannel->pController = pController;
122                         pImplChannel->bIndex = bBit;
123                         pImplChannel->bEnd = hw_ep->bLocalEnd;
124                         pImplChannel->bTransmit = bTransmit;
125                         pChannel = &(pImplChannel->Channel);
126                         pChannel->pPrivateData = pImplChannel;
127                         pChannel->bStatus = MGC_DMA_STATUS_FREE;
128                         pChannel->dwMaxLength = 0x10000;
129                         /* Tx => mode 1; Rx => mode 0 */
130                         pChannel->bDesiredMode = bTransmit;
131                         pChannel->dwActualLength = 0;
132                         break;
133                 }
134         }
135         return pChannel;
136 }
137
138 static void hsdma_channel_release(struct dma_channel *pChannel)
139 {
140         struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
141
142         pImplChannel->pController->bmUsedChannels &=
143             ~(1 << pImplChannel->bIndex);
144         pChannel->bStatus = MGC_DMA_STATUS_FREE;
145 }
146
147 static void clear_state(struct dma_channel *pChannel)
148 {
149         struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
150         struct hsdma *pController = pImplChannel->pController;
151         u8 *pBase = pController->pCoreBase;
152         u8 bChannel = pImplChannel->bIndex;
153
154         musb_writew(pBase,
155                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_CONTROL),
156                     0);
157         musb_writel(pBase,
158                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_ADDRESS),
159                     0);
160         musb_writel(pBase,
161                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_COUNT),
162                     0);
163
164         pChannel->dwActualLength = 0L;
165         pImplChannel->dwStartAddress = 0;
166         pImplChannel->dwCount = 0;
167 }
168
169 static u8 configure_channel(struct dma_channel *pChannel,
170                                   u16 wPacketSize, u8 bMode,
171                                   dma_addr_t dma_addr, u32 dwLength)
172 {
173         struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
174         struct hsdma *pController = pImplChannel->pController;
175         u8 *pBase = pController->pCoreBase;
176         u8 bChannel = pImplChannel->bIndex;
177         u16 wCsr = 0;
178
179         DBG(2, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
180             pChannel, wPacketSize, dma_addr, dwLength, bMode);
181
182         if (bMode) {
183                 wCsr |= 1 << MGC_S_HSDMA_MODE1;
184                 if (dwLength < wPacketSize) {
185                         return FALSE;
186                 }
187                 if (wPacketSize >= 64) {
188                         wCsr |=
189                             MGC_HSDMA_BURSTMODE_INCR16 << MGC_S_HSDMA_BURSTMODE;
190                 } else if (wPacketSize >= 32) {
191                         wCsr |=
192                             MGC_HSDMA_BURSTMODE_INCR8 << MGC_S_HSDMA_BURSTMODE;
193                 } else if (wPacketSize >= 16) {
194                         wCsr |=
195                             MGC_HSDMA_BURSTMODE_INCR4 << MGC_S_HSDMA_BURSTMODE;
196                 }
197         }
198
199         wCsr |= (pImplChannel->bEnd << MGC_S_HSDMA_ENDPOINT)
200                 | (1 << MGC_S_HSDMA_ENABLE)
201                 | (1 << MGC_S_HSDMA_IRQENABLE)
202                 | (pImplChannel->bTransmit ? (1 << MGC_S_HSDMA_TRANSMIT) : 0);
203
204         /* address/count */
205         musb_writel(pBase,
206                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_ADDRESS),
207                     dma_addr);
208         musb_writel(pBase,
209                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_COUNT),
210                     dwLength);
211
212         /* control (this should start things) */
213         musb_writew(pBase,
214                     MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_CONTROL),
215                     wCsr);
216
217         return TRUE;
218 }
219
220 static int hsdma_channel_program(struct dma_channel * pChannel,
221                                   u16 wPacketSize, u8 bMode,
222                                   dma_addr_t dma_addr, u32 dwLength)
223 {
224         struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
225
226         DBG(2, "pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
227                wPacketSize, dma_addr, dwLength, bMode);
228
229         BUG_ON(pChannel->bStatus != MGC_DMA_STATUS_FREE);
230
231         pChannel->dwActualLength = 0L;
232         pImplChannel->dwStartAddress = dma_addr;
233         pImplChannel->dwCount = dwLength;
234
235         pChannel->bStatus = MGC_DMA_STATUS_BUSY;
236
237         if ((bMode == 1) && (dwLength >= wPacketSize)) {
238
239 #if 0
240                 /* mode 1 sends an extra IN token at the end of
241                  * full packet transfer in host Rx
242                  */
243                 if (dwLength % wPacketSize == 0)
244                         dwLength -= wPacketSize;
245
246                 /* mode 1 doesn't give an interrupt on short packet */
247                 configure_channel(pChannel, wPacketSize, 1, dma_addr,
248                                   dwLength & ~(wPacketSize - 1));
249                 /* the rest (<= pkt_size) will be transferred in mode 0 */
250 #endif
251
252                 configure_channel(pChannel, wPacketSize, 1, dma_addr,
253                                   dwLength);
254
255         } else
256                 configure_channel(pChannel, wPacketSize, 0, dma_addr,
257                                   dwLength);
258
259         return TRUE;
260 }
261
262 // REVISIT...
263 static int hsdma_channel_abort(struct dma_channel *pChannel)
264 {
265         clear_state(pChannel);
266         pChannel->bStatus = MGC_DMA_STATUS_FREE;
267         return 0;
268 }
269
270 static irqreturn_t hsdma_irq(int irq, void *pPrivateData)
271 {
272         u8 bChannel;
273         u16 wCsr;
274         u32 dwAddress;
275         struct hsdma_channel *pImplChannel;
276         struct hsdma *pController = pPrivateData;
277         u8 *pBase = pController->pCoreBase;
278         struct dma_channel *pChannel;
279         u8 bIntr = musb_readb(pBase, MGC_O_HSDMA_INTR);
280
281         if (!bIntr)
282                 return IRQ_NONE;
283
284         for (bChannel = 0; bChannel < MGC_HSDMA_CHANNELS; bChannel++) {
285                 if (bIntr & (1 << bChannel)) {
286
287                         pImplChannel = &pController->aChannel[bChannel];
288                         pChannel = &pImplChannel->Channel;
289
290                         wCsr = musb_readw(pBase,
291                                        MGC_HSDMA_CHANNEL_OFFSET(bChannel,
292                                                         MGC_O_HSDMA_CONTROL));
293
294                         if (wCsr & (1 << MGC_S_HSDMA_BUSERROR)) {
295                                 pImplChannel->Channel.bStatus =
296                                     MGC_DMA_STATUS_BUS_ABORT;
297                         } else {
298                                 dwAddress = musb_readl(pBase,
299                                                        MGC_HSDMA_CHANNEL_OFFSET
300                                                        (bChannel,
301                                                         MGC_O_HSDMA_ADDRESS));
302                                 pChannel->dwActualLength =
303                                     dwAddress - pImplChannel->dwStartAddress;
304
305                                 DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
306                                     pChannel, pImplChannel->dwStartAddress,
307                                     dwAddress, pChannel->dwActualLength,
308                                     pImplChannel->dwCount,
309                                     (pChannel->dwActualLength <
310                                         pImplChannel->dwCount) ?
311                                         "=> reconfig 0": "=> complete");
312 #if 0
313                                 if (pChannel->dwActualLength <
314                                     pImplChannel->dwCount) {
315                                         /* mode 1 sends an extra IN request if
316                                         the last packet is a complete packet */
317                                         u16 newcsr = MGC_ReadCsr16(pBase,
318                                                         MGC_O_HDRC_RXCSR,
319                                                         pImplChannel->bEnd);
320                                         newcsr &= ~(MGC_M_RXCSR_H_AUTOREQ |
321                                                     MGC_M_RXCSR_H_REQPKT);
322                                         MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR,
323                                                        pImplChannel->bEnd,
324                                                        MGC_M_RXCSR_H_WZC_BITS |
325                                                                 newcsr);
326
327                                         configure_channel(pChannel,
328                                                 pImplChannel->wMaxPacketSize,
329                                                 0, dwAddress,
330                                                 pImplChannel->dwCount -
331                                                     pChannel->dwActualLength);
332                                 }
333                                 else
334 #endif
335                                 {
336                                         pChannel->bStatus = MGC_DMA_STATUS_FREE;
337                                         /* completed */
338                                         musb_dma_completion(
339                                                 pController->pDmaPrivate,
340                                                 pImplChannel->bEnd,
341                                                 pImplChannel->bTransmit);
342                                 }
343                         }
344                 }
345         }
346         return IRQ_HANDLED;
347 }
348
349 void dma_controller_destroy(struct dma_controller *pController)
350 {
351         struct hsdma *pHsController = pController->pPrivateData;
352
353         pHsController->Controller.pPrivateData = NULL;
354         kfree(pHsController);
355 }
356
357 struct dma_controller *__init
358 dma_controller_create(struct musb *pThis, void __iomem *pCoreBase)
359 {
360         struct hsdma *pController;
361         struct device *dev = pThis->controller;
362         struct platform_device *pdev = to_platform_device(dev);
363         int irq = platform_get_irq(pdev, 1);
364
365         if (irq == 0) {
366                 dev_err(dev, "No DMA interrupt line!\n");
367                 return NULL;
368         }
369
370         if (!(pController = kzalloc(sizeof *pController, GFP_KERNEL)))
371                 return NULL;
372
373         pController->bChannelCount = MGC_HSDMA_CHANNELS;
374         pController->pDmaPrivate = pThis;
375         pController->pCoreBase = pCoreBase;
376
377         pController->Controller.pPrivateData = pController;
378         pController->Controller.start = hsdma_start;
379         pController->Controller.stop = hsdma_stop;
380         pController->Controller.channel_alloc = hsdma_channel_alloc;
381         pController->Controller.channel_release = hsdma_channel_release;
382         pController->Controller.channel_program = hsdma_channel_program;
383         pController->Controller.channel_abort = hsdma_channel_abort;
384
385         if (request_irq(irq, hsdma_irq, IRQF_DISABLED,
386                         pThis->controller->bus_id, &pController->Controller)) {
387                 dev_err(dev, "request_irq %d failed!\n", irq);
388                 kfree(pController);
389                 return NULL;
390         }
391
392         return &pController->Controller;
393 }