From 1aec91e5b3e5bb980f2029579bda36f306c9a000 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Thu, 13 Feb 2025 18:32:38 +0100 Subject: sdcard driver moved to drv/ --- fw/fe310/eos/dev/drv/sdcard.c | 549 ++++++++++++++++++++++++++++++++++++++++++ fw/fe310/eos/dev/drv/sdcard.h | 22 ++ fw/fe310/eos/dev/sdcard.c | 545 ----------------------------------------- fw/fe310/eos/dev/sdcard.h | 22 -- 4 files changed, 571 insertions(+), 567 deletions(-) create mode 100644 fw/fe310/eos/dev/drv/sdcard.c create mode 100644 fw/fe310/eos/dev/drv/sdcard.h delete mode 100644 fw/fe310/eos/dev/sdcard.c delete mode 100644 fw/fe310/eos/dev/sdcard.h diff --git a/fw/fe310/eos/dev/drv/sdcard.c b/fw/fe310/eos/dev/drv/sdcard.c new file mode 100644 index 0000000..bc6b999 --- /dev/null +++ b/fw/fe310/eos/dev/drv/sdcard.c @@ -0,0 +1,549 @@ +#include +#include + +#include "eos.h" + +#include "sdc_platform.h" +#include "sdcard.h" + +#ifdef SDC_DEBUG +#include +#endif + +#define SDC_TIMEOUT_CMD 500 +#define SDC_TIMEOUT_READ 200 +#define SDC_TIMEOUT_WRITE 500 + +#define SDC_POLY_CRC7 0x09 +#define SDC_POLY_CRC16 0x1021 + +#define SDC_CMD_FLAG_CRC 0x01 +#define SDC_CMD_FLAG_NOCS 0x02 +#define SDC_CMD_FLAG_NOWAIT 0x04 +#define SDC_CMD_FLAG_RSTUFF 0x08 + +#define SDC_TOKEN_START_BLK 0xfe +#define SDC_TOKEN_START_BLKM 0xfc +#define SDC_TOKEN_STOP_TRAN 0xfd + +#define SDC_DRESP_MASK 0x1f +#define SDC_DRESP_ACCEPT 0x05 +#define SDC_DRESP_ERR_CRC 0x0b +#define SDC_DRESP_ERR_WRITE 0x0d + +#define SDC_R1_READY 0x00 + +#define SDC_R1_IDLE_STATE 0x01 +#define SDC_R1_ERASE_RESET 0x02 +#define SDC_R1_ILLEGAL_CMD 0x04 +#define SDC_R1_ERR_CMD_CRC 0x08 +#define SDC_R1_ERR_ERASE_SEQ 0x10 +#define SDC_R1_ERR_ADDR 0x20 +#define SDC_R1_ERR_PARAM 0x40 + +#define SDC_NCR 10 + +#define SDC_RV2ERR(rv) ((rv < 0) ? rv : SDC_ERR) + +/* CMD */ +#define GO_IDLE_STATE 0 +#define SEND_OP_COND 1 +#define SEND_IF_COND 8 +#define SEND_CSD 9 +#define STOP_TRANSMISSION 12 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define READ_MULTIPLE_BLOCK 18 +#define WRITE_BLOCK 24 +#define WRITE_MULTIPLE_BLOCK 25 +#define ERASE_WR_BLK_START 32 +#define ERASE_WR_BLK_END 33 +#define ERASE 38 +#define APP_CMD 55 +#define READ_OCR 58 + +/* ACMD */ +#define SD_STATUS 13 +#define SET_WR_BLK_ERASE_COUNT 23 +#define SD_APP_OP_COND 41 + +static uint8_t sdc_type = 0; + +static uint8_t sdc_crc7(uint8_t crc, uint8_t b) { + int i; + + for (i=8; i--; b<<=1) { + crc <<= 1; + if ((b ^ crc) & 0x80) crc ^= SDC_POLY_CRC7; + } + return crc & 0x7f; +} + +static uint16_t sdc_crc16(uint16_t crc, uint8_t b) { + int i; + + crc = crc ^ ((uint16_t)b << 8); + for (i=8; i--;) { + if (crc & 0x8000) { + crc = (crc << 1) ^ SDC_POLY_CRC16; + } else { + crc <<= 1; + } + } + return crc; +} + +static uint32_t sdc_nto(uint32_t start, uint32_t timeout) { + uint32_t d = sdc_tdelta_ms(start); + return (d > timeout) ? 0 : timeout - d; +} + +static uint8_t sdc_xchg8(uint8_t data) { + return sdc_spi_xchg8(data, 0); +} + +static uint16_t sdc_xchg16(uint16_t data) { + return sdc_spi_xchg16(data, 0); +} + +static uint32_t sdc_xchg32(uint32_t data) { + return sdc_spi_xchg32(data, 0); +} + +static void sdc_buf_send(unsigned char *buffer, uint16_t len) { + int i; + + for (i=0; i> 24); + crc = sdc_crc7(crc, arg >> 16); + crc = sdc_crc7(crc, arg >> 8); + crc = sdc_crc7(crc, arg); + } + crc = (crc << 1) | 0x01; + sdc_xchg8(cmd); + sdc_xchg32(arg); + sdc_xchg8(crc); + if (flags & SDC_CMD_FLAG_RSTUFF) sdc_xchg8(0xff); + + i = SDC_NCR; + do { + ret = sdc_xchg8(0xff); + } while ((ret & 0x80) && --i); + if (ret & 0x80) return SDC_ERR_BUSY; + + return ret; +} + +static int sdc_ready(uint32_t timeout) { + uint8_t d = 0; + uint32_t start; + + if (timeout == 0) return SDC_ERR_BUSY; + + start = sdc_get_tick(); + do { + if (sdc_tdelta_ms(start) > timeout) break; + d = sdc_xchg8(0xff); + } while (d != 0xff); + if (d != 0xff) return SDC_ERR_BUSY; + + return SDC_OK; +} + +static int sdc_block_read(uint8_t *buffer, uint16_t len, uint32_t timeout) { + uint8_t token = 0xff; + uint32_t start; + + if (timeout == 0) return SDC_ERR_BUSY; + + start = sdc_get_tick(); + do { + if (sdc_tdelta_ms(start) > timeout) break; + token = sdc_xchg8(0xff); + } while (token == 0xff); + if (token == 0xff) return SDC_ERR_BUSY; + if (token != SDC_TOKEN_START_BLK) return SDC_ERR; + + sdc_buf_recv(buffer, len); + sdc_xchg16(0xffff); /* dummy CRC */ + + return SDC_OK; +} + +static int sdc_block_write(uint8_t token, uint8_t *buffer, uint16_t len, uint32_t timeout) { + uint8_t d; + int rv; + + rv = sdc_ready(timeout); + if (rv) return rv; + + sdc_xchg8(token); + if (buffer && len) { + sdc_buf_send(buffer, len); + sdc_xchg16(0xffff); /* dummy CRC */ + + d = sdc_xchg8(0xff); /* Response */ + if ((d & SDC_DRESP_MASK) != SDC_DRESP_ACCEPT) return SDC_ERR; + } + + return SDC_OK; +} + +static int sdc_cmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { + int do_cs = !(flags & SDC_CMD_FLAG_NOCS); + int do_wait = !(flags & SDC_CMD_FLAG_NOWAIT); + int rv = SDC_OK; + + if (do_cs) sdc_select(); + if (do_wait) rv = sdc_ready(timeout); + if (rv) { + if (do_cs) sdc_deselect(); + return rv; + } + rv = sdc_xchg_cmd(cmd, arg, flags); + if (do_cs) sdc_deselect(); + return rv; +} + +static int sdc_acmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { + int rv; + uint32_t start; + + start = sdc_get_tick(); + rv = sdc_cmd(APP_CMD, 0, flags, timeout); + if (rv & ~SDC_R1_IDLE_STATE) return rv; + + if (flags & SDC_CMD_FLAG_NOCS) { + sdc_deselect(); + sdc_select(); + } + return sdc_cmd(cmd, arg, flags, sdc_nto(start, timeout)); +} + +int sdc_init(uint32_t timeout) { + int rv, i; + uint8_t _type; + uint8_t ocr[4]; + uint32_t start; + + start = sdc_get_tick(); + sdc_sleep(5); + for (i=10; i--;) sdc_xchg8(0xff); /* 80 dummy cycles */ + + rv = sdc_cmd(GO_IDLE_STATE, 0, SDC_CMD_FLAG_CRC, SDC_TIMEOUT_CMD); + if (rv != SDC_R1_IDLE_STATE) return SDC_RV2ERR(rv); + + sdc_select(); + rv = sdc_cmd(SEND_IF_COND, 0x1aa, SDC_CMD_FLAG_CRC | SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); + switch (rv) { + case SDC_R1_IDLE_STATE: + for (i=0; i<4; i++) { /* R7 response */ + ocr[i] = sdc_xchg8(0xff); + } + sdc_deselect(); + if (ocr[2] == 0x01 && ocr[3] == 0xaa) { /* Check voltage range: 2.7-3.6V */ + do { + rv = sdc_acmd(SD_APP_OP_COND, 0x40000000, 0, sdc_nto(start, timeout)); + } while (rv == SDC_R1_IDLE_STATE); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + + sdc_select(); + rv = sdc_cmd(READ_OCR, 0, SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); + if (rv == SDC_R1_READY) { + for (i=0; i<4; i++) { /* R7 response */ + ocr[i] = sdc_xchg8(0xff); + } + sdc_deselect(); + } else { + sdc_deselect(); + return SDC_RV2ERR(rv); + } + + _type = SDC_TYPE_SDC2; + if (ocr[0] & 0xc0) _type |= SDC_CAP_BLK; + } + break; + + case SDC_R1_IDLE_STATE | SDC_R1_ILLEGAL_CMD: + sdc_deselect(); + rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); + switch (rv) { + case SDC_R1_IDLE_STATE: + do { + rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); + } while (rv == SDC_R1_IDLE_STATE); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + case SDC_R1_READY: + _type = SDC_TYPE_SDC1; + break; + + default: + do { + rv = sdc_cmd(SEND_OP_COND, 0, 0, sdc_nto(start, timeout)); + } while (rv == SDC_R1_IDLE_STATE); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + _type = SDC_TYPE_MMC; + break; + + } + break; + + default: + sdc_deselect(); + return SDC_RV2ERR(rv); + } + + if (!(_type & SDC_CAP_BLK)) { + rv = sdc_cmd(SET_BLOCKLEN, 512, 0, sdc_nto(start, timeout)); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + } + + if (_type & SDC_TYPE_SDC) { + uint8_t csd[16]; + + sdc_select(); + rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); + if (rv == SDC_R1_READY) { + rv = sdc_block_read(csd, 16, sdc_nto(start, timeout)); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + if (rv) return rv; + +#ifdef SDC_DEBUG + printf("SDCARD CSD: "); + for (i=0; i<16; i++) { + printf("%.2x ", csd[i]); + } + printf("\n"); +#endif + if (csd[10] & 0x40) _type |= SDC_CAP_ERASE_EN; + } + + sdc_type = _type; + return SDC_OK; +} + +#include "board.h" +#include "spi.h" + +int sdc_init(uint8_t wakeup_cause) { + int rv; + + sdc_spi_set_div(SDC_SPI_DEV_SDC, 1024); // 100 - 400 kHz + + rv = sdc_spi_select(SDC_SPI_DEV_SDC); + if (rv) goto sdc_init_fin; + + rv = sdc_init(1000); + sdc_spi_deselect(); + +sdc_init_fin: + sdc_spi_set_div(SDC_SPI_DEV_SDC, SPI_DIV_SDC); + + return rv; +} + +uint8_t sdc_get_type(void) { + return sdc_type & SDC_TYPE_MASK; +} + +uint8_t sdc_get_cap(void) { + return sdc_type & SDC_CAP_MASK; +} + +int sdc_get_sect_count(uint32_t timeout, uint32_t *sectors) { + int rv; + uint8_t csd[16]; + uint32_t start; + + start = sdc_get_tick(); + sdc_select(); + rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, timeout); + if (rv == SDC_R1_READY) { + rv = sdc_block_read(csd, 16, sdc_nto(start, timeout)); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + if (rv) return rv; + + if ((csd[0] >> 6) == 1) { /* SDCv2 */ + *sectors = (csd[9] + (csd[8] << 8) + ((csd[7] & 0x3f) << 16) + 1) << 10; + } else { /* SDCv1 or MMC*/ + uint8_t n = (csd[5] & 0x0f) + (csd[10] >> 7) + ((csd[9] & 0x03) << 1) + 2; + *sectors = (csd[8] >> 6) + (csd[7] << 2) + ((csd[6] & 0x03) << 10) + 1; + *sectors = *sectors << (n - 9); + } + + return SDC_OK; +} + +int sdc_get_blk_size(uint32_t timeout, uint32_t *size) { + int rv; + uint8_t rbl[64]; /* SD Status or CSD register */ + uint32_t start; + + start = sdc_get_tick(); + sdc_select(); + if (sdc_type & SDC_TYPE_SDC2) { + rv = sdc_acmd(SD_STATUS, 0, SDC_CMD_FLAG_NOCS, timeout); + sdc_xchg8(0xff); /* R2 response */ + } else { + rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, timeout); + } + if (rv == SDC_R1_READY) { + rv = sdc_block_read(rbl, (sdc_type & SDC_TYPE_SDC2) ? 64 : 16, sdc_nto(start, timeout)); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + if (rv) return rv; + + if (sdc_type & SDC_TYPE_SDC2) { + *size = 16UL << (rbl[10] >> 4); + } else if (sdc_type & SDC_TYPE_SDC1) { + *size = (((rbl[10] & 0x3f) << 1) + (rbl[11] >> 7) + 1) << ((rbl[13] >> 6) - 1); + } else { + *size = (((rbl[10] & 0x7c) >> 2) + 1) * (((rbl[11] & 0x03) << 3) + (rbl[11] >> 5) + 1); + } + + return SDC_OK; +} + +int sdc_sync(uint32_t timeout) { + int rv; + + sdc_select(); + rv = sdc_ready(timeout); + sdc_deselect(); + + return rv; +} + +int sdc_erase(uint32_t blk_start, uint32_t blk_end, uint32_t timeout) { + int rv; + uint32_t start; + + if (!(sdc_type & SDC_TYPE_SDC)) return SDC_ERR; + if (!(sdc_type & SDC_CAP_ERASE_EN)) return SDC_ERR; + if (!(sdc_type & SDC_CAP_BLK)) { + blk_start *= 512; + blk_end *= 512; + } + + start = sdc_get_tick(); + rv = sdc_cmd(ERASE_WR_BLK_START, blk_start, 0, timeout); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + + rv = sdc_cmd(ERASE_WR_BLK_END, blk_end, 0, sdc_nto(start, timeout)); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + + rv = sdc_cmd(ERASE, 0, 0, sdc_nto(start, timeout)); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + + return sdc_sync(sdc_nto(start, timeout)); +} + +int sdc_sect_read(uint32_t sect, unsigned int count, uint8_t *buffer) { + int rv; + uint8_t cmd = ((count == 1) ? READ_SINGLE_BLOCK : READ_MULTIPLE_BLOCK); + + if (!(sdc_type & SDC_CAP_BLK)) sect *= 512; + + sdc_select(); + rv = sdc_cmd(cmd, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); + if (rv == SDC_R1_READY) { + int _rv = SDC_R1_READY; + + while (count) { + rv = sdc_block_read(buffer, 512, SDC_TIMEOUT_READ); + if (rv) break; + sdc_decrypt(sect, buffer); + buffer += 512; + count--; + } + if (cmd == READ_MULTIPLE_BLOCK) _rv = sdc_cmd(STOP_TRANSMISSION, 0, SDC_CMD_FLAG_NOCS | SDC_CMD_FLAG_NOWAIT | SDC_CMD_FLAG_RSTUFF, 0); + if (!rv && (_rv != SDC_R1_READY)) rv = SDC_RV2ERR(_rv); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + + return rv; +} + +int sdc_sect_write(uint32_t sect, unsigned int count, uint8_t *buffer) { + int rv; + + if (!(sdc_type & SDC_CAP_BLK)) sect *= 512; + + if (count == 1) { + sdc_select(); + rv = sdc_cmd(WRITE_BLOCK, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); + if (rv == SDC_R1_READY) { + sdc_encrypt(sect, buffer); + rv = sdc_block_write(SDC_TOKEN_START_BLK, buffer, 512, SDC_TIMEOUT_WRITE); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + } else { + if (sdc_type & SDC_TYPE_SDC) { + rv = sdc_acmd(SET_WR_BLK_ERASE_COUNT, count, 0, SDC_TIMEOUT_CMD); + if (rv != SDC_R1_READY) return SDC_RV2ERR(rv); + } + + sdc_select(); + rv = sdc_cmd(WRITE_MULTIPLE_BLOCK, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); + if (rv == SDC_R1_READY) { + int _rv; + + while (count) { + sdc_encrypt(sect, buffer); + rv = sdc_block_write(SDC_TOKEN_START_BLKM, buffer, 512, SDC_TIMEOUT_WRITE); + if (rv) break; + buffer += 512; + count--; + } + _rv = sdc_block_write(SDC_TOKEN_STOP_TRAN, NULL, 0, SDC_TIMEOUT_WRITE); + if (!rv && (_rv != SDC_R1_READY)) rv = SDC_RV2ERR(_rv); + } else { + rv = SDC_RV2ERR(rv); + } + sdc_deselect(); + } + + return rv; +} diff --git a/fw/fe310/eos/dev/drv/sdcard.h b/fw/fe310/eos/dev/drv/sdcard.h new file mode 100644 index 0000000..ec453f4 --- /dev/null +++ b/fw/fe310/eos/dev/drv/sdcard.h @@ -0,0 +1,22 @@ +#include + +#define SDC_TYPE_MMC 0x01 + +#define SDC_TYPE_SDC1 0x04 +#define SDC_TYPE_SDC2 0x08 +#define SDC_TYPE_SDC 0x0c +#define SDC_TYPE_MASK 0x0f + +#define SDC_CAP_BLK 0x10 +#define SDC_CAP_ERASE_EN 0x20 +#define SDC_CAP_MASK 0xf0 + +int sdc_init(uint32_t timeout); +uint8_t eos_sdc_type(void); +uint8_t eos_sdc_cap(void); +int eos_sdc_get_sect_count(uint32_t timeout, uint32_t *sectors); +int eos_sdc_get_blk_size(uint32_t timeout, uint32_t *size); +int eos_sdc_sync(uint32_t timeout); +int eos_sdc_erase(uint32_t blk_start, uint32_t blk_end, uint32_t timeout); +int eos_sdc_sect_read(uint32_t sect, unsigned int count, uint8_t *buffer); +int eos_sdc_sect_write(uint32_t sect, unsigned int count, uint8_t *buffer); diff --git a/fw/fe310/eos/dev/sdcard.c b/fw/fe310/eos/dev/sdcard.c deleted file mode 100644 index a2ee598..0000000 --- a/fw/fe310/eos/dev/sdcard.c +++ /dev/null @@ -1,545 +0,0 @@ -#include -#include -#include - -#include "eos.h" -#include "soc/timer.h" -#include "soc/spi.h" - -#include "spi.h" - -#include "sdc_crypto.h" -#include "sdcard.h" - -#define SDC_TIMEOUT_CMD 500 -#define SDC_TIMEOUT_READ 200 -#define SDC_TIMEOUT_WRITE 500 - -#define SDC_POLY_CRC7 0x09 -#define SDC_POLY_CRC16 0x1021 - -#define SDC_CMD_FLAG_CRC 0x01 -#define SDC_CMD_FLAG_NOCS 0x02 -#define SDC_CMD_FLAG_NOWAIT 0x04 -#define SDC_CMD_FLAG_RSTUFF 0x08 - -#define SDC_TOKEN_START_BLK 0xfe -#define SDC_TOKEN_START_BLKM 0xfc -#define SDC_TOKEN_STOP_TRAN 0xfd - -#define SDC_DRESP_MASK 0x1f -#define SDC_DRESP_ACCEPT 0x05 -#define SDC_DRESP_ERR_CRC 0x0b -#define SDC_DRESP_ERR_WRITE 0x0d - -#define SDC_R1_READY 0x00 - -#define SDC_R1_IDLE_STATE 0x01 -#define SDC_R1_ERASE_RESET 0x02 -#define SDC_R1_ILLEGAL_CMD 0x04 -#define SDC_R1_ERR_CMD_CRC 0x08 -#define SDC_R1_ERR_ERASE_SEQ 0x10 -#define SDC_R1_ERR_ADDR 0x20 -#define SDC_R1_ERR_PARAM 0x40 - -#define SDC_NCR 10 - -#define SDC_ERR(rv) ((rv < 0) ? rv : EOS_ERR) - -/* CMD */ -#define GO_IDLE_STATE 0 -#define SEND_OP_COND 1 -#define SEND_IF_COND 8 -#define SEND_CSD 9 -#define STOP_TRANSMISSION 12 -#define SET_BLOCKLEN 16 -#define READ_SINGLE_BLOCK 17 -#define READ_MULTIPLE_BLOCK 18 -#define WRITE_BLOCK 24 -#define WRITE_MULTIPLE_BLOCK 25 -#define ERASE_WR_BLK_START 32 -#define ERASE_WR_BLK_END 33 -#define ERASE 38 -#define APP_CMD 55 -#define READ_OCR 58 - -/* ACMD */ -#define SD_STATUS 13 -#define SET_WR_BLK_ERASE_COUNT 23 -#define SD_APP_OP_COND 41 - -static uint8_t sdc_type = 0; - -static uint8_t sdc_crc7(uint8_t crc, uint8_t b) { - int i; - - for (i=8; i--; b<<=1) { - crc <<= 1; - if ((b ^ crc) & 0x80) crc ^= SDC_POLY_CRC7; - } - return crc & 0x7f; -} - -static uint16_t sdc_crc16(uint16_t crc, uint8_t b) { - int i; - - crc = crc ^ ((uint16_t)b << 8); - for (i=8; i--;) { - if (crc & 0x8000) { - crc = (crc << 1) ^ SDC_POLY_CRC16; - } else { - crc <<= 1; - } - } - return crc; -} - -static uint32_t sdc_nto(uint32_t start, uint32_t timeout) { - uint32_t d = eos_time_delta_ms(start); - return (d > timeout) ? 0 : timeout - d; -} - -static uint8_t sdc_xchg8(uint8_t data) { - return eos_spi_xchg8(data, 0); -} - -static uint16_t sdc_xchg16(uint16_t data) { - return eos_spi_xchg16(data, 0); -} - -static uint32_t sdc_xchg32(uint32_t data) { - return eos_spi_xchg32(data, 0); -} - -static void sdc_buf_send(unsigned char *buffer, uint16_t len) { - int i; - - for (i=0; i> 24); - crc = sdc_crc7(crc, arg >> 16); - crc = sdc_crc7(crc, arg >> 8); - crc = sdc_crc7(crc, arg); - } - crc = (crc << 1) | 0x01; - sdc_xchg8(cmd); - sdc_xchg32(arg); - sdc_xchg8(crc); - if (flags & SDC_CMD_FLAG_RSTUFF) sdc_xchg8(0xff); - - i = SDC_NCR; - do { - ret = sdc_xchg8(0xff); - } while ((ret & 0x80) && --i); - if (ret & 0x80) return EOS_ERR_BUSY; - - return ret; -} - -static int sdc_ready(uint32_t timeout) { - uint8_t d = 0; - uint32_t start; - - if (timeout == 0) return EOS_ERR_BUSY; - - start = eos_time_get_tick(); - do { - if (eos_time_delta_ms(start) > timeout) break; - d = sdc_xchg8(0xff); - } while (d != 0xff); - if (d != 0xff) return EOS_ERR_BUSY; - - return EOS_OK; -} - -static int sdc_block_read(uint8_t *buffer, uint16_t len, uint32_t timeout) { - uint8_t token = 0xff; - uint32_t start; - - if (timeout == 0) return EOS_ERR_BUSY; - - start = eos_time_get_tick(); - do { - if (eos_time_delta_ms(start) > timeout) break; - token = sdc_xchg8(0xff); - } while (token == 0xff); - if (token == 0xff) return EOS_ERR_BUSY; - if (token != SDC_TOKEN_START_BLK) return EOS_ERR; - - sdc_buf_recv(buffer, len); - sdc_xchg16(0xffff); /* dummy CRC */ - - return EOS_OK; -} - -static int sdc_block_write(uint8_t token, uint8_t *buffer, uint16_t len, uint32_t timeout) { - uint8_t d; - int rv; - - rv = sdc_ready(timeout); - if (rv) return rv; - - sdc_xchg8(token); - if (buffer && len) { - sdc_buf_send(buffer, len); - sdc_xchg16(0xffff); /* dummy CRC */ - - d = sdc_xchg8(0xff); /* Response */ - if ((d & SDC_DRESP_MASK) != SDC_DRESP_ACCEPT) return EOS_ERR; - } - - return EOS_OK; -} - -static int sdc_cmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { - int do_cs = !(flags & SDC_CMD_FLAG_NOCS); - int do_wait = !(flags & SDC_CMD_FLAG_NOWAIT); - int rv = EOS_OK; - - if (do_cs) sdc_select(); - if (do_wait) rv = sdc_ready(timeout); - if (rv) { - if (do_cs) sdc_deselect(); - return rv; - } - rv = sdc_xchg_cmd(cmd, arg, flags); - if (do_cs) sdc_deselect(); - return rv; -} - -static int sdc_acmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { - int rv; - uint32_t start; - - start = eos_time_get_tick(); - rv = sdc_cmd(APP_CMD, 0, flags, timeout); - if (rv & ~SDC_R1_IDLE_STATE) return rv; - - if (flags & SDC_CMD_FLAG_NOCS) { - sdc_deselect(); - sdc_select(); - } - return sdc_cmd(cmd, arg, flags, sdc_nto(start, timeout)); -} - -static int sdc_init(uint32_t timeout) { - int rv, i; - uint8_t _type; - uint8_t ocr[4]; - uint32_t start; - - start = eos_time_get_tick(); - eos_time_sleep(100); - for (i=10; i--;) sdc_xchg8(0xff); /* 80 dummy cycles */ - - rv = sdc_cmd(GO_IDLE_STATE, 0, SDC_CMD_FLAG_CRC, SDC_TIMEOUT_CMD); - if (rv != SDC_R1_IDLE_STATE) return SDC_ERR(rv); - - sdc_select(); - rv = sdc_cmd(SEND_IF_COND, 0x1aa, SDC_CMD_FLAG_CRC | SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); - switch (rv) { - case SDC_R1_IDLE_STATE: - for (i=0; i<4; i++) { /* R7 response */ - ocr[i] = sdc_xchg8(0xff); - } - sdc_deselect(); - if (ocr[2] == 0x01 && ocr[3] == 0xaa) { /* Check voltage range: 2.7-3.6V */ - do { - rv = sdc_acmd(SD_APP_OP_COND, 0x40000000, 0, sdc_nto(start, timeout)); - } while (rv == SDC_R1_IDLE_STATE); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - - sdc_select(); - rv = sdc_cmd(READ_OCR, 0, SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); - if (rv == SDC_R1_READY) { - for (i=0; i<4; i++) { /* R7 response */ - ocr[i] = sdc_xchg8(0xff); - } - sdc_deselect(); - } else { - sdc_deselect(); - return SDC_ERR(rv); - } - - _type = EOS_SDC_TYPE_SDC2; - if (ocr[0] & 0xc0) _type |= EOS_SDC_CAP_BLK; - } - break; - - case SDC_R1_IDLE_STATE | SDC_R1_ILLEGAL_CMD: - sdc_deselect(); - rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); - switch (rv) { - case SDC_R1_IDLE_STATE: - do { - rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); - } while (rv == SDC_R1_IDLE_STATE); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - case SDC_R1_READY: - _type = EOS_SDC_TYPE_SDC1; - break; - - default: - do { - rv = sdc_cmd(SEND_OP_COND, 0, 0, sdc_nto(start, timeout)); - } while (rv == SDC_R1_IDLE_STATE); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - _type = EOS_SDC_TYPE_MMC; - break; - - } - break; - - default: - sdc_deselect(); - return SDC_ERR(rv); - } - - if (!(_type & EOS_SDC_CAP_BLK)) { - rv = sdc_cmd(SET_BLOCKLEN, 512, 0, sdc_nto(start, timeout)); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - } - - if (_type & EOS_SDC_TYPE_SDC) { - uint8_t csd[16]; - - sdc_select(); - rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); - if (rv == SDC_R1_READY) { - rv = sdc_block_read(csd, 16, sdc_nto(start, timeout)); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - if (rv) return rv; - - for (i=0; i<16; i++) { - printf("%.2x ", csd[i]); - } - printf("\n"); - if (csd[10] & 0x40) _type |= EOS_SDC_CAP_ERASE_EN; - } - - eos_spi_set_div(EOS_SPI_DEV_SDC, 5); - sdc_type = _type; - return EOS_OK; -} - -int eos_sdc_init(uint8_t wakeup_cause) { - int rv; - - rv = eos_spi_select(EOS_SPI_DEV_SDC); - if (rv) return rv; - - rv = sdc_init(5000); - if (rv) { - printf("SDC ERROR\n"); - } else { - printf("SDC OK:%x\n", sdc_type); - } - eos_spi_deselect(); - - return EOS_OK; -} - -uint8_t eos_sdc_type(void) { - return sdc_type & EOS_SDC_TYPE_MASK; -} - -uint8_t eos_sdc_cap(void) { - return sdc_type & EOS_SDC_CAP_MASK; -} - -int eos_sdc_get_sect_count(uint32_t timeout, uint32_t *sectors) { - int rv; - uint8_t csd[16]; - uint32_t start; - - start = eos_time_get_tick(); - sdc_select(); - rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, timeout); - if (rv == SDC_R1_READY) { - rv = sdc_block_read(csd, 16, sdc_nto(start, timeout)); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - if (rv) return rv; - - if ((csd[0] >> 6) == 1) { /* SDCv2 */ - *sectors = (csd[9] + (csd[8] << 8) + ((csd[7] & 0x3f) << 16) + 1) << 10; - } else { /* SDCv1 or MMC*/ - uint8_t n = (csd[5] & 0x0f) + (csd[10] >> 7) + ((csd[9] & 0x03) << 1) + 2; - *sectors = (csd[8] >> 6) + (csd[7] << 2) + ((csd[6] & 0x03) << 10) + 1; - *sectors = *sectors << (n - 9); - } - - return EOS_OK; -} - -int eos_sdc_get_blk_size(uint32_t timeout, uint32_t *size) { - int rv; - uint8_t rbl[64]; /* SD Status or CSD register */ - uint32_t start; - - start = eos_time_get_tick(); - sdc_select(); - if (sdc_type & EOS_SDC_TYPE_SDC2) { - rv = sdc_acmd(SD_STATUS, 0, SDC_CMD_FLAG_NOCS, timeout); - sdc_xchg8(0xff); /* R2 response */ - } else { - rv = sdc_cmd(SEND_CSD, 0, SDC_CMD_FLAG_NOCS, timeout); - } - if (rv == SDC_R1_READY) { - rv = sdc_block_read(rbl, (sdc_type & EOS_SDC_TYPE_SDC2) ? 64 : 16, sdc_nto(start, timeout)); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - if (rv) return rv; - - if (sdc_type & EOS_SDC_TYPE_SDC2) { - *size = 16UL << (rbl[10] >> 4); - } else if (sdc_type & EOS_SDC_TYPE_SDC1) { - *size = (((rbl[10] & 0x3f) << 1) + (rbl[11] >> 7) + 1) << ((rbl[13] >> 6) - 1); - } else { - *size = (((rbl[10] & 0x7c) >> 2) + 1) * (((rbl[11] & 0x03) << 3) + (rbl[11] >> 5) + 1); - } - - return EOS_OK; -} - -int eos_sdc_sync(uint32_t timeout) { - int rv; - - sdc_select(); - rv = sdc_ready(timeout); - sdc_deselect(); - - return rv; -} - -int eos_sdc_erase(uint32_t blk_start, uint32_t blk_end, uint32_t timeout) { - int rv; - uint32_t start; - - if (!(sdc_type & EOS_SDC_TYPE_SDC)) return EOS_ERR; - if (!(sdc_type & EOS_SDC_CAP_ERASE_EN)) return EOS_ERR; - if (!(sdc_type & EOS_SDC_CAP_BLK)) { - blk_start *= 512; - blk_end *= 512; - } - - start = eos_time_get_tick(); - rv = sdc_cmd(ERASE_WR_BLK_START, blk_start, 0, timeout); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - - rv = sdc_cmd(ERASE_WR_BLK_END, blk_end, 0, sdc_nto(start, timeout)); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - - rv = sdc_cmd(ERASE, 0, 0, sdc_nto(start, timeout)); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - - return eos_sdc_sync(sdc_nto(start, timeout)); -} - -int eos_sdc_sect_read(uint32_t sect, unsigned int count, uint8_t *buffer) { - int rv; - uint8_t cmd = ((count == 1) ? READ_SINGLE_BLOCK : READ_MULTIPLE_BLOCK); - - if (!(sdc_type & EOS_SDC_CAP_BLK)) sect *= 512; - - sdc_select(); - rv = sdc_cmd(cmd, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); - if (rv == SDC_R1_READY) { - int _rv = SDC_R1_READY; - - while (count) { - rv = sdc_block_read(buffer, 512, SDC_TIMEOUT_READ); - if (rv) break; - eos_sdcc_decrypt(sect, buffer); - buffer += 512; - count--; - } - if (cmd == READ_MULTIPLE_BLOCK) _rv = sdc_cmd(STOP_TRANSMISSION, 0, SDC_CMD_FLAG_NOCS | SDC_CMD_FLAG_NOWAIT | SDC_CMD_FLAG_RSTUFF, 0); - if (!rv && (_rv != SDC_R1_READY)) rv = SDC_ERR(_rv); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - - return rv; -} - -int eos_sdc_sect_write(uint32_t sect, unsigned int count, uint8_t *buffer) { - int rv; - - if (!(sdc_type & EOS_SDC_CAP_BLK)) sect *= 512; - - if (count == 1) { - sdc_select(); - rv = sdc_cmd(WRITE_BLOCK, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); - if (rv == SDC_R1_READY) { - eos_sdcc_encrypt(sect, buffer); - rv = sdc_block_write(SDC_TOKEN_START_BLK, buffer, 512, SDC_TIMEOUT_WRITE); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - } else { - if (sdc_type & EOS_SDC_TYPE_SDC) { - rv = sdc_acmd(SET_WR_BLK_ERASE_COUNT, count, 0, SDC_TIMEOUT_CMD); - if (rv != SDC_R1_READY) return SDC_ERR(rv); - } - - sdc_select(); - rv = sdc_cmd(WRITE_MULTIPLE_BLOCK, sect, SDC_CMD_FLAG_NOCS, SDC_TIMEOUT_CMD); - if (rv == SDC_R1_READY) { - int _rv; - - while (count) { - eos_sdcc_encrypt(sect, buffer); - rv = sdc_block_write(SDC_TOKEN_START_BLKM, buffer, 512, SDC_TIMEOUT_WRITE); - if (rv) break; - buffer += 512; - count--; - } - _rv = sdc_block_write(SDC_TOKEN_STOP_TRAN, NULL, 0, SDC_TIMEOUT_WRITE); - if (!rv && (_rv != SDC_R1_READY)) rv = SDC_ERR(_rv); - } else { - rv = SDC_ERR(rv); - } - sdc_deselect(); - } - - return rv; -} diff --git a/fw/fe310/eos/dev/sdcard.h b/fw/fe310/eos/dev/sdcard.h deleted file mode 100644 index 910a6e0..0000000 --- a/fw/fe310/eos/dev/sdcard.h +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#define EOS_SDC_TYPE_MMC 0x01 - -#define EOS_SDC_TYPE_SDC1 0x04 -#define EOS_SDC_TYPE_SDC2 0x08 -#define EOS_SDC_TYPE_SDC 0x0c -#define EOS_SDC_TYPE_MASK 0x0f - -#define EOS_SDC_CAP_BLK 0x10 -#define EOS_SDC_CAP_ERASE_EN 0x20 -#define EOS_SDC_CAP_MASK 0xf0 - -int eos_sdc_init(uint8_t wakeup_cause); -uint8_t eos_sdc_type(void); -uint8_t eos_sdc_cap(void); -int eos_sdc_get_sect_count(uint32_t timeout, uint32_t *sectors); -int eos_sdc_get_blk_size(uint32_t timeout, uint32_t *size); -int eos_sdc_sync(uint32_t timeout); -int eos_sdc_erase(uint32_t blk_start, uint32_t blk_end, uint32_t timeout); -int eos_sdc_sect_read(uint32_t sect, unsigned int count, uint8_t *buffer); -int eos_sdc_sect_write(uint32_t sect, unsigned int count, uint8_t *buffer); -- cgit v1.2.3