Merge branch 'for-2.6.40' of git://linux-nfs.org/~bfields/linux
[deliverable/linux.git] / drivers / dma / pch_dma.c
index 8d8fef1480a93115ab17c51f6c97d0130b44b21d..ff5b38f9d45bc98249ddf2a648a5b338f63f3496 100644 (file)
@@ -77,10 +77,10 @@ struct pch_dma_regs {
        u32     dma_ctl0;
        u32     dma_ctl1;
        u32     dma_ctl2;
-       u32     reserved1;
+       u32     dma_ctl3;
        u32     dma_sts0;
        u32     dma_sts1;
-       u32     reserved2;
+       u32     dma_sts2;
        u32     reserved3;
        struct pch_dma_desc_regs desc[MAX_CHAN_NR];
 };
@@ -130,6 +130,7 @@ struct pch_dma {
 #define PCH_DMA_CTL0   0x00
 #define PCH_DMA_CTL1   0x04
 #define PCH_DMA_CTL2   0x08
+#define PCH_DMA_CTL3   0x0C
 #define PCH_DMA_STS0   0x10
 #define PCH_DMA_STS1   0x14
 
@@ -138,7 +139,8 @@ struct pch_dma {
 #define dma_writel(pd, name, val) \
        writel((val), (pd)->membase + PCH_DMA_##name)
 
-static inline struct pch_dma_desc *to_pd_desc(struct dma_async_tx_descriptor *txd)
+static inline
+struct pch_dma_desc *to_pd_desc(struct dma_async_tx_descriptor *txd)
 {
        return container_of(txd, struct pch_dma_desc, txd);
 }
@@ -163,13 +165,15 @@ static inline struct device *chan2parent(struct dma_chan *chan)
        return chan->dev->device.parent;
 }
 
-static inline struct pch_dma_desc *pdc_first_active(struct pch_dma_chan *pd_chan)
+static inline
+struct pch_dma_desc *pdc_first_active(struct pch_dma_chan *pd_chan)
 {
        return list_first_entry(&pd_chan->active_list,
                                struct pch_dma_desc, desc_node);
 }
 
-static inline struct pch_dma_desc *pdc_first_queued(struct pch_dma_chan *pd_chan)
+static inline
+struct pch_dma_desc *pdc_first_queued(struct pch_dma_chan *pd_chan)
 {
        return list_first_entry(&pd_chan->queue,
                                struct pch_dma_desc, desc_node);
@@ -199,16 +203,30 @@ static void pdc_set_dir(struct dma_chan *chan)
        struct pch_dma *pd = to_pd(chan->device);
        u32 val;
 
-       val = dma_readl(pd, CTL0);
+       if (chan->chan_id < 8) {
+               val = dma_readl(pd, CTL0);
 
-       if (pd_chan->dir == DMA_TO_DEVICE)
-               val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
-                              DMA_CTL0_DIR_SHIFT_BITS);
-       else
-               val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
-                                DMA_CTL0_DIR_SHIFT_BITS));
+               if (pd_chan->dir == DMA_TO_DEVICE)
+                       val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
+                                      DMA_CTL0_DIR_SHIFT_BITS);
+               else
+                       val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
+                                        DMA_CTL0_DIR_SHIFT_BITS));
+
+               dma_writel(pd, CTL0, val);
+       } else {
+               int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
+               val = dma_readl(pd, CTL3);
 
-       dma_writel(pd, CTL0, val);
+               if (pd_chan->dir == DMA_TO_DEVICE)
+                       val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch +
+                                      DMA_CTL0_DIR_SHIFT_BITS);
+               else
+                       val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * ch +
+                                        DMA_CTL0_DIR_SHIFT_BITS));
+
+               dma_writel(pd, CTL3, val);
+       }
 
        dev_dbg(chan2dev(chan), "pdc_set_dir: chan %d -> %x\n",
                chan->chan_id, val);
@@ -219,13 +237,26 @@ static void pdc_set_mode(struct dma_chan *chan, u32 mode)
        struct pch_dma *pd = to_pd(chan->device);
        u32 val;
 
-       val = dma_readl(pd, CTL0);
+       if (chan->chan_id < 8) {
+               val = dma_readl(pd, CTL0);
+
+               val &= ~(DMA_CTL0_MODE_MASK_BITS <<
+                       (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+               val |= mode << (DMA_CTL0_BITS_PER_CH * chan->chan_id);
 
-       val &= ~(DMA_CTL0_MODE_MASK_BITS <<
-               (DMA_CTL0_BITS_PER_CH * chan->chan_id));
-       val |= mode << (DMA_CTL0_BITS_PER_CH * chan->chan_id);
+               dma_writel(pd, CTL0, val);
+       } else {
+               int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
+
+               val = dma_readl(pd, CTL3);
+
+               val &= ~(DMA_CTL0_MODE_MASK_BITS <<
+                       (DMA_CTL0_BITS_PER_CH * ch));
+               val |= mode << (DMA_CTL0_BITS_PER_CH * ch);
 
-       dma_writel(pd, CTL0, val);
+               dma_writel(pd, CTL3, val);
+
+       }
 
        dev_dbg(chan2dev(chan), "pdc_set_mode: chan %d -> %x\n",
                chan->chan_id, val);
@@ -251,9 +282,6 @@ static bool pdc_is_idle(struct pch_dma_chan *pd_chan)
 
 static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
 {
-       struct pch_dma *pd = to_pd(pd_chan->chan.device);
-       u32 val;
-
        if (!pdc_is_idle(pd_chan)) {
                dev_err(chan2dev(&pd_chan->chan),
                        "BUG: Attempt to start non-idle channel\n");
@@ -279,10 +307,6 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
                channel_writel(pd_chan, NEXT, desc->txd.phys);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG);
        }
-
-       val = dma_readl(pd, CTL2);
-       val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id);
-       dma_writel(pd, CTL2, val);
 }
 
 static void pdc_chain_complete(struct pch_dma_chan *pd_chan,
@@ -403,7 +427,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan)
 {
        struct pch_dma_desc *desc, *_d;
        struct pch_dma_desc *ret = NULL;
-       int i;
+       int i = 0;
 
        spin_lock(&pd_chan->lock);
        list_for_each_entry_safe(desc, _d, &pd_chan->free_list, desc_node) {
@@ -478,7 +502,6 @@ static int pd_alloc_chan_resources(struct dma_chan *chan)
        spin_unlock_bh(&pd_chan->lock);
 
        pdc_enable_irq(chan, 1);
-       pdc_set_dir(chan);
 
        return pd_chan->descs_allocated;
 }
@@ -561,6 +584,9 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
        else
                return NULL;
 
+       pd_chan->dir = direction;
+       pdc_set_dir(chan);
+
        for_each_sg(sgl, sg, sg_len, i) {
                desc = pdc_desc_get(pd_chan);
 
@@ -703,6 +729,7 @@ static void pch_dma_save_regs(struct pch_dma *pd)
        pd->regs.dma_ctl0 = dma_readl(pd, CTL0);
        pd->regs.dma_ctl1 = dma_readl(pd, CTL1);
        pd->regs.dma_ctl2 = dma_readl(pd, CTL2);
+       pd->regs.dma_ctl3 = dma_readl(pd, CTL3);
 
        list_for_each_entry_safe(chan, _c, &pd->dma.channels, device_node) {
                pd_chan = to_pd_chan(chan);
@@ -725,6 +752,7 @@ static void pch_dma_restore_regs(struct pch_dma *pd)
        dma_writel(pd, CTL0, pd->regs.dma_ctl0);
        dma_writel(pd, CTL1, pd->regs.dma_ctl1);
        dma_writel(pd, CTL2, pd->regs.dma_ctl2);
+       dma_writel(pd, CTL3, pd->regs.dma_ctl3);
 
        list_for_each_entry_safe(chan, _c, &pd->dma.channels, device_node) {
                pd_chan = to_pd_chan(chan);
@@ -850,8 +878,6 @@ static int __devinit pch_dma_probe(struct pci_dev *pdev,
 
                pd_chan->membase = &regs->desc[i];
 
-               pd_chan->dir = (i % 2) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
                spin_lock_init(&pd_chan->lock);
 
                INIT_LIST_HEAD(&pd_chan->active_list);
@@ -929,13 +955,23 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev)
 #define PCI_DEVICE_ID_ML7213_DMA1_8CH  0x8026
 #define PCI_DEVICE_ID_ML7213_DMA2_8CH  0x802B
 #define PCI_DEVICE_ID_ML7213_DMA3_4CH  0x8034
+#define PCI_DEVICE_ID_ML7213_DMA4_12CH 0x8032
+#define PCI_DEVICE_ID_ML7223_DMA1_4CH  0x800B
+#define PCI_DEVICE_ID_ML7223_DMA2_4CH  0x800E
+#define PCI_DEVICE_ID_ML7223_DMA3_4CH  0x8017
+#define PCI_DEVICE_ID_ML7223_DMA4_4CH  0x803B
 
-static const struct pci_device_id pch_dma_id_table[] = {
+DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_4CH), 4 },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA1_8CH), 8}, /* UART Video */
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA2_8CH), 8}, /* PCMIF SPI */
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA3_4CH), 4}, /* FPGA */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA4_12CH), 12}, /* I2S */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA1_4CH), 4}, /* UART */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */
        { 0, },
 };
 
This page took 0.030613 seconds and 5 git commands to generate.