ti_sdhci.c (271051) | ti_sdhci.c (276287) |
---|---|
1/*- 2 * Copyright (c) 2013 Ian Lepore <ian@freebsd.org> 3 * Copyright (c) 2011 Ben Gray <ben.r.gray@gmail.com>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2013 Ian Lepore <ian@freebsd.org> 3 * Copyright (c) 2011 Ben Gray <ben.r.gray@gmail.com>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_sdhci.c 271051 2014-09-03 20:07:26Z marius $"); | 29__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_sdhci.c 276287 2014-12-27 04:54:36Z ian $"); |
30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/gpio.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/module.h> --- 69 unchanged lines hidden (view full) --- 107 108#define MMCHS_SYSCONFIG 0x010 109#define MMCHS_SYSCONFIG_RESET (1 << 1) 110#define MMCHS_SYSSTATUS 0x014 111#define MMCHS_SYSSTATUS_RESETDONE (1 << 0) 112#define MMCHS_CON 0x02C 113#define MMCHS_CON_DW8 (1 << 5) 114#define MMCHS_CON_DVAL_8_4MS (3 << 9) | 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/gpio.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/module.h> --- 69 unchanged lines hidden (view full) --- 107 108#define MMCHS_SYSCONFIG 0x010 109#define MMCHS_SYSCONFIG_RESET (1 << 1) 110#define MMCHS_SYSSTATUS 0x014 111#define MMCHS_SYSSTATUS_RESETDONE (1 << 0) 112#define MMCHS_CON 0x02C 113#define MMCHS_CON_DW8 (1 << 5) 114#define MMCHS_CON_DVAL_8_4MS (3 << 9) |
115#define MMCHS_CON_OD (1 << 0) |
|
115#define MMCHS_SYSCTL 0x12C 116#define MMCHS_SYSCTL_CLKD_MASK 0x3FF 117#define MMCHS_SYSCTL_CLKD_SHIFT 6 118#define MMCHS_SD_CAPA 0x140 119#define MMCHS_SD_CAPA_VS18 (1 << 26) 120#define MMCHS_SD_CAPA_VS30 (1 << 25) 121#define MMCHS_SD_CAPA_VS33 (1 << 24) 122 --- 199 unchanged lines hidden (view full) --- 322} 323 324static int 325ti_sdhci_update_ios(device_t brdev, device_t reqdev) 326{ 327 struct ti_sdhci_softc *sc = device_get_softc(brdev); 328 struct sdhci_slot *slot; 329 struct mmc_ios *ios; | 116#define MMCHS_SYSCTL 0x12C 117#define MMCHS_SYSCTL_CLKD_MASK 0x3FF 118#define MMCHS_SYSCTL_CLKD_SHIFT 6 119#define MMCHS_SD_CAPA 0x140 120#define MMCHS_SD_CAPA_VS18 (1 << 26) 121#define MMCHS_SD_CAPA_VS30 (1 << 25) 122#define MMCHS_SD_CAPA_VS33 (1 << 24) 123 --- 199 unchanged lines hidden (view full) --- 323} 324 325static int 326ti_sdhci_update_ios(device_t brdev, device_t reqdev) 327{ 328 struct ti_sdhci_softc *sc = device_get_softc(brdev); 329 struct sdhci_slot *slot; 330 struct mmc_ios *ios; |
330 uint32_t val32; | 331 uint32_t val32, newval32; |
331 332 slot = device_get_ivars(reqdev); 333 ios = &slot->host.ios; 334 335 /* 336 * There is an 8-bit-bus bit in the MMCHS control register which, when 337 * set, overrides the 1 vs 4 bit setting in the standard SDHCI 338 * registers. Set that bit first according to whether an 8-bit bus is 339 * requested, then let the standard driver handle everything else. 340 */ 341 val32 = ti_mmchs_read_4(sc, MMCHS_CON); | 332 333 slot = device_get_ivars(reqdev); 334 ios = &slot->host.ios; 335 336 /* 337 * There is an 8-bit-bus bit in the MMCHS control register which, when 338 * set, overrides the 1 vs 4 bit setting in the standard SDHCI 339 * registers. Set that bit first according to whether an 8-bit bus is 340 * requested, then let the standard driver handle everything else. 341 */ 342 val32 = ti_mmchs_read_4(sc, MMCHS_CON); |
343 newval32 = val32; 344 |
|
342 if (ios->bus_width == bus_width_8) | 345 if (ios->bus_width == bus_width_8) |
343 ti_mmchs_write_4(sc, MMCHS_CON, val32 | MMCHS_CON_DW8); | 346 newval32 |= MMCHS_CON_DW8; |
344 else | 347 else |
345 ti_mmchs_write_4(sc, MMCHS_CON, val32 & ~MMCHS_CON_DW8); | 348 newval32 &= ~MMCHS_CON_DW8; |
346 | 349 |
350 if (ios->bus_mode == opendrain) 351 newval32 |= MMCHS_CON_OD; 352 else /* if (ios->bus_mode == pushpull) */ 353 newval32 &= ~MMCHS_CON_OD; 354 355 if (newval32 != val32) 356 ti_mmchs_write_4(sc, MMCHS_CON, newval32); 357 |
|
347 return (sdhci_generic_update_ios(brdev, reqdev)); 348} 349 350static int 351ti_sdhci_get_ro(device_t brdev, device_t reqdev) 352{ 353 struct ti_sdhci_softc *sc = device_get_softc(brdev); 354 unsigned int readonly = 0; --- 32 unchanged lines hidden (view full) --- 387 if (ti_prcm_clk_get_source_freq(clk, &sc->baseclk_hz) != 0) { 388 device_printf(dev, "Error: failed to get source clock freq\n"); 389 return; 390 } 391 392 /* Issue a softreset to the controller */ 393 ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET); 394 timeout = 1000; | 358 return (sdhci_generic_update_ios(brdev, reqdev)); 359} 360 361static int 362ti_sdhci_get_ro(device_t brdev, device_t reqdev) 363{ 364 struct ti_sdhci_softc *sc = device_get_softc(brdev); 365 unsigned int readonly = 0; --- 32 unchanged lines hidden (view full) --- 398 if (ti_prcm_clk_get_source_freq(clk, &sc->baseclk_hz) != 0) { 399 device_printf(dev, "Error: failed to get source clock freq\n"); 400 return; 401 } 402 403 /* Issue a softreset to the controller */ 404 ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET); 405 timeout = 1000; |
395 while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & MMCHS_SYSSTATUS_RESETDONE)) { | 406 while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & 407 MMCHS_SYSSTATUS_RESETDONE)) { |
396 if (--timeout == 0) { | 408 if (--timeout == 0) { |
397 device_printf(dev, "Error: Controller reset operation timed out\n"); | 409 device_printf(dev, 410 "Error: Controller reset operation timed out\n"); |
398 break; 399 } 400 DELAY(100); 401 } 402 | 411 break; 412 } 413 DELAY(100); 414 } 415 |
403 /* Reset both the command and data state machines */ | 416 /* 417 * Reset the command and data state machines and also other aspects of 418 * the controller such as bus clock and power. 419 * 420 * If we read the software reset register too fast after writing it we 421 * can get back a zero that means the reset hasn't started yet rather 422 * than that the reset is complete. Per TI recommendations, work around 423 * it by reading until we see the reset bit asserted, then read until 424 * it's clear. We also set the SDHCI_QUIRK_WAITFOR_RESET_ASSERTED quirk 425 * so that the main sdhci driver uses this same logic in its resets. 426 */ |
404 ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL); | 427 ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL); |
405 timeout = 1000; 406 while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL)) { | 428 timeout = 10000; 429 while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) & 430 SDHCI_RESET_ALL) != SDHCI_RESET_ALL) { |
407 if (--timeout == 0) { | 431 if (--timeout == 0) { |
408 device_printf(dev, "Error: Software reset operation timed out\n"); | |
409 break; 410 } | 432 break; 433 } |
434 DELAY(1); 435 } 436 timeout = 10000; 437 while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) & 438 SDHCI_RESET_ALL)) { 439 if (--timeout == 0) { 440 device_printf(dev, 441 "Error: Software reset operation timed out\n"); 442 break; 443 } |
|
411 DELAY(100); 412 } 413 414 /* 415 * The attach() routine has examined fdt data and set flags in 416 * slot.host.caps to reflect what voltages we can handle. Set those 417 * values in the CAPA register. The manual says that these values can 418 * only be set once, "before initialization" whatever that means, and --- 138 unchanged lines hidden (view full) --- 557 558 /* 559 * The MMCHS hardware shifts the 136-bit response data (in violation of 560 * the spec), so tell the sdhci driver not to do the same in software. 561 */ 562 sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE; 563 564 /* | 444 DELAY(100); 445 } 446 447 /* 448 * The attach() routine has examined fdt data and set flags in 449 * slot.host.caps to reflect what voltages we can handle. Set those 450 * values in the CAPA register. The manual says that these values can 451 * only be set once, "before initialization" whatever that means, and --- 138 unchanged lines hidden (view full) --- 590 591 /* 592 * The MMCHS hardware shifts the 136-bit response data (in violation of 593 * the spec), so tell the sdhci driver not to do the same in software. 594 */ 595 sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE; 596 597 /* |
598 * Reset bits are broken, have to wait to see the bits asserted 599 * before waiting to see them de-asserted. 600 */ 601 sc->slot.quirks |= SDHCI_QUIRK_WAITFOR_RESET_ASSERTED; 602 603 /* |
|
565 * DMA is not really broken, I just haven't implemented it yet. 566 */ 567 sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA; 568 569 /* 570 * Set up the hardware and go. Note that this sets many of the 571 * slot.host.* fields, so we have to do this before overriding any of 572 * those values based on fdt data, below. --- 108 unchanged lines hidden --- | 604 * DMA is not really broken, I just haven't implemented it yet. 605 */ 606 sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA; 607 608 /* 609 * Set up the hardware and go. Note that this sets many of the 610 * slot.host.* fields, so we have to do this before overriding any of 611 * those values based on fdt data, below. --- 108 unchanged lines hidden --- |