imx233: fix drive strength for sd/mmc

At high speed, we need a drive strength of 8mA on the clock line
to get stable transfers.

Change-Id: Ida668db10cd3e10ad5740e35fd973f2fa394edb2
This commit is contained in:
Amaury Pouly 2013-08-21 11:11:36 +02:00
parent 462adf2a0f
commit 96d355abba
3 changed files with 47 additions and 40 deletions

View file

@ -206,6 +206,17 @@ static void sdmmc_detect_callback(int ssp)
imx233_ssp_sdmmc_is_detect_inverted(ssp));
}
static void sdmmc_enable_pullups(int drive, bool pullup)
{
/* setup pins, never use alternatives pin on SSP1 because no device use it
* but this could be made a flag */
int bus_width = SDMMC_MODE(drive) == MMC_MODE ? 8 : 4;
if(SDMMC_SSP(drive) == 1)
imx233_ssp_setup_ssp1_sd_mmc_pins(pullup, bus_width, false);
else
imx233_ssp_setup_ssp2_sd_mmc_pins(pullup, bus_width);
}
static void sdmmc_power(int drive, bool on)
{
/* power chip if needed */
@ -223,13 +234,8 @@ static void sdmmc_power(int drive, bool on)
}
if(SDMMC_FLAGS(drive) & POWER_DELAY)
sleep(SDMMC_CONF(drive).power_delay);
/* setup pins, never use alternatives pin on SSP1 because no device use it
* but this could be made a flag */
int bus_width = SDMMC_MODE(drive) == MMC_MODE ? 8 : 4;
if(SDMMC_SSP(drive) == 1)
imx233_ssp_setup_ssp1_sd_mmc_pins(on, bus_width, PINCTRL_DRIVE_4mA, false);
else
imx233_ssp_setup_ssp2_sd_mmc_pins(on, bus_width, PINCTRL_DRIVE_4mA);
/* enable pullups for identification */
sdmmc_enable_pullups(drive, true);
}
#define MCI_NO_RESP 0

View file

@ -168,24 +168,27 @@ void imx233_ssp_softreset(int ssp)
void imx233_ssp_set_timings(int ssp, int divide, int rate, int timeout)
{
ASSERT_SSP(ssp)
if(divide == 0 || (divide % 2) == 1)
panicf("SSP timing divide must be event");
SSP_REGn(SSP_TIMING, ssp) = BF_OR3(SSP_TIMING, CLOCK_DIVIDE(divide),
CLOCK_RATE(rate), TIMEOUT(timeout));
}
void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width,
unsigned drive_strength, bool use_alt)
void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width, bool use_alt)
{
(void) use_alt;
unsigned clk_drive = PINCTRL_DRIVE_8mA;
unsigned dat_drive = PINCTRL_DRIVE_4mA;
/* SSP_{CMD,SCK} */
imx233_pinctrl_setup_vpin(VPIN_SSP1_CMD, "ssp1_cmd", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_SCK, "ssp1_sck", drive_strength, false);
imx233_pinctrl_setup_vpin(VPIN_SSP1_CMD, "ssp1_cmd", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_SCK, "ssp1_sck", clk_drive, false);
/* SSP_DATA{0-3} */
imx233_pinctrl_setup_vpin(VPIN_SSP1_D0, "ssp1_d0", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D0, "ssp1_d0", dat_drive, enable_pullups);
if(bus_width >= 4)
{
imx233_pinctrl_setup_vpin(VPIN_SSP1_D1, "ssp1_d1", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D2, "ssp1_d2", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D3, "ssp1_d3", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D1, "ssp1_d1", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D2, "ssp1_d2", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D3, "ssp1_d3", dat_drive, enable_pullups);
}
if(bus_width >= 8)
{
@ -193,20 +196,20 @@ void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width,
if(use_alt)
{
#ifdef VPIN_SSP1_D4_ALT
imx233_pinctrl_setup_vpin(VPIN_SSP1_D4_ALT, "ssp1_d4", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D5_ALT, "ssp1_d5", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D6_ALT, "ssp1_d6", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D7_ALT, "ssp1_d7", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D4_ALT, "ssp1_d4", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D5_ALT, "ssp1_d5", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D6_ALT, "ssp1_d6", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D7_ALT, "ssp1_d7", dat_drive, enable_pullups);
#else
panicf("there is ssp1 alt on this soc!");
#endif
}
else
{
imx233_pinctrl_setup_vpin(VPIN_SSP1_D4, "ssp1_d4", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D5, "ssp1_d5", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D6, "ssp1_d6", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D7, "ssp1_d7", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D4, "ssp1_d4", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D5, "ssp1_d5", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D6, "ssp1_d6", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP1_D7, "ssp1_d7", dat_drive, enable_pullups);
}
#else
panicf("ssp1 bus width is limited to 4 on this soc!");
@ -214,30 +217,30 @@ void imx233_ssp_setup_ssp1_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)
void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width)
{
(void) enable_pullups;
(void) bus_width;
(void) drive_strength;
unsigned clk_drive = PINCTRL_DRIVE_8mA;
unsigned dat_drive = PINCTRL_DRIVE_4mA;
#ifdef VPIN_SSP2_CMD
/* SSP_{CMD,SCK} */
imx233_pinctrl_setup_vpin(VPIN_SSP2_CMD, "ssp2_cmd", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_SCK, "ssp2_sck", drive_strength, false);
imx233_pinctrl_setup_vpin(VPIN_SSP2_CMD, "ssp2_cmd", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_SCK, "ssp2_sck", clk_drive, false);
/* SSP_DATA{0-3} */
imx233_pinctrl_setup_vpin(VPIN_SSP2_D0, "ssp2_d0", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D0, "ssp2_d0", dat_drive, enable_pullups);
if(bus_width >= 4)
{
imx233_pinctrl_setup_vpin(VPIN_SSP2_D1, "ssp2_d1", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D2, "ssp2_d2", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D3, "ssp2_d3", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D1, "ssp2_d1", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D2, "ssp2_d2", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D3, "ssp2_d3", dat_drive, enable_pullups);
}
if(bus_width >= 8)
{
imx233_pinctrl_setup_vpin(VPIN_SSP2_D4, "ssp2_d4", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D5, "ssp2_d5", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D6, "ssp2_d6", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D7, "ssp2_d7", drive_strength, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D4, "ssp2_d4", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D5, "ssp2_d5", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D6, "ssp2_d6", dat_drive, enable_pullups);
imx233_pinctrl_setup_vpin(VPIN_SSP2_D7, "ssp2_d7", dat_drive, enable_pullups);
}
#else
panicf("there is no ssp2 on this soc!");

View file

@ -98,10 +98,8 @@ 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);
/* pullups/alternative are ignored on targets which don't support it */
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);
void imx233_ssp_setup_ssp1_sd_mmc_pins(bool enable_pullups, unsigned bus_width, bool use_alt);
void imx233_ssp_setup_ssp2_sd_mmc_pins(bool enable_pullups, unsigned bus_width);
/* after callback is fired, imx233_ssp_sdmmc_setup_detect needs to be called
* to enable detection again. If first_time is true, the callback will
* be called if the sd card is inserted when the function is called, otherwise