Commit 91e9c4fec7ee777213859aa1a18bf0b885527637
Committed by
Greg Kroah-Hartman
1 parent
c9cd06b3d6
Exists in
master
and in
39 other branches
musb: split out CPPI interrupt handler
As DaVinci DM646x has a dedicated CPPI DMA interrupt, replace cppi_completion() (which has always been kind of layering violation) by a complete CPPI interrupt handler. [ dbrownell@users.sourceforge.net: only cppi_dma.c needs platform device header, not cppi_dma.h ] Signed-off-by: Dmitry Krivoschekov <dkrivoschekov@ru.mvista.com> Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 3 changed files with 39 additions and 15 deletions Side-by-side Diff
drivers/usb/musb/cppi_dma.c
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci. |
7 | 7 | */ |
8 | 8 | |
9 | +#include <linux/platform_device.h> | |
9 | 10 | #include <linux/usb.h> |
10 | 11 | |
11 | 12 | #include "musb_core.h" |
12 | 13 | |
13 | 14 | |
14 | 15 | |
15 | 16 | |
... | ... | @@ -1145,17 +1146,27 @@ |
1145 | 1146 | return completed; |
1146 | 1147 | } |
1147 | 1148 | |
1148 | -void cppi_completion(struct musb *musb, u32 rx, u32 tx) | |
1149 | +irqreturn_t cppi_interrupt(int irq, void *dev_id) | |
1149 | 1150 | { |
1150 | - void __iomem *tibase; | |
1151 | - int i, index; | |
1151 | + struct musb *musb = dev_id; | |
1152 | 1152 | struct cppi *cppi; |
1153 | + void __iomem *tibase; | |
1153 | 1154 | struct musb_hw_ep *hw_ep = NULL; |
1155 | + u32 rx, tx; | |
1156 | + int i, index; | |
1154 | 1157 | |
1155 | 1158 | cppi = container_of(musb->dma_controller, struct cppi, controller); |
1156 | 1159 | |
1157 | 1160 | tibase = musb->ctrl_base; |
1158 | 1161 | |
1162 | + tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); | |
1163 | + rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); | |
1164 | + | |
1165 | + if (!tx && !rx) | |
1166 | + return IRQ_NONE; | |
1167 | + | |
1168 | + DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx); | |
1169 | + | |
1159 | 1170 | /* process TX channels */ |
1160 | 1171 | for (index = 0; tx; tx = tx >> 1, index++) { |
1161 | 1172 | struct cppi_channel *tx_ch; |
... | ... | @@ -1273,6 +1284,8 @@ |
1273 | 1284 | |
1274 | 1285 | /* write to CPPI EOI register to re-enable interrupts */ |
1275 | 1286 | musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); |
1287 | + | |
1288 | + return IRQ_HANDLED; | |
1276 | 1289 | } |
1277 | 1290 | |
1278 | 1291 | /* Instantiate a software object representing a DMA controller. */ |
... | ... | @@ -1280,6 +1293,9 @@ |
1280 | 1293 | dma_controller_create(struct musb *musb, void __iomem *mregs) |
1281 | 1294 | { |
1282 | 1295 | struct cppi *controller; |
1296 | + struct device *dev = musb->controller; | |
1297 | + struct platform_device *pdev = to_platform_device(dev); | |
1298 | + int irq = platform_get_irq(pdev, 1); | |
1283 | 1299 | |
1284 | 1300 | controller = kzalloc(sizeof *controller, GFP_KERNEL); |
1285 | 1301 | if (!controller) |
... | ... | @@ -1310,6 +1326,15 @@ |
1310 | 1326 | return NULL; |
1311 | 1327 | } |
1312 | 1328 | |
1329 | + if (irq > 0) { | |
1330 | + if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) { | |
1331 | + dev_err(dev, "request_irq %d failed!\n", irq); | |
1332 | + dma_controller_destroy(&controller->controller); | |
1333 | + return NULL; | |
1334 | + } | |
1335 | + controller->irq = irq; | |
1336 | + } | |
1337 | + | |
1313 | 1338 | return &controller->controller; |
1314 | 1339 | } |
1315 | 1340 | |
... | ... | @@ -1321,6 +1346,9 @@ |
1321 | 1346 | struct cppi *cppi; |
1322 | 1347 | |
1323 | 1348 | cppi = container_of(c, struct cppi, controller); |
1349 | + | |
1350 | + if (cppi->irq) | |
1351 | + free_irq(cppi->irq, cppi->musb); | |
1324 | 1352 | |
1325 | 1353 | /* assert: caller stopped the controller first */ |
1326 | 1354 | dma_pool_destroy(cppi->pool); |
drivers/usb/musb/cppi_dma.h
... | ... | @@ -119,6 +119,8 @@ |
119 | 119 | void __iomem *mregs; /* Mentor regs */ |
120 | 120 | void __iomem *tibase; /* TI/CPPI regs */ |
121 | 121 | |
122 | + int irq; | |
123 | + | |
122 | 124 | struct cppi_channel tx[4]; |
123 | 125 | struct cppi_channel rx[4]; |
124 | 126 | |
... | ... | @@ -127,8 +129,8 @@ |
127 | 129 | struct list_head tx_complete; |
128 | 130 | }; |
129 | 131 | |
130 | -/* irq handling hook */ | |
131 | -extern void cppi_completion(struct musb *, u32 rx, u32 tx); | |
132 | +/* CPPI IRQ handler */ | |
133 | +extern irqreturn_t cppi_interrupt(int, void *); | |
132 | 134 | |
133 | 135 | #endif /* end of ifndef _CPPI_DMA_H_ */ |
drivers/usb/musb/davinci.c
... | ... | @@ -265,6 +265,7 @@ |
265 | 265 | irqreturn_t retval = IRQ_NONE; |
266 | 266 | struct musb *musb = __hci; |
267 | 267 | void __iomem *tibase = musb->ctrl_base; |
268 | + struct cppi *cppi; | |
268 | 269 | u32 tmp; |
269 | 270 | |
270 | 271 | spin_lock_irqsave(&musb->lock, flags); |
... | ... | @@ -281,16 +282,9 @@ |
281 | 282 | /* CPPI interrupts share the same IRQ line, but have their own |
282 | 283 | * mask, state, "vector", and EOI registers. |
283 | 284 | */ |
284 | - if (is_cppi_enabled()) { | |
285 | - u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); | |
286 | - u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); | |
287 | - | |
288 | - if (cppi_tx || cppi_rx) { | |
289 | - DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx); | |
290 | - cppi_completion(musb, cppi_rx, cppi_tx); | |
291 | - retval = IRQ_HANDLED; | |
292 | - } | |
293 | - } | |
285 | + cppi = container_of(musb->dma_controller, struct cppi, controller); | |
286 | + if (is_cppi_enabled() && musb->dma_controller && !cppi->irq) | |
287 | + retval = cppi_interrupt(irq, __hci); | |
294 | 288 | |
295 | 289 | /* ack and handle non-CPPI interrupts */ |
296 | 290 | tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); |