From owner-freebsd-arm@FreeBSD.ORG Mon Aug 27 04:10:06 2012 Return-Path: Delivered-To: freebsd-arm@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B4900106564A for ; Mon, 27 Aug 2012 04:10:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 9FBAA8FC1B for ; Mon, 27 Aug 2012 04:10:06 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q7R4A6GM022828 for ; Mon, 27 Aug 2012 04:10:06 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q7R4A65W022827; Mon, 27 Aug 2012 04:10:06 GMT (envelope-from gnats) Date: Mon, 27 Aug 2012 04:10:06 GMT Message-Id: <201208270410.q7R4A65W022827@freefall.freebsd.org> To: freebsd-arm@FreeBSD.org From: dfilter@FreeBSD.ORG (dfilter service) Cc: Subject: Re: arm/155214: commit references a PR X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: dfilter service List-Id: Porting FreeBSD to the StrongARM Processor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Aug 2012 04:10:06 -0000 The following reply was made to PR arm/155214; it has been noted by GNATS. From: dfilter@FreeBSD.ORG (dfilter service) To: bug-followup@FreeBSD.org Cc: Subject: Re: arm/155214: commit references a PR Date: Mon, 27 Aug 2012 04:04:04 +0000 (UTC) Author: imp Date: Mon Aug 27 04:03:49 2012 New Revision: 239719 URL: http://svn.freebsd.org/changeset/base/239719 Log: 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 Modified: head/sys/arm/at91/at91_mci.c Modified: head/sys/arm/at91/at91_mci.c ============================================================================== --- head/sys/arm/at91/at91_mci.c Mon Aug 27 03:09:39 2012 (r239718) +++ head/sys/arm/at91/at91_mci.c Mon Aug 27 04:03:49 2012 (r239719) @@ -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); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"