sdhctrl: use a 4bit bus

This commit is contained in:
Sven Peter 2009-05-16 18:14:15 +02:00
parent 9bb8946e59
commit 1e2d42e984
3 changed files with 62 additions and 35 deletions

46
sdhc.c
View File

@ -131,8 +131,6 @@ int sdhc_host_maxblklen(sdmmc_chipset_handle_t);
int sdhc_card_detect(sdmmc_chipset_handle_t); int sdhc_card_detect(sdmmc_chipset_handle_t);
int sdhc_bus_power(sdmmc_chipset_handle_t, u_int32_t); int sdhc_bus_power(sdmmc_chipset_handle_t, u_int32_t);
int sdhc_bus_clock(sdmmc_chipset_handle_t, int); int sdhc_bus_clock(sdmmc_chipset_handle_t, int);
void sdhc_card_intr_mask(sdmmc_chipset_handle_t, int);
void sdhc_card_intr_ack(sdmmc_chipset_handle_t);
void sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); void sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *);
int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t); int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t);
@ -141,6 +139,7 @@ int sdhc_wait_intr(struct sdhc_host *, int, int);
void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *); void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *);
void sdhc_read_data(struct sdhc_host *, u_char *, int); void sdhc_read_data(struct sdhc_host *, u_char *, int);
void sdhc_write_data(struct sdhc_host *, u_char *, int); void sdhc_write_data(struct sdhc_host *, u_char *, int);
void sdhc_set_bus_width(sdmmc_chipset_handle_t, int);
#ifdef SDHC_DEBUG #ifdef SDHC_DEBUG
int sdhcdebug = 2; int sdhcdebug = 2;
@ -163,9 +162,7 @@ struct sdmmc_chip_functions sdhc_functions = {
sdhc_bus_clock, sdhc_bus_clock,
/* command execution */ /* command execution */
sdhc_exec_command, sdhc_exec_command,
/* card interrupt */ sdhc_set_bus_width,
sdhc_card_intr_mask,
sdhc_card_intr_ack
}; };
/* /*
@ -556,28 +553,6 @@ ret:
return error; return error;
} }
void
sdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable)
{
struct sdhc_host *hp = sch;
if (enable) {
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
} else {
HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
}
}
void
sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
{
struct sdhc_host *hp = sch;
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
}
int int
sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value) sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value)
{ {
@ -830,6 +805,23 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
return; return;
} }
void
sdhc_set_bus_width(sdmmc_chipset_handle_t sch, int enable)
{
struct sdhc_host *hp = sch;
u_int16_t hctl;
hctl = HREAD2(hp, SDHC_HOST_CTL);
if (enable)
hctl |= SDHC_4BIT_MODE;
else
hctl &= ~SDHC_4BIT_MODE;
HWRITE2(hp, SDHC_HOST_CTL, hctl);
}
/* Prepare for another command. */ /* Prepare for another command. */
int int
sdhc_soft_reset(struct sdhc_host *hp, int mask) sdhc_soft_reset(struct sdhc_host *hp, int mask)

38
sdmmc.c
View File

@ -82,6 +82,11 @@ static inline void sdmmc_host_exec_command(struct sdmmc_card *card, struct
{ {
sdmmc_chip_exec_command(card->functions, card->handle, cmd); sdmmc_chip_exec_command(card->functions, card->handle, cmd);
} }
static inline void sdmmc_host_set_bus_width(struct sdmmc_card *card, int
enable)
{
sdmmc_chip_set_bus_width(card->functions, card->handle, enable);
}
struct device *sdmmc_attach(struct sdmmc_chip_functions *functions, struct device *sdmmc_attach(struct sdmmc_chip_functions *functions,
sdmmc_chipset_handle_t handle, const char *name, int no) sdmmc_chipset_handle_t handle, const char *name, int no)
@ -307,6 +312,7 @@ void sdmmc_needs_discover(struct device *dev)
} }
sdmmc_select(dev); sdmmc_select(dev);
DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n")); DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SET_BLOCKLEN; cmd.c_opcode = MMC_SET_BLOCKLEN;
@ -319,11 +325,43 @@ void sdmmc_needs_discover(struct device *dev)
c->inserted = c->selected = 0; c->inserted = c->selected = 0;
goto out_clock; goto out_clock;
} }
/* we can assume that every card supports a 4bit bus
* (see Simplified Physical Layer Spec, 5.6 SCR register (page 90),
* SD_BUS_WIDTHS)
*/
memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_APP_CMD;
cmd.c_arg = ((u32)c->rca)<<16;
cmd.c_flags = SCF_RSP_R1;
sdmmc_host_exec_command(c, &cmd);
if (cmd.c_error) {
gecko_printf("sdmmc: MMC_APP_CMD failed for "
"card %d with %d\n", no, cmd.c_error);
goto out_power;
}
memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = SD_APP_SET_BUS_WIDTH;
cmd.c_arg = SD_ARG_BUS_WIDTH_4;
cmd.c_flags = SCF_RSP_R1;
sdmmc_host_exec_command(c, &cmd);
if (cmd.c_error) {
gecko_printf("sdmmc: SD_APP_SET_BUS_WIDTH failed for "
"card %d with %d\n", no, cmd.c_error);
goto out_power;
}
sdmmc_host_set_bus_width(c, 1);
return; return;
out_clock: out_clock:
out_power: out_power:
c->inserted = c->selected = 0;
sdmmc_host_power(c, 0); sdmmc_host_power(c, 0);
sdmmc_host_reset(c);
out: out:
return; return;

View File

@ -38,9 +38,8 @@ struct sdmmc_chip_functions {
/* command execution */ /* command execution */
void (*exec_command)(sdmmc_chipset_handle_t, void (*exec_command)(sdmmc_chipset_handle_t,
struct sdmmc_command *); struct sdmmc_command *);
/* card interrupt */ /* bus width */
void (*card_intr_mask)(sdmmc_chipset_handle_t, int); void (*set_bus_width)(sdmmc_chipset_handle_t, int);
void (*card_intr_ack)(sdmmc_chipset_handle_t);
}; };
/* host controller reset */ /* host controller reset */
@ -62,11 +61,9 @@ struct sdmmc_chip_functions {
/* command execution */ /* command execution */
#define sdmmc_chip_exec_command(tag, handle, cmdp) \ #define sdmmc_chip_exec_command(tag, handle, cmdp) \
((tag)->exec_command((handle), (cmdp))) ((tag)->exec_command((handle), (cmdp)))
/* card interrupt */ /* bus widht */
#define sdmmc_chip_card_intr_mask(tag, handle, enable) \ #define sdmmc_chip_set_bus_width(tag, handle, enable) \
((tag)->card_intr_mask((handle), (enable))) ((tag)->set_bus_width((handle), (enable)))
#define sdmmc_chip_card_intr_ack(tag, handle) \
((tag)->card_intr_ack((handle)))
/* clock frequencies for sdmmc_chip_bus_clock() */ /* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0 #define SDMMC_SDCLK_OFF 0