diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/imx233/debug-imx233.c | 62 | ||||
-rw-r--r-- | firmware/target/arm/imx233/sdmmc-imx233.c | 71 |
2 files changed, 127 insertions, 6 deletions
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c index edb84b990a..2d0150e33d 100644 --- a/firmware/target/arm/imx233/debug-imx233.c +++ b/firmware/target/arm/imx233/debug-imx233.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include "stdio.h" | 43 | #include "stdio.h" |
44 | #include "button.h" | 44 | #include "button.h" |
45 | #include "button-imx233.h" | 45 | #include "button-imx233.h" |
46 | #include "sdmmc-imx233.h" | ||
47 | #include "storage.h" | ||
46 | 48 | ||
47 | #include "regs/usbphy.h" | 49 | #include "regs/usbphy.h" |
48 | #include "regs/timrot.h" | 50 | #include "regs/timrot.h" |
@@ -1190,6 +1192,65 @@ bool dbg_hw_info_button(void) | |||
1190 | } | 1192 | } |
1191 | } | 1193 | } |
1192 | 1194 | ||
1195 | bool dbg_hw_info_sdmmc(void) | ||
1196 | { | ||
1197 | lcd_setfont(FONT_SYSFIXED); | ||
1198 | |||
1199 | while(1) | ||
1200 | { | ||
1201 | int button = my_get_action(HZ / 10); | ||
1202 | switch(button) | ||
1203 | { | ||
1204 | case ACT_NEXT: | ||
1205 | case ACT_PREV: | ||
1206 | case ACT_OK: | ||
1207 | lcd_setfont(FONT_UI); | ||
1208 | return true; | ||
1209 | case ACT_CANCEL: | ||
1210 | lcd_setfont(FONT_UI); | ||
1211 | return false; | ||
1212 | } | ||
1213 | |||
1214 | lcd_clear_display(); | ||
1215 | int line = 0; | ||
1216 | #if CONFIG_STORAGE & STORAGE_MMC | ||
1217 | int mmc_idx = 0; | ||
1218 | #endif | ||
1219 | #if CONFIG_STORAGE & STORAGE_SD | ||
1220 | int sd_idx = 0; | ||
1221 | #endif | ||
1222 | for(int drive = 0; drive < storage_num_drives(); drive++) | ||
1223 | { | ||
1224 | struct sdmmc_info_t info; | ||
1225 | if(false) {} | ||
1226 | #if CONFIG_STORAGE & STORAGE_MMC | ||
1227 | else if(storage_driver_type(drive) == STORAGE_MMC_NUM) | ||
1228 | info = imx233_mmc_get_info(mmc_idx++); | ||
1229 | #endif | ||
1230 | #if CONFIG_STORAGE & STORAGE_SD | ||
1231 | else if(storage_driver_type(drive) == STORAGE_SD_NUM) | ||
1232 | info = imx233_sd_get_info(sd_idx++); | ||
1233 | #endif | ||
1234 | else | ||
1235 | continue; | ||
1236 | lcd_putsf(0, line++, "%s", info.slot_name); | ||
1237 | #ifdef HAVE_HOTSWAP | ||
1238 | bool removable = storage_removable(info.drive); | ||
1239 | bool present = storage_present(info.drive); | ||
1240 | if(removable) | ||
1241 | lcd_putsf(0, line++, " removable %spresent", present ? "" : "not "); | ||
1242 | if(!present) | ||
1243 | continue; | ||
1244 | #endif | ||
1245 | lcd_putsf(0, line++, " bus: %d sbc: %d", info.bus_width, info.has_sbc); | ||
1246 | lcd_putsf(0, line++, " hs: %s", info.hs_enabled ? "enabled" : | ||
1247 | info.hs_capable ? "disabled" : "not capable"); | ||
1248 | } | ||
1249 | lcd_update(); | ||
1250 | yield(); | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1193 | static struct | 1254 | static struct |
1194 | { | 1255 | { |
1195 | const char *name; | 1256 | const char *name; |
@@ -1215,6 +1276,7 @@ static struct | |||
1215 | {"audio", dbg_hw_info_audio}, | 1276 | {"audio", dbg_hw_info_audio}, |
1216 | {"timrot", dbg_hw_info_timrot}, | 1277 | {"timrot", dbg_hw_info_timrot}, |
1217 | {"button", dbg_hw_info_button}, | 1278 | {"button", dbg_hw_info_button}, |
1279 | {"sdmmc", dbg_hw_info_sdmmc}, | ||
1218 | {"target", dbg_hw_target_info}, | 1280 | {"target", dbg_hw_target_info}, |
1219 | }; | 1281 | }; |
1220 | 1282 | ||
diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c index 4296720810..13ef1b8375 100644 --- a/firmware/target/arm/imx233/sdmmc-imx233.c +++ b/firmware/target/arm/imx233/sdmmc-imx233.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #error SD/MMC mismatch | 55 | #error SD/MMC mismatch |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | /* static configuration */ | ||
58 | struct sdmmc_config_t | 59 | struct sdmmc_config_t |
59 | { | 60 | { |
60 | const char *name; /* name(for debug) */ | 61 | const char *name; /* name(for debug) */ |
@@ -85,7 +86,7 @@ struct sdmmc_config_t | |||
85 | #define PIN2BANK(v) ((v) >> 5) | 86 | #define PIN2BANK(v) ((v) >> 5) |
86 | #define PIN2PIN(v) ((v) & 0x1f) | 87 | #define PIN2PIN(v) ((v) & 0x1f) |
87 | 88 | ||
88 | struct sdmmc_config_t sdmmc_config[] = | 89 | const struct sdmmc_config_t sdmmc_config[] = |
89 | { | 90 | { |
90 | #ifdef SANSA_FUZEPLUS | 91 | #ifdef SANSA_FUZEPLUS |
91 | /* The Fuze+ uses pin #B0P8 for power */ | 92 | /* The Fuze+ uses pin #B0P8 for power */ |
@@ -181,6 +182,15 @@ struct sdmmc_config_t sdmmc_config[] = | |||
181 | #endif | 182 | #endif |
182 | }; | 183 | }; |
183 | 184 | ||
185 | /* drive status */ | ||
186 | struct sdmmc_status_t | ||
187 | { | ||
188 | int bus_width; /* bus width (1, 4 or 8) */ | ||
189 | bool hs_capable; /* HS capable device */ | ||
190 | bool hs_enabled; /* HS enabled */ | ||
191 | bool has_sbc; /* support SET_BLOCK_COUNT */ | ||
192 | }; | ||
193 | |||
184 | #define SDMMC_NUM_DRIVES (sizeof(sdmmc_config) / sizeof(sdmmc_config[0])) | 194 | #define SDMMC_NUM_DRIVES (sizeof(sdmmc_config) / sizeof(sdmmc_config[0])) |
185 | 195 | ||
186 | #define SDMMC_CONF(drive) sdmmc_config[drive] | 196 | #define SDMMC_CONF(drive) sdmmc_config[drive] |
@@ -200,11 +210,12 @@ static uint8_t aligned_buffer[SDMMC_NUM_DRIVES][512] CACHEALIGN_ATTR; | |||
200 | static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; | 210 | static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; |
201 | static struct mutex mutex[SDMMC_NUM_DRIVES]; | 211 | static struct mutex mutex[SDMMC_NUM_DRIVES]; |
202 | static int disk_last_activity[SDMMC_NUM_DRIVES]; | 212 | static int disk_last_activity[SDMMC_NUM_DRIVES]; |
203 | static bool support_set_block_count[SDMMC_NUM_DRIVES]; | 213 | static struct sdmmc_status_t sdmmc_status[SDMMC_NUM_DRIVES]; |
204 | #define MIN_YIELD_PERIOD 5 | 214 | #define MIN_YIELD_PERIOD 5 |
205 | 215 | ||
206 | #define SDMMC_INFO(drive) sdmmc_card_info[drive] | 216 | #define SDMMC_INFO(drive) sdmmc_card_info[drive] |
207 | #define SDMMC_RCA(drive) SDMMC_INFO(drive).rca | 217 | #define SDMMC_RCA(drive) SDMMC_INFO(drive).rca |
218 | #define SDMMC_STATUS(drive) sdmmc_status[drive] | ||
208 | 219 | ||
209 | /* sd only */ | 220 | /* sd only */ |
210 | static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | 221 | static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; |
@@ -425,6 +436,7 @@ static int init_sd_card(int drive) | |||
425 | 436 | ||
426 | /* Switch to 4-bit */ | 437 | /* Switch to 4-bit */ |
427 | imx233_ssp_set_bus_width(ssp, 4); | 438 | imx233_ssp_set_bus_width(ssp, 4); |
439 | SDMMC_STATUS(drive).bus_width = 4; | ||
428 | 440 | ||
429 | /* Try to switch V2 cards to HS timings, non HS seem to ignore this */ | 441 | /* Try to switch V2 cards to HS timings, non HS seem to ignore this */ |
430 | if(sd_v2) | 442 | if(sd_v2) |
@@ -441,7 +453,7 @@ static int init_sd_card(int drive) | |||
441 | } | 453 | } |
442 | 454 | ||
443 | /* probe for CMD23 support */ | 455 | /* probe for CMD23 support */ |
444 | support_set_block_count[drive] = false; | 456 | SDMMC_STATUS(drive).has_sbc = false; |
445 | /* ACMD51, only transfer 8 bytes */ | 457 | /* ACMD51, only transfer 8 bytes */ |
446 | imx233_ssp_set_block_size(ssp, /*log2(8)*/3); | 458 | imx233_ssp_set_block_size(ssp, /*log2(8)*/3); |
447 | if(send_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, &resp)) | 459 | if(send_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, &resp)) |
@@ -450,7 +462,7 @@ static int init_sd_card(int drive) | |||
450 | aligned_buffer[drive], 1, true, true, NULL) == SSP_SUCCESS) | 462 | aligned_buffer[drive], 1, true, true, NULL) == SSP_SUCCESS) |
451 | { | 463 | { |
452 | if(aligned_buffer[drive][3] & 2) | 464 | if(aligned_buffer[drive][3] & 2) |
453 | support_set_block_count[drive] = true; | 465 | SDMMC_STATUS(drive).has_sbc = true; |
454 | } | 466 | } |
455 | } | 467 | } |
456 | imx233_ssp_set_block_size(ssp, /*log2(512)*/9); | 468 | imx233_ssp_set_block_size(ssp, /*log2(512)*/9); |
@@ -458,6 +470,8 @@ static int init_sd_card(int drive) | |||
458 | /* SSPCLK @ 96MHz | 470 | /* SSPCLK @ 96MHz |
459 | * gives bitrate of 96 / 4 / 1 = 24MHz | 471 | * gives bitrate of 96 / 4 / 1 = 24MHz |
460 | * gives bitrate of 96 / 2 / 1 = 48MHz */ | 472 | * gives bitrate of 96 / 2 / 1 = 48MHz */ |
473 | SDMMC_STATUS(drive).hs_capable = sd_hs; | ||
474 | SDMMC_STATUS(drive).hs_enabled = false; | ||
461 | if(/*sd_hs*/false) | 475 | if(/*sd_hs*/false) |
462 | imx233_ssp_set_timings(ssp, 2, 0, 0xffff); | 476 | imx233_ssp_set_timings(ssp, 2, 0, 0xffff); |
463 | else | 477 | else |
@@ -534,6 +548,9 @@ static int init_mmc_drive(int drive) | |||
534 | /* SSPCLK @ 96MHz | 548 | /* SSPCLK @ 96MHz |
535 | * gives bitrate of 96 / 2 / 1 = 48MHz */ | 549 | * gives bitrate of 96 / 2 / 1 = 48MHz */ |
536 | imx233_ssp_set_timings(ssp, 2, 0, 0xffff); | 550 | imx233_ssp_set_timings(ssp, 2, 0, 0xffff); |
551 | SDMMC_STATUS(drive).bus_width = 8; | ||
552 | SDMMC_STATUS(drive).hs_capable = true; | ||
553 | SDMMC_STATUS(drive).hs_enabled = true; | ||
537 | 554 | ||
538 | /* read extended CSD */ | 555 | /* read extended CSD */ |
539 | { | 556 | { |
@@ -549,7 +566,7 @@ static int init_mmc_drive(int drive) | |||
549 | return -13; | 566 | return -13; |
550 | 567 | ||
551 | /* MMC always support CMD23 */ | 568 | /* MMC always support CMD23 */ |
552 | support_set_block_count[drive] = false; | 569 | SDMMC_STATUS(drive).has_sbc = false; |
553 | SDMMC_INFO(drive).initialized = 1; | 570 | SDMMC_INFO(drive).initialized = 1; |
554 | 571 | ||
555 | return 0; | 572 | return 0; |
@@ -565,7 +582,7 @@ static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, | |||
565 | { | 582 | { |
566 | int this_count = MIN(count, IMX233_MAX_SINGLE_DMA_XFER_SIZE / 512); | 583 | int this_count = MIN(count, IMX233_MAX_SINGLE_DMA_XFER_SIZE / 512); |
567 | bool need_stop = true; | 584 | bool need_stop = true; |
568 | if(support_set_block_count[drive] && send_cmd(drive, 23, this_count, MCI_RESP, &resp)) | 585 | if(SDMMC_STATUS(drive).has_sbc && send_cmd(drive, 23, this_count, MCI_RESP, &resp)) |
569 | need_stop = false; | 586 | need_stop = false; |
570 | /* Set bank_start to the correct unit (blocks or bytes). | 587 | /* Set bank_start to the correct unit (blocks or bytes). |
571 | * MMC drives use block addressing, SD cards bytes or blocks */ | 588 | * MMC drives use block addressing, SD cards bytes or blocks */ |
@@ -1070,3 +1087,45 @@ tCardInfo *mmc_card_info(int card_no) | |||
1070 | } | 1087 | } |
1071 | 1088 | ||
1072 | #endif | 1089 | #endif |
1090 | |||
1091 | /** Information about SD/MMC slot */ | ||
1092 | struct sdmmc_info_t | ||
1093 | { | ||
1094 | int drive; /* drive number (for queries like storage_removable(drive) */ | ||
1095 | const char *slot_name; /* name of the slot: 'internal' or 'microsd' */ | ||
1096 | bool window; /* is window enabled for this slot? */ | ||
1097 | int bus_width; /* current bus width */ | ||
1098 | bool hs_capable; /* is device high-speed capable? */ | ||
1099 | bool hs_enabled; /* is high-speed enabled? */ | ||
1100 | bool has_sbc; /* device support SET_BLOCK_COUNT */ | ||
1101 | }; | ||
1102 | |||
1103 | struct sdmmc_info_t imx233_sdmmc_get_info(int drive, int storage_drive) | ||
1104 | { | ||
1105 | struct sdmmc_info_t info; | ||
1106 | memset(&info, 0, sizeof(info)); | ||
1107 | info.drive = storage_drive; | ||
1108 | info.slot_name = SDMMC_CONF(drive).name; | ||
1109 | info.window = !!(SDMMC_CONF(drive).flags & WINDOW); | ||
1110 | info.bus_width = SDMMC_STATUS(drive).bus_width; | ||
1111 | info.hs_capable = SDMMC_STATUS(drive).hs_capable; | ||
1112 | info.hs_enabled = SDMMC_STATUS(drive).hs_enabled; | ||
1113 | info.has_sbc = SDMMC_STATUS(drive).has_sbc; | ||
1114 | return info; | ||
1115 | } | ||
1116 | |||
1117 | #if CONFIG_STORAGE & STORAGE_SD | ||
1118 | /* return information about a particular sd device (use regular drive number) */ | ||
1119 | struct sdmmc_info_t imx233_sd_get_info(int card_no) | ||
1120 | { | ||
1121 | return imx233_sdmmc_get_info(sd_map[card_no], sd_first_drive + card_no); | ||
1122 | } | ||
1123 | #endif | ||
1124 | |||
1125 | #if CONFIG_STORAGE & STORAGE_MMC | ||
1126 | /* return information about a particular mmc device (use regular drive number) */ | ||
1127 | struct sdmmc_info_t imx233_mmc_get_info(int card_no) | ||
1128 | { | ||
1129 | return imx233_sdmmc_get_info(mmc_map[card_no], mmc_first_drive + card_no); | ||
1130 | } | ||
1131 | #endif | ||