11c6a0718SPierre Ossman /* 270f10482SPierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver 31c6a0718SPierre Ossman * 4b69c9058SPierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. 51c6a0718SPierre Ossman * 61c6a0718SPierre Ossman * This program is free software; you can redistribute it and/or modify 71c6a0718SPierre Ossman * it under the terms of the GNU General Public License as published by 81c6a0718SPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 91c6a0718SPierre Ossman * your option) any later version. 1084c46a53SPierre Ossman * 1184c46a53SPierre Ossman * Thanks to the following companies for their support: 1284c46a53SPierre Ossman * 1384c46a53SPierre Ossman * - JMicron (hardware and technical support) 141c6a0718SPierre Ossman */ 151c6a0718SPierre Ossman 161c6a0718SPierre Ossman #include <linux/delay.h> 175a436cc0SAdrian Hunter #include <linux/ktime.h> 181c6a0718SPierre Ossman #include <linux/highmem.h> 19b8c86fc5SPierre Ossman #include <linux/io.h> 2088b47679SPaul Gortmaker #include <linux/module.h> 211c6a0718SPierre Ossman #include <linux/dma-mapping.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 2311763609SRalf Baechle #include <linux/scatterlist.h> 249bea3c85SMarek Szyprowski #include <linux/regulator/consumer.h> 2566fd8ad5SAdrian Hunter #include <linux/pm_runtime.h> 2692e0c44bSZach Brown #include <linux/of.h> 271c6a0718SPierre Ossman 282f730fecSPierre Ossman #include <linux/leds.h> 292f730fecSPierre Ossman 3022113efdSAries Lee #include <linux/mmc/mmc.h> 311c6a0718SPierre Ossman #include <linux/mmc/host.h> 32473b095aSAaron Lu #include <linux/mmc/card.h> 3385cc1c33SCorneliu Doban #include <linux/mmc/sdio.h> 34bec9d4e5SGuennadi Liakhovetski #include <linux/mmc/slot-gpio.h> 351c6a0718SPierre Ossman 361c6a0718SPierre Ossman #include "sdhci.h" 371c6a0718SPierre Ossman 381c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 391c6a0718SPierre Ossman 401c6a0718SPierre Ossman #define DBG(f, x...) \ 41f421865dSAdrian Hunter pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 421c6a0718SPierre Ossman 4385ad90e2SAdrian Hunter #define SDHCI_DUMP(f, x...) \ 4485ad90e2SAdrian Hunter pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 4585ad90e2SAdrian Hunter 46b513ea25SArindam Nath #define MAX_TUNING_LOOP 40 47b513ea25SArindam Nath 481c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 4966fd8ad5SAdrian Hunter static unsigned int debug_quirks2; 501c6a0718SPierre Ossman 511c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *); 521c6a0718SPierre Ossman 5352983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); 541c6a0718SPierre Ossman 55d2898172SAdrian Hunter void sdhci_dumpregs(struct sdhci_host *host) 561c6a0718SPierre Ossman { 5785ad90e2SAdrian Hunter SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); 581c6a0718SPierre Ossman 5985ad90e2SAdrian Hunter SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n", 604e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 614e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 6285ad90e2SAdrian Hunter SDHCI_DUMP("Blk size: 0x%08x | Blk cnt: 0x%08x\n", 634e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 644e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 6585ad90e2SAdrian Hunter SDHCI_DUMP("Argument: 0x%08x | Trn mode: 0x%08x\n", 664e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 674e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 6885ad90e2SAdrian Hunter SDHCI_DUMP("Present: 0x%08x | Host ctl: 0x%08x\n", 694e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 704e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 7185ad90e2SAdrian Hunter SDHCI_DUMP("Power: 0x%08x | Blk gap: 0x%08x\n", 724e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 734e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 7485ad90e2SAdrian Hunter SDHCI_DUMP("Wake-up: 0x%08x | Clock: 0x%08x\n", 754e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 764e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 7785ad90e2SAdrian Hunter SDHCI_DUMP("Timeout: 0x%08x | Int stat: 0x%08x\n", 784e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 794e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 8085ad90e2SAdrian Hunter SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n", 814e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 824e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 8385ad90e2SAdrian Hunter SDHCI_DUMP("AC12 err: 0x%08x | Slot int: 0x%08x\n", 844e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 854e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 8685ad90e2SAdrian Hunter SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n", 874e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 88e8120ad1SPhilip Rakity sdhci_readl(host, SDHCI_CAPABILITIES_1)); 8985ad90e2SAdrian Hunter SDHCI_DUMP("Cmd: 0x%08x | Max curr: 0x%08x\n", 90e8120ad1SPhilip Rakity sdhci_readw(host, SDHCI_COMMAND), 914e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 9285ad90e2SAdrian Hunter SDHCI_DUMP("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n", 937962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE), 947962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 4)); 9585ad90e2SAdrian Hunter SDHCI_DUMP("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n", 967962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 8), 977962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 12)); 9885ad90e2SAdrian Hunter SDHCI_DUMP("Host ctl2: 0x%08x\n", 99f2119df6SArindam Nath sdhci_readw(host, SDHCI_HOST_CONTROL2)); 1001c6a0718SPierre Ossman 101e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_ADMA) { 10285ad90e2SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) { 10385ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", 104c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 105c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI), 106c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 10785ad90e2SAdrian Hunter } else { 10885ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 109c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 110c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 111e57a5f61SAdrian Hunter } 11285ad90e2SAdrian Hunter } 113be3f4ae0SBen Dooks 11485ad90e2SAdrian Hunter SDHCI_DUMP("============================================\n"); 1151c6a0718SPierre Ossman } 116d2898172SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_dumpregs); 1171c6a0718SPierre Ossman 1181c6a0718SPierre Ossman /*****************************************************************************\ 1191c6a0718SPierre Ossman * * 1201c6a0718SPierre Ossman * Low level functions * 1211c6a0718SPierre Ossman * * 1221c6a0718SPierre Ossman \*****************************************************************************/ 1231c6a0718SPierre Ossman 12456a590dcSAdrian Hunter static inline bool sdhci_data_line_cmd(struct mmc_command *cmd) 12556a590dcSAdrian Hunter { 12656a590dcSAdrian Hunter return cmd->data || cmd->flags & MMC_RSP_BUSY; 12756a590dcSAdrian Hunter } 12856a590dcSAdrian Hunter 1297260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1307260cf5eSAnton Vorontsov { 1315b4f1f6cSRussell King u32 present; 1327260cf5eSAnton Vorontsov 133c79396c1SAdrian Hunter if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || 134860951c5SJaehoon Chung !mmc_card_is_removable(host->mmc)) 13566fd8ad5SAdrian Hunter return; 13666fd8ad5SAdrian Hunter 1375b4f1f6cSRussell King if (enable) { 138d25928d1SShawn Guo present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 139d25928d1SShawn Guo SDHCI_CARD_PRESENT; 140d25928d1SShawn Guo 1415b4f1f6cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 1425b4f1f6cSRussell King SDHCI_INT_CARD_INSERT; 1435b4f1f6cSRussell King } else { 1445b4f1f6cSRussell King host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 1455b4f1f6cSRussell King } 146b537f94cSRussell King 147b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 148b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1497260cf5eSAnton Vorontsov } 1507260cf5eSAnton Vorontsov 1517260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host) 1527260cf5eSAnton Vorontsov { 1537260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true); 1547260cf5eSAnton Vorontsov } 1557260cf5eSAnton Vorontsov 1567260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host) 1577260cf5eSAnton Vorontsov { 1587260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false); 1597260cf5eSAnton Vorontsov } 1607260cf5eSAnton Vorontsov 16102d0b685SUlf Hansson static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) 16202d0b685SUlf Hansson { 16302d0b685SUlf Hansson if (host->bus_on) 16402d0b685SUlf Hansson return; 16502d0b685SUlf Hansson host->bus_on = true; 16602d0b685SUlf Hansson pm_runtime_get_noresume(host->mmc->parent); 16702d0b685SUlf Hansson } 16802d0b685SUlf Hansson 16902d0b685SUlf Hansson static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) 17002d0b685SUlf Hansson { 17102d0b685SUlf Hansson if (!host->bus_on) 17202d0b685SUlf Hansson return; 17302d0b685SUlf Hansson host->bus_on = false; 17402d0b685SUlf Hansson pm_runtime_put_noidle(host->mmc->parent); 17502d0b685SUlf Hansson } 17602d0b685SUlf Hansson 17703231f9bSRussell King void sdhci_reset(struct sdhci_host *host, u8 mask) 1781c6a0718SPierre Ossman { 1795a436cc0SAdrian Hunter ktime_t timeout; 180393c1a34SPhilip Rakity 1814e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 1821c6a0718SPierre Ossman 183f0710a55SAdrian Hunter if (mask & SDHCI_RESET_ALL) { 1841c6a0718SPierre Ossman host->clock = 0; 185f0710a55SAdrian Hunter /* Reset-all turns off SD Bus Power */ 186f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 187f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 188f0710a55SAdrian Hunter } 1891c6a0718SPierre Ossman 1901c6a0718SPierre Ossman /* Wait max 100 ms */ 1915a436cc0SAdrian Hunter timeout = ktime_add_ms(ktime_get(), 100); 1921c6a0718SPierre Ossman 1931c6a0718SPierre Ossman /* hw clears the bit when it's done */ 1944e4141a5SAnton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 1955a436cc0SAdrian Hunter if (ktime_after(ktime_get(), timeout)) { 196a3c76eb9SGirish K S pr_err("%s: Reset 0x%x never completed.\n", 1971c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 1981c6a0718SPierre Ossman sdhci_dumpregs(host); 1991c6a0718SPierre Ossman return; 2001c6a0718SPierre Ossman } 2015a436cc0SAdrian Hunter udelay(10); 2021c6a0718SPierre Ossman } 20303231f9bSRussell King } 20403231f9bSRussell King EXPORT_SYMBOL_GPL(sdhci_reset); 205063a9dbbSAnton Vorontsov 20603231f9bSRussell King static void sdhci_do_reset(struct sdhci_host *host, u8 mask) 20703231f9bSRussell King { 20803231f9bSRussell King if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 209d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 210d3940f27SAdrian Hunter 211d3940f27SAdrian Hunter if (!mmc->ops->get_cd(mmc)) 21203231f9bSRussell King return; 21303231f9bSRussell King } 21403231f9bSRussell King 21503231f9bSRussell King host->ops->reset(host, mask); 216393c1a34SPhilip Rakity 217da91a8f9SRussell King if (mask & SDHCI_RESET_ALL) { 2183abc1e80SShaohui Xie if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 219da91a8f9SRussell King if (host->ops->enable_dma) 2203abc1e80SShaohui Xie host->ops->enable_dma(host); 2213abc1e80SShaohui Xie } 222da91a8f9SRussell King 223da91a8f9SRussell King /* Resetting the controller clears many */ 224da91a8f9SRussell King host->preset_enabled = false; 225da91a8f9SRussell King } 2261c6a0718SPierre Ossman } 2271c6a0718SPierre Ossman 228f5c1ab82SAdrian Hunter static void sdhci_set_default_irqs(struct sdhci_host *host) 2291c6a0718SPierre Ossman { 230b537f94cSRussell King host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 231b537f94cSRussell King SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | 232b537f94cSRussell King SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | 233b537f94cSRussell King SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | 234b537f94cSRussell King SDHCI_INT_RESPONSE; 235b537f94cSRussell King 236f37b20ebSDong Aisheng if (host->tuning_mode == SDHCI_TUNING_MODE_2 || 237f37b20ebSDong Aisheng host->tuning_mode == SDHCI_TUNING_MODE_3) 238f37b20ebSDong Aisheng host->ier |= SDHCI_INT_RETUNE; 239f37b20ebSDong Aisheng 240b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 241b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 242f5c1ab82SAdrian Hunter } 243f5c1ab82SAdrian Hunter 244f5c1ab82SAdrian Hunter static void sdhci_init(struct sdhci_host *host, int soft) 245f5c1ab82SAdrian Hunter { 246f5c1ab82SAdrian Hunter struct mmc_host *mmc = host->mmc; 247f5c1ab82SAdrian Hunter 248f5c1ab82SAdrian Hunter if (soft) 249f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 250f5c1ab82SAdrian Hunter else 251f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 252f5c1ab82SAdrian Hunter 253f5c1ab82SAdrian Hunter sdhci_set_default_irqs(host); 2542f4cbb3dSNicolas Pitre 255f12e39dbSAdrian Hunter host->cqe_on = false; 256f12e39dbSAdrian Hunter 2572f4cbb3dSNicolas Pitre if (soft) { 2582f4cbb3dSNicolas Pitre /* force clock reconfiguration */ 2592f4cbb3dSNicolas Pitre host->clock = 0; 260d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 2612f4cbb3dSNicolas Pitre } 2627260cf5eSAnton Vorontsov } 2631c6a0718SPierre Ossman 2647260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 2657260cf5eSAnton Vorontsov { 2662f4cbb3dSNicolas Pitre sdhci_init(host, 0); 2677260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 2681c6a0718SPierre Ossman } 2691c6a0718SPierre Ossman 270061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host) 2711c6a0718SPierre Ossman { 2721c6a0718SPierre Ossman u8 ctrl; 2731c6a0718SPierre Ossman 2744e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 2751c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 2764e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2771c6a0718SPierre Ossman } 2781c6a0718SPierre Ossman 279061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host) 2801c6a0718SPierre Ossman { 2811c6a0718SPierre Ossman u8 ctrl; 2821c6a0718SPierre Ossman 2834e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 2841c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2854e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2861c6a0718SPierre Ossman } 2871c6a0718SPierre Ossman 2884f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS) 2892f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 2902f730fecSPierre Ossman enum led_brightness brightness) 2912f730fecSPierre Ossman { 2922f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2932f730fecSPierre Ossman unsigned long flags; 2942f730fecSPierre Ossman 2952f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 2962f730fecSPierre Ossman 29766fd8ad5SAdrian Hunter if (host->runtime_suspended) 29866fd8ad5SAdrian Hunter goto out; 29966fd8ad5SAdrian Hunter 3002f730fecSPierre Ossman if (brightness == LED_OFF) 301061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 3022f730fecSPierre Ossman else 303061d17a6SAdrian Hunter __sdhci_led_activate(host); 30466fd8ad5SAdrian Hunter out: 3052f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 3062f730fecSPierre Ossman } 307061d17a6SAdrian Hunter 308061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host) 309061d17a6SAdrian Hunter { 310061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc; 311061d17a6SAdrian Hunter 312061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name), 313061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc)); 314061d17a6SAdrian Hunter 315061d17a6SAdrian Hunter host->led.name = host->led_name; 316061d17a6SAdrian Hunter host->led.brightness = LED_OFF; 317061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc); 318061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control; 319061d17a6SAdrian Hunter 320061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led); 321061d17a6SAdrian Hunter } 322061d17a6SAdrian Hunter 323061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host) 324061d17a6SAdrian Hunter { 325061d17a6SAdrian Hunter led_classdev_unregister(&host->led); 326061d17a6SAdrian Hunter } 327061d17a6SAdrian Hunter 328061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 329061d17a6SAdrian Hunter { 330061d17a6SAdrian Hunter } 331061d17a6SAdrian Hunter 332061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 333061d17a6SAdrian Hunter { 334061d17a6SAdrian Hunter } 335061d17a6SAdrian Hunter 336061d17a6SAdrian Hunter #else 337061d17a6SAdrian Hunter 338061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host) 339061d17a6SAdrian Hunter { 340061d17a6SAdrian Hunter return 0; 341061d17a6SAdrian Hunter } 342061d17a6SAdrian Hunter 343061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host) 344061d17a6SAdrian Hunter { 345061d17a6SAdrian Hunter } 346061d17a6SAdrian Hunter 347061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 348061d17a6SAdrian Hunter { 349061d17a6SAdrian Hunter __sdhci_led_activate(host); 350061d17a6SAdrian Hunter } 351061d17a6SAdrian Hunter 352061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 353061d17a6SAdrian Hunter { 354061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 355061d17a6SAdrian Hunter } 356061d17a6SAdrian Hunter 3572f730fecSPierre Ossman #endif 3582f730fecSPierre Ossman 3591c6a0718SPierre Ossman /*****************************************************************************\ 3601c6a0718SPierre Ossman * * 3611c6a0718SPierre Ossman * Core functions * 3621c6a0718SPierre Ossman * * 3631c6a0718SPierre Ossman \*****************************************************************************/ 3641c6a0718SPierre Ossman 3651c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 3661c6a0718SPierre Ossman { 3677659150cSPierre Ossman unsigned long flags; 3687659150cSPierre Ossman size_t blksize, len, chunk; 3697244b85bSSteven Noonan u32 uninitialized_var(scratch); 3707659150cSPierre Ossman u8 *buf; 3711c6a0718SPierre Ossman 3721c6a0718SPierre Ossman DBG("PIO reading\n"); 3731c6a0718SPierre Ossman 3741c6a0718SPierre Ossman blksize = host->data->blksz; 3757659150cSPierre Ossman chunk = 0; 3761c6a0718SPierre Ossman 3777659150cSPierre Ossman local_irq_save(flags); 3781c6a0718SPierre Ossman 3791c6a0718SPierre Ossman while (blksize) { 380bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 3817659150cSPierre Ossman 3827659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 3837659150cSPierre Ossman 3847659150cSPierre Ossman blksize -= len; 3857659150cSPierre Ossman host->sg_miter.consumed = len; 3867659150cSPierre Ossman 3877659150cSPierre Ossman buf = host->sg_miter.addr; 3887659150cSPierre Ossman 3897659150cSPierre Ossman while (len) { 3907659150cSPierre Ossman if (chunk == 0) { 3914e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 3927659150cSPierre Ossman chunk = 4; 3931c6a0718SPierre Ossman } 3941c6a0718SPierre Ossman 3957659150cSPierre Ossman *buf = scratch & 0xFF; 3961c6a0718SPierre Ossman 3977659150cSPierre Ossman buf++; 3987659150cSPierre Ossman scratch >>= 8; 3997659150cSPierre Ossman chunk--; 4007659150cSPierre Ossman len--; 4017659150cSPierre Ossman } 4021c6a0718SPierre Ossman } 4031c6a0718SPierre Ossman 4047659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 4057659150cSPierre Ossman 4067659150cSPierre Ossman local_irq_restore(flags); 4071c6a0718SPierre Ossman } 4081c6a0718SPierre Ossman 4091c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 4101c6a0718SPierre Ossman { 4117659150cSPierre Ossman unsigned long flags; 4127659150cSPierre Ossman size_t blksize, len, chunk; 4137659150cSPierre Ossman u32 scratch; 4147659150cSPierre Ossman u8 *buf; 4151c6a0718SPierre Ossman 4161c6a0718SPierre Ossman DBG("PIO writing\n"); 4171c6a0718SPierre Ossman 4181c6a0718SPierre Ossman blksize = host->data->blksz; 4197659150cSPierre Ossman chunk = 0; 4207659150cSPierre Ossman scratch = 0; 4211c6a0718SPierre Ossman 4227659150cSPierre Ossman local_irq_save(flags); 4231c6a0718SPierre Ossman 4241c6a0718SPierre Ossman while (blksize) { 425bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 4261c6a0718SPierre Ossman 4277659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 4281c6a0718SPierre Ossman 4297659150cSPierre Ossman blksize -= len; 4307659150cSPierre Ossman host->sg_miter.consumed = len; 4317659150cSPierre Ossman 4327659150cSPierre Ossman buf = host->sg_miter.addr; 4337659150cSPierre Ossman 4347659150cSPierre Ossman while (len) { 4357659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 4367659150cSPierre Ossman 4377659150cSPierre Ossman buf++; 4387659150cSPierre Ossman chunk++; 4397659150cSPierre Ossman len--; 4407659150cSPierre Ossman 4417659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 4424e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 4437659150cSPierre Ossman chunk = 0; 4447659150cSPierre Ossman scratch = 0; 4457659150cSPierre Ossman } 4467659150cSPierre Ossman } 4471c6a0718SPierre Ossman } 4481c6a0718SPierre Ossman 4497659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 4501c6a0718SPierre Ossman 4517659150cSPierre Ossman local_irq_restore(flags); 4521c6a0718SPierre Ossman } 4531c6a0718SPierre Ossman 4541c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 4551c6a0718SPierre Ossman { 4561c6a0718SPierre Ossman u32 mask; 4571c6a0718SPierre Ossman 4587659150cSPierre Ossman if (host->blocks == 0) 4591c6a0718SPierre Ossman return; 4601c6a0718SPierre Ossman 4611c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 4621c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 4631c6a0718SPierre Ossman else 4641c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 4651c6a0718SPierre Ossman 4664a3cba32SPierre Ossman /* 4674a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 4684a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 4694a3cba32SPierre Ossman * we can ignore the bits. 4704a3cba32SPierre Ossman */ 4714a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 4724a3cba32SPierre Ossman (host->data->blocks == 1)) 4734a3cba32SPierre Ossman mask = ~0; 4744a3cba32SPierre Ossman 4754e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 4763e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 4773e3bf207SAnton Vorontsov udelay(100); 4783e3bf207SAnton Vorontsov 4791c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 4801c6a0718SPierre Ossman sdhci_read_block_pio(host); 4811c6a0718SPierre Ossman else 4821c6a0718SPierre Ossman sdhci_write_block_pio(host); 4831c6a0718SPierre Ossman 4847659150cSPierre Ossman host->blocks--; 4857659150cSPierre Ossman if (host->blocks == 0) 4861c6a0718SPierre Ossman break; 4871c6a0718SPierre Ossman } 4881c6a0718SPierre Ossman 4891c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 4901c6a0718SPierre Ossman } 4911c6a0718SPierre Ossman 49248857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host, 493c0999b72SRussell King struct mmc_data *data, int cookie) 49448857d9bSRussell King { 49548857d9bSRussell King int sg_count; 49648857d9bSRussell King 49794538e51SRussell King /* 49894538e51SRussell King * If the data buffers are already mapped, return the previous 49994538e51SRussell King * dma_map_sg() result. 50094538e51SRussell King */ 50194538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED) 50248857d9bSRussell King return data->sg_count; 50348857d9bSRussell King 50448857d9bSRussell King sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 505feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 50648857d9bSRussell King 50748857d9bSRussell King if (sg_count == 0) 50848857d9bSRussell King return -ENOSPC; 50948857d9bSRussell King 51048857d9bSRussell King data->sg_count = sg_count; 511c0999b72SRussell King data->host_cookie = cookie; 51248857d9bSRussell King 51348857d9bSRussell King return sg_count; 51448857d9bSRussell King } 51548857d9bSRussell King 5162134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 5172134a922SPierre Ossman { 5182134a922SPierre Ossman local_irq_save(*flags); 519482fce99SCong Wang return kmap_atomic(sg_page(sg)) + sg->offset; 5202134a922SPierre Ossman } 5212134a922SPierre Ossman 5222134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 5232134a922SPierre Ossman { 524482fce99SCong Wang kunmap_atomic(buffer); 5252134a922SPierre Ossman local_irq_restore(*flags); 5262134a922SPierre Ossman } 5272134a922SPierre Ossman 528e57a5f61SAdrian Hunter static void sdhci_adma_write_desc(struct sdhci_host *host, void *desc, 529e57a5f61SAdrian Hunter dma_addr_t addr, int len, unsigned cmd) 530118cd17dSBen Dooks { 531e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 532118cd17dSBen Dooks 533e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */ 5340545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd); 5350545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len); 536e57a5f61SAdrian Hunter dma_desc->addr_lo = cpu_to_le32((u32)addr); 537e57a5f61SAdrian Hunter 538e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 539e57a5f61SAdrian Hunter dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32); 540118cd17dSBen Dooks } 541118cd17dSBen Dooks 542b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc) 543b5ffa674SAdrian Hunter { 544e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 545b5ffa674SAdrian Hunter 546e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */ 5470545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END); 548b5ffa674SAdrian Hunter } 549b5ffa674SAdrian Hunter 55060c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host, 55160c64762SRussell King struct mmc_data *data, int sg_count) 5522134a922SPierre Ossman { 5532134a922SPierre Ossman struct scatterlist *sg; 5542134a922SPierre Ossman unsigned long flags; 555acc3ad13SRussell King dma_addr_t addr, align_addr; 556acc3ad13SRussell King void *desc, *align; 557acc3ad13SRussell King char *buffer; 558acc3ad13SRussell King int len, offset, i; 5592134a922SPierre Ossman 5602134a922SPierre Ossman /* 5612134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 5622134a922SPierre Ossman * We currently guess that it is LE. 5632134a922SPierre Ossman */ 5642134a922SPierre Ossman 56560c64762SRussell King host->sg_count = sg_count; 5662134a922SPierre Ossman 5674efaa6fbSAdrian Hunter desc = host->adma_table; 5682134a922SPierre Ossman align = host->align_buffer; 5692134a922SPierre Ossman 5702134a922SPierre Ossman align_addr = host->align_addr; 5712134a922SPierre Ossman 5722134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5732134a922SPierre Ossman addr = sg_dma_address(sg); 5742134a922SPierre Ossman len = sg_dma_len(sg); 5752134a922SPierre Ossman 5762134a922SPierre Ossman /* 577acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must 578acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce 579acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the 5802134a922SPierre Ossman * alignment. 5812134a922SPierre Ossman */ 58204a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & 58304a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK; 5842134a922SPierre Ossman if (offset) { 5852134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5862134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5872134a922SPierre Ossman memcpy(align, buffer, offset); 5882134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5892134a922SPierre Ossman } 5902134a922SPierre Ossman 591118cd17dSBen Dooks /* tran, valid */ 592e57a5f61SAdrian Hunter sdhci_adma_write_desc(host, desc, align_addr, offset, 593739d46dcSAdrian Hunter ADMA2_TRAN_VALID); 5942134a922SPierre Ossman 5952134a922SPierre Ossman BUG_ON(offset > 65536); 5962134a922SPierre Ossman 59704a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 59804a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN; 5992134a922SPierre Ossman 60076fe379aSAdrian Hunter desc += host->desc_sz; 6012134a922SPierre Ossman 6022134a922SPierre Ossman addr += offset; 6032134a922SPierre Ossman len -= offset; 6042134a922SPierre Ossman } 6052134a922SPierre Ossman 6062134a922SPierre Ossman BUG_ON(len > 65536); 6072134a922SPierre Ossman 608347ea32dSAdrian Hunter if (len) { 609118cd17dSBen Dooks /* tran, valid */ 610347ea32dSAdrian Hunter sdhci_adma_write_desc(host, desc, addr, len, 611347ea32dSAdrian Hunter ADMA2_TRAN_VALID); 61276fe379aSAdrian Hunter desc += host->desc_sz; 613347ea32dSAdrian Hunter } 6142134a922SPierre Ossman 6152134a922SPierre Ossman /* 6162134a922SPierre Ossman * If this triggers then we have a calculation bug 6172134a922SPierre Ossman * somewhere. :/ 6182134a922SPierre Ossman */ 61976fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz); 6202134a922SPierre Ossman } 6212134a922SPierre Ossman 62270764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 623acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */ 6244efaa6fbSAdrian Hunter if (desc != host->adma_table) { 62576fe379aSAdrian Hunter desc -= host->desc_sz; 626b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc); 62770764a90SThomas Abraham } 62870764a90SThomas Abraham } else { 629acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */ 630e57a5f61SAdrian Hunter sdhci_adma_write_desc(host, desc, 0, 0, ADMA2_NOP_END_VALID); 63170764a90SThomas Abraham } 6322134a922SPierre Ossman } 6332134a922SPierre Ossman 6342134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 6352134a922SPierre Ossman struct mmc_data *data) 6362134a922SPierre Ossman { 6372134a922SPierre Ossman struct scatterlist *sg; 6382134a922SPierre Ossman int i, size; 6391c3d5f6dSAdrian Hunter void *align; 6402134a922SPierre Ossman char *buffer; 6412134a922SPierre Ossman unsigned long flags; 6422134a922SPierre Ossman 64347fa9613SRussell King if (data->flags & MMC_DATA_READ) { 64447fa9613SRussell King bool has_unaligned = false; 64547fa9613SRussell King 646de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */ 647de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i) 64804a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 649de0b65a7SRussell King has_unaligned = true; 650de0b65a7SRussell King break; 651de0b65a7SRussell King } 652de0b65a7SRussell King 65347fa9613SRussell King if (has_unaligned) { 6542134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 655f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE); 6562134a922SPierre Ossman 6572134a922SPierre Ossman align = host->align_buffer; 6582134a922SPierre Ossman 6592134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 66004a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 66104a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN - 66204a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK); 6632134a922SPierre Ossman 6642134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 6652134a922SPierre Ossman memcpy(buffer, align, size); 6662134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 6672134a922SPierre Ossman 66804a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 6692134a922SPierre Ossman } 6702134a922SPierre Ossman } 6712134a922SPierre Ossman } 67247fa9613SRussell King } 6732134a922SPierre Ossman } 6742134a922SPierre Ossman 675a3c7778fSAndrei Warkentin static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) 6761c6a0718SPierre Ossman { 6771c6a0718SPierre Ossman u8 count; 678a3c7778fSAndrei Warkentin struct mmc_data *data = cmd->data; 6791c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 6801c6a0718SPierre Ossman 681ee53ab5dSPierre Ossman /* 682ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 683ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 684ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 685ee53ab5dSPierre Ossman * timeout value. 686ee53ab5dSPierre Ossman */ 68711a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 688ee53ab5dSPierre Ossman return 0xE; 689e538fbe8SPierre Ossman 690a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */ 6911d4d7744SUlf Hansson if (!data && !cmd->busy_timeout) 692a3c7778fSAndrei Warkentin return 0xE; 693a3c7778fSAndrei Warkentin 6941c6a0718SPierre Ossman /* timeout in us */ 695a3c7778fSAndrei Warkentin if (!data) 6961d4d7744SUlf Hansson target_timeout = cmd->busy_timeout * 1000; 69778a2ca27SAndy Shevchenko else { 698fafcfda9SRussell King target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); 6997f05538aSRussell King if (host->clock && data->timeout_clks) { 7007f05538aSRussell King unsigned long long val; 7017f05538aSRussell King 7027f05538aSRussell King /* 7037f05538aSRussell King * data->timeout_clks is in units of clock cycles. 7047f05538aSRussell King * host->clock is in Hz. target_timeout is in us. 7057f05538aSRussell King * Hence, us = 1000000 * cycles / Hz. Round up. 7067f05538aSRussell King */ 70702265cd6SHaibo Chen val = 1000000ULL * data->timeout_clks; 7087f05538aSRussell King if (do_div(val, host->clock)) 7097f05538aSRussell King target_timeout++; 7107f05538aSRussell King target_timeout += val; 7117f05538aSRussell King } 71278a2ca27SAndy Shevchenko } 7131c6a0718SPierre Ossman 7141c6a0718SPierre Ossman /* 7151c6a0718SPierre Ossman * Figure out needed cycles. 7161c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 7171c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 7181c6a0718SPierre Ossman * minimum resolution of 6 bits: 7191c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 7201c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 7211c6a0718SPierre Ossman * => 7221c6a0718SPierre Ossman * (1) / (2) > 2^6 7231c6a0718SPierre Ossman */ 7241c6a0718SPierre Ossman count = 0; 7251c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 7261c6a0718SPierre Ossman while (current_timeout < target_timeout) { 7271c6a0718SPierre Ossman count++; 7281c6a0718SPierre Ossman current_timeout <<= 1; 7291c6a0718SPierre Ossman if (count >= 0xF) 7301c6a0718SPierre Ossman break; 7311c6a0718SPierre Ossman } 7321c6a0718SPierre Ossman 7331c6a0718SPierre Ossman if (count >= 0xF) { 734f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n", 735f421865dSAdrian Hunter count, cmd->opcode); 7361c6a0718SPierre Ossman count = 0xE; 7371c6a0718SPierre Ossman } 7381c6a0718SPierre Ossman 739ee53ab5dSPierre Ossman return count; 740ee53ab5dSPierre Ossman } 741ee53ab5dSPierre Ossman 7426aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 7436aa943abSAnton Vorontsov { 7446aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 7456aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 7466aa943abSAnton Vorontsov 7476aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 748b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs; 7496aa943abSAnton Vorontsov else 750b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs; 751b537f94cSRussell King 752b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 753b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 7546aa943abSAnton Vorontsov } 7556aa943abSAnton Vorontsov 756b45e668aSAisheng Dong static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 757ee53ab5dSPierre Ossman { 758ee53ab5dSPierre Ossman u8 count; 759b45e668aSAisheng Dong 760b45e668aSAisheng Dong if (host->ops->set_timeout) { 761b45e668aSAisheng Dong host->ops->set_timeout(host, cmd); 762b45e668aSAisheng Dong } else { 763b45e668aSAisheng Dong count = sdhci_calc_timeout(host, cmd); 764b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 765b45e668aSAisheng Dong } 766b45e668aSAisheng Dong } 767b45e668aSAisheng Dong 768b45e668aSAisheng Dong static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 769b45e668aSAisheng Dong { 7702134a922SPierre Ossman u8 ctrl; 771a3c7778fSAndrei Warkentin struct mmc_data *data = cmd->data; 772ee53ab5dSPierre Ossman 77356a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 774b45e668aSAisheng Dong sdhci_set_timeout(host, cmd); 775a3c7778fSAndrei Warkentin 776a3c7778fSAndrei Warkentin if (!data) 777ee53ab5dSPierre Ossman return; 778ee53ab5dSPierre Ossman 77943dea098SAdrian Hunter WARN_ON(host->data); 78043dea098SAdrian Hunter 781ee53ab5dSPierre Ossman /* Sanity checks */ 782ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 783ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 784ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 785ee53ab5dSPierre Ossman 786ee53ab5dSPierre Ossman host->data = data; 787ee53ab5dSPierre Ossman host->data_early = 0; 788f6a03cbfSMikko Vinni host->data->bytes_xfered = 0; 789ee53ab5dSPierre Ossman 790fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 791fce14421SRussell King struct scatterlist *sg; 792fce14421SRussell King unsigned int length_mask, offset_mask; 793fce14421SRussell King int i; 794fce14421SRussell King 795c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 796c9fddbc4SPierre Ossman 7972134a922SPierre Ossman /* 7982134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 7992134a922SPierre Ossman * scatterlist. 800df953925SRussell King * 801df953925SRussell King * The assumption here being that alignment and lengths are 802df953925SRussell King * the same after DMA mapping to device address space. 8032134a922SPierre Ossman */ 804a0eaf0f9SRussell King length_mask = 0; 805df953925SRussell King offset_mask = 0; 8062134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 807df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) { 808a0eaf0f9SRussell King length_mask = 3; 809df953925SRussell King /* 810df953925SRussell King * As we use up to 3 byte chunks to work 811df953925SRussell King * around alignment problems, we need to 812df953925SRussell King * check the offset as well. 813df953925SRussell King */ 814df953925SRussell King offset_mask = 3; 815df953925SRussell King } 8162134a922SPierre Ossman } else { 8172134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 818a0eaf0f9SRussell King length_mask = 3; 819df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 820df953925SRussell King offset_mask = 3; 8212134a922SPierre Ossman } 8222134a922SPierre Ossman 823df953925SRussell King if (unlikely(length_mask | offset_mask)) { 8242134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 825a0eaf0f9SRussell King if (sg->length & length_mask) { 8262e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n", 8272134a922SPierre Ossman sg->length); 828c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 8292134a922SPierre Ossman break; 8302134a922SPierre Ossman } 831a0eaf0f9SRussell King if (sg->offset & offset_mask) { 8322e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n"); 833c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 8342134a922SPierre Ossman break; 8352134a922SPierre Ossman } 8362134a922SPierre Ossman } 8372134a922SPierre Ossman } 8382134a922SPierre Ossman } 8392134a922SPierre Ossman 8408f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 841c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 8428f1934ceSPierre Ossman 84362a7f368SJiri Slaby if (sg_cnt <= 0) { 8448f1934ceSPierre Ossman /* 8458f1934ceSPierre Ossman * This only happens when someone fed 8468f1934ceSPierre Ossman * us an invalid request. 8478f1934ceSPierre Ossman */ 8488f1934ceSPierre Ossman WARN_ON(1); 849ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 85060c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) { 85160c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt); 85260c64762SRussell King 85360c64762SRussell King sdhci_writel(host, host->adma_addr, SDHCI_ADMA_ADDRESS); 85460c64762SRussell King if (host->flags & SDHCI_USE_64_BIT_DMA) 85560c64762SRussell King sdhci_writel(host, 85660c64762SRussell King (u64)host->adma_addr >> 32, 85760c64762SRussell King SDHCI_ADMA_ADDRESS_HI); 8588f1934ceSPierre Ossman } else { 859719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 8604e4141a5SAnton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 8614e4141a5SAnton Vorontsov SDHCI_DMA_ADDRESS); 8628f1934ceSPierre Ossman } 8638f1934ceSPierre Ossman } 8648f1934ceSPierre Ossman 8652134a922SPierre Ossman /* 8662134a922SPierre Ossman * Always adjust the DMA selection as some controllers 8672134a922SPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 8682134a922SPierre Ossman * is ADMA. 8692134a922SPierre Ossman */ 8702134a922SPierre Ossman if (host->version >= SDHCI_SPEC_200) { 8714e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 8722134a922SPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 8732134a922SPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 874e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA)) { 875e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 876e57a5f61SAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 8772134a922SPierre Ossman else 878e57a5f61SAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 879e57a5f61SAdrian Hunter } else { 8802134a922SPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 881e57a5f61SAdrian Hunter } 8824e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 883c9fddbc4SPierre Ossman } 884c9fddbc4SPierre Ossman 8858f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 886da60a91dSSebastian Andrzej Siewior int flags; 887da60a91dSSebastian Andrzej Siewior 888da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 889da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 890da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 891da60a91dSSebastian Andrzej Siewior else 892da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 893da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 8947659150cSPierre Ossman host->blocks = data->blocks; 8951c6a0718SPierre Ossman } 8961c6a0718SPierre Ossman 8976aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 8986aa943abSAnton Vorontsov 899f6a03cbfSMikko Vinni /* Set the DMA boundary value and block size */ 900c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), 901c846a00fSSrinivas Kandagatla SDHCI_BLOCK_SIZE); 9024e4141a5SAnton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 9031c6a0718SPierre Ossman } 9041c6a0718SPierre Ossman 9050293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host, 9060293d501SAdrian Hunter struct mmc_request *mrq) 9070293d501SAdrian Hunter { 90820845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && 90920845befSAdrian Hunter !mrq->cap_cmd_during_tfr; 9100293d501SAdrian Hunter } 9110293d501SAdrian Hunter 9121c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 913e89d456fSAndrei Warkentin struct mmc_command *cmd) 9141c6a0718SPierre Ossman { 915d3fc5d71SVincent Yang u16 mode = 0; 916e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data; 9171c6a0718SPierre Ossman 9182b558c13SDong Aisheng if (data == NULL) { 9199b8ffea6SVincent Wan if (host->quirks2 & 9209b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { 9219b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 9229b8ffea6SVincent Wan } else { 9232b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */ 9242b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); 9252b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | 9262b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); 9279b8ffea6SVincent Wan } 9281c6a0718SPierre Ossman return; 9292b558c13SDong Aisheng } 9301c6a0718SPierre Ossman 931e538fbe8SPierre Ossman WARN_ON(!host->data); 932e538fbe8SPierre Ossman 933d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) 9341c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 935d3fc5d71SVincent Yang 936e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 937d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; 938e89d456fSAndrei Warkentin /* 939e89d456fSAndrei Warkentin * If we are sending CMD23, CMD12 never gets sent 940e89d456fSAndrei Warkentin * on successful completion (so no Auto-CMD12). 941e89d456fSAndrei Warkentin */ 9420293d501SAdrian Hunter if (sdhci_auto_cmd12(host, cmd->mrq) && 94385cc1c33SCorneliu Doban (cmd->opcode != SD_IO_RW_EXTENDED)) 944e89d456fSAndrei Warkentin mode |= SDHCI_TRNS_AUTO_CMD12; 945a4c73abaSAdrian Hunter else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { 9468edf6371SAndrei Warkentin mode |= SDHCI_TRNS_AUTO_CMD23; 947a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); 948c4512f79SJerry Huang } 9498edf6371SAndrei Warkentin } 9508edf6371SAndrei Warkentin 9511c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 9521c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 953c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 9541c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 9551c6a0718SPierre Ossman 9564e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 9571c6a0718SPierre Ossman } 9581c6a0718SPierre Ossman 9590cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 9600cc563ceSAdrian Hunter { 9610cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) && 9620cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) || 9630cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) || 9640cc563ceSAdrian Hunter (mrq->data && ((mrq->data->error && !mrq->data->stop) || 9650cc563ceSAdrian Hunter (mrq->data->stop && mrq->data->stop->error))) || 9660cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); 9670cc563ceSAdrian Hunter } 9680cc563ceSAdrian Hunter 9694e9f8fe5SAdrian Hunter static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 9704e9f8fe5SAdrian Hunter { 9714e9f8fe5SAdrian Hunter int i; 9724e9f8fe5SAdrian Hunter 9734e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 9744e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) { 9754e9f8fe5SAdrian Hunter WARN_ON(1); 9764e9f8fe5SAdrian Hunter return; 9774e9f8fe5SAdrian Hunter } 9784e9f8fe5SAdrian Hunter } 9794e9f8fe5SAdrian Hunter 9804e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 9814e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) { 9824e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq; 9834e9f8fe5SAdrian Hunter break; 9844e9f8fe5SAdrian Hunter } 9854e9f8fe5SAdrian Hunter } 9864e9f8fe5SAdrian Hunter 9874e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS); 9884e9f8fe5SAdrian Hunter 9894e9f8fe5SAdrian Hunter tasklet_schedule(&host->finish_tasklet); 9904e9f8fe5SAdrian Hunter } 9914e9f8fe5SAdrian Hunter 992a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 993a6d3bdd5SAdrian Hunter { 9945a8a3fefSAdrian Hunter if (host->cmd && host->cmd->mrq == mrq) 9955a8a3fefSAdrian Hunter host->cmd = NULL; 9965a8a3fefSAdrian Hunter 9975a8a3fefSAdrian Hunter if (host->data_cmd && host->data_cmd->mrq == mrq) 9985a8a3fefSAdrian Hunter host->data_cmd = NULL; 9995a8a3fefSAdrian Hunter 10005a8a3fefSAdrian Hunter if (host->data && host->data->mrq == mrq) 10015a8a3fefSAdrian Hunter host->data = NULL; 10025a8a3fefSAdrian Hunter 1003ed1563deSAdrian Hunter if (sdhci_needs_reset(host, mrq)) 1004ed1563deSAdrian Hunter host->pending_reset = true; 1005ed1563deSAdrian Hunter 10064e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq); 1007a6d3bdd5SAdrian Hunter } 1008a6d3bdd5SAdrian Hunter 10091c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *host) 10101c6a0718SPierre Ossman { 101133a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 101233a57adbSAdrian Hunter struct mmc_data *data = host->data; 10131c6a0718SPierre Ossman 10141c6a0718SPierre Ossman host->data = NULL; 10157c89a3d9SAdrian Hunter host->data_cmd = NULL; 10161c6a0718SPierre Ossman 1017add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 1018add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) 10192134a922SPierre Ossman sdhci_adma_table_post(host, data); 1020f55c98f7SRussell King 10211c6a0718SPierre Ossman /* 1022c9b74c5bSPierre Ossman * The specification states that the block count register must 1023c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 1024c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 1025c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 1026c9b74c5bSPierre Ossman * in the event of an error. 10271c6a0718SPierre Ossman */ 1028c9b74c5bSPierre Ossman if (data->error) 1029c9b74c5bSPierre Ossman data->bytes_xfered = 0; 10301c6a0718SPierre Ossman else 1031c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 10321c6a0718SPierre Ossman 1033e89d456fSAndrei Warkentin /* 1034e89d456fSAndrei Warkentin * Need to send CMD12 if - 1035e89d456fSAndrei Warkentin * a) open-ended multiblock transfer (no CMD23) 1036e89d456fSAndrei Warkentin * b) error in multiblock transfer 1037e89d456fSAndrei Warkentin */ 1038e89d456fSAndrei Warkentin if (data->stop && 1039e89d456fSAndrei Warkentin (data->error || 1040a4c73abaSAdrian Hunter !data->mrq->sbc)) { 1041e89d456fSAndrei Warkentin 10421c6a0718SPierre Ossman /* 10431c6a0718SPierre Ossman * The controller needs a reset of internal state machines 10441c6a0718SPierre Ossman * upon error conditions. 10451c6a0718SPierre Ossman */ 104617b0429dSPierre Ossman if (data->error) { 104733a57adbSAdrian Hunter if (!host->cmd || host->cmd == data_cmd) 104803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 104903231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 10501c6a0718SPierre Ossman } 10511c6a0718SPierre Ossman 105220845befSAdrian Hunter /* 105320845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line 105420845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's 105520845befSAdrian Hunter * responsibility to send the stop command if required. 105620845befSAdrian Hunter */ 105720845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) { 105820845befSAdrian Hunter sdhci_finish_mrq(host, data->mrq); 105920845befSAdrian Hunter } else { 10608842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */ 10618842fd17SAdrian Hunter host->cmd = NULL; 10621c6a0718SPierre Ossman sdhci_send_command(host, data->stop); 106320845befSAdrian Hunter } 1064a6d3bdd5SAdrian Hunter } else { 1065a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, data->mrq); 1066a6d3bdd5SAdrian Hunter } 10671c6a0718SPierre Ossman } 10681c6a0718SPierre Ossman 1069d7422fb4SAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, 1070d7422fb4SAdrian Hunter unsigned long timeout) 1071d7422fb4SAdrian Hunter { 1072d7422fb4SAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 1073d7422fb4SAdrian Hunter mod_timer(&host->data_timer, timeout); 1074d7422fb4SAdrian Hunter else 1075d7422fb4SAdrian Hunter mod_timer(&host->timer, timeout); 1076d7422fb4SAdrian Hunter } 1077d7422fb4SAdrian Hunter 1078d7422fb4SAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) 1079d7422fb4SAdrian Hunter { 1080d7422fb4SAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 1081d7422fb4SAdrian Hunter del_timer(&host->data_timer); 1082d7422fb4SAdrian Hunter else 1083d7422fb4SAdrian Hunter del_timer(&host->timer); 1084d7422fb4SAdrian Hunter } 1085d7422fb4SAdrian Hunter 1086c0e55129SDong Aisheng void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 10871c6a0718SPierre Ossman { 10881c6a0718SPierre Ossman int flags; 10891c6a0718SPierre Ossman u32 mask; 10901c6a0718SPierre Ossman unsigned long timeout; 10911c6a0718SPierre Ossman 10921c6a0718SPierre Ossman WARN_ON(host->cmd); 10931c6a0718SPierre Ossman 109496776200SRussell King /* Initially, a command has no error */ 109596776200SRussell King cmd->error = 0; 109696776200SRussell King 1097fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && 1098fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION) 1099fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY; 1100fc605f1dSAdrian Hunter 11011c6a0718SPierre Ossman /* Wait max 10 ms */ 11021c6a0718SPierre Ossman timeout = 10; 11031c6a0718SPierre Ossman 11041c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 110556a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 11061c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 11071c6a0718SPierre Ossman 11081c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 11091c6a0718SPierre Ossman though they might use busy signaling */ 1110a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) 11111c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 11121c6a0718SPierre Ossman 11134e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 11141c6a0718SPierre Ossman if (timeout == 0) { 11152e4456f0SMarek Vasut pr_err("%s: Controller never released inhibit bit(s).\n", 11162e4456f0SMarek Vasut mmc_hostname(host->mmc)); 11171c6a0718SPierre Ossman sdhci_dumpregs(host); 111817b0429dSPierre Ossman cmd->error = -EIO; 1119a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 11201c6a0718SPierre Ossman return; 11211c6a0718SPierre Ossman } 11221c6a0718SPierre Ossman timeout--; 11231c6a0718SPierre Ossman mdelay(1); 11241c6a0718SPierre Ossman } 11251c6a0718SPierre Ossman 11263e1a6892SAdrian Hunter timeout = jiffies; 11271d4d7744SUlf Hansson if (!cmd->data && cmd->busy_timeout > 9000) 11281d4d7744SUlf Hansson timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 11293e1a6892SAdrian Hunter else 11303e1a6892SAdrian Hunter timeout += 10 * HZ; 1131d7422fb4SAdrian Hunter sdhci_mod_timer(host, cmd->mrq, timeout); 11321c6a0718SPierre Ossman 11331c6a0718SPierre Ossman host->cmd = cmd; 113456a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) { 11357c89a3d9SAdrian Hunter WARN_ON(host->data_cmd); 11367c89a3d9SAdrian Hunter host->data_cmd = cmd; 11377c89a3d9SAdrian Hunter } 11381c6a0718SPierre Ossman 1139a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd); 11401c6a0718SPierre Ossman 11414e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 11421c6a0718SPierre Ossman 1143e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd); 11441c6a0718SPierre Ossman 11451c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1146a3c76eb9SGirish K S pr_err("%s: Unsupported response type!\n", 11471c6a0718SPierre Ossman mmc_hostname(host->mmc)); 114817b0429dSPierre Ossman cmd->error = -EINVAL; 1149a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 11501c6a0718SPierre Ossman return; 11511c6a0718SPierre Ossman } 11521c6a0718SPierre Ossman 11531c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 11541c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 11551c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 11561c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 11571c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 11581c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 11591c6a0718SPierre Ossman else 11601c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 11611c6a0718SPierre Ossman 11621c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 11631c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 11641c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 11651c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 1166b513ea25SArindam Nath 1167b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 1168069c9f14SGirish K S if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || 1169069c9f14SGirish K S cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) 11701c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 11711c6a0718SPierre Ossman 11724e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 11731c6a0718SPierre Ossman } 1174c0e55129SDong Aisheng EXPORT_SYMBOL_GPL(sdhci_send_command); 11751c6a0718SPierre Ossman 11764a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) 11774a5fc119SAdrian Hunter { 11784a5fc119SAdrian Hunter int i, reg; 11794a5fc119SAdrian Hunter 11804a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 11814a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4; 11824a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg); 11834a5fc119SAdrian Hunter } 11844a5fc119SAdrian Hunter 11851284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) 11861284c248SKishon Vijay Abraham I return; 11871284c248SKishon Vijay Abraham I 11884a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */ 11894a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 11904a5fc119SAdrian Hunter cmd->resp[i] <<= 8; 11914a5fc119SAdrian Hunter if (i != 3) 11924a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24; 11934a5fc119SAdrian Hunter } 11944a5fc119SAdrian Hunter } 11954a5fc119SAdrian Hunter 11961c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 11971c6a0718SPierre Ossman { 1198e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd; 11991c6a0718SPierre Ossman 1200e0a5640aSAdrian Hunter host->cmd = NULL; 1201e0a5640aSAdrian Hunter 1202e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) { 1203e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) { 12044a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd); 12051c6a0718SPierre Ossman } else { 1206e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 12071c6a0718SPierre Ossman } 12081c6a0718SPierre Ossman } 12091c6a0718SPierre Ossman 121020845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 121120845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq); 121220845befSAdrian Hunter 12136bde8681SAdrian Hunter /* 12146bde8681SAdrian Hunter * The host can send and interrupt when the busy state has 12156bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles. 12166bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting 12176bde8681SAdrian Hunter * for data to complete. 12186bde8681SAdrian Hunter * 12196bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this 12206bde8681SAdrian Hunter * feature so there might be some problems with older 12216bde8681SAdrian Hunter * controllers. 12226bde8681SAdrian Hunter */ 1223e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) { 1224e0a5640aSAdrian Hunter if (cmd->data) { 12256bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer"); 12266bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 1227ea968023SAdrian Hunter cmd == host->data_cmd) { 1228ea968023SAdrian Hunter /* Command complete before busy is ended */ 12296bde8681SAdrian Hunter return; 12306bde8681SAdrian Hunter } 12316bde8681SAdrian Hunter } 12326bde8681SAdrian Hunter 1233e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */ 1234a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) { 1235a4c73abaSAdrian Hunter sdhci_send_command(host, cmd->mrq->cmd); 1236e89d456fSAndrei Warkentin } else { 1237e89d456fSAndrei Warkentin 1238e89d456fSAndrei Warkentin /* Processed actual command. */ 1239e538fbe8SPierre Ossman if (host->data && host->data_early) 1240e538fbe8SPierre Ossman sdhci_finish_data(host); 1241e538fbe8SPierre Ossman 1242e0a5640aSAdrian Hunter if (!cmd->data) 1243a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 12441c6a0718SPierre Ossman } 1245e89d456fSAndrei Warkentin } 12461c6a0718SPierre Ossman 124752983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host) 124852983382SKevin Liu { 1249d975f121SRussell King u16 preset = 0; 125052983382SKevin Liu 1251d975f121SRussell King switch (host->timing) { 1252d975f121SRussell King case MMC_TIMING_UHS_SDR12: 125352983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 125452983382SKevin Liu break; 1255d975f121SRussell King case MMC_TIMING_UHS_SDR25: 125652983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); 125752983382SKevin Liu break; 1258d975f121SRussell King case MMC_TIMING_UHS_SDR50: 125952983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); 126052983382SKevin Liu break; 1261d975f121SRussell King case MMC_TIMING_UHS_SDR104: 1262d975f121SRussell King case MMC_TIMING_MMC_HS200: 126352983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); 126452983382SKevin Liu break; 1265d975f121SRussell King case MMC_TIMING_UHS_DDR50: 12660dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52: 126752983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); 126852983382SKevin Liu break; 1269e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 1270e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); 1271e9fb05d5SAdrian Hunter break; 127252983382SKevin Liu default: 127352983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n", 127452983382SKevin Liu mmc_hostname(host->mmc)); 127552983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 127652983382SKevin Liu break; 127752983382SKevin Liu } 127852983382SKevin Liu return preset; 127952983382SKevin Liu } 128052983382SKevin Liu 1281fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, 1282fb9ee047SLudovic Desroches unsigned int *actual_clock) 12831c6a0718SPierre Ossman { 1284c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */ 1285df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1; 1286c3ed3877SArindam Nath u16 clk = 0; 12875497159cSludovic.desroches@atmel.com bool switch_base_clk = false; 12881c6a0718SPierre Ossman 128985105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1290da91a8f9SRussell King if (host->preset_enabled) { 129152983382SKevin Liu u16 pre_val; 129252983382SKevin Liu 129352983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 129452983382SKevin Liu pre_val = sdhci_get_preset_value(host); 129552983382SKevin Liu div = (pre_val & SDHCI_PRESET_SDCLK_FREQ_MASK) 129652983382SKevin Liu >> SDHCI_PRESET_SDCLK_FREQ_SHIFT; 129752983382SKevin Liu if (host->clk_mul && 129852983382SKevin Liu (pre_val & SDHCI_PRESET_CLKGEN_SEL_MASK)) { 129952983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE; 130052983382SKevin Liu real_div = div + 1; 130152983382SKevin Liu clk_mul = host->clk_mul; 130252983382SKevin Liu } else { 130352983382SKevin Liu real_div = max_t(int, 1, div << 1); 130452983382SKevin Liu } 130552983382SKevin Liu goto clock_set; 130652983382SKevin Liu } 130752983382SKevin Liu 1308c3ed3877SArindam Nath /* 1309c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock 1310c3ed3877SArindam Nath * Mode. 1311c3ed3877SArindam Nath */ 1312c3ed3877SArindam Nath if (host->clk_mul) { 1313c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) { 131452983382SKevin Liu if ((host->max_clk * host->clk_mul / div) 131552983382SKevin Liu <= clock) 1316c3ed3877SArindam Nath break; 1317c3ed3877SArindam Nath } 13185497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) { 1319c3ed3877SArindam Nath /* 1320c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock 1321c3ed3877SArindam Nath * Control register. 1322c3ed3877SArindam Nath */ 1323c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1324df16219fSGiuseppe CAVALLARO real_div = div; 1325df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul; 1326c3ed3877SArindam Nath div--; 1327c3ed3877SArindam Nath } else { 13285497159cSludovic.desroches@atmel.com /* 13295497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock 13305497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock. 13315497159cSludovic.desroches@atmel.com */ 13325497159cSludovic.desroches@atmel.com switch_base_clk = true; 13335497159cSludovic.desroches@atmel.com } 13345497159cSludovic.desroches@atmel.com } 13355497159cSludovic.desroches@atmel.com 13365497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) { 133785105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 133885105c53SZhangfei Gao if (host->max_clk <= clock) 133985105c53SZhangfei Gao div = 1; 134085105c53SZhangfei Gao else { 1341c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1342c3ed3877SArindam Nath div += 2) { 134385105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 134485105c53SZhangfei Gao break; 134585105c53SZhangfei Gao } 134685105c53SZhangfei Gao } 1347df16219fSGiuseppe CAVALLARO real_div = div; 1348c3ed3877SArindam Nath div >>= 1; 1349d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) 1350d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000) 1351d1955c3aSSuneel Garapati div = 1; 1352c3ed3877SArindam Nath } 135385105c53SZhangfei Gao } else { 135485105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 13550397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 13561c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 13571c6a0718SPierre Ossman break; 13581c6a0718SPierre Ossman } 1359df16219fSGiuseppe CAVALLARO real_div = div; 13601c6a0718SPierre Ossman div >>= 1; 1361c3ed3877SArindam Nath } 13621c6a0718SPierre Ossman 136352983382SKevin Liu clock_set: 136403d6f5ffSAisheng Dong if (real_div) 1365fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div; 1366c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 136785105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 136885105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1369fb9ee047SLudovic Desroches 1370fb9ee047SLudovic Desroches return clk; 1371fb9ee047SLudovic Desroches } 1372fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk); 1373fb9ee047SLudovic Desroches 1374fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk) 1375fb9ee047SLudovic Desroches { 13765a436cc0SAdrian Hunter ktime_t timeout; 1377fb9ee047SLudovic Desroches 13781c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 13794e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 13801c6a0718SPierre Ossman 138127f6cb16SChris Ball /* Wait max 20 ms */ 13825a436cc0SAdrian Hunter timeout = ktime_add_ms(ktime_get(), 20); 13834e4141a5SAnton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 13841c6a0718SPierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 13855a436cc0SAdrian Hunter if (ktime_after(ktime_get(), timeout)) { 13862e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n", 13872e4456f0SMarek Vasut mmc_hostname(host->mmc)); 13881c6a0718SPierre Ossman sdhci_dumpregs(host); 13891c6a0718SPierre Ossman return; 13901c6a0718SPierre Ossman } 13915a436cc0SAdrian Hunter udelay(10); 13921c6a0718SPierre Ossman } 13931c6a0718SPierre Ossman 13941c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 13954e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 13961c6a0718SPierre Ossman } 1397fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk); 1398fec79673SRitesh Harjani 1399fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 1400fec79673SRitesh Harjani { 1401fec79673SRitesh Harjani u16 clk; 1402fec79673SRitesh Harjani 1403fec79673SRitesh Harjani host->mmc->actual_clock = 0; 1404fec79673SRitesh Harjani 1405fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 1406fec79673SRitesh Harjani 1407fec79673SRitesh Harjani if (clock == 0) 1408fec79673SRitesh Harjani return; 1409fec79673SRitesh Harjani 1410fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 1411fec79673SRitesh Harjani sdhci_enable_clk(host, clk); 1412fec79673SRitesh Harjani } 14131771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock); 14141c6a0718SPierre Ossman 14151dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, 141624fbb3caSRussell King unsigned short vdd) 14171c6a0718SPierre Ossman { 14183a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 14191dceb041SAdrian Hunter 14201dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 14211dceb041SAdrian Hunter 14221dceb041SAdrian Hunter if (mode != MMC_POWER_OFF) 14231dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); 14241dceb041SAdrian Hunter else 14251dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 14261dceb041SAdrian Hunter } 14271dceb041SAdrian Hunter 1428606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, 14291dceb041SAdrian Hunter unsigned short vdd) 14301dceb041SAdrian Hunter { 14318364248aSGiuseppe Cavallaro u8 pwr = 0; 14321c6a0718SPierre Ossman 143324fbb3caSRussell King if (mode != MMC_POWER_OFF) { 143424fbb3caSRussell King switch (1 << vdd) { 1435ae628903SPierre Ossman case MMC_VDD_165_195: 1436ae628903SPierre Ossman pwr = SDHCI_POWER_180; 1437ae628903SPierre Ossman break; 1438ae628903SPierre Ossman case MMC_VDD_29_30: 1439ae628903SPierre Ossman case MMC_VDD_30_31: 1440ae628903SPierre Ossman pwr = SDHCI_POWER_300; 1441ae628903SPierre Ossman break; 1442ae628903SPierre Ossman case MMC_VDD_32_33: 1443ae628903SPierre Ossman case MMC_VDD_33_34: 1444ae628903SPierre Ossman pwr = SDHCI_POWER_330; 1445ae628903SPierre Ossman break; 1446ae628903SPierre Ossman default: 14479d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n", 14489d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd); 14499d5de93fSAdrian Hunter break; 1450ae628903SPierre Ossman } 1451ae628903SPierre Ossman } 1452ae628903SPierre Ossman 1453ae628903SPierre Ossman if (host->pwr == pwr) 1454e921a8b6SRussell King return; 14551c6a0718SPierre Ossman 1456ae628903SPierre Ossman host->pwr = pwr; 1457ae628903SPierre Ossman 1458ae628903SPierre Ossman if (pwr == 0) { 14594e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1460f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 1461f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 1462e921a8b6SRussell King } else { 14631c6a0718SPierre Ossman /* 14641c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 14651c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 14661c6a0718SPierre Ossman */ 1467b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 14684e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 14691c6a0718SPierre Ossman 1470e08c1694SAndres Salomon /* 1471e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the 1472e921a8b6SRussell King * voltage and set turn on power at the same time, so set the 1473e921a8b6SRussell King * voltage first. 1474e08c1694SAndres Salomon */ 147511a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 14764e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 14771c6a0718SPierre Ossman 1478ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 1479ae628903SPierre Ossman 1480ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1481557b0697SHarald Welte 1482f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 1483f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host); 1484f0710a55SAdrian Hunter 1485557b0697SHarald Welte /* 1486e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before 1487e921a8b6SRussell King * they can apply clock after applying power 1488557b0697SHarald Welte */ 148911a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1490557b0697SHarald Welte mdelay(10); 1491e921a8b6SRussell King } 1492918f4cbdSJisheng Zhang } 1493606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); 14941dceb041SAdrian Hunter 1495606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode, 14961dceb041SAdrian Hunter unsigned short vdd) 14971dceb041SAdrian Hunter { 1498606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc)) 1499606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd); 15001dceb041SAdrian Hunter else 1501606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd); 15021c6a0718SPierre Ossman } 1503606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power); 15041c6a0718SPierre Ossman 15051c6a0718SPierre Ossman /*****************************************************************************\ 15061c6a0718SPierre Ossman * * 15071c6a0718SPierre Ossman * MMC callbacks * 15081c6a0718SPierre Ossman * * 15091c6a0718SPierre Ossman \*****************************************************************************/ 15101c6a0718SPierre Ossman 15111c6a0718SPierre Ossman static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 15121c6a0718SPierre Ossman { 15131c6a0718SPierre Ossman struct sdhci_host *host; 1514505a8680SShawn Guo int present; 15151c6a0718SPierre Ossman unsigned long flags; 15161c6a0718SPierre Ossman 15171c6a0718SPierre Ossman host = mmc_priv(mmc); 15181c6a0718SPierre Ossman 151904e079cfSScott Branden /* Firstly check card presence */ 15208d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc); 15212836766aSKrzysztof Kozlowski 15221c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 15231c6a0718SPierre Ossman 1524061d17a6SAdrian Hunter sdhci_led_activate(host); 1525e89d456fSAndrei Warkentin 1526e89d456fSAndrei Warkentin /* 1527e89d456fSAndrei Warkentin * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED 1528e89d456fSAndrei Warkentin * requests if Auto-CMD12 is enabled. 1529e89d456fSAndrei Warkentin */ 15300293d501SAdrian Hunter if (sdhci_auto_cmd12(host, mrq)) { 1531c4512f79SJerry Huang if (mrq->stop) { 1532c4512f79SJerry Huang mrq->data->stop = NULL; 1533c4512f79SJerry Huang mrq->stop = NULL; 1534c4512f79SJerry Huang } 1535c4512f79SJerry Huang } 15361c6a0718SPierre Ossman 153768d1fb7eSAnton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 1538a4c73abaSAdrian Hunter mrq->cmd->error = -ENOMEDIUM; 1539a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, mrq); 1540cf2b5eeaSArindam Nath } else { 15418edf6371SAndrei Warkentin if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) 1542e89d456fSAndrei Warkentin sdhci_send_command(host, mrq->sbc); 1543e89d456fSAndrei Warkentin else 15441c6a0718SPierre Ossman sdhci_send_command(host, mrq->cmd); 1545cf2b5eeaSArindam Nath } 15461c6a0718SPierre Ossman 15471c6a0718SPierre Ossman mmiowb(); 15481c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 15491c6a0718SPierre Ossman } 15501c6a0718SPierre Ossman 15512317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width) 15522317f56cSRussell King { 15532317f56cSRussell King u8 ctrl; 15542317f56cSRussell King 15552317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 15562317f56cSRussell King if (width == MMC_BUS_WIDTH_8) { 15572317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 15582317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS; 15592317f56cSRussell King } else { 156098f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA) 15612317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS; 15622317f56cSRussell King if (width == MMC_BUS_WIDTH_4) 15632317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS; 15642317f56cSRussell King else 15652317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 15662317f56cSRussell King } 15672317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 15682317f56cSRussell King } 15692317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width); 15702317f56cSRussell King 157196d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) 157296d7b78cSRussell King { 157396d7b78cSRussell King u16 ctrl_2; 157496d7b78cSRussell King 157596d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 157696d7b78cSRussell King /* Select Bus Speed Mode for host */ 157796d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 157896d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) || 157996d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104)) 158096d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 158196d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12) 158296d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 158396d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR25) 158496d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 158596d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50) 158696d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 158796d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) || 158896d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52)) 158996d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 1590e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400) 1591e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ 159296d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 159396d7b78cSRussell King } 159496d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); 159596d7b78cSRussell King 15966a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 15971c6a0718SPierre Ossman { 1598ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 15991c6a0718SPierre Ossman u8 ctrl; 16001c6a0718SPierre Ossman 160184ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED) 160284ec048bSAdrian Hunter return; 160384ec048bSAdrian Hunter 1604ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) { 16053a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) && 16063a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF) 16074e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 1608ceb6143bSAdrian Hunter return; 1609ceb6143bSAdrian Hunter } 16101e72859eSPierre Ossman 16111c6a0718SPierre Ossman /* 16121c6a0718SPierre Ossman * Reset the chip on each power off. 16131c6a0718SPierre Ossman * Should clear out any weird states. 16141c6a0718SPierre Ossman */ 16151c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 16164e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 16177260cf5eSAnton Vorontsov sdhci_reinit(host); 16181c6a0718SPierre Ossman } 16191c6a0718SPierre Ossman 162052983382SKevin Liu if (host->version >= SDHCI_SPEC_300 && 1621372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) && 1622372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 162352983382SKevin Liu sdhci_enable_preset_value(host, false); 162452983382SKevin Liu 1625373073efSRussell King if (!ios->clock || ios->clock != host->clock) { 16261771059cSRussell King host->ops->set_clock(host, ios->clock); 1627373073efSRussell King host->clock = ios->clock; 162803d6f5ffSAisheng Dong 162903d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && 163003d6f5ffSAisheng Dong host->clock) { 163103d6f5ffSAisheng Dong host->timeout_clk = host->mmc->actual_clock ? 163203d6f5ffSAisheng Dong host->mmc->actual_clock / 1000 : 163303d6f5ffSAisheng Dong host->clock / 1000; 163403d6f5ffSAisheng Dong host->mmc->max_busy_timeout = 163503d6f5ffSAisheng Dong host->ops->get_max_timeout_count ? 163603d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) : 163703d6f5ffSAisheng Dong 1 << 27; 163803d6f5ffSAisheng Dong host->mmc->max_busy_timeout /= host->timeout_clk; 163903d6f5ffSAisheng Dong } 1640373073efSRussell King } 16411c6a0718SPierre Ossman 1642606d3131SAdrian Hunter if (host->ops->set_power) 1643606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd); 1644606d3131SAdrian Hunter else 1645606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd); 16461c6a0718SPierre Ossman 1647643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 1648643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1649643a81ffSPhilip Rakity 16502317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width); 165115ec4461SPhilip Rakity 165215ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 16531c6a0718SPierre Ossman 1654501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { 1655501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS || 1656273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS || 1657273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 || 1658273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 || 1659273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 || 1660273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 || 1661273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 || 1662273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 || 1663273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25) 16641c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 16651c6a0718SPierre Ossman else 16661c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 1667501639bfSyangbo lu } 16681c6a0718SPierre Ossman 1669d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) { 167049c468fcSArindam Nath u16 clk, ctrl_2; 167149c468fcSArindam Nath 1672da91a8f9SRussell King if (!host->preset_enabled) { 1673758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1674d6d50a15SArindam Nath /* 1675d6d50a15SArindam Nath * We only need to set Driver Strength if the 1676d6d50a15SArindam Nath * preset value enable is not set. 1677d6d50a15SArindam Nath */ 1678da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1679d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 1680d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 1681d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 168243e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B) 168343e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 1684d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 1685d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 168643e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D) 168743e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D; 168843e943a0SPetri Gynther else { 16892e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n", 16902e4456f0SMarek Vasut mmc_hostname(mmc)); 169143e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 169243e943a0SPetri Gynther } 1693d6d50a15SArindam Nath 1694d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 1695758535c4SArindam Nath } else { 1696758535c4SArindam Nath /* 1697758535c4SArindam Nath * According to SDHC Spec v3.00, if the Preset Value 1698758535c4SArindam Nath * Enable in the Host Control 2 register is set, we 1699758535c4SArindam Nath * need to reset SD Clock Enable before changing High 1700758535c4SArindam Nath * Speed Enable to avoid generating clock gliches. 1701758535c4SArindam Nath */ 1702758535c4SArindam Nath 1703758535c4SArindam Nath /* Reset SD Clock Enable */ 1704758535c4SArindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1705758535c4SArindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 1706758535c4SArindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1707758535c4SArindam Nath 1708758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1709758535c4SArindam Nath 1710758535c4SArindam Nath /* Re-enable SD Clock */ 17111771059cSRussell King host->ops->set_clock(host, host->clock); 1712d6d50a15SArindam Nath } 171349c468fcSArindam Nath 17146322cdd0SPhilip Rakity /* Reset SD Clock Enable */ 17156322cdd0SPhilip Rakity clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 17166322cdd0SPhilip Rakity clk &= ~SDHCI_CLOCK_CARD_EN; 17176322cdd0SPhilip Rakity sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 17186322cdd0SPhilip Rakity 17196322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing); 1720d975f121SRussell King host->timing = ios->timing; 172149c468fcSArindam Nath 172252983382SKevin Liu if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && 172352983382SKevin Liu ((ios->timing == MMC_TIMING_UHS_SDR12) || 172452983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR25) || 172552983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR50) || 172652983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR104) || 17270dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_UHS_DDR50) || 17280dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_MMC_DDR52))) { 172952983382SKevin Liu u16 preset; 173052983382SKevin Liu 173152983382SKevin Liu sdhci_enable_preset_value(host, true); 173252983382SKevin Liu preset = sdhci_get_preset_value(host); 173352983382SKevin Liu ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK) 173452983382SKevin Liu >> SDHCI_PRESET_DRV_SHIFT; 173552983382SKevin Liu } 173652983382SKevin Liu 173749c468fcSArindam Nath /* Re-enable SD Clock */ 17381771059cSRussell King host->ops->set_clock(host, host->clock); 1739758535c4SArindam Nath } else 1740758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1741d6d50a15SArindam Nath 1742b8352260SLeandro Dorileo /* 1743b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1744b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1745b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 1746b8352260SLeandro Dorileo */ 1747b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 174803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1749b8352260SLeandro Dorileo 17501c6a0718SPierre Ossman mmiowb(); 17511c6a0718SPierre Ossman } 17526a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios); 17531c6a0718SPierre Ossman 1754ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc) 175566fd8ad5SAdrian Hunter { 175666fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 1757ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc); 175894144a46SKevin Liu 175994144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD) 176094144a46SKevin Liu return 0; 176194144a46SKevin Liu 176288af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */ 1763860951c5SJaehoon Chung if (!mmc_card_is_removable(host->mmc)) 176494144a46SKevin Liu return 1; 176594144a46SKevin Liu 176688af5655SIvan T. Ivanov /* 176788af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence 176888af5655SIvan T. Ivanov * over build in controller functionality 176988af5655SIvan T. Ivanov */ 1770287980e4SArnd Bergmann if (gpio_cd >= 0) 177194144a46SKevin Liu return !!gpio_cd; 177294144a46SKevin Liu 177388af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */ 177488af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 177588af5655SIvan T. Ivanov return 1; 177688af5655SIvan T. Ivanov 177794144a46SKevin Liu /* Host native card detect */ 177894144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 177994144a46SKevin Liu } 178094144a46SKevin Liu 178166fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host) 17821c6a0718SPierre Ossman { 17831c6a0718SPierre Ossman unsigned long flags; 17842dfb579cSWolfram Sang int is_readonly; 17851c6a0718SPierre Ossman 17861c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 17871c6a0718SPierre Ossman 17881e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 17892dfb579cSWolfram Sang is_readonly = 0; 17902dfb579cSWolfram Sang else if (host->ops->get_ro) 17912dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 17921e72859eSPierre Ossman else 17932dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 17942dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 17951c6a0718SPierre Ossman 17961c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 17971c6a0718SPierre Ossman 17982dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 17992dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 18002dfb579cSWolfram Sang !is_readonly : is_readonly; 18011c6a0718SPierre Ossman } 18021c6a0718SPierre Ossman 180382b0e23aSTakashi Iwai #define SAMPLE_COUNT 5 180482b0e23aSTakashi Iwai 1805ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc) 180682b0e23aSTakashi Iwai { 1807ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 180882b0e23aSTakashi Iwai int i, ro_count; 180982b0e23aSTakashi Iwai 181082b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 181166fd8ad5SAdrian Hunter return sdhci_check_ro(host); 181282b0e23aSTakashi Iwai 181382b0e23aSTakashi Iwai ro_count = 0; 181482b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 181566fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) { 181682b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 181782b0e23aSTakashi Iwai return 1; 181882b0e23aSTakashi Iwai } 181982b0e23aSTakashi Iwai msleep(30); 182082b0e23aSTakashi Iwai } 182182b0e23aSTakashi Iwai return 0; 182282b0e23aSTakashi Iwai } 182382b0e23aSTakashi Iwai 182420758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc) 182520758b66SAdrian Hunter { 182620758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 182720758b66SAdrian Hunter 182820758b66SAdrian Hunter if (host->ops && host->ops->hw_reset) 182920758b66SAdrian Hunter host->ops->hw_reset(host); 183020758b66SAdrian Hunter } 183120758b66SAdrian Hunter 183266fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) 183366fd8ad5SAdrian Hunter { 1834be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) { 183566fd8ad5SAdrian Hunter if (enable) 1836b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT; 18377260cf5eSAnton Vorontsov else 1838b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT; 1839b537f94cSRussell King 1840b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1841b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1842f75979b7SPierre Ossman mmiowb(); 184366fd8ad5SAdrian Hunter } 1844ef104333SRussell King } 1845f75979b7SPierre Ossman 18462f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 184766fd8ad5SAdrian Hunter { 184866fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 184966fd8ad5SAdrian Hunter unsigned long flags; 185066fd8ad5SAdrian Hunter 1851923713b3SHans de Goede if (enable) 1852923713b3SHans de Goede pm_runtime_get_noresume(host->mmc->parent); 1853923713b3SHans de Goede 185466fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1855ef104333SRussell King if (enable) 1856ef104333SRussell King host->flags |= SDHCI_SDIO_IRQ_ENABLED; 1857ef104333SRussell King else 1858ef104333SRussell King host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; 1859ef104333SRussell King 186066fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable); 1861f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1862923713b3SHans de Goede 1863923713b3SHans de Goede if (!enable) 1864923713b3SHans de Goede pm_runtime_put_noidle(host->mmc->parent); 1865f75979b7SPierre Ossman } 18662f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); 1867f75979b7SPierre Ossman 1868c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 186921f5998fSFabio Estevam struct mmc_ios *ios) 1870f2119df6SArindam Nath { 1871ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 187220b92a30SKevin Liu u16 ctrl; 18736231f3deSPhilip Rakity int ret; 1874f2119df6SArindam Nath 187520b92a30SKevin Liu /* 187620b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers 187720b92a30SKevin Liu * v3.00 and above. 187820b92a30SKevin Liu */ 187920b92a30SKevin Liu if (host->version < SDHCI_SPEC_300) 188020b92a30SKevin Liu return 0; 188120b92a30SKevin Liu 188220b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 188320b92a30SKevin Liu 188421f5998fSFabio Estevam switch (ios->signal_voltage) { 188520b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330: 18868cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330)) 18878cb851a4SAdrian Hunter return -EINVAL; 1888f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 1889f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 1890f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1891f2119df6SArindam Nath 18923a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 1893761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 18946231f3deSPhilip Rakity if (ret) { 18956606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n", 18966606110dSJoe Perches mmc_hostname(mmc)); 18976231f3deSPhilip Rakity return -EIO; 18986231f3deSPhilip Rakity } 18996231f3deSPhilip Rakity } 1900f2119df6SArindam Nath /* Wait for 5ms */ 1901f2119df6SArindam Nath usleep_range(5000, 5500); 1902f2119df6SArindam Nath 1903f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */ 1904f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1905f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 1906f2119df6SArindam Nath return 0; 19076231f3deSPhilip Rakity 19086606110dSJoe Perches pr_warn("%s: 3.3V regulator output did not became stable\n", 19094e743f1fSMarkus Mayer mmc_hostname(mmc)); 19106231f3deSPhilip Rakity 191120b92a30SKevin Liu return -EAGAIN; 191220b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180: 19138cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180)) 19148cb851a4SAdrian Hunter return -EINVAL; 19153a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 1916761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 191720b92a30SKevin Liu if (ret) { 19186606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n", 19196606110dSJoe Perches mmc_hostname(mmc)); 1920f2119df6SArindam Nath return -EIO; 1921f2119df6SArindam Nath } 192220b92a30SKevin Liu } 19236231f3deSPhilip Rakity 1924f2119df6SArindam Nath /* 1925f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2 1926f2119df6SArindam Nath * register 1927f2119df6SArindam Nath */ 1928f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180; 1929f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1930f2119df6SArindam Nath 19319d967a61SVincent Yang /* Some controller need to do more when switching */ 19329d967a61SVincent Yang if (host->ops->voltage_switch) 19339d967a61SVincent Yang host->ops->voltage_switch(host); 19349d967a61SVincent Yang 193520b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */ 1936f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 193720b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180) 1938f2119df6SArindam Nath return 0; 1939f2119df6SArindam Nath 19406606110dSJoe Perches pr_warn("%s: 1.8V regulator output did not became stable\n", 19414e743f1fSMarkus Mayer mmc_hostname(mmc)); 19426231f3deSPhilip Rakity 1943f2119df6SArindam Nath return -EAGAIN; 194420b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120: 19458cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120)) 19468cb851a4SAdrian Hunter return -EINVAL; 19473a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 1948761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 194920b92a30SKevin Liu if (ret) { 19506606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n", 19516606110dSJoe Perches mmc_hostname(mmc)); 195220b92a30SKevin Liu return -EIO; 19536231f3deSPhilip Rakity } 195420b92a30SKevin Liu } 19556231f3deSPhilip Rakity return 0; 195620b92a30SKevin Liu default: 1957f2119df6SArindam Nath /* No signal voltage switch required */ 1958f2119df6SArindam Nath return 0; 1959f2119df6SArindam Nath } 196020b92a30SKevin Liu } 1961c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch); 1962f2119df6SArindam Nath 196320b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc) 196420b92a30SKevin Liu { 196520b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc); 196620b92a30SKevin Liu u32 present_state; 196720b92a30SKevin Liu 1968e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */ 196920b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 197020b92a30SKevin Liu 1971e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK); 197220b92a30SKevin Liu } 197320b92a30SKevin Liu 1974b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) 1975b5540ce1SAdrian Hunter { 1976b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 1977b5540ce1SAdrian Hunter unsigned long flags; 1978b5540ce1SAdrian Hunter 1979b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1980b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING; 1981b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 1982b5540ce1SAdrian Hunter 1983b5540ce1SAdrian Hunter return 0; 1984b5540ce1SAdrian Hunter } 1985b5540ce1SAdrian Hunter 1986da4bc4f2SAdrian Hunter static void sdhci_start_tuning(struct sdhci_host *host) 1987da4bc4f2SAdrian Hunter { 1988da4bc4f2SAdrian Hunter u16 ctrl; 1989da4bc4f2SAdrian Hunter 1990da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1991da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING; 1992da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) 1993da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK; 1994da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1995da4bc4f2SAdrian Hunter 1996da4bc4f2SAdrian Hunter /* 1997da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command 1998da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that. 1999da4bc4f2SAdrian Hunter * 2000da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence 2001da4bc4f2SAdrian Hunter * is being performed, the controller does not generate 2002da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But 2003da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_ 2004da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here. 2005da4bc4f2SAdrian Hunter */ 2006da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); 2007da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); 2008da4bc4f2SAdrian Hunter } 2009da4bc4f2SAdrian Hunter 2010da4bc4f2SAdrian Hunter static void sdhci_end_tuning(struct sdhci_host *host) 2011da4bc4f2SAdrian Hunter { 2012da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2013da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2014da4bc4f2SAdrian Hunter } 2015da4bc4f2SAdrian Hunter 2016da4bc4f2SAdrian Hunter static void sdhci_reset_tuning(struct sdhci_host *host) 2017da4bc4f2SAdrian Hunter { 2018da4bc4f2SAdrian Hunter u16 ctrl; 2019da4bc4f2SAdrian Hunter 2020da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2021da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK; 2022da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 2023da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2024da4bc4f2SAdrian Hunter } 2025da4bc4f2SAdrian Hunter 20262a85ef25SAdrian Hunter static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) 2027da4bc4f2SAdrian Hunter { 2028da4bc4f2SAdrian Hunter sdhci_reset_tuning(host); 2029da4bc4f2SAdrian Hunter 2030da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 2031da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 2032da4bc4f2SAdrian Hunter 2033da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 2034da4bc4f2SAdrian Hunter 2035da4bc4f2SAdrian Hunter mmc_abort_tuning(host->mmc, opcode); 2036da4bc4f2SAdrian Hunter } 2037da4bc4f2SAdrian Hunter 2038da4bc4f2SAdrian Hunter /* 2039da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI 2040da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it 2041da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command 2042da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout 2043da4bc4f2SAdrian Hunter * interrupt so special handling is needed. 2044da4bc4f2SAdrian Hunter */ 20452a85ef25SAdrian Hunter static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) 2046da4bc4f2SAdrian Hunter { 2047da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc; 2048c7836d15SMasahiro Yamada struct mmc_command cmd = {}; 2049c7836d15SMasahiro Yamada struct mmc_request mrq = {}; 20502a85ef25SAdrian Hunter unsigned long flags; 2051c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary; 20522a85ef25SAdrian Hunter 20532a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2054da4bc4f2SAdrian Hunter 2055da4bc4f2SAdrian Hunter cmd.opcode = opcode; 2056da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 2057da4bc4f2SAdrian Hunter cmd.mrq = &mrq; 2058da4bc4f2SAdrian Hunter 2059da4bc4f2SAdrian Hunter mrq.cmd = &cmd; 2060da4bc4f2SAdrian Hunter /* 2061da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning 2062da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size 2063da4bc4f2SAdrian Hunter * to 64 here. 2064da4bc4f2SAdrian Hunter */ 206585336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 && 206685336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8) 2067c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE); 206885336109SAdrian Hunter else 2069c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE); 2070da4bc4f2SAdrian Hunter 2071da4bc4f2SAdrian Hunter /* 2072da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller. 2073da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register. 2074da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block 2075da4bc4f2SAdrian Hunter * Select in the same register to 0. 2076da4bc4f2SAdrian Hunter */ 2077da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 2078da4bc4f2SAdrian Hunter 2079da4bc4f2SAdrian Hunter sdhci_send_command(host, &cmd); 2080da4bc4f2SAdrian Hunter 2081da4bc4f2SAdrian Hunter host->cmd = NULL; 2082da4bc4f2SAdrian Hunter 2083da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq); 2084da4bc4f2SAdrian Hunter 2085da4bc4f2SAdrian Hunter host->tuning_done = 0; 2086da4bc4f2SAdrian Hunter 20872a85ef25SAdrian Hunter mmiowb(); 2088da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2089da4bc4f2SAdrian Hunter 2090da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */ 2091da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), 2092da4bc4f2SAdrian Hunter msecs_to_jiffies(50)); 2093da4bc4f2SAdrian Hunter 2094da4bc4f2SAdrian Hunter } 2095da4bc4f2SAdrian Hunter 20962a85ef25SAdrian Hunter static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 20976b11e70bSAdrian Hunter { 20986b11e70bSAdrian Hunter int i; 20996b11e70bSAdrian Hunter 21006b11e70bSAdrian Hunter /* 21016b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number 21026b11e70bSAdrian Hunter * of loops reaches 40 times. 21036b11e70bSAdrian Hunter */ 21046b11e70bSAdrian Hunter for (i = 0; i < MAX_TUNING_LOOP; i++) { 21056b11e70bSAdrian Hunter u16 ctrl; 21066b11e70bSAdrian Hunter 21072a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode); 21086b11e70bSAdrian Hunter 21096b11e70bSAdrian Hunter if (!host->tuning_done) { 21106b11e70bSAdrian Hunter pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", 21116b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 21122a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode); 21136b11e70bSAdrian Hunter return; 21146b11e70bSAdrian Hunter } 21156b11e70bSAdrian Hunter 21166b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 21176b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 21186b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK) 21196b11e70bSAdrian Hunter return; /* Success! */ 21206b11e70bSAdrian Hunter break; 21216b11e70bSAdrian Hunter } 21226b11e70bSAdrian Hunter 212383b600b8SAdrian Hunter /* Spec does not require a delay between tuning cycles */ 212483b600b8SAdrian Hunter if (host->tuning_delay > 0) 212583b600b8SAdrian Hunter mdelay(host->tuning_delay); 21266b11e70bSAdrian Hunter } 21276b11e70bSAdrian Hunter 21286b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 21296b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 21306b11e70bSAdrian Hunter sdhci_reset_tuning(host); 21316b11e70bSAdrian Hunter } 21326b11e70bSAdrian Hunter 213385a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 2134b513ea25SArindam Nath { 21354b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc); 2136b513ea25SArindam Nath int err = 0; 213738e40bf5SAdrian Hunter unsigned int tuning_count = 0; 2138b5540ce1SAdrian Hunter bool hs400_tuning; 2139b513ea25SArindam Nath 2140b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING; 2141b5540ce1SAdrian Hunter 214238e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1) 214338e40bf5SAdrian Hunter tuning_count = host->tuning_count; 214438e40bf5SAdrian Hunter 2145b513ea25SArindam Nath /* 21469faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50 21479faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in 21489faac7b9SWeijun Yang * the Capabilities register. 2149069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the 2150069c9f14SGirish K S * tuning function has to be executed. 2151b513ea25SArindam Nath */ 21524b6f37d3SRussell King switch (host->timing) { 2153b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */ 2154e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 2155b5540ce1SAdrian Hunter err = -EINVAL; 21562a85ef25SAdrian Hunter goto out; 2157b5540ce1SAdrian Hunter 21584b6f37d3SRussell King case MMC_TIMING_MMC_HS200: 2159b5540ce1SAdrian Hunter /* 2160b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so 2161b5540ce1SAdrian Hunter * disable it here. 2162b5540ce1SAdrian Hunter */ 2163b5540ce1SAdrian Hunter if (hs400_tuning) 2164b5540ce1SAdrian Hunter tuning_count = 0; 2165b5540ce1SAdrian Hunter break; 2166b5540ce1SAdrian Hunter 21674b6f37d3SRussell King case MMC_TIMING_UHS_SDR104: 21689faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50: 21694b6f37d3SRussell King break; 2170069c9f14SGirish K S 21714b6f37d3SRussell King case MMC_TIMING_UHS_SDR50: 21724228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING) 21734b6f37d3SRussell King break; 21744b6f37d3SRussell King /* FALLTHROUGH */ 21754b6f37d3SRussell King 21764b6f37d3SRussell King default: 21772a85ef25SAdrian Hunter goto out; 2178b513ea25SArindam Nath } 2179b513ea25SArindam Nath 218045251812SDong Aisheng if (host->ops->platform_execute_tuning) { 21818a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode); 21822a85ef25SAdrian Hunter goto out; 218345251812SDong Aisheng } 218445251812SDong Aisheng 21856b11e70bSAdrian Hunter host->mmc->retune_period = tuning_count; 21866b11e70bSAdrian Hunter 218783b600b8SAdrian Hunter if (host->tuning_delay < 0) 218883b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; 218983b600b8SAdrian Hunter 2190da4bc4f2SAdrian Hunter sdhci_start_tuning(host); 2191b513ea25SArindam Nath 21922a85ef25SAdrian Hunter __sdhci_execute_tuning(host, opcode); 2193cf2b5eeaSArindam Nath 2194da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 21952a85ef25SAdrian Hunter out: 21968a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING; 21976b11e70bSAdrian Hunter 2198b513ea25SArindam Nath return err; 2199b513ea25SArindam Nath } 220085a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning); 2201b513ea25SArindam Nath 220252983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) 22034d55c5a1SArindam Nath { 22044d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */ 22054d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300) 22064d55c5a1SArindam Nath return; 22074d55c5a1SArindam Nath 22084d55c5a1SArindam Nath /* 22094d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already 22104d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out. 22114d55c5a1SArindam Nath */ 2212da91a8f9SRussell King if (host->preset_enabled != enable) { 2213da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2214da91a8f9SRussell King 2215da91a8f9SRussell King if (enable) 22164d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 2217da91a8f9SRussell King else 22184d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 2219da91a8f9SRussell King 22204d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2221da91a8f9SRussell King 2222da91a8f9SRussell King if (enable) 2223da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED; 2224da91a8f9SRussell King else 222566fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED; 2226da91a8f9SRussell King 2227da91a8f9SRussell King host->preset_enabled = enable; 22284d55c5a1SArindam Nath } 222966fd8ad5SAdrian Hunter } 223066fd8ad5SAdrian Hunter 2231348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 2232348487cbSHaibo Chen int err) 2233348487cbSHaibo Chen { 2234348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2235348487cbSHaibo Chen struct mmc_data *data = mrq->data; 2236348487cbSHaibo Chen 2237f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED) 2238348487cbSHaibo Chen dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 2239feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 2240771a3dc2SRussell King 2241d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED; 2242348487cbSHaibo Chen } 2243348487cbSHaibo Chen 2244d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 2245348487cbSHaibo Chen { 2246348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2247348487cbSHaibo Chen 2248d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED; 2249348487cbSHaibo Chen 2250348487cbSHaibo Chen if (host->flags & SDHCI_REQ_USE_DMA) 225194538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); 2252348487cbSHaibo Chen } 2253348487cbSHaibo Chen 22545d0d11c5SAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host) 22555d0d11c5SAdrian Hunter { 22565d0d11c5SAdrian Hunter return host->cmd || host->data_cmd; 22575d0d11c5SAdrian Hunter } 22585d0d11c5SAdrian Hunter 22595d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) 22605d0d11c5SAdrian Hunter { 22615d0d11c5SAdrian Hunter if (host->data_cmd) { 22625d0d11c5SAdrian Hunter host->data_cmd->error = err; 22635d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 22645d0d11c5SAdrian Hunter } 22655d0d11c5SAdrian Hunter 22665d0d11c5SAdrian Hunter if (host->cmd) { 22675d0d11c5SAdrian Hunter host->cmd->error = err; 22685d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 22695d0d11c5SAdrian Hunter } 22705d0d11c5SAdrian Hunter } 22715d0d11c5SAdrian Hunter 227271e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc) 22731c6a0718SPierre Ossman { 227471e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc); 22751c6a0718SPierre Ossman unsigned long flags; 22762836766aSKrzysztof Kozlowski int present; 22771c6a0718SPierre Ossman 2278722e1280SChristian Daudt /* First check if client has provided their own card event */ 2279722e1280SChristian Daudt if (host->ops->card_event) 2280722e1280SChristian Daudt host->ops->card_event(host); 2281722e1280SChristian Daudt 2282d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc); 22832836766aSKrzysztof Kozlowski 22841c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 22851c6a0718SPierre Ossman 22865d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */ 22875d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) { 2288a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n", 22891c6a0718SPierre Ossman mmc_hostname(host->mmc)); 2290a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n", 22911c6a0718SPierre Ossman mmc_hostname(host->mmc)); 22921c6a0718SPierre Ossman 229303231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 229403231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 22951c6a0718SPierre Ossman 22965d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 22971c6a0718SPierre Ossman } 22981c6a0718SPierre Ossman 22991c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 230071e69211SGuennadi Liakhovetski } 230171e69211SGuennadi Liakhovetski 230271e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = { 230371e69211SGuennadi Liakhovetski .request = sdhci_request, 2304348487cbSHaibo Chen .post_req = sdhci_post_req, 2305348487cbSHaibo Chen .pre_req = sdhci_pre_req, 230671e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios, 230794144a46SKevin Liu .get_cd = sdhci_get_cd, 230871e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro, 230971e69211SGuennadi Liakhovetski .hw_reset = sdhci_hw_reset, 231071e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq, 231171e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 2312b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning, 231371e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning, 231471e69211SGuennadi Liakhovetski .card_event = sdhci_card_event, 231520b92a30SKevin Liu .card_busy = sdhci_card_busy, 231671e69211SGuennadi Liakhovetski }; 231771e69211SGuennadi Liakhovetski 231871e69211SGuennadi Liakhovetski /*****************************************************************************\ 231971e69211SGuennadi Liakhovetski * * 232071e69211SGuennadi Liakhovetski * Tasklets * 232171e69211SGuennadi Liakhovetski * * 232271e69211SGuennadi Liakhovetski \*****************************************************************************/ 232371e69211SGuennadi Liakhovetski 23244e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host) 23251c6a0718SPierre Ossman { 23261c6a0718SPierre Ossman unsigned long flags; 23271c6a0718SPierre Ossman struct mmc_request *mrq; 23284e9f8fe5SAdrian Hunter int i; 23291c6a0718SPierre Ossman 233066fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 233166fd8ad5SAdrian Hunter 23324e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 23334e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i]; 23346ebebeabSAdrian Hunter if (mrq) 23354e9f8fe5SAdrian Hunter break; 23364e9f8fe5SAdrian Hunter } 23371c6a0718SPierre Ossman 23384e9f8fe5SAdrian Hunter if (!mrq) { 23394e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 23404e9f8fe5SAdrian Hunter return true; 23414e9f8fe5SAdrian Hunter } 23421c6a0718SPierre Ossman 2343d7422fb4SAdrian Hunter sdhci_del_timer(host, mrq); 2344d7422fb4SAdrian Hunter 23451c6a0718SPierre Ossman /* 2346054cedffSRussell King * Always unmap the data buffers if they were mapped by 2347054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request. 2348054cedffSRussell King * This avoids leaking DMA mappings on error. 2349054cedffSRussell King */ 2350054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) { 2351054cedffSRussell King struct mmc_data *data = mrq->data; 2352054cedffSRussell King 2353054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) { 2354054cedffSRussell King dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 2355feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 2356054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED; 2357054cedffSRussell King } 2358054cedffSRussell King } 2359054cedffSRussell King 2360054cedffSRussell King /* 23611c6a0718SPierre Ossman * The controller needs a reset of internal state machines 23621c6a0718SPierre Ossman * upon error conditions. 23631c6a0718SPierre Ossman */ 23640cc563ceSAdrian Hunter if (sdhci_needs_reset(host, mrq)) { 23656ebebeabSAdrian Hunter /* 23666ebebeabSAdrian Hunter * Do not finish until command and data lines are available for 23676ebebeabSAdrian Hunter * reset. Note there can only be one other mrq, so it cannot 23686ebebeabSAdrian Hunter * also be in mrqs_done, otherwise host->cmd and host->data_cmd 23696ebebeabSAdrian Hunter * would both be null. 23706ebebeabSAdrian Hunter */ 23716ebebeabSAdrian Hunter if (host->cmd || host->data_cmd) { 23726ebebeabSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 23736ebebeabSAdrian Hunter return true; 23746ebebeabSAdrian Hunter } 23756ebebeabSAdrian Hunter 23761c6a0718SPierre Ossman /* Some controllers need this kick or reset won't work here */ 23778213af3bSAndy Shevchenko if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) 23781c6a0718SPierre Ossman /* This is to force an update */ 23791771059cSRussell King host->ops->set_clock(host, host->clock); 23801c6a0718SPierre Ossman 23811c6a0718SPierre Ossman /* Spec says we should do both at the same time, but Ricoh 23821c6a0718SPierre Ossman controllers do not like that. */ 238303231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 238403231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 2385ed1563deSAdrian Hunter 2386ed1563deSAdrian Hunter host->pending_reset = false; 23871c6a0718SPierre Ossman } 23881c6a0718SPierre Ossman 23894e9f8fe5SAdrian Hunter if (!sdhci_has_requests(host)) 2390061d17a6SAdrian Hunter sdhci_led_deactivate(host); 23911c6a0718SPierre Ossman 23926ebebeabSAdrian Hunter host->mrqs_done[i] = NULL; 23936ebebeabSAdrian Hunter 23941c6a0718SPierre Ossman mmiowb(); 23951c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 23961c6a0718SPierre Ossman 23971c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 23984e9f8fe5SAdrian Hunter 23994e9f8fe5SAdrian Hunter return false; 24004e9f8fe5SAdrian Hunter } 24014e9f8fe5SAdrian Hunter 24024e9f8fe5SAdrian Hunter static void sdhci_tasklet_finish(unsigned long param) 24034e9f8fe5SAdrian Hunter { 24044e9f8fe5SAdrian Hunter struct sdhci_host *host = (struct sdhci_host *)param; 24054e9f8fe5SAdrian Hunter 24064e9f8fe5SAdrian Hunter while (!sdhci_request_done(host)) 24074e9f8fe5SAdrian Hunter ; 24081c6a0718SPierre Ossman } 24091c6a0718SPierre Ossman 24102ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t) 24111c6a0718SPierre Ossman { 24121c6a0718SPierre Ossman struct sdhci_host *host; 24131c6a0718SPierre Ossman unsigned long flags; 24141c6a0718SPierre Ossman 24152ee4f620SKees Cook host = from_timer(host, t, timer); 24161c6a0718SPierre Ossman 24171c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 24181c6a0718SPierre Ossman 2419d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { 2420d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", 2421d7422fb4SAdrian Hunter mmc_hostname(host->mmc)); 2422d7422fb4SAdrian Hunter sdhci_dumpregs(host); 2423d7422fb4SAdrian Hunter 2424d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT; 2425d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 2426d7422fb4SAdrian Hunter } 2427d7422fb4SAdrian Hunter 2428d7422fb4SAdrian Hunter mmiowb(); 2429d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2430d7422fb4SAdrian Hunter } 2431d7422fb4SAdrian Hunter 24322ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t) 2433d7422fb4SAdrian Hunter { 2434d7422fb4SAdrian Hunter struct sdhci_host *host; 2435d7422fb4SAdrian Hunter unsigned long flags; 2436d7422fb4SAdrian Hunter 24372ee4f620SKees Cook host = from_timer(host, t, data_timer); 2438d7422fb4SAdrian Hunter 2439d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2440d7422fb4SAdrian Hunter 2441d7422fb4SAdrian Hunter if (host->data || host->data_cmd || 2442d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) { 24432e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n", 24442e4456f0SMarek Vasut mmc_hostname(host->mmc)); 24451c6a0718SPierre Ossman sdhci_dumpregs(host); 24461c6a0718SPierre Ossman 24471c6a0718SPierre Ossman if (host->data) { 244817b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 24491c6a0718SPierre Ossman sdhci_finish_data(host); 2450d7422fb4SAdrian Hunter } else if (host->data_cmd) { 2451d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT; 2452d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 24531c6a0718SPierre Ossman } else { 245417b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 2455d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 24561c6a0718SPierre Ossman } 24571c6a0718SPierre Ossman } 24581c6a0718SPierre Ossman 24591c6a0718SPierre Ossman mmiowb(); 24601c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 24611c6a0718SPierre Ossman } 24621c6a0718SPierre Ossman 24631c6a0718SPierre Ossman /*****************************************************************************\ 24641c6a0718SPierre Ossman * * 24651c6a0718SPierre Ossman * Interrupt handling * 24661c6a0718SPierre Ossman * * 24671c6a0718SPierre Ossman \*****************************************************************************/ 24681c6a0718SPierre Ossman 2469fc605f1dSAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 24701c6a0718SPierre Ossman { 24711c6a0718SPierre Ossman if (!host->cmd) { 2472ed1563deSAdrian Hunter /* 2473ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 2474ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 2475ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 2476ed1563deSAdrian Hunter */ 2477ed1563deSAdrian Hunter if (host->pending_reset) 2478ed1563deSAdrian Hunter return; 24792e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", 2480b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 24811c6a0718SPierre Ossman sdhci_dumpregs(host); 24821c6a0718SPierre Ossman return; 24831c6a0718SPierre Ossman } 24841c6a0718SPierre Ossman 2485ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | 2486ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { 24871c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 248817b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 2489ec014cbaSRussell King else 249017b0429dSPierre Ossman host->cmd->error = -EILSEQ; 24911c6a0718SPierre Ossman 249271fcbda0SRussell King /* 249371fcbda0SRussell King * If this command initiates a data phase and a response 249471fcbda0SRussell King * CRC error is signalled, the card can start transferring 249571fcbda0SRussell King * data - the card may have received the command without 249671fcbda0SRussell King * error. We must not terminate the mmc_request early. 249771fcbda0SRussell King * 249871fcbda0SRussell King * If the card did not receive the command or returned an 249971fcbda0SRussell King * error which prevented it sending data, the data phase 250071fcbda0SRussell King * will time out. 250171fcbda0SRussell King */ 250271fcbda0SRussell King if (host->cmd->data && 250371fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == 250471fcbda0SRussell King SDHCI_INT_CRC) { 250571fcbda0SRussell King host->cmd = NULL; 250671fcbda0SRussell King return; 250771fcbda0SRussell King } 250871fcbda0SRussell King 2509a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 2510e809517fSPierre Ossman return; 2511e809517fSPierre Ossman } 2512e809517fSPierre Ossman 2513e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 251443b58b36SPierre Ossman sdhci_finish_command(host); 25151c6a0718SPierre Ossman } 25161c6a0718SPierre Ossman 251708621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host) 25186882a8c0SBen Dooks { 25191c3d5f6dSAdrian Hunter void *desc = host->adma_table; 25206882a8c0SBen Dooks 25216882a8c0SBen Dooks sdhci_dumpregs(host); 25226882a8c0SBen Dooks 25236882a8c0SBen Dooks while (true) { 2524e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 25256882a8c0SBen Dooks 2526e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 2527f421865dSAdrian Hunter DBG("%p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", 2528f421865dSAdrian Hunter desc, le32_to_cpu(dma_desc->addr_hi), 2529e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo), 2530e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len), 2531e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd)); 2532e57a5f61SAdrian Hunter else 2533f421865dSAdrian Hunter DBG("%p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 2534f421865dSAdrian Hunter desc, le32_to_cpu(dma_desc->addr_lo), 25350545230fSAdrian Hunter le16_to_cpu(dma_desc->len), 25360545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd)); 25376882a8c0SBen Dooks 253876fe379aSAdrian Hunter desc += host->desc_sz; 25396882a8c0SBen Dooks 25400545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) 25416882a8c0SBen Dooks break; 25426882a8c0SBen Dooks } 25436882a8c0SBen Dooks } 25446882a8c0SBen Dooks 25451c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 25461c6a0718SPierre Ossman { 2547069c9f14SGirish K S u32 command; 25481c6a0718SPierre Ossman 2549b513ea25SArindam Nath /* CMD19 generates _only_ Buffer Read Ready interrupt */ 2550b513ea25SArindam Nath if (intmask & SDHCI_INT_DATA_AVAIL) { 2551069c9f14SGirish K S command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); 2552069c9f14SGirish K S if (command == MMC_SEND_TUNING_BLOCK || 2553069c9f14SGirish K S command == MMC_SEND_TUNING_BLOCK_HS200) { 2554b513ea25SArindam Nath host->tuning_done = 1; 2555b513ea25SArindam Nath wake_up(&host->buf_ready_int); 2556b513ea25SArindam Nath return; 2557b513ea25SArindam Nath } 2558b513ea25SArindam Nath } 2559b513ea25SArindam Nath 25601c6a0718SPierre Ossman if (!host->data) { 25617c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 25627c89a3d9SAdrian Hunter 25631c6a0718SPierre Ossman /* 2564e809517fSPierre Ossman * The "data complete" interrupt is also used to 2565e809517fSPierre Ossman * indicate that a busy state has ended. See comment 2566e809517fSPierre Ossman * above in sdhci_cmd_irq(). 25671c6a0718SPierre Ossman */ 25687c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { 2569c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) { 257069b962a6SAdrian Hunter host->data_cmd = NULL; 25717c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT; 2572a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, data_cmd->mrq); 2573c5abd5e8SMatthieu CASTET return; 2574c5abd5e8SMatthieu CASTET } 2575e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 257669b962a6SAdrian Hunter host->data_cmd = NULL; 2577e99783a4SChanho Min /* 2578e99783a4SChanho Min * Some cards handle busy-end interrupt 2579e99783a4SChanho Min * before the command completed, so make 2580e99783a4SChanho Min * sure we do things in the proper order. 2581e99783a4SChanho Min */ 2582ea968023SAdrian Hunter if (host->cmd == data_cmd) 2583ea968023SAdrian Hunter return; 2584ea968023SAdrian Hunter 2585a6d3bdd5SAdrian Hunter sdhci_finish_mrq(host, data_cmd->mrq); 25861c6a0718SPierre Ossman return; 2587e809517fSPierre Ossman } 2588e809517fSPierre Ossman } 25891c6a0718SPierre Ossman 2590ed1563deSAdrian Hunter /* 2591ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 2592ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 2593ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 2594ed1563deSAdrian Hunter */ 2595ed1563deSAdrian Hunter if (host->pending_reset) 2596ed1563deSAdrian Hunter return; 2597ed1563deSAdrian Hunter 25982e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", 2599b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 26001c6a0718SPierre Ossman sdhci_dumpregs(host); 26011c6a0718SPierre Ossman 26021c6a0718SPierre Ossman return; 26031c6a0718SPierre Ossman } 26041c6a0718SPierre Ossman 26051c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 260617b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 260722113efdSAries Lee else if (intmask & SDHCI_INT_DATA_END_BIT) 260822113efdSAries Lee host->data->error = -EILSEQ; 260922113efdSAries Lee else if ((intmask & SDHCI_INT_DATA_CRC) && 261022113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 261122113efdSAries Lee != MMC_BUS_TEST_R) 261217b0429dSPierre Ossman host->data->error = -EILSEQ; 26136882a8c0SBen Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 2614a3c76eb9SGirish K S pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); 261508621b18SAdrian Hunter sdhci_adma_show_error(host); 26162134a922SPierre Ossman host->data->error = -EIO; 2617a4071fbbSHaijun Zhang if (host->ops->adma_workaround) 2618a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask); 26196882a8c0SBen Dooks } 26201c6a0718SPierre Ossman 262117b0429dSPierre Ossman if (host->data->error) 26221c6a0718SPierre Ossman sdhci_finish_data(host); 26231c6a0718SPierre Ossman else { 26241c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 26251c6a0718SPierre Ossman sdhci_transfer_pio(host); 26261c6a0718SPierre Ossman 26276ba736a1SPierre Ossman /* 26286ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 26296ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 26306ba736a1SPierre Ossman * we need to at least restart the transfer. 2631f6a03cbfSMikko Vinni * 2632f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 2633f6a03cbfSMikko Vinni * should return a valid address to continue from, but as 2634f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them. 26356ba736a1SPierre Ossman */ 2636f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 2637f6a03cbfSMikko Vinni u32 dmastart, dmanow; 2638f6a03cbfSMikko Vinni dmastart = sg_dma_address(host->data->sg); 2639f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 2640f6a03cbfSMikko Vinni /* 2641f6a03cbfSMikko Vinni * Force update to the next DMA block boundary. 2642f6a03cbfSMikko Vinni */ 2643f6a03cbfSMikko Vinni dmanow = (dmanow & 2644f6a03cbfSMikko Vinni ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 2645f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 2646f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 2647f421865dSAdrian Hunter DBG("DMA base 0x%08x, transferred 0x%06x bytes, next 0x%08x\n", 2648f421865dSAdrian Hunter dmastart, host->data->bytes_xfered, dmanow); 2649f6a03cbfSMikko Vinni sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 2650f6a03cbfSMikko Vinni } 26516ba736a1SPierre Ossman 2652e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 26537c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) { 2654e538fbe8SPierre Ossman /* 2655e538fbe8SPierre Ossman * Data managed to finish before the 2656e538fbe8SPierre Ossman * command completed. Make sure we do 2657e538fbe8SPierre Ossman * things in the proper order. 2658e538fbe8SPierre Ossman */ 2659e538fbe8SPierre Ossman host->data_early = 1; 2660e538fbe8SPierre Ossman } else { 26611c6a0718SPierre Ossman sdhci_finish_data(host); 26621c6a0718SPierre Ossman } 26631c6a0718SPierre Ossman } 2664e538fbe8SPierre Ossman } 2665e538fbe8SPierre Ossman } 26661c6a0718SPierre Ossman 26671c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 26681c6a0718SPierre Ossman { 2669781e989cSRussell King irqreturn_t result = IRQ_NONE; 26701c6a0718SPierre Ossman struct sdhci_host *host = dev_id; 267141005003SRussell King u32 intmask, mask, unexpected = 0; 2672781e989cSRussell King int max_loops = 16; 26731c6a0718SPierre Ossman 26741c6a0718SPierre Ossman spin_lock(&host->lock); 26751c6a0718SPierre Ossman 2676be138554SRussell King if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) { 267766fd8ad5SAdrian Hunter spin_unlock(&host->lock); 2678655bca76SAdrian Hunter return IRQ_NONE; 267966fd8ad5SAdrian Hunter } 268066fd8ad5SAdrian Hunter 26814e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 26821c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 26831c6a0718SPierre Ossman result = IRQ_NONE; 26841c6a0718SPierre Ossman goto out; 26851c6a0718SPierre Ossman } 26861c6a0718SPierre Ossman 268741005003SRussell King do { 2688f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask); 2689f12e39dbSAdrian Hunter 2690f12e39dbSAdrian Hunter if (host->ops->irq) { 2691f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask); 2692f12e39dbSAdrian Hunter if (!intmask) 2693f12e39dbSAdrian Hunter goto cont; 2694f12e39dbSAdrian Hunter } 2695f12e39dbSAdrian Hunter 269641005003SRussell King /* Clear selected interrupts. */ 269741005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 269841005003SRussell King SDHCI_INT_BUS_POWER); 269941005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS); 270041005003SRussell King 27011c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 2702d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 2703d25928d1SShawn Guo SDHCI_CARD_PRESENT; 2704d25928d1SShawn Guo 2705d25928d1SShawn Guo /* 270641005003SRussell King * There is a observation on i.mx esdhc. INSERT 270741005003SRussell King * bit will be immediately set again when it gets 270841005003SRussell King * cleared, if a card is inserted. We have to mask 270941005003SRussell King * the irq to prevent interrupt storm which will 271041005003SRussell King * freeze the system. And the REMOVE gets the 271141005003SRussell King * same situation. 2712d25928d1SShawn Guo * 271341005003SRussell King * More testing are needed here to ensure it works 271441005003SRussell King * for other platforms though. 2715d25928d1SShawn Guo */ 2716b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT | 2717d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE); 2718b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 2719b537f94cSRussell King SDHCI_INT_CARD_INSERT; 2720b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2721b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2722d25928d1SShawn Guo 27234e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 27244e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 27253560db8eSRussell King 27263560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | 27273560db8eSRussell King SDHCI_INT_CARD_REMOVE); 27283560db8eSRussell King result = IRQ_WAKE_THREAD; 27291c6a0718SPierre Ossman } 27301c6a0718SPierre Ossman 273141005003SRussell King if (intmask & SDHCI_INT_CMD_MASK) 2732fc605f1dSAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 27331c6a0718SPierre Ossman 273441005003SRussell King if (intmask & SDHCI_INT_DATA_MASK) 27351c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 27361c6a0718SPierre Ossman 273741005003SRussell King if (intmask & SDHCI_INT_BUS_POWER) 2738a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n", 27391c6a0718SPierre Ossman mmc_hostname(host->mmc)); 27401c6a0718SPierre Ossman 2741f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE) 2742f37b20ebSDong Aisheng mmc_retune_needed(host->mmc); 2743f37b20ebSDong Aisheng 2744161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) && 2745161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) { 2746781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false); 2747781e989cSRussell King host->thread_isr |= SDHCI_INT_CARD_INT; 2748781e989cSRussell King result = IRQ_WAKE_THREAD; 2749781e989cSRussell King } 2750f75979b7SPierre Ossman 275141005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 275241005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 275341005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | 2754f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); 2755f75979b7SPierre Ossman 27561c6a0718SPierre Ossman if (intmask) { 27576379b237SAlexander Stein unexpected |= intmask; 27584e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 27591c6a0718SPierre Ossman } 2760f12e39dbSAdrian Hunter cont: 2761781e989cSRussell King if (result == IRQ_NONE) 27621c6a0718SPierre Ossman result = IRQ_HANDLED; 27631c6a0718SPierre Ossman 27646379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS); 276541005003SRussell King } while (intmask && --max_loops); 27661c6a0718SPierre Ossman out: 27671c6a0718SPierre Ossman spin_unlock(&host->lock); 27681c6a0718SPierre Ossman 27696379b237SAlexander Stein if (unexpected) { 27706379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n", 27716379b237SAlexander Stein mmc_hostname(host->mmc), unexpected); 27726379b237SAlexander Stein sdhci_dumpregs(host); 27736379b237SAlexander Stein } 2774f75979b7SPierre Ossman 27751c6a0718SPierre Ossman return result; 27761c6a0718SPierre Ossman } 27771c6a0718SPierre Ossman 2778781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) 2779781e989cSRussell King { 2780781e989cSRussell King struct sdhci_host *host = dev_id; 2781781e989cSRussell King unsigned long flags; 2782781e989cSRussell King u32 isr; 2783781e989cSRussell King 2784781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 2785781e989cSRussell King isr = host->thread_isr; 2786781e989cSRussell King host->thread_isr = 0; 2787781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 2788781e989cSRussell King 27893560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 2790d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 2791d3940f27SAdrian Hunter 2792d3940f27SAdrian Hunter mmc->ops->card_event(mmc); 2793d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200)); 27943560db8eSRussell King } 27953560db8eSRussell King 2796781e989cSRussell King if (isr & SDHCI_INT_CARD_INT) { 2797781e989cSRussell King sdio_run_irqs(host->mmc); 2798781e989cSRussell King 2799781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 2800781e989cSRussell King if (host->flags & SDHCI_SDIO_IRQ_ENABLED) 2801781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, true); 2802781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 2803781e989cSRussell King } 2804781e989cSRussell King 2805781e989cSRussell King return isr ? IRQ_HANDLED : IRQ_NONE; 2806781e989cSRussell King } 2807781e989cSRussell King 28081c6a0718SPierre Ossman /*****************************************************************************\ 28091c6a0718SPierre Ossman * * 28101c6a0718SPierre Ossman * Suspend/resume * 28111c6a0718SPierre Ossman * * 28121c6a0718SPierre Ossman \*****************************************************************************/ 28131c6a0718SPierre Ossman 28141c6a0718SPierre Ossman #ifdef CONFIG_PM 281584d62605SLudovic Desroches /* 281684d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in 281784d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal 281884d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification. 281984d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in 282084d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by 282184d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init(). 282284d62605SLudovic Desroches */ 2823ad080d79SKevin Liu void sdhci_enable_irq_wakeups(struct sdhci_host *host) 2824ad080d79SKevin Liu { 2825ad080d79SKevin Liu u8 val; 2826ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 2827ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 282884d62605SLudovic Desroches u32 irq_val = SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 282984d62605SLudovic Desroches SDHCI_INT_CARD_INT; 2830ad080d79SKevin Liu 2831ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 2832ad080d79SKevin Liu val |= mask ; 2833ad080d79SKevin Liu /* Avoid fake wake up */ 283484d62605SLudovic Desroches if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) { 2835ad080d79SKevin Liu val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE); 283684d62605SLudovic Desroches irq_val &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 283784d62605SLudovic Desroches } 2838ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 283984d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); 2840ad080d79SKevin Liu } 2841ad080d79SKevin Liu EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); 2842ad080d79SKevin Liu 28430b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host) 2844ad080d79SKevin Liu { 2845ad080d79SKevin Liu u8 val; 2846ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 2847ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 2848ad080d79SKevin Liu 2849ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 2850ad080d79SKevin Liu val &= ~mask; 2851ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 2852ad080d79SKevin Liu } 28531c6a0718SPierre Ossman 285429495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host) 28551c6a0718SPierre Ossman { 28567260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 28577260cf5eSAnton Vorontsov 285866c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 2859cf2b5eeaSArindam Nath 2860ad080d79SKevin Liu if (!device_may_wakeup(mmc_dev(host->mmc))) { 2861b537f94cSRussell King host->ier = 0; 2862b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 2863b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 2864b8c86fc5SPierre Ossman free_irq(host->irq, host); 2865ad080d79SKevin Liu } else { 2866ad080d79SKevin Liu sdhci_enable_irq_wakeups(host); 2867ad080d79SKevin Liu enable_irq_wake(host->irq); 2868ad080d79SKevin Liu } 28694ee14ec6SUlf Hansson return 0; 2870b8c86fc5SPierre Ossman } 2871b8c86fc5SPierre Ossman 2872b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 2873b8c86fc5SPierre Ossman 2874b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 2875b8c86fc5SPierre Ossman { 2876d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 28774ee14ec6SUlf Hansson int ret = 0; 2878b8c86fc5SPierre Ossman 2879a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 2880b8c86fc5SPierre Ossman if (host->ops->enable_dma) 2881b8c86fc5SPierre Ossman host->ops->enable_dma(host); 2882b8c86fc5SPierre Ossman } 2883b8c86fc5SPierre Ossman 28846308d290SAdrian Hunter if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && 28856308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { 28866308d290SAdrian Hunter /* Card keeps power but host controller does not */ 28876308d290SAdrian Hunter sdhci_init(host, 0); 28886308d290SAdrian Hunter host->pwr = 0; 28896308d290SAdrian Hunter host->clock = 0; 2890d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 28916308d290SAdrian Hunter } else { 28922f4cbb3dSNicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 28931c6a0718SPierre Ossman mmiowb(); 28946308d290SAdrian Hunter } 2895b8c86fc5SPierre Ossman 289614a7b416SHaibo Chen if (!device_may_wakeup(mmc_dev(host->mmc))) { 289714a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq, 289814a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED, 289914a7b416SHaibo Chen mmc_hostname(host->mmc), host); 290014a7b416SHaibo Chen if (ret) 290114a7b416SHaibo Chen return ret; 290214a7b416SHaibo Chen } else { 290314a7b416SHaibo Chen sdhci_disable_irq_wakeups(host); 290414a7b416SHaibo Chen disable_irq_wake(host->irq); 290514a7b416SHaibo Chen } 290614a7b416SHaibo Chen 29077260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 29087260cf5eSAnton Vorontsov 29092f4cbb3dSNicolas Pitre return ret; 29101c6a0718SPierre Ossman } 29111c6a0718SPierre Ossman 2912b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 291366fd8ad5SAdrian Hunter 291466fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host) 291566fd8ad5SAdrian Hunter { 291666fd8ad5SAdrian Hunter unsigned long flags; 291766fd8ad5SAdrian Hunter 291866c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 291966fd8ad5SAdrian Hunter 292066fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2921b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT; 2922b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2923b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 292466fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 292566fd8ad5SAdrian Hunter 2926781e989cSRussell King synchronize_hardirq(host->irq); 292766fd8ad5SAdrian Hunter 292866fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 292966fd8ad5SAdrian Hunter host->runtime_suspended = true; 293066fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 293166fd8ad5SAdrian Hunter 29328a125badSMarkus Pargmann return 0; 293366fd8ad5SAdrian Hunter } 293466fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); 293566fd8ad5SAdrian Hunter 293666fd8ad5SAdrian Hunter int sdhci_runtime_resume_host(struct sdhci_host *host) 293766fd8ad5SAdrian Hunter { 2938d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 293966fd8ad5SAdrian Hunter unsigned long flags; 29408a125badSMarkus Pargmann int host_flags = host->flags; 294166fd8ad5SAdrian Hunter 294266fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 294366fd8ad5SAdrian Hunter if (host->ops->enable_dma) 294466fd8ad5SAdrian Hunter host->ops->enable_dma(host); 294566fd8ad5SAdrian Hunter } 294666fd8ad5SAdrian Hunter 294766fd8ad5SAdrian Hunter sdhci_init(host, 0); 294866fd8ad5SAdrian Hunter 294970bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && 295070bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) { 295166fd8ad5SAdrian Hunter /* Force clock and power re-program */ 295266fd8ad5SAdrian Hunter host->pwr = 0; 295366fd8ad5SAdrian Hunter host->clock = 0; 2954d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); 2955d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 295666fd8ad5SAdrian Hunter 295752983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) && 295852983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { 295952983382SKevin Liu spin_lock_irqsave(&host->lock, flags); 296052983382SKevin Liu sdhci_enable_preset_value(host, true); 296152983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags); 296252983382SKevin Liu } 296366fd8ad5SAdrian Hunter 2964086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) && 2965086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe) 2966086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios); 296784ec048bSAdrian Hunter } 2968086b0ddbSAdrian Hunter 296966fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 297066fd8ad5SAdrian Hunter 297166fd8ad5SAdrian Hunter host->runtime_suspended = false; 297266fd8ad5SAdrian Hunter 297366fd8ad5SAdrian Hunter /* Enable SDIO IRQ */ 2974ef104333SRussell King if (host->flags & SDHCI_SDIO_IRQ_ENABLED) 297566fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 297666fd8ad5SAdrian Hunter 297766fd8ad5SAdrian Hunter /* Enable Card Detection */ 297866fd8ad5SAdrian Hunter sdhci_enable_card_detection(host); 297966fd8ad5SAdrian Hunter 298066fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 298166fd8ad5SAdrian Hunter 29828a125badSMarkus Pargmann return 0; 298366fd8ad5SAdrian Hunter } 298466fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); 298566fd8ad5SAdrian Hunter 2986162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */ 298766fd8ad5SAdrian Hunter 29881c6a0718SPierre Ossman /*****************************************************************************\ 29891c6a0718SPierre Ossman * * 2990f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers * 2991f12e39dbSAdrian Hunter * * 2992f12e39dbSAdrian Hunter \*****************************************************************************/ 2993f12e39dbSAdrian Hunter 2994f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc) 2995f12e39dbSAdrian Hunter { 2996f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2997f12e39dbSAdrian Hunter unsigned long flags; 2998f12e39dbSAdrian Hunter u8 ctrl; 2999f12e39dbSAdrian Hunter 3000f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3001f12e39dbSAdrian Hunter 3002f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3003f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK; 3004f12e39dbSAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3005f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 3006f12e39dbSAdrian Hunter else 3007f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 3008f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3009f12e39dbSAdrian Hunter 3010c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512), 3011f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE); 3012f12e39dbSAdrian Hunter 3013f12e39dbSAdrian Hunter /* Set maximum timeout */ 3014f12e39dbSAdrian Hunter sdhci_writeb(host, 0xE, SDHCI_TIMEOUT_CONTROL); 3015f12e39dbSAdrian Hunter 3016f12e39dbSAdrian Hunter host->ier = host->cqe_ier; 3017f12e39dbSAdrian Hunter 3018f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3019f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3020f12e39dbSAdrian Hunter 3021f12e39dbSAdrian Hunter host->cqe_on = true; 3022f12e39dbSAdrian Hunter 3023f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n", 3024f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3025f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3026f12e39dbSAdrian Hunter 3027f12e39dbSAdrian Hunter mmiowb(); 3028f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3029f12e39dbSAdrian Hunter } 3030f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable); 3031f12e39dbSAdrian Hunter 3032f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) 3033f12e39dbSAdrian Hunter { 3034f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3035f12e39dbSAdrian Hunter unsigned long flags; 3036f12e39dbSAdrian Hunter 3037f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3038f12e39dbSAdrian Hunter 3039f12e39dbSAdrian Hunter sdhci_set_default_irqs(host); 3040f12e39dbSAdrian Hunter 3041f12e39dbSAdrian Hunter host->cqe_on = false; 3042f12e39dbSAdrian Hunter 3043f12e39dbSAdrian Hunter if (recovery) { 3044f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 3045f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 3046f12e39dbSAdrian Hunter } 3047f12e39dbSAdrian Hunter 3048f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", 3049f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3050f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3051f12e39dbSAdrian Hunter 3052f12e39dbSAdrian Hunter mmiowb(); 3053f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3054f12e39dbSAdrian Hunter } 3055f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable); 3056f12e39dbSAdrian Hunter 3057f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, 3058f12e39dbSAdrian Hunter int *data_error) 3059f12e39dbSAdrian Hunter { 3060f12e39dbSAdrian Hunter u32 mask; 3061f12e39dbSAdrian Hunter 3062f12e39dbSAdrian Hunter if (!host->cqe_on) 3063f12e39dbSAdrian Hunter return false; 3064f12e39dbSAdrian Hunter 3065f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) 3066f12e39dbSAdrian Hunter *cmd_error = -EILSEQ; 3067f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_TIMEOUT) 3068f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT; 3069f12e39dbSAdrian Hunter else 3070f12e39dbSAdrian Hunter *cmd_error = 0; 3071f12e39dbSAdrian Hunter 3072f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) 3073f12e39dbSAdrian Hunter *data_error = -EILSEQ; 3074f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_DATA_TIMEOUT) 3075f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT; 3076f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_ADMA_ERROR) 3077f12e39dbSAdrian Hunter *data_error = -EIO; 3078f12e39dbSAdrian Hunter else 3079f12e39dbSAdrian Hunter *data_error = 0; 3080f12e39dbSAdrian Hunter 3081f12e39dbSAdrian Hunter /* Clear selected interrupts. */ 3082f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier; 3083f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS); 3084f12e39dbSAdrian Hunter 3085f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER) 3086f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n", 3087f12e39dbSAdrian Hunter mmc_hostname(host->mmc)); 3088f12e39dbSAdrian Hunter 3089f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR); 3090f12e39dbSAdrian Hunter if (intmask) { 3091f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS); 3092f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", 3093f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask); 3094f12e39dbSAdrian Hunter sdhci_dumpregs(host); 3095f12e39dbSAdrian Hunter } 3096f12e39dbSAdrian Hunter 3097f12e39dbSAdrian Hunter return true; 3098f12e39dbSAdrian Hunter } 3099f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq); 3100f12e39dbSAdrian Hunter 3101f12e39dbSAdrian Hunter /*****************************************************************************\ 3102f12e39dbSAdrian Hunter * * 3103b8c86fc5SPierre Ossman * Device allocation/registration * 31041c6a0718SPierre Ossman * * 31051c6a0718SPierre Ossman \*****************************************************************************/ 31061c6a0718SPierre Ossman 3107b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 3108b8c86fc5SPierre Ossman size_t priv_size) 31091c6a0718SPierre Ossman { 31101c6a0718SPierre Ossman struct mmc_host *mmc; 31111c6a0718SPierre Ossman struct sdhci_host *host; 31121c6a0718SPierre Ossman 3113b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 31141c6a0718SPierre Ossman 3115b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 31161c6a0718SPierre Ossman if (!mmc) 3117b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 31181c6a0718SPierre Ossman 31191c6a0718SPierre Ossman host = mmc_priv(mmc); 31201c6a0718SPierre Ossman host->mmc = mmc; 3121bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops; 3122bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops; 31231c6a0718SPierre Ossman 31248cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330; 31258cb851a4SAdrian Hunter 3126f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK; 3127f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK; 3128f12e39dbSAdrian Hunter 312983b600b8SAdrian Hunter host->tuning_delay = -1; 313083b600b8SAdrian Hunter 3131c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG; 3132c846a00fSSrinivas Kandagatla 3133b8c86fc5SPierre Ossman return host; 31341c6a0718SPierre Ossman } 31351c6a0718SPierre Ossman 3136b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 3137b8c86fc5SPierre Ossman 31387b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host) 31397b91369bSAlexandre Courbot { 31407b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc; 31417b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc); 31427b91369bSAlexandre Courbot int ret = -EINVAL; 31437b91369bSAlexandre Courbot 31447b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) 31457b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 31467b91369bSAlexandre Courbot 31477b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */ 31487b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) { 31497b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 31507b91369bSAlexandre Courbot if (ret) { 31517b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n", 31527b91369bSAlexandre Courbot mmc_hostname(mmc)); 31537b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 31547b91369bSAlexandre Courbot } 31557b91369bSAlexandre Courbot } 31567b91369bSAlexandre Courbot 31577b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */ 31587b91369bSAlexandre Courbot if (ret) { 31597b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 31607b91369bSAlexandre Courbot if (ret) 31617b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n", 31627b91369bSAlexandre Courbot mmc_hostname(mmc)); 31637b91369bSAlexandre Courbot } 31647b91369bSAlexandre Courbot 31657b91369bSAlexandre Courbot return ret; 31667b91369bSAlexandre Courbot } 31677b91369bSAlexandre Courbot 31686132a3bfSAdrian Hunter void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1) 31696132a3bfSAdrian Hunter { 31706132a3bfSAdrian Hunter u16 v; 317192e0c44bSZach Brown u64 dt_caps_mask = 0; 317292e0c44bSZach Brown u64 dt_caps = 0; 31736132a3bfSAdrian Hunter 31746132a3bfSAdrian Hunter if (host->read_caps) 31756132a3bfSAdrian Hunter return; 31766132a3bfSAdrian Hunter 31776132a3bfSAdrian Hunter host->read_caps = true; 31786132a3bfSAdrian Hunter 31796132a3bfSAdrian Hunter if (debug_quirks) 31806132a3bfSAdrian Hunter host->quirks = debug_quirks; 31816132a3bfSAdrian Hunter 31826132a3bfSAdrian Hunter if (debug_quirks2) 31836132a3bfSAdrian Hunter host->quirks2 = debug_quirks2; 31846132a3bfSAdrian Hunter 31856132a3bfSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 31866132a3bfSAdrian Hunter 318792e0c44bSZach Brown of_property_read_u64(mmc_dev(host->mmc)->of_node, 318892e0c44bSZach Brown "sdhci-caps-mask", &dt_caps_mask); 318992e0c44bSZach Brown of_property_read_u64(mmc_dev(host->mmc)->of_node, 319092e0c44bSZach Brown "sdhci-caps", &dt_caps); 319192e0c44bSZach Brown 31926132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); 31936132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; 31946132a3bfSAdrian Hunter 31956132a3bfSAdrian Hunter if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) 31966132a3bfSAdrian Hunter return; 31976132a3bfSAdrian Hunter 319892e0c44bSZach Brown if (caps) { 319992e0c44bSZach Brown host->caps = *caps; 320092e0c44bSZach Brown } else { 320192e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); 320292e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask); 320392e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps); 320492e0c44bSZach Brown } 32056132a3bfSAdrian Hunter 32066132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300) 32076132a3bfSAdrian Hunter return; 32086132a3bfSAdrian Hunter 320992e0c44bSZach Brown if (caps1) { 321092e0c44bSZach Brown host->caps1 = *caps1; 321192e0c44bSZach Brown } else { 321292e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); 321392e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask); 321492e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps); 321592e0c44bSZach Brown } 32166132a3bfSAdrian Hunter } 32176132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps); 32186132a3bfSAdrian Hunter 321952f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host) 3220b8c86fc5SPierre Ossman { 3221b8c86fc5SPierre Ossman struct mmc_host *mmc; 3222f2119df6SArindam Nath u32 max_current_caps; 3223f2119df6SArindam Nath unsigned int ocr_avail; 3224f5fa92e5SAdrian Hunter unsigned int override_timeout_clk; 322559241757SDong Aisheng u32 max_clk; 3226b8c86fc5SPierre Ossman int ret; 3227b8c86fc5SPierre Ossman 3228b8c86fc5SPierre Ossman WARN_ON(host == NULL); 3229b8c86fc5SPierre Ossman if (host == NULL) 3230b8c86fc5SPierre Ossman return -EINVAL; 3231b8c86fc5SPierre Ossman 3232b8c86fc5SPierre Ossman mmc = host->mmc; 3233b8c86fc5SPierre Ossman 3234efba142bSJon Hunter /* 3235efba142bSJon Hunter * If there are external regulators, get them. Note this must be done 3236efba142bSJon Hunter * early before resetting the host and reading the capabilities so that 3237efba142bSJon Hunter * the host can take the appropriate action if regulators are not 3238efba142bSJon Hunter * available. 3239efba142bSJon Hunter */ 3240efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc); 32412a63303dSWolfram Sang if (ret) 3242efba142bSJon Hunter return ret; 3243efba142bSJon Hunter 324406ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n", 324506ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION), 324606ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE)); 324706ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n", 324806ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES), 324906ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1)); 325006ebc601SShawn Lin 32516132a3bfSAdrian Hunter sdhci_read_caps(host); 3252b8c86fc5SPierre Ossman 3253f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk; 3254f5fa92e5SAdrian Hunter 325585105c53SZhangfei Gao if (host->version > SDHCI_SPEC_300) { 32562e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n", 32572e4456f0SMarek Vasut mmc_hostname(mmc), host->version); 32581c6a0718SPierre Ossman } 32591c6a0718SPierre Ossman 3260b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 3261a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 326228da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA)) 3263a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 32641c6a0718SPierre Ossman else 3265a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 32661c6a0718SPierre Ossman 3267b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 3268a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 3269cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 3270a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 32717c168e3dSFeng Tang } 32727c168e3dSFeng Tang 3273f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) && 327428da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2)) 32752134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 32762134a922SPierre Ossman 32772134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 32782134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 32792134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 32802134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 32812134a922SPierre Ossman } 32822134a922SPierre Ossman 3283e57a5f61SAdrian Hunter /* 3284e57a5f61SAdrian Hunter * It is assumed that a 64-bit capable device has set a 64-bit DMA mask 3285e57a5f61SAdrian Hunter * and *must* do 64-bit DMA. A driver has the opportunity to change 3286e57a5f61SAdrian Hunter * that during the first call to ->enable_dma(). Similarly 3287e57a5f61SAdrian Hunter * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to 3288e57a5f61SAdrian Hunter * implement. 3289e57a5f61SAdrian Hunter */ 329028da3589SAdrian Hunter if (host->caps & SDHCI_CAN_64BIT) 3291e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA; 3292e57a5f61SAdrian Hunter 3293a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 32947b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host); 32957b91369bSAlexandre Courbot 32967b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma) 32977b91369bSAlexandre Courbot ret = host->ops->enable_dma(host); 32987b91369bSAlexandre Courbot 32997b91369bSAlexandre Courbot if (ret) { 33006606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n", 3301b8c86fc5SPierre Ossman mmc_hostname(mmc)); 33027b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 33037b91369bSAlexandre Courbot 33047b91369bSAlexandre Courbot ret = 0; 33051c6a0718SPierre Ossman } 3306b8c86fc5SPierre Ossman } 33071c6a0718SPierre Ossman 3308e57a5f61SAdrian Hunter /* SDMA does not support 64-bit DMA */ 3309e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3310e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA; 3311e57a5f61SAdrian Hunter 33122134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 3313e66e61cbSRussell King dma_addr_t dma; 3314e66e61cbSRussell King void *buf; 3315e66e61cbSRussell King 33162134a922SPierre Ossman /* 331776fe379aSAdrian Hunter * The DMA descriptor table size is calculated as the maximum 331876fe379aSAdrian Hunter * number of segments times 2, to allow for an alignment 331976fe379aSAdrian Hunter * descriptor for each segment, plus 1 for a nop end descriptor, 332076fe379aSAdrian Hunter * all multipled by the descriptor size. 33212134a922SPierre Ossman */ 3322e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) { 3323e57a5f61SAdrian Hunter host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * 3324e57a5f61SAdrian Hunter SDHCI_ADMA2_64_DESC_SZ; 3325e57a5f61SAdrian Hunter host->desc_sz = SDHCI_ADMA2_64_DESC_SZ; 3326e57a5f61SAdrian Hunter } else { 3327739d46dcSAdrian Hunter host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * 3328739d46dcSAdrian Hunter SDHCI_ADMA2_32_DESC_SZ; 3329739d46dcSAdrian Hunter host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; 3330e57a5f61SAdrian Hunter } 3331e66e61cbSRussell King 333204a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; 3333e66e61cbSRussell King buf = dma_alloc_coherent(mmc_dev(mmc), host->align_buffer_sz + 3334e66e61cbSRussell King host->adma_table_sz, &dma, GFP_KERNEL); 3335e66e61cbSRussell King if (!buf) { 33366606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", 33372134a922SPierre Ossman mmc_hostname(mmc)); 33382134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 3339e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) & 3340e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) { 33416606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n", 3342d1e49f77SRussell King mmc_hostname(mmc)); 3343d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA; 3344e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 3345e66e61cbSRussell King host->adma_table_sz, buf, dma); 3346e66e61cbSRussell King } else { 3347e66e61cbSRussell King host->align_buffer = buf; 3348e66e61cbSRussell King host->align_addr = dma; 3349edd63fccSRussell King 3350e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz; 3351e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz; 3352e66e61cbSRussell King } 33532134a922SPierre Ossman } 33542134a922SPierre Ossman 33557659150cSPierre Ossman /* 33567659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 33577659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 33587659150cSPierre Ossman * mask here in that case. 33597659150cSPierre Ossman */ 3360a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 33617659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 33624e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask; 33637659150cSPierre Ossman } 33641c6a0718SPierre Ossman 3365c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 336628da3589SAdrian Hunter host->max_clk = (host->caps & SDHCI_CLOCK_V3_BASE_MASK) 3367c4687d5fSZhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 3368c4687d5fSZhangfei Gao else 336928da3589SAdrian Hunter host->max_clk = (host->caps & SDHCI_CLOCK_BASE_MASK) 3370c4687d5fSZhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 3371c4687d5fSZhangfei Gao 33724240ff0aSBen Dooks host->max_clk *= 1000000; 3373f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 3374f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 33754240ff0aSBen Dooks if (!host->ops->get_max_clock) { 33762e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n", 33772e4456f0SMarek Vasut mmc_hostname(mmc)); 3378eb5c20deSAdrian Hunter ret = -ENODEV; 3379eb5c20deSAdrian Hunter goto undma; 33801c6a0718SPierre Ossman } 33814240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 33824240ff0aSBen Dooks } 33831c6a0718SPierre Ossman 33841c6a0718SPierre Ossman /* 3385c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock 3386c3ed3877SArindam Nath * multiplier is supported. 3387c3ed3877SArindam Nath */ 338828da3589SAdrian Hunter host->clk_mul = (host->caps1 & SDHCI_CLOCK_MUL_MASK) >> 3389c3ed3877SArindam Nath SDHCI_CLOCK_MUL_SHIFT; 3390c3ed3877SArindam Nath 3391c3ed3877SArindam Nath /* 3392c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable 3393c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock 3394c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier 3395c3ed3877SArindam Nath * in the Capabilities Register. 3396c3ed3877SArindam Nath */ 3397c3ed3877SArindam Nath if (host->clk_mul) 3398c3ed3877SArindam Nath host->clk_mul += 1; 3399c3ed3877SArindam Nath 3400c3ed3877SArindam Nath /* 34011c6a0718SPierre Ossman * Set host parameters. 34021c6a0718SPierre Ossman */ 340359241757SDong Aisheng max_clk = host->max_clk; 340459241757SDong Aisheng 3405ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 3406a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 3407c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) { 3408c3ed3877SArindam Nath if (host->clk_mul) { 3409c3ed3877SArindam Nath mmc->f_min = (host->max_clk * host->clk_mul) / 1024; 341059241757SDong Aisheng max_clk = host->max_clk * host->clk_mul; 3411c3ed3877SArindam Nath } else 34120397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 3413c3ed3877SArindam Nath } else 34140397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 341515ec4461SPhilip Rakity 3416d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk) 341759241757SDong Aisheng mmc->f_max = max_clk; 341859241757SDong Aisheng 341928aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 342028da3589SAdrian Hunter host->timeout_clk = (host->caps & SDHCI_TIMEOUT_CLK_MASK) >> 342128aab053SAisheng Dong SDHCI_TIMEOUT_CLK_SHIFT; 34228cc35289SShawn Lin 34238cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) 34248cc35289SShawn Lin host->timeout_clk *= 1000; 34258cc35289SShawn Lin 3426272308caSAndy Shevchenko if (host->timeout_clk == 0) { 34278cc35289SShawn Lin if (!host->ops->get_timeout_clock) { 342828aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", 342928aab053SAisheng Dong mmc_hostname(mmc)); 3430eb5c20deSAdrian Hunter ret = -ENODEV; 3431eb5c20deSAdrian Hunter goto undma; 3432272308caSAndy Shevchenko } 343328aab053SAisheng Dong 34348cc35289SShawn Lin host->timeout_clk = 34358cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host), 34368cc35289SShawn Lin 1000); 34378cc35289SShawn Lin } 3438272308caSAndy Shevchenko 343999513624SAdrian Hunter if (override_timeout_clk) 344099513624SAdrian Hunter host->timeout_clk = override_timeout_clk; 344199513624SAdrian Hunter 3442a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ? 3443a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27; 3444a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk; 344528aab053SAisheng Dong } 344658d1246dSAdrian Hunter 3447e89d456fSAndrei Warkentin mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; 3448781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; 3449e89d456fSAndrei Warkentin 3450e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 3451e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 34525fe23c7fSAnton Vorontsov 34538edf6371SAndrei Warkentin /* Auto-CMD23 stuff only works in ADMA or PIO. */ 34544f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 34558edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 34563bfa6f03SScott Branden !(host->flags & SDHCI_USE_SDMA)) && 34573bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { 34588edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 3459f421865dSAdrian Hunter DBG("Auto-CMD23 available\n"); 34608edf6371SAndrei Warkentin } else { 3461f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n"); 34628edf6371SAndrei Warkentin } 34638edf6371SAndrei Warkentin 346415ec4461SPhilip Rakity /* 346515ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself 346615ec4461SPhilip Rakity * might not have the pins brought out. Boards that support 346715ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 346815ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we 346915ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 347015ec4461SPhilip Rakity */ 34715fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 347215ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 34731c6a0718SPierre Ossman 347463ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) 347563ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23; 347663ef5d8cSJerry Huang 347728da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD) 3478a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 34791c6a0718SPierre Ossman 3480176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 3481860951c5SJaehoon Chung mmc_card_is_removable(mmc) && 3482287980e4SArnd Bergmann mmc_gpio_get_cd(host->mmc) < 0) 348368d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 348468d1fb7eSAnton Vorontsov 34856231f3deSPhilip Rakity /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ 34863a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 34873a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc); 34883a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 3489cec2e216SKevin Liu 1950000)) 349028da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | 34918363c374SKevin Liu SDHCI_SUPPORT_SDR50 | 34926231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50); 3493a3361abaSChris Ball if (ret) { 3494a3361abaSChris Ball pr_warn("%s: Failed to enable vqmmc regulator: %d\n", 3495a3361abaSChris Ball mmc_hostname(mmc), ret); 34964bb74313SAdrian Hunter mmc->supply.vqmmc = ERR_PTR(-EINVAL); 3497a3361abaSChris Ball } 34988363c374SKevin Liu } 34996231f3deSPhilip Rakity 350028da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { 350128da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 35026a66180aSDaniel Drake SDHCI_SUPPORT_DDR50); 350328da3589SAdrian Hunter } 35046a66180aSDaniel Drake 35054188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ 350628da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 35074188bba0SAl Cooper SDHCI_SUPPORT_DDR50)) 3508f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 3509f2119df6SArindam Nath 3510f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */ 351128da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) { 3512f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 3513156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2 3514156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200. 3515156e14b1SGiuseppe CAVALLARO */ 3516549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) 3517156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200; 351828da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { 3519f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 352028da3589SAdrian Hunter } 3521f2119df6SArindam Nath 3522e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && 352328da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400)) 3524e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400; 3525e9fb05d5SAdrian Hunter 3526549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && 3527549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) || 3528549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 3529549c0b18SAdrian Hunter 1300000))) 3530549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; 3531549c0b18SAdrian Hunter 353228da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) && 35339107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) 3534f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 3535f2119df6SArindam Nath 3536069c9f14SGirish K S /* Does the host need tuning for SDR50? */ 353728da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING) 3538b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 3539b513ea25SArindam Nath 3540d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 354128da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A) 3542d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 354328da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C) 3544d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 354528da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D) 3546d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 3547d6d50a15SArindam Nath 3548cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */ 354928da3589SAdrian Hunter host->tuning_count = (host->caps1 & SDHCI_RETUNING_TIMER_COUNT_MASK) >> 3550cf2b5eeaSArindam Nath SDHCI_RETUNING_TIMER_COUNT_SHIFT; 3551cf2b5eeaSArindam Nath 3552cf2b5eeaSArindam Nath /* 3553cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of 3554cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1). 3555cf2b5eeaSArindam Nath */ 3556cf2b5eeaSArindam Nath if (host->tuning_count) 3557cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 3558cf2b5eeaSArindam Nath 3559cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */ 356028da3589SAdrian Hunter host->tuning_mode = (host->caps1 & SDHCI_RETUNING_MODE_MASK) >> 3561cf2b5eeaSArindam Nath SDHCI_RETUNING_MODE_SHIFT; 3562cf2b5eeaSArindam Nath 35638f230f45STakashi Iwai ocr_avail = 0; 3564bad37e1aSPhilip Rakity 3565f2119df6SArindam Nath /* 3566f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System 3567f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 3568f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities 3569f2119df6SArindam Nath * register is set. The actual current value is 4 times the register 3570f2119df6SArindam Nath * value. 3571f2119df6SArindam Nath */ 3572f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 35733a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { 3574ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc); 3575bad37e1aSPhilip Rakity if (curr > 0) { 3576bad37e1aSPhilip Rakity 3577bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */ 3578bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */ 3579bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; 3580bad37e1aSPhilip Rakity 3581bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 3582bad37e1aSPhilip Rakity max_current_caps = 3583bad37e1aSPhilip Rakity (curr << SDHCI_MAX_CURRENT_330_SHIFT) | 3584bad37e1aSPhilip Rakity (curr << SDHCI_MAX_CURRENT_300_SHIFT) | 3585bad37e1aSPhilip Rakity (curr << SDHCI_MAX_CURRENT_180_SHIFT); 3586bad37e1aSPhilip Rakity } 3587bad37e1aSPhilip Rakity } 3588f2119df6SArindam Nath 358928da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) { 35908f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 3591f2119df6SArindam Nath 359255c4665eSAaron Lu mmc->max_current_330 = ((max_current_caps & 3593f2119df6SArindam Nath SDHCI_MAX_CURRENT_330_MASK) >> 3594f2119df6SArindam Nath SDHCI_MAX_CURRENT_330_SHIFT) * 3595f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 3596f2119df6SArindam Nath } 359728da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) { 35988f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 3599f2119df6SArindam Nath 360055c4665eSAaron Lu mmc->max_current_300 = ((max_current_caps & 3601f2119df6SArindam Nath SDHCI_MAX_CURRENT_300_MASK) >> 3602f2119df6SArindam Nath SDHCI_MAX_CURRENT_300_SHIFT) * 3603f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 3604f2119df6SArindam Nath } 360528da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) { 36068f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195; 36078f230f45STakashi Iwai 360855c4665eSAaron Lu mmc->max_current_180 = ((max_current_caps & 3609f2119df6SArindam Nath SDHCI_MAX_CURRENT_180_MASK) >> 3610f2119df6SArindam Nath SDHCI_MAX_CURRENT_180_SHIFT) * 3611f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 3612f2119df6SArindam Nath } 3613f2119df6SArindam Nath 36145fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */ 36155fd26c7eSUlf Hansson if (host->ocr_mask) 36165fd26c7eSUlf Hansson ocr_avail = host->ocr_mask; 36175fd26c7eSUlf Hansson 36185fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */ 36193a48edc4STim Kryger if (mmc->ocr_avail) 362052221610STim Kryger ocr_avail = mmc->ocr_avail; 36213a48edc4STim Kryger 36228f230f45STakashi Iwai mmc->ocr_avail = ocr_avail; 36238f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 36248f230f45STakashi Iwai if (host->ocr_avail_sdio) 36258f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 36268f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail; 36278f230f45STakashi Iwai if (host->ocr_avail_sd) 36288f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 36298f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */ 36308f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 36318f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 36328f230f45STakashi Iwai if (host->ocr_avail_mmc) 36338f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 36341c6a0718SPierre Ossman 36351c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 36362e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n", 36372e4456f0SMarek Vasut mmc_hostname(mmc)); 3638eb5c20deSAdrian Hunter ret = -ENODEV; 3639eb5c20deSAdrian Hunter goto unreg; 36401c6a0718SPierre Ossman } 36411c6a0718SPierre Ossman 36428cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 36438cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 36448cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || 36458cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) 36468cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180; 36478cb851a4SAdrian Hunter 36488cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) 36498cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120; 36508cb851a4SAdrian Hunter 36511c6a0718SPierre Ossman spin_lock_init(&host->lock); 36521c6a0718SPierre Ossman 36531c6a0718SPierre Ossman /* 36542134a922SPierre Ossman * Maximum number of segments. Depends on if the hardware 36552134a922SPierre Ossman * can do scatter/gather or not. 36561c6a0718SPierre Ossman */ 36572134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 36584fb213f8SAdrian Hunter mmc->max_segs = SDHCI_MAX_SEGS; 3659a13abc7bSRichard Röjfors else if (host->flags & SDHCI_USE_SDMA) 3660a36274e0SMartin K. Petersen mmc->max_segs = 1; 36612134a922SPierre Ossman else /* PIO */ 36624fb213f8SAdrian Hunter mmc->max_segs = SDHCI_MAX_SEGS; 36631c6a0718SPierre Ossman 36641c6a0718SPierre Ossman /* 3665ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary 3666ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this 3667ac00531dSAdrian Hunter * is less anyway. 36681c6a0718SPierre Ossman */ 36691c6a0718SPierre Ossman mmc->max_req_size = 524288; 36701c6a0718SPierre Ossman 36711c6a0718SPierre Ossman /* 36721c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 36732134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 36742134a922SPierre Ossman * be larger than 64 KiB though. 36751c6a0718SPierre Ossman */ 367630652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 367730652aa3SOlof Johansson if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) 367830652aa3SOlof Johansson mmc->max_seg_size = 65535; 36792134a922SPierre Ossman else 368030652aa3SOlof Johansson mmc->max_seg_size = 65536; 368130652aa3SOlof Johansson } else { 36821c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 368330652aa3SOlof Johansson } 36841c6a0718SPierre Ossman 36851c6a0718SPierre Ossman /* 36861c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 36871c6a0718SPierre Ossman * is specified in the capabilities register. 36881c6a0718SPierre Ossman */ 36890633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 36900633f654SAnton Vorontsov mmc->max_blk_size = 2; 36910633f654SAnton Vorontsov } else { 369228da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> 36930633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 36941c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 36956606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", 36966606110dSJoe Perches mmc_hostname(mmc)); 36970633f654SAnton Vorontsov mmc->max_blk_size = 0; 36980633f654SAnton Vorontsov } 36990633f654SAnton Vorontsov } 37000633f654SAnton Vorontsov 37011c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 37021c6a0718SPierre Ossman 37031c6a0718SPierre Ossman /* 37041c6a0718SPierre Ossman * Maximum block count. 37051c6a0718SPierre Ossman */ 37061388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 37071c6a0718SPierre Ossman 370852f5336dSAdrian Hunter return 0; 370952f5336dSAdrian Hunter 371052f5336dSAdrian Hunter unreg: 371152f5336dSAdrian Hunter if (!IS_ERR(mmc->supply.vqmmc)) 371252f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc); 371352f5336dSAdrian Hunter undma: 371452f5336dSAdrian Hunter if (host->align_buffer) 371552f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 371652f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer, 371752f5336dSAdrian Hunter host->align_addr); 371852f5336dSAdrian Hunter host->adma_table = NULL; 371952f5336dSAdrian Hunter host->align_buffer = NULL; 372052f5336dSAdrian Hunter 372152f5336dSAdrian Hunter return ret; 372252f5336dSAdrian Hunter } 372352f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host); 372452f5336dSAdrian Hunter 37254180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host) 37264180ffa8SAdrian Hunter { 37274180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc; 37284180ffa8SAdrian Hunter 37294180ffa8SAdrian Hunter if (!IS_ERR(mmc->supply.vqmmc)) 37304180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc); 37314180ffa8SAdrian Hunter 37324180ffa8SAdrian Hunter if (host->align_buffer) 37334180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 37344180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer, 37354180ffa8SAdrian Hunter host->align_addr); 37364180ffa8SAdrian Hunter host->adma_table = NULL; 37374180ffa8SAdrian Hunter host->align_buffer = NULL; 37384180ffa8SAdrian Hunter } 37394180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host); 37404180ffa8SAdrian Hunter 374152f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host) 374252f5336dSAdrian Hunter { 374352f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc; 374452f5336dSAdrian Hunter int ret; 374552f5336dSAdrian Hunter 37461c6a0718SPierre Ossman /* 37471c6a0718SPierre Ossman * Init tasklets. 37481c6a0718SPierre Ossman */ 37491c6a0718SPierre Ossman tasklet_init(&host->finish_tasklet, 37501c6a0718SPierre Ossman sdhci_tasklet_finish, (unsigned long)host); 37511c6a0718SPierre Ossman 37522ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0); 37532ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); 37541c6a0718SPierre Ossman 3755b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int); 3756b513ea25SArindam Nath 37572af502caSShawn Guo sdhci_init(host, 0); 37582af502caSShawn Guo 3759781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, 3760781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host); 37610fc81ee3SMark Brown if (ret) { 37620fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n", 37630fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret); 37641c6a0718SPierre Ossman goto untasklet; 37650fc81ee3SMark Brown } 37661c6a0718SPierre Ossman 3767061d17a6SAdrian Hunter ret = sdhci_led_register(host); 37680fc81ee3SMark Brown if (ret) { 37690fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n", 37700fc81ee3SMark Brown mmc_hostname(mmc), ret); 3771eb5c20deSAdrian Hunter goto unirq; 37720fc81ee3SMark Brown } 37732f730fecSPierre Ossman 37741c6a0718SPierre Ossman mmiowb(); 37751c6a0718SPierre Ossman 3776eb5c20deSAdrian Hunter ret = mmc_add_host(mmc); 3777eb5c20deSAdrian Hunter if (ret) 3778eb5c20deSAdrian Hunter goto unled; 37791c6a0718SPierre Ossman 3780a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n", 3781d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 3782e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ? 3783e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : 3784a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 37851c6a0718SPierre Ossman 37867260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 37877260cf5eSAnton Vorontsov 37881c6a0718SPierre Ossman return 0; 37891c6a0718SPierre Ossman 3790eb5c20deSAdrian Hunter unled: 3791061d17a6SAdrian Hunter sdhci_led_unregister(host); 3792eb5c20deSAdrian Hunter unirq: 379303231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 3794b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3795b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 37962f730fecSPierre Ossman free_irq(host->irq, host); 37971c6a0718SPierre Ossman untasklet: 37981c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 379952f5336dSAdrian Hunter 38001c6a0718SPierre Ossman return ret; 38011c6a0718SPierre Ossman } 380252f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host); 38031c6a0718SPierre Ossman 380452f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host) 380552f5336dSAdrian Hunter { 380652f5336dSAdrian Hunter int ret; 380752f5336dSAdrian Hunter 380852f5336dSAdrian Hunter ret = sdhci_setup_host(host); 380952f5336dSAdrian Hunter if (ret) 381052f5336dSAdrian Hunter return ret; 381152f5336dSAdrian Hunter 38124180ffa8SAdrian Hunter ret = __sdhci_add_host(host); 38134180ffa8SAdrian Hunter if (ret) 38144180ffa8SAdrian Hunter goto cleanup; 38154180ffa8SAdrian Hunter 38164180ffa8SAdrian Hunter return 0; 38174180ffa8SAdrian Hunter 38184180ffa8SAdrian Hunter cleanup: 38194180ffa8SAdrian Hunter sdhci_cleanup_host(host); 38204180ffa8SAdrian Hunter 38214180ffa8SAdrian Hunter return ret; 382252f5336dSAdrian Hunter } 3823b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 3824b8c86fc5SPierre Ossman 38251e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 38261c6a0718SPierre Ossman { 38273a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 38281e72859eSPierre Ossman unsigned long flags; 38291e72859eSPierre Ossman 38301e72859eSPierre Ossman if (dead) { 38311e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 38321e72859eSPierre Ossman 38331e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 38341e72859eSPierre Ossman 38355d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) { 3836a3c76eb9SGirish K S pr_err("%s: Controller removed during " 38374e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc)); 38385d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 38391e72859eSPierre Ossman } 38401e72859eSPierre Ossman 38411e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 38421e72859eSPierre Ossman } 38431e72859eSPierre Ossman 38447260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 38457260cf5eSAnton Vorontsov 38464e743f1fSMarkus Mayer mmc_remove_host(mmc); 38471c6a0718SPierre Ossman 3848061d17a6SAdrian Hunter sdhci_led_unregister(host); 38492f730fecSPierre Ossman 38501e72859eSPierre Ossman if (!dead) 385103231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 38521c6a0718SPierre Ossman 3853b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3854b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 38551c6a0718SPierre Ossman free_irq(host->irq, host); 38561c6a0718SPierre Ossman 38571c6a0718SPierre Ossman del_timer_sync(&host->timer); 3858d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer); 38591c6a0718SPierre Ossman 38601c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 38612134a922SPierre Ossman 38623a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) 38633a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc); 38646231f3deSPhilip Rakity 3865edd63fccSRussell King if (host->align_buffer) 3866e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 3867e66e61cbSRussell King host->adma_table_sz, host->align_buffer, 3868e66e61cbSRussell King host->align_addr); 38692134a922SPierre Ossman 38704efaa6fbSAdrian Hunter host->adma_table = NULL; 38712134a922SPierre Ossman host->align_buffer = NULL; 38721c6a0718SPierre Ossman } 38731c6a0718SPierre Ossman 3874b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 3875b8c86fc5SPierre Ossman 3876b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 38771c6a0718SPierre Ossman { 3878b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 38791c6a0718SPierre Ossman } 38801c6a0718SPierre Ossman 3881b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 38821c6a0718SPierre Ossman 38831c6a0718SPierre Ossman /*****************************************************************************\ 38841c6a0718SPierre Ossman * * 38851c6a0718SPierre Ossman * Driver init/exit * 38861c6a0718SPierre Ossman * * 38871c6a0718SPierre Ossman \*****************************************************************************/ 38881c6a0718SPierre Ossman 38891c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 38901c6a0718SPierre Ossman { 3891a3c76eb9SGirish K S pr_info(DRIVER_NAME 38921c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 3893a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 38941c6a0718SPierre Ossman 3895b8c86fc5SPierre Ossman return 0; 38961c6a0718SPierre Ossman } 38971c6a0718SPierre Ossman 38981c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 38991c6a0718SPierre Ossman { 39001c6a0718SPierre Ossman } 39011c6a0718SPierre Ossman 39021c6a0718SPierre Ossman module_init(sdhci_drv_init); 39031c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 39041c6a0718SPierre Ossman 39051c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 390666fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444); 39071c6a0718SPierre Ossman 390832710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 3909b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 39101c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 39111c6a0718SPierre Ossman 39121c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 391366fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks."); 3914