spisdcard: revert to 8-bit SPI, optimize spisdcardreceive_block and reduce clk to...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 17 Jul 2020 09:58:26 +0000 (11:58 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 17 Jul 2020 09:58:26 +0000 (11:58 +0200)
litex/soc/integration/soc.py
litex/soc/software/liblitesdcard/spisdcard.c

index aee695c1072317265b5341c8fdc7bec88e5ffa51..6e64e8493635cf292fbef71699f677ac48ace39d 100644 (file)
@@ -1263,7 +1263,7 @@ class LiteXSoC(SoC):
         pads = self.platform.request(name)
         if hasattr(pads, "rst"):
             self.comb += pads.rst.eq(0)
-        spisdcard = SPIMaster(pads, 32, self.sys_clk_freq, spi_clk_freq, mode="aligned")
+        spisdcard = SPIMaster(pads, 8, self.sys_clk_freq, spi_clk_freq)
         spisdcard.add_clk_divider()
         setattr(self.submodules, name, spisdcard)
         self.add_csr(name)
index 7131d083069d564017af934c7ef445d6367076c2..55854b76adb09d18697e37c6450e2a45d6acead7 100644 (file)
 #define SPISDCARD_CLK_FREQ_INIT 400000
 #endif
 #ifndef SPISDCARD_CLK_FREQ
-#define SPISDCARD_CLK_FREQ 16000000
+#define SPISDCARD_CLK_FREQ 12500000
 #endif
 
+/*-----------------------------------------------------------------------*/
+/* Helpers                                                               */
+/*-----------------------------------------------------------------------*/
+
+#define max(x, y) (((x) > (y)) ? (x) : (y))
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+
 /*-----------------------------------------------------------------------*/
 /* SPI Master low-level functions                                        */
 /*-----------------------------------------------------------------------*/
 
 static void spi_set_clk_freq(uint32_t clk_freq) {
     uint32_t divider;
-    divider = CONFIG_CLOCK_FREQUENCY/clk_freq + 1;
-    if (divider >= 65535) /* 16-bit hardware divider */
-        divider = 65535;
-    if (divider <= 2)     /* At least half CPU speed */
-        divider = 2;
+    divider = CONFIG_CLOCK_FREQUENCY/clk_freq;
+    divider = max(divider,     2);
+    divider = min(divider,   256);
 #ifdef SPISDCARD_DEBUG
     printf("Setting SDCard clk freq to ");
     if (clk_freq > 1000000)
@@ -125,7 +130,8 @@ static void busy_wait_us(unsigned int us)
 }
 
 static uint8_t spisdcardreceive_block(uint8_t *buf) {
-    uint8_t i;
+    uint16_t i;
+    uint8_t done;
     uint32_t timeout;
 
     /* Wait 100ms for a start of block */
@@ -140,17 +146,19 @@ static uint8_t spisdcardreceive_block(uint8_t *buf) {
         return 0;
 
     /* Receive block */
-    spisdcard_mosi_write(0xffffffff);
-    for (i=0; i<128; i++) {
-        uint32_t word;
-        spisdcard_control_write(32*SPI_LENGTH | SPI_START);
-        while(spisdcard_status_read() != SPI_DONE);
-        word = spisdcard_miso_read();
-        buf[0] = (word >> 24) & 0xff;
-        buf[1] = (word >> 16) & 0xff;
-        buf[2] = (word >>  8) & 0xff;
-        buf[3] = (word >>  0) & 0xff;
-        buf += 4;
+    spisdcard_mosi_write(0xff);
+    i = 0;
+    for (;;) {
+        done = spisdcard_status_read() & SPI_DONE;
+        if (done) {
+            spisdcard_control_write(8*SPI_LENGTH | SPI_START);
+            *buf = spisdcard_miso_read();
+            if (i == 512)
+                break;
+            if (i != 0)
+                buf++;
+            i++;
+        }
     }
 
     /* Discard CRC */