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> 171c6a0718SPierre Ossman #include <linux/highmem.h> 18b8c86fc5SPierre Ossman #include <linux/io.h> 191c6a0718SPierre Ossman #include <linux/dma-mapping.h> 2011763609SRalf Baechle #include <linux/scatterlist.h> 211c6a0718SPierre Ossman 222f730fecSPierre Ossman #include <linux/leds.h> 232f730fecSPierre Ossman 241c6a0718SPierre Ossman #include <linux/mmc/host.h> 251c6a0718SPierre Ossman 261c6a0718SPierre Ossman #include "sdhci.h" 271c6a0718SPierre Ossman 281c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 291c6a0718SPierre Ossman 301c6a0718SPierre Ossman #define DBG(f, x...) \ 311c6a0718SPierre Ossman pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 321c6a0718SPierre Ossman 33f9134319SPierre Ossman #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 34f9134319SPierre Ossman defined(CONFIG_MMC_SDHCI_MODULE)) 35f9134319SPierre Ossman #define SDHCI_USE_LEDS_CLASS 36f9134319SPierre Ossman #endif 37f9134319SPierre Ossman 381c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 391c6a0718SPierre Ossman 401c6a0718SPierre Ossman static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); 411c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *); 421c6a0718SPierre Ossman 431c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 441c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *); 451c6a0718SPierre Ossman 461c6a0718SPierre Ossman static void sdhci_dumpregs(struct sdhci_host *host) 471c6a0718SPierre Ossman { 481c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); 491c6a0718SPierre Ossman 501c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 514e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 524e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 531c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 544e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 554e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 561c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 574e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 584e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 591c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 604e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 614e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 621c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 634e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 644e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 651c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 664e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 674e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 681c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 694e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 704e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 711c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 724e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 734e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 741c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 754e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 764e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 771c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", 784e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 794e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 801c6a0718SPierre Ossman 81be3f4ae0SBen Dooks if (host->flags & SDHCI_USE_ADMA) 82be3f4ae0SBen Dooks printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 83be3f4ae0SBen Dooks readl(host->ioaddr + SDHCI_ADMA_ERROR), 84be3f4ae0SBen Dooks readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); 85be3f4ae0SBen Dooks 861c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 871c6a0718SPierre Ossman } 881c6a0718SPierre Ossman 891c6a0718SPierre Ossman /*****************************************************************************\ 901c6a0718SPierre Ossman * * 911c6a0718SPierre Ossman * Low level functions * 921c6a0718SPierre Ossman * * 931c6a0718SPierre Ossman \*****************************************************************************/ 941c6a0718SPierre Ossman 957260cf5eSAnton Vorontsov static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 967260cf5eSAnton Vorontsov { 977260cf5eSAnton Vorontsov u32 ier; 987260cf5eSAnton Vorontsov 997260cf5eSAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1007260cf5eSAnton Vorontsov ier &= ~clear; 1017260cf5eSAnton Vorontsov ier |= set; 1027260cf5eSAnton Vorontsov sdhci_writel(host, ier, SDHCI_INT_ENABLE); 1037260cf5eSAnton Vorontsov sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 1047260cf5eSAnton Vorontsov } 1057260cf5eSAnton Vorontsov 1067260cf5eSAnton Vorontsov static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) 1077260cf5eSAnton Vorontsov { 1087260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, 0, irqs); 1097260cf5eSAnton Vorontsov } 1107260cf5eSAnton Vorontsov 1117260cf5eSAnton Vorontsov static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) 1127260cf5eSAnton Vorontsov { 1137260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, irqs, 0); 1147260cf5eSAnton Vorontsov } 1157260cf5eSAnton Vorontsov 1167260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1177260cf5eSAnton Vorontsov { 1187260cf5eSAnton Vorontsov u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 1197260cf5eSAnton Vorontsov 12068d1fb7eSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 12168d1fb7eSAnton Vorontsov return; 12268d1fb7eSAnton Vorontsov 1237260cf5eSAnton Vorontsov if (enable) 1247260cf5eSAnton Vorontsov sdhci_unmask_irqs(host, irqs); 1257260cf5eSAnton Vorontsov else 1267260cf5eSAnton Vorontsov sdhci_mask_irqs(host, irqs); 1277260cf5eSAnton Vorontsov } 1287260cf5eSAnton Vorontsov 1297260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host) 1307260cf5eSAnton Vorontsov { 1317260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true); 1327260cf5eSAnton Vorontsov } 1337260cf5eSAnton Vorontsov 1347260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host) 1357260cf5eSAnton Vorontsov { 1367260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false); 1377260cf5eSAnton Vorontsov } 1387260cf5eSAnton Vorontsov 1391c6a0718SPierre Ossman static void sdhci_reset(struct sdhci_host *host, u8 mask) 1401c6a0718SPierre Ossman { 1411c6a0718SPierre Ossman unsigned long timeout; 142063a9dbbSAnton Vorontsov u32 uninitialized_var(ier); 1431c6a0718SPierre Ossman 144b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 1454e4141a5SAnton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & 1461c6a0718SPierre Ossman SDHCI_CARD_PRESENT)) 1471c6a0718SPierre Ossman return; 1481c6a0718SPierre Ossman } 1491c6a0718SPierre Ossman 150063a9dbbSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 151063a9dbbSAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 152063a9dbbSAnton Vorontsov 1534e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 1541c6a0718SPierre Ossman 1551c6a0718SPierre Ossman if (mask & SDHCI_RESET_ALL) 1561c6a0718SPierre Ossman host->clock = 0; 1571c6a0718SPierre Ossman 1581c6a0718SPierre Ossman /* Wait max 100 ms */ 1591c6a0718SPierre Ossman timeout = 100; 1601c6a0718SPierre Ossman 1611c6a0718SPierre Ossman /* hw clears the bit when it's done */ 1624e4141a5SAnton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 1631c6a0718SPierre Ossman if (timeout == 0) { 1641c6a0718SPierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 1651c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 1661c6a0718SPierre Ossman sdhci_dumpregs(host); 1671c6a0718SPierre Ossman return; 1681c6a0718SPierre Ossman } 1691c6a0718SPierre Ossman timeout--; 1701c6a0718SPierre Ossman mdelay(1); 1711c6a0718SPierre Ossman } 172063a9dbbSAnton Vorontsov 173063a9dbbSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 174063a9dbbSAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 1751c6a0718SPierre Ossman } 1761c6a0718SPierre Ossman 1771c6a0718SPierre Ossman static void sdhci_init(struct sdhci_host *host) 1781c6a0718SPierre Ossman { 1791c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1801c6a0718SPierre Ossman 1817260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 1827260cf5eSAnton Vorontsov SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 1831c6a0718SPierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 1841c6a0718SPierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 1856aa943abSAnton Vorontsov SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 1867260cf5eSAnton Vorontsov } 1871c6a0718SPierre Ossman 1887260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 1897260cf5eSAnton Vorontsov { 1907260cf5eSAnton Vorontsov sdhci_init(host); 1917260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 1921c6a0718SPierre Ossman } 1931c6a0718SPierre Ossman 1941c6a0718SPierre Ossman static void sdhci_activate_led(struct sdhci_host *host) 1951c6a0718SPierre Ossman { 1961c6a0718SPierre Ossman u8 ctrl; 1971c6a0718SPierre Ossman 1984e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 1991c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 2004e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2011c6a0718SPierre Ossman } 2021c6a0718SPierre Ossman 2031c6a0718SPierre Ossman static void sdhci_deactivate_led(struct sdhci_host *host) 2041c6a0718SPierre Ossman { 2051c6a0718SPierre Ossman u8 ctrl; 2061c6a0718SPierre Ossman 2074e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 2081c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2094e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2101c6a0718SPierre Ossman } 2111c6a0718SPierre Ossman 212f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 2132f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 2142f730fecSPierre Ossman enum led_brightness brightness) 2152f730fecSPierre Ossman { 2162f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2172f730fecSPierre Ossman unsigned long flags; 2182f730fecSPierre Ossman 2192f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 2202f730fecSPierre Ossman 2212f730fecSPierre Ossman if (brightness == LED_OFF) 2222f730fecSPierre Ossman sdhci_deactivate_led(host); 2232f730fecSPierre Ossman else 2242f730fecSPierre Ossman sdhci_activate_led(host); 2252f730fecSPierre Ossman 2262f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2272f730fecSPierre Ossman } 2282f730fecSPierre Ossman #endif 2292f730fecSPierre Ossman 2301c6a0718SPierre Ossman /*****************************************************************************\ 2311c6a0718SPierre Ossman * * 2321c6a0718SPierre Ossman * Core functions * 2331c6a0718SPierre Ossman * * 2341c6a0718SPierre Ossman \*****************************************************************************/ 2351c6a0718SPierre Ossman 2361c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 2371c6a0718SPierre Ossman { 2387659150cSPierre Ossman unsigned long flags; 2397659150cSPierre Ossman size_t blksize, len, chunk; 2407244b85bSSteven Noonan u32 uninitialized_var(scratch); 2417659150cSPierre Ossman u8 *buf; 2421c6a0718SPierre Ossman 2431c6a0718SPierre Ossman DBG("PIO reading\n"); 2441c6a0718SPierre Ossman 2451c6a0718SPierre Ossman blksize = host->data->blksz; 2467659150cSPierre Ossman chunk = 0; 2471c6a0718SPierre Ossman 2487659150cSPierre Ossman local_irq_save(flags); 2491c6a0718SPierre Ossman 2501c6a0718SPierre Ossman while (blksize) { 2517659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 2527659150cSPierre Ossman BUG(); 2537659150cSPierre Ossman 2547659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 2557659150cSPierre Ossman 2567659150cSPierre Ossman blksize -= len; 2577659150cSPierre Ossman host->sg_miter.consumed = len; 2587659150cSPierre Ossman 2597659150cSPierre Ossman buf = host->sg_miter.addr; 2607659150cSPierre Ossman 2617659150cSPierre Ossman while (len) { 2627659150cSPierre Ossman if (chunk == 0) { 2634e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 2647659150cSPierre Ossman chunk = 4; 2651c6a0718SPierre Ossman } 2661c6a0718SPierre Ossman 2677659150cSPierre Ossman *buf = scratch & 0xFF; 2681c6a0718SPierre Ossman 2697659150cSPierre Ossman buf++; 2707659150cSPierre Ossman scratch >>= 8; 2717659150cSPierre Ossman chunk--; 2727659150cSPierre Ossman len--; 2737659150cSPierre Ossman } 2741c6a0718SPierre Ossman } 2751c6a0718SPierre Ossman 2767659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 2777659150cSPierre Ossman 2787659150cSPierre Ossman local_irq_restore(flags); 2791c6a0718SPierre Ossman } 2801c6a0718SPierre Ossman 2811c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 2821c6a0718SPierre Ossman { 2837659150cSPierre Ossman unsigned long flags; 2847659150cSPierre Ossman size_t blksize, len, chunk; 2857659150cSPierre Ossman u32 scratch; 2867659150cSPierre Ossman u8 *buf; 2871c6a0718SPierre Ossman 2881c6a0718SPierre Ossman DBG("PIO writing\n"); 2891c6a0718SPierre Ossman 2901c6a0718SPierre Ossman blksize = host->data->blksz; 2917659150cSPierre Ossman chunk = 0; 2927659150cSPierre Ossman scratch = 0; 2931c6a0718SPierre Ossman 2947659150cSPierre Ossman local_irq_save(flags); 2951c6a0718SPierre Ossman 2961c6a0718SPierre Ossman while (blksize) { 2977659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 2987659150cSPierre Ossman BUG(); 2991c6a0718SPierre Ossman 3007659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 3011c6a0718SPierre Ossman 3027659150cSPierre Ossman blksize -= len; 3037659150cSPierre Ossman host->sg_miter.consumed = len; 3047659150cSPierre Ossman 3057659150cSPierre Ossman buf = host->sg_miter.addr; 3067659150cSPierre Ossman 3077659150cSPierre Ossman while (len) { 3087659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 3097659150cSPierre Ossman 3107659150cSPierre Ossman buf++; 3117659150cSPierre Ossman chunk++; 3127659150cSPierre Ossman len--; 3137659150cSPierre Ossman 3147659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 3154e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 3167659150cSPierre Ossman chunk = 0; 3177659150cSPierre Ossman scratch = 0; 3187659150cSPierre Ossman } 3197659150cSPierre Ossman } 3201c6a0718SPierre Ossman } 3211c6a0718SPierre Ossman 3227659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 3231c6a0718SPierre Ossman 3247659150cSPierre Ossman local_irq_restore(flags); 3251c6a0718SPierre Ossman } 3261c6a0718SPierre Ossman 3271c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 3281c6a0718SPierre Ossman { 3291c6a0718SPierre Ossman u32 mask; 3301c6a0718SPierre Ossman 3311c6a0718SPierre Ossman BUG_ON(!host->data); 3321c6a0718SPierre Ossman 3337659150cSPierre Ossman if (host->blocks == 0) 3341c6a0718SPierre Ossman return; 3351c6a0718SPierre Ossman 3361c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 3371c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 3381c6a0718SPierre Ossman else 3391c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 3401c6a0718SPierre Ossman 3414a3cba32SPierre Ossman /* 3424a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 3434a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 3444a3cba32SPierre Ossman * we can ignore the bits. 3454a3cba32SPierre Ossman */ 3464a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 3474a3cba32SPierre Ossman (host->data->blocks == 1)) 3484a3cba32SPierre Ossman mask = ~0; 3494a3cba32SPierre Ossman 3504e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 3513e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 3523e3bf207SAnton Vorontsov udelay(100); 3533e3bf207SAnton Vorontsov 3541c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 3551c6a0718SPierre Ossman sdhci_read_block_pio(host); 3561c6a0718SPierre Ossman else 3571c6a0718SPierre Ossman sdhci_write_block_pio(host); 3581c6a0718SPierre Ossman 3597659150cSPierre Ossman host->blocks--; 3607659150cSPierre Ossman if (host->blocks == 0) 3611c6a0718SPierre Ossman break; 3621c6a0718SPierre Ossman } 3631c6a0718SPierre Ossman 3641c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 3651c6a0718SPierre Ossman } 3661c6a0718SPierre Ossman 3672134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3682134a922SPierre Ossman { 3692134a922SPierre Ossman local_irq_save(*flags); 3702134a922SPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 3712134a922SPierre Ossman } 3722134a922SPierre Ossman 3732134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 3742134a922SPierre Ossman { 3752134a922SPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 3762134a922SPierre Ossman local_irq_restore(*flags); 3772134a922SPierre Ossman } 3782134a922SPierre Ossman 3798f1934ceSPierre Ossman static int sdhci_adma_table_pre(struct sdhci_host *host, 3802134a922SPierre Ossman struct mmc_data *data) 3812134a922SPierre Ossman { 3822134a922SPierre Ossman int direction; 3832134a922SPierre Ossman 3842134a922SPierre Ossman u8 *desc; 3852134a922SPierre Ossman u8 *align; 3862134a922SPierre Ossman dma_addr_t addr; 3872134a922SPierre Ossman dma_addr_t align_addr; 3882134a922SPierre Ossman int len, offset; 3892134a922SPierre Ossman 3902134a922SPierre Ossman struct scatterlist *sg; 3912134a922SPierre Ossman int i; 3922134a922SPierre Ossman char *buffer; 3932134a922SPierre Ossman unsigned long flags; 3942134a922SPierre Ossman 3952134a922SPierre Ossman /* 3962134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 3972134a922SPierre Ossman * We currently guess that it is LE. 3982134a922SPierre Ossman */ 3992134a922SPierre Ossman 4002134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 4012134a922SPierre Ossman direction = DMA_FROM_DEVICE; 4022134a922SPierre Ossman else 4032134a922SPierre Ossman direction = DMA_TO_DEVICE; 4042134a922SPierre Ossman 4052134a922SPierre Ossman /* 4062134a922SPierre Ossman * The ADMA descriptor table is mapped further down as we 4072134a922SPierre Ossman * need to fill it with data first. 4082134a922SPierre Ossman */ 4092134a922SPierre Ossman 4102134a922SPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 4112134a922SPierre Ossman host->align_buffer, 128 * 4, direction); 4128d8bb39bSFUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4138f1934ceSPierre Ossman goto fail; 4142134a922SPierre Ossman BUG_ON(host->align_addr & 0x3); 4152134a922SPierre Ossman 4162134a922SPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 4172134a922SPierre Ossman data->sg, data->sg_len, direction); 4188f1934ceSPierre Ossman if (host->sg_count == 0) 4198f1934ceSPierre Ossman goto unmap_align; 4202134a922SPierre Ossman 4212134a922SPierre Ossman desc = host->adma_desc; 4222134a922SPierre Ossman align = host->align_buffer; 4232134a922SPierre Ossman 4242134a922SPierre Ossman align_addr = host->align_addr; 4252134a922SPierre Ossman 4262134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4272134a922SPierre Ossman addr = sg_dma_address(sg); 4282134a922SPierre Ossman len = sg_dma_len(sg); 4292134a922SPierre Ossman 4302134a922SPierre Ossman /* 4312134a922SPierre Ossman * The SDHCI specification states that ADMA 4322134a922SPierre Ossman * addresses must be 32-bit aligned. If they 4332134a922SPierre Ossman * aren't, then we use a bounce buffer for 4342134a922SPierre Ossman * the (up to three) bytes that screw up the 4352134a922SPierre Ossman * alignment. 4362134a922SPierre Ossman */ 4372134a922SPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 4382134a922SPierre Ossman if (offset) { 4392134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4402134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 4416cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 4422134a922SPierre Ossman memcpy(align, buffer, offset); 4432134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 4442134a922SPierre Ossman } 4452134a922SPierre Ossman 4462134a922SPierre Ossman desc[7] = (align_addr >> 24) & 0xff; 4472134a922SPierre Ossman desc[6] = (align_addr >> 16) & 0xff; 4482134a922SPierre Ossman desc[5] = (align_addr >> 8) & 0xff; 4492134a922SPierre Ossman desc[4] = (align_addr >> 0) & 0xff; 4502134a922SPierre Ossman 4512134a922SPierre Ossman BUG_ON(offset > 65536); 4522134a922SPierre Ossman 4532134a922SPierre Ossman desc[3] = (offset >> 8) & 0xff; 4542134a922SPierre Ossman desc[2] = (offset >> 0) & 0xff; 4552134a922SPierre Ossman 4562134a922SPierre Ossman desc[1] = 0x00; 4572134a922SPierre Ossman desc[0] = 0x21; /* tran, valid */ 4582134a922SPierre Ossman 4592134a922SPierre Ossman align += 4; 4602134a922SPierre Ossman align_addr += 4; 4612134a922SPierre Ossman 4622134a922SPierre Ossman desc += 8; 4632134a922SPierre Ossman 4642134a922SPierre Ossman addr += offset; 4652134a922SPierre Ossman len -= offset; 4662134a922SPierre Ossman } 4672134a922SPierre Ossman 4682134a922SPierre Ossman desc[7] = (addr >> 24) & 0xff; 4692134a922SPierre Ossman desc[6] = (addr >> 16) & 0xff; 4702134a922SPierre Ossman desc[5] = (addr >> 8) & 0xff; 4712134a922SPierre Ossman desc[4] = (addr >> 0) & 0xff; 4722134a922SPierre Ossman 4732134a922SPierre Ossman BUG_ON(len > 65536); 4742134a922SPierre Ossman 4752134a922SPierre Ossman desc[3] = (len >> 8) & 0xff; 4762134a922SPierre Ossman desc[2] = (len >> 0) & 0xff; 4772134a922SPierre Ossman 4782134a922SPierre Ossman desc[1] = 0x00; 4792134a922SPierre Ossman desc[0] = 0x21; /* tran, valid */ 4802134a922SPierre Ossman 4812134a922SPierre Ossman desc += 8; 4822134a922SPierre Ossman 4832134a922SPierre Ossman /* 4842134a922SPierre Ossman * If this triggers then we have a calculation bug 4852134a922SPierre Ossman * somewhere. :/ 4862134a922SPierre Ossman */ 4872134a922SPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 4882134a922SPierre Ossman } 4892134a922SPierre Ossman 4902134a922SPierre Ossman /* 4912134a922SPierre Ossman * Add a terminating entry. 4922134a922SPierre Ossman */ 4932134a922SPierre Ossman desc[7] = 0; 4942134a922SPierre Ossman desc[6] = 0; 4952134a922SPierre Ossman desc[5] = 0; 4962134a922SPierre Ossman desc[4] = 0; 4972134a922SPierre Ossman 4982134a922SPierre Ossman desc[3] = 0; 4992134a922SPierre Ossman desc[2] = 0; 5002134a922SPierre Ossman 5012134a922SPierre Ossman desc[1] = 0x00; 5022134a922SPierre Ossman desc[0] = 0x03; /* nop, end, valid */ 5032134a922SPierre Ossman 5042134a922SPierre Ossman /* 5052134a922SPierre Ossman * Resync align buffer as we might have changed it. 5062134a922SPierre Ossman */ 5072134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5082134a922SPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 5092134a922SPierre Ossman host->align_addr, 128 * 4, direction); 5102134a922SPierre Ossman } 5112134a922SPierre Ossman 5122134a922SPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 5132134a922SPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 514980167b7SPierre Ossman if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) 5158f1934ceSPierre Ossman goto unmap_entries; 5162134a922SPierre Ossman BUG_ON(host->adma_addr & 0x3); 5178f1934ceSPierre Ossman 5188f1934ceSPierre Ossman return 0; 5198f1934ceSPierre Ossman 5208f1934ceSPierre Ossman unmap_entries: 5218f1934ceSPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5228f1934ceSPierre Ossman data->sg_len, direction); 5238f1934ceSPierre Ossman unmap_align: 5248f1934ceSPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5258f1934ceSPierre Ossman 128 * 4, direction); 5268f1934ceSPierre Ossman fail: 5278f1934ceSPierre Ossman return -EINVAL; 5282134a922SPierre Ossman } 5292134a922SPierre Ossman 5302134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 5312134a922SPierre Ossman struct mmc_data *data) 5322134a922SPierre Ossman { 5332134a922SPierre Ossman int direction; 5342134a922SPierre Ossman 5352134a922SPierre Ossman struct scatterlist *sg; 5362134a922SPierre Ossman int i, size; 5372134a922SPierre Ossman u8 *align; 5382134a922SPierre Ossman char *buffer; 5392134a922SPierre Ossman unsigned long flags; 5402134a922SPierre Ossman 5412134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 5422134a922SPierre Ossman direction = DMA_FROM_DEVICE; 5432134a922SPierre Ossman else 5442134a922SPierre Ossman direction = DMA_TO_DEVICE; 5452134a922SPierre Ossman 5462134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 5472134a922SPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 5482134a922SPierre Ossman 5492134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5502134a922SPierre Ossman 128 * 4, direction); 5512134a922SPierre Ossman 5522134a922SPierre Ossman if (data->flags & MMC_DATA_READ) { 5532134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 5542134a922SPierre Ossman data->sg_len, direction); 5552134a922SPierre Ossman 5562134a922SPierre Ossman align = host->align_buffer; 5572134a922SPierre Ossman 5582134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5592134a922SPierre Ossman if (sg_dma_address(sg) & 0x3) { 5602134a922SPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 5612134a922SPierre Ossman 5622134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5636cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5642134a922SPierre Ossman memcpy(buffer, align, size); 5652134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5662134a922SPierre Ossman 5672134a922SPierre Ossman align += 4; 5682134a922SPierre Ossman } 5692134a922SPierre Ossman } 5702134a922SPierre Ossman } 5712134a922SPierre Ossman 5722134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5732134a922SPierre Ossman data->sg_len, direction); 5742134a922SPierre Ossman } 5752134a922SPierre Ossman 576ee53ab5dSPierre Ossman static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) 5771c6a0718SPierre Ossman { 5781c6a0718SPierre Ossman u8 count; 5791c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 5801c6a0718SPierre Ossman 581ee53ab5dSPierre Ossman /* 582ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 583ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 584ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 585ee53ab5dSPierre Ossman * timeout value. 586ee53ab5dSPierre Ossman */ 587ee53ab5dSPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)) 588ee53ab5dSPierre Ossman return 0xE; 589e538fbe8SPierre Ossman 5901c6a0718SPierre Ossman /* timeout in us */ 5911c6a0718SPierre Ossman target_timeout = data->timeout_ns / 1000 + 5921c6a0718SPierre Ossman data->timeout_clks / host->clock; 5931c6a0718SPierre Ossman 5941c6a0718SPierre Ossman /* 5951c6a0718SPierre Ossman * Figure out needed cycles. 5961c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 5971c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 5981c6a0718SPierre Ossman * minimum resolution of 6 bits: 5991c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 6001c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 6011c6a0718SPierre Ossman * => 6021c6a0718SPierre Ossman * (1) / (2) > 2^6 6031c6a0718SPierre Ossman */ 6041c6a0718SPierre Ossman count = 0; 6051c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 6061c6a0718SPierre Ossman while (current_timeout < target_timeout) { 6071c6a0718SPierre Ossman count++; 6081c6a0718SPierre Ossman current_timeout <<= 1; 6091c6a0718SPierre Ossman if (count >= 0xF) 6101c6a0718SPierre Ossman break; 6111c6a0718SPierre Ossman } 6121c6a0718SPierre Ossman 6131c6a0718SPierre Ossman if (count >= 0xF) { 6141c6a0718SPierre Ossman printk(KERN_WARNING "%s: Too large timeout requested!\n", 6151c6a0718SPierre Ossman mmc_hostname(host->mmc)); 6161c6a0718SPierre Ossman count = 0xE; 6171c6a0718SPierre Ossman } 6181c6a0718SPierre Ossman 619ee53ab5dSPierre Ossman return count; 620ee53ab5dSPierre Ossman } 621ee53ab5dSPierre Ossman 6226aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 6236aa943abSAnton Vorontsov { 6246aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 6256aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 6266aa943abSAnton Vorontsov 6276aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 6286aa943abSAnton Vorontsov sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 6296aa943abSAnton Vorontsov else 6306aa943abSAnton Vorontsov sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); 6316aa943abSAnton Vorontsov } 6326aa943abSAnton Vorontsov 633ee53ab5dSPierre Ossman static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 634ee53ab5dSPierre Ossman { 635ee53ab5dSPierre Ossman u8 count; 6362134a922SPierre Ossman u8 ctrl; 6378f1934ceSPierre Ossman int ret; 638ee53ab5dSPierre Ossman 639ee53ab5dSPierre Ossman WARN_ON(host->data); 640ee53ab5dSPierre Ossman 641ee53ab5dSPierre Ossman if (data == NULL) 642ee53ab5dSPierre Ossman return; 643ee53ab5dSPierre Ossman 644ee53ab5dSPierre Ossman /* Sanity checks */ 645ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 646ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 647ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 648ee53ab5dSPierre Ossman 649ee53ab5dSPierre Ossman host->data = data; 650ee53ab5dSPierre Ossman host->data_early = 0; 651ee53ab5dSPierre Ossman 652ee53ab5dSPierre Ossman count = sdhci_calc_timeout(host, data); 6534e4141a5SAnton Vorontsov sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 6541c6a0718SPierre Ossman 655c9fddbc4SPierre Ossman if (host->flags & SDHCI_USE_DMA) 656c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 657c9fddbc4SPierre Ossman 6582134a922SPierre Ossman /* 6592134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 6602134a922SPierre Ossman * scatterlist. 6612134a922SPierre Ossman */ 6622134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6632134a922SPierre Ossman int broken, i; 6642134a922SPierre Ossman struct scatterlist *sg; 6652134a922SPierre Ossman 6662134a922SPierre Ossman broken = 0; 6672134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6682134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 6692134a922SPierre Ossman broken = 1; 6702134a922SPierre Ossman } else { 6712134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 6722134a922SPierre Ossman broken = 1; 6732134a922SPierre Ossman } 6742134a922SPierre Ossman 6752134a922SPierre Ossman if (unlikely(broken)) { 6762134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6772134a922SPierre Ossman if (sg->length & 0x3) { 6782134a922SPierre Ossman DBG("Reverting to PIO because of " 6792134a922SPierre Ossman "transfer size (%d)\n", 6802134a922SPierre Ossman sg->length); 681c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6822134a922SPierre Ossman break; 6832134a922SPierre Ossman } 6842134a922SPierre Ossman } 6852134a922SPierre Ossman } 686c9fddbc4SPierre Ossman } 687c9fddbc4SPierre Ossman 688c9fddbc4SPierre Ossman /* 689c9fddbc4SPierre Ossman * The assumption here being that alignment is the same after 690c9fddbc4SPierre Ossman * translation to device address space. 691c9fddbc4SPierre Ossman */ 6922134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6932134a922SPierre Ossman int broken, i; 6942134a922SPierre Ossman struct scatterlist *sg; 6952134a922SPierre Ossman 6962134a922SPierre Ossman broken = 0; 6972134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6982134a922SPierre Ossman /* 6992134a922SPierre Ossman * As we use 3 byte chunks to work around 7002134a922SPierre Ossman * alignment problems, we need to check this 7012134a922SPierre Ossman * quirk. 7022134a922SPierre Ossman */ 7032134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7042134a922SPierre Ossman broken = 1; 7052134a922SPierre Ossman } else { 7062134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 7072134a922SPierre Ossman broken = 1; 7082134a922SPierre Ossman } 7092134a922SPierre Ossman 7102134a922SPierre Ossman if (unlikely(broken)) { 7112134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7122134a922SPierre Ossman if (sg->offset & 0x3) { 7132134a922SPierre Ossman DBG("Reverting to PIO because of " 7142134a922SPierre Ossman "bad alignment\n"); 715c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7162134a922SPierre Ossman break; 7172134a922SPierre Ossman } 7182134a922SPierre Ossman } 7192134a922SPierre Ossman } 7202134a922SPierre Ossman } 7212134a922SPierre Ossman 7228f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7238f1934ceSPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7248f1934ceSPierre Ossman ret = sdhci_adma_table_pre(host, data); 7258f1934ceSPierre Ossman if (ret) { 7268f1934ceSPierre Ossman /* 7278f1934ceSPierre Ossman * This only happens when someone fed 7288f1934ceSPierre Ossman * us an invalid request. 7298f1934ceSPierre Ossman */ 7308f1934ceSPierre Ossman WARN_ON(1); 731ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7328f1934ceSPierre Ossman } else { 7334e4141a5SAnton Vorontsov sdhci_writel(host, host->adma_addr, 7344e4141a5SAnton Vorontsov SDHCI_ADMA_ADDRESS); 7358f1934ceSPierre Ossman } 7368f1934ceSPierre Ossman } else { 737c8b3e02eSTomas Winkler int sg_cnt; 7388f1934ceSPierre Ossman 739c8b3e02eSTomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 7408f1934ceSPierre Ossman data->sg, data->sg_len, 7418f1934ceSPierre Ossman (data->flags & MMC_DATA_READ) ? 7428f1934ceSPierre Ossman DMA_FROM_DEVICE : 7438f1934ceSPierre Ossman DMA_TO_DEVICE); 744c8b3e02eSTomas Winkler if (sg_cnt == 0) { 7458f1934ceSPierre Ossman /* 7468f1934ceSPierre Ossman * This only happens when someone fed 7478f1934ceSPierre Ossman * us an invalid request. 7488f1934ceSPierre Ossman */ 7498f1934ceSPierre Ossman WARN_ON(1); 750ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7518f1934ceSPierre Ossman } else { 752719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 7534e4141a5SAnton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 7544e4141a5SAnton Vorontsov SDHCI_DMA_ADDRESS); 7558f1934ceSPierre Ossman } 7568f1934ceSPierre Ossman } 7578f1934ceSPierre Ossman } 7588f1934ceSPierre Ossman 7592134a922SPierre Ossman /* 7602134a922SPierre Ossman * Always adjust the DMA selection as some controllers 7612134a922SPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 7622134a922SPierre Ossman * is ADMA. 7632134a922SPierre Ossman */ 7642134a922SPierre Ossman if (host->version >= SDHCI_SPEC_200) { 7654e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 7662134a922SPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 7672134a922SPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 7682134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) 7692134a922SPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 7702134a922SPierre Ossman else 7712134a922SPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 7724e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 773c9fddbc4SPierre Ossman } 774c9fddbc4SPierre Ossman 7758f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 7767659150cSPierre Ossman sg_miter_start(&host->sg_miter, 7777659150cSPierre Ossman data->sg, data->sg_len, SG_MITER_ATOMIC); 7787659150cSPierre Ossman host->blocks = data->blocks; 7791c6a0718SPierre Ossman } 7801c6a0718SPierre Ossman 7816aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 7826aa943abSAnton Vorontsov 7831c6a0718SPierre Ossman /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 7844e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE); 7854e4141a5SAnton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 7861c6a0718SPierre Ossman } 7871c6a0718SPierre Ossman 7881c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 7891c6a0718SPierre Ossman struct mmc_data *data) 7901c6a0718SPierre Ossman { 7911c6a0718SPierre Ossman u16 mode; 7921c6a0718SPierre Ossman 7931c6a0718SPierre Ossman if (data == NULL) 7941c6a0718SPierre Ossman return; 7951c6a0718SPierre Ossman 796e538fbe8SPierre Ossman WARN_ON(!host->data); 797e538fbe8SPierre Ossman 7981c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 7991c6a0718SPierre Ossman if (data->blocks > 1) 8001c6a0718SPierre Ossman mode |= SDHCI_TRNS_MULTI; 8011c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 8021c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 803c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 8041c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 8051c6a0718SPierre Ossman 8064e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 8071c6a0718SPierre Ossman } 8081c6a0718SPierre Ossman 8091c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *host) 8101c6a0718SPierre Ossman { 8111c6a0718SPierre Ossman struct mmc_data *data; 8121c6a0718SPierre Ossman 8131c6a0718SPierre Ossman BUG_ON(!host->data); 8141c6a0718SPierre Ossman 8151c6a0718SPierre Ossman data = host->data; 8161c6a0718SPierre Ossman host->data = NULL; 8171c6a0718SPierre Ossman 818c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 8192134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 8202134a922SPierre Ossman sdhci_adma_table_post(host, data); 8212134a922SPierre Ossman else { 8222134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 8232134a922SPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 824b8c86fc5SPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 8251c6a0718SPierre Ossman } 8262134a922SPierre Ossman } 8271c6a0718SPierre Ossman 8281c6a0718SPierre Ossman /* 829c9b74c5bSPierre Ossman * The specification states that the block count register must 830c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 831c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 832c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 833c9b74c5bSPierre Ossman * in the event of an error. 8341c6a0718SPierre Ossman */ 835c9b74c5bSPierre Ossman if (data->error) 836c9b74c5bSPierre Ossman data->bytes_xfered = 0; 8371c6a0718SPierre Ossman else 838c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 8391c6a0718SPierre Ossman 8401c6a0718SPierre Ossman if (data->stop) { 8411c6a0718SPierre Ossman /* 8421c6a0718SPierre Ossman * The controller needs a reset of internal state machines 8431c6a0718SPierre Ossman * upon error conditions. 8441c6a0718SPierre Ossman */ 84517b0429dSPierre Ossman if (data->error) { 8461c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 8471c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 8481c6a0718SPierre Ossman } 8491c6a0718SPierre Ossman 8501c6a0718SPierre Ossman sdhci_send_command(host, data->stop); 8511c6a0718SPierre Ossman } else 8521c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8531c6a0718SPierre Ossman } 8541c6a0718SPierre Ossman 8551c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 8561c6a0718SPierre Ossman { 8571c6a0718SPierre Ossman int flags; 8581c6a0718SPierre Ossman u32 mask; 8591c6a0718SPierre Ossman unsigned long timeout; 8601c6a0718SPierre Ossman 8611c6a0718SPierre Ossman WARN_ON(host->cmd); 8621c6a0718SPierre Ossman 8631c6a0718SPierre Ossman /* Wait max 10 ms */ 8641c6a0718SPierre Ossman timeout = 10; 8651c6a0718SPierre Ossman 8661c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 8671c6a0718SPierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 8681c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 8691c6a0718SPierre Ossman 8701c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 8711c6a0718SPierre Ossman though they might use busy signaling */ 8721c6a0718SPierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 8731c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 8741c6a0718SPierre Ossman 8754e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 8761c6a0718SPierre Ossman if (timeout == 0) { 8771c6a0718SPierre Ossman printk(KERN_ERR "%s: Controller never released " 8781c6a0718SPierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 8791c6a0718SPierre Ossman sdhci_dumpregs(host); 88017b0429dSPierre Ossman cmd->error = -EIO; 8811c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8821c6a0718SPierre Ossman return; 8831c6a0718SPierre Ossman } 8841c6a0718SPierre Ossman timeout--; 8851c6a0718SPierre Ossman mdelay(1); 8861c6a0718SPierre Ossman } 8871c6a0718SPierre Ossman 8881c6a0718SPierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 8891c6a0718SPierre Ossman 8901c6a0718SPierre Ossman host->cmd = cmd; 8911c6a0718SPierre Ossman 8921c6a0718SPierre Ossman sdhci_prepare_data(host, cmd->data); 8931c6a0718SPierre Ossman 8944e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 8951c6a0718SPierre Ossman 8961c6a0718SPierre Ossman sdhci_set_transfer_mode(host, cmd->data); 8971c6a0718SPierre Ossman 8981c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 8991c6a0718SPierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 9001c6a0718SPierre Ossman mmc_hostname(host->mmc)); 90117b0429dSPierre Ossman cmd->error = -EINVAL; 9021c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 9031c6a0718SPierre Ossman return; 9041c6a0718SPierre Ossman } 9051c6a0718SPierre Ossman 9061c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 9071c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 9081c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 9091c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 9101c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 9111c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 9121c6a0718SPierre Ossman else 9131c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 9141c6a0718SPierre Ossman 9151c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 9161c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 9171c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 9181c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 9191c6a0718SPierre Ossman if (cmd->data) 9201c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 9211c6a0718SPierre Ossman 9224e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 9231c6a0718SPierre Ossman } 9241c6a0718SPierre Ossman 9251c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 9261c6a0718SPierre Ossman { 9271c6a0718SPierre Ossman int i; 9281c6a0718SPierre Ossman 9291c6a0718SPierre Ossman BUG_ON(host->cmd == NULL); 9301c6a0718SPierre Ossman 9311c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 9321c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_136) { 9331c6a0718SPierre Ossman /* CRC is stripped so we need to do some shifting. */ 9341c6a0718SPierre Ossman for (i = 0;i < 4;i++) { 9354e4141a5SAnton Vorontsov host->cmd->resp[i] = sdhci_readl(host, 9361c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 9371c6a0718SPierre Ossman if (i != 3) 9381c6a0718SPierre Ossman host->cmd->resp[i] |= 9394e4141a5SAnton Vorontsov sdhci_readb(host, 9401c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 9411c6a0718SPierre Ossman } 9421c6a0718SPierre Ossman } else { 9434e4141a5SAnton Vorontsov host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 9441c6a0718SPierre Ossman } 9451c6a0718SPierre Ossman } 9461c6a0718SPierre Ossman 94717b0429dSPierre Ossman host->cmd->error = 0; 9481c6a0718SPierre Ossman 949e538fbe8SPierre Ossman if (host->data && host->data_early) 950e538fbe8SPierre Ossman sdhci_finish_data(host); 951e538fbe8SPierre Ossman 952e538fbe8SPierre Ossman if (!host->cmd->data) 9531c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 9541c6a0718SPierre Ossman 9551c6a0718SPierre Ossman host->cmd = NULL; 9561c6a0718SPierre Ossman } 9571c6a0718SPierre Ossman 9581c6a0718SPierre Ossman static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 9591c6a0718SPierre Ossman { 9601c6a0718SPierre Ossman int div; 9611c6a0718SPierre Ossman u16 clk; 9621c6a0718SPierre Ossman unsigned long timeout; 9631c6a0718SPierre Ossman 9641c6a0718SPierre Ossman if (clock == host->clock) 9651c6a0718SPierre Ossman return; 9661c6a0718SPierre Ossman 9678114634cSAnton Vorontsov if (host->ops->set_clock) { 9688114634cSAnton Vorontsov host->ops->set_clock(host, clock); 9698114634cSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) 9708114634cSAnton Vorontsov return; 9718114634cSAnton Vorontsov } 9728114634cSAnton Vorontsov 9734e4141a5SAnton Vorontsov sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 9741c6a0718SPierre Ossman 9751c6a0718SPierre Ossman if (clock == 0) 9761c6a0718SPierre Ossman goto out; 9771c6a0718SPierre Ossman 9781c6a0718SPierre Ossman for (div = 1;div < 256;div *= 2) { 9791c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 9801c6a0718SPierre Ossman break; 9811c6a0718SPierre Ossman } 9821c6a0718SPierre Ossman div >>= 1; 9831c6a0718SPierre Ossman 9841c6a0718SPierre Ossman clk = div << SDHCI_DIVIDER_SHIFT; 9851c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 9864e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 9871c6a0718SPierre Ossman 9881c6a0718SPierre Ossman /* Wait max 10 ms */ 9891c6a0718SPierre Ossman timeout = 10; 9904e4141a5SAnton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 9911c6a0718SPierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 9921c6a0718SPierre Ossman if (timeout == 0) { 9931c6a0718SPierre Ossman printk(KERN_ERR "%s: Internal clock never " 9941c6a0718SPierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 9951c6a0718SPierre Ossman sdhci_dumpregs(host); 9961c6a0718SPierre Ossman return; 9971c6a0718SPierre Ossman } 9981c6a0718SPierre Ossman timeout--; 9991c6a0718SPierre Ossman mdelay(1); 10001c6a0718SPierre Ossman } 10011c6a0718SPierre Ossman 10021c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 10034e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 10041c6a0718SPierre Ossman 10051c6a0718SPierre Ossman out: 10061c6a0718SPierre Ossman host->clock = clock; 10071c6a0718SPierre Ossman } 10081c6a0718SPierre Ossman 10091c6a0718SPierre Ossman static void sdhci_set_power(struct sdhci_host *host, unsigned short power) 10101c6a0718SPierre Ossman { 10111c6a0718SPierre Ossman u8 pwr; 10121c6a0718SPierre Ossman 1013ae628903SPierre Ossman if (power == (unsigned short)-1) 1014ae628903SPierre Ossman pwr = 0; 1015ae628903SPierre Ossman else { 1016ae628903SPierre Ossman switch (1 << power) { 1017ae628903SPierre Ossman case MMC_VDD_165_195: 1018ae628903SPierre Ossman pwr = SDHCI_POWER_180; 1019ae628903SPierre Ossman break; 1020ae628903SPierre Ossman case MMC_VDD_29_30: 1021ae628903SPierre Ossman case MMC_VDD_30_31: 1022ae628903SPierre Ossman pwr = SDHCI_POWER_300; 1023ae628903SPierre Ossman break; 1024ae628903SPierre Ossman case MMC_VDD_32_33: 1025ae628903SPierre Ossman case MMC_VDD_33_34: 1026ae628903SPierre Ossman pwr = SDHCI_POWER_330; 1027ae628903SPierre Ossman break; 1028ae628903SPierre Ossman default: 1029ae628903SPierre Ossman BUG(); 1030ae628903SPierre Ossman } 1031ae628903SPierre Ossman } 1032ae628903SPierre Ossman 1033ae628903SPierre Ossman if (host->pwr == pwr) 10341c6a0718SPierre Ossman return; 10351c6a0718SPierre Ossman 1036ae628903SPierre Ossman host->pwr = pwr; 1037ae628903SPierre Ossman 1038ae628903SPierre Ossman if (pwr == 0) { 10394e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1040ae628903SPierre Ossman return; 10411c6a0718SPierre Ossman } 10421c6a0718SPierre Ossman 10431c6a0718SPierre Ossman /* 10441c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 10451c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 10461c6a0718SPierre Ossman */ 1047b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 10484e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 10491c6a0718SPierre Ossman 1050e08c1694SAndres Salomon /* 1051c71f6512SAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 1052e08c1694SAndres Salomon * and set turn on power at the same time, so set the voltage first. 1053e08c1694SAndres Salomon */ 1054b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) 10554e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 10561c6a0718SPierre Ossman 1057ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 1058ae628903SPierre Ossman 1059ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 10601c6a0718SPierre Ossman } 10611c6a0718SPierre Ossman 10621c6a0718SPierre Ossman /*****************************************************************************\ 10631c6a0718SPierre Ossman * * 10641c6a0718SPierre Ossman * MMC callbacks * 10651c6a0718SPierre Ossman * * 10661c6a0718SPierre Ossman \*****************************************************************************/ 10671c6a0718SPierre Ossman 10681c6a0718SPierre Ossman static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 10691c6a0718SPierre Ossman { 10701c6a0718SPierre Ossman struct sdhci_host *host; 107168d1fb7eSAnton Vorontsov bool present; 10721c6a0718SPierre Ossman unsigned long flags; 10731c6a0718SPierre Ossman 10741c6a0718SPierre Ossman host = mmc_priv(mmc); 10751c6a0718SPierre Ossman 10761c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 10771c6a0718SPierre Ossman 10781c6a0718SPierre Ossman WARN_ON(host->mrq != NULL); 10791c6a0718SPierre Ossman 1080f9134319SPierre Ossman #ifndef SDHCI_USE_LEDS_CLASS 10811c6a0718SPierre Ossman sdhci_activate_led(host); 10822f730fecSPierre Ossman #endif 10831c6a0718SPierre Ossman 10841c6a0718SPierre Ossman host->mrq = mrq; 10851c6a0718SPierre Ossman 108668d1fb7eSAnton Vorontsov /* If polling, assume that the card is always present. */ 108768d1fb7eSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 108868d1fb7eSAnton Vorontsov present = true; 108968d1fb7eSAnton Vorontsov else 109068d1fb7eSAnton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 109168d1fb7eSAnton Vorontsov SDHCI_CARD_PRESENT; 109268d1fb7eSAnton Vorontsov 109368d1fb7eSAnton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 109417b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 10951c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 10961c6a0718SPierre Ossman } else 10971c6a0718SPierre Ossman sdhci_send_command(host, mrq->cmd); 10981c6a0718SPierre Ossman 10991c6a0718SPierre Ossman mmiowb(); 11001c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 11011c6a0718SPierre Ossman } 11021c6a0718SPierre Ossman 11031c6a0718SPierre Ossman static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 11041c6a0718SPierre Ossman { 11051c6a0718SPierre Ossman struct sdhci_host *host; 11061c6a0718SPierre Ossman unsigned long flags; 11071c6a0718SPierre Ossman u8 ctrl; 11081c6a0718SPierre Ossman 11091c6a0718SPierre Ossman host = mmc_priv(mmc); 11101c6a0718SPierre Ossman 11111c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11121c6a0718SPierre Ossman 11131e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11141e72859eSPierre Ossman goto out; 11151e72859eSPierre Ossman 11161c6a0718SPierre Ossman /* 11171c6a0718SPierre Ossman * Reset the chip on each power off. 11181c6a0718SPierre Ossman * Should clear out any weird states. 11191c6a0718SPierre Ossman */ 11201c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 11214e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 11227260cf5eSAnton Vorontsov sdhci_reinit(host); 11231c6a0718SPierre Ossman } 11241c6a0718SPierre Ossman 11251c6a0718SPierre Ossman sdhci_set_clock(host, ios->clock); 11261c6a0718SPierre Ossman 11271c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) 11281c6a0718SPierre Ossman sdhci_set_power(host, -1); 11291c6a0718SPierre Ossman else 11301c6a0718SPierre Ossman sdhci_set_power(host, ios->vdd); 11311c6a0718SPierre Ossman 11324e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 11331c6a0718SPierre Ossman 11341c6a0718SPierre Ossman if (ios->bus_width == MMC_BUS_WIDTH_4) 11351c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_4BITBUS; 11361c6a0718SPierre Ossman else 11371c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_4BITBUS; 11381c6a0718SPierre Ossman 11391c6a0718SPierre Ossman if (ios->timing == MMC_TIMING_SD_HS) 11401c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 11411c6a0718SPierre Ossman else 11421c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 11431c6a0718SPierre Ossman 11444e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 11451c6a0718SPierre Ossman 1146b8352260SLeandro Dorileo /* 1147b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1148b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1149b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 1150b8352260SLeandro Dorileo */ 1151b8c86fc5SPierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1152b8352260SLeandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1153b8352260SLeandro Dorileo 11541e72859eSPierre Ossman out: 11551c6a0718SPierre Ossman mmiowb(); 11561c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 11571c6a0718SPierre Ossman } 11581c6a0718SPierre Ossman 11591c6a0718SPierre Ossman static int sdhci_get_ro(struct mmc_host *mmc) 11601c6a0718SPierre Ossman { 11611c6a0718SPierre Ossman struct sdhci_host *host; 11621c6a0718SPierre Ossman unsigned long flags; 11631c6a0718SPierre Ossman int present; 11641c6a0718SPierre Ossman 11651c6a0718SPierre Ossman host = mmc_priv(mmc); 11661c6a0718SPierre Ossman 11671c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11681c6a0718SPierre Ossman 11691e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11701e72859eSPierre Ossman present = 0; 11711e72859eSPierre Ossman else 11724e4141a5SAnton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE); 11731c6a0718SPierre Ossman 11741c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 11751c6a0718SPierre Ossman 1176c5075a10SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT) 1177c5075a10SAnton Vorontsov return !!(present & SDHCI_WRITE_PROTECT); 11781c6a0718SPierre Ossman return !(present & SDHCI_WRITE_PROTECT); 11791c6a0718SPierre Ossman } 11801c6a0718SPierre Ossman 1181f75979b7SPierre Ossman static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1182f75979b7SPierre Ossman { 1183f75979b7SPierre Ossman struct sdhci_host *host; 1184f75979b7SPierre Ossman unsigned long flags; 1185f75979b7SPierre Ossman 1186f75979b7SPierre Ossman host = mmc_priv(mmc); 1187f75979b7SPierre Ossman 1188f75979b7SPierre Ossman spin_lock_irqsave(&host->lock, flags); 1189f75979b7SPierre Ossman 11901e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11911e72859eSPierre Ossman goto out; 11921e72859eSPierre Ossman 1193f75979b7SPierre Ossman if (enable) 11947260cf5eSAnton Vorontsov sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); 11957260cf5eSAnton Vorontsov else 11967260cf5eSAnton Vorontsov sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); 11971e72859eSPierre Ossman out: 1198f75979b7SPierre Ossman mmiowb(); 1199f75979b7SPierre Ossman 1200f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1201f75979b7SPierre Ossman } 1202f75979b7SPierre Ossman 12031c6a0718SPierre Ossman static const struct mmc_host_ops sdhci_ops = { 12041c6a0718SPierre Ossman .request = sdhci_request, 12051c6a0718SPierre Ossman .set_ios = sdhci_set_ios, 12061c6a0718SPierre Ossman .get_ro = sdhci_get_ro, 1207f75979b7SPierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 12081c6a0718SPierre Ossman }; 12091c6a0718SPierre Ossman 12101c6a0718SPierre Ossman /*****************************************************************************\ 12111c6a0718SPierre Ossman * * 12121c6a0718SPierre Ossman * Tasklets * 12131c6a0718SPierre Ossman * * 12141c6a0718SPierre Ossman \*****************************************************************************/ 12151c6a0718SPierre Ossman 12161c6a0718SPierre Ossman static void sdhci_tasklet_card(unsigned long param) 12171c6a0718SPierre Ossman { 12181c6a0718SPierre Ossman struct sdhci_host *host; 12191c6a0718SPierre Ossman unsigned long flags; 12201c6a0718SPierre Ossman 12211c6a0718SPierre Ossman host = (struct sdhci_host*)param; 12221c6a0718SPierre Ossman 12231c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 12241c6a0718SPierre Ossman 12254e4141a5SAnton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 12261c6a0718SPierre Ossman if (host->mrq) { 12271c6a0718SPierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 12281c6a0718SPierre Ossman mmc_hostname(host->mmc)); 12291c6a0718SPierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 12301c6a0718SPierre Ossman mmc_hostname(host->mmc)); 12311c6a0718SPierre Ossman 12321c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 12331c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 12341c6a0718SPierre Ossman 123517b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 12361c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 12371c6a0718SPierre Ossman } 12381c6a0718SPierre Ossman } 12391c6a0718SPierre Ossman 12401c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12411c6a0718SPierre Ossman 124204cf585dSPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 12431c6a0718SPierre Ossman } 12441c6a0718SPierre Ossman 12451c6a0718SPierre Ossman static void sdhci_tasklet_finish(unsigned long param) 12461c6a0718SPierre Ossman { 12471c6a0718SPierre Ossman struct sdhci_host *host; 12481c6a0718SPierre Ossman unsigned long flags; 12491c6a0718SPierre Ossman struct mmc_request *mrq; 12501c6a0718SPierre Ossman 12511c6a0718SPierre Ossman host = (struct sdhci_host*)param; 12521c6a0718SPierre Ossman 12531c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 12541c6a0718SPierre Ossman 12551c6a0718SPierre Ossman del_timer(&host->timer); 12561c6a0718SPierre Ossman 12571c6a0718SPierre Ossman mrq = host->mrq; 12581c6a0718SPierre Ossman 12591c6a0718SPierre Ossman /* 12601c6a0718SPierre Ossman * The controller needs a reset of internal state machines 12611c6a0718SPierre Ossman * upon error conditions. 12621c6a0718SPierre Ossman */ 12631e72859eSPierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 12641e72859eSPierre Ossman (mrq->cmd->error || 126517b0429dSPierre Ossman (mrq->data && (mrq->data->error || 126684c46a53SPierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 12671e72859eSPierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 12681c6a0718SPierre Ossman 12691c6a0718SPierre Ossman /* Some controllers need this kick or reset won't work here */ 1270b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 12711c6a0718SPierre Ossman unsigned int clock; 12721c6a0718SPierre Ossman 12731c6a0718SPierre Ossman /* This is to force an update */ 12741c6a0718SPierre Ossman clock = host->clock; 12751c6a0718SPierre Ossman host->clock = 0; 12761c6a0718SPierre Ossman sdhci_set_clock(host, clock); 12771c6a0718SPierre Ossman } 12781c6a0718SPierre Ossman 12791c6a0718SPierre Ossman /* Spec says we should do both at the same time, but Ricoh 12801c6a0718SPierre Ossman controllers do not like that. */ 12811c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 12821c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 12831c6a0718SPierre Ossman } 12841c6a0718SPierre Ossman 12851c6a0718SPierre Ossman host->mrq = NULL; 12861c6a0718SPierre Ossman host->cmd = NULL; 12871c6a0718SPierre Ossman host->data = NULL; 12881c6a0718SPierre Ossman 1289f9134319SPierre Ossman #ifndef SDHCI_USE_LEDS_CLASS 12901c6a0718SPierre Ossman sdhci_deactivate_led(host); 12912f730fecSPierre Ossman #endif 12921c6a0718SPierre Ossman 12931c6a0718SPierre Ossman mmiowb(); 12941c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12951c6a0718SPierre Ossman 12961c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 12971c6a0718SPierre Ossman } 12981c6a0718SPierre Ossman 12991c6a0718SPierre Ossman static void sdhci_timeout_timer(unsigned long data) 13001c6a0718SPierre Ossman { 13011c6a0718SPierre Ossman struct sdhci_host *host; 13021c6a0718SPierre Ossman unsigned long flags; 13031c6a0718SPierre Ossman 13041c6a0718SPierre Ossman host = (struct sdhci_host*)data; 13051c6a0718SPierre Ossman 13061c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 13071c6a0718SPierre Ossman 13081c6a0718SPierre Ossman if (host->mrq) { 13091c6a0718SPierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 13101c6a0718SPierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 13111c6a0718SPierre Ossman sdhci_dumpregs(host); 13121c6a0718SPierre Ossman 13131c6a0718SPierre Ossman if (host->data) { 131417b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 13151c6a0718SPierre Ossman sdhci_finish_data(host); 13161c6a0718SPierre Ossman } else { 13171c6a0718SPierre Ossman if (host->cmd) 131817b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 13191c6a0718SPierre Ossman else 132017b0429dSPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 13211c6a0718SPierre Ossman 13221c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 13231c6a0718SPierre Ossman } 13241c6a0718SPierre Ossman } 13251c6a0718SPierre Ossman 13261c6a0718SPierre Ossman mmiowb(); 13271c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 13281c6a0718SPierre Ossman } 13291c6a0718SPierre Ossman 13301c6a0718SPierre Ossman /*****************************************************************************\ 13311c6a0718SPierre Ossman * * 13321c6a0718SPierre Ossman * Interrupt handling * 13331c6a0718SPierre Ossman * * 13341c6a0718SPierre Ossman \*****************************************************************************/ 13351c6a0718SPierre Ossman 13361c6a0718SPierre Ossman static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 13371c6a0718SPierre Ossman { 13381c6a0718SPierre Ossman BUG_ON(intmask == 0); 13391c6a0718SPierre Ossman 13401c6a0718SPierre Ossman if (!host->cmd) { 1341b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1342b67ac3f3SPierre Ossman "though no command operation was in progress.\n", 1343b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 13441c6a0718SPierre Ossman sdhci_dumpregs(host); 13451c6a0718SPierre Ossman return; 13461c6a0718SPierre Ossman } 13471c6a0718SPierre Ossman 13481c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 134917b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 135017b0429dSPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 135117b0429dSPierre Ossman SDHCI_INT_INDEX)) 135217b0429dSPierre Ossman host->cmd->error = -EILSEQ; 13531c6a0718SPierre Ossman 1354e809517fSPierre Ossman if (host->cmd->error) { 13551c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 1356e809517fSPierre Ossman return; 1357e809517fSPierre Ossman } 1358e809517fSPierre Ossman 1359e809517fSPierre Ossman /* 1360e809517fSPierre Ossman * The host can send and interrupt when the busy state has 1361e809517fSPierre Ossman * ended, allowing us to wait without wasting CPU cycles. 1362e809517fSPierre Ossman * Unfortunately this is overloaded on the "data complete" 1363e809517fSPierre Ossman * interrupt, so we need to take some care when handling 1364e809517fSPierre Ossman * it. 1365e809517fSPierre Ossman * 1366e809517fSPierre Ossman * Note: The 1.0 specification is a bit ambiguous about this 1367e809517fSPierre Ossman * feature so there might be some problems with older 1368e809517fSPierre Ossman * controllers. 1369e809517fSPierre Ossman */ 1370e809517fSPierre Ossman if (host->cmd->flags & MMC_RSP_BUSY) { 1371e809517fSPierre Ossman if (host->cmd->data) 1372e809517fSPierre Ossman DBG("Cannot wait for busy signal when also " 1373e809517fSPierre Ossman "doing a data transfer"); 1374f945405cSBen Dooks else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 1375e809517fSPierre Ossman return; 1376f945405cSBen Dooks 1377f945405cSBen Dooks /* The controller does not support the end-of-busy IRQ, 1378f945405cSBen Dooks * fall through and take the SDHCI_INT_RESPONSE */ 1379e809517fSPierre Ossman } 1380e809517fSPierre Ossman 1381e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 138243b58b36SPierre Ossman sdhci_finish_command(host); 13831c6a0718SPierre Ossman } 13841c6a0718SPierre Ossman 13856882a8c0SBen Dooks #ifdef DEBUG 13866882a8c0SBen Dooks static void sdhci_show_adma_error(struct sdhci_host *host) 13876882a8c0SBen Dooks { 13886882a8c0SBen Dooks const char *name = mmc_hostname(host->mmc); 13896882a8c0SBen Dooks u8 *desc = host->adma_desc; 13906882a8c0SBen Dooks __le32 *dma; 13916882a8c0SBen Dooks __le16 *len; 13926882a8c0SBen Dooks u8 attr; 13936882a8c0SBen Dooks 13946882a8c0SBen Dooks sdhci_dumpregs(host); 13956882a8c0SBen Dooks 13966882a8c0SBen Dooks while (true) { 13976882a8c0SBen Dooks dma = (__le32 *)(desc + 4); 13986882a8c0SBen Dooks len = (__le16 *)(desc + 2); 13996882a8c0SBen Dooks attr = *desc; 14006882a8c0SBen Dooks 14016882a8c0SBen Dooks DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 14026882a8c0SBen Dooks name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); 14036882a8c0SBen Dooks 14046882a8c0SBen Dooks desc += 8; 14056882a8c0SBen Dooks 14066882a8c0SBen Dooks if (attr & 2) 14076882a8c0SBen Dooks break; 14086882a8c0SBen Dooks } 14096882a8c0SBen Dooks } 14106882a8c0SBen Dooks #else 14116882a8c0SBen Dooks static void sdhci_show_adma_error(struct sdhci_host *host) { } 14126882a8c0SBen Dooks #endif 14136882a8c0SBen Dooks 14141c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 14151c6a0718SPierre Ossman { 14161c6a0718SPierre Ossman BUG_ON(intmask == 0); 14171c6a0718SPierre Ossman 14181c6a0718SPierre Ossman if (!host->data) { 14191c6a0718SPierre Ossman /* 1420e809517fSPierre Ossman * The "data complete" interrupt is also used to 1421e809517fSPierre Ossman * indicate that a busy state has ended. See comment 1422e809517fSPierre Ossman * above in sdhci_cmd_irq(). 14231c6a0718SPierre Ossman */ 1424e809517fSPierre Ossman if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { 1425e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1426e809517fSPierre Ossman sdhci_finish_command(host); 14271c6a0718SPierre Ossman return; 1428e809517fSPierre Ossman } 1429e809517fSPierre Ossman } 14301c6a0718SPierre Ossman 1431b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 1432b67ac3f3SPierre Ossman "though no data operation was in progress.\n", 1433b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 14341c6a0718SPierre Ossman sdhci_dumpregs(host); 14351c6a0718SPierre Ossman 14361c6a0718SPierre Ossman return; 14371c6a0718SPierre Ossman } 14381c6a0718SPierre Ossman 14391c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 144017b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 144117b0429dSPierre Ossman else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 144217b0429dSPierre Ossman host->data->error = -EILSEQ; 14436882a8c0SBen Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 14446882a8c0SBen Dooks printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); 14456882a8c0SBen Dooks sdhci_show_adma_error(host); 14462134a922SPierre Ossman host->data->error = -EIO; 14476882a8c0SBen Dooks } 14481c6a0718SPierre Ossman 144917b0429dSPierre Ossman if (host->data->error) 14501c6a0718SPierre Ossman sdhci_finish_data(host); 14511c6a0718SPierre Ossman else { 14521c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 14531c6a0718SPierre Ossman sdhci_transfer_pio(host); 14541c6a0718SPierre Ossman 14556ba736a1SPierre Ossman /* 14566ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 14576ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 14586ba736a1SPierre Ossman * we need to at least restart the transfer. 14596ba736a1SPierre Ossman */ 14606ba736a1SPierre Ossman if (intmask & SDHCI_INT_DMA_END) 14614e4141a5SAnton Vorontsov sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS), 14624e4141a5SAnton Vorontsov SDHCI_DMA_ADDRESS); 14636ba736a1SPierre Ossman 1464e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1465e538fbe8SPierre Ossman if (host->cmd) { 1466e538fbe8SPierre Ossman /* 1467e538fbe8SPierre Ossman * Data managed to finish before the 1468e538fbe8SPierre Ossman * command completed. Make sure we do 1469e538fbe8SPierre Ossman * things in the proper order. 1470e538fbe8SPierre Ossman */ 1471e538fbe8SPierre Ossman host->data_early = 1; 1472e538fbe8SPierre Ossman } else { 14731c6a0718SPierre Ossman sdhci_finish_data(host); 14741c6a0718SPierre Ossman } 14751c6a0718SPierre Ossman } 1476e538fbe8SPierre Ossman } 1477e538fbe8SPierre Ossman } 14781c6a0718SPierre Ossman 14791c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 14801c6a0718SPierre Ossman { 14811c6a0718SPierre Ossman irqreturn_t result; 14821c6a0718SPierre Ossman struct sdhci_host* host = dev_id; 14831c6a0718SPierre Ossman u32 intmask; 1484f75979b7SPierre Ossman int cardint = 0; 14851c6a0718SPierre Ossman 14861c6a0718SPierre Ossman spin_lock(&host->lock); 14871c6a0718SPierre Ossman 14884e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 14891c6a0718SPierre Ossman 14901c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 14911c6a0718SPierre Ossman result = IRQ_NONE; 14921c6a0718SPierre Ossman goto out; 14931c6a0718SPierre Ossman } 14941c6a0718SPierre Ossman 1495b69c9058SPierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 1496b69c9058SPierre Ossman mmc_hostname(host->mmc), intmask); 14971c6a0718SPierre Ossman 14981c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 14994e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 15004e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 15011c6a0718SPierre Ossman tasklet_schedule(&host->card_tasklet); 15021c6a0718SPierre Ossman } 15031c6a0718SPierre Ossman 15041c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 15051c6a0718SPierre Ossman 15061c6a0718SPierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 15074e4141a5SAnton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 15084e4141a5SAnton Vorontsov SDHCI_INT_STATUS); 15091c6a0718SPierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 15101c6a0718SPierre Ossman } 15111c6a0718SPierre Ossman 15121c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 15134e4141a5SAnton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, 15144e4141a5SAnton Vorontsov SDHCI_INT_STATUS); 15151c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 15161c6a0718SPierre Ossman } 15171c6a0718SPierre Ossman 15181c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 15191c6a0718SPierre Ossman 1520964f9ce2SPierre Ossman intmask &= ~SDHCI_INT_ERROR; 1521964f9ce2SPierre Ossman 15221c6a0718SPierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 15231c6a0718SPierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 15241c6a0718SPierre Ossman mmc_hostname(host->mmc)); 15254e4141a5SAnton Vorontsov sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); 15261c6a0718SPierre Ossman } 15271c6a0718SPierre Ossman 15289d26a5d3SRolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 15291c6a0718SPierre Ossman 1530f75979b7SPierre Ossman if (intmask & SDHCI_INT_CARD_INT) 1531f75979b7SPierre Ossman cardint = 1; 1532f75979b7SPierre Ossman 1533f75979b7SPierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 1534f75979b7SPierre Ossman 15351c6a0718SPierre Ossman if (intmask) { 15361c6a0718SPierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 15371c6a0718SPierre Ossman mmc_hostname(host->mmc), intmask); 15381c6a0718SPierre Ossman sdhci_dumpregs(host); 15391c6a0718SPierre Ossman 15404e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 15411c6a0718SPierre Ossman } 15421c6a0718SPierre Ossman 15431c6a0718SPierre Ossman result = IRQ_HANDLED; 15441c6a0718SPierre Ossman 15451c6a0718SPierre Ossman mmiowb(); 15461c6a0718SPierre Ossman out: 15471c6a0718SPierre Ossman spin_unlock(&host->lock); 15481c6a0718SPierre Ossman 1549f75979b7SPierre Ossman /* 1550f75979b7SPierre Ossman * We have to delay this as it calls back into the driver. 1551f75979b7SPierre Ossman */ 1552f75979b7SPierre Ossman if (cardint) 1553f75979b7SPierre Ossman mmc_signal_sdio_irq(host->mmc); 1554f75979b7SPierre Ossman 15551c6a0718SPierre Ossman return result; 15561c6a0718SPierre Ossman } 15571c6a0718SPierre Ossman 15581c6a0718SPierre Ossman /*****************************************************************************\ 15591c6a0718SPierre Ossman * * 15601c6a0718SPierre Ossman * Suspend/resume * 15611c6a0718SPierre Ossman * * 15621c6a0718SPierre Ossman \*****************************************************************************/ 15631c6a0718SPierre Ossman 15641c6a0718SPierre Ossman #ifdef CONFIG_PM 15651c6a0718SPierre Ossman 1566b8c86fc5SPierre Ossman int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 15671c6a0718SPierre Ossman { 1568b8c86fc5SPierre Ossman int ret; 15691c6a0718SPierre Ossman 15707260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 15717260cf5eSAnton Vorontsov 1572b8c86fc5SPierre Ossman ret = mmc_suspend_host(host->mmc, state); 15731c6a0718SPierre Ossman if (ret) 15741c6a0718SPierre Ossman return ret; 15751c6a0718SPierre Ossman 1576b8c86fc5SPierre Ossman free_irq(host->irq, host); 1577b8c86fc5SPierre Ossman 1578b8c86fc5SPierre Ossman return 0; 1579b8c86fc5SPierre Ossman } 1580b8c86fc5SPierre Ossman 1581b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 1582b8c86fc5SPierre Ossman 1583b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 1584b8c86fc5SPierre Ossman { 1585b8c86fc5SPierre Ossman int ret; 1586b8c86fc5SPierre Ossman 1587b8c86fc5SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 1588b8c86fc5SPierre Ossman if (host->ops->enable_dma) 1589b8c86fc5SPierre Ossman host->ops->enable_dma(host); 1590b8c86fc5SPierre Ossman } 1591b8c86fc5SPierre Ossman 1592b8c86fc5SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1593b8c86fc5SPierre Ossman mmc_hostname(host->mmc), host); 15941c6a0718SPierre Ossman if (ret) 15951c6a0718SPierre Ossman return ret; 1596b8c86fc5SPierre Ossman 1597b8c86fc5SPierre Ossman sdhci_init(host); 15981c6a0718SPierre Ossman mmiowb(); 1599b8c86fc5SPierre Ossman 1600b8c86fc5SPierre Ossman ret = mmc_resume_host(host->mmc); 16011c6a0718SPierre Ossman if (ret) 16021c6a0718SPierre Ossman return ret; 16031c6a0718SPierre Ossman 16047260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 16057260cf5eSAnton Vorontsov 16061c6a0718SPierre Ossman return 0; 16071c6a0718SPierre Ossman } 16081c6a0718SPierre Ossman 1609b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 16101c6a0718SPierre Ossman 16111c6a0718SPierre Ossman #endif /* CONFIG_PM */ 16121c6a0718SPierre Ossman 16131c6a0718SPierre Ossman /*****************************************************************************\ 16141c6a0718SPierre Ossman * * 1615b8c86fc5SPierre Ossman * Device allocation/registration * 16161c6a0718SPierre Ossman * * 16171c6a0718SPierre Ossman \*****************************************************************************/ 16181c6a0718SPierre Ossman 1619b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 1620b8c86fc5SPierre Ossman size_t priv_size) 16211c6a0718SPierre Ossman { 16221c6a0718SPierre Ossman struct mmc_host *mmc; 16231c6a0718SPierre Ossman struct sdhci_host *host; 16241c6a0718SPierre Ossman 1625b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 16261c6a0718SPierre Ossman 1627b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 16281c6a0718SPierre Ossman if (!mmc) 1629b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 16301c6a0718SPierre Ossman 16311c6a0718SPierre Ossman host = mmc_priv(mmc); 16321c6a0718SPierre Ossman host->mmc = mmc; 16331c6a0718SPierre Ossman 1634b8c86fc5SPierre Ossman return host; 16351c6a0718SPierre Ossman } 16361c6a0718SPierre Ossman 1637b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 1638b8c86fc5SPierre Ossman 1639b8c86fc5SPierre Ossman int sdhci_add_host(struct sdhci_host *host) 1640b8c86fc5SPierre Ossman { 1641b8c86fc5SPierre Ossman struct mmc_host *mmc; 1642b8c86fc5SPierre Ossman unsigned int caps; 1643b8c86fc5SPierre Ossman int ret; 1644b8c86fc5SPierre Ossman 1645b8c86fc5SPierre Ossman WARN_ON(host == NULL); 1646b8c86fc5SPierre Ossman if (host == NULL) 1647b8c86fc5SPierre Ossman return -EINVAL; 1648b8c86fc5SPierre Ossman 1649b8c86fc5SPierre Ossman mmc = host->mmc; 1650b8c86fc5SPierre Ossman 1651b8c86fc5SPierre Ossman if (debug_quirks) 1652b8c86fc5SPierre Ossman host->quirks = debug_quirks; 1653b8c86fc5SPierre Ossman 16541c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 16551c6a0718SPierre Ossman 16564e4141a5SAnton Vorontsov host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 16572134a922SPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 16582134a922SPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 16592134a922SPierre Ossman if (host->version > SDHCI_SPEC_200) { 16601c6a0718SPierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 1661b69c9058SPierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 16622134a922SPierre Ossman host->version); 16631c6a0718SPierre Ossman } 16641c6a0718SPierre Ossman 16654e4141a5SAnton Vorontsov caps = sdhci_readl(host, SDHCI_CAPABILITIES); 16661c6a0718SPierre Ossman 1667b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 16681c6a0718SPierre Ossman host->flags |= SDHCI_USE_DMA; 16691c6a0718SPierre Ossman else if (!(caps & SDHCI_CAN_DO_DMA)) 16701c6a0718SPierre Ossman DBG("Controller doesn't have DMA capability\n"); 16711c6a0718SPierre Ossman else 16721c6a0718SPierre Ossman host->flags |= SDHCI_USE_DMA; 16731c6a0718SPierre Ossman 1674b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 16757c168e3dSFeng Tang (host->flags & SDHCI_USE_DMA)) { 1676cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 16777c168e3dSFeng Tang host->flags &= ~SDHCI_USE_DMA; 16787c168e3dSFeng Tang } 16797c168e3dSFeng Tang 16801c6a0718SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 16812134a922SPierre Ossman if ((host->version >= SDHCI_SPEC_200) && 16822134a922SPierre Ossman (caps & SDHCI_CAN_DO_ADMA2)) 16832134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 16842134a922SPierre Ossman } 16852134a922SPierre Ossman 16862134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 16872134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 16882134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 16892134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 16902134a922SPierre Ossman } 16912134a922SPierre Ossman 16922134a922SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 1693b8c86fc5SPierre Ossman if (host->ops->enable_dma) { 1694b8c86fc5SPierre Ossman if (host->ops->enable_dma(host)) { 1695b8c86fc5SPierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 1696b8c86fc5SPierre Ossman "available. Falling back to PIO.\n", 1697b8c86fc5SPierre Ossman mmc_hostname(mmc)); 16982134a922SPierre Ossman host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA); 16991c6a0718SPierre Ossman } 17001c6a0718SPierre Ossman } 1701b8c86fc5SPierre Ossman } 17021c6a0718SPierre Ossman 17032134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 17042134a922SPierre Ossman /* 17052134a922SPierre Ossman * We need to allocate descriptors for all sg entries 17062134a922SPierre Ossman * (128) and potentially one alignment transfer for 17072134a922SPierre Ossman * each of those entries. 17082134a922SPierre Ossman */ 17092134a922SPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 17102134a922SPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 17112134a922SPierre Ossman if (!host->adma_desc || !host->align_buffer) { 17122134a922SPierre Ossman kfree(host->adma_desc); 17132134a922SPierre Ossman kfree(host->align_buffer); 17142134a922SPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 17152134a922SPierre Ossman "buffers. Falling back to standard DMA.\n", 17162134a922SPierre Ossman mmc_hostname(mmc)); 17172134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17182134a922SPierre Ossman } 17192134a922SPierre Ossman } 17202134a922SPierre Ossman 17217659150cSPierre Ossman /* 17227659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 17237659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 17247659150cSPierre Ossman * mask here in that case. 17257659150cSPierre Ossman */ 17267659150cSPierre Ossman if (!(host->flags & SDHCI_USE_DMA)) { 17277659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 17287659150cSPierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 17297659150cSPierre Ossman } 17301c6a0718SPierre Ossman 17311c6a0718SPierre Ossman host->max_clk = 17321c6a0718SPierre Ossman (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 17334240ff0aSBen Dooks host->max_clk *= 1000000; 17341c6a0718SPierre Ossman if (host->max_clk == 0) { 17354240ff0aSBen Dooks if (!host->ops->get_max_clock) { 17364240ff0aSBen Dooks printk(KERN_ERR 17374240ff0aSBen Dooks "%s: Hardware doesn't specify base clock " 1738b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1739b8c86fc5SPierre Ossman return -ENODEV; 17401c6a0718SPierre Ossman } 17414240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 17424240ff0aSBen Dooks } 17431c6a0718SPierre Ossman 17441c6a0718SPierre Ossman host->timeout_clk = 17451c6a0718SPierre Ossman (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 17461c6a0718SPierre Ossman if (host->timeout_clk == 0) { 17474240ff0aSBen Dooks if (!host->ops->get_timeout_clock) { 17484240ff0aSBen Dooks printk(KERN_ERR 17494240ff0aSBen Dooks "%s: Hardware doesn't specify timeout clock " 1750b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1751b8c86fc5SPierre Ossman return -ENODEV; 17521c6a0718SPierre Ossman } 17534240ff0aSBen Dooks host->timeout_clk = host->ops->get_timeout_clock(host); 17544240ff0aSBen Dooks } 17551c6a0718SPierre Ossman if (caps & SDHCI_TIMEOUT_CLK_UNIT) 17561c6a0718SPierre Ossman host->timeout_clk *= 1000; 17571c6a0718SPierre Ossman 17581c6a0718SPierre Ossman /* 17591c6a0718SPierre Ossman * Set host parameters. 17601c6a0718SPierre Ossman */ 17611c6a0718SPierre Ossman mmc->ops = &sdhci_ops; 17621c6a0718SPierre Ossman mmc->f_min = host->max_clk / 256; 17631c6a0718SPierre Ossman mmc->f_max = host->max_clk; 1764c9b74c5bSPierre Ossman mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; 17651c6a0718SPierre Ossman 176686a6a874SPierre Ossman if (caps & SDHCI_CAN_DO_HISPD) 17671c6a0718SPierre Ossman mmc->caps |= MMC_CAP_SD_HIGHSPEED; 17681c6a0718SPierre Ossman 176968d1fb7eSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 177068d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 177168d1fb7eSAnton Vorontsov 17721c6a0718SPierre Ossman mmc->ocr_avail = 0; 17731c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_330) 17741c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; 17751c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_300) 17761c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; 17771c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_180) 177855556da0SPhilip Langdale mmc->ocr_avail |= MMC_VDD_165_195; 17791c6a0718SPierre Ossman 17801c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 17811c6a0718SPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 1782b69c9058SPierre Ossman "support voltages.\n", mmc_hostname(mmc)); 1783b8c86fc5SPierre Ossman return -ENODEV; 17841c6a0718SPierre Ossman } 17851c6a0718SPierre Ossman 17861c6a0718SPierre Ossman spin_lock_init(&host->lock); 17871c6a0718SPierre Ossman 17881c6a0718SPierre Ossman /* 17892134a922SPierre Ossman * Maximum number of segments. Depends on if the hardware 17902134a922SPierre Ossman * can do scatter/gather or not. 17911c6a0718SPierre Ossman */ 17922134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 17932134a922SPierre Ossman mmc->max_hw_segs = 128; 17942134a922SPierre Ossman else if (host->flags & SDHCI_USE_DMA) 17951c6a0718SPierre Ossman mmc->max_hw_segs = 1; 17962134a922SPierre Ossman else /* PIO */ 17972134a922SPierre Ossman mmc->max_hw_segs = 128; 17982134a922SPierre Ossman mmc->max_phys_segs = 128; 17991c6a0718SPierre Ossman 18001c6a0718SPierre Ossman /* 18011c6a0718SPierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 18021c6a0718SPierre Ossman * size (512KiB). 18031c6a0718SPierre Ossman */ 18041c6a0718SPierre Ossman mmc->max_req_size = 524288; 18051c6a0718SPierre Ossman 18061c6a0718SPierre Ossman /* 18071c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 18082134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 18092134a922SPierre Ossman * be larger than 64 KiB though. 18101c6a0718SPierre Ossman */ 18112134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 18122134a922SPierre Ossman mmc->max_seg_size = 65536; 18132134a922SPierre Ossman else 18141c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 18151c6a0718SPierre Ossman 18161c6a0718SPierre Ossman /* 18171c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 18181c6a0718SPierre Ossman * is specified in the capabilities register. 18191c6a0718SPierre Ossman */ 18200633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 18210633f654SAnton Vorontsov mmc->max_blk_size = 2; 18220633f654SAnton Vorontsov } else { 18230633f654SAnton Vorontsov mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> 18240633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 18251c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 1826b69c9058SPierre Ossman printk(KERN_WARNING "%s: Invalid maximum block size, " 1827b69c9058SPierre Ossman "assuming 512 bytes\n", mmc_hostname(mmc)); 18280633f654SAnton Vorontsov mmc->max_blk_size = 0; 18290633f654SAnton Vorontsov } 18300633f654SAnton Vorontsov } 18310633f654SAnton Vorontsov 18321c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 18331c6a0718SPierre Ossman 18341c6a0718SPierre Ossman /* 18351c6a0718SPierre Ossman * Maximum block count. 18361c6a0718SPierre Ossman */ 18371c6a0718SPierre Ossman mmc->max_blk_count = 65535; 18381c6a0718SPierre Ossman 18391c6a0718SPierre Ossman /* 18401c6a0718SPierre Ossman * Init tasklets. 18411c6a0718SPierre Ossman */ 18421c6a0718SPierre Ossman tasklet_init(&host->card_tasklet, 18431c6a0718SPierre Ossman sdhci_tasklet_card, (unsigned long)host); 18441c6a0718SPierre Ossman tasklet_init(&host->finish_tasklet, 18451c6a0718SPierre Ossman sdhci_tasklet_finish, (unsigned long)host); 18461c6a0718SPierre Ossman 18471c6a0718SPierre Ossman setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 18481c6a0718SPierre Ossman 18491c6a0718SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1850b69c9058SPierre Ossman mmc_hostname(mmc), host); 18511c6a0718SPierre Ossman if (ret) 18521c6a0718SPierre Ossman goto untasklet; 18531c6a0718SPierre Ossman 18541c6a0718SPierre Ossman sdhci_init(host); 18551c6a0718SPierre Ossman 18561c6a0718SPierre Ossman #ifdef CONFIG_MMC_DEBUG 18571c6a0718SPierre Ossman sdhci_dumpregs(host); 18581c6a0718SPierre Ossman #endif 18591c6a0718SPierre Ossman 1860f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 18615dbace0cSHelmut Schaa snprintf(host->led_name, sizeof(host->led_name), 18625dbace0cSHelmut Schaa "%s::", mmc_hostname(mmc)); 18635dbace0cSHelmut Schaa host->led.name = host->led_name; 18642f730fecSPierre Ossman host->led.brightness = LED_OFF; 18652f730fecSPierre Ossman host->led.default_trigger = mmc_hostname(mmc); 18662f730fecSPierre Ossman host->led.brightness_set = sdhci_led_control; 18672f730fecSPierre Ossman 1868b8c86fc5SPierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 18692f730fecSPierre Ossman if (ret) 18702f730fecSPierre Ossman goto reset; 18712f730fecSPierre Ossman #endif 18722f730fecSPierre Ossman 18731c6a0718SPierre Ossman mmiowb(); 18741c6a0718SPierre Ossman 18751c6a0718SPierre Ossman mmc_add_host(mmc); 18761c6a0718SPierre Ossman 18772134a922SPierre Ossman printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", 1878d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 18792134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)?"A":"", 18801c6a0718SPierre Ossman (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); 18811c6a0718SPierre Ossman 18827260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 18837260cf5eSAnton Vorontsov 18841c6a0718SPierre Ossman return 0; 18851c6a0718SPierre Ossman 1886f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 18872f730fecSPierre Ossman reset: 18882f730fecSPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 18892f730fecSPierre Ossman free_irq(host->irq, host); 18902f730fecSPierre Ossman #endif 18911c6a0718SPierre Ossman untasklet: 18921c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 18931c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 18941c6a0718SPierre Ossman 18951c6a0718SPierre Ossman return ret; 18961c6a0718SPierre Ossman } 18971c6a0718SPierre Ossman 1898b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 1899b8c86fc5SPierre Ossman 19001e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 19011c6a0718SPierre Ossman { 19021e72859eSPierre Ossman unsigned long flags; 19031e72859eSPierre Ossman 19041e72859eSPierre Ossman if (dead) { 19051e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 19061e72859eSPierre Ossman 19071e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 19081e72859eSPierre Ossman 19091e72859eSPierre Ossman if (host->mrq) { 19101e72859eSPierre Ossman printk(KERN_ERR "%s: Controller removed during " 19111e72859eSPierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 19121e72859eSPierre Ossman 19131e72859eSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 19141e72859eSPierre Ossman tasklet_schedule(&host->finish_tasklet); 19151e72859eSPierre Ossman } 19161e72859eSPierre Ossman 19171e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 19181e72859eSPierre Ossman } 19191e72859eSPierre Ossman 19207260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 19217260cf5eSAnton Vorontsov 1922b8c86fc5SPierre Ossman mmc_remove_host(host->mmc); 19231c6a0718SPierre Ossman 1924f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 19252f730fecSPierre Ossman led_classdev_unregister(&host->led); 19262f730fecSPierre Ossman #endif 19272f730fecSPierre Ossman 19281e72859eSPierre Ossman if (!dead) 19291c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 19301c6a0718SPierre Ossman 19311c6a0718SPierre Ossman free_irq(host->irq, host); 19321c6a0718SPierre Ossman 19331c6a0718SPierre Ossman del_timer_sync(&host->timer); 19341c6a0718SPierre Ossman 19351c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 19361c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 19372134a922SPierre Ossman 19382134a922SPierre Ossman kfree(host->adma_desc); 19392134a922SPierre Ossman kfree(host->align_buffer); 19402134a922SPierre Ossman 19412134a922SPierre Ossman host->adma_desc = NULL; 19422134a922SPierre Ossman host->align_buffer = NULL; 19431c6a0718SPierre Ossman } 19441c6a0718SPierre Ossman 1945b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 1946b8c86fc5SPierre Ossman 1947b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 19481c6a0718SPierre Ossman { 1949b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 19501c6a0718SPierre Ossman } 19511c6a0718SPierre Ossman 1952b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 19531c6a0718SPierre Ossman 19541c6a0718SPierre Ossman /*****************************************************************************\ 19551c6a0718SPierre Ossman * * 19561c6a0718SPierre Ossman * Driver init/exit * 19571c6a0718SPierre Ossman * * 19581c6a0718SPierre Ossman \*****************************************************************************/ 19591c6a0718SPierre Ossman 19601c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 19611c6a0718SPierre Ossman { 19621c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME 19631c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 19641c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 19651c6a0718SPierre Ossman 1966b8c86fc5SPierre Ossman return 0; 19671c6a0718SPierre Ossman } 19681c6a0718SPierre Ossman 19691c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 19701c6a0718SPierre Ossman { 19711c6a0718SPierre Ossman } 19721c6a0718SPierre Ossman 19731c6a0718SPierre Ossman module_init(sdhci_drv_init); 19741c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 19751c6a0718SPierre Ossman 19761c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 19771c6a0718SPierre Ossman 197832710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 1979b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 19801c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 19811c6a0718SPierre Ossman 19821c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 1983