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:
parent
09bf9c23ab
commit
fa8b5b6324
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user