diff options
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index ab12fa5a1296..b419afaa2389 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -24,8 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <cpu/dma.h> | 27 | #include <asm/dmaengine.h> |
28 | #include <asm/dma-sh.h> | ||
29 | #include "shdma.h" | 28 | #include "shdma.h" |
30 | 29 | ||
31 | /* DMA descriptor control */ | 30 | /* DMA descriptor control */ |
@@ -38,15 +37,8 @@ enum sh_dmae_desc_status { | |||
38 | }; | 37 | }; |
39 | 38 | ||
40 | #define NR_DESCS_PER_CHANNEL 32 | 39 | #define NR_DESCS_PER_CHANNEL 32 |
41 | /* | 40 | /* Default MEMCPY transfer size = 2^2 = 4 bytes */ |
42 | * Define the default configuration for dual address memory-memory transfer. | 41 | #define LOG2_DEFAULT_XFER_SIZE 2 |
43 | * The 0x400 value represents auto-request, external->external. | ||
44 | * | ||
45 | * And this driver set 4byte burst mode. | ||
46 | * If you want to change mode, you need to change RS_DEFAULT of value. | ||
47 | * (ex 1byte burst mode -> (RS_DUAL & ~TS_32) | ||
48 | */ | ||
49 | #define RS_DEFAULT (RS_DUAL) | ||
50 | 42 | ||
51 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ | 43 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ |
52 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; | 44 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; |
@@ -90,7 +82,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) | |||
90 | unsigned short dmaor; | 82 | unsigned short dmaor; |
91 | 83 | ||
92 | sh_dmae_ctl_stop(shdev); | 84 | sh_dmae_ctl_stop(shdev); |
93 | dmaor = dmaor_read(shdev) | DMAOR_INIT; | 85 | dmaor = dmaor_read(shdev) | shdev->pdata->dmaor_init; |
94 | 86 | ||
95 | dmaor_write(shdev, dmaor); | 87 | dmaor_write(shdev, dmaor); |
96 | if (dmaor_read(shdev) & (DMAOR_AE | DMAOR_NMIF)) { | 88 | if (dmaor_read(shdev) & (DMAOR_AE | DMAOR_NMIF)) { |
@@ -110,13 +102,36 @@ static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) | |||
110 | return false; /* waiting */ | 102 | return false; /* waiting */ |
111 | } | 103 | } |
112 | 104 | ||
113 | static unsigned int ts_shift[] = TS_SHIFT; | 105 | static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr) |
114 | static inline unsigned int calc_xmit_shift(u32 chcr) | ||
115 | { | 106 | { |
116 | int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) | | 107 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, |
117 | ((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT); | 108 | struct sh_dmae_device, common); |
109 | struct sh_dmae_pdata *pdata = shdev->pdata; | ||
110 | int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) | | ||
111 | ((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift); | ||
112 | |||
113 | if (cnt >= pdata->ts_shift_num) | ||
114 | cnt = 0; | ||
118 | 115 | ||
119 | return ts_shift[cnt]; | 116 | return pdata->ts_shift[cnt]; |
117 | } | ||
118 | |||
119 | static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size) | ||
120 | { | ||
121 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, | ||
122 | struct sh_dmae_device, common); | ||
123 | struct sh_dmae_pdata *pdata = shdev->pdata; | ||
124 | int i; | ||
125 | |||
126 | for (i = 0; i < pdata->ts_shift_num; i++) | ||
127 | if (pdata->ts_shift[i] == l2size) | ||
128 | break; | ||
129 | |||
130 | if (i == pdata->ts_shift_num) | ||
131 | i = 0; | ||
132 | |||
133 | return ((i << pdata->ts_low_shift) & pdata->ts_low_mask) | | ||
134 | ((i << pdata->ts_high_shift) & pdata->ts_high_mask); | ||
120 | } | 135 | } |
121 | 136 | ||
122 | static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) | 137 | static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) |
@@ -144,8 +159,13 @@ static void dmae_halt(struct sh_dmae_chan *sh_chan) | |||
144 | 159 | ||
145 | static void dmae_init(struct sh_dmae_chan *sh_chan) | 160 | static void dmae_init(struct sh_dmae_chan *sh_chan) |
146 | { | 161 | { |
147 | u32 chcr = RS_DEFAULT; /* default is DUAL mode */ | 162 | /* |
148 | sh_chan->xmit_shift = calc_xmit_shift(chcr); | 163 | * Default configuration for dual address memory-memory transfer. |
164 | * 0x400 represents auto-request. | ||
165 | */ | ||
166 | u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, | ||
167 | LOG2_DEFAULT_XFER_SIZE); | ||
168 | sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr); | ||
149 | sh_dmae_writel(sh_chan, chcr, CHCR); | 169 | sh_dmae_writel(sh_chan, chcr, CHCR); |
150 | } | 170 | } |
151 | 171 | ||
@@ -155,7 +175,7 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) | |||
155 | if (dmae_is_busy(sh_chan)) | 175 | if (dmae_is_busy(sh_chan)) |
156 | return -EBUSY; | 176 | return -EBUSY; |
157 | 177 | ||
158 | sh_chan->xmit_shift = calc_xmit_shift(val); | 178 | sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); |
159 | sh_dmae_writel(sh_chan, val, CHCR); | 179 | sh_dmae_writel(sh_chan, val, CHCR); |
160 | 180 | ||
161 | return 0; | 181 | return 0; |
@@ -285,9 +305,8 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
285 | 305 | ||
286 | dmae_set_dmars(sh_chan, cfg->mid_rid); | 306 | dmae_set_dmars(sh_chan, cfg->mid_rid); |
287 | dmae_set_chcr(sh_chan, cfg->chcr); | 307 | dmae_set_chcr(sh_chan, cfg->chcr); |
288 | } else { | 308 | } else if ((sh_dmae_readl(sh_chan, CHCR) & 0xf00) != 0x400) { |
289 | if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400) | 309 | dmae_init(sh_chan); |
290 | dmae_set_chcr(sh_chan, RS_DEFAULT); | ||
291 | } | 310 | } |
292 | 311 | ||
293 | spin_lock_bh(&sh_chan->desc_lock); | 312 | spin_lock_bh(&sh_chan->desc_lock); |
@@ -757,7 +776,7 @@ static irqreturn_t sh_dmae_err(int irq, void *data) | |||
757 | sh_dmae_ctl_stop(shdev); | 776 | sh_dmae_ctl_stop(shdev); |
758 | 777 | ||
759 | /* We cannot detect, which channel caused the error, have to reset all */ | 778 | /* We cannot detect, which channel caused the error, have to reset all */ |
760 | for (i = 0; i < MAX_DMA_CHANNELS; i++) { | 779 | for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) { |
761 | struct sh_dmae_chan *sh_chan = shdev->chan[i]; | 780 | struct sh_dmae_chan *sh_chan = shdev->chan[i]; |
762 | if (sh_chan) { | 781 | if (sh_chan) { |
763 | struct sh_desc *desc; | 782 | struct sh_desc *desc; |
@@ -822,6 +841,9 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
822 | return -ENOMEM; | 841 | return -ENOMEM; |
823 | } | 842 | } |
824 | 843 | ||
844 | /* copy struct dma_device */ | ||
845 | new_sh_chan->common.device = &shdev->common; | ||
846 | |||
825 | new_sh_chan->dev = shdev->common.dev; | 847 | new_sh_chan->dev = shdev->common.dev; |
826 | new_sh_chan->id = id; | 848 | new_sh_chan->id = id; |
827 | new_sh_chan->irq = irq; | 849 | new_sh_chan->irq = irq; |
@@ -840,9 +862,6 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
840 | INIT_LIST_HEAD(&new_sh_chan->ld_queue); | 862 | INIT_LIST_HEAD(&new_sh_chan->ld_queue); |
841 | INIT_LIST_HEAD(&new_sh_chan->ld_free); | 863 | INIT_LIST_HEAD(&new_sh_chan->ld_free); |
842 | 864 | ||
843 | /* copy struct dma_device */ | ||
844 | new_sh_chan->common.device = &shdev->common; | ||
845 | |||
846 | /* Add the channel to DMA device channel list */ | 865 | /* Add the channel to DMA device channel list */ |
847 | list_add_tail(&new_sh_chan->common.device_node, | 866 | list_add_tail(&new_sh_chan->common.device_node, |
848 | &shdev->common.channels); | 867 | &shdev->common.channels); |
@@ -896,8 +915,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
896 | { | 915 | { |
897 | struct sh_dmae_pdata *pdata = pdev->dev.platform_data; | 916 | struct sh_dmae_pdata *pdata = pdev->dev.platform_data; |
898 | unsigned long irqflags = IRQF_DISABLED, | 917 | unsigned long irqflags = IRQF_DISABLED, |
899 | chan_flag[MAX_DMA_CHANNELS] = {}; | 918 | chan_flag[SH_DMAC_MAX_CHANNELS] = {}; |
900 | int errirq, chan_irq[MAX_DMA_CHANNELS]; | 919 | int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; |
901 | int err, i, irq_cnt = 0, irqres = 0; | 920 | int err, i, irq_cnt = 0, irqres = 0; |
902 | struct sh_dmae_device *shdev; | 921 | struct sh_dmae_device *shdev; |
903 | struct resource *chan, *dmars, *errirq_res, *chanirq_res; | 922 | struct resource *chan, *dmars, *errirq_res, *chanirq_res; |
@@ -983,7 +1002,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
983 | 1002 | ||
984 | shdev->common.dev = &pdev->dev; | 1003 | shdev->common.dev = &pdev->dev; |
985 | /* Default transfer size of 32 bytes requires 32-byte alignment */ | 1004 | /* Default transfer size of 32 bytes requires 32-byte alignment */ |
986 | shdev->common.copy_align = 5; | 1005 | shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; |
987 | 1006 | ||
988 | #if defined(CONFIG_CPU_SH4) | 1007 | #if defined(CONFIG_CPU_SH4) |
989 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | 1008 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |