linux/drivers/mmc/host/sdhci-esdhc.h
<<
>>
Prefs
   1/*
   2 * Freescale eSDHC controller driver generics for OF and pltfm.
   3 *
   4 * Copyright (c) 2007 Freescale Semiconductor, Inc.
   5 * Copyright (c) 2009 MontaVista Software, Inc.
   6 * Copyright (c) 2010 Pengutronix e.K.
   7 *   Author: Wolfram Sang <w.sang@pengutronix.de>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License.
  12 */
  13
  14#ifndef _DRIVERS_MMC_SDHCI_ESDHC_H
  15#define _DRIVERS_MMC_SDHCI_ESDHC_H
  16
  17/*
  18 * Ops and quirks for the Freescale eSDHC controller.
  19 */
  20
  21#define ESDHC_DEFAULT_QUIRKS    (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
  22                                SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
  23                                SDHCI_QUIRK_NO_BUSY_IRQ | \
  24                                SDHCI_QUIRK_NONSTANDARD_CLOCK | \
  25                                SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
  26                                SDHCI_QUIRK_PIO_NEEDS_DELAY | \
  27                                SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | \
  28                                SDHCI_QUIRK_NO_CARD_NO_RESET)
  29
  30#define ESDHC_SYSTEM_CONTROL    0x2c
  31#define ESDHC_CLOCK_MASK        0x0000fff0
  32#define ESDHC_PREDIV_SHIFT      8
  33#define ESDHC_DIVIDER_SHIFT     4
  34#define ESDHC_CLOCK_PEREN       0x00000004
  35#define ESDHC_CLOCK_HCKEN       0x00000002
  36#define ESDHC_CLOCK_IPGEN       0x00000001
  37
  38/* pltfm-specific */
  39#define ESDHC_HOST_CONTROL_LE   0x20
  40
  41/* OF-specific */
  42#define ESDHC_DMA_SYSCTL        0x40c
  43#define ESDHC_DMA_SNOOP         0x00000040
  44
  45#define ESDHC_HOST_CONTROL_RES  0x05
  46
  47static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
  48{
  49        int pre_div = 2;
  50        int div = 1;
  51        u32 temp;
  52
  53        temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
  54        temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
  55                | ESDHC_CLOCK_MASK);
  56        sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
  57
  58        if (clock == 0)
  59                goto out;
  60
  61        while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
  62                pre_div *= 2;
  63
  64        while (host->max_clk / pre_div / div > clock && div < 16)
  65                div++;
  66
  67        dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
  68                clock, host->max_clk / pre_div / div);
  69
  70        pre_div >>= 1;
  71        div--;
  72
  73        temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
  74        temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
  75                | (div << ESDHC_DIVIDER_SHIFT)
  76                | (pre_div << ESDHC_PREDIV_SHIFT));
  77        sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
  78        mdelay(100);
  79out:
  80        host->clock = clock;
  81}
  82
  83#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
  84