void pxa2xx_spi_dma_handler(int channel, void *data)
{
    struct driver_data *drv_data = data;
    u32 irq_status = DCSR(channel) & DMA_INT_MASK;

    if (irq_status & DCSR_BUSERR) {

        if (channel == drv_data->tx_channel)
            pxa2xx_spi_dma_error_stop(drv_data,
                                      "dma_handler: bad bus address on tx channel");
        else
            pxa2xx_spi_dma_error_stop(drv_data,
                                      "dma_handler: bad bus address on rx channel");
        return;
    }

    /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
    if ((channel == drv_data->tx_channel)
            && (irq_status & DCSR_ENDINTR)
            && (drv_data->ssp_type == PXA25x_SSP)) {

        /* Wait for rx to stall */
        if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
            dev_err(&drv_data->pdev->dev,
                    "dma_handler: ssp rx stall failed\n");

        /* finish this transfer, start the next */
        pxa2xx_spi_dma_transfer_complete(drv_data);
    }
}
示例#2
0
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
{
	struct spi_message *msg = drv_data->cur_msg;

	/* Clear and disable interrupts on SSP and DMA channels*/
	pxa2xx_spi_write(drv_data, SSCR1,
			 pxa2xx_spi_read(drv_data, SSCR1)
			 & ~drv_data->dma_cr1);
	write_SSSR_CS(drv_data, drv_data->clear_sr);
	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;

	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
		dev_err(&drv_data->pdev->dev,
			"dma_handler: dma rx channel stop failed\n");

	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
		dev_err(&drv_data->pdev->dev,
			"dma_transfer: ssp rx stall failed\n");

	pxa2xx_spi_unmap_dma_buffers(drv_data);

	/* update the buffer pointer for the amount completed in dma */
	drv_data->rx += drv_data->len -
			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);

	/* read trailing data from fifo, it does not matter how many
	 * bytes are in the fifo just read until buffer is full
	 * or fifo is empty, which ever occurs first */
	drv_data->read(drv_data);

	/* return count of what was actually read */
	msg->actual_length += drv_data->len -
				(drv_data->rx_end - drv_data->rx);

	/* Transfer delays and chip select release are
	 * handled in pump_transfers or giveback
	 */

	/* Move to next transfer */
	msg->state = pxa2xx_spi_next_transfer(drv_data);

	/* Schedule transfer tasklet */
	tasklet_schedule(&drv_data->pump_transfers);
}