| 1 | #include <boot_ioc.h> | 
|---|
| 2 |  | 
|---|
| 3 | #ifndef SOCLIB_IOC | 
|---|
| 4 |  | 
|---|
| 5 | static struct sdcard_dev  _sdcard_device; | 
|---|
| 6 | static struct spi_dev   *const  _spi_device   = ( struct spi_dev * )IOC_BASE; | 
|---|
| 7 |  | 
|---|
| 8 | #endif // end ifndef SOCLIB_IOC | 
|---|
| 9 |  | 
|---|
| 10 | #define SDCARD_RESET_ITER_MAX 4 | 
|---|
| 11 |  | 
|---|
| 12 | inline void boot_sleep(int cycles) | 
|---|
| 13 | { | 
|---|
| 14 | int i; | 
|---|
| 15 | for (i = 0; i < cycles; i++); | 
|---|
| 16 | } | 
|---|
| 17 |  | 
|---|
| 18 | #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) | 
|---|
| 19 | inline unsigned int boot_proctime() | 
|---|
| 20 | { | 
|---|
| 21 | unsigned int ret; | 
|---|
| 22 | asm volatile ("mfc0 %0, $9":"=r" (ret)); | 
|---|
| 23 | return ret; | 
|---|
| 24 | } | 
|---|
| 25 | #endif | 
|---|
| 26 |  | 
|---|
| 27 | #ifndef SOCLIB_IOC | 
|---|
| 28 | int boot_ioc_init() | 
|---|
| 29 | { | 
|---|
| 30 | unsigned char sdcard_rsp; | 
|---|
| 31 |  | 
|---|
| 32 | boot_puts("Initializing block device\n\r"); | 
|---|
| 33 |  | 
|---|
| 34 | /** | 
|---|
| 35 | * Initializing the SPI controller | 
|---|
| 36 | */ | 
|---|
| 37 | spi_dev_config ( | 
|---|
| 38 | _spi_device   , | 
|---|
| 39 | 200000        , /**< SPI_clk: 200 Khz */ | 
|---|
| 40 | SYSCLK_FREQ   , /**< Sys_clk          */ | 
|---|
| 41 | 8             , /**< Charlen: 8       */ | 
|---|
| 42 | SPI_TX_NEGEDGE, | 
|---|
| 43 | SPI_RX_POSEDGE | 
|---|
| 44 | ); | 
|---|
| 45 |  | 
|---|
| 46 | /** | 
|---|
| 47 | * Initializing the SD Card | 
|---|
| 48 | */ | 
|---|
| 49 | unsigned int iter = 0; | 
|---|
| 50 | while(1) | 
|---|
| 51 | { | 
|---|
| 52 | boot_puts("Trying to initialize SD card... "); | 
|---|
| 53 |  | 
|---|
| 54 | sdcard_rsp = sdcard_dev_open(&_sdcard_device, _spi_device, 0); | 
|---|
| 55 | if (sdcard_rsp == 0) | 
|---|
| 56 | { | 
|---|
| 57 | boot_puts("OK\n"); | 
|---|
| 58 | break; | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | boot_puts("KO\n"); | 
|---|
| 62 | boot_sleep(1000); | 
|---|
| 63 | if (++iter >= SDCARD_RESET_ITER_MAX) | 
|---|
| 64 | { | 
|---|
| 65 | boot_puts("\nERROR: During SD card reset to IDLE state\n" | 
|---|
| 66 | "/ card response = "); | 
|---|
| 67 | boot_putx(sdcard_rsp); | 
|---|
| 68 | boot_puts("\n"); | 
|---|
| 69 | boot_exit(); | 
|---|
| 70 | } | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 | /** | 
|---|
| 74 | * Set the block length of the SD Card | 
|---|
| 75 | */ | 
|---|
| 76 | sdcard_rsp = sdcard_dev_set_blocklen(&_sdcard_device, 512); | 
|---|
| 77 | if (sdcard_rsp) | 
|---|
| 78 | { | 
|---|
| 79 | boot_puts("ERROR: During SD card blocklen initialization\n"); | 
|---|
| 80 | boot_exit(); | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | /** | 
|---|
| 84 | * Incrementing SDCARD clock frequency for normal function | 
|---|
| 85 | */ | 
|---|
| 86 | spi_dev_config ( | 
|---|
| 87 | _spi_device , | 
|---|
| 88 | 10000000    , /**< SPI_clk 10 Mhz */ | 
|---|
| 89 | SYSCLK_FREQ , /**< Sys_clk        */ | 
|---|
| 90 | -1          , /**< Charlen: 8     */ | 
|---|
| 91 | -1          , | 
|---|
| 92 | -1 | 
|---|
| 93 | ); | 
|---|
| 94 |  | 
|---|
| 95 | boot_puts("Finish block device initialization\n\r"); | 
|---|
| 96 |  | 
|---|
| 97 | return 0; | 
|---|
| 98 | } | 
|---|
| 99 | #endif // end ifndef SOCLIB_IOC | 
|---|
| 100 |  | 
|---|
| 101 | /** | 
|---|
| 102 | * _boot_ioc_completed() | 
|---|
| 103 | * | 
|---|
| 104 | * This blocking function checks completion of an I/O transfer and reports errors. | 
|---|
| 105 | * | 
|---|
| 106 | * \note It returns 0 if the transfer is successfully completed. | 
|---|
| 107 | *       It returns -1 if an error has been reported. | 
|---|
| 108 | */ | 
|---|
| 109 | #ifdef SOCLIB_IOC | 
|---|
| 110 | static int _boot_ioc_completed() | 
|---|
| 111 | { | 
|---|
| 112 | unsigned int status = 0; | 
|---|
| 113 |  | 
|---|
| 114 |  | 
|---|
| 115 | unsigned int * ioc_address = ( unsigned int * )IOC_BASE; | 
|---|
| 116 |  | 
|---|
| 117 | while ( 1 ) | 
|---|
| 118 | { | 
|---|
| 119 | status = ioread32(&ioc_address[BLOCK_DEVICE_STATUS]); | 
|---|
| 120 |  | 
|---|
| 121 | if (( status == BLOCK_DEVICE_READ_SUCCESS ) || | 
|---|
| 122 | ( status == BLOCK_DEVICE_READ_ERROR  )) | 
|---|
| 123 | break; | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | return status; | 
|---|
| 127 | } | 
|---|
| 128 | #endif | 
|---|
| 129 |  | 
|---|
| 130 | /** | 
|---|
| 131 | * boot_ioc_read() | 
|---|
| 132 | * | 
|---|
| 133 | * Transfer data from a file on the block device to a memory buffer. | 
|---|
| 134 | * | 
|---|
| 135 | * \param lba    : first block index on the disk | 
|---|
| 136 | * \param buffer : base address of the memory buffer | 
|---|
| 137 | * \param count  : number of blocks to be transfered | 
|---|
| 138 | * | 
|---|
| 139 | * \note This is a blocking function. The function returns once the transfer | 
|---|
| 140 | *       has finished | 
|---|
| 141 | */ | 
|---|
| 142 |  | 
|---|
| 143 | #ifdef SOCLIB_IOC | 
|---|
| 144 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 145 | // SOCLIB version of the boot_ioc_read function | 
|---|
| 146 |  | 
|---|
| 147 | void boot_buf_invalidate ( | 
|---|
| 148 | const void * buffer, | 
|---|
| 149 | unsigned int line_size, | 
|---|
| 150 | unsigned int size); | 
|---|
| 151 |  | 
|---|
| 152 | void boot_mcc_invalidate ( | 
|---|
| 153 | const void * buffer, | 
|---|
| 154 | unsigned int size); | 
|---|
| 155 |  | 
|---|
| 156 | int boot_ioc_read(unsigned int lba, void* buffer, unsigned int count) | 
|---|
| 157 | { | 
|---|
| 158 |  | 
|---|
| 159 | unsigned int * ioc_address  = (unsigned int*)IOC_BASE; | 
|---|
| 160 |  | 
|---|
| 161 | #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) | 
|---|
| 162 | unsigned int start_time; | 
|---|
| 163 | unsigned int end_time; | 
|---|
| 164 | boot_puts("[ DEBUG ] Reading blocks "); | 
|---|
| 165 | boot_putd(lba); | 
|---|
| 166 | boot_puts(" to "); | 
|---|
| 167 | boot_putd(lba + count - 1); | 
|---|
| 168 |  | 
|---|
| 169 | start_time = boot_proctime(); | 
|---|
| 170 | #endif | 
|---|
| 171 |  | 
|---|
| 172 | // block_device configuration | 
|---|
| 173 | iowrite32( &ioc_address[BLOCK_DEVICE_BUFFER], | 
|---|
| 174 | ( unsigned int ) buffer ); | 
|---|
| 175 |  | 
|---|
| 176 | iowrite32( &ioc_address[BLOCK_DEVICE_COUNT], | 
|---|
| 177 | ( unsigned int ) count ); | 
|---|
| 178 |  | 
|---|
| 179 | iowrite32( &ioc_address[BLOCK_DEVICE_LBA], | 
|---|
| 180 | ( unsigned int ) lba ); | 
|---|
| 181 |  | 
|---|
| 182 | iowrite32( &ioc_address[BLOCK_DEVICE_IRQ_ENABLE], | 
|---|
| 183 | ( unsigned int ) 0 ); | 
|---|
| 184 |  | 
|---|
| 185 | iowrite32( &ioc_address[BLOCK_DEVICE_OP], | 
|---|
| 186 | ( unsigned int ) BLOCK_DEVICE_READ ); | 
|---|
| 187 |  | 
|---|
| 188 | _boot_ioc_completed(); | 
|---|
| 189 |  | 
|---|
| 190 | #if (CACHE_COHERENCE == 0) || (USE_IOB == 1) | 
|---|
| 191 | boot_buf_invalidate(buffer, CACHE_LINE_SIZE, count * 512); | 
|---|
| 192 | #endif | 
|---|
| 193 |  | 
|---|
| 194 | #if (USE_IOB == 1) | 
|---|
| 195 | boot_mcc_invalidate(buffer, count * 512); | 
|---|
| 196 | #endif | 
|---|
| 197 |  | 
|---|
| 198 | #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) | 
|---|
| 199 | end_time = boot_proctime(); | 
|---|
| 200 |  | 
|---|
| 201 | boot_puts(" / cycles for transfert: "); | 
|---|
| 202 | boot_putd(end_time - start_time); | 
|---|
| 203 | boot_puts("\n"); | 
|---|
| 204 | #endif | 
|---|
| 205 |  | 
|---|
| 206 | return 0; | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | #else | 
|---|
| 210 |  | 
|---|
| 211 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 212 | // FPGA version of the boot_ioc_read function | 
|---|
| 213 |  | 
|---|
| 214 | int boot_ioc_read(unsigned int lba, void* buffer, unsigned int count) | 
|---|
| 215 | { | 
|---|
| 216 | unsigned int sdcard_rsp; | 
|---|
| 217 | unsigned int i; | 
|---|
| 218 |  | 
|---|
| 219 | sdcard_dev_lseek(&_sdcard_device, lba); | 
|---|
| 220 |  | 
|---|
| 221 | #if (BOOT_DEBUG ==1 && BOOT_DEBUG_IOC == 1) | 
|---|
| 222 | unsigned int start_time; | 
|---|
| 223 | unsigned int end_time; | 
|---|
| 224 | boot_puts("[ DEBUG ] Reading blocks "); | 
|---|
| 225 | boot_putd(lba); | 
|---|
| 226 | boot_puts(" to "); | 
|---|
| 227 | boot_putd(lba + count - 1); | 
|---|
| 228 |  | 
|---|
| 229 | start_time = boot_proctime(); | 
|---|
| 230 | #endif | 
|---|
| 231 |  | 
|---|
| 232 | for(i = 0; i < count; i++) | 
|---|
| 233 | { | 
|---|
| 234 | if (( sdcard_rsp = sdcard_dev_read ( | 
|---|
| 235 | &_sdcard_device, | 
|---|
| 236 | (unsigned char *) buffer + (512 * i), | 
|---|
| 237 | 512 | 
|---|
| 238 | ) | 
|---|
| 239 | )) | 
|---|
| 240 | { | 
|---|
| 241 | boot_puts("ERROR during read on the SDCARD device. Code: "); | 
|---|
| 242 | boot_putx(sdcard_rsp); | 
|---|
| 243 | boot_puts("\n\r"); | 
|---|
| 244 |  | 
|---|
| 245 | return 1; | 
|---|
| 246 | } | 
|---|
| 247 | } | 
|---|
| 248 |  | 
|---|
| 249 | #if (BOOT_DEBUG == 1 && BOOT_DEBUG_IOC == 1) | 
|---|
| 250 | end_time = boot_proctime(); | 
|---|
| 251 |  | 
|---|
| 252 | boot_puts(" / cycles for transfert: "); | 
|---|
| 253 | boot_putd(end_time - start_time); | 
|---|
| 254 | boot_puts("\n"); | 
|---|
| 255 | #endif | 
|---|
| 256 |  | 
|---|
| 257 | return 0; | 
|---|
| 258 | } | 
|---|
| 259 | #endif | 
|---|
| 260 |  | 
|---|
| 261 | /** | 
|---|
| 262 | * _dcache_buf_invalidate() | 
|---|
| 263 | * | 
|---|
| 264 | * Invalidate all data cache lines corresponding to a memory | 
|---|
| 265 | * buffer (identified by an address and a size). | 
|---|
| 266 | */ | 
|---|
| 267 | #if (CACHE_COHERENCE == 0) || (USE_IOB == 1) | 
|---|
| 268 | void boot_buf_invalidate ( | 
|---|
| 269 | const void * buffer, | 
|---|
| 270 | unsigned int line_size, | 
|---|
| 271 | unsigned int size) | 
|---|
| 272 | { | 
|---|
| 273 | unsigned int i; | 
|---|
| 274 |  | 
|---|
| 275 | // iterate on cache lines | 
|---|
| 276 | for (i = 0; i <= size; i += line_size) { | 
|---|
| 277 | asm volatile( | 
|---|
| 278 | " cache %0, %1" | 
|---|
| 279 | :// no outputs | 
|---|
| 280 | :"i" (0x11), "R" (*((unsigned char *) buffer + i)) | 
|---|
| 281 | ); | 
|---|
| 282 | } | 
|---|
| 283 | } | 
|---|
| 284 | #endif | 
|---|
| 285 |  | 
|---|
| 286 | /** | 
|---|
| 287 | * boot_mcc_inval() | 
|---|
| 288 | * | 
|---|
| 289 | * Invalidate all data cache lines corresponding to a memory | 
|---|
| 290 | * buffer (identified by an address and a size). | 
|---|
| 291 | */ | 
|---|
| 292 | #if (USE_IOB == 1) | 
|---|
| 293 | void boot_mcc_invalidate ( | 
|---|
| 294 | const void * buffer, | 
|---|
| 295 | unsigned int size) | 
|---|
| 296 | { | 
|---|
| 297 | unsigned int * mcc_address = (unsigned int *)MCC_BASE; | 
|---|
| 298 |  | 
|---|
| 299 | // get the hard lock assuring exclusive access to MEMC | 
|---|
| 300 | while (ioread32(&mcc_address[MCC_LOCK])); | 
|---|
| 301 |  | 
|---|
| 302 | // write invalidate paremeters on the memory cache | 
|---|
| 303 | // this preloader use only the cluster 0 and then the HI bits are not used | 
|---|
| 304 |  | 
|---|
| 305 | iowrite32(&mcc_address[MCC_ADDR_LO], (unsigned int) buffer); | 
|---|
| 306 | iowrite32(&mcc_address[MCC_ADDR_HI], (unsigned int) 0); | 
|---|
| 307 | iowrite32(&mcc_address[MCC_LENGTH] , (unsigned int) size); | 
|---|
| 308 | iowrite32(&mcc_address[MCC_CMD]    , (unsigned int) MCC_CMD_INVAL); | 
|---|
| 309 |  | 
|---|
| 310 | // release the lock protecting MEMC | 
|---|
| 311 | iowrite32(&mcc_address[MCC_LOCK], (unsigned int) 0); | 
|---|
| 312 | } | 
|---|
| 313 | #endif | 
|---|
| 314 |  | 
|---|
| 315 | /* | 
|---|
| 316 | * vim: tabstop=4 : shiftwidth=4 : expandtab | 
|---|
| 317 | */ | 
|---|