diff --git a/bootloader/imx233.c b/bootloader/imx233.c index bec8ceec5b..f6c5ad9cf4 100644 --- a/bootloader/imx233.c +++ b/bootloader/imx233.c @@ -40,8 +40,8 @@ #include "usb.h" -void main(void) NORETURN_ATTR; -void main(void) +void main(uint32_t arg) NORETURN_ATTR; +void main(uint32_t arg) { unsigned char* loadbuffer; int buffer_size; @@ -62,6 +62,8 @@ void main(void) button_init_device(); //button_debug_screen(); + printf("arg=%c%c%c%c", arg >> 24, + (arg >> 16) & 0xff, (arg >> 8) & 0xff, (arg & 0xff)); ret = storage_init(); if(ret < 0) @@ -84,6 +86,9 @@ void main(void) error(EDISK, ret, true); } + if(button_read_device() & BUTTON_VOL_UP) + printf("Booting from SD card required."); + printf("Loading firmware"); loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */ diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h index e0dc76a766..4c3cd6014b 100644 --- a/firmware/export/config/sansafuzeplus.h +++ b/firmware/export/config/sansafuzeplus.h @@ -118,13 +118,9 @@ #define HAVE_FLASH_STORAGE /* define this if the flash memory uses the SecureDigital Memory Card protocol */ -#ifdef BOOTLOADER -# define CONFIG_STORAGE STORAGE_MMC -#else -# define CONFIG_STORAGE (STORAGE_SD | STORAGE_MMC) -# define NUM_DRIVES 2 -# define HAVE_HOTSWAP -#endif +#define CONFIG_STORAGE (STORAGE_SD | STORAGE_MMC) +#define NUM_DRIVES 2 +#define HAVE_HOTSWAP /* todo */ #define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */ diff --git a/firmware/target/arm/imx233/mmc-imx233.c b/firmware/target/arm/imx233/mmc-imx233.c index b0f1f36c26..889ba0cb82 100644 --- a/firmware/target/arm/imx233/mmc-imx233.c +++ b/firmware/target/arm/imx233/mmc-imx233.c @@ -25,7 +25,6 @@ #include "storage.h" #include "ssp-imx233.h" #include "pinctrl-imx233.h" -#include "button-target.h" /** * This code assumes a single eMMC internal flash @@ -216,3 +215,9 @@ int mmc_write_sectors(IF_MD2(int drive,) unsigned long start, int count, const v (void) buf; return -1; } + +bool mmc_present(IF_MD(int drive)) +{ + IF_MD((void) drive); + return true; +} diff --git a/firmware/target/arm/imx233/sd-imx233.c b/firmware/target/arm/imx233/sd-imx233.c index ccd8bf35c1..5e9f2cf030 100644 --- a/firmware/target/arm/imx233/sd-imx233.c +++ b/firmware/target/arm/imx233/sd-imx233.c @@ -22,9 +22,54 @@ #include "system.h" #include "sd.h" #include "sdmmc.h" +#include "ssp-imx233.h" +#include "pinctrl-imx233.h" +#include "button-target.h" + +/** + * This code assumes a single SD card slot + */ + +#ifdef SANSA_FUZEPLUS +#define SD_SSP 1 +#else +#error You need to configure the ssp to use +#endif + +static tCardInfo card_info; +static struct mutex sd_mutex; + +static void sd_detect_callback(int ssp) +{ + (void)ssp; + + /* This is called only if the state was stable for 300ms - check state + * and post appropriate event. */ + if(imx233_ssp_sdmmc_detect(SD_SSP)) + queue_broadcast(SYS_HOTSWAP_INSERTED, 0); + else + queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); + printf("sd_detect_callback(%d)", imx233_ssp_sdmmc_detect(SD_SSP)); + imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); +} int sd_init(void) { + mutex_init(&sd_mutex); + + imx233_ssp_start(SD_SSP); + imx233_ssp_softreset(SD_SSP); + imx233_ssp_set_mode(SD_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC); + #ifdef SANSA_FUZEPLUS + imx233_ssp_setup_ssp1_sd_mmc_pins(true, 4, PINCTRL_DRIVE_8mA, false); + #endif + imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); + /* SSPCLK @ 96MHz + * gives bitrate of 96000 / 240 / 1 = 400kHz */ + imx233_ssp_set_timings(SD_SSP, 240, 0, 0xffff); + imx233_ssp_set_bus_width(SD_SSP, 1); + imx233_ssp_set_block_size(SD_SSP, 9); + return 0; } @@ -57,6 +102,12 @@ tCardInfo *card_get_info_target(int card_no) int sd_num_drives(int first_drive) { (void) first_drive; - return 0; + return 1; +} + +bool sd_present(IF_MD(int drive)) +{ + IF_MD((void) drive); + return imx233_ssp_sdmmc_detect(SD_SSP); } diff --git a/firmware/target/arm/imx233/ssp-imx233.c b/firmware/target/arm/imx233/ssp-imx233.c index 59405bbdc2..c3ce8a8f58 100644 --- a/firmware/target/arm/imx233/ssp-imx233.c +++ b/firmware/target/arm/imx233/ssp-imx233.c @@ -44,6 +44,7 @@ static struct semaphore ssp_sema[2]; static struct ssp_dma_command_t ssp_dma_cmd[2]; static uint32_t ssp_bus_width[2]; static unsigned ssp_log_block_size[2]; +static ssp_detect_cb_t ssp_detect_cb[2]; void INT_SSP(int ssp) { @@ -146,22 +147,7 @@ static void setup_ssp_sd_pins(int ssp) if(ssp == 1) { - /* SSP_SCK: drive 8mA */ - imx233_set_pin_drive_strength(2, 6, PINCTRL_DRIVE_8mA); - /* SSP_{SCK,DATA{3,2,1,0},DETECT,CMD} */ - imx233_set_pin_function(2, 6, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 5, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 4, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 3, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 2, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 1, PINCTRL_FUNCTION_MAIN); - imx233_set_pin_function(2, 0, PINCTRL_FUNCTION_MAIN); - /* SSP_CMD: pullup */ - imx233_enable_pin_pullup(2, 0, true); - imx233_enable_pin_pullup(2, 2, true); - imx233_enable_pin_pullup(2, 3, true); - imx233_enable_pin_pullup(2, 4, true); - imx233_enable_pin_pullup(2, 5, true); + } else { @@ -170,6 +156,41 @@ static void setup_ssp_sd_pins(int ssp) } #endif +void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width, + unsigned drive_strength, bool use_alt) +{ + /* SSP_{CMD,SCK} */ + imx233_set_pin_drive_strength(2, 0, drive_strength); + imx233_set_pin_drive_strength(2, 6, drive_strength); + imx233_set_pin_function(2, 0, PINCTRL_FUNCTION_MAIN); + imx233_set_pin_function(2, 6, PINCTRL_FUNCTION_MAIN); + imx233_enable_pin_pullup(2, 0, enable_pullups); + /* SSP_DATA{0-3} */ + for(unsigned i = 0; i < MIN(bus_width, 4); i++) + { + imx233_set_pin_drive_strength(2, 2 + i, drive_strength); + imx233_set_pin_function(2, 2 + i, PINCTRL_FUNCTION_MAIN); + imx233_enable_pin_pullup(2, 2 + i, enable_pullups); + } + + /* SSP_DATA{4-7} */ + for(unsigned i = 4; i < bus_width; i++) + { + if(use_alt) + { + imx233_set_pin_drive_strength(0, 22 + i, drive_strength); + imx233_set_pin_function(0, 22 + i, PINCTRL_FUNCTION_ALT2); + imx233_enable_pin_pullup(0, 22 + i, enable_pullups); + } + else + { + imx233_set_pin_drive_strength(0, 4 + i, drive_strength); + imx233_set_pin_function(0, 4 + i, PINCTRL_FUNCTION_ALT2); + imx233_enable_pin_pullup(0, 4 + i, enable_pullups); + } + } +} + void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width, unsigned drive_strength) { @@ -301,3 +322,52 @@ void imx233_ssp_sd_mmc_power_up_sequence(int ssp) mdelay(1); __REG_CLR(HW_SSP_CMD0(ssp)) = HW_SSP_CMD0__CONT_CLKING_EN; } + +static int ssp_detect_oneshot_callback(int ssp) +{ + printf("ssp_detect_oneshot_callback(%d)", ssp); + if(ssp_detect_cb[ssp - 1]) + ssp_detect_cb[ssp - 1](ssp); + + return 0; +} + +static int ssp1_detect_oneshot_callback(struct timeout *tmo) +{ + (void) tmo; + return ssp_detect_oneshot_callback(1); +} + +static int ssp2_detect_oneshot_callback(struct timeout *tmo) +{ + (void) tmo; + return ssp_detect_oneshot_callback(2); +} + +static void detect_irq(int bank, int pin) +{ + static struct timeout ssp1_detect_oneshot; + static struct timeout ssp2_detect_oneshot; + if(bank == 2 && pin == 1) + timeout_register(&ssp1_detect_oneshot, ssp1_detect_oneshot_callback, (3*HZ/10), 0); + else if(bank == 0 && pin == 19) + timeout_register(&ssp2_detect_oneshot, ssp2_detect_oneshot_callback, (3*HZ/10), 0); +} + +void imx233_ssp_sdmmc_setup_detect(int ssp, bool enable, ssp_detect_cb_t fn) +{ + int bank = ssp == 1 ? 2 : 0; + int pin = ssp == 1 ? 1 : 19; + ssp_detect_cb[ssp - 1] = fn; + if(enable) + { + imx233_set_pin_function(bank, pin, PINCTRL_FUNCTION_GPIO); + imx233_enable_gpio_output(bank, pin, false); + } + imx233_setup_pin_irq(bank, pin, enable, true, !imx233_ssp_sdmmc_detect(ssp), detect_irq); +} + +bool imx233_ssp_sdmmc_detect(int ssp) +{ + return !!(HW_SSP_STATUS(ssp) & HW_SSP_STATUS__CARD_DETECT); +} diff --git a/firmware/target/arm/imx233/ssp-imx233.h b/firmware/target/arm/imx233/ssp-imx233.h index c7c891ec0b..c9083d8d75 100644 --- a/firmware/target/arm/imx233/ssp-imx233.h +++ b/firmware/target/arm/imx233/ssp-imx233.h @@ -27,6 +27,7 @@ #include "cpu.h" #include "system.h" #include "system-target.h" +#include "pinctrl-imx233.h" /* ssp can value 1 or 2 */ #define __SSP_SELECT(ssp, ssp1, ssp2) ((ssp) == 1 ? (ssp1) : (ssp2)) @@ -122,6 +123,7 @@ #define HW_SSP_STATUS__RESP_TIMEOUT (1 << 14) #define HW_SSP_STATUS__RESP_ERR (1 << 15) #define HW_SSP_STATUS__RESP_CRC_ERR (1 << 16) +#define HW_SSP_STATUS__CARD_DETECT (1 << 28) #define HW_SSP_STATUS__ALL_ERRORS 0x1f800 #define HW_SSP_DEBUG(ssp) (*(volatile uint32_t *)(HW_SSP_BASE(ssp) + 0x100)) @@ -142,6 +144,8 @@ enum imx233_ssp_resp_t SSP_LONG_RESP }; +typedef void (*ssp_detect_cb_t)(int ssp); + void imx233_ssp_init(void); void imx233_ssp_start(int ssp); void imx233_ssp_stop(int ssp); @@ -156,8 +160,14 @@ void imx233_ssp_set_block_size(int ssp, unsigned log_block_size); enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_t cmd_arg, enum imx233_ssp_resp_t resp, void *buffer, unsigned block_count, bool wait4irq, bool read, uint32_t *resp_ptr); +void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width, + unsigned drive_strength, bool use_alt); void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width, unsigned drive_strength); +/* after callback is fired, imx233_ssp_sdmmc_setup_detect needs to be called + * to enable detection again */ +void imx233_ssp_sdmmc_setup_detect(int ssp, bool enable, ssp_detect_cb_t fn); +bool imx233_ssp_sdmmc_detect(int ssp); /* SD/MMC requires that the card be provided the clock during an init sequence of * at least 1msec (or 74 clocks). Does NOT touch the clock so it has to be correct. */ void imx233_ssp_sd_mmc_power_up_sequence(int ssp);