?? fpga_spi.c
字號:
memcpy((void *)buf, (void *)(ptr+ i*xferlen) ,xferlen ); do_omap_spi_xfer(hSpi, buf, xferlen); } _left =FPGA_FILE_SIZE %xferlen; if(_left) { memcpy((void *)buf, (void *)(ptr+ i*xferlen) ,_left); do_omap_spi_xfer(hSpi, buf, _left); } kfree(buf); SPI_TRACE_LEAVE();} //////////////////////////////////////////////////////////////////////////////////////////////////////// xfer data by dma.:static void omap_spi_tx_dma_callback(int lch, u16 ch_status, void *data){ SPI_TRACE_ENTER(); { omap_free_dma(dma_tx_lch); // note the tx xfer is completed complete(&tx_dma_completion); } SPI_TRACE_LEAVE();}static inline int IsWithinRange(unsigned int min, unsigned int max, unsigned int x) //[min <= x <= max]{ if( (x >= min) && (x <= max) ) return 1; return 0;}static int _omap_spi_xfer_buffer_dma(CSL_SpiHandle hSpi, dma_addr_t buffer, unsigned int len /*bytes*/){ DBG("_omap_spi_xfer_buffer_dma: from 0x%x, len %d\n", buffer, len); SPI_TRACE_ENTER(); { CSL_Status status; unsigned char spi_cmd8; int srcmode = -1; unsigned int xferbits = 8 * sizeof(unsigned int); // check src buffer mode. if( IsWithinRange(EMIFF_DRAM_START, EMIFF_DRAM_END, buffer) ) { // buffer on RAM srcmode = OMAP_DMA_PORT_EMIFF; SPI_ASSERT( (buffer + len) <= EMIFF_DRAM_END); } else if( IsWithinRange(EMIFS_FLASH_START, EMIFS_FLASH_END, buffer) ) { // buffer on Flash srcmode = OMAP_DMA_PORT_EMIFS; SPI_ASSERT( (buffer + len) <= EMIFS_FLASH_END); } else { // not support. printk("OMAP-SPI: buffer address 0x%x Invalid.\n", buffer); return -1; } // request DMA channel for SPI TX DMA if (omap_request_dma(OMAP_DMA_SPI_TX, "SPI DMA_TX", omap_spi_tx_dma_callback, NULL, &dma_tx_lch)) { printk("OMAP-SPI: Unable to request DMA channel for SPI TX.\n"); return -EAGAIN; } // set DMA params. omap_set_dma_transfer_params(dma_tx_lch, OMAP_DMA_DATA_TYPE_S32, len >> 2, 1, OMAP_DMA_SYNC_ELEMENT); omap_set_dma_dest_params(dma_tx_lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, (unsigned long)&(hSpi->regs->SPI_TX)); omap_set_dma_src_params(dma_tx_lch, srcmode, OMAP_DMA_AMODE_POST_INC, buffer); omap_set_dma_priority(OMAP_DMA_PORT_EMIFS, 0); // 0 to 15 DBG("TX DMA on channel %d: [%s -> TIPB]\n", dma_tx_lch, (srcmode == OMAP_DMA_PORT_EMIFF) ? "EMIFF" : "EMIFS"); // init dma tx completion. init_completion(&(tx_dma_completion)); // set SPI NBits spi_cmd8 = xferbits; status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_NB_SET, &spi_cmd8);//SPI_CTRL:NB is set 31 SPI_ASSERT(status == CSL_SOK); // set SPI DMA mode status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_CPT_DMA_ENABLE, NULL );//SPI_SET1: DMA_EN is set 1 SPI_ASSERT(status == CSL_SOK); // start system DMA omap_start_dma(dma_tx_lch); // Write process active, start spi xfer. spi_cmd8 = CSL_SPI_INT_TX_MASK; status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_XFER_ENABLE, &spi_cmd8 );//SPI_CTRL:WR is set SPI_ASSERT(status == CSL_SOK); // wait DMA xfer over. wait_for_completion(&(tx_dma_completion)); omap_spi_dump_registers(hSpi); } SPI_TRACE_LEAVE(); return len; }static void do_omap_spi_xfer_dma(CSL_SpiHandle hSpi, dma_addr_t buffer, int _dmasize/*bytes*/ ,unsigned int len /* bytes */){ SPI_TRACE_ENTER(); { int i, loopnum,_left; if((_dmasize<4)||(_dmasize>65535*4)) // dma transfer max = 65535 * 4 bytes.spru 742.pdf page 726 printk("OMAP-SPI: the dma transfer size is out of boundnary.\n"); loopnum = len / _dmasize; _left = len % _dmasize; RecordTime(); for(i = 0; i < loopnum; i++) { _omap_spi_xfer_buffer_dma(hSpi, buffer + i * _dmasize, _dmasize); } if(_left) { _omap_spi_xfer_buffer_dma(hSpi, buffer + i * _dmasize, _left); } RecordTime(); } SPI_TRACE_LEAVE();}///////////////////////////////////////////////////////////////////////////////////////////////set the fpga gpio direction to control the downloading int config_gpio_fpga_direction(void){ omap_set_gpio_direction(GPIO11, GPIO_IN); omap_set_gpio_direction(GPIO12, GPIO_IN); omap_set_gpio_direction(GPIO15, GPIO_OUT); return 0;}//////////////////////////////////////////////////////////////////////////////////////////////if status is high ,ready to receive data,low ,not ready or errorint read_fpga_nstatus(void)//{ int nstatus; nstatus = omap_get_gpio_datain(FPGA_nSTATUS); return nstatus;}//////////////////////////////////////////////////////////////////////////////////////////////if config_doneis high , receive data is completed and successful,low ,not over or errorint read_fpga_config_done(void){ int retval ; retval = omap_get_gpio_datain(FPGA_CONF_DONE); return retval; }/////////////////////////////////////////////////////////////////////////////////////////////start to notice fpga receive dataint set_fpga_nconfig(int data){ omap_set_gpio_dataout(FPGA_nCONFIG, data); return 0;}//////////////////////////////////////////////////////////////////////////////////////////////// assure the only one hold the spi resources!!!static int _omap_spi_download_fpga(void *unused){ CSL_Status status; CSL_SpiHwSetup setupori, hwSetup; unsigned char spi_ad; int dmasize = 1024*255; int download_time = 0; SPI_TRACE_ENTER(); { OMAP_SPI_ENTER_CRITICALSECTION();//make sure the fpga hold the spi recources daemonize("fpga-spi"); config_gpio_fpga_direction(); // spi chip support library open hSpi = CSL_spiOpen(&spiObj,CSL_SPI,NULL,&status); SPI_ASSERT(status == CSL_SOK); // reset spi. status = CSL_spiHwControl(hSpi, CSL_SPI_CMD_PRI_RESET, NULL); SPI_ASSERT(status == CSL_SOK); // get spi hardware setup status = CSL_spiGetHwSetup (hSpi, &setupori); SPI_ASSERT(status == CSL_SOK); // config spi registers memset(&hwSetup, 0, sizeof(CSL_SpiHwSetup)); hwSetup.opMode = CSL_SPI_OPMOD_MASTER;//SPI_SET2:Mater mode hwSetup.autoIdle = CSL_SPI_AUTOIDLE_CLK_GATED; //SPI_SCR:automatic OCP clock hwSetup.wakeupEnable = CSL_SPI_WAKEUP_DISABLE; //SPI_SCR:wake-up disable hwSetup.idleMode = CSL_SPI_NO_IDLE; //CSL_SPI_SMRT_IDLE; hwSetup.prescale = CSL_SPI_PRESCALE_1;//12M hwSetup.spiFmt[CSL_SPI].clkPhase = CSL_SPI_PHASE_OUT;//SPI_SET2:CP is set1, the middle of the data transfer hwSetup.spiFmt[CSL_SPI].enaLvl = CSL_SPI_ENA_LVL_LOW;//SPI_SET2:CE is set 0,the active level is low hwSetup.spiFmt[CSL_SPI].polarity = CSL_SPI_POLARITY_LOW;//SPI_SET2:CI is set 0,the inactive edge state is low status = CSL_spiHwSetup(hSpi, &hwSetup); SPI_ASSERT(status == CSL_SOK); // Enable EN_CLK status = CSL_spiHwControl (hSpi, CSL_SPI_CMD_ENABLE, NULL );//SPI_SET1:EN_CLK is set1 SPI_ASSERT(status == CSL_SOK); udelay(100); // Select Device 0 spi_ad = 0x0; status = CSL_spiHwControl(hSpi, CSL_SPI_CMD_CSEL_SET, &spi_ad);//SPI_CTRL:AD ,enable device 0 SPI_ASSERT(status == CSL_SOK); //notice the fpga to ready set_fpga_nconfig(enable); udelay(100); if (!read_fpga_nstatus())//if ready is not ok { printk( "ERROR FPGA-SPI: the FPGA is not ready to receive data.\n"); return (-1); } do_omap_spi_xfer_dma(hSpi, FPGA_FILE_BASE,dmasize, FPGA_FILE_SIZE); if(!read_fpga_config_done()) { printk( " ERROR PGA-SPI: the FPGA download failed.\n"); return (-1); } else printk("---------------FPGA-SPI: FPGA download finished---------- .\n"); status = CSL_spiClose(&spiObj); SPI_ASSERT(status == CSL_SOK); OMAP_SPI_LEAVE_CRITICALSECTION();// FPGA release the spi resources } SPI_TRACE_LEAVE(); return 0;}//just an entry.static int __init omap_spi_start_download_fpga(void){ pid_t pid; if (machine_is_omap_osk()) { omap_cfg_reg(K13_1610_GPIO11); omap_cfg_reg(L16_1610_GPIO12); omap_cfg_reg(K16_1610_GPIO15); } pid = kernel_thread(_omap_spi_download_fpga, NULL, 0); DBG("OMAP SPI: start download fpga thread[pid %d]\n", pid); return 0;}late_initcall(omap_spi_start_download_fpga);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -