#include #ifndef SOCLIB_IOC static struct sdcard_dev _sdcard_device; static struct spi_dev *const _spi_device = ( struct spi_dev * )IOC_PADDR_BASE; #endif #define SDCARD_RESET_ITER_MAX 4 /////////////////////////////////// inline void reset_sleep(int cycles) { int i; for (i = 0; i < cycles; i++); } #if RESET_DEBUG //////////////////////////////////// inline unsigned int reset_proctime() { unsigned int ret; asm volatile ("mfc0 %0, $9":"=r" (ret)); return ret; } #endif #ifndef SOCLIB_IOC ///////////////////////////////////////////////////////////////////////////////// // reset_ioc_init // This function initializes the SDCARD / required for FPGA. ///////////////////////////////////////////////////////////////////////////////// int reset_ioc_init() { unsigned char sdcard_rsp; reset_puts("Initializing block device\n\r"); /** * Initializing the SPI controller */ spi_dev_config ( _spi_device , 200000 , /**< SPI_clk: 200 Khz */ SYSCLK_FREQ , /**< Sys_clk */ 8 , /**< Charlen: 8 */ SPI_TX_NEGEDGE, SPI_RX_POSEDGE ); /** * Initializing the SD Card */ unsigned int iter = 0; while(1) { reset_puts("Trying to initialize SD card... "); sdcard_rsp = sdcard_dev_open(&_sdcard_device, _spi_device, 0); if (sdcard_rsp == 0) { reset_puts("OK\n"); break; } reset_puts("KO\n"); reset_sleep(1000); if (++iter >= SDCARD_RESET_ITER_MAX) { reset_puts("\nERROR: During SD card reset to IDLE state\n" "/ card response = "); reset_putx(sdcard_rsp); reset_puts("\n"); reset_exit(); } } /** * Set the block length of the SD Card */ sdcard_rsp = sdcard_dev_set_blocklen(&_sdcard_device, 512); if (sdcard_rsp) { reset_puts("ERROR: During SD card blocklen initialization\n"); reset_exit(); } /** * Incrementing SDCARD clock frequency for normal function */ spi_dev_config ( _spi_device , 10000000 , /**< SPI_clk 10 Mhz */ SYSCLK_FREQ , /**< Sys_clk */ -1 , /**< Charlen: 8 */ -1 , -1 ); reset_puts("Finish block device initialization\n\r"); return 0; } // end reset_ioc_init() #endif #ifdef SOCLIB_IOC ///////////////////////////////////////////////////////////////////////////////////// // reset_ioc_completed() // This blocking function checks completion of an I/O transfer and reports errors. // It returns 0 if the transfer is successfully completed. // It returns -1 if an error has been reported. ///////////////////////////////////////////////////////////////////////////////////// int reset_ioc_completed() { unsigned int status = 0; unsigned int * ioc_address = ( unsigned int * )IOC_PADDR_BASE; while ( 1 ) { status = ioread32(&ioc_address[BLOCK_DEVICE_STATUS]); if (( status == BLOCK_DEVICE_READ_SUCCESS ) || ( status == BLOCK_DEVICE_READ_ERROR )) break; } return status; } // end reset_ioc_completed() #endif #ifdef SOCLIB_IOC ///////////////////////////////////////////////////////////////////////////////////// // reset_ioc_read() // Transfer data the block device to a memory buffer: SOCLIB version // - param lba : first block index on the disk // - param buffer : base address of the memory buffer // - param count : number of blocks to be transfered // This is a blocking function. The function returns once the transfer is completed. ///////////////////////////////////////////////////////////////////////////////////// int reset_ioc_read( unsigned int lba, void* buffer, unsigned int count ) { unsigned int * ioc_address = (unsigned int*)IOC_PADDR_BASE; #if RESET_DEBUG unsigned int start_time; unsigned int end_time; reset_puts("[RESET DEBUG] Reading blocks "); reset_putd(lba); reset_puts(" to "); reset_putd(lba + count - 1); start_time = reset_proctime(); #endif // block_device configuration iowrite32( &ioc_address[BLOCK_DEVICE_BUFFER], ( unsigned int ) buffer ); iowrite32( &ioc_address[BLOCK_DEVICE_COUNT], ( unsigned int ) count ); iowrite32( &ioc_address[BLOCK_DEVICE_LBA], ( unsigned int ) lba ); iowrite32( &ioc_address[BLOCK_DEVICE_IRQ_ENABLE], ( unsigned int ) 0 ); iowrite32( &ioc_address[BLOCK_DEVICE_OP], ( unsigned int ) BLOCK_DEVICE_READ ); reset_ioc_completed(); #if (CACHE_COHERENCE == 0) || (USE_IOB == 1) reset_buf_invalidate(buffer, CACHE_LINE_SIZE, count * 512); #endif #if USE_IOB reset_mcc_invalidate(buffer, count * 512); #endif #if RESET_DEBUG end_time = reset_proctime(); reset_puts(" / cycles for transfert: "); reset_putd(end_time - start_time); reset_puts("\n"); #endif return 0; } // end reset_ioc_read() #else ///////////////////////////////////////////////////////////////////////////////////// // reset_ioc_read() // Transfer data the block device to a memory buffer: FPGA version // - param lba : first block index on the disk // - param buffer : base address of the memory buffer // - param count : number of blocks to be transfered // This is a blocking function. The function returns once the transfer is completed. ///////////////////////////////////////////////////////////////////////////////////// int reset_ioc_read( unsigned int lba, void* buffer, unsigned int count ) { unsigned int sdcard_rsp; unsigned int i; sdcard_dev_lseek(&_sdcard_device, lba); #if RESET_DEBUG unsigned int start_time; unsigned int end_time; reset_puts("[RESET DEBUG] Reading blocks "); reset_putd(lba); reset_puts(" to "); reset_putd(lba + count - 1); start_time = reset_proctime(); #endif for(i = 0; i < count; i++) { if (( sdcard_rsp = sdcard_dev_read ( &_sdcard_device, (unsigned char *) buffer + (512 * i), 512 ) )) { reset_puts("ERROR during read on the SDCARD device. Code: "); reset_putx(sdcard_rsp); reset_puts("\n\r"); return 1; } } #if RESET_DEBUG end_time = reset_proctime(); reset_puts(" / cycles for transfert: "); reset_putd(end_time - start_time); reset_puts("\n"); #endif return 0; } // end reset_ioc_read() #endif ////////////////////////////////////////////////////////////////////////////// // reset_dcache_buf_invalidate() // Invalidate all data cache lines corresponding to a memory buffer // (identified by an address and a size) in L1 cache. ///////////////////////////////////////////////////////////////////////////// #if (CACHE_COHERENCE == 0) || (USE_IOB == 1) void reset_buf_invalidate ( const void * buffer, unsigned int line_size, unsigned int size) { unsigned int i; // iterate on cache lines for (i = 0; i <= size; i += line_size) { asm volatile( " cache %0, %1" :// no outputs :"i" (0x11), "R" (*((unsigned char *) buffer + i)) ); } } #endif ////////////////////////////////////////////////////////////////////////////// // reset_mcc_inval() // Invalidate all data cache lines corresponding to a memory buffer // (identified by an address and a size) in L2 cache. ///////////////////////////////////////////////////////////////////////////// #if USE_IOB void reset_mcc_invalidate ( const void * buffer, unsigned int size) { unsigned int * mcc_address = (unsigned int *)MCC_PADDR_BASE; // get the hard lock assuring exclusive access to MEMC while (ioread32(&mcc_address[MCC_LOCK])); // write invalidate paremeters on the memory cache // this preloader use only the cluster 0 and then the HI bits are not used iowrite32(&mcc_address[MCC_ADDR_LO], (unsigned int) buffer); iowrite32(&mcc_address[MCC_ADDR_HI], (unsigned int) 0); iowrite32(&mcc_address[MCC_LENGTH] , (unsigned int) size); iowrite32(&mcc_address[MCC_CMD] , (unsigned int) MCC_CMD_INVAL); // release the lock protecting MEMC iowrite32(&mcc_address[MCC_LOCK], (unsigned int) 0); } #endif /* * vim: tabstop=4 : shiftwidth=4 : expandtab */