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); }
/* * 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; }
/* * 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; }
/* * 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; }