#include #ifndef SOCLIB_IOC static struct sdcard_dev _sdcard_device; static struct spi_dev *const _spi_device = ( struct spi_dev * )IOC_BASE; #endif // end ifndef SOCLIB_IOC #define SDCARD_RESET_ITER_MAX 4 inline void boot_sleep(int cycles) { int i; for (i = 0; i < cycles; i++); } #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) inline unsigned int boot_proctime() { unsigned int ret; asm volatile ("mfc0 %0, $9":"=r" (ret)); return ret; } #endif #ifndef SOCLIB_IOC int boot_ioc_init() { unsigned char sdcard_rsp; boot_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) { boot_puts("Trying to initialize SD card... "); sdcard_rsp = sdcard_dev_open(&_sdcard_device, _spi_device, 0); if (sdcard_rsp == 0) { boot_puts("OK\n"); break; } boot_puts("KO\n"); boot_sleep(1000); if (++iter >= SDCARD_RESET_ITER_MAX) { boot_puts("\nERROR: During SD card reset to IDLE state\n" "/ card response = "); boot_putx(sdcard_rsp); boot_puts("\n"); boot_exit(); } } /** * Set the block length of the SD Card */ sdcard_rsp = sdcard_dev_set_blocklen(&_sdcard_device, 512); if (sdcard_rsp) { boot_puts("ERROR: During SD card blocklen initialization\n"); boot_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 ); boot_puts("Finish block device initialization\n\r"); return 0; } #endif // end ifndef SOCLIB_IOC /** * _boot_ioc_completed() * * This blocking function checks completion of an I/O transfer and reports errors. * * \note It returns 0 if the transfer is successfully completed. * It returns -1 if an error has been reported. */ #ifdef SOCLIB_IOC static int _boot_ioc_completed() { unsigned int status = 0; unsigned int * ioc_address = ( unsigned int * )IOC_BASE; while ( 1 ) { status = ioread32(&ioc_address[BLOCK_DEVICE_STATUS]); if (( status == BLOCK_DEVICE_READ_SUCCESS ) || ( status == BLOCK_DEVICE_READ_ERROR )) break; } return status; } #endif /** * boot_ioc_read() * * Transfer data from a file on the block device to a memory buffer. * * \param lba : first block index on the disk * \param buffer : base address of the memory buffer * \param count : number of blocks to be transfered * * \note This is a blocking function. The function returns once the transfer * has finished */ #ifdef SOCLIB_IOC /////////////////////////////////////////////////////////////////////////////// // SOCLIB version of the boot_ioc_read function int boot_ioc_read(unsigned int lba, void* buffer, unsigned int count) { unsigned int * ioc_address = (unsigned int*)IOC_BASE; #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) unsigned int start_time; unsigned int end_time; boot_puts("[ DEBUG ] Reading blocks "); boot_putd(lba); boot_puts(" to "); boot_putd(lba + count - 1); start_time = boot_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 ); _boot_ioc_completed(); #if (CACHE_COHERENCE == 0) boot_dbuf_invalidate(buffer, CACHE_LINE_SIZE, count * 512); #endif #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) end_time = boot_proctime(); boot_puts(" / cycles for transfert: "); boot_putd(end_time - start_time); boot_puts("\n"); #endif return 0; } #else /////////////////////////////////////////////////////////////////////////////// // FPGA version of the boot_ioc_read function int boot_ioc_read(unsigned int lba, void* buffer, unsigned int count) { unsigned int sdcard_rsp; unsigned int i; sdcard_dev_lseek(&_sdcard_device, lba); #if (BOOT_DEBUG ==1 && BOOT_DEBUG_IOC == 1) unsigned int start_time; unsigned int end_time; boot_puts("[ DEBUG ] Reading blocks "); boot_putd(lba); boot_puts(" to "); boot_putd(lba + count - 1); start_time = boot_proctime(); #endif for(i = 0; i < count; i++) { if (( sdcard_rsp = sdcard_dev_read ( &_sdcard_device, (unsigned char *) buffer + (512 * i), 512 ) )) { boot_puts("ERROR during read on the SDCARD device. Code: "); boot_putx(sdcard_rsp); boot_puts("\n\r"); return 1; } } #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) end_time = boot_proctime(); boot_puts(" / cycles for transfert: "); boot_putd(end_time - start_time); boot_puts("\n"); #endif return 0; } #endif /** * _dcache_buf_invalidate() * * Invalidate all data cache lines corresponding to a memory * buffer (identified by an address and a size). */ #if (CACHE_COHERENCE == 0) void boot_dbuf_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 /* * vim: tabstop=4 : shiftwidth=4 : expandtab */