imx233: small dma changes, update debug screen

Reduce DMA maximum transfer size since transfering 64Kb requires
to set a size of 0 and it's not worth adding checks everywhere
to handle this special case. Also add statistics about unaligned
transfer (wrt to cache). Update debug screen accordingly and
simplify it so it can fit smaller screens too.

Change-Id: I18391702f5e100a21f6f8d1ebab28d9f2bd8c66f
This commit is contained in:
Amaury Pouly 2012-08-18 15:22:51 +02:00
parent 51919937a9
commit 246c2127a7
3 changed files with 26 additions and 16 deletions

View file

@ -111,17 +111,15 @@ bool dbg_hw_info_dma(void)
lcd_clear_display();
lcd_putsf(0, 0, "I G F C E name bar apb ahb");
lcd_putsf(0, 0, "S C name bar apb ahb una");
for(unsigned i = 0; i < ARRAYLEN(dbg_channels); i++)
{
struct imx233_dma_info_t info = imx233_dma_get_info(dbg_channels[i].chan, DMA_INFO_ALL);
lcd_putsf(0, i + 1, "%c %c %c %c %c %4s %x %x %x",
info.int_enabled ? 'i' : ' ',
info.gated ? 'g' : ' ',
info.freezed ? 'f' : ' ',
info.int_cmdcomplt ? 'c' : ' ',
info.int_error ? 'e' : ' ',
dbg_channels[i].name, info.bar, info.apb_bytes, info.ahb_bytes);
lcd_putsf(0, i + 1, "%c %c %4s %8x %3x %3x %3x",
info.gated ? 'g' : info.freezed ? 'f' : ' ',
!info.int_enabled ? '-' : info.int_error ? 'e' : info.int_cmdcomplt ? 'c' : ' ',
dbg_channels[i].name, info.bar, info.apb_bytes, info.ahb_bytes,
info.nr_unaligned);
}
lcd_update();

View file

@ -27,6 +27,9 @@
#include "lcd.h"
#include "string.h"
// statistics about unaligned transfers
static int apb_nr_unaligned[32];
void imx233_dma_init(void)
{
/* Enable APHB and APBX */
@ -142,7 +145,7 @@ bool imx233_dma_is_channel_error_irq(unsigned chan)
/* Commit and/or discard all DMA descriptors and buffers pointed by them,
* handle circular lists. At the same time, convert virtual pointers to
* real ones */
static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd)
static void imx233_dma_commit_and_discard(unsigned chan, struct apb_dma_command_t *cmd)
{
/* We handle circular descriptors by using unused bits:
* bits 8-11 are not used by the hardware so we first go through the whole
@ -162,6 +165,8 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd)
/* host > device: commit and discard */
else if(op == HW_APB_CHx_CMD__COMMAND__READ)
commit_discard_dcache_range(cur->buffer, sz);
if((uint32_t)cur->buffer % CACHEALIGN_SIZE)
apb_nr_unaligned[chan]++;
/* Virtual to physical buffer pointer conversion */
cur->buffer = PHYSICAL_ADDR(cur->buffer);
/* chain ? */
@ -195,7 +200,7 @@ static void imx233_dma_commit_and_discard(struct apb_dma_command_t *cmd)
void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
{
imx233_dma_commit_and_discard(cmd);
imx233_dma_commit_and_discard(chan, cmd);
if(APB_IS_APBX_CHANNEL(chan))
{
HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)PHYSICAL_ADDR(cmd);
@ -208,16 +213,18 @@ void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
}
}
void imx233_dma_wait_completion(unsigned chan)
int imx233_dma_wait_completion(unsigned chan, unsigned tmo)
{
tmo += current_tick;
volatile uint32_t *sema;
if(APB_IS_APBX_CHANNEL(chan))
sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
else
sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
while(*sema & HW_APB_CHx_SEMA__PHORE_BM)
while(*sema & HW_APB_CHx_SEMA__PHORE_BM && !TIME_AFTER(current_tick, tmo))
yield();
return __XTRACT_EX(*sema, HW_APB_CHx_SEMA__PHORE);
}
struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags)
@ -254,6 +261,7 @@ struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags)
s.int_error = apbx ? HW_APBX_CTRL2 & HW_APBX_CTRL2__CHx_ERROR_IRQ(dmac) :
HW_APBH_CTRL2 & HW_APBH_CTRL2__CHx_ERROR_IRQ(dmac);
}
s.nr_unaligned = apb_nr_unaligned[chan];
return s;
}

View file

@ -154,6 +154,7 @@ struct imx233_dma_info_t
bool int_enabled;
bool int_cmdcomplt;
bool int_error;
int nr_unaligned;
};
#define APBH_DMA_CHANNEL(i) i
@ -168,6 +169,7 @@ struct imx233_dma_info_t
#define APB_NAND(dev) APBH_DMA_CHANNEL(HW_APBH_NAND(dev))
#define HW_APB_CHx_CMD__COMMAND_BM 0x3
#define HW_APB_CHx_CMD__COMMAND_BP 0
#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0
#define HW_APB_CHx_CMD__COMMAND__WRITE 1
#define HW_APB_CHx_CMD__COMMAND__READ 2
@ -180,7 +182,7 @@ struct imx233_dma_info_t
#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6)
#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7)
/* An errata advise not to use it */
//#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000
#define HW_APB_CHx_CMD__CMDWORDS_BP 12
#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000
@ -193,8 +195,9 @@ struct imx233_dma_info_t
#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000
#define HW_APB_CHx_SEMA__PHORE_BP 16
/* A single descriptor cannot transfer more than 2^16 bytes */
#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16)
/* A single descriptor cannot transfer more than 2^16 bytes but because of the
* weird 0=64KiB, it's safer to restrict to 2^15 */
#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 15)
void imx233_dma_init(void);
void imx233_dma_reset_channel(unsigned chan);
@ -208,7 +211,8 @@ void imx233_dma_clear_channel_interrupt(unsigned chan);
bool imx233_dma_is_channel_error_irq(unsigned chan);
/* assume no command is in progress */
void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd);
void imx233_dma_wait_completion(unsigned chan);
/* return value of the semaphore */
int imx233_dma_wait_completion(unsigned chan, unsigned tmo);
/* get some info
* WARNING: if channel is not freezed, data might not be coherent ! */
struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags);