|
@@ -160,6 +160,7 @@ struct dw_spi {
|
|
|
void (*transfer_handler)(struct dw_spi *dws);
|
|
void (*transfer_handler)(struct dw_spi *dws);
|
|
|
u32 current_freq; /* frequency in hz */
|
|
u32 current_freq; /* frequency in hz */
|
|
|
u32 current_qspi_freq;
|
|
u32 current_qspi_freq;
|
|
|
|
|
+ int xfer_ret;
|
|
|
|
|
|
|
|
/* DMA info */
|
|
/* DMA info */
|
|
|
int dma_inited;
|
|
int dma_inited;
|
|
@@ -404,6 +405,7 @@ static void dma_transfer(struct dw_spi *dws)
|
|
|
|
|
|
|
|
dw_readl(dws, DW_SPI_ICR);
|
|
dw_readl(dws, DW_SPI_ICR);
|
|
|
int_error_stop(dws, "dma_transfer: fifo overrun/underrun");
|
|
int_error_stop(dws, "dma_transfer: fifo overrun/underrun");
|
|
|
|
|
+ dws->xfer_ret = 1;
|
|
|
xQueueSendFromISR(dws->xfer_done, NULL, 0);
|
|
xQueueSendFromISR(dws->xfer_done, NULL, 0);
|
|
|
|
|
|
|
|
return;
|
|
return;
|
|
@@ -626,6 +628,7 @@ xfer_continue:
|
|
|
if (ndf > 0xffff) ndf = 0xffff;
|
|
if (ndf > 0xffff) ndf = 0xffff;
|
|
|
|
|
|
|
|
dws->dma_mapped = 1;
|
|
dws->dma_mapped = 1;
|
|
|
|
|
+ dws->xfer_ret = 0;
|
|
|
dws->rx = (u8*)message->recv_buf + xfer_len;
|
|
dws->rx = (u8*)message->recv_buf + xfer_len;
|
|
|
dws->len = (ndf + 1) * dws->n_bytes;
|
|
dws->len = (ndf + 1) * dws->n_bytes;
|
|
|
dws->rx_end = (u8*)dws->rx + dws->len;
|
|
dws->rx_end = (u8*)dws->rx + dws->len;
|
|
@@ -721,13 +724,35 @@ xfer_continue:
|
|
|
goto end;
|
|
goto end;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (dws->dma_mapped && dws->rx_dummy_buffer) {
|
|
|
|
|
|
|
+ if (dws->xfer_ret) {
|
|
|
|
|
+ dws->xfer_ret = 0;
|
|
|
|
|
+ ret = -1;
|
|
|
|
|
+ if (dws->dma_mapped) {
|
|
|
|
|
+ if (dws->rx_dummy_buffer) {
|
|
|
|
|
+ vPortFree(dws->rx_dummy_buffer);
|
|
|
|
|
+ dws->rx_dummy_buffer = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ dma_stop_channel(dws->dma_rx);
|
|
|
|
|
+ }
|
|
|
|
|
+ goto end;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dws->dma_mapped) {
|
|
|
|
|
+ portDISABLE_INTERRUPTS();
|
|
|
|
|
+ if (dws->rx_dummy_buffer) {
|
|
|
|
|
+ CP15_invalidate_dcache_for_dma((uint32_t)dws->rx_dummy_buffer,
|
|
|
|
|
+ (uint32_t)dws->rx_dummy_buffer + dws->len);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ CP15_invalidate_dcache_for_dma((uint32_t)dws->rx, (uint32_t)dws->rx + dws->len);
|
|
|
|
|
+ }
|
|
|
|
|
+ portENABLE_INTERRUPTS();
|
|
|
|
|
+ if (dws->rx_dummy_buffer) {
|
|
|
memcpy(dws->rx, dws->rx_dummy_buffer, dws->len);
|
|
memcpy(dws->rx, dws->rx_dummy_buffer, dws->len);
|
|
|
vPortFree(dws->rx_dummy_buffer);
|
|
vPortFree(dws->rx_dummy_buffer);
|
|
|
dws->rx_dummy_buffer = NULL;
|
|
dws->rx_dummy_buffer = NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
dma_stop_channel(dws->dma_rx);
|
|
dma_stop_channel(dws->dma_rx);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
xfer_len += dws->len;
|
|
xfer_len += dws->len;
|
|
|
if (xfer_len < message->length) {
|
|
if (xfer_len < message->length) {
|
|
@@ -909,7 +934,7 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_message *message)
|
|
|
cfg.direction = DMA_DEV_TO_MEM;
|
|
cfg.direction = DMA_DEV_TO_MEM;
|
|
|
cfg.src_addr = REGS_SPI0_BASE + DW_SPI_DR;
|
|
cfg.src_addr = REGS_SPI0_BASE + DW_SPI_DR;
|
|
|
//if (((u32)dws->rx/* | dws->len*/) & (ARCH_DMA_MINALIGN - 1)) {
|
|
//if (((u32)dws->rx/* | dws->len*/) & (ARCH_DMA_MINALIGN - 1)) {
|
|
|
- if ((u32)dws->rx & 3) {
|
|
|
|
|
|
|
+ if ((u32)dws->rx & 31) {
|
|
|
dws->rx_dummy_buffer = pvPortMalloc(dws->len);
|
|
dws->rx_dummy_buffer = pvPortMalloc(dws->len);
|
|
|
if (!dws->rx_dummy_buffer)
|
|
if (!dws->rx_dummy_buffer)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|