コード例 #1
0
void AT91F_SpiInit(void)
{
	/* Reset the SPI */
	writel(AT91_SPI_SWRST, AT91_BASE_SPI + AT91_SPI_CR);

	/* Configure SPI in Master Mode with No CS selected !!! */
	writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS,
	       AT91_BASE_SPI + AT91_SPI_MR);

	/* Configure CS0 */
	writel(AT91_SPI_NCPHA |
	       (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
	       (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
	       ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
	       AT91_BASE_SPI + AT91_SPI_CSR(0));

#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1
	/* Configure CS1 */
	writel(AT91_SPI_NCPHA |
	       (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
	       (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
	       ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
	       AT91_BASE_SPI + AT91_SPI_CSR(1));
#endif
#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS2
	/* Configure CS2 */
	writel(AT91_SPI_NCPHA |
	       (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
	       (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
	       ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
	       AT91_BASE_SPI + AT91_SPI_CSR(2));
#endif
#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS3
	/* Configure CS3 */
	writel(AT91_SPI_NCPHA |
	       (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
	       (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
	       ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
	       AT91_BASE_SPI + AT91_SPI_CSR(3));
#endif

	/* SPI_Enable */
	writel(AT91_SPI_SPIEN, AT91_BASE_SPI + AT91_SPI_CR);

	while (!(readl(AT91_BASE_SPI + AT91_SPI_SR) & AT91_SPI_SPIENS));

	/*
	 * Add tempo to get SPI in a safe state.
	 * Should not be needed for new silicon (Rev B)
	 */
	udelay(500000);
	readl(AT91_BASE_SPI + AT91_SPI_SR);
	readl(AT91_BASE_SPI + AT91_SPI_RDR);

}
コード例 #2
0
/*
 * Handle interrupts from the SPI controller.
 */
static irqreturn_t at91spi_interrupt(int irq, void *dev_id)
{
	unsigned int status;
	struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
	struct spi_transfer_list *list = device->xfers;

#ifdef DEBUG_SPI
	printk("SPI interrupt %i\n", current_device);
#endif

	if (!list)
		panic("at91_spi: spi_interrupt with a NULL transfer list");

		status = at91_spi_read(AT91_SPI_SR) & at91_spi_read(AT91_SPI_IMR);	/* read status */

	dma_unmap_single(NULL, device->tx, list->txlen[list->curr], DMA_TO_DEVICE);
	dma_unmap_single(NULL, device->rx, list->rxlen[list->curr], DMA_FROM_DEVICE);

	device->tx = device->txnext;	/* move next transfer to current transfer */
	device->rx = device->rxnext;

	list->curr = list->curr + 1;
	if (list->curr == list->nr_transfers) {		/* all transfers complete */
		at91_spi_write(AT91_SPI_IDR, AT91_SPI_ENDRX);		/* disable interrupt */

		/* Disable transmitter and receiver */
		at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);

		device->xfers = NULL;
		complete(&transfer_complete);
	}
	else if (list->curr+1 == list->nr_transfers) {	/* no more next transfers */
		device->txnext = 0;
		device->rxnext = 0;
		at91_spi_write(ATMEL_PDC_TNCR, 0);
		at91_spi_write(ATMEL_PDC_RNCR, 0);
	}
	else {
		int i = (list->curr)+1;

		/* If we are in 16-bit mode, we need to modify what we pass to the PDC */
		int tx_size = (at91_spi_read(AT91_SPI_CSR(current_device)) & AT91_SPI_BITS_16) ? 2 : 1;

		device->txnext = dma_map_single(NULL, list->tx[i], list->txlen[i], DMA_TO_DEVICE);
		device->rxnext = dma_map_single(NULL, list->rx[i], list->rxlen[i], DMA_FROM_DEVICE);
		at91_spi_write(ATMEL_PDC_TNPR, device->txnext);
		at91_spi_write(ATMEL_PDC_RNPR, device->rxnext);
		at91_spi_write(ATMEL_PDC_TNCR, list->txlen[i] / tx_size);
		at91_spi_write(ATMEL_PDC_RNCR, list->rxlen[i] / tx_size);
	}
	return IRQ_HANDLED;
}
コード例 #3
0
/*
 * Perform a data transfer over the SPI bus
 */
int spi_transfer(struct spi_transfer_list* list)
{
	struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
	int tx_size;

	if (!list)
		panic("at91_spi: spi_transfer called with NULL transfer list");
	if (current_device == -1)
		panic("at91_spi: spi_transfer called without acquiring bus");

#ifdef DEBUG_SPI
	printk("SPI transfer start [%i]\n", list->nr_transfers);
#endif

	/* If we are in 16-bit mode, we need to modify what we pass to the PDC */
	tx_size = (at91_spi_read(AT91_SPI_CSR(current_device)) & AT91_SPI_BITS_16) ? 2 : 1;

	/* Store transfer list */
	device->xfers = list;
	list->curr = 0;

	/* Assume there must be at least one transfer */
	device->tx = dma_map_single(NULL, list->tx[0], list->txlen[0], DMA_TO_DEVICE);
	device->rx = dma_map_single(NULL, list->rx[0], list->rxlen[0], DMA_FROM_DEVICE);

	/* Program PDC registers */
	at91_spi_write(ATMEL_PDC_TPR, device->tx);
	at91_spi_write(ATMEL_PDC_RPR, device->rx);
	at91_spi_write(ATMEL_PDC_TCR, list->txlen[0] / tx_size);
	at91_spi_write(ATMEL_PDC_RCR, list->rxlen[0] / tx_size);

	/* Is there a second transfer? */
	if (list->nr_transfers > 1) {
		device->txnext = dma_map_single(NULL, list->tx[1], list->txlen[1], DMA_TO_DEVICE);
		device->rxnext = dma_map_single(NULL, list->rx[1], list->rxlen[1], DMA_FROM_DEVICE);

		/* Program Next PDC registers */
		at91_spi_write(ATMEL_PDC_TNPR, device->txnext);
		at91_spi_write(ATMEL_PDC_RNPR, device->rxnext);
		at91_spi_write(ATMEL_PDC_TNCR, list->txlen[1] / tx_size);
		at91_spi_write(ATMEL_PDC_RNCR, list->rxlen[1] / tx_size);
	}
	else {
		device->txnext = 0;
		device->rxnext = 0;
		at91_spi_write(ATMEL_PDC_TNCR, 0);
		at91_spi_write(ATMEL_PDC_RNCR, 0);
	}

	// TODO: If we are doing consecutive transfers (at high speed, or
	//   small buffers), then it might be worth modifying the 'Delay between
	//   Consecutive Transfers' in the CSR registers.
	//   This is an issue if we cannot chain the next buffer fast enough
	//   in the interrupt handler.

	/* Enable transmitter and receiver */
	at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN | ATMEL_PDC_TXTEN);

	at91_spi_write(AT91_SPI_IER, AT91_SPI_ENDRX);		/* enable buffer complete interrupt */
	wait_for_completion(&transfer_complete);

#ifdef DEBUG_SPI
	printk("SPI transfer end\n");
#endif

	return 0;
}
コード例 #4
0
/*
 * Initialize the SPI controller
 */
static int __init at91spi_probe(struct platform_device *pdev)
{
	int i;
	unsigned long scbr;
	struct resource *res;

	init_MUTEX(&spi_lock);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENXIO;

	if (!request_mem_region(res->start, res->end - res->start + 1, "at91_spi"))
		return -EBUSY;

	spi_base = ioremap(res->start, res->end - res->start + 1);
	if (!spi_base) {
		release_mem_region(res->start, res->end - res->start + 1);
		return -ENOMEM;
	}

	spi_clk = clk_get(NULL, "spi_clk");
	if (IS_ERR(spi_clk)) {
		printk(KERN_ERR "at91_spi: no clock defined\n");
		iounmap(spi_base);
		release_mem_region(res->start, res->end - res->start + 1);
		return -ENODEV;
	}

	at91_spi_write(AT91_SPI_CR, AT91_SPI_SWRST);	/* software reset of SPI controller */

	/*
	 * Calculate the correct SPI baud-rate divisor.
	 */
	scbr = clk_get_rate(spi_clk) / (2 * DEFAULT_SPI_CLK);
	scbr = scbr + 1;		/* round up */

	printk(KERN_INFO "at91_spi: Baud rate set to %ld\n", clk_get_rate(spi_clk) / (2 * scbr));

	/* Set Chip Select registers to good defaults */
	for (i = 0; i < 4; i++) {
		at91_spi_write(AT91_SPI_CSR(i), AT91_SPI_CPOL | AT91_SPI_BITS_8 | (16 << 16) | (scbr << 8));
	}

	at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);

	memset(&spi_dev, 0, sizeof(spi_dev));
	spi_dev[0].pcs = 0xE;
	spi_dev[1].pcs = 0xD;
	spi_dev[2].pcs = 0xB;
	spi_dev[3].pcs = 0x7;

	if (request_irq(AT91RM9200_ID_SPI, at91spi_interrupt, 0, "spi", NULL)) {
		clk_put(spi_clk);
		iounmap(spi_base);
		release_mem_region(res->start, res->end - res->start + 1);
		return -EBUSY;
	}

	at91_spi_write(AT91_SPI_CR, AT91_SPI_SPIEN);		/* Enable SPI */

	return 0;
}