imx233/fuze+: add SD detection support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30196 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
85c32dbd12
commit
82f70b8efd
6 changed files with 164 additions and 27 deletions
|
@ -40,8 +40,8 @@
|
||||||
|
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
void main(void) NORETURN_ATTR;
|
void main(uint32_t arg) NORETURN_ATTR;
|
||||||
void main(void)
|
void main(uint32_t arg)
|
||||||
{
|
{
|
||||||
unsigned char* loadbuffer;
|
unsigned char* loadbuffer;
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
|
@ -62,6 +62,8 @@ void main(void)
|
||||||
button_init_device();
|
button_init_device();
|
||||||
|
|
||||||
//button_debug_screen();
|
//button_debug_screen();
|
||||||
|
printf("arg=%c%c%c%c", arg >> 24,
|
||||||
|
(arg >> 16) & 0xff, (arg >> 8) & 0xff, (arg & 0xff));
|
||||||
|
|
||||||
ret = storage_init();
|
ret = storage_init();
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
|
@ -84,6 +86,9 @@ void main(void)
|
||||||
error(EDISK, ret, true);
|
error(EDISK, ret, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(button_read_device() & BUTTON_VOL_UP)
|
||||||
|
printf("Booting from SD card required.");
|
||||||
|
|
||||||
printf("Loading firmware");
|
printf("Loading firmware");
|
||||||
|
|
||||||
loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */
|
loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */
|
||||||
|
|
|
@ -118,13 +118,9 @@
|
||||||
#define HAVE_FLASH_STORAGE
|
#define HAVE_FLASH_STORAGE
|
||||||
|
|
||||||
/* define this if the flash memory uses the SecureDigital Memory Card protocol */
|
/* define this if the flash memory uses the SecureDigital Memory Card protocol */
|
||||||
#ifdef BOOTLOADER
|
#define CONFIG_STORAGE (STORAGE_SD | STORAGE_MMC)
|
||||||
# define CONFIG_STORAGE STORAGE_MMC
|
#define NUM_DRIVES 2
|
||||||
#else
|
#define HAVE_HOTSWAP
|
||||||
# define CONFIG_STORAGE (STORAGE_SD | STORAGE_MMC)
|
|
||||||
# define NUM_DRIVES 2
|
|
||||||
# define HAVE_HOTSWAP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* todo */
|
/* todo */
|
||||||
#define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */
|
#define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "ssp-imx233.h"
|
#include "ssp-imx233.h"
|
||||||
#include "pinctrl-imx233.h"
|
#include "pinctrl-imx233.h"
|
||||||
#include "button-target.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This code assumes a single eMMC internal flash
|
* 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;
|
(void) buf;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mmc_present(IF_MD(int drive))
|
||||||
|
{
|
||||||
|
IF_MD((void) drive);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -22,9 +22,54 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "sdmmc.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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +102,12 @@ tCardInfo *card_get_info_target(int card_no)
|
||||||
int sd_num_drives(int first_drive)
|
int sd_num_drives(int first_drive)
|
||||||
{
|
{
|
||||||
(void) 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ static struct semaphore ssp_sema[2];
|
||||||
static struct ssp_dma_command_t ssp_dma_cmd[2];
|
static struct ssp_dma_command_t ssp_dma_cmd[2];
|
||||||
static uint32_t ssp_bus_width[2];
|
static uint32_t ssp_bus_width[2];
|
||||||
static unsigned ssp_log_block_size[2];
|
static unsigned ssp_log_block_size[2];
|
||||||
|
static ssp_detect_cb_t ssp_detect_cb[2];
|
||||||
|
|
||||||
void INT_SSP(int ssp)
|
void INT_SSP(int ssp)
|
||||||
{
|
{
|
||||||
|
@ -146,22 +147,7 @@ static void setup_ssp_sd_pins(int ssp)
|
||||||
|
|
||||||
if(ssp == 1)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -170,6 +156,41 @@ static void setup_ssp_sd_pins(int ssp)
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width,
|
||||||
unsigned drive_strength)
|
unsigned drive_strength)
|
||||||
{
|
{
|
||||||
|
@ -301,3 +322,52 @@ void imx233_ssp_sd_mmc_power_up_sequence(int ssp)
|
||||||
mdelay(1);
|
mdelay(1);
|
||||||
__REG_CLR(HW_SSP_CMD0(ssp)) = HW_SSP_CMD0__CONT_CLKING_EN;
|
__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);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "system-target.h"
|
#include "system-target.h"
|
||||||
|
#include "pinctrl-imx233.h"
|
||||||
|
|
||||||
/* ssp can value 1 or 2 */
|
/* ssp can value 1 or 2 */
|
||||||
#define __SSP_SELECT(ssp, ssp1, ssp2) ((ssp) == 1 ? (ssp1) : (ssp2))
|
#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_TIMEOUT (1 << 14)
|
||||||
#define HW_SSP_STATUS__RESP_ERR (1 << 15)
|
#define HW_SSP_STATUS__RESP_ERR (1 << 15)
|
||||||
#define HW_SSP_STATUS__RESP_CRC_ERR (1 << 16)
|
#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_STATUS__ALL_ERRORS 0x1f800
|
||||||
|
|
||||||
#define HW_SSP_DEBUG(ssp) (*(volatile uint32_t *)(HW_SSP_BASE(ssp) + 0x100))
|
#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
|
SSP_LONG_RESP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*ssp_detect_cb_t)(int ssp);
|
||||||
|
|
||||||
void imx233_ssp_init(void);
|
void imx233_ssp_init(void);
|
||||||
void imx233_ssp_start(int ssp);
|
void imx233_ssp_start(int ssp);
|
||||||
void imx233_ssp_stop(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,
|
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,
|
uint32_t cmd_arg, enum imx233_ssp_resp_t resp, void *buffer, unsigned block_count,
|
||||||
bool wait4irq, bool read, uint32_t *resp_ptr);
|
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,
|
void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width,
|
||||||
unsigned drive_strength);
|
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
|
/* 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. */
|
* 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);
|
void imx233_ssp_sd_mmc_power_up_sequence(int ssp);
|
||||||
|
|
Loading…
Reference in a new issue