Esempio n. 1
0
static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi,
		unsigned int bytes, enum spi_direction dir)
{
	unsigned int todo, wcount;

	/*
	 * For DMA we need to think of things in terms of word count.
	 * AHB width is fixed at 32-bits. To avoid overrunning
	 * the in/out buffers we must align down. (Note: lowest 2-bits
	 * in WCOUNT register are ignored, and WCOUNT seems to count
	 * words starting at n-1)
	 *
	 * Example: If "bytes" is 7 and we are transferring 1-byte at a time,
	 * WCOUNT should be 4. The remaining 3 bytes must be transferred
	 * using PIO.
	 */
	todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_DMA - TEGRA_DMA_ALIGN_BYTES);
	todo = ALIGN_DOWN(todo, TEGRA_DMA_ALIGN_BYTES);
	wcount = ALIGN_DOWN(todo - TEGRA_DMA_ALIGN_BYTES, TEGRA_DMA_ALIGN_BYTES);

	flush_fifos(spi);

	if (dir == SPI_SEND) {
		spi->dma_out = dma_claim();
		if (!spi->dma_out)
			return -1;

		/* ensure bytes to send will be visible to DMA controller */
		dcache_clean_by_mva(spi->out_buf, bytes);

		write32(&spi->dma_out->regs->apb_ptr,
			(uintptr_t) & spi->regs->tx_fifo);
		write32(&spi->dma_out->regs->ahb_ptr, (uintptr_t)spi->out_buf);
		setbits_le32(&spi->dma_out->regs->csr, APB_CSR_DIR);
		setup_dma_params(spi, spi->dma_out);
		write32(&spi->dma_out->regs->wcount, wcount);
	} else {
		spi->dma_in = dma_claim();
		if (!spi->dma_in)
			return -1;

		/* avoid data collisions */
		dcache_clean_invalidate_by_mva(spi->in_buf, bytes);

		write32(&spi->dma_in->regs->apb_ptr,
			(uintptr_t)&spi->regs->rx_fifo);
		write32(&spi->dma_in->regs->ahb_ptr, (uintptr_t)spi->in_buf);
		clrbits_le32(&spi->dma_in->regs->csr, APB_CSR_DIR);
		setup_dma_params(spi, spi->dma_in);
		write32(&spi->dma_in->regs->wcount, wcount);
	}

	/* BLOCK_SIZE starts at n-1 */
	write32(&spi->regs->dma_blk, todo - 1);
	return todo;
}
Esempio n. 2
0
int
pcie_write(char *buf, int size)
{
   volatile char *tmp = (char *)_dma_addr_ptr;
   int i, tlp_sz, tlp_cnt, nsize;
   unsigned long long watchdog=0;
   
   for(i=0; i < size; i++) {
      tmp[i] = buf[i]; // todo: is memcpy safe here?
   }
   
   setup_dma_params(size, &nsize, &tlp_sz, &tlp_cnt);
   setup_read_dma(tlp_sz, tlp_cnt);
   read_dma_start(); // move data from main memory to FPGA
   
   ++__fifowcnt__; // increment local write count
   
   while(__fifowcnt__ != read_ctrl(RX_CNT_OFFSET)) { // spin-wait until FPGA consumes entire DMA payload 
      if(++watchdog > TIMEOUT) {
         printk("timeout\n");
         return 0;
      }
   }
   
   return size;
}
Esempio n. 3
0
int
pcie_read(char *buf, int size)
{
   unsigned long long watchdog=0;
   volatile char *tmp = (char *)_dma_addr_ptr;
   int i, tlp_sz, tlp_cnt, nsize;
   //unsigned long long watchdog=0;
   
   ++__fiforcnt__; // increment local read count
   
   //printk("waiting.... me:%llx it:%x\n", __fiforcnt__, read_ctrl(TX_CNT_OFFSET));
   while(__fiforcnt__ != read_ctrl(TX_CNT_OFFSET)) {
      //printk("waiting.... me:%llx it:%x\n", __fiforcnt__, read_ctrl(TX_CNT_OFFSET));
      if(++watchdog > TIMEOUT) {
         printk("fiforcnt timeout\n");
         return 0;
      }
   }
   //printk("done waiting.... me:%llx it:%x\n", __fiforcnt__, read_ctrl(TX_CNT_OFFSET));
   
   setup_dma_params(size, &nsize, &tlp_sz, &tlp_cnt);
   setup_write_dma(tlp_sz, tlp_cnt);
   write_dma_start(); // move data from FPGA to main memory
   
 //  printk("waiting for write_dma_done()\n");
   watchdog = 0;
   while(!write_dma_done()) {
      if(++watchdog > TIMEOUT) {
         printk("write dma done timeout\n");
         return 0;
      }
   }
  // printk("write_dma_done()\n");
   
   for(i=0; i < size; i++)
      buf[i] = tmp[i];
   
   return size;
}