1 // See LICENSE for license details.
13 #define PAYLOAD_SIZE (16 << 11)
15 #define F_CLK 50000000UL
17 static volatile uint32_t * const spi
= (void *)(SPI_CTRL_ADDR
);
19 static inline uint8_t spi_xfer(uint8_t d
)
23 REG32(spi
, SPI_REG_TXFIFO
) = d
;
25 r
= REG32(spi
, SPI_REG_RXFIFO
);
30 static inline uint8_t sd_dummy(void)
32 return spi_xfer(0xFF);
35 static uint8_t sd_cmd(uint8_t cmd
, uint32_t arg
, uint8_t crc
)
40 REG32(spi
, SPI_REG_CSMODE
) = SPI_CSMODE_HOLD
;
53 // dprintf("sd:cmd: %hx\r\n", r);
57 kputs("sd_cmd: timeout");
62 static inline void sd_cmd_end(void)
65 REG32(spi
, SPI_REG_CSMODE
) = SPI_CSMODE_AUTO
;
69 static void sd_poweron(void)
72 REG32(spi
, SPI_REG_SCKDIV
) = (F_CLK
/ 300000UL);
73 REG32(spi
, SPI_REG_CSMODE
) = SPI_CSMODE_OFF
;
74 for (i
= 10; i
> 0; i
--) {
77 REG32(spi
, SPI_REG_CSMODE
) = SPI_CSMODE_AUTO
;
80 static int sd_cmd0(void)
84 rc
= (sd_cmd(0x40, 0, 0x95) != 0x01);
89 static int sd_cmd8(void)
93 rc
= (sd_cmd(0x48, 0x000001AA, 0x87) != 0x01);
94 sd_dummy(); /* command version; reserved */
95 sd_dummy(); /* reserved */
96 rc
|= ((sd_dummy() & 0xF) != 0x1); /* voltage */
97 rc
|= (sd_dummy() != 0xAA); /* check pattern */
102 static void sd_cmd55(void)
104 sd_cmd(0x77, 0, 0x65);
108 static int sd_acmd41(void)
114 r
= sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */
119 static int sd_cmd58(void)
123 rc
= (sd_cmd(0x7A, 0, 0xFD) != 0x00);
124 rc
|= ((sd_dummy() & 0x80) != 0x80); /* Power up status */
132 static int sd_cmd16(void)
136 rc
= (sd_cmd(0x50, 0x200, 0x15) != 0x00);
141 static uint16_t crc16_round(uint16_t crc
, uint8_t data
) {
142 crc
= (uint8_t)(crc
>> 8) | (crc
<< 8);
144 crc
^= (uint8_t)(crc
>> 4) & 0xf;
146 crc
^= (crc
& 0xff) << 5;
151 #define SPIN_UPDATE(i) (!((i) & ((1 << SPIN_SHIFT)-1)))
152 #define SPIN_INDEX(i) (((i) >> SPIN_SHIFT) & 0x3)
154 static const char spinner
[] = { '-', '/', '|', '\\' };
156 static int copy(void)
158 volatile uint8_t *p
= (void *)(PAYLOAD_DEST
);
159 long i
= PAYLOAD_SIZE
;
165 REG32(spi
, SPI_REG_SCKDIV
) = (F_CLK
/ 20000000UL);
166 if (sd_cmd(0x52, 0, 0xE1) != 0x00) {
171 uint16_t crc
, crc_exp
;
176 while (sd_dummy() != 0xFE);
178 uint8_t x
= sd_dummy();
180 crc
= crc16_round(crc
, x
);
183 crc_exp
= ((uint16_t)sd_dummy() << 8);
184 crc_exp
|= sd_dummy();
186 if (crc
!= crc_exp
) {
187 kputs("\b- CRC mismatch ");
192 if (SPIN_UPDATE(i
)) {
194 kputc(spinner
[SPIN_INDEX(i
)]);
199 sd_cmd(0x4C, 0, 0x01);
207 REG32(uart
, UART_REG_TXCTRL
) = UART_TXEN
;
223 __asm__
__volatile__ ("fence.i" : : : "memory");