mmp_tdma.c (f1a7757008b810217b2380d01b740244f21c09bd) | mmp_tdma.c (293b2da1b61136813fc2764f43304c66ff8040e9) |
---|---|
1/* 2 * Driver For Marvell Two-channel DMA Engine 3 * 4 * Copyright: Marvell International Ltd. 5 * 6 * The code contained herein is licensed under the GNU General Public 7 * License. You may obtain a copy of the GNU General Public License 8 * Version 2 or later at the following locations: --- 5 unchanged lines hidden (view full) --- 14#include <linux/types.h> 15#include <linux/interrupt.h> 16#include <linux/dma-mapping.h> 17#include <linux/slab.h> 18#include <linux/dmaengine.h> 19#include <linux/platform_device.h> 20#include <linux/device.h> 21#include <mach/regs-icu.h> | 1/* 2 * Driver For Marvell Two-channel DMA Engine 3 * 4 * Copyright: Marvell International Ltd. 5 * 6 * The code contained herein is licensed under the GNU General Public 7 * License. You may obtain a copy of the GNU General Public License 8 * Version 2 or later at the following locations: --- 5 unchanged lines hidden (view full) --- 14#include <linux/types.h> 15#include <linux/interrupt.h> 16#include <linux/dma-mapping.h> 17#include <linux/slab.h> 18#include <linux/dmaengine.h> 19#include <linux/platform_device.h> 20#include <linux/device.h> 21#include <mach/regs-icu.h> |
22#include <mach/sram.h> 23#include <linux/of_device.h> | 22#include <linux/platform_data/dma-mmp_tdma.h> |
24 25#include "dmaengine.h" 26 27/* 28 * Two-Channel DMA registers 29 */ 30#define TDBCR 0x00 /* Byte Count */ 31#define TDSAR 0x10 /* Src Addr */ --- 91 unchanged lines hidden (view full) --- 123}; 124 125#define TDMA_CHANNEL_NUM 2 126struct mmp_tdma_device { 127 struct device *dev; 128 void __iomem *base; 129 struct dma_device device; 130 struct mmp_tdma_chan *tdmac[TDMA_CHANNEL_NUM]; | 23 24#include "dmaengine.h" 25 26/* 27 * Two-Channel DMA registers 28 */ 29#define TDBCR 0x00 /* Byte Count */ 30#define TDSAR 0x10 /* Src Addr */ --- 91 unchanged lines hidden (view full) --- 122}; 123 124#define TDMA_CHANNEL_NUM 2 125struct mmp_tdma_device { 126 struct device *dev; 127 void __iomem *base; 128 struct dma_device device; 129 struct mmp_tdma_chan *tdmac[TDMA_CHANNEL_NUM]; |
130 int irq; |
|
131}; 132 133#define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan) 134 135static void mmp_tdma_chan_set_desc(struct mmp_tdma_chan *tdmac, dma_addr_t phys) 136{ 137 writel(phys, tdmac->reg_base + TDNDPR); 138 writel(readl(tdmac->reg_base + TDCR) | TDCR_FETCHND, --- 348 unchanged lines hidden (view full) --- 487 488 /* alloc channel */ 489 tdmac = devm_kzalloc(tdev->dev, sizeof(*tdmac), GFP_KERNEL); 490 if (!tdmac) { 491 dev_err(tdev->dev, "no free memory for DMA channels!\n"); 492 return -ENOMEM; 493 } 494 if (irq) | 131}; 132 133#define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan) 134 135static void mmp_tdma_chan_set_desc(struct mmp_tdma_chan *tdmac, dma_addr_t phys) 136{ 137 writel(phys, tdmac->reg_base + TDNDPR); 138 writel(readl(tdmac->reg_base + TDCR) | TDCR_FETCHND, --- 348 unchanged lines hidden (view full) --- 487 488 /* alloc channel */ 489 tdmac = devm_kzalloc(tdev->dev, sizeof(*tdmac), GFP_KERNEL); 490 if (!tdmac) { 491 dev_err(tdev->dev, "no free memory for DMA channels!\n"); 492 return -ENOMEM; 493 } 494 if (irq) |
495 tdmac->irq = irq; | 495 tdmac->irq = irq + idx; |
496 tdmac->dev = tdev->dev; 497 tdmac->chan.device = &tdev->device; 498 tdmac->idx = idx; 499 tdmac->type = type; 500 tdmac->reg_base = (unsigned long)tdev->base + idx * 4; 501 tdmac->status = DMA_SUCCESS; 502 tdev->tdmac[tdmac->idx] = tdmac; 503 tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); 504 505 /* add the channel to tdma_chan list */ 506 list_add_tail(&tdmac->chan.device_node, 507 &tdev->device.channels); | 496 tdmac->dev = tdev->dev; 497 tdmac->chan.device = &tdev->device; 498 tdmac->idx = idx; 499 tdmac->type = type; 500 tdmac->reg_base = (unsigned long)tdev->base + idx * 4; 501 tdmac->status = DMA_SUCCESS; 502 tdev->tdmac[tdmac->idx] = tdmac; 503 tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); 504 505 /* add the channel to tdma_chan list */ 506 list_add_tail(&tdmac->chan.device_node, 507 &tdev->device.channels); |
508 |
|
508 return 0; 509} 510 | 509 return 0; 510} 511 |
511static struct of_device_id mmp_tdma_dt_ids[] = { 512 { .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA}, 513 { .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU}, 514 {} 515}; 516MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids); 517 | |
518static int __devinit mmp_tdma_probe(struct platform_device *pdev) 519{ | 512static int __devinit mmp_tdma_probe(struct platform_device *pdev) 513{ |
520 enum mmp_tdma_type type; 521 const struct of_device_id *of_id; | 514 const struct platform_device_id *id = platform_get_device_id(pdev); 515 enum mmp_tdma_type type = id->driver_data; |
522 struct mmp_tdma_device *tdev; 523 struct resource *iores; 524 int i, ret; | 516 struct mmp_tdma_device *tdev; 517 struct resource *iores; 518 int i, ret; |
525 int irq = 0, irq_num = 0; | 519 int irq = 0; |
526 int chan_num = TDMA_CHANNEL_NUM; 527 | 520 int chan_num = TDMA_CHANNEL_NUM; 521 |
528 of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev); 529 if (of_id) 530 type = (enum mmp_tdma_type) of_id->data; 531 else 532 type = platform_get_device_id(pdev)->driver_data; 533 | |
534 /* always have couple channels */ 535 tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); 536 if (!tdev) 537 return -ENOMEM; 538 539 tdev->dev = &pdev->dev; | 522 /* always have couple channels */ 523 tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); 524 if (!tdev) 525 return -ENOMEM; 526 527 tdev->dev = &pdev->dev; |
528 iores = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 529 if (!iores) 530 return -EINVAL; |
|
540 | 531 |
541 for (i = 0; i < chan_num; i++) { 542 if (platform_get_irq(pdev, i) > 0) 543 irq_num++; 544 } | 532 if (resource_size(iores) != chan_num) 533 tdev->irq = iores->start; 534 else 535 irq = iores->start; |
545 546 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 547 if (!iores) 548 return -EINVAL; 549 550 tdev->base = devm_request_and_ioremap(&pdev->dev, iores); 551 if (!tdev->base) 552 return -EADDRNOTAVAIL; 553 | 536 537 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 538 if (!iores) 539 return -EINVAL; 540 541 tdev->base = devm_request_and_ioremap(&pdev->dev, iores); 542 if (!tdev->base) 543 return -EADDRNOTAVAIL; 544 |
554 INIT_LIST_HEAD(&tdev->device.channels); 555 556 if (irq_num != chan_num) { 557 irq = platform_get_irq(pdev, 0); 558 ret = devm_request_irq(&pdev->dev, irq, | 545 if (tdev->irq) { 546 ret = devm_request_irq(&pdev->dev, tdev->irq, |
559 mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev); 560 if (ret) 561 return ret; 562 } 563 | 547 mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev); 548 if (ret) 549 return ret; 550 } 551 |
552 dma_cap_set(DMA_SLAVE, tdev->device.cap_mask); 553 dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask); 554 555 INIT_LIST_HEAD(&tdev->device.channels); 556 |
|
564 /* initialize channel parameters */ 565 for (i = 0; i < chan_num; i++) { | 557 /* initialize channel parameters */ 558 for (i = 0; i < chan_num; i++) { |
566 irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i); | |
567 ret = mmp_tdma_chan_init(tdev, i, irq, type); 568 if (ret) 569 return ret; 570 } 571 | 559 ret = mmp_tdma_chan_init(tdev, i, irq, type); 560 if (ret) 561 return ret; 562 } 563 |
572 dma_cap_set(DMA_SLAVE, tdev->device.cap_mask); 573 dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask); | |
574 tdev->device.dev = &pdev->dev; 575 tdev->device.device_alloc_chan_resources = 576 mmp_tdma_alloc_chan_resources; 577 tdev->device.device_free_chan_resources = 578 mmp_tdma_free_chan_resources; 579 tdev->device.device_prep_dma_cyclic = mmp_tdma_prep_dma_cyclic; 580 tdev->device.device_tx_status = mmp_tdma_tx_status; 581 tdev->device.device_issue_pending = mmp_tdma_issue_pending; --- 18 unchanged lines hidden (view full) --- 600 { "pxa910-squ", PXA910_SQU }, 601 { }, 602}; 603 604static struct platform_driver mmp_tdma_driver = { 605 .driver = { 606 .name = "mmp-tdma", 607 .owner = THIS_MODULE, | 564 tdev->device.dev = &pdev->dev; 565 tdev->device.device_alloc_chan_resources = 566 mmp_tdma_alloc_chan_resources; 567 tdev->device.device_free_chan_resources = 568 mmp_tdma_free_chan_resources; 569 tdev->device.device_prep_dma_cyclic = mmp_tdma_prep_dma_cyclic; 570 tdev->device.device_tx_status = mmp_tdma_tx_status; 571 tdev->device.device_issue_pending = mmp_tdma_issue_pending; --- 18 unchanged lines hidden (view full) --- 590 { "pxa910-squ", PXA910_SQU }, 591 { }, 592}; 593 594static struct platform_driver mmp_tdma_driver = { 595 .driver = { 596 .name = "mmp-tdma", 597 .owner = THIS_MODULE, |
608 .of_match_table = mmp_tdma_dt_ids, | |
609 }, 610 .id_table = mmp_tdma_id_table, 611 .probe = mmp_tdma_probe, 612 .remove = __devexit_p(mmp_tdma_remove), 613}; 614 615module_platform_driver(mmp_tdma_driver); 616 617MODULE_LICENSE("GPL"); 618MODULE_DESCRIPTION("MMP Two-Channel DMA Driver"); 619MODULE_ALIAS("platform:mmp-tdma"); 620MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 621MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>"); | 598 }, 599 .id_table = mmp_tdma_id_table, 600 .probe = mmp_tdma_probe, 601 .remove = __devexit_p(mmp_tdma_remove), 602}; 603 604module_platform_driver(mmp_tdma_driver); 605 606MODULE_LICENSE("GPL"); 607MODULE_DESCRIPTION("MMP Two-Channel DMA Driver"); 608MODULE_ALIAS("platform:mmp-tdma"); 609MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 610MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>"); |