Update Litex bios to handle updated litesdcard.
authorKamil Rakoczy <krakoczy@antmicro.com>
Fri, 3 Apr 2020 12:58:36 +0000 (14:58 +0200)
committerKamil Rakoczy <krakoczy@antmicro.com>
Tue, 12 May 2020 08:07:16 +0000 (10:07 +0200)
litex/soc/software/bios/commands/cmd_sdcard.c
litex/soc/software/bios/sdcard.c
litex/soc/software/bios/sdcard.h

index 96f9fe64c701f8a9eab364d8eeba988dd7713fc5..d9545e07ace9907a15c043eb48c3d6c0c229d67c 100644 (file)
@@ -52,34 +52,92 @@ define_command(sdclk, sdclk, "SDCard set clk frequency (Mhz)", SD_CMDS);
  *
  */
 #ifdef CSR_SDCORE_BASE
-define_command(sdinit, sdinit, "SDCard initialization", SD_CMDS);
+define_command(sdinit, sdcard_init, "SDCard initialization", SD_CMDS);
 #endif
 
 /**
  * Command "sdtest"
  *
- * Perform SDcard access tests
+ * Perform SDcard read/write tests
  *
  */
 #ifdef CSR_SDCORE_BASE
 static void sdtest(int nb_params, char **params)
 {
-       unsigned int loops;
+       unsigned int blocks;
        char *c;
 
        if (nb_params < 1) {
-               printf("sdtest <loops>");
+               printf("sdtest <number of blocks>");
                return;
        }
 
-       loops = strtoul(params[0], &c, 0);
+       blocks = strtoul(params[0], &c, 0);
        if (*c != 0) {
-               printf("Incorrect number of loops");
+               printf("Incorrect number of blocks to write");
                return;
        }
 
-       sdcard_test(loops);
+       sdcard_test(blocks);
 }
 
 define_command(sdtest, sdtest, "SDCard test", SD_CMDS);
 #endif
+
+/**
+ * Command "sdtestread"
+ *
+ * Perform SDcard read test
+ *
+ */
+#ifdef CSR_SDCORE_BASE
+static void sdtestread(int nb_params, char **params)
+{
+       unsigned int block;
+       char *c;
+
+       if (nb_params < 1) {
+               printf("sdtestread <block number>");
+               return;
+       }
+
+       block = strtoul(params[0], &c, 0);
+       if (*c != 0) {
+               printf("Incorrect number of block to read");
+               return;
+       }
+
+       sdcard_test_read(block);
+}
+
+define_command(sdtestread, sdtestread, "SDCard test read", SD_CMDS);
+#endif
+
+/**
+ * Command "sdtestwrite"
+ *
+ * Perform SDcard write test
+ *
+ */
+#ifdef CSR_SDCORE_BASE
+static void sdtestwrite(int nb_params, char **params)
+{
+       unsigned int block;
+       char *c;
+
+       if (nb_params < 2) {
+               printf("sdtestread <block number> <str to write>");
+               return;
+       }
+
+       block = strtoul(params[0], &c, 0);
+       if (*c != 0) {
+               printf("Incorrect number of block to write");
+               return;
+       }
+
+       sdcard_test_write(block, params[1]);
+}
+
+define_command(sdtestwrite, sdtestwrite, "SDCard test write", SD_CMDS);
+#endif
index 314b9e28b3c64861f5fa33e24e1177905f8039cd..274f3cfacad0284bd16cfca8495f3a168951be59 100644 (file)
@@ -1,6 +1,7 @@
 // This file is Copyright (c) 2017 Florent Kermarrec <florent@enjoy-digital.fr>
 // This file is Copyright (c) 2019 Kees Jongenburger <kees.jongenburger@gmail.com>
 // This file is Copyright (c) 2018 bunnie <bunnie@kosagi.com>
+// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
 // License: BSD
 
 #include <stdio.h>
 
 #define SDCARD_DEBUG
 
-/* clocking */
+#define CHECK_LOOPS_PRINT_THRESHOLD 1000000
+
+#define REPEATED_MSG(cnt, thr, fmt, ...) do { \
+                       const int _cnt = (cnt); \
+                       if((_cnt) >= (thr)) { \
+                               if((_cnt) > (thr)) { \
+                                       printf("\033[1A\033[1G"); \
+                               } \
+                               printf(fmt "\033[0m\033[K\n", ## __VA_ARGS__); \
+                       } \
+               } while(0);
+
+#define BLOCK_SIZE 512
+#define NO_RESPONSE 0xFF
+
+#define SDCARD_RESPONSE_SIZE 5
+unsigned int sdcard_response[SDCARD_RESPONSE_SIZE];
+
+volatile char *SDREAD = (char*)(SDREAD_BASE);
+volatile char *SDWRITE = (char*)(SDWRITE_BASE);
 
 #ifdef CSR_SDCLK_CMD_DATA_ADDR
 
+/* clocking */
 static void sdclk_dcm_write(int cmd, int data)
 {
        int word;
@@ -70,13 +91,13 @@ void sdclk_set_clk(unsigned int freq) {
        while(!(sdclk_status_read() & CLKGEN_STATUS_LOCKED));
 }
 
-#elif CSR_SDCLK_MMCM_DRP_WRITE_ADDR
+#elif CSR_MMCM_DRP_WRITE_ADDR
 
 static void sdclk_mmcm_write(unsigned int adr, unsigned int data) {
-       sdclk_mmcm_drp_adr_write(adr);
-       sdclk_mmcm_drp_dat_w_write(data);
-       sdclk_mmcm_drp_write_write(1);
-       while(!sdclk_mmcm_drp_drdy_read());
+       mmcm_drp_adr_write(adr);
+       mmcm_drp_dat_w_write(data);
+       mmcm_drp_write_write(1);
+       while(!mmcm_drp_drdy_read());
 }
 
 
@@ -157,40 +178,41 @@ static unsigned int sdtimer_get(void)
        return sdtimer_value_read();
 }
 
-unsigned int sdcard_response[4];
 
 int sdcard_wait_cmd_done(void) {
+       unsigned check_counter = 0;
        unsigned int cmdevt;
        while (1) {
                cmdevt = sdcore_cmdevt_read();
-#ifdef SDCARD_DEBUG
-               printf("cmdevt: %08x\n", cmdevt);
-#endif
+               REPEATED_MSG(++check_counter, CHECK_LOOPS_PRINT_THRESHOLD,
+                                        "\033[36m  cmdevt: %08x (check #%d)",
+                                        cmdevt, check_counter);
+               if(check_counter > CHECK_LOOPS_PRINT_THRESHOLD) {
+                       putchar('\n');
+                       return NO_RESPONSE; //If we reach threshold, and cmdevt didn't return valid status, return NO_RESPONSE
+               }
                if (cmdevt & 0x1) {
-                       if (cmdevt & 0x4) {
-#ifdef SDCARD_DEBUG
-                               printf("cmdevt: SD_TIMEOUT\n");
-#endif
+                       if (cmdevt & 0x4)
                                return SD_TIMEOUT;
-                       }
-                       else if (cmdevt & 0x8) {
-#ifdef SDCARD_DEBUG
-                               printf("cmdevt: SD_CRCERROR\n");
+                       else if (cmdevt & 0x8)
                                return SD_CRCERROR;
-#endif
-                       }
                        return SD_OK;
                }
        }
 }
 
 int sdcard_wait_data_done(void) {
+       unsigned check_counter = 0;
        unsigned int dataevt;
        while (1) {
                dataevt = sdcore_dataevt_read();
-#ifdef SDCARD_DEBUG
-               printf("dataevt: %08x\n", dataevt);
-#endif
+               REPEATED_MSG(++check_counter, CHECK_LOOPS_PRINT_THRESHOLD,
+                                        "\033[36m  dataevt: %08x (check #%d)",
+                                        dataevt, check_counter);
+               if(check_counter > CHECK_LOOPS_PRINT_THRESHOLD) {
+                       putchar('\n');
+                       return NO_RESPONSE; //If we reach threshold, and cmdevt didn't return valid status, return NO_RESPONSE
+               }
                if (dataevt & 0x1) {
                        if (dataevt & 0x4)
                                return SD_TIMEOUT;
@@ -202,19 +224,68 @@ int sdcard_wait_data_done(void) {
 }
 
 int sdcard_wait_response(void) {
-       int status = sdcard_wait_cmd_done();
+        int i, j;
+       int status;
+
+       status = sdcard_wait_cmd_done();
+
+#if CONFIG_CSR_DATA_WIDTH == 8
+       unsigned int r;
+
+       // LSB is located at RESPONSE_ADDR + (RESPONSE_SIZE - 1) * 4
+       int offset;
+       for(i = 0; i < SDCARD_RESPONSE_SIZE; i++) {
+         r = 0;
+         for(j = 0; j < 4; j++) {
+           // SD card response consists of 17 bytes
+           // scattered accross 5 32-bit CSRs.
+           // In a configuration with CONFIG_CSR_DATA_WIDTH == 8
+           // this means we need to do 17 32-bit reads
+           // and group bytes as described below:
+           // sdcard_response | CSR_SDCORE_RESPONSE_ADDR
+           // offset          | offsets
+           // ------------------------------------------
+           //               0 | [           0 ]
+           //               1 | [  4  8 12 16 ]
+           //               2 | [ 20 23 28 32 ]
+           //               3 | [ 36 40 44 48 ]
+           //               4 | [ 52 56 60 64 ]
+           // ------------------------------------------
+           //                   |          ^  |
+           //                   +--- u32 --|--+
+           //                              LS byte
+           offset = 4 * ((CSR_SDCORE_RESPONSE_SIZE - 1) - j - i * 4);
+           if(offset >= 0) {
+              // Read response and move it by 'j' bytes
+             r |= ((csr_read_simple(CSR_SDCORE_RESPONSE_ADDR + offset) & 0xFF) << (j * 8));
+           }
+         }
+         sdcard_response[(SDCARD_RESPONSE_SIZE - 1) - i] = r;  // NOTE: this is "backwards" but sticking with this because it's compatible with CSR32
+       }
+#else
+       volatile unsigned int *buffer = (unsigned int *)CSR_SDCORE_RESPONSE_ADDR;
+
+       for(i = 0; i < SDCARD_RESPONSE_SIZE; i++) {
+               sdcard_response[i] = buffer[i];
+       }
+#endif
 
-       csr_rd_buf_uint32(CSR_SDCORE_RESPONSE_ADDR, sdcard_response, 4);
 #ifdef SDCARD_DEBUG
-       printf("sdcard_response = [%08x, %08x, %08x, %08x];\n",
-               sdcard_response[0], sdcard_response[1],
-               sdcard_response[2], sdcard_response[3]);
+       for(i = 0; i < SDCARD_RESPONSE_SIZE; i++) {
+               printf("%08x ", sdcard_response[i]);
+       }
+       printf("\n");
 #endif
 
        return status;
 }
 
 /* commands */
+#if CONFIG_CSR_DATA_WIDTH == 8
+#define  CSR8_CMD_FIX          sdcore_issue_cmd_write(1)
+#else
+#define  CSR8_CMD_FIX
+#endif
 
 void sdcard_go_idle(void) {
 #ifdef SDCARD_DEBUG
@@ -222,15 +293,18 @@ void sdcard_go_idle(void) {
 #endif
        sdcore_argument_write(0x00000000);
        sdcore_command_write((0 << 8) | SDCARD_CTRL_RESPONSE_NONE);
+       CSR8_CMD_FIX;
 }
 
 int sdcard_send_ext_csd(void) {
+       unsigned int arg;
+       arg = 0x000001aa;
 #ifdef SDCARD_DEBUG
-       printf("CMD8: SEND_EXT_CSD\n");
+       printf("CMD8: SEND_EXT_CSD, arg: 0x%08x\n", arg);
 #endif
-       sdcore_argument_write(0x000001aa);
-       sdcore_command_write((8 << 8) | SDCARD_CTRL_RESPONSE_NONE);
-       busy_wait(1);
+       sdcore_argument_write(arg);
+       sdcore_command_write((8 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -240,23 +314,23 @@ int sdcard_app_cmd(int rca) {
 #endif
        sdcore_argument_write(rca << 16);
        sdcore_command_write((55 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
 int sdcard_app_send_op_cond(int hcs, int s18r) {
        unsigned int arg;
-#ifdef SDCARD_DEBUG
-       printf("ACMD41: APP_SEND_OP_COND\n");
-#endif
        arg = 0x10ff8000;
        if (hcs)
                arg |= 0x60000000;
        if (s18r)
                arg |= 0x01000000;
+#ifdef SDCARD_DEBUG
+       printf("ACMD41: APP_SEND_OP_COND, arg: %08x\n", arg);
+#endif
        sdcore_argument_write(arg);
        sdcore_command_write((41 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -266,7 +340,7 @@ int sdcard_all_send_cid(void) {
 #endif
        sdcore_argument_write(0x00000000);
        sdcore_command_write((2 << 8) | SDCARD_CTRL_RESPONSE_LONG);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -276,7 +350,7 @@ int sdcard_set_relative_address(void) {
 #endif
        sdcore_argument_write(0x00000000);
        sdcore_command_write((3 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -286,7 +360,7 @@ int sdcard_send_cid(unsigned int rca) {
 #endif
        sdcore_argument_write(rca << 16);
        sdcore_command_write((10 << 8) | SDCARD_CTRL_RESPONSE_LONG);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -296,7 +370,7 @@ int sdcard_send_csd(unsigned int rca) {
 #endif
        sdcore_argument_write(rca << 16);
        sdcore_command_write((9 << 8) | SDCARD_CTRL_RESPONSE_LONG);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -306,7 +380,7 @@ int sdcard_select_card(unsigned int rca) {
 #endif
        sdcore_argument_write(rca << 16);
        sdcore_command_write((7 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -316,7 +390,7 @@ int sdcard_app_set_bus_width(void) {
 #endif
        sdcore_argument_write(0x00000002);
        sdcore_command_write((6 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -335,9 +409,8 @@ int sdcard_switch(unsigned int mode, unsigned int group, unsigned int value, uns
        sdcore_blockcount_write(1);
        sdcore_command_write((6 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                 (SDCARD_CTRL_DATA_TRANSFER_READ << 5));
-       busy_wait(1);
+       CSR8_CMD_FIX;
        sdcard_wait_response();
-       busy_wait(1);
        return sdcard_wait_data_done();
 }
 
@@ -350,9 +423,8 @@ int sdcard_app_send_scr(void) {
        sdcore_blockcount_write(1);
        sdcore_command_write((51 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                 (SDCARD_CTRL_DATA_TRANSFER_READ << 5));
-       busy_wait(1);
+       CSR8_CMD_FIX;
        sdcard_wait_response();
-       busy_wait(1);
        return sdcard_wait_data_done();
 }
 
@@ -363,7 +435,7 @@ int sdcard_app_set_blocklen(unsigned int blocklen) {
 #endif
        sdcore_argument_write(blocklen);
        sdcore_command_write((16 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -374,10 +446,11 @@ int sdcard_write_single_block(unsigned int blockaddr) {
        int cmd_response = -1;
        while (cmd_response != SD_OK) {
                sdcore_argument_write(blockaddr);
-               sdcore_blocksize_write(512);
+               sdcore_blocksize_write(BLOCK_SIZE);
                sdcore_blockcount_write(1);
                sdcore_command_write((24 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                         (SDCARD_CTRL_DATA_TRANSFER_WRITE << 5));
+               CSR8_CMD_FIX;
                cmd_response = sdcard_wait_response();
        }
        return cmd_response;
@@ -390,10 +463,11 @@ int sdcard_write_multiple_block(unsigned int blockaddr, unsigned int blockcnt) {
        int cmd_response = -1;
        while (cmd_response != SD_OK) {
                sdcore_argument_write(blockaddr);
-               sdcore_blocksize_write(512);
+               sdcore_blocksize_write(BLOCK_SIZE);
                sdcore_blockcount_write(blockcnt);
                sdcore_command_write((25 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                         (SDCARD_CTRL_DATA_TRANSFER_WRITE << 5));
+               CSR8_CMD_FIX;
                cmd_response = sdcard_wait_response();
        }
        return cmd_response;
@@ -406,10 +480,11 @@ int sdcard_read_single_block(unsigned int blockaddr) {
 int cmd_response = -1;
        while (cmd_response != SD_OK) {
                sdcore_argument_write(blockaddr);
-               sdcore_blocksize_write(512);
+               sdcore_blocksize_write(BLOCK_SIZE);
                sdcore_blockcount_write(1);
                sdcore_command_write((17 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                         (SDCARD_CTRL_DATA_TRANSFER_READ << 5));
+               CSR8_CMD_FIX;
                cmd_response = sdcard_wait_response();
        }
        return sdcard_wait_data_done();
@@ -422,10 +497,11 @@ int sdcard_read_multiple_block(unsigned int blockaddr, unsigned int blockcnt) {
 int cmd_response = -1;
        while (cmd_response != SD_OK) {
                sdcore_argument_write(blockaddr);
-               sdcore_blocksize_write(512);
+               sdcore_blocksize_write(BLOCK_SIZE);
                sdcore_blockcount_write(blockcnt);
                sdcore_command_write((18 << 8) | SDCARD_CTRL_RESPONSE_SHORT |
                                                         (SDCARD_CTRL_DATA_TRANSFER_READ << 5));
+               CSR8_CMD_FIX;
                cmd_response = sdcard_wait_response();
        }
        return cmd_response;
@@ -437,7 +513,7 @@ int sdcard_stop_transmission(void) {
 #endif
        sdcore_argument_write(0x0000000);
        sdcore_command_write((12 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -447,7 +523,7 @@ int sdcard_send_status(unsigned int rca) {
 #endif
        sdcore_argument_write(rca << 16);
        sdcore_command_write((13 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -457,7 +533,7 @@ int sdcard_set_block_count(unsigned int blockcnt) {
 #endif
        sdcore_argument_write(blockcnt);
        sdcore_command_write((23 << 8) | SDCARD_CTRL_RESPONSE_SHORT);
-       busy_wait(1);
+       CSR8_CMD_FIX;
        return sdcard_wait_response();
 }
 
@@ -467,65 +543,100 @@ void sdcard_decode_cid(void) {
                "Manufacturer ID: 0x%x\n"
                "Application ID 0x%x\n"
                "Product name: %c%c%c%c%c\n",
-                       sdcard_response[0],
                        sdcard_response[1],
                        sdcard_response[2],
                        sdcard_response[3],
+                       sdcard_response[4],
 
-                       (sdcard_response[0] >> 16) & 0xffff,
+                       (sdcard_response[1] >> 16) & 0xffff,
 
-                       sdcard_response[0] & 0xffff,
+                       sdcard_response[1] & 0xffff,
 
-                       (sdcard_response[1] >> 24) & 0xff,
-                       (sdcard_response[1] >> 16) & 0xff,
-                       (sdcard_response[1] >>  8) & 0xff,
-                       (sdcard_response[1] >>  0) & 0xff,
-                       (sdcard_response[2] >> 24) & 0xff
+                       (sdcard_response[2] >> 24) & 0xff,
+                       (sdcard_response[2] >> 16) & 0xff,
+                       (sdcard_response[2] >>  8) & 0xff,
+                       (sdcard_response[2] >>  0) & 0xff,
+                       (sdcard_response[3] >> 24) & 0xff
                );
+       int crc = sdcard_response[4] & 0x000000FF;
+       int month = (sdcard_response[4] & 0x00000F00) >> 8;
+       int year = (sdcard_response[4] & 0x000FF000) >> 12;
+       int psn = ((sdcard_response[4] & 0xFF000000) >> 24) | ((sdcard_response[3] & 0x00FFFFFF) << 8);
+       printf( "CRC: %02x\n", crc);
+       printf( "Production date(m/yy): %d/%d\n", month, year);
+       printf( "PSN: %08x\n", psn);
+       printf( "OID: %c%c\n", (sdcard_response[1] & 0x00FF0000) >> 16, (sdcard_response[1] & 0x0000FF00) >> 8);
 }
 
 void sdcard_decode_csd(void) {
        /* FIXME: only support CSR structure version 2.0 */
+
+       int size = ((sdcard_response[3] & 0xFFFF0000) >> 16) + ((sdcard_response[2] & 0x000000FF) << 16) + 1;
        printf(
                "CSD Register: 0x%x%08x%08x%08x\n"
                "Max data transfer rate: %d MB/s\n"
                "Max read block length: %d bytes\n"
                "Device size: %d GB\n",
-                       sdcard_response[0],
                        sdcard_response[1],
                        sdcard_response[2],
                        sdcard_response[3],
+                       sdcard_response[4],
 
                        (sdcard_response[1] >> 24) & 0xff,
 
-                       (1 << ((sdcard_response[1] >> 8) & 0xf)),
+                       (1 << ((sdcard_response[2] >> 16) & 0xf)),
 
-                       ((sdcard_response[2] >> 8) & 0x3fffff)*512/(1024*1024)
+                       size * BLOCK_SIZE / (1024 * 1024)
        );
 }
 
 /* bist */
 
-void sdcard_bist_generator_start(unsigned int blockcnt) {
-       bist_generator_reset_write(1);
-       bist_generator_count_write(blockcnt);
-       bist_generator_start_write(1);
-}
-
-void sdcard_bist_generator_wait(void) {
-       while((bist_generator_done_read() & 0x1) == 0);
-}
-
-
-void sdcard_bist_checker_start(unsigned int blockcnt) {
-       bist_checker_reset_write(1);
-       bist_checker_count_write(blockcnt);
-       bist_checker_start_write(1);
+#ifdef CSR_SDDATAWRITER_BASE
+void sdcard_sddatawriter_start(void) {
+       sddatawriter_reset_write(1);
+       sddatawriter_start_write(1);
+}
+
+int sdcard_sddatawriter_wait(void) {
+       unsigned check_counter = 0;
+       unsigned done = 0;
+       while(!done) {
+               done = sddatawriter_done_read();
+               REPEATED_MSG(++check_counter, CHECK_LOOPS_PRINT_THRESHOLD,
+                                        "\033[36m  sddatawriter_done_read: %08x (check #%d)",
+                                        done, ++check_counter);
+               if(check_counter > CHECK_LOOPS_PRINT_THRESHOLD) {
+                       putchar('\n');
+                       return NO_RESPONSE; //If we reach threshold, and cmdevt didn't return valid status, return NO_RESPONSE
+               }
+       }
+       return 0;
 }
+#endif
 
-void sdcard_bist_checker_wait(void) {
-       while((bist_checker_done_read() & 0x1) == 0);
+#ifdef CSR_SDDATAREADER_BASE
+void sdcard_sddatareader_start(void) {
+       sddatareader_reset_write(1);
+       sddatareader_start_write(1);
+}
+
+int sdcard_sddatareader_wait(void) {
+       unsigned check_counter = 0;
+       unsigned done = 0;
+       while((done & 1) == 0) {
+               done = sddatareader_done_read();
+               REPEATED_MSG(++check_counter, CHECK_LOOPS_PRINT_THRESHOLD,
+                                        "\033[36m  sddatareader_done_read: %08x (check #%d)",
+                                        done, check_counter);
+               if(check_counter > CHECK_LOOPS_PRINT_THRESHOLD) {
+                       putchar('\n');
+                       return NO_RESPONSE; //If we reach threshold, and cmdevt didn't return valid status, return NO_RESPONSE
+               }
+       }
+       return 0;
 }
+#endif
 
 /* user */
 
@@ -542,13 +653,26 @@ int sdcard_init(void) {
        sdcard_go_idle();
        busy_wait(1);
        sdcard_send_ext_csd();
+#ifdef SDCARD_DEBUG
+       printf("Accepted voltage: ");
+       if(sdcard_response[4] & 0x0)
+               printf("Not defined\n");
+       else if(sdcard_response[4] >> 8 & 0x1)
+               printf("2.7-3.6V\n");
+       else if(sdcard_response[4] >> 12 & 0x1)
+               printf("Reserved\n");
+       else if(sdcard_response[4] >> 16 & 0x1)
+               printf("Reserved\n");
+       else
+               printf("Invalid response\n");
+#endif
 
        /* wait for card to be ready */
        /* FIXME: 1.8v support */
        for(;;) {
                sdcard_app_cmd(0);
                sdcard_app_send_op_cond(1, 0);
-               if (sdcard_response[3] & 0x80000000) {
+               if (sdcard_response[4] & 0x80000000) {
                        break;
                }
                busy_wait(1);
@@ -562,7 +686,7 @@ int sdcard_init(void) {
 
        /* set relative card address */
        sdcard_set_relative_address();
-       rca = (sdcard_response[3] >> 16) & 0xffff;
+       rca = (sdcard_response[4] >> 16) & 0xffff;
 
        /* set cid */
        sdcard_send_cid(rca);
@@ -595,66 +719,195 @@ int sdcard_init(void) {
        sdcard_app_send_scr();
 
        /* set block length */
-       sdcard_app_set_blocklen(512);
+       sdcard_app_set_blocklen(BLOCK_SIZE);
 
        return 0;
 }
 
-int sdcard_test(unsigned int loops) {
-       unsigned int i;
-       unsigned int length;
-       unsigned int blocks;
-       unsigned int start;
-       unsigned int end;
-       unsigned int errors = 0;
-       unsigned long write_speed, read_speed;
+void hexdump(volatile const char *buf, size_t len)
+{
+    enum {
+        BYTES_PER_ROW = 16,
+        BYTES_PER_GROUP = 4,
+        ADDR_COL_1 = 1,
+        HEX_COL_1 = ADDR_COL_1 + 7,
+        CHAR_COL_1 = HEX_COL_1 + 3 * BYTES_PER_ROW
+                     + (BYTES_PER_ROW/BYTES_PER_GROUP) + 1,
+    };
+
+    int i;
+    unsigned char c;
+    int printable = 0;
+    unsigned column, hex_column, char_column;
+    char cstr[] = ".";
+
+    // Erase line
+    printf("\033[2K");
+
+    for(i = 0; i < len; ++i) {
+        c = cstr[0] = buf[i];
+        printable = (c >= ' ' && c < 127);
+        column = i % BYTES_PER_ROW;
+        hex_column = HEX_COL_1 + 3 * column + (column/BYTES_PER_GROUP);
+        char_column = CHAR_COL_1 + column + (column/BYTES_PER_GROUP);
+
+        if(column == 0) {
+            printf("\033[33m%04x\033[0m", i);
+        }
+
+        printf("\033[%uG""%02x"
+               "\033[%uG""%s""%s"
+               "\033[0m%s",
+               hex_column, c,
+               char_column, printable ? "\033[40m" : "\033[90m",
+               printable ? cstr : ".",
+               (column == BYTES_PER_ROW - 1 || i == len - 1) ? "\n" : "");
+    }
+    printf("\n");
+}
+
+void sdcard_test_write(unsigned block, const char *data)
+{
+#ifdef CSR_SDDATAWRITER_BASE
+       const char *c = data;
+       int i;
+       for(i = 0; i < BLOCK_SIZE; i++) {
+               SDWRITE[i] = *c;
+               if(*(++c) == 0) {
+                       c = data;
+               }
+       }
 
-       sdcore_cmdtimeout_write(1<<19);
-       sdcore_datatimeout_write(1<<19);
+       printf("SDWRITE:\n");
+       hexdump(SDWRITE, BLOCK_SIZE);
 
-       sdtimer_init();
+       sdcard_set_block_count(1);
+       sdcard_sddatawriter_start();
+       sdcard_write_single_block(block * BLOCK_SIZE);
+       sdcard_sddatawriter_wait();
+       sdcard_stop_transmission();
+#else
+       printf("Writer core not present\n");
+#endif
+}
 
-       length = 4*1024*1024;
-       blocks = length/512;
+void sdcard_test_read(unsigned block)
+{
+#ifdef CSR_SDDATAREADER_BASE
+       int i;
+       for(i = 0; i < sizeof(SDREAD); ++i) {
+               SDREAD[i] = 0;
+       }
+       printf("SDREAD (0x%08x) before read:\n", SDREAD);
+       hexdump(SDREAD, BLOCK_SIZE);
+
+       sdcard_set_block_count(1);
+       sdcard_sddatareader_start();
+       sdcard_read_single_block(block * BLOCK_SIZE);
+       sdcard_sddatareader_wait();
 
-       for(i=0; i<loops; i++) {
-               /* write */
-               start = sdtimer_get();
-               sdcard_set_block_count(blocks);
-               sdcard_bist_generator_start(blocks);
-               sdcard_write_multiple_block(i, blocks);
-               sdcard_bist_generator_wait();
+       printf("SDREAD (0x%08x) after read:\n", SDREAD);
+       hexdump(SDREAD, BLOCK_SIZE);
+#else
+       printf("Reader core not present\n");
+#endif
+}
+
+int sdcard_test(unsigned int count)
+{
+#if defined(CSR_SDDATAREADER_BASE) && defined(CSR_SDDATAWRITER_BASE)
+       srand(0);
+       int i, j, status;
+       int crcerrors = 0;
+       int timeouterrors = 0;
+       int repeat = 0;
+
+       sdcore_datawcrcclear_write(1);
+
+       for(i = 0; i < count; i = repeat ? i : i + 1) {
+               REPEATED_MSG(i, 0, "\033[96mWriting block %d (%d/%d); crc errors: %d; timeouts: %d; datawcrc: %u",
+                                        i, i + 1, count, crcerrors, timeouterrors, sdcore_datawcrcerrors_read());
+               if(!repeat) {
+                       for(j = 0; j < BLOCK_SIZE; ++j) {
+                               unsigned number = rand();
+                               SDWRITE[j] = number & 0xFF;
+                       }
+               } else {
+                       busy_wait(1);
+               }
+               repeat = 0;
+
+               sdcard_set_block_count(1);
+               sdcard_sddatawriter_start();
+               status = sdcard_write_single_block(i * BLOCK_SIZE);
+               if (status == SD_CRCERROR) {
+                       ++crcerrors;
+               } else if (status == SD_TIMEOUT) {
+                       ++timeouterrors;
+               }
+               if (status != SD_OK) {
+                       REPEATED_MSG(1, 0, "\033[31m  Repeating\n");
+                       repeat = 1;
+               }
+               status = sdcard_sddatawriter_wait();
+               if (status != 0) {
+                       REPEATED_MSG(1, 0, "\033[31m  Repeating\n");
+                       repeat = 1;
+               }
                sdcard_stop_transmission();
-               end = sdtimer_get();
-               write_speed = length*(CONFIG_CLOCK_FREQUENCY/100000)/((start - end)/100000);
-
-               /* delay FIXME */
-               busy_wait(200);
-
-               /* read */
-               start = sdtimer_get();
-               sdcard_set_block_count(blocks);
-               sdcard_bist_checker_start(blocks);
-               sdcard_read_multiple_block(i, blocks);
-               sdcard_bist_checker_wait();
-               end = sdtimer_get();
-               read_speed = length*(CONFIG_CLOCK_FREQUENCY/100000)/((start - end)/100000);
-
-               /* errors */
-               errors = bist_checker_errors_read();
-
-               /* infos */
-               if ((i%8) == 0)
-                       printf("LOOP WRITE_SPEED  READ_SPEED ERRORS\n");
-               printf("%4d %6d MB/s %6d MB/s %6d\n",
-                       i,
-                       write_speed/(1024*1024),
-                       read_speed/(1024*1024),
-                       errors
-               );
        }
+       REPEATED_MSG(i, 0, "\033[39;1mWriting crc errors: %d; timeouts: %d; datawcrc: %u",
+                                crcerrors, timeouterrors, sdcore_datawcrcerrors_read());
+
+       srand(0);
+       int errors = 0;
+       int errorsblk = 0;
+       crcerrors = 0;
+       timeouterrors = 0;
+       for(i = 0; i < count; i = repeat ? i : i + 1) {
+               REPEATED_MSG(i, 0, "\033[96mReading and checking block %d (%d/%d); errors: %d in %d blocks; crc errors: %d; timeouts: %d",
+                                        i, i + 1, count, errors, errorsblk, crcerrors, timeouterrors);
+
+               repeat = 0;
+               sdcard_set_block_count(1);
+               sdcard_sddatareader_start();
+               status = sdcard_read_single_block(i * BLOCK_SIZE);
+               if (status == SD_CRCERROR) {
+                       ++crcerrors;
+               } else if (status == SD_TIMEOUT) {
+                       ++timeouterrors;
+               }
+               if (status != SD_OK) {
+                       REPEATED_MSG(1, 0, "\033[31m  Repeating\n");
+                       repeat = 1;
+                       continue;
+               }
+               status = sdcard_sddatareader_wait();
+               if (status != 0) {
+                       REPEATED_MSG(1, 0, "\033[31m  Repeating\n");
+                       repeat = 1;
+                       continue;
+               }
 
-       return errors;
-}
+               int ok = 1;
+               for(j = 0; j < BLOCK_SIZE; ++j) {
+                       unsigned number = rand();
 
+                       if(SDREAD[j] != (number & 0xFF)) {
+                               ++errors;
+                               ok = 0;
+                       }
+               }
+               if(!ok) {
+                       REPEATED_MSG(0, 0, "\033[31m  Block check failed\n");
+                       ++errorsblk;
+               }
+       }
+       REPEATED_MSG(i, 0, "\033[39;1mReading errors: %d in %d blocks; crc errors: %d; timeouts: %d",
+                                errors, errorsblk, crcerrors, timeouterrors);
+#else
+       printf("Reader and/or writer core not present\n");
+#endif
+       return 0;
+}
 #endif /* CSR_SDCORE_BASE */
index 58f97c3bd97a6f2a1e3720efac3a6157c0364a58..690d85bc626e71a6b4d27e784bef9fa8fac2539c 100644 (file)
@@ -90,8 +90,15 @@ void sdcard_bist_checker_start(unsigned int blockcnt);
 void sdcard_bist_checker_wait(void);
 
 /* user */
+void hexdump(volatile const char *buf, size_t len);
 
 int sdcard_init(void);
+void sdcard_test_write(unsigned block, const char *data);
+void sdcard_test_read(unsigned block);
+void sdcard_sddatawriter_start(void);
+void sdcard_sddatareader_start(void);
+int sdcard_sddatawriter_wait(void);
+int sdcard_sddatareader_wait(void);
 int sdcard_test(unsigned int loops);
 
 #endif /* CSR_SDCORE_BASE */