sdhci.c (241600) | sdhci.c (242320) |
---|---|
1/*- 2 * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 10 unchanged lines hidden (view full) --- 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 10 unchanged lines hidden (view full) --- 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> |
27__FBSDID("$FreeBSD: head/sys/dev/sdhci/sdhci.c 241600 2012-10-16 01:10:43Z gonzo $"); | 27__FBSDID("$FreeBSD: head/sys/dev/sdhci/sdhci.c 242320 2012-10-29 17:21:58Z gonzo $"); |
28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/bus.h> 32#include <sys/conf.h> 33#include <sys/kernel.h> 34#include <sys/lock.h> 35#include <sys/module.h> --- 180 unchanged lines hidden (view full) --- 216 WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 217} 218 219static void 220sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) 221{ 222 uint32_t res; 223 uint16_t clk; | 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/bus.h> 32#include <sys/conf.h> 33#include <sys/kernel.h> 34#include <sys/lock.h> 35#include <sys/module.h> --- 180 unchanged lines hidden (view full) --- 216 WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 217} 218 219static void 220sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) 221{ 222 uint32_t res; 223 uint16_t clk; |
224 uint16_t div; |
|
224 int timeout; 225 226 if (clock == slot->clock) 227 return; 228 slot->clock = clock; 229 230 /* Turn off the clock. */ 231 WR2(slot, SDHCI_CLOCK_CONTROL, 0); 232 /* If no clock requested - left it so. */ 233 if (clock == 0) 234 return; | 225 int timeout; 226 227 if (clock == slot->clock) 228 return; 229 slot->clock = clock; 230 231 /* Turn off the clock. */ 232 WR2(slot, SDHCI_CLOCK_CONTROL, 0); 233 /* If no clock requested - left it so. */ 234 if (clock == 0) 235 return; |
235 /* Looking for highest freq <= clock. */ 236 res = slot->max_clk; 237 for (clk = 1; clk < 256; clk <<= 1) { 238 if (res <= clock) 239 break; 240 res >>= 1; | 236 if (slot->version < SDHCI_SPEC_300) { 237 /* Looking for highest freq <= clock. */ 238 res = slot->max_clk; 239 for (div = 1; div < 256; div <<= 1) { 240 if (res <= clock) 241 break; 242 res >>= 1; 243 } 244 /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ 245 div >>= 1; |
241 } | 246 } |
242 /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ 243 clk >>= 1; | 247 else { 248 /* Version 3.0 divisors are multiples of two up to 1023*2 */ 249 if (clock > slot->max_clk) 250 div = 2; 251 else { 252 for (div = 2; div < 1023*2; div += 2) { 253 if ((slot->max_clk / div) <= clock) 254 break; 255 } 256 } 257 div >>= 1; 258 } 259 260 if (bootverbose || sdhci_debug) 261 slot_printf(slot, "Divider %d for freq %d (max %d)\n", 262 div, clock, slot->max_clk); 263 |
244 /* Now we have got divider, set it. */ | 264 /* Now we have got divider, set it. */ |
245 clk <<= SDHCI_DIVIDER_SHIFT; | 265 clk = (div & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT; 266 clk |= ((div >> SDHCI_DIVIDER_MASK_LEN) & SDHCI_DIVIDER_HI_MASK) 267 << SDHCI_DIVIDER_HI_SHIFT; 268 |
246 WR2(slot, SDHCI_CLOCK_CONTROL, clk); 247 /* Enable clock. */ 248 clk |= SDHCI_CLOCK_INT_EN; 249 WR2(slot, SDHCI_CLOCK_CONTROL, clk); 250 /* Wait up to 10 ms until it stabilize. */ 251 timeout = 10; 252 while (!((clk = RD2(slot, SDHCI_CLOCK_CONTROL)) 253 & SDHCI_CLOCK_INT_STABLE)) { --- 229 unchanged lines hidden (view full) --- 483 else 484 return (EFAULT); 485 } 486 487 /* Initialize slot. */ 488 sdhci_init(slot); 489 slot->version = (RD2(slot, SDHCI_HOST_VERSION) 490 >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; | 269 WR2(slot, SDHCI_CLOCK_CONTROL, clk); 270 /* Enable clock. */ 271 clk |= SDHCI_CLOCK_INT_EN; 272 WR2(slot, SDHCI_CLOCK_CONTROL, clk); 273 /* Wait up to 10 ms until it stabilize. */ 274 timeout = 10; 275 while (!((clk = RD2(slot, SDHCI_CLOCK_CONTROL)) 276 & SDHCI_CLOCK_INT_STABLE)) { --- 229 unchanged lines hidden (view full) --- 506 else 507 return (EFAULT); 508 } 509 510 /* Initialize slot. */ 511 sdhci_init(slot); 512 slot->version = (RD2(slot, SDHCI_HOST_VERSION) 513 >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; |
491 caps = RD4(slot, SDHCI_CAPABILITIES); | 514 if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) 515 caps = slot->caps; 516 else 517 caps = RD4(slot, SDHCI_CAPABILITIES); |
492 /* Calculate base clock frequency. */ 493 slot->max_clk = 494 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 495 if (slot->max_clk == 0) { 496 slot->max_clk = 50; 497 device_printf(dev, "Hardware doesn't specify base clock " 498 "frequency.\n"); 499 } 500 slot->max_clk *= 1000000; 501 /* Calculate timeout clock frequency. */ | 518 /* Calculate base clock frequency. */ 519 slot->max_clk = 520 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 521 if (slot->max_clk == 0) { 522 slot->max_clk = 50; 523 device_printf(dev, "Hardware doesn't specify base clock " 524 "frequency.\n"); 525 } 526 slot->max_clk *= 1000000; 527 /* Calculate timeout clock frequency. */ |
502 slot->timeout_clk = 503 (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; | 528 if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) { 529 slot->timeout_clk = slot->max_clk / 1000; 530 } else { 531 slot->timeout_clk = 532 (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 533 if (caps & SDHCI_TIMEOUT_CLK_UNIT) 534 slot->timeout_clk *= 1000; 535 } 536 |
504 if (slot->timeout_clk == 0) { 505 device_printf(dev, "Hardware doesn't specify timeout clock " 506 "frequency.\n"); 507 } | 537 if (slot->timeout_clk == 0) { 538 device_printf(dev, "Hardware doesn't specify timeout clock " 539 "frequency.\n"); 540 } |
508 if (caps & SDHCI_TIMEOUT_CLK_UNIT) 509 slot->timeout_clk *= 1000; | |
510 511 slot->host.f_min = slot->max_clk / 256; 512 slot->host.f_max = slot->max_clk; 513 slot->host.host_ocr = 0; 514 if (caps & SDHCI_CAN_VDD_330) 515 slot->host.host_ocr |= MMC_OCR_320_330 | MMC_OCR_330_340; 516 if (caps & SDHCI_CAN_VDD_300) 517 slot->host.host_ocr |= MMC_OCR_290_300 | MMC_OCR_300_310; --- 292 unchanged lines hidden (view full) --- 810 } 811 /* Compensate for an off-by-one error in the CaFe chip.*/ 812 if (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL) 813 div++; 814 if (div >= 0xF) { 815 slot_printf(slot, "Timeout too large!\n"); 816 div = 0xE; 817 } | 541 542 slot->host.f_min = slot->max_clk / 256; 543 slot->host.f_max = slot->max_clk; 544 slot->host.host_ocr = 0; 545 if (caps & SDHCI_CAN_VDD_330) 546 slot->host.host_ocr |= MMC_OCR_320_330 | MMC_OCR_330_340; 547 if (caps & SDHCI_CAN_VDD_300) 548 slot->host.host_ocr |= MMC_OCR_290_300 | MMC_OCR_300_310; --- 292 unchanged lines hidden (view full) --- 841 } 842 /* Compensate for an off-by-one error in the CaFe chip.*/ 843 if (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL) 844 div++; 845 if (div >= 0xF) { 846 slot_printf(slot, "Timeout too large!\n"); 847 div = 0xE; 848 } |
849 if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 850 div = 0xE; |
|
818 WR1(slot, SDHCI_TIMEOUT_CONTROL, div); 819 820 if (data == NULL) 821 return; 822 823 /* Use DMA if possible. */ 824 if ((slot->opt & SDHCI_HAVE_DMA)) 825 slot->flags |= SDHCI_USE_DMA; --- 475 unchanged lines hidden --- | 851 WR1(slot, SDHCI_TIMEOUT_CONTROL, div); 852 853 if (data == NULL) 854 return; 855 856 /* Use DMA if possible. */ 857 if ((slot->opt & SDHCI_HAVE_DMA)) 858 slot->flags |= SDHCI_USE_DMA; --- 475 unchanged lines hidden --- |