From 1e2d42e984e03ba8dfdd367c4b54a9e3ab98ea77 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Sat, 16 May 2009 18:14:15 +0200 Subject: [PATCH] sdhctrl: use a 4bit bus --- sdhc.c | 46 +++++++++++++++++++--------------------------- sdmmc.c | 38 ++++++++++++++++++++++++++++++++++++++ sdmmcchip.h | 13 +++++-------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/sdhc.c b/sdhc.c index 3753a03..a95a471 100644 --- a/sdhc.c +++ b/sdhc.c @@ -131,8 +131,6 @@ int sdhc_host_maxblklen(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_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 *); int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); 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_read_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 int sdhcdebug = 2; @@ -163,9 +162,7 @@ struct sdmmc_chip_functions sdhc_functions = { sdhc_bus_clock, /* command execution */ sdhc_exec_command, - /* card interrupt */ - sdhc_card_intr_mask, - sdhc_card_intr_ack + sdhc_set_bus_width, }; /* @@ -556,28 +553,6 @@ ret: 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 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; } +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. */ int sdhc_soft_reset(struct sdhc_host *hp, int mask) diff --git a/sdmmc.c b/sdmmc.c index 9a80e86..68cff7c 100644 --- a/sdmmc.c +++ b/sdmmc.c @@ -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); } +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, sdmmc_chipset_handle_t handle, const char *name, int no) @@ -307,6 +312,7 @@ void sdmmc_needs_discover(struct device *dev) } sdmmc_select(dev); + DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n")); memset(&cmd, 0, sizeof(cmd)); cmd.c_opcode = MMC_SET_BLOCKLEN; @@ -319,11 +325,43 @@ void sdmmc_needs_discover(struct device *dev) c->inserted = c->selected = 0; 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; out_clock: out_power: + c->inserted = c->selected = 0; sdmmc_host_power(c, 0); + sdmmc_host_reset(c); out: return; diff --git a/sdmmcchip.h b/sdmmcchip.h index 96f9fb0..05a567e 100644 --- a/sdmmcchip.h +++ b/sdmmcchip.h @@ -38,9 +38,8 @@ struct sdmmc_chip_functions { /* command execution */ void (*exec_command)(sdmmc_chipset_handle_t, struct sdmmc_command *); - /* card interrupt */ - void (*card_intr_mask)(sdmmc_chipset_handle_t, int); - void (*card_intr_ack)(sdmmc_chipset_handle_t); + /* bus width */ + void (*set_bus_width)(sdmmc_chipset_handle_t, int); }; /* host controller reset */ @@ -62,11 +61,9 @@ struct sdmmc_chip_functions { /* command execution */ #define sdmmc_chip_exec_command(tag, handle, cmdp) \ ((tag)->exec_command((handle), (cmdp))) -/* card interrupt */ -#define sdmmc_chip_card_intr_mask(tag, handle, enable) \ - ((tag)->card_intr_mask((handle), (enable))) -#define sdmmc_chip_card_intr_ack(tag, handle) \ - ((tag)->card_intr_ack((handle))) +/* bus widht */ +#define sdmmc_chip_set_bus_width(tag, handle, enable) \ + ((tag)->set_bus_width((handle), (enable))) /* clock frequencies for sdmmc_chip_bus_clock() */ #define SDMMC_SDCLK_OFF 0