aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThang Q. Nguyen <tqnguyen@apm.com>2012-05-10 00:17:10 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-07-25 15:54:21 -0400
commitdc7f71f486f4f5fa96f6dcf86833da020cde8a11 (patch)
tree0f8b83ed3584b270b24dd61f1f9b5b543536f24e
parentfacb8fa6c784893ad1da9f0fd160e3b3c5fad2c4 (diff)
sata_dwc_460ex: device tree may specify dma_channel
Only channel 0 is currently support and the driver code is fixed on channel 0. This patch lets device node specifying dma-channel in case it is not 0. If no dma-channel property is specified, channel 0 is used as default. Signed-off-by: Thang Q. Nguyen <tqnguyen@apm.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rwxr-xr-x[-rw-r--r--]drivers/ata/sata_dwc_460ex.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index ae13ef1945ba..937aeb34b310 100644..100755
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -158,6 +158,7 @@ enum {
158/* Assign HW handshaking interface (x) to destination / source peripheral */ 158/* Assign HW handshaking interface (x) to destination / source peripheral */
159#define DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11) 159#define DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11)
160#define DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7) 160#define DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7)
161#define DMA_CFG_HW_CH_PRIOR(int_num) (((int_num) & 0xF) << 5)
161#define DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master)) 162#define DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master))
162 163
163/* 164/*
@@ -318,6 +319,7 @@ struct sata_dwc_host_priv {
318 u32 dma_interrupt_count; 319 u32 dma_interrupt_count;
319 struct ahb_dma_regs *sata_dma_regs; 320 struct ahb_dma_regs *sata_dma_regs;
320 struct device *dwc_dev; 321 struct device *dwc_dev;
322 int dma_channel;
321}; 323};
322struct sata_dwc_host_priv host_pvt; 324struct sata_dwc_host_priv host_pvt;
323/* 325/*
@@ -437,15 +439,12 @@ static void clear_chan_interrupts(int c)
437 */ 439 */
438static int dma_request_channel(void) 440static int dma_request_channel(void)
439{ 441{
440 int i; 442 /* Check if the channel is not currently in use */
441 443 if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) &
442 for (i = 0; i < DMA_NUM_CHANS; i++) { 444 DMA_CHANNEL(host_pvt.dma_channel)))
443 if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) &\ 445 return host_pvt.dma_channel;
444 DMA_CHANNEL(i))) 446 dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n",
445 return i; 447 __func__, host_pvt.dma_channel);
446 }
447 dev_err(host_pvt.dwc_dev, "%s NO channel chan_en: 0x%08x\n", __func__,
448 in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)));
449 return -1; 448 return -1;
450} 449}
451 450
@@ -481,7 +480,8 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
481 dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", 480 dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n",
482 tfr_reg, err_reg, hsdevp->dma_pending[tag], port); 481 tfr_reg, err_reg, hsdevp->dma_pending[tag], port);
483 482
484 for (chan = 0; chan < DMA_NUM_CHANS; chan++) { 483 chan = host_pvt.dma_channel;
484 if (chan >= 0) {
485 /* Check for end-of-transfer interrupt. */ 485 /* Check for end-of-transfer interrupt. */
486 if (tfr_reg & DMA_CHANNEL(chan)) { 486 if (tfr_reg & DMA_CHANNEL(chan)) {
487 /* 487 /*
@@ -534,9 +534,9 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
534static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq) 534static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq)
535{ 535{
536 int retval = 0; 536 int retval = 0;
537 int chan; 537 int chan = host_pvt.dma_channel;
538 538
539 for (chan = 0; chan < DMA_NUM_CHANS; chan++) { 539 if (chan >= 0) {
540 /* Unmask error interrupt */ 540 /* Unmask error interrupt */
541 out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low, 541 out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low,
542 DMA_ENABLE_CHAN(chan)); 542 DMA_ENABLE_CHAN(chan));
@@ -575,7 +575,10 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,
575 int fis_len = 0; 575 int fis_len = 0;
576 dma_addr_t next_llp; 576 dma_addr_t next_llp;
577 int bl; 577 int bl;
578 int sms_val, dms_val;
578 579
580 sms_val = 0;
581 dms_val = 1 + host_pvt.dma_channel;
579 dev_dbg(host_pvt.dwc_dev, "%s: sg=%p nelem=%d lli=%p dma_lli=0x%08x" 582 dev_dbg(host_pvt.dwc_dev, "%s: sg=%p nelem=%d lli=%p dma_lli=0x%08x"
580 " dmadr=0x%08x\n", __func__, sg, num_elems, lli, (u32)dma_lli, 583 " dmadr=0x%08x\n", __func__, sg, num_elems, lli, (u32)dma_lli,
581 (u32)dmadr_addr); 584 (u32)dmadr_addr);
@@ -635,8 +638,8 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,
635 638
636 lli[idx].ctl.low = cpu_to_le32( 639 lli[idx].ctl.low = cpu_to_le32(
637 DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | 640 DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) |
638 DMA_CTL_SMS(0) | 641 DMA_CTL_SMS(sms_val) |
639 DMA_CTL_DMS(1) | 642 DMA_CTL_DMS(dms_val) |
640 DMA_CTL_SRC_MSIZE(bl) | 643 DMA_CTL_SRC_MSIZE(bl) |
641 DMA_CTL_DST_MSIZE(bl) | 644 DMA_CTL_DST_MSIZE(bl) |
642 DMA_CTL_SINC_NOCHANGE | 645 DMA_CTL_SINC_NOCHANGE |
@@ -651,8 +654,8 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,
651 654
652 lli[idx].ctl.low = cpu_to_le32( 655 lli[idx].ctl.low = cpu_to_le32(
653 DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | 656 DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) |
654 DMA_CTL_SMS(1) | 657 DMA_CTL_SMS(dms_val) |
655 DMA_CTL_DMS(0) | 658 DMA_CTL_DMS(sms_val) |
656 DMA_CTL_SRC_MSIZE(bl) | 659 DMA_CTL_SRC_MSIZE(bl) |
657 DMA_CTL_DST_MSIZE(bl) | 660 DMA_CTL_DST_MSIZE(bl) |
658 DMA_CTL_DINC_NOCHANGE | 661 DMA_CTL_DINC_NOCHANGE |
@@ -744,8 +747,10 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
744 747
745 /* Program the CFG register. */ 748 /* Program the CFG register. */
746 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high), 749 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high),
750 DMA_CFG_HW_HS_SRC(dma_ch) | DMA_CFG_HW_HS_DEST(dma_ch) |
747 DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ); 751 DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ);
748 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low), 0); 752 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low),
753 DMA_CFG_HW_CH_PRIOR(dma_ch));
749 754
750 /* Program the address of the linked list */ 755 /* Program the address of the linked list */
751 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low), 756 out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low),
@@ -1660,6 +1665,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
1660 struct ata_host *host; 1665 struct ata_host *host;
1661 struct ata_port_info pi = sata_dwc_port_info[0]; 1666 struct ata_port_info pi = sata_dwc_port_info[0];
1662 const struct ata_port_info *ppi[] = { &pi, NULL }; 1667 const struct ata_port_info *ppi[] = { &pi, NULL };
1668 struct device_node *np = ofdev->dev.of_node;
1669 u32 dma_chan;
1663 1670
1664 /* Allocate DWC SATA device */ 1671 /* Allocate DWC SATA device */
1665 hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); 1672 hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
@@ -1669,6 +1676,13 @@ static int sata_dwc_probe(struct platform_device *ofdev)
1669 goto error; 1676 goto error;
1670 } 1677 }
1671 1678
1679 if (of_property_read_u32(np, "dma-channel", &dma_chan)) {
1680 dev_warn(&ofdev->dev, "no dma-channel property set."
1681 " Use channel 0\n");
1682 dma_chan = 0;
1683 }
1684 host_pvt.dma_channel = dma_chan;
1685
1672 /* Ioremap SATA registers */ 1686 /* Ioremap SATA registers */
1673 base = of_iomap(ofdev->dev.of_node, 0); 1687 base = of_iomap(ofdev->dev.of_node, 0);
1674 if (!base) { 1688 if (!base) {