Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.11-rc4 617 lines 16 kB view raw
1/* 2 * Copyright (C) 2013, Lars-Peter Clausen <lars@metafoo.de> 3 * JZ4740 DMAC support 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 * You should have received a copy of the GNU General Public License along 11 * with this program; if not, write to the Free Software Foundation, Inc., 12 * 675 Mass Ave, Cambridge, MA 02139, USA. 13 * 14 */ 15 16#include <linux/dmaengine.h> 17#include <linux/dma-mapping.h> 18#include <linux/err.h> 19#include <linux/init.h> 20#include <linux/list.h> 21#include <linux/module.h> 22#include <linux/platform_device.h> 23#include <linux/slab.h> 24#include <linux/spinlock.h> 25#include <linux/irq.h> 26#include <linux/clk.h> 27 28#include <asm/mach-jz4740/dma.h> 29 30#include "virt-dma.h" 31 32#define JZ_DMA_NR_CHANS 6 33 34#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20) 35#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20) 36#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20) 37#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20) 38#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20) 39#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20) 40#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20) 41 42#define JZ_REG_DMA_CTRL 0x300 43#define JZ_REG_DMA_IRQ 0x304 44#define JZ_REG_DMA_DOORBELL 0x308 45#define JZ_REG_DMA_DOORBELL_SET 0x30C 46 47#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31) 48#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6) 49#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4) 50#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3) 51#define JZ_DMA_STATUS_CTRL_HALT BIT(2) 52#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1) 53#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0) 54 55#define JZ_DMA_CMD_SRC_INC BIT(23) 56#define JZ_DMA_CMD_DST_INC BIT(22) 57#define JZ_DMA_CMD_RDIL_MASK (0xf << 16) 58#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14) 59#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12) 60#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8) 61#define JZ_DMA_CMD_BLOCK_MODE BIT(7) 62#define JZ_DMA_CMD_DESC_VALID BIT(4) 63#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3) 64#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2) 65#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1) 66#define JZ_DMA_CMD_LINK_ENABLE BIT(0) 67 68#define JZ_DMA_CMD_FLAGS_OFFSET 22 69#define JZ_DMA_CMD_RDIL_OFFSET 16 70#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14 71#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12 72#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8 73#define JZ_DMA_CMD_MODE_OFFSET 7 74 75#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8) 76#define JZ_DMA_CTRL_HALT BIT(3) 77#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2) 78#define JZ_DMA_CTRL_ENABLE BIT(0) 79 80enum jz4740_dma_width { 81 JZ4740_DMA_WIDTH_32BIT = 0, 82 JZ4740_DMA_WIDTH_8BIT = 1, 83 JZ4740_DMA_WIDTH_16BIT = 2, 84}; 85 86enum jz4740_dma_transfer_size { 87 JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0, 88 JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1, 89 JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2, 90 JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3, 91 JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4, 92}; 93 94enum jz4740_dma_flags { 95 JZ4740_DMA_SRC_AUTOINC = 0x2, 96 JZ4740_DMA_DST_AUTOINC = 0x1, 97}; 98 99enum jz4740_dma_mode { 100 JZ4740_DMA_MODE_SINGLE = 0, 101 JZ4740_DMA_MODE_BLOCK = 1, 102}; 103 104struct jz4740_dma_sg { 105 dma_addr_t addr; 106 unsigned int len; 107}; 108 109struct jz4740_dma_desc { 110 struct virt_dma_desc vdesc; 111 112 enum dma_transfer_direction direction; 113 bool cyclic; 114 115 unsigned int num_sgs; 116 struct jz4740_dma_sg sg[]; 117}; 118 119struct jz4740_dmaengine_chan { 120 struct virt_dma_chan vchan; 121 unsigned int id; 122 123 dma_addr_t fifo_addr; 124 unsigned int transfer_shift; 125 126 struct jz4740_dma_desc *desc; 127 unsigned int next_sg; 128}; 129 130struct jz4740_dma_dev { 131 struct dma_device ddev; 132 void __iomem *base; 133 struct clk *clk; 134 135 struct jz4740_dmaengine_chan chan[JZ_DMA_NR_CHANS]; 136}; 137 138static struct jz4740_dma_dev *jz4740_dma_chan_get_dev( 139 struct jz4740_dmaengine_chan *chan) 140{ 141 return container_of(chan->vchan.chan.device, struct jz4740_dma_dev, 142 ddev); 143} 144 145static struct jz4740_dmaengine_chan *to_jz4740_dma_chan(struct dma_chan *c) 146{ 147 return container_of(c, struct jz4740_dmaengine_chan, vchan.chan); 148} 149 150static struct jz4740_dma_desc *to_jz4740_dma_desc(struct virt_dma_desc *vdesc) 151{ 152 return container_of(vdesc, struct jz4740_dma_desc, vdesc); 153} 154 155static inline uint32_t jz4740_dma_read(struct jz4740_dma_dev *dmadev, 156 unsigned int reg) 157{ 158 return readl(dmadev->base + reg); 159} 160 161static inline void jz4740_dma_write(struct jz4740_dma_dev *dmadev, 162 unsigned reg, uint32_t val) 163{ 164 writel(val, dmadev->base + reg); 165} 166 167static inline void jz4740_dma_write_mask(struct jz4740_dma_dev *dmadev, 168 unsigned int reg, uint32_t val, uint32_t mask) 169{ 170 uint32_t tmp; 171 172 tmp = jz4740_dma_read(dmadev, reg); 173 tmp &= ~mask; 174 tmp |= val; 175 jz4740_dma_write(dmadev, reg, tmp); 176} 177 178static struct jz4740_dma_desc *jz4740_dma_alloc_desc(unsigned int num_sgs) 179{ 180 return kzalloc(sizeof(struct jz4740_dma_desc) + 181 sizeof(struct jz4740_dma_sg) * num_sgs, GFP_ATOMIC); 182} 183 184static enum jz4740_dma_width jz4740_dma_width(enum dma_slave_buswidth width) 185{ 186 switch (width) { 187 case DMA_SLAVE_BUSWIDTH_1_BYTE: 188 return JZ4740_DMA_WIDTH_8BIT; 189 case DMA_SLAVE_BUSWIDTH_2_BYTES: 190 return JZ4740_DMA_WIDTH_16BIT; 191 case DMA_SLAVE_BUSWIDTH_4_BYTES: 192 return JZ4740_DMA_WIDTH_32BIT; 193 default: 194 return JZ4740_DMA_WIDTH_32BIT; 195 } 196} 197 198static enum jz4740_dma_transfer_size jz4740_dma_maxburst(u32 maxburst) 199{ 200 if (maxburst <= 1) 201 return JZ4740_DMA_TRANSFER_SIZE_1BYTE; 202 else if (maxburst <= 3) 203 return JZ4740_DMA_TRANSFER_SIZE_2BYTE; 204 else if (maxburst <= 15) 205 return JZ4740_DMA_TRANSFER_SIZE_4BYTE; 206 else if (maxburst <= 31) 207 return JZ4740_DMA_TRANSFER_SIZE_16BYTE; 208 209 return JZ4740_DMA_TRANSFER_SIZE_32BYTE; 210} 211 212static int jz4740_dma_slave_config(struct dma_chan *c, 213 const struct dma_slave_config *config) 214{ 215 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 216 struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); 217 enum jz4740_dma_width src_width; 218 enum jz4740_dma_width dst_width; 219 enum jz4740_dma_transfer_size transfer_size; 220 enum jz4740_dma_flags flags; 221 uint32_t cmd; 222 223 switch (config->direction) { 224 case DMA_MEM_TO_DEV: 225 flags = JZ4740_DMA_SRC_AUTOINC; 226 transfer_size = jz4740_dma_maxburst(config->dst_maxburst); 227 chan->fifo_addr = config->dst_addr; 228 break; 229 case DMA_DEV_TO_MEM: 230 flags = JZ4740_DMA_DST_AUTOINC; 231 transfer_size = jz4740_dma_maxburst(config->src_maxburst); 232 chan->fifo_addr = config->src_addr; 233 break; 234 default: 235 return -EINVAL; 236 } 237 238 src_width = jz4740_dma_width(config->src_addr_width); 239 dst_width = jz4740_dma_width(config->dst_addr_width); 240 241 switch (transfer_size) { 242 case JZ4740_DMA_TRANSFER_SIZE_2BYTE: 243 chan->transfer_shift = 1; 244 break; 245 case JZ4740_DMA_TRANSFER_SIZE_4BYTE: 246 chan->transfer_shift = 2; 247 break; 248 case JZ4740_DMA_TRANSFER_SIZE_16BYTE: 249 chan->transfer_shift = 4; 250 break; 251 case JZ4740_DMA_TRANSFER_SIZE_32BYTE: 252 chan->transfer_shift = 5; 253 break; 254 default: 255 chan->transfer_shift = 0; 256 break; 257 } 258 259 cmd = flags << JZ_DMA_CMD_FLAGS_OFFSET; 260 cmd |= src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET; 261 cmd |= dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET; 262 cmd |= transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET; 263 cmd |= JZ4740_DMA_MODE_SINGLE << JZ_DMA_CMD_MODE_OFFSET; 264 cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE; 265 266 jz4740_dma_write(dmadev, JZ_REG_DMA_CMD(chan->id), cmd); 267 jz4740_dma_write(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0); 268 jz4740_dma_write(dmadev, JZ_REG_DMA_REQ_TYPE(chan->id), 269 config->slave_id); 270 271 return 0; 272} 273 274static int jz4740_dma_terminate_all(struct dma_chan *c) 275{ 276 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 277 struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); 278 unsigned long flags; 279 LIST_HEAD(head); 280 281 spin_lock_irqsave(&chan->vchan.lock, flags); 282 jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0, 283 JZ_DMA_STATUS_CTRL_ENABLE); 284 chan->desc = NULL; 285 vchan_get_all_descriptors(&chan->vchan, &head); 286 spin_unlock_irqrestore(&chan->vchan.lock, flags); 287 288 vchan_dma_desc_free_list(&chan->vchan, &head); 289 290 return 0; 291} 292 293static int jz4740_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 294 unsigned long arg) 295{ 296 struct dma_slave_config *config = (struct dma_slave_config *)arg; 297 298 switch (cmd) { 299 case DMA_SLAVE_CONFIG: 300 return jz4740_dma_slave_config(chan, config); 301 case DMA_TERMINATE_ALL: 302 return jz4740_dma_terminate_all(chan); 303 default: 304 return -ENOSYS; 305 } 306} 307 308static int jz4740_dma_start_transfer(struct jz4740_dmaengine_chan *chan) 309{ 310 struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); 311 dma_addr_t src_addr, dst_addr; 312 struct virt_dma_desc *vdesc; 313 struct jz4740_dma_sg *sg; 314 315 jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0, 316 JZ_DMA_STATUS_CTRL_ENABLE); 317 318 if (!chan->desc) { 319 vdesc = vchan_next_desc(&chan->vchan); 320 if (!vdesc) 321 return 0; 322 chan->desc = to_jz4740_dma_desc(vdesc); 323 chan->next_sg = 0; 324 } 325 326 if (chan->next_sg == chan->desc->num_sgs) 327 chan->next_sg = 0; 328 329 sg = &chan->desc->sg[chan->next_sg]; 330 331 if (chan->desc->direction == DMA_MEM_TO_DEV) { 332 src_addr = sg->addr; 333 dst_addr = chan->fifo_addr; 334 } else { 335 src_addr = chan->fifo_addr; 336 dst_addr = sg->addr; 337 } 338 jz4740_dma_write(dmadev, JZ_REG_DMA_SRC_ADDR(chan->id), src_addr); 339 jz4740_dma_write(dmadev, JZ_REG_DMA_DST_ADDR(chan->id), dst_addr); 340 jz4740_dma_write(dmadev, JZ_REG_DMA_TRANSFER_COUNT(chan->id), 341 sg->len >> chan->transfer_shift); 342 343 chan->next_sg++; 344 345 jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 346 JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE, 347 JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC | 348 JZ_DMA_STATUS_CTRL_ENABLE); 349 350 jz4740_dma_write_mask(dmadev, JZ_REG_DMA_CTRL, 351 JZ_DMA_CTRL_ENABLE, 352 JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE); 353 354 return 0; 355} 356 357static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan) 358{ 359 spin_lock(&chan->vchan.lock); 360 if (chan->desc) { 361 if (chan->desc && chan->desc->cyclic) { 362 vchan_cyclic_callback(&chan->desc->vdesc); 363 } else { 364 if (chan->next_sg == chan->desc->num_sgs) { 365 chan->desc = NULL; 366 vchan_cookie_complete(&chan->desc->vdesc); 367 } 368 } 369 } 370 jz4740_dma_start_transfer(chan); 371 spin_unlock(&chan->vchan.lock); 372} 373 374static irqreturn_t jz4740_dma_irq(int irq, void *devid) 375{ 376 struct jz4740_dma_dev *dmadev = devid; 377 uint32_t irq_status; 378 unsigned int i; 379 380 irq_status = readl(dmadev->base + JZ_REG_DMA_IRQ); 381 382 for (i = 0; i < 6; ++i) { 383 if (irq_status & (1 << i)) { 384 jz4740_dma_write_mask(dmadev, 385 JZ_REG_DMA_STATUS_CTRL(i), 0, 386 JZ_DMA_STATUS_CTRL_ENABLE | 387 JZ_DMA_STATUS_CTRL_TRANSFER_DONE); 388 389 jz4740_dma_chan_irq(&dmadev->chan[i]); 390 } 391 } 392 393 return IRQ_HANDLED; 394} 395 396static void jz4740_dma_issue_pending(struct dma_chan *c) 397{ 398 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 399 unsigned long flags; 400 401 spin_lock_irqsave(&chan->vchan.lock, flags); 402 if (vchan_issue_pending(&chan->vchan) && !chan->desc) 403 jz4740_dma_start_transfer(chan); 404 spin_unlock_irqrestore(&chan->vchan.lock, flags); 405} 406 407static struct dma_async_tx_descriptor *jz4740_dma_prep_slave_sg( 408 struct dma_chan *c, struct scatterlist *sgl, 409 unsigned int sg_len, enum dma_transfer_direction direction, 410 unsigned long flags, void *context) 411{ 412 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 413 struct jz4740_dma_desc *desc; 414 struct scatterlist *sg; 415 unsigned int i; 416 417 desc = jz4740_dma_alloc_desc(sg_len); 418 if (!desc) 419 return NULL; 420 421 for_each_sg(sgl, sg, sg_len, i) { 422 desc->sg[i].addr = sg_dma_address(sg); 423 desc->sg[i].len = sg_dma_len(sg); 424 } 425 426 desc->num_sgs = sg_len; 427 desc->direction = direction; 428 desc->cyclic = false; 429 430 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 431} 432 433static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic( 434 struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, 435 size_t period_len, enum dma_transfer_direction direction, 436 unsigned long flags, void *context) 437{ 438 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 439 struct jz4740_dma_desc *desc; 440 unsigned int num_periods, i; 441 442 if (buf_len % period_len) 443 return NULL; 444 445 num_periods = buf_len / period_len; 446 447 desc = jz4740_dma_alloc_desc(num_periods); 448 if (!desc) 449 return NULL; 450 451 for (i = 0; i < num_periods; i++) { 452 desc->sg[i].addr = buf_addr; 453 desc->sg[i].len = period_len; 454 buf_addr += period_len; 455 } 456 457 desc->num_sgs = num_periods; 458 desc->direction = direction; 459 desc->cyclic = true; 460 461 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 462} 463 464static size_t jz4740_dma_desc_residue(struct jz4740_dmaengine_chan *chan, 465 struct jz4740_dma_desc *desc, unsigned int next_sg) 466{ 467 struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); 468 unsigned int residue, count; 469 unsigned int i; 470 471 residue = 0; 472 473 for (i = next_sg; i < desc->num_sgs; i++) 474 residue += desc->sg[i].len; 475 476 if (next_sg != 0) { 477 count = jz4740_dma_read(dmadev, 478 JZ_REG_DMA_TRANSFER_COUNT(chan->id)); 479 residue += count << chan->transfer_shift; 480 } 481 482 return residue; 483} 484 485static enum dma_status jz4740_dma_tx_status(struct dma_chan *c, 486 dma_cookie_t cookie, struct dma_tx_state *state) 487{ 488 struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); 489 struct virt_dma_desc *vdesc; 490 enum dma_status status; 491 unsigned long flags; 492 493 status = dma_cookie_status(c, cookie, state); 494 if (status == DMA_SUCCESS || !state) 495 return status; 496 497 spin_lock_irqsave(&chan->vchan.lock, flags); 498 vdesc = vchan_find_desc(&chan->vchan, cookie); 499 if (cookie == chan->desc->vdesc.tx.cookie) { 500 state->residue = jz4740_dma_desc_residue(chan, chan->desc, 501 chan->next_sg); 502 } else if (vdesc) { 503 state->residue = jz4740_dma_desc_residue(chan, 504 to_jz4740_dma_desc(vdesc), 0); 505 } else { 506 state->residue = 0; 507 } 508 spin_unlock_irqrestore(&chan->vchan.lock, flags); 509 510 return status; 511} 512 513static int jz4740_dma_alloc_chan_resources(struct dma_chan *c) 514{ 515 return 0; 516} 517 518static void jz4740_dma_free_chan_resources(struct dma_chan *c) 519{ 520 vchan_free_chan_resources(to_virt_chan(c)); 521} 522 523static void jz4740_dma_desc_free(struct virt_dma_desc *vdesc) 524{ 525 kfree(container_of(vdesc, struct jz4740_dma_desc, vdesc)); 526} 527 528static int jz4740_dma_probe(struct platform_device *pdev) 529{ 530 struct jz4740_dmaengine_chan *chan; 531 struct jz4740_dma_dev *dmadev; 532 struct dma_device *dd; 533 unsigned int i; 534 struct resource *res; 535 int ret; 536 int irq; 537 538 dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL); 539 if (!dmadev) 540 return -EINVAL; 541 542 dd = &dmadev->ddev; 543 544 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 545 dmadev->base = devm_ioremap_resource(&pdev->dev, res); 546 if (IS_ERR(dmadev->base)) 547 return PTR_ERR(dmadev->base); 548 549 dmadev->clk = clk_get(&pdev->dev, "dma"); 550 if (IS_ERR(dmadev->clk)) 551 return PTR_ERR(dmadev->clk); 552 553 clk_prepare_enable(dmadev->clk); 554 555 dma_cap_set(DMA_SLAVE, dd->cap_mask); 556 dma_cap_set(DMA_CYCLIC, dd->cap_mask); 557 dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources; 558 dd->device_free_chan_resources = jz4740_dma_free_chan_resources; 559 dd->device_tx_status = jz4740_dma_tx_status; 560 dd->device_issue_pending = jz4740_dma_issue_pending; 561 dd->device_prep_slave_sg = jz4740_dma_prep_slave_sg; 562 dd->device_prep_dma_cyclic = jz4740_dma_prep_dma_cyclic; 563 dd->device_control = jz4740_dma_control; 564 dd->dev = &pdev->dev; 565 dd->chancnt = JZ_DMA_NR_CHANS; 566 INIT_LIST_HEAD(&dd->channels); 567 568 for (i = 0; i < dd->chancnt; i++) { 569 chan = &dmadev->chan[i]; 570 chan->id = i; 571 chan->vchan.desc_free = jz4740_dma_desc_free; 572 vchan_init(&chan->vchan, dd); 573 } 574 575 ret = dma_async_device_register(dd); 576 if (ret) 577 return ret; 578 579 irq = platform_get_irq(pdev, 0); 580 ret = request_irq(irq, jz4740_dma_irq, 0, dev_name(&pdev->dev), dmadev); 581 if (ret) 582 goto err_unregister; 583 584 platform_set_drvdata(pdev, dmadev); 585 586 return 0; 587 588err_unregister: 589 dma_async_device_unregister(dd); 590 return ret; 591} 592 593static int jz4740_dma_remove(struct platform_device *pdev) 594{ 595 struct jz4740_dma_dev *dmadev = platform_get_drvdata(pdev); 596 int irq = platform_get_irq(pdev, 0); 597 598 free_irq(irq, dmadev); 599 dma_async_device_unregister(&dmadev->ddev); 600 clk_disable_unprepare(dmadev->clk); 601 602 return 0; 603} 604 605static struct platform_driver jz4740_dma_driver = { 606 .probe = jz4740_dma_probe, 607 .remove = jz4740_dma_remove, 608 .driver = { 609 .name = "jz4740-dma", 610 .owner = THIS_MODULE, 611 }, 612}; 613module_platform_driver(jz4740_dma_driver); 614 615MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 616MODULE_DESCRIPTION("JZ4740 DMA driver"); 617MODULE_LICENSE("GPLv2");