1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-24 02:26:15 +02:00

ubb-patgen/ubb-patgen.c: clean up pattern generation and boundaries

The main change is to use only a single transfer and thus avoid tri-stating
DATx during the command phase. To control the timing, we put the first word
"manually" into the FIFO, wait until it has been sent on the bus, and only
then DMA the rest.
This commit is contained in:
Werner Almesberger 2013-01-14 16:44:41 -03:00
parent 09bf9c23ab
commit fa8b5b6324

View File

@ -174,8 +174,35 @@ static void dma_setup(unsigned long buf, int nibbles)
} }
static void wait_dma_done(void)
{
while (!((DCS(DMA) >> 3) & 1)); /* DCS.TT */
}
static void wait_response(void)
{
while (!((MSC_STAT >> 11 ) & 1)); /* MSC_STAT.END_CMD_RES */
}
static void wait_fifo_empty(void)
{
while (!((MSC_STAT >> 6 ) & 1)); /* MSC_STAT.DATA_FIFO_EMPTY */
}
static void wait_shifted(const struct mmcclk *clk)
{
/* 8 nibbles */
double us = 8*1000000.0/clk->bus_clk_hz;
usleep((int) us+1);
}
static void mmc_buffer(const struct mmcclk *clk, static void mmc_buffer(const struct mmcclk *clk,
unsigned long buf, int nibbles) uint8_t first, unsigned long buf, int nibbles, uint32_t mask)
{ {
MSC_STRPCL = 1 << 3; /* reset the MSC */ MSC_STRPCL = 1 << 3; /* reset the MSC */
@ -186,6 +213,7 @@ static void mmc_buffer(const struct mmcclk *clk,
MSC_CLKRT = clk->clkrt; /* cleared by MSC reset */ MSC_CLKRT = clk->clkrt; /* cleared by MSC reset */
MSC_STRPCL = 2; /* start the bus clock */ MSC_STRPCL = 2; /* start the bus clock */
MSC_RESTO = 0xffff; /* maximum response time-out */ MSC_RESTO = 0xffff; /* maximum response time-out */
MSC_BLKLEN = 0xfff; /* never reach the end (with CRC) */
MSC_CMDAT = MSC_CMDAT =
(2 << 9) | /* 4 bit bus */ (2 << 9) | /* 4 bit bus */
@ -196,25 +224,33 @@ static void mmc_buffer(const struct mmcclk *clk,
MSC_STRPCL = 4; /* START_OP */ MSC_STRPCL = 4; /* START_OP */
wait_response();
MSC_TXFIFO = first*0x11111111;
wait_fifo_empty();
wait_shifted(clk);
PDFUNS = mask;
DCS(DMA) = DCS(DMA) =
(1 << 31) | /* no descriptor */ (1 << 31) | /* no descriptor */
1; /* enable transfer */ 1; /* enable transfer */
usleep(100); wait_dma_done();
sleep(1); wait_fifo_empty();
wait_shifted(clk);
printf("MSC_STAT 0x%x\n", MSC_STAT);
} }
static void send_buffer(const struct mmcclk *clk, static void send_buffer(const struct mmcclk *clk,
const uint8_t *buf, int nibbles) const uint8_t *buf, int nibbles, uint32_t mask)
{ {
unsigned long phys; unsigned long phys;
phys = physmem_xlat((void *) buf); phys = physmem_xlat((void *) buf);
mmc_buffer(clk, phys, nibbles); mmc_buffer(clk, buf[0] >> 4, phys, nibbles, mask);
} }
@ -224,7 +260,6 @@ static int dma_pattern(const struct mmcclk *clk,
int n = strlen(pattern); int n = strlen(pattern);
int rounded = (n+63) & ~63; int rounded = (n+63) & ~63;
uint8_t *buf = physmem_malloc(rounded >> 1); uint8_t *buf = physmem_malloc(rounded >> 1);
uint8_t *tmp = physmem_malloc(32);
int i; int i;
if (!n) if (!n)
@ -242,17 +277,12 @@ static int dma_pattern(const struct mmcclk *clk,
dma_init(); dma_init();
PDFUNS = UBB_CMD;
PDDATC = ~((buf[0] >> 4) << 10) & mask; PDDATC = ~((buf[0] >> 4) << 10) & mask;
PDDATS = (buf[0] >> 4) << 10; PDDATS = (buf[0] >> 4) << 10;
PDDIRS = mask; PDDIRS = mask;
memset(tmp, (buf[0] >> 4)*0x11, 64); send_buffer(clk, buf, rounded, mask);
send_buffer(clk, tmp, 64);
PDFUNS = mask;
send_buffer(clk, buf, rounded);
PDDATC = ~((buf[(rounded >> 1)-1] & 0xf) << 10) & mask; PDDATC = ~((buf[(rounded >> 1)-1] & 0xf) << 10) & mask;
PDDATS = (buf[(rounded >> 1)-1] & 0xf) << 10; PDDATS = (buf[(rounded >> 1)-1] & 0xf) << 10;