1 /******************************************************************
2 * Copyright 2005 Mentor Graphics Corporation
3 * Copyright (C) 2005-2006 by Texas Instruments
5 * This file is part of the Inventra Controller Driver for Linux.
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
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.
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
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 ******************************************************************/
35 * DMA implementation for high-speed controllers.
41 /****************************** CONSTANTS ********************************/
43 #define MGC_O_HSDMA_BASE 0x200
44 #define MGC_O_HSDMA_INTR 0x200
46 #define MGC_O_HSDMA_CONTROL 4
47 #define MGC_O_HSDMA_ADDRESS 8
48 #define MGC_O_HSDMA_COUNT 0xc
50 #define MGC_HSDMA_CHANNEL_OFFSET(_bChannel, _bOffset) \
51 (MGC_O_HSDMA_BASE + (_bChannel << 4) + _bOffset)
53 /* control register (16-bit): */
54 #define MGC_S_HSDMA_ENABLE 0
55 #define MGC_S_HSDMA_TRANSMIT 1
56 #define MGC_S_HSDMA_MODE1 2
57 #define MGC_S_HSDMA_IRQENABLE 3
58 #define MGC_S_HSDMA_ENDPOINT 4
59 #define MGC_S_HSDMA_BUSERROR 8
60 #define MGC_S_HSDMA_BURSTMODE 9
61 #define MGC_M_HSDMA_BURSTMODE (3 << MGC_S_HSDMA_BURSTMODE)
62 #define MGC_HSDMA_BURSTMODE_UNSPEC 0
63 #define MGC_HSDMA_BURSTMODE_INCR4 1
64 #define MGC_HSDMA_BURSTMODE_INCR8 2
65 #define MGC_HSDMA_BURSTMODE_INCR16 3
67 #define MGC_HSDMA_CHANNELS 8
69 /******************************* Types ********************************/
71 struct _MGC_HsDmaController;
74 struct dma_channel Channel;
75 struct _MGC_HsDmaController *pController;
84 struct dma_controller Controller;
85 MGC_HsDmaChannel aChannel[MGC_HSDMA_CHANNELS];
87 void __iomem *pCoreBase;
92 /* FIXME remove typedef noise */
93 typedef struct hsdma MGC_HsDmaController;
95 /****************************** FUNCTIONS ********************************/
97 static int MGC_HsDmaStartController(struct dma_controller *c)
103 static int MGC_HsDmaStopController(struct dma_controller *c)
109 static struct dma_channel *MGC_HsDmaAllocateChannel(
110 struct dma_controller *c,
111 struct musb_hw_ep *hw_ep,
115 struct dma_channel *pChannel = NULL;
116 MGC_HsDmaChannel *pImplChannel = NULL;
117 MGC_HsDmaController *pController;
119 pcontroller = container_of(c, struct hsdma, Controller);
120 for (bBit = 0; bBit < MGC_HSDMA_CHANNELS; bBit++) {
121 if (!(pController->bmUsedChannels & (1 << bBit))) {
122 pController->bmUsedChannels |= (1 << bBit);
123 pImplChannel = &(pController->aChannel[bBit]);
124 pImplChannel->pController = pController;
125 pImplChannel->bIndex = bBit;
126 pImplChannel->bEnd = hw_ep->bLocalEnd;
127 pImplChannel->bTransmit = bTransmit;
128 pChannel = &(pImplChannel->Channel);
129 pChannel->pPrivateData = pImplChannel;
130 pChannel->bStatus = MGC_DMA_STATUS_FREE;
131 pChannel->dwMaxLength = 0x10000;
132 /* Tx => mode 1; Rx => mode 0 */
133 pChannel->bDesiredMode = bTransmit;
134 pChannel->dwActualLength = 0;
141 static void MGC_HsDmaReleaseChannel(struct dma_channel *pChannel)
143 MGC_HsDmaChannel *pImplChannel =
144 (MGC_HsDmaChannel *) pChannel->pPrivateData;
146 pImplChannel->pController->bmUsedChannels &=
147 ~(1 << pImplChannel->bIndex);
148 pChannel->bStatus = MGC_DMA_STATUS_FREE;
151 static void clear_state(struct dma_channel *pChannel)
153 MGC_HsDmaChannel *pImplChannel =
154 (MGC_HsDmaChannel *) pChannel->pPrivateData;
155 MGC_HsDmaController *pController = pImplChannel->pController;
156 u8 *pBase = pController->pCoreBase;
157 u8 bChannel = pImplChannel->bIndex;
160 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_CONTROL),
163 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_ADDRESS),
166 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_COUNT),
169 pChannel->dwActualLength = 0L;
170 pImplChannel->dwStartAddress = 0;
171 pImplChannel->dwCount = 0;
174 static u8 configure_channel(struct dma_channel *pChannel,
175 u16 wPacketSize, u8 bMode,
176 dma_addr_t dma_addr, u32 dwLength)
178 MGC_HsDmaChannel *pImplChannel =
179 (MGC_HsDmaChannel *) pChannel->pPrivateData;
180 MGC_HsDmaController *pController = pImplChannel->pController;
181 u8 *pBase = pController->pCoreBase;
182 u8 bChannel = pImplChannel->bIndex;
185 DBG(2, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
186 pChannel, wPacketSize, dma_addr, dwLength, bMode);
189 wCsr |= 1 << MGC_S_HSDMA_MODE1;
190 if (dwLength < wPacketSize) {
193 if (wPacketSize >= 64) {
195 MGC_HSDMA_BURSTMODE_INCR16 << MGC_S_HSDMA_BURSTMODE;
196 } else if (wPacketSize >= 32) {
198 MGC_HSDMA_BURSTMODE_INCR8 << MGC_S_HSDMA_BURSTMODE;
199 } else if (wPacketSize >= 16) {
201 MGC_HSDMA_BURSTMODE_INCR4 << MGC_S_HSDMA_BURSTMODE;
205 wCsr |= (pImplChannel->bEnd << MGC_S_HSDMA_ENDPOINT)
206 | (1 << MGC_S_HSDMA_ENABLE)
207 | (1 << MGC_S_HSDMA_IRQENABLE)
208 | (pImplChannel->bTransmit ? (1 << MGC_S_HSDMA_TRANSMIT) : 0);
212 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_ADDRESS),
215 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_COUNT),
218 /* control (this should start things) */
220 MGC_HSDMA_CHANNEL_OFFSET(bChannel, MGC_O_HSDMA_CONTROL),
226 static int MGC_HsDmaProgramChannel(struct dma_channel * pChannel,
227 u16 wPacketSize, u8 bMode,
228 dma_addr_t dma_addr, u32 dwLength)
230 MGC_HsDmaChannel *pImplChannel =
231 (MGC_HsDmaChannel *) pChannel->pPrivateData;
233 DBG(2, "pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
234 wPacketSize, dma_addr, dwLength, bMode);
236 BUG_ON(pChannel->bStatus != MGC_DMA_STATUS_FREE);
238 pChannel->dwActualLength = 0L;
239 pImplChannel->dwStartAddress = dma_addr;
240 pImplChannel->dwCount = dwLength;
242 pChannel->bStatus = MGC_DMA_STATUS_BUSY;
244 if ((bMode == 1) && (dwLength >= wPacketSize)) {
247 /* mode 1 sends an extra IN token at the end of
248 * full packet transfer in host Rx
250 if (dwLength % wPacketSize == 0)
251 dwLength -= wPacketSize;
253 /* mode 1 doesn't give an interrupt on short packet */
254 configure_channel(pChannel, wPacketSize, 1, dma_addr,
255 dwLength & ~(wPacketSize - 1));
256 /* the rest (<= pkt_size) will be transferred in mode 0 */
259 configure_channel(pChannel, wPacketSize, 1, dma_addr,
263 configure_channel(pChannel, wPacketSize, 0, dma_addr,
270 static int MGC_HsDmaAbortChannel(struct dma_channel *pChannel)
272 clear_state(pChannel);
273 pChannel->bStatus = MGC_DMA_STATUS_FREE;
278 hsdma_irq(int irq, void *pPrivateData, struct pt_regs *regs)
283 MGC_HsDmaChannel *pImplChannel;
284 MGC_HsDmaController *pController = pPrivateData;
285 u8 *pBase = pController->pCoreBase;
286 struct dma_channel *pChannel;
287 u8 bIntr = musb_readb(pBase, MGC_O_HSDMA_INTR);
292 for (bChannel = 0; bChannel < MGC_HSDMA_CHANNELS; bChannel++) {
293 if (bIntr & (1 << bChannel)) {
295 pImplChannel = (MGC_HsDmaChannel *)
296 &(pController->aChannel[bChannel]);
297 pChannel = &pImplChannel->Channel;
299 wCsr = musb_readw(pBase,
300 MGC_HSDMA_CHANNEL_OFFSET(bChannel,
301 MGC_O_HSDMA_CONTROL));
303 if (wCsr & (1 << MGC_S_HSDMA_BUSERROR)) {
304 pImplChannel->Channel.bStatus =
305 MGC_DMA_STATUS_BUS_ABORT;
307 dwAddress = musb_readl(pBase,
308 MGC_HSDMA_CHANNEL_OFFSET
310 MGC_O_HSDMA_ADDRESS));
311 pChannel->dwActualLength =
312 dwAddress - pImplChannel->dwStartAddress;
314 DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
315 pChannel, pImplChannel->dwStartAddress,
316 dwAddress, pChannel->dwActualLength,
317 pImplChannel->dwCount,
318 (pChannel->dwActualLength <
319 pImplChannel->dwCount) ?
320 "=> reconfig 0": "=> complete");
322 if (pChannel->dwActualLength <
323 pImplChannel->dwCount) {
324 /* mode 1 sends an extra IN request if
325 the last packet is a complete packet */
326 u16 newcsr = MGC_ReadCsr16(pBase,
329 newcsr &= ~(MGC_M_RXCSR_H_AUTOREQ |
330 MGC_M_RXCSR_H_REQPKT);
331 MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR,
333 MGC_M_RXCSR_H_WZC_BITS |
336 configure_channel(pChannel,
337 pImplChannel->wMaxPacketSize,
339 pImplChannel->dwCount -
340 pChannel->dwActualLength);
345 pChannel->bStatus = MGC_DMA_STATUS_FREE;
348 pController->pDmaPrivate,
350 pImplChannel->bTransmit);
358 static void hsdma_controller_destroy(struct dma_controller *pController)
360 MGC_HsDmaController *pHsController = pController->pPrivateData;
363 pHsController->Controller.pPrivateData = NULL;
364 kfree(pHsController);
368 static struct dma_controller *
369 hsdma_controller_new(struct musb *pThis, void __iomem *pCoreBase)
371 MGC_HsDmaController *pController;
372 struct device *dev = pThis->controller;
373 struct platform_device *pdev = to_platform_device(dev);
374 int irq = platform_get_irq(pdev, 1);
377 dev_err(dev, "No DMA interrupt line!\n");
381 if (!(pController = kzalloc(sizeof(MGC_HsDmaController), GFP_KERNEL)))
384 pController->bChannelCount = MGC_HSDMA_CHANNELS;
385 pController->pDmaPrivate = pThis;
386 pController->pCoreBase = pCoreBase;
388 pController->Controller.pPrivateData = pController;
389 pController->Controller.start = MGC_HsDmaStartController;
390 pController->Controller.stop = MGC_HsDmaStopController;
391 pController->Controller.channel_alloc = MGC_HsDmaAllocateChannel;
392 pController->Controller.channel_release = MGC_HsDmaReleaseChannel;
393 pController->Controller.channel_program = MGC_HsDmaProgramChannel;
394 pController->Controller.channel_abort = MGC_HsDmaAbortChannel;
396 if (request_irq(irq, hsdma_irq, SA_INTERRUPT,
397 pThis->controller->bus_id, &pController->Controller)) {
398 dev_err(dev, "request_irq %d failed!\n", irq);
399 hsdma_controller_destroy(&pController->Controller);
403 return &pController->Controller;
406 const struct dma_controller_factory dma_controller_factory = {
407 .create = hsdma_controller_new,
408 .destroy = hsdma_controller_destroy,