?? fpga_spi.c
字號:
/* * linux/arch/arm/omap/omap1/fpga_spi.c * * Copyright (C) 2006 GE Corporation * Author: Yang Yong <yongyoung.yang@ge.com> * * Download FPGA data to Ateral stratix2 FPGA via SPI * *//* * linux/arch/arm/omap/omap1/fpga_spi.c * * Copyright (C) 2006 GE Corporation * Author: Yang Yong <yongyoung.yang@ge.com> * * Download FPGA data to Ateral stratix2 FPGA via SPI * */#include <linux/module.h>#include <linux/init.h>#include <linux/device.h>#include <linux/wait.h>#include <linux/completion.h>#include <linux/interrupt.h>#include <linux/err.h>#include <linux/time.h>#include <linux/types.h> #include <linux/slab.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/delay.h>#include <asm/irq.h>#include <asm/arch/dma.h>#include <asm/arch/mux.h>#include <asm/arch/irqs.h>#include <asm/arch/dsp_common.h>#include <asm/arch/mcbsp.h>#include <asm/arch/gpio.h>#include <asm/hardware/clock.h>#include <asm/mach-types.h>/// merged from TI omap5912osk CSL(Chip support library).#include <asm/arch/spi/csl_spi.h>#include <asm/arch/spi/soc.h>#include "fpga_spi.h"/// omap memeory map//Flash physical Memmap [0x00000000, 0x02000000]#define EMIFS_FLASH_START 0x00000000#define EMIFS_FLASH_END 0x02000000#define EMIFS_FLASH_SIZE (EMIFS_FLASH_END - EMIFS_FLASH_START)//SDRAM physical Memmap [0x10000000, 0x12000000]#define EMIFF_DRAM_START 0x10000000#define EMIFF_DRAM_END 0x12000000#define EMIFF_DRAM_SIZE (EMIFF_DRAM_END - EMIFF_DRAM_START)// fpga file info#define FPGA_FILE_BASE 0x01000000#define FPGA_FILE_SIZE (1205084)#define GPIO11 (11)#define GPIO12 (12)#define GPIO15 (15) #define FPGA_CONF_DONE GPIO12#define FPGA_nSTATUS GPIO11#define FPGA_nCONFIG GPIO15#define GPIO_OUT (0)#define GPIO_IN (1)#define enable (1)#define disable (0)///////////////////////////////////////////////////////////////////////////////////////////////#undef CONFIG_SPI_DEBUG//#define CONFIG_SPI_DEBUG#ifdef CONFIG_SPI_DEBUG#define DBG(x...) printk(KERN_INFO "OMAP-SPI:" x)#else#define DBG(x...) do { } while (0)#endif#define SPI_HALT() { do {} while(1); }#define SPI_TRACE_CURRENTPOS() DBG("->Go to %s, %s line %d\n", __func__, __FILE__, __LINE__)#define SPI_TRACE_ENTER() DBG("--->Entering %s, %s line %d\n", __func__, __FILE__, __LINE__)#define SPI_TRACE_LEAVE() DBG("<---Leaving %s, %s line %d\n", __func__, __FILE__, __LINE__)#define SPI_ASSERT(x) \ {\ if(!(x)) \ DBG("Assert <%s> Failed! [%s, %s line %d]\n", #x, __func__, __FILE__, __LINE__);\ }/////////////////////////////////////////////////////////////////////////////////////////////static inline int RecordTime(void){#if defined(CONFIG_SPI_DEBUG) #define MAX_SPI_DMA_TV 256 static struct timeval spi_dma_tv[ MAX_SPI_DMA_TV ]; static int index = 0; int msvalue; if(index >= MAX_SPI_DMA_TV) { index = 1; spi_dma_tv[0] = spi_dma_tv[MAX_SPI_DMA_TV]; } do_gettimeofday(&(spi_dma_tv[index])); DBG("[%d]SPI Time Stub:[%6ds:%7dus]\n", index, (int)spi_dma_tv[index].tv_sec, (int)spi_dma_tv[index].tv_usec); if(index > 0) { msvalue = (spi_dma_tv[index].tv_sec - spi_dma_tv[index - 1].tv_sec) * 1000 + (spi_dma_tv[index].tv_usec - spi_dma_tv[index - 1].tv_usec) / 1000; printk(KERN_INFO "OMAP-SPI:" "%d: %d ms\n", index + 1, msvalue); } return index++;#else return 0;#endif}/////////////////////////////////////////////////////////////////////////////////// static CSL_SpiObj spiObj;static CSL_SpiHandle hSpi = NULL;static int dma_tx_lch;static struct completion tx_irq_completion;static struct completion tx_dma_completion;DECLARE_MUTEX(omap_spi_sem);#define OMAP_SPI_ENTER_CRITICALSECTION() \ do { down(&omap_spi_sem); } while(0);#define OMAP_SPI_LEAVE_CRITICALSECTION() \ do { up(&omap_spi_sem); } while(0);////////////////////////////////////////////////////////////////////////////////////check the spi registersstatic void omap_spi_dump_registers(CSL_SpiHandle hSpi){#if defined(CONFIG_SPI_DEBUG) unsigned int spi_regbase; SPI_ASSERT(hSpi != (CSL_SpiHandle)NULL); spi_regbase = (unsigned int)hSpi->regs; DBG("##################################\n"); DBG("#[0x%x]SPI_REV: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_REV), hSpi->regs->SPI_REV); DBG("#[0x%x]SPI_SCR: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_SCR), hSpi->regs->SPI_SCR); DBG("#[0x%x]SPI_SSR: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_SSR), hSpi->regs->SPI_SSR); DBG("#[0x%x]SPI_ISR: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_ISR), hSpi->regs->SPI_ISR); DBG("#[0x%x]SPI_IER: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_IER), hSpi->regs->SPI_IER); DBG("#[0x%x]SPI_SET1: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_SET1), hSpi->regs->SPI_SET1); DBG("#[0x%x]SPI_SET2: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_SET2), hSpi->regs->SPI_SET2); DBG("#[0x%x]SPI_CTRL: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_CTRL), hSpi->regs->SPI_CTRL); DBG("#[0x%x]SPI_DSR: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_DSR), hSpi->regs->SPI_DSR); DBG("#[0x%x]SPI_TX: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_TX), hSpi->regs->SPI_TX); DBG("#[0x%x]SPI_RX: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_RX), hSpi->regs->SPI_RX); DBG("#[0x%x]SPI_TEST: 0x%x\n", (unsigned int)&(hSpi->regs->SPI_TEST), hSpi->regs->SPI_TEST); DBG("##################################\n");#endif} ////////////////////////////////////////////////////////////////////////////////////////// xfer without dma via spi. when the transmission is completed ,an interrupt occuredstatic irqreturn_t omap_spi_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs){ SPI_TRACE_ENTER(); { CSL_Status status; unsigned short spi_isr; unsigned short spi_cmd; status = CSL_spiGetHwStatus(hSpi, CSL_SPI_QUERY_EVT_STATUS, &spi_isr); SPI_ASSERT(status == CSL_SOK); spi_cmd = CSL_SPI_INT_TX_MASK; status = CSL_spiHwControl(hSpi, CSL_SPI_CMD_EVT_CLEAR, &spi_cmd);//SPI_ISR: WE is set SPI_ASSERT(status == CSL_SOK); complete(&tx_irq_completion); } SPI_TRACE_LEAVE(); return IRQ_HANDLED;}///////////////////////////////////////////////////////////////////////////////////////////xfer without dma typedef unsigned int XFERTYPE;#define XFERSIZE sizeof(XFERTYPE)static int _omap_spi_xfer_buffer(CSL_SpiHandle hSpi, unsigned int *buffer, unsigned int len /*bytes*/){ SPI_ASSERT(buffer != NULL); SPI_ASSERT(len % XFERSIZE == 0); SPI_TRACE_ENTER(); { CSL_Status status; unsigned short spi_cmd; unsigned char spi_cmd8; // Enable TX interrupt spi_cmd = CSL_SPI_INT_TX_MASK; status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_INT_ENABLE, &spi_cmd );//SPI_IER:MSK1 is set SPI_ASSERT(status == CSL_SOK); {//xfer body int i; XFERTYPE *pbuf = buffer; for(i = 0; i < (len / XFERSIZE); i++) {//for each xfer CSL_SpiXevArg xevArg; // Write data to TX register XFERTYPE tmpdata = *pbuf; xevArg.data = &tmpdata; xevArg.nBytes = XFERSIZE; status = CSL_spiWrite(hSpi, &xevArg); SPI_ASSERT(status == CSL_SOK); // Write process active spi_cmd = CSL_SPI_INT_TX_MASK; status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_XFER_ENABLE, &spi_cmd );//SPI_CTRL:WR is set SPI_ASSERT(status == CSL_SOK); wait_for_completion(&tx_irq_completion); omap_spi_dump_registers( hSpi); pbuf++; }// for_each xfer }// xfer body }// SPI_TRACE_LEAVE(); return len; }static void do_omap_spi_xfer(CSL_SpiHandle hSpi, unsigned int *buffer, unsigned int len){ SPI_TRACE_ENTER(); {// spi xfer without dma. {// get SPI IRQ int err; err = request_irq(INT_1610_SPI, omap_spi_tx_irq_handler, 0, "SPI TX", NULL); if (err != 0) { printk(KERN_ERR "OMAP-SPI: Unable to request TX IRQ %d for SPI%d\n",INT_1610_SPI, 0); return; } DBG("OMAP-SPI: request TX IRQ %d for SPI\n", INT_1610_SPI); //init SPI IRQ completion init_completion(&tx_irq_completion); } _omap_spi_xfer_buffer(hSpi, buffer, len); //free SPI IRQ free_irq(INT_1610_SPI, NULL); } SPI_TRACE_LEAVE();}static void test_omap_spi_xfer(CSL_SpiHandle hSpi){ SPI_TRACE_ENTER(); #define BUFSIZE (256) unsigned int *buf; XFERTYPE i,_left, loopnum, xferlen; xferlen =BUFSIZE * sizeof(XFERTYPE); buf =(unsigned int * )kmalloc(xferlen,GFP_KERNEL); //remap flash address void * ptr = ioremap(FPGA_FILE_BASE, FPGA_FILE_SIZE); loopnum = FPGA_FILE_SIZE/xferlen; for( i=0; i<loopnum; i++) { //copy fpga file data from flash
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -