Index: dev/mmc/mmc.c =================================================================== --- dev/mmc/mmc.c (revision 246573) +++ dev/mmc/mmc.c (working copy) @@ -578,6 +578,8 @@ mmcbr_update_ios(dev); mmc_ms_delay(1); + printf("mmcbr_set_clock %d == %d\n", __LINE__, + mmcbr_get_f_min(sc->dev)); mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev)); mmcbr_set_timing(dev, bus_timing_normal); mmcbr_set_power_mode(dev, power_on); @@ -651,6 +653,8 @@ data.flags = MMC_DATA_READ; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); + if (err != MMC_ERR_NONE) + device_printf(sc->dev, "SWITCH command failed\n"); return (err); } @@ -1067,7 +1071,8 @@ cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, 0); - memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t)); + if (err == MMC_ERR_NONE) + memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t)); return (err); } @@ -1092,8 +1097,11 @@ data.flags = MMC_DATA_READ; err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); - rawscr[0] = be32toh(rawscr[0]); - rawscr[1] = be32toh(rawscr[1]); + if (err == MMC_ERR_NONE) { + rawscr[0] = be32toh(rawscr[0]); + rawscr[1] = be32toh(rawscr[1]); + } + return (err); } @@ -1274,7 +1282,11 @@ mmc_send_relative_addr(sc, &resp); ivar->rca = resp >> 16; /* Get card CSD. */ - mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + if (err != MMC_ERR_NONE) { + device_printf(sc->dev, "Error reading CSD %d\n", err); + break; + } if (bootverbose || mmc_debug) device_printf(sc->dev, "%sard detected (CSD %08x%08x%08x%08x)\n", @@ -1303,7 +1315,13 @@ /* Get card SCR. Card must be selected to fetch it. */ mmc_select_card(sc, ivar->rca); - mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); + err = mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); + if (err != MMC_ERR_NONE) { + device_printf(sc->dev, + "Error reading card SCR %d\n", err); + break; + } + mmc_app_decode_scr(ivar->raw_scr, &ivar->scr); /* Get card switch capabilities (command class 10). */ if ((ivar->scr.sda_vsn >= 1) && @@ -1357,7 +1375,11 @@ ivar->rca = rca++; mmc_set_relative_addr(sc, ivar->rca); /* Get card CSD. */ - mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + if (err != MMC_ERR_NONE) { + device_printf(sc->dev, "Error reading CSD %d\n", err); + break; + } if (bootverbose || mmc_debug) device_printf(sc->dev, "%sard detected (CSD %08x%08x%08x%08x)\n", @@ -1533,6 +1555,8 @@ mmc_idle_cards(sc); } else { mmcbr_set_bus_mode(dev, opendrain); + printf("mmcbr_set_clock %d == %d\n", __LINE__, + mmcbr_get_f_min(dev)); mmcbr_set_clock(dev, mmcbr_get_f_min(dev)); mmcbr_update_ios(dev); /* XXX recompute vdd based on new cards? */ @@ -1604,7 +1628,7 @@ free(kids, M_TEMP); if (max_timing == bus_timing_hs) max_dtr = max_hs_dtr; - if (bootverbose || mmc_debug) { + if (1) { device_printf(sc->dev, "setting transfer rate to %d.%03dMHz%s\n", max_dtr / 1000000, (max_dtr / 1000) % 1000, Index: dev/sdhci/sdhci.h =================================================================== --- dev/sdhci/sdhci.h (revision 246573) +++ dev/sdhci/sdhci.h (working copy) @@ -266,5 +266,6 @@ int sdhci_generic_acquire_host(device_t brdev, device_t reqdev); int sdhci_generic_release_host(device_t brdev, device_t reqdev); void sdhci_generic_intr(struct sdhci_slot *slot); +uint32_t sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot); #endif /* __SDHCI_H__ */ Index: dev/sdhci/sdhci_if.m =================================================================== --- dev/sdhci/sdhci_if.m (revision 246573) +++ dev/sdhci/sdhci_if.m (working copy) @@ -58,7 +58,18 @@ # that mmc/sd card drivers call to make requests. # +#include +#include +#include +#include +#include + #include + +#include +#include +#include + CODE { struct sdhci_slot; } @@ -119,3 +130,8 @@ uint32_t *data; bus_size_t count; } + +METHOD uint32_t min_freq { + device_t brdev; + struct sdhci_slot *slot; +} DEFAULT sdhci_generic_min_freq; Index: dev/sdhci/sdhci.c =================================================================== --- dev/sdhci/sdhci.c (revision 246573) +++ dev/sdhci/sdhci.c (working copy) @@ -65,7 +65,7 @@ static SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver"); -int sdhci_debug = 0; +int sdhci_debug = 1; TUNABLE_INT("hw.sdhci.debug", &sdhci_debug); SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level"); @@ -98,6 +98,9 @@ #define SDHCI_DEFAULT_MAX_FREQ 50 +#define SDHCI_200_MAX_DIVIDER 256 +#define SDHCI_300_MAX_DIVIDER 2046 + static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { @@ -238,7 +241,7 @@ if (slot->version < SDHCI_SPEC_300) { /* Looking for highest freq <= clock. */ res = slot->max_clk; - for (div = 1; div < 256; div <<= 1) { + for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) { if (res <= clock) break; res >>= 1; @@ -248,10 +251,10 @@ } else { /* Version 3.0 divisors are multiples of two up to 1023*2 */ - if (clock > slot->max_clk) - div = 2; + if (clock >= slot->max_clk) + div = 0; else { - for (div = 2; div < 1023*2; div += 2) { + for (div = 2; div < SDHCI_300_MAX_DIVIDER; div += 2) { if ((slot->max_clk / div) <= clock) break; } @@ -545,7 +548,7 @@ "frequency.\n"); } - slot->host.f_min = slot->max_clk / 256; + slot->host.f_min = SDHCI_MIN_FREQ(slot->bus, slot); slot->host.f_max = slot->max_clk; slot->host.host_ocr = 0; if (caps & SDHCI_CAN_VDD_330) @@ -635,6 +638,15 @@ return (0); } +uint32_t +sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot) +{ + if (slot->version >= SDHCI_SPEC_300) + return (slot->max_clk / SDHCI_300_MAX_DIVIDER); + else + return (slot->max_clk / SDHCI_200_MAX_DIVIDER); +} + int sdhci_generic_update_ios(device_t brdev, device_t reqdev) { @@ -1078,8 +1090,12 @@ } if (intmask & SDHCI_INT_DATA_TIMEOUT) slot->curcmd->error = MMC_ERR_TIMEOUT; - else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) + else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) { + if (intmask & SDHCI_INT_DATA_CRC) { + panic("DATA CRC error\n"); + } slot->curcmd->error = MMC_ERR_BADCRC; + } if (slot->curcmd->data == NULL && (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DMA_END))) { @@ -1299,14 +1315,30 @@ break; case MMCBR_IVAR_CLOCK: if (value > 0) { - uint32_t clock = slot->max_clk; + uint32_t max_clock; + uint32_t clock; int i; - for (i = 0; i < 8; i++) { - if (clock <= value) - break; - clock >>= 1; + max_clock = slot->max_clk; + clock = max_clock; + + if (slot->version < SDHCI_SPEC_300) { + for (i = 0; i < SDHCI_200_MAX_DIVIDER; + i <<= 1) { + if (clock <= value) + break; + clock >>= 1; + } } + else { + for (i = 0; i < SDHCI_300_MAX_DIVIDER; + i += 2) { + if (clock <= value) + break; + clock = max_clock / (i + 2); + } + } + slot->host.ios.clock = clock; } else slot->host.ios.clock = 0; Index: arm/broadcom/bcm2835/bcm2835_sdhci.c =================================================================== --- arm/broadcom/bcm2835/bcm2835_sdhci.c (revision 246573) +++ arm/broadcom/bcm2835/bcm2835_sdhci.c (working copy) @@ -334,6 +334,18 @@ bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count); } +static uint32_t +bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot) +{ + + /* + * Arasan HC seems to have problem with + * Data CRC on lower frequencies. Cap minimum + * frequncy at 8MHz to work around this issue + */ + return (8*1000*1000); +} + static device_method_t bcm_sdhci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcm_sdhci_probe), @@ -353,6 +365,7 @@ DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), /* SDHCI registers accessors */ + DEVMETHOD(sdhci_min_freq, bcm_sdhci_min_freq), DEVMETHOD(sdhci_read_1, bcm_sdhci_read_1), DEVMETHOD(sdhci_read_2, bcm_sdhci_read_2), DEVMETHOD(sdhci_read_4, bcm_sdhci_read_4), @@ -375,3 +388,4 @@ DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass, 0, 0); MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1); +MODULE_DEPEND(sdhci_bcm, mbox, 1, 1, 1);