/*
* ADMA driver for Nvidia's Tegra210 ADMA controller.
*
- * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
/* Returns bytes transferred with period size granularity */
static inline uint64_t tegra_adma_get_position(struct tegra_adma_chan *tdc)
{
+ unsigned long cur_tc = 0;
uint64_t tx_done_max = (ADMA_CH_TRANSFER_DONE_COUNT_MASK >>
ADMA_CH_TRANSFER_DONE_COUNT_SHIFT) + 1;
uint64_t tx_done = channel_read(tdc, ADMA_CH_TRANSFER_STATUS) &
else
tdc->total_tx_done += (tx_done - tdc->channel_reg.tx_done);
tdc->channel_reg.tx_done = tx_done;
- return tdc->total_tx_done * tdc->channel_reg.tc;
+
+ /* read TC_STATUS register to get current transfer status */
+ cur_tc = channel_read(tdc, ADMA_CH_TC_STATUS);
+ /* get transferred data count */
+ cur_tc = tdc->channel_reg.tc - cur_tc;
+
+ return (tdc->total_tx_done * tdc->channel_reg.tc) + cur_tc;
}
static bool handle_continuous_head_request(struct tegra_adma_chan *tdc,
list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
if (dma_desc->txd.cookie == cookie) {
residual = dma_desc->bytes_requested -
- (dma_desc->bytes_transferred %
+ (tegra_adma_get_position(tdc) %
dma_desc->bytes_requested);
dma_set_residue(txstate, residual);
ret = dma_desc->dma_status;
dma_desc = sg_req->dma_desc;
if (dma_desc->txd.cookie == cookie) {
residual = dma_desc->bytes_requested -
- (dma_desc->bytes_transferred %
+ (tegra_adma_get_position(tdc) %
dma_desc->bytes_requested);
dma_set_residue(txstate, residual);
ret = dma_desc->dma_status;