svn commit: r246886 - head/sys/dev/sdhci
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Sat Feb 16 23:12:07 UTC 2013
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;
More information about the svn-src-head
mailing list