diff options
| -rw-r--r-- | drivers/dma/mmp_tdma.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 70c2fa9963cd..b6f4e1fc9c78 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c | |||
| @@ -110,7 +110,7 @@ struct mmp_tdma_chan { | |||
| 110 | struct tasklet_struct tasklet; | 110 | struct tasklet_struct tasklet; |
| 111 | 111 | ||
| 112 | struct mmp_tdma_desc *desc_arr; | 112 | struct mmp_tdma_desc *desc_arr; |
| 113 | phys_addr_t desc_arr_phys; | 113 | dma_addr_t desc_arr_phys; |
| 114 | int desc_num; | 114 | int desc_num; |
| 115 | enum dma_transfer_direction dir; | 115 | enum dma_transfer_direction dir; |
| 116 | dma_addr_t dev_addr; | 116 | dma_addr_t dev_addr; |
| @@ -166,9 +166,12 @@ static void mmp_tdma_enable_chan(struct mmp_tdma_chan *tdmac) | |||
| 166 | static int mmp_tdma_disable_chan(struct dma_chan *chan) | 166 | static int mmp_tdma_disable_chan(struct dma_chan *chan) |
| 167 | { | 167 | { |
| 168 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); | 168 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); |
| 169 | u32 tdcr; | ||
| 169 | 170 | ||
| 170 | writel(readl(tdmac->reg_base + TDCR) & ~TDCR_CHANEN, | 171 | tdcr = readl(tdmac->reg_base + TDCR); |
| 171 | tdmac->reg_base + TDCR); | 172 | tdcr |= TDCR_ABR; |
| 173 | tdcr &= ~TDCR_CHANEN; | ||
| 174 | writel(tdcr, tdmac->reg_base + TDCR); | ||
| 172 | 175 | ||
| 173 | tdmac->status = DMA_COMPLETE; | 176 | tdmac->status = DMA_COMPLETE; |
| 174 | 177 | ||
| @@ -296,12 +299,27 @@ static int mmp_tdma_clear_chan_irq(struct mmp_tdma_chan *tdmac) | |||
| 296 | return -EAGAIN; | 299 | return -EAGAIN; |
| 297 | } | 300 | } |
| 298 | 301 | ||
| 302 | static size_t mmp_tdma_get_pos(struct mmp_tdma_chan *tdmac) | ||
| 303 | { | ||
| 304 | size_t reg; | ||
| 305 | |||
| 306 | if (tdmac->idx == 0) { | ||
| 307 | reg = __raw_readl(tdmac->reg_base + TDSAR); | ||
| 308 | reg -= tdmac->desc_arr[0].src_addr; | ||
| 309 | } else if (tdmac->idx == 1) { | ||
| 310 | reg = __raw_readl(tdmac->reg_base + TDDAR); | ||
| 311 | reg -= tdmac->desc_arr[0].dst_addr; | ||
| 312 | } else | ||
| 313 | return -EINVAL; | ||
| 314 | |||
| 315 | return reg; | ||
| 316 | } | ||
| 317 | |||
| 299 | static irqreturn_t mmp_tdma_chan_handler(int irq, void *dev_id) | 318 | static irqreturn_t mmp_tdma_chan_handler(int irq, void *dev_id) |
| 300 | { | 319 | { |
| 301 | struct mmp_tdma_chan *tdmac = dev_id; | 320 | struct mmp_tdma_chan *tdmac = dev_id; |
| 302 | 321 | ||
| 303 | if (mmp_tdma_clear_chan_irq(tdmac) == 0) { | 322 | if (mmp_tdma_clear_chan_irq(tdmac) == 0) { |
| 304 | tdmac->pos = (tdmac->pos + tdmac->period_len) % tdmac->buf_len; | ||
| 305 | tasklet_schedule(&tdmac->tasklet); | 323 | tasklet_schedule(&tdmac->tasklet); |
| 306 | return IRQ_HANDLED; | 324 | return IRQ_HANDLED; |
| 307 | } else | 325 | } else |
| @@ -343,7 +361,7 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac) | |||
| 343 | int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); | 361 | int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); |
| 344 | 362 | ||
| 345 | gpool = tdmac->pool; | 363 | gpool = tdmac->pool; |
| 346 | if (tdmac->desc_arr) | 364 | if (gpool && tdmac->desc_arr) |
| 347 | gen_pool_free(gpool, (unsigned long)tdmac->desc_arr, | 365 | gen_pool_free(gpool, (unsigned long)tdmac->desc_arr, |
| 348 | size); | 366 | size); |
| 349 | tdmac->desc_arr = NULL; | 367 | tdmac->desc_arr = NULL; |
| @@ -499,6 +517,7 @@ static enum dma_status mmp_tdma_tx_status(struct dma_chan *chan, | |||
| 499 | { | 517 | { |
| 500 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); | 518 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); |
| 501 | 519 | ||
| 520 | tdmac->pos = mmp_tdma_get_pos(tdmac); | ||
| 502 | dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, | 521 | dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, |
| 503 | tdmac->buf_len - tdmac->pos); | 522 | tdmac->buf_len - tdmac->pos); |
| 504 | 523 | ||
| @@ -610,7 +629,7 @@ static int mmp_tdma_probe(struct platform_device *pdev) | |||
| 610 | int i, ret; | 629 | int i, ret; |
| 611 | int irq = 0, irq_num = 0; | 630 | int irq = 0, irq_num = 0; |
| 612 | int chan_num = TDMA_CHANNEL_NUM; | 631 | int chan_num = TDMA_CHANNEL_NUM; |
| 613 | struct gen_pool *pool; | 632 | struct gen_pool *pool = NULL; |
| 614 | 633 | ||
| 615 | of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev); | 634 | of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev); |
| 616 | if (of_id) | 635 | if (of_id) |
