irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) { u32 irq_status; irq_status = pxa2xx_spi_read(drv_data, SSSR) & drv_data->mask_sr; if (irq_status & SSSR_ROR) { pxa2xx_spi_dma_error_stop(drv_data, "dma_transfer: fifo overrun"); return IRQ_HANDLED; } /* Check for false positive timeout */ if ((irq_status & SSSR_TINT) && (DCSR(drv_data->tx_channel) & DCSR_RUN)) { pxa2xx_spi_write(drv_data, SSSR, SSSR_TINT); return IRQ_HANDLED; } if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { /* Clear and disable timeout interrupt, do the rest in * dma_transfer_complete */ if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); /* finish this transfer, start the next */ pxa2xx_spi_dma_transfer_complete(drv_data); return IRQ_HANDLED; } /* Opps problem detected */ return IRQ_NONE; }
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, bool error) { struct spi_message *msg = drv_data->master->cur_msg; /* * It is possible that one CPU is handling ROR interrupt and other * just gets DMA completion. Calling pump_transfers() twice for the * same transfer leads to problems thus we prevent concurrent calls * by using ->dma_running. */ if (atomic_dec_and_test(&drv_data->dma_running)) { /* * If the other CPU is still handling the ROR interrupt we * might not know about the error yet. So we re-check the * ROR bit here before we clear the status register. */ if (!error) { u32 status = pxa2xx_spi_read(drv_data, SSSR) & drv_data->mask_sr; error = status & SSSR_ROR; } /* Clear status & disable interrupts */ 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); if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); if (!error) { msg->actual_length += drv_data->len; msg->state = pxa2xx_spi_next_transfer(drv_data); } else { /* In case we got an error we disable the SSP now */ pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); msg->state = ERROR_STATE; } tasklet_schedule(&drv_data->pump_transfers); } }
static int u32_writer(struct driver_data *drv_data) { if (pxa2xx_spi_txfifo_full(drv_data) || (drv_data->tx == drv_data->tx_end)) return 0; pxa2xx_spi_write(drv_data, SSDR, *(u32 *)(drv_data->tx)); drv_data->tx += 4; return 1; }
static int null_writer(struct driver_data *drv_data) { u8 n_bytes = drv_data->n_bytes; if (pxa2xx_spi_txfifo_full(drv_data) || (drv_data->tx == drv_data->tx_end)) return 0; pxa2xx_spi_write(drv_data, SSDR, 0); drv_data->tx += n_bytes; return 1; }
static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data, const char *msg) { /* Stop and reset */ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; write_SSSR_CS(drv_data, drv_data->clear_sr); pxa2xx_spi_write(drv_data, SSCR1, pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->dma_cr1); if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_flush(drv_data); pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); pxa2xx_spi_unmap_dma_buffers(drv_data); dev_err(&drv_data->pdev->dev, "%s\n", msg); drv_data->cur_msg->state = ERROR_STATE; tasklet_schedule(&drv_data->pump_transfers); }
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); }
static void cs_assert(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; if (drv_data->ssp_type == CE4100_SSP) { pxa2xx_spi_write(drv_data, SSSR, drv_data->cur_chip->frm); return; } if (chip->cs_control) { chip->cs_control(PXA2XX_CS_ASSERT); return; } if (gpio_is_valid(chip->gpio_cs)) { gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted); return; } if (is_lpss_ssp(drv_data)) lpss_ssp_cs_control(drv_data, true); }