mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 19:14:40 +02:00
ubb-patgen/ubb-patgen.c: describe the pattern transfer logic
This commit is contained in:
parent
fa8b5b6324
commit
e5cb1c98ea
@ -204,6 +204,13 @@ static void wait_shifted(const struct mmcclk *clk)
|
|||||||
static void mmc_buffer(const struct mmcclk *clk,
|
static void mmc_buffer(const struct mmcclk *clk,
|
||||||
uint8_t first, unsigned long buf, int nibbles, uint32_t mask)
|
uint8_t first, unsigned long buf, int nibbles, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If under control of the MMC controller, DATx tri-state until we
|
||||||
|
* actually send data. That's why they have been set up as GPIOs and
|
||||||
|
* we'll only switch them to function when the MMC controller is in a
|
||||||
|
* well-defined state.
|
||||||
|
*/
|
||||||
|
|
||||||
MSC_STRPCL = 1 << 3; /* reset the MSC */
|
MSC_STRPCL = 1 << 3; /* reset the MSC */
|
||||||
|
|
||||||
while (MSC_STAT & (1 << 15)); /* wait until reset finishes */
|
while (MSC_STAT & (1 << 15)); /* wait until reset finishes */
|
||||||
@ -224,6 +231,12 @@ static void mmc_buffer(const struct mmcclk *clk,
|
|||||||
|
|
||||||
MSC_STRPCL = 4; /* START_OP */
|
MSC_STRPCL = 4; /* START_OP */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we've reached the end of the command and then send the
|
||||||
|
* first pattern (eight times, since this is the smallest amount we
|
||||||
|
* can send.
|
||||||
|
*/
|
||||||
|
|
||||||
wait_response();
|
wait_response();
|
||||||
|
|
||||||
MSC_TXFIFO = first*0x11111111;
|
MSC_TXFIFO = first*0x11111111;
|
||||||
@ -231,8 +244,20 @@ static void mmc_buffer(const struct mmcclk *clk,
|
|||||||
wait_fifo_empty();
|
wait_fifo_empty();
|
||||||
wait_shifted(clk);
|
wait_shifted(clk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the transfer (of nominally 4095 bytes) is not done yet, the
|
||||||
|
* MMC controller will hold the bus at the last value sent. It's now
|
||||||
|
* safe to switch from GPIO to function.
|
||||||
|
*/
|
||||||
|
|
||||||
PDFUNS = mask;
|
PDFUNS = mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the pattern with DMA. Note that we still have to send the first
|
||||||
|
* pattern, since the static state we begin from may not have been
|
||||||
|
* present long enough.
|
||||||
|
*/
|
||||||
|
|
||||||
DCS(DMA) =
|
DCS(DMA) =
|
||||||
(1 << 31) | /* no descriptor */
|
(1 << 31) | /* no descriptor */
|
||||||
1; /* enable transfer */
|
1; /* enable transfer */
|
||||||
@ -241,6 +266,14 @@ static void mmc_buffer(const struct mmcclk *clk,
|
|||||||
|
|
||||||
wait_fifo_empty();
|
wait_fifo_empty();
|
||||||
wait_shifted(clk);
|
wait_shifted(clk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're done. As far as the MMC controller is concerned, the transfer
|
||||||
|
* is still not finished (i.e., we haven't sent 4095 bytes) and will
|
||||||
|
* therefore just hold the bus. We can now return the bus to GPIO.
|
||||||
|
* This form of handover also prevents the MMC controller from sending
|
||||||
|
* a CRC, which may confuse the recipient of the pattern.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -277,6 +310,8 @@ static int dma_pattern(const struct mmcclk *clk,
|
|||||||
|
|
||||||
dma_init();
|
dma_init();
|
||||||
|
|
||||||
|
/* Initial static state: the first pattern. */
|
||||||
|
|
||||||
PDFUNS = UBB_CMD;
|
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;
|
||||||
@ -284,6 +319,8 @@ static int dma_pattern(const struct mmcclk *clk,
|
|||||||
|
|
||||||
send_buffer(clk, buf, rounded, mask);
|
send_buffer(clk, buf, rounded, mask);
|
||||||
|
|
||||||
|
/* Final static state: the last pattern. */
|
||||||
|
|
||||||
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