summaryrefslogtreecommitdiffstats
path: root/sys/arm/at91/at91_mci.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2012-08-27 04:03:49 +0000
committerimp <imp@FreeBSD.org>2012-08-27 04:03:49 +0000
commit0e233741f6b9527df54a71928e8f201483bef1f4 (patch)
treefbc2f748321e7e6362d3f3e6aba13da9a9669a76 /sys/arm/at91/at91_mci.c
parentf83ff5dc9510433a6364807b123ff7b12553b700 (diff)
downloadFreeBSD-src-0e233741f6b9527df54a71928e8f201483bef1f4.zip
FreeBSD-src-0e233741f6b9527df54a71928e8f201483bef1f4.tar.gz
Don't puprosely overclock the SD bus to 30MHz, make the user
explicltly enable that. The driver chose to use 60MHz / 2 (30MHz) most of the time rather than 60MHz / 4 (15MHz) based on the Linux driver of the time. This pushes the spec a little in order to not suffer the penalty of running at 15MHz. However, when other bus masters are active in the system, and the user tries 4-wire mode, the internal bus arbitration would fail with data loss as a result. # Comments from PR were reworked to reflect my historical perspective PR: 155214 (partial) Submitted by: Ian Lepore
Diffstat (limited to 'sys/arm/at91/at91_mci.c')
-rw-r--r--sys/arm/at91/at91_mci.c102
1 files changed, 91 insertions, 11 deletions
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index 9a1bb31..033dbdd 100644
--- a/sys/arm/at91/at91_mci.c
+++ b/sys/arm/at91/at91_mci.c
@@ -67,6 +67,53 @@ __FBSDID("$FreeBSD$");
#include "opt_at91.h"
+/*
+ * About running the MCI bus at 30mhz...
+ *
+ * Historically, the MCI bus has been run at 30mhz on systems with a 60mhz
+ * master clock, due to a bug in the mantissa table in dev/mmc.c making it
+ * appear that the card's max speed was always 30mhz. Fixing that bug causes
+ * the mmc driver to request a 25mhz clock (as it should) and the logic in
+ * at91_mci_update_ios() picks the highest speed that doesn't exceed that limit.
+ * With a 60mhz MCK that would be 15mhz, and that's a real performance buzzkill
+ * when you've been getting away with 30mhz all along.
+ *
+ * By defining AT91_MCI_USE_30MHZ (or setting the 30mhz=1 device hint or
+ * sysctl) you can enable logic in at91_mci_update_ios() to overlcock the SD
+ * bus a little by running it at MCK / 2 when MCK is between greater than
+ * 50MHz and the requested speed is 25mhz. This appears to work on virtually
+ * all SD cards, since it is what this driver has been doing prior to the
+ * introduction of this option, where the overclocking vs underclocking
+ * decision was automaticly "overclock". Modern SD cards can run at
+ * 45mhz/1-bit in standard mode (high speed mode enable commands not sent)
+ * without problems.
+ *
+ * Speaking of high-speed mode, the rm9200 manual says the MCI device supports
+ * the SD v1.0 specification and can run up to 50mhz. This is interesting in
+ * that the SD v1.0 spec caps the speed at 25mhz; high speed mode was added in
+ * the v1.10 spec. Furthermore, high speed mode doesn't just crank up the
+ * clock, it alters the signal timing. The rm9200 MCI device doesn't support
+ * these altered timings. So while speeds over 25mhz may work, they only work
+ * in what the SD spec calls "default" speed mode, and it amounts to violating
+ * the spec by overclocking the bus.
+ *
+ * If you also enable 4-wire mode it's possible the 30mhz transfers will fail.
+ * On the AT91RM9200, due to bugs in the bus contention logic, if you have the
+ * USB host device and OHCI driver enabled will fail. Even underclocking to
+ * 15MHz, intermittant overrun and underrun errors occur. Note that you don't
+ * even need to have usb devices attached to the system, the errors begin to
+ * occur as soon as the OHCI driver sets the register bit to enable periodic
+ * transfers. It appears (based on brief investigation) that the usb host
+ * controller uses so much ASB bandwidth that sometimes the DMA for MCI
+ * transfers doesn't get a bus grant in time and data gets dropped. Adding
+ * even a modicum of network activity changes the symptom from intermittant to
+ * very frequent. Members of the AT91SAM9 family have corrected this problem, or
+ * are at least better about their use of the bus.
+ */
+#ifndef AT91_MCI_USE_30MHZ
+#define AT91_MCI_USE_30MHZ 1
+#endif
+
#define BBSZ 512
struct at91_mci_softc {
@@ -76,9 +123,10 @@ struct at91_mci_softc {
#define CAP_HAS_4WIRE 1 /* Has 4 wire bus */
#define CAP_NEEDS_BYTESWAP 2 /* broken hardware needing bounce */
int flags;
- int has_4wire;
#define CMD_STARTED 1
#define STOP_STARTED 2
+ int has_4wire;
+ int use_30mhz;
struct resource *irq_res; /* IRQ resource */
struct resource *mem_res; /* Memory resource */
struct mtx sc_mtx;
@@ -236,16 +284,33 @@ at91_mci_attach(device_t dev)
if (sc->has_4wire)
sc->sc_cap |= CAP_HAS_4WIRE;
- sc->host.f_min = at91_master_clock / 512;
+#if defined(AT91_MCI_USE_30MHZ) && AT91_MCI_USE_30MHZ != 0
+ sc->use_30mhz = 1;
+#endif
+ resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "30mhz", &sc->use_30mhz);
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "30mhz",
+ CTLFLAG_RW, &sc->use_30mhz, 0, "use 30mhz clock for 25mhz request");
+
+ /* Our real min freq is master_clock/512, but upper driver layers are
+ * going to set the min speed during card discovery, and the right speed
+ * for that is 400khz, so advertise a safe value just under that.
+ *
+ * For max speed, while the rm9200 manual says the max is 50mhz, it also
+ * says it supports only the SD v1.0 spec, which means the real limit is
+ * 25mhz. On the other hand, historical use has been to slightly violate
+ * the standard by running the bus at 30mhz. For more information on
+ * that, see the comments at the top of this file.
+ */
sc->host.f_min = 375000;
sc->host.f_max = at91_master_clock / 2;
- if (sc->host.f_max > 50000000)
- sc->host.f_max = 50000000; /* Limit to 50MHz */
-
+ if (sc->host.f_max > 25000000)
+ sc->host.f_max = 25000000; /* Limit to 25MHz */
sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
sc->host.caps = 0;
if (sc->sc_cap & CAP_HAS_4WIRE)
sc->host.caps |= MMC_CAP_4_BIT_DATA;
+
child = device_add_child(dev, "mmc", 0);
device_set_ivars(dev, &sc->host);
err = bus_generic_attach(dev);
@@ -338,23 +403,38 @@ static int
at91_mci_update_ios(device_t brdev, device_t reqdev)
{
struct at91_mci_softc *sc;
- struct mmc_host *host;
struct mmc_ios *ios;
uint32_t clkdiv;
sc = device_get_softc(brdev);
- host = &sc->host;
- ios = &host->ios;
- // bus mode?
+ ios = &sc->host.ios;
+
+ /*
+ * Calculate our closest available clock speed that doesn't exceed the
+ * requested speed.
+ *
+ * If the master clock is greater than 50MHz and the requested bus
+ * speed is 25mhz and the use_30mhz flag is on, set clkdiv to zero to
+ * get a master_clock / 2 (25-30MHz) MMC/SD clock rather than settle for
+ * the next lower click (12-15MHz). See comments near the top of the
+ * file for more info.
+ *
+ * Whatever we come up with, store it back into ios->clock so that the
+ * upper layer drivers can report the actual speed of the bus.
+ */
if (ios->clock == 0) {
WR4(sc, MCI_CR, MCI_CR_MCIDIS);
clkdiv = 0;
} else {
- WR4(sc, MCI_CR, MCI_CR_MCIEN);
- if ((at91_master_clock % (ios->clock * 2)) == 0)
+ WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN);
+ if (sc->use_30mhz && ios->clock == 25000000 &&
+ at91_master_clock > 50000000)
+ clkdiv = 0;
+ else if ((at91_master_clock % (ios->clock * 2)) == 0)
clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
else
clkdiv = (at91_master_clock / ios->clock) / 2;
+ ios->clock = at91_master_clock / ((clkdiv+1) * 2);
}
if (ios->bus_width == bus_width_4)
WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) | MCI_SDCR_SDCBUS);
OpenPOWER on IntegriCloud