From owner-svn-src-head@FreeBSD.ORG Mon Oct 29 17:21:59 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 1CBC070E; Mon, 29 Oct 2012 17:21:59 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ED2168FC0A; Mon, 29 Oct 2012 17:21:58 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q9THLwfC006876; Mon, 29 Oct 2012 17:21:58 GMT (envelope-from gonzo@svn.freebsd.org) Received: (from gonzo@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q9THLw0W006873; Mon, 29 Oct 2012 17:21:58 GMT (envelope-from gonzo@svn.freebsd.org) Message-Id: <201210291721.q9THLw0W006873@svn.freebsd.org> From: Oleksandr Tymoshenko Date: Mon, 29 Oct 2012 17:21:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r242320 - head/sys/dev/sdhci X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Oct 2012 17:21:59 -0000 Author: gonzo Date: Mon Oct 29 17:21:58 2012 New Revision: 242320 URL: http://svn.freebsd.org/changeset/base/242320 Log: Add new quirks: - Data timeout is broken - Data timeout uses SD clock - Capabilities register is unavailable Add calculations for clock divisor for SDHCI 3.0 Modified: head/sys/dev/sdhci/sdhci.c head/sys/dev/sdhci/sdhci.h Modified: head/sys/dev/sdhci/sdhci.c ============================================================================== --- head/sys/dev/sdhci/sdhci.c Mon Oct 29 17:19:43 2012 (r242319) +++ head/sys/dev/sdhci/sdhci.c Mon Oct 29 17:21:58 2012 (r242320) @@ -221,6 +221,7 @@ sdhci_set_clock(struct sdhci_slot *slot, { uint32_t res; uint16_t clk; + uint16_t div; int timeout; if (clock == slot->clock) @@ -232,17 +233,39 @@ sdhci_set_clock(struct sdhci_slot *slot, /* If no clock requested - left it so. */ if (clock == 0) return; - /* Looking for highest freq <= clock. */ - res = slot->max_clk; - for (clk = 1; clk < 256; clk <<= 1) { - if (res <= clock) - break; - res >>= 1; + if (slot->version < SDHCI_SPEC_300) { + /* Looking for highest freq <= clock. */ + res = slot->max_clk; + for (div = 1; div < 256; div <<= 1) { + if (res <= clock) + break; + res >>= 1; + } + /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ + div >>= 1; + } + else { + /* Version 3.0 divisors are multiples of two up to 1023*2 */ + if (clock > slot->max_clk) + div = 2; + else { + for (div = 2; div < 1023*2; div += 2) { + if ((slot->max_clk / div) <= clock) + break; + } + } + div >>= 1; } - /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ - clk >>= 1; + + if (bootverbose || sdhci_debug) + slot_printf(slot, "Divider %d for freq %d (max %d)\n", + div, clock, slot->max_clk); + /* Now we have got divider, set it. */ - clk <<= SDHCI_DIVIDER_SHIFT; + clk = (div & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div >> SDHCI_DIVIDER_MASK_LEN) & SDHCI_DIVIDER_HI_MASK) + << SDHCI_DIVIDER_HI_SHIFT; + WR2(slot, SDHCI_CLOCK_CONTROL, clk); /* Enable clock. */ clk |= SDHCI_CLOCK_INT_EN; @@ -488,7 +511,10 @@ sdhci_init_slot(device_t dev, struct sdh sdhci_init(slot); slot->version = (RD2(slot, SDHCI_HOST_VERSION) >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; - caps = RD4(slot, SDHCI_CAPABILITIES); + if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) + caps = slot->caps; + else + caps = RD4(slot, SDHCI_CAPABILITIES); /* Calculate base clock frequency. */ slot->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; @@ -499,14 +525,19 @@ sdhci_init_slot(device_t dev, struct sdh } slot->max_clk *= 1000000; /* Calculate timeout clock frequency. */ - slot->timeout_clk = - (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; + if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) { + slot->timeout_clk = slot->max_clk / 1000; + } else { + slot->timeout_clk = + (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; + if (caps & SDHCI_TIMEOUT_CLK_UNIT) + slot->timeout_clk *= 1000; + } + if (slot->timeout_clk == 0) { device_printf(dev, "Hardware doesn't specify timeout clock " "frequency.\n"); } - if (caps & SDHCI_TIMEOUT_CLK_UNIT) - slot->timeout_clk *= 1000; slot->host.f_min = slot->max_clk / 256; slot->host.f_max = slot->max_clk; @@ -815,6 +846,8 @@ sdhci_start_data(struct sdhci_slot *slot slot_printf(slot, "Timeout too large!\n"); div = 0xE; } + if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) + div = 0xE; WR1(slot, SDHCI_TIMEOUT_CONTROL, div); if (data == NULL) Modified: head/sys/dev/sdhci/sdhci.h ============================================================================== --- head/sys/dev/sdhci/sdhci.h Mon Oct 29 17:19:43 2012 (r242319) +++ head/sys/dev/sdhci/sdhci.h Mon Oct 29 17:21:58 2012 (r242320) @@ -51,12 +51,16 @@ #define SDHCI_QUIRK_BROKEN_TIMINGS (1<<8) /* Controller needs lowered frequency */ #define SDHCI_QUIRK_LOWER_FREQUENCY (1<<9) - +/* Data timeout is invalid, should use SD clock */ +#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<10) +/* Timeout value is invalid, should be overriden */ +#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<11) +/* SDHCI_CAPABILITIES is invalid */ +#define SDHCI_QUIRK_MISSING_CAPS (1<<12) /* * Controller registers */ - #define SDHCI_DMA_ADDRESS 0x00 #define SDHCI_BLOCK_SIZE 0x04 @@ -130,7 +134,11 @@ #define SDHCI_WAKE_UP_CONTROL 0x2B #define SDHCI_CLOCK_CONTROL 0x2C +#define SDHCI_DIVIDER_MASK 0xff +#define SDHCI_DIVIDER_MASK_LEN 8 #define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_MASK 3 +#define SDHCI_DIVIDER_HI_SHIFT 6 #define SDHCI_CLOCK_CARD_EN 0x0004 #define SDHCI_CLOCK_INT_STABLE 0x0002 #define SDHCI_CLOCK_INT_EN 0x0001 @@ -204,9 +212,13 @@ #define SDHCI_VENDOR_VER_SHIFT 8 #define SDHCI_SPEC_VER_MASK 0x00FF #define SDHCI_SPEC_VER_SHIFT 0 +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 struct sdhci_slot { u_int quirks; /* Chip specific quirks */ + u_int caps; /* Override SDHCI_CAPABILITIES */ device_t bus; /* Bus device */ device_t dev; /* Slot device */ u_char num; /* Slot number */