Author: gonzo Date: Sat Feb 16 23:12:06 2013 New Revision: 246886 URL: http://svnweb.freebsd.org/changeset/base/246886
Log: Various timing-related fixes: - Replace divisor numbers with more descirptive names - Properly calculate minimum frequency for SDHCI 3.0 - Properly calculate frequency for SDHCI 3.0 in mmcbr_set_clock - Add min_freq method to sdhci_if.m and provide default implementation. By re-implementing this method hardware drivers can control frequency controller operates when executing initialization sequence Modified: head/sys/dev/sdhci/sdhci.c head/sys/dev/sdhci/sdhci.h head/sys/dev/sdhci/sdhci_if.m Modified: head/sys/dev/sdhci/sdhci.c ============================================================================== --- head/sys/dev/sdhci/sdhci.c Sat Feb 16 22:44:02 2013 (r246885) +++ head/sys/dev/sdhci/sdhci.c Sat Feb 16 23:12:06 2013 (r246886) @@ -65,7 +65,7 @@ struct sdhci_softc { 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 @@ static void sdhci_card_task(void *, int) #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 @@ sdhci_set_clock(struct sdhci_slot *slot, 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 @@ sdhci_set_clock(struct sdhci_slot *slot, } 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 @@ sdhci_init_slot(device_t dev, struct sdh "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 @@ sdhci_generic_resume(struct sdhci_slot * 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 @@ sdhci_data_irq(struct sdhci_slot *slot, } 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 @@ sdhci_generic_write_ivar(device_t bus, d 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; Modified: head/sys/dev/sdhci/sdhci.h ============================================================================== --- head/sys/dev/sdhci/sdhci.h Sat Feb 16 22:44:02 2013 (r246885) +++ head/sys/dev/sdhci/sdhci.h Sat Feb 16 23:12:06 2013 (r246886) @@ -266,5 +266,6 @@ int sdhci_generic_get_ro(device_t brdev, 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__ */ Modified: head/sys/dev/sdhci/sdhci_if.m ============================================================================== --- head/sys/dev/sdhci/sdhci_if.m Sat Feb 16 22:44:02 2013 (r246885) +++ head/sys/dev/sdhci/sdhci_if.m Sat Feb 16 23:12:06 2013 (r246886) @@ -58,7 +58,18 @@ # that mmc/sd card drivers call to make requests. # +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/taskqueue.h> + #include <machine/bus.h> + +#include <dev/mmc/bridge.h> +#include <dev/mmc/mmcreg.h> +#include <dev/sdhci/sdhci.h> + CODE { struct sdhci_slot; } @@ -119,3 +130,8 @@ METHOD void write_multi_4 { uint32_t *data; bus_size_t count; } + +METHOD uint32_t min_freq { + device_t brdev; + struct sdhci_slot *slot; +} DEFAULT sdhci_generic_min_freq; _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"