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> 205a0e3ad6STejun Heo #include <linux/slab.h> 2111763609SRalf Baechle #include <linux/scatterlist.h> 229bea3c85SMarek Szyprowski #include <linux/regulator/consumer.h> 231c6a0718SPierre Ossman 242f730fecSPierre Ossman #include <linux/leds.h> 252f730fecSPierre Ossman 261c6a0718SPierre Ossman #include <linux/mmc/host.h> 271c6a0718SPierre Ossman 281c6a0718SPierre Ossman #include "sdhci.h" 291c6a0718SPierre Ossman 301c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 311c6a0718SPierre Ossman 321c6a0718SPierre Ossman #define DBG(f, x...) \ 331c6a0718SPierre Ossman pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 341c6a0718SPierre Ossman 35f9134319SPierre Ossman #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 36f9134319SPierre Ossman defined(CONFIG_MMC_SDHCI_MODULE)) 37f9134319SPierre Ossman #define SDHCI_USE_LEDS_CLASS 38f9134319SPierre Ossman #endif 39f9134319SPierre Ossman 401c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 411c6a0718SPierre Ossman 421c6a0718SPierre Ossman static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); 431c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *); 441c6a0718SPierre Ossman 451c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 461c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *); 471c6a0718SPierre Ossman 481c6a0718SPierre Ossman static void sdhci_dumpregs(struct sdhci_host *host) 491c6a0718SPierre Ossman { 50412ab659SPhilip Rakity printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", 51412ab659SPhilip Rakity mmc_hostname(host->mmc)); 521c6a0718SPierre Ossman 531c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 544e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 554e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 561c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 574e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 584e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 591c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 604e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 614e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 621c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 634e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 644e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 651c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 664e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 674e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 681c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 694e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 704e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 711c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 724e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 734e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 741c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 754e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 764e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 771c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 784e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 794e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 801c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", 814e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 824e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 831c6a0718SPierre Ossman 84be3f4ae0SBen Dooks if (host->flags & SDHCI_USE_ADMA) 85be3f4ae0SBen Dooks printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 86be3f4ae0SBen Dooks readl(host->ioaddr + SDHCI_ADMA_ERROR), 87be3f4ae0SBen Dooks readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); 88be3f4ae0SBen Dooks 891c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 901c6a0718SPierre Ossman } 911c6a0718SPierre Ossman 921c6a0718SPierre Ossman /*****************************************************************************\ 931c6a0718SPierre Ossman * * 941c6a0718SPierre Ossman * Low level functions * 951c6a0718SPierre Ossman * * 961c6a0718SPierre Ossman \*****************************************************************************/ 971c6a0718SPierre Ossman 987260cf5eSAnton Vorontsov static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 997260cf5eSAnton Vorontsov { 1007260cf5eSAnton Vorontsov u32 ier; 1017260cf5eSAnton Vorontsov 1027260cf5eSAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1037260cf5eSAnton Vorontsov ier &= ~clear; 1047260cf5eSAnton Vorontsov ier |= set; 1057260cf5eSAnton Vorontsov sdhci_writel(host, ier, SDHCI_INT_ENABLE); 1067260cf5eSAnton Vorontsov sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 1077260cf5eSAnton Vorontsov } 1087260cf5eSAnton Vorontsov 1097260cf5eSAnton Vorontsov static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) 1107260cf5eSAnton Vorontsov { 1117260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, 0, irqs); 1127260cf5eSAnton Vorontsov } 1137260cf5eSAnton Vorontsov 1147260cf5eSAnton Vorontsov static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) 1157260cf5eSAnton Vorontsov { 1167260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, irqs, 0); 1177260cf5eSAnton Vorontsov } 1187260cf5eSAnton Vorontsov 1197260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1207260cf5eSAnton Vorontsov { 1217260cf5eSAnton Vorontsov u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 1227260cf5eSAnton Vorontsov 12368d1fb7eSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 12468d1fb7eSAnton Vorontsov return; 12568d1fb7eSAnton Vorontsov 1267260cf5eSAnton Vorontsov if (enable) 1277260cf5eSAnton Vorontsov sdhci_unmask_irqs(host, irqs); 1287260cf5eSAnton Vorontsov else 1297260cf5eSAnton Vorontsov sdhci_mask_irqs(host, irqs); 1307260cf5eSAnton Vorontsov } 1317260cf5eSAnton Vorontsov 1327260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host) 1337260cf5eSAnton Vorontsov { 1347260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true); 1357260cf5eSAnton Vorontsov } 1367260cf5eSAnton Vorontsov 1377260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host) 1387260cf5eSAnton Vorontsov { 1397260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false); 1407260cf5eSAnton Vorontsov } 1417260cf5eSAnton Vorontsov 1421c6a0718SPierre Ossman static void sdhci_reset(struct sdhci_host *host, u8 mask) 1431c6a0718SPierre Ossman { 1441c6a0718SPierre Ossman unsigned long timeout; 145063a9dbbSAnton Vorontsov u32 uninitialized_var(ier); 1461c6a0718SPierre Ossman 147b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 1484e4141a5SAnton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & 1491c6a0718SPierre Ossman SDHCI_CARD_PRESENT)) 1501c6a0718SPierre Ossman return; 1511c6a0718SPierre Ossman } 1521c6a0718SPierre Ossman 153063a9dbbSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 154063a9dbbSAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 155063a9dbbSAnton Vorontsov 1564e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 1571c6a0718SPierre Ossman 1581c6a0718SPierre Ossman if (mask & SDHCI_RESET_ALL) 1591c6a0718SPierre Ossman host->clock = 0; 1601c6a0718SPierre Ossman 1611c6a0718SPierre Ossman /* Wait max 100 ms */ 1621c6a0718SPierre Ossman timeout = 100; 1631c6a0718SPierre Ossman 1641c6a0718SPierre Ossman /* hw clears the bit when it's done */ 1654e4141a5SAnton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 1661c6a0718SPierre Ossman if (timeout == 0) { 1671c6a0718SPierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 1681c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 1691c6a0718SPierre Ossman sdhci_dumpregs(host); 1701c6a0718SPierre Ossman return; 1711c6a0718SPierre Ossman } 1721c6a0718SPierre Ossman timeout--; 1731c6a0718SPierre Ossman mdelay(1); 1741c6a0718SPierre Ossman } 175063a9dbbSAnton Vorontsov 176063a9dbbSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 177063a9dbbSAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 1781c6a0718SPierre Ossman } 1791c6a0718SPierre Ossman 1802f4cbb3dSNicolas Pitre static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); 1812f4cbb3dSNicolas Pitre 1822f4cbb3dSNicolas Pitre static void sdhci_init(struct sdhci_host *host, int soft) 1831c6a0718SPierre Ossman { 1842f4cbb3dSNicolas Pitre if (soft) 1852f4cbb3dSNicolas Pitre sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); 1862f4cbb3dSNicolas Pitre else 1871c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1881c6a0718SPierre Ossman 1897260cf5eSAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 1907260cf5eSAnton Vorontsov SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 1911c6a0718SPierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 1921c6a0718SPierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 1936aa943abSAnton Vorontsov SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 1942f4cbb3dSNicolas Pitre 1952f4cbb3dSNicolas Pitre if (soft) { 1962f4cbb3dSNicolas Pitre /* force clock reconfiguration */ 1972f4cbb3dSNicolas Pitre host->clock = 0; 1982f4cbb3dSNicolas Pitre sdhci_set_ios(host->mmc, &host->mmc->ios); 1992f4cbb3dSNicolas Pitre } 2007260cf5eSAnton Vorontsov } 2011c6a0718SPierre Ossman 2027260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 2037260cf5eSAnton Vorontsov { 2042f4cbb3dSNicolas Pitre sdhci_init(host, 0); 2057260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 2061c6a0718SPierre Ossman } 2071c6a0718SPierre Ossman 2081c6a0718SPierre Ossman static void sdhci_activate_led(struct sdhci_host *host) 2091c6a0718SPierre Ossman { 2101c6a0718SPierre Ossman u8 ctrl; 2111c6a0718SPierre Ossman 2124e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 2131c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 2144e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2151c6a0718SPierre Ossman } 2161c6a0718SPierre Ossman 2171c6a0718SPierre Ossman static void sdhci_deactivate_led(struct sdhci_host *host) 2181c6a0718SPierre Ossman { 2191c6a0718SPierre Ossman u8 ctrl; 2201c6a0718SPierre Ossman 2214e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 2221c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2234e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2241c6a0718SPierre Ossman } 2251c6a0718SPierre Ossman 226f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 2272f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 2282f730fecSPierre Ossman enum led_brightness brightness) 2292f730fecSPierre Ossman { 2302f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2312f730fecSPierre Ossman unsigned long flags; 2322f730fecSPierre Ossman 2332f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 2342f730fecSPierre Ossman 2352f730fecSPierre Ossman if (brightness == LED_OFF) 2362f730fecSPierre Ossman sdhci_deactivate_led(host); 2372f730fecSPierre Ossman else 2382f730fecSPierre Ossman sdhci_activate_led(host); 2392f730fecSPierre Ossman 2402f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2412f730fecSPierre Ossman } 2422f730fecSPierre Ossman #endif 2432f730fecSPierre Ossman 2441c6a0718SPierre Ossman /*****************************************************************************\ 2451c6a0718SPierre Ossman * * 2461c6a0718SPierre Ossman * Core functions * 2471c6a0718SPierre Ossman * * 2481c6a0718SPierre Ossman \*****************************************************************************/ 2491c6a0718SPierre Ossman 2501c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 2511c6a0718SPierre Ossman { 2527659150cSPierre Ossman unsigned long flags; 2537659150cSPierre Ossman size_t blksize, len, chunk; 2547244b85bSSteven Noonan u32 uninitialized_var(scratch); 2557659150cSPierre Ossman u8 *buf; 2561c6a0718SPierre Ossman 2571c6a0718SPierre Ossman DBG("PIO reading\n"); 2581c6a0718SPierre Ossman 2591c6a0718SPierre Ossman blksize = host->data->blksz; 2607659150cSPierre Ossman chunk = 0; 2611c6a0718SPierre Ossman 2627659150cSPierre Ossman local_irq_save(flags); 2631c6a0718SPierre Ossman 2641c6a0718SPierre Ossman while (blksize) { 2657659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 2667659150cSPierre Ossman BUG(); 2677659150cSPierre Ossman 2687659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 2697659150cSPierre Ossman 2707659150cSPierre Ossman blksize -= len; 2717659150cSPierre Ossman host->sg_miter.consumed = len; 2727659150cSPierre Ossman 2737659150cSPierre Ossman buf = host->sg_miter.addr; 2747659150cSPierre Ossman 2757659150cSPierre Ossman while (len) { 2767659150cSPierre Ossman if (chunk == 0) { 2774e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 2787659150cSPierre Ossman chunk = 4; 2791c6a0718SPierre Ossman } 2801c6a0718SPierre Ossman 2817659150cSPierre Ossman *buf = scratch & 0xFF; 2821c6a0718SPierre Ossman 2837659150cSPierre Ossman buf++; 2847659150cSPierre Ossman scratch >>= 8; 2857659150cSPierre Ossman chunk--; 2867659150cSPierre Ossman len--; 2877659150cSPierre Ossman } 2881c6a0718SPierre Ossman } 2891c6a0718SPierre Ossman 2907659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 2917659150cSPierre Ossman 2927659150cSPierre Ossman local_irq_restore(flags); 2931c6a0718SPierre Ossman } 2941c6a0718SPierre Ossman 2951c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 2961c6a0718SPierre Ossman { 2977659150cSPierre Ossman unsigned long flags; 2987659150cSPierre Ossman size_t blksize, len, chunk; 2997659150cSPierre Ossman u32 scratch; 3007659150cSPierre Ossman u8 *buf; 3011c6a0718SPierre Ossman 3021c6a0718SPierre Ossman DBG("PIO writing\n"); 3031c6a0718SPierre Ossman 3041c6a0718SPierre Ossman blksize = host->data->blksz; 3057659150cSPierre Ossman chunk = 0; 3067659150cSPierre Ossman scratch = 0; 3071c6a0718SPierre Ossman 3087659150cSPierre Ossman local_irq_save(flags); 3091c6a0718SPierre Ossman 3101c6a0718SPierre Ossman while (blksize) { 3117659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 3127659150cSPierre Ossman BUG(); 3131c6a0718SPierre Ossman 3147659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 3151c6a0718SPierre Ossman 3167659150cSPierre Ossman blksize -= len; 3177659150cSPierre Ossman host->sg_miter.consumed = len; 3187659150cSPierre Ossman 3197659150cSPierre Ossman buf = host->sg_miter.addr; 3207659150cSPierre Ossman 3217659150cSPierre Ossman while (len) { 3227659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 3237659150cSPierre Ossman 3247659150cSPierre Ossman buf++; 3257659150cSPierre Ossman chunk++; 3267659150cSPierre Ossman len--; 3277659150cSPierre Ossman 3287659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 3294e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 3307659150cSPierre Ossman chunk = 0; 3317659150cSPierre Ossman scratch = 0; 3327659150cSPierre Ossman } 3337659150cSPierre Ossman } 3341c6a0718SPierre Ossman } 3351c6a0718SPierre Ossman 3367659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 3371c6a0718SPierre Ossman 3387659150cSPierre Ossman local_irq_restore(flags); 3391c6a0718SPierre Ossman } 3401c6a0718SPierre Ossman 3411c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 3421c6a0718SPierre Ossman { 3431c6a0718SPierre Ossman u32 mask; 3441c6a0718SPierre Ossman 3451c6a0718SPierre Ossman BUG_ON(!host->data); 3461c6a0718SPierre Ossman 3477659150cSPierre Ossman if (host->blocks == 0) 3481c6a0718SPierre Ossman return; 3491c6a0718SPierre Ossman 3501c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 3511c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 3521c6a0718SPierre Ossman else 3531c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 3541c6a0718SPierre Ossman 3554a3cba32SPierre Ossman /* 3564a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 3574a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 3584a3cba32SPierre Ossman * we can ignore the bits. 3594a3cba32SPierre Ossman */ 3604a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 3614a3cba32SPierre Ossman (host->data->blocks == 1)) 3624a3cba32SPierre Ossman mask = ~0; 3634a3cba32SPierre Ossman 3644e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 3653e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 3663e3bf207SAnton Vorontsov udelay(100); 3673e3bf207SAnton Vorontsov 3681c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 3691c6a0718SPierre Ossman sdhci_read_block_pio(host); 3701c6a0718SPierre Ossman else 3711c6a0718SPierre Ossman sdhci_write_block_pio(host); 3721c6a0718SPierre Ossman 3737659150cSPierre Ossman host->blocks--; 3747659150cSPierre Ossman if (host->blocks == 0) 3751c6a0718SPierre Ossman break; 3761c6a0718SPierre Ossman } 3771c6a0718SPierre Ossman 3781c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 3791c6a0718SPierre Ossman } 3801c6a0718SPierre Ossman 3812134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3822134a922SPierre Ossman { 3832134a922SPierre Ossman local_irq_save(*flags); 3842134a922SPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 3852134a922SPierre Ossman } 3862134a922SPierre Ossman 3872134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 3882134a922SPierre Ossman { 3892134a922SPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 3902134a922SPierre Ossman local_irq_restore(*flags); 3912134a922SPierre Ossman } 3922134a922SPierre Ossman 393118cd17dSBen Dooks static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd) 394118cd17dSBen Dooks { 3959e506f35SBen Dooks __le32 *dataddr = (__le32 __force *)(desc + 4); 3969e506f35SBen Dooks __le16 *cmdlen = (__le16 __force *)desc; 397118cd17dSBen Dooks 3989e506f35SBen Dooks /* SDHCI specification says ADMA descriptors should be 4 byte 3999e506f35SBen Dooks * aligned, so using 16 or 32bit operations should be safe. */ 400118cd17dSBen Dooks 4019e506f35SBen Dooks cmdlen[0] = cpu_to_le16(cmd); 4029e506f35SBen Dooks cmdlen[1] = cpu_to_le16(len); 4039e506f35SBen Dooks 4049e506f35SBen Dooks dataddr[0] = cpu_to_le32(addr); 405118cd17dSBen Dooks } 406118cd17dSBen Dooks 4078f1934ceSPierre Ossman static int sdhci_adma_table_pre(struct sdhci_host *host, 4082134a922SPierre Ossman struct mmc_data *data) 4092134a922SPierre Ossman { 4102134a922SPierre Ossman int direction; 4112134a922SPierre Ossman 4122134a922SPierre Ossman u8 *desc; 4132134a922SPierre Ossman u8 *align; 4142134a922SPierre Ossman dma_addr_t addr; 4152134a922SPierre Ossman dma_addr_t align_addr; 4162134a922SPierre Ossman int len, offset; 4172134a922SPierre Ossman 4182134a922SPierre Ossman struct scatterlist *sg; 4192134a922SPierre Ossman int i; 4202134a922SPierre Ossman char *buffer; 4212134a922SPierre Ossman unsigned long flags; 4222134a922SPierre Ossman 4232134a922SPierre Ossman /* 4242134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 4252134a922SPierre Ossman * We currently guess that it is LE. 4262134a922SPierre Ossman */ 4272134a922SPierre Ossman 4282134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 4292134a922SPierre Ossman direction = DMA_FROM_DEVICE; 4302134a922SPierre Ossman else 4312134a922SPierre Ossman direction = DMA_TO_DEVICE; 4322134a922SPierre Ossman 4332134a922SPierre Ossman /* 4342134a922SPierre Ossman * The ADMA descriptor table is mapped further down as we 4352134a922SPierre Ossman * need to fill it with data first. 4362134a922SPierre Ossman */ 4372134a922SPierre Ossman 4382134a922SPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 4392134a922SPierre Ossman host->align_buffer, 128 * 4, direction); 4408d8bb39bSFUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4418f1934ceSPierre Ossman goto fail; 4422134a922SPierre Ossman BUG_ON(host->align_addr & 0x3); 4432134a922SPierre Ossman 4442134a922SPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 4452134a922SPierre Ossman data->sg, data->sg_len, direction); 4468f1934ceSPierre Ossman if (host->sg_count == 0) 4478f1934ceSPierre Ossman goto unmap_align; 4482134a922SPierre Ossman 4492134a922SPierre Ossman desc = host->adma_desc; 4502134a922SPierre Ossman align = host->align_buffer; 4512134a922SPierre Ossman 4522134a922SPierre Ossman align_addr = host->align_addr; 4532134a922SPierre Ossman 4542134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4552134a922SPierre Ossman addr = sg_dma_address(sg); 4562134a922SPierre Ossman len = sg_dma_len(sg); 4572134a922SPierre Ossman 4582134a922SPierre Ossman /* 4592134a922SPierre Ossman * The SDHCI specification states that ADMA 4602134a922SPierre Ossman * addresses must be 32-bit aligned. If they 4612134a922SPierre Ossman * aren't, then we use a bounce buffer for 4622134a922SPierre Ossman * the (up to three) bytes that screw up the 4632134a922SPierre Ossman * alignment. 4642134a922SPierre Ossman */ 4652134a922SPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 4662134a922SPierre Ossman if (offset) { 4672134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4682134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 4696cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 4702134a922SPierre Ossman memcpy(align, buffer, offset); 4712134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 4722134a922SPierre Ossman } 4732134a922SPierre Ossman 474118cd17dSBen Dooks /* tran, valid */ 475118cd17dSBen Dooks sdhci_set_adma_desc(desc, align_addr, offset, 0x21); 4762134a922SPierre Ossman 4772134a922SPierre Ossman BUG_ON(offset > 65536); 4782134a922SPierre Ossman 4792134a922SPierre Ossman align += 4; 4802134a922SPierre Ossman align_addr += 4; 4812134a922SPierre Ossman 4822134a922SPierre Ossman desc += 8; 4832134a922SPierre Ossman 4842134a922SPierre Ossman addr += offset; 4852134a922SPierre Ossman len -= offset; 4862134a922SPierre Ossman } 4872134a922SPierre Ossman 4882134a922SPierre Ossman BUG_ON(len > 65536); 4892134a922SPierre Ossman 490118cd17dSBen Dooks /* tran, valid */ 491118cd17dSBen Dooks sdhci_set_adma_desc(desc, addr, len, 0x21); 4922134a922SPierre Ossman desc += 8; 4932134a922SPierre Ossman 4942134a922SPierre Ossman /* 4952134a922SPierre Ossman * If this triggers then we have a calculation bug 4962134a922SPierre Ossman * somewhere. :/ 4972134a922SPierre Ossman */ 4982134a922SPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 4992134a922SPierre Ossman } 5002134a922SPierre Ossman 50170764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 50270764a90SThomas Abraham /* 50370764a90SThomas Abraham * Mark the last descriptor as the terminating descriptor 50470764a90SThomas Abraham */ 50570764a90SThomas Abraham if (desc != host->adma_desc) { 50670764a90SThomas Abraham desc -= 8; 50770764a90SThomas Abraham desc[0] |= 0x2; /* end */ 50870764a90SThomas Abraham } 50970764a90SThomas Abraham } else { 5102134a922SPierre Ossman /* 5112134a922SPierre Ossman * Add a terminating entry. 5122134a922SPierre Ossman */ 5132134a922SPierre Ossman 514118cd17dSBen Dooks /* nop, end, valid */ 515118cd17dSBen Dooks sdhci_set_adma_desc(desc, 0, 0, 0x3); 51670764a90SThomas Abraham } 5172134a922SPierre Ossman 5182134a922SPierre Ossman /* 5192134a922SPierre Ossman * Resync align buffer as we might have changed it. 5202134a922SPierre Ossman */ 5212134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5222134a922SPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 5232134a922SPierre Ossman host->align_addr, 128 * 4, direction); 5242134a922SPierre Ossman } 5252134a922SPierre Ossman 5262134a922SPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 5272134a922SPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 528980167b7SPierre Ossman if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) 5298f1934ceSPierre Ossman goto unmap_entries; 5302134a922SPierre Ossman BUG_ON(host->adma_addr & 0x3); 5318f1934ceSPierre Ossman 5328f1934ceSPierre Ossman return 0; 5338f1934ceSPierre Ossman 5348f1934ceSPierre Ossman unmap_entries: 5358f1934ceSPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5368f1934ceSPierre Ossman data->sg_len, direction); 5378f1934ceSPierre Ossman unmap_align: 5388f1934ceSPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5398f1934ceSPierre Ossman 128 * 4, direction); 5408f1934ceSPierre Ossman fail: 5418f1934ceSPierre Ossman return -EINVAL; 5422134a922SPierre Ossman } 5432134a922SPierre Ossman 5442134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 5452134a922SPierre Ossman struct mmc_data *data) 5462134a922SPierre Ossman { 5472134a922SPierre Ossman int direction; 5482134a922SPierre Ossman 5492134a922SPierre Ossman struct scatterlist *sg; 5502134a922SPierre Ossman int i, size; 5512134a922SPierre Ossman u8 *align; 5522134a922SPierre Ossman char *buffer; 5532134a922SPierre Ossman unsigned long flags; 5542134a922SPierre Ossman 5552134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 5562134a922SPierre Ossman direction = DMA_FROM_DEVICE; 5572134a922SPierre Ossman else 5582134a922SPierre Ossman direction = DMA_TO_DEVICE; 5592134a922SPierre Ossman 5602134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 5612134a922SPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 5622134a922SPierre Ossman 5632134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5642134a922SPierre Ossman 128 * 4, direction); 5652134a922SPierre Ossman 5662134a922SPierre Ossman if (data->flags & MMC_DATA_READ) { 5672134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 5682134a922SPierre Ossman data->sg_len, direction); 5692134a922SPierre Ossman 5702134a922SPierre Ossman align = host->align_buffer; 5712134a922SPierre Ossman 5722134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5732134a922SPierre Ossman if (sg_dma_address(sg) & 0x3) { 5742134a922SPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 5752134a922SPierre Ossman 5762134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5776cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5782134a922SPierre Ossman memcpy(buffer, align, size); 5792134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5802134a922SPierre Ossman 5812134a922SPierre Ossman align += 4; 5822134a922SPierre Ossman } 5832134a922SPierre Ossman } 5842134a922SPierre Ossman } 5852134a922SPierre Ossman 5862134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5872134a922SPierre Ossman data->sg_len, direction); 5882134a922SPierre Ossman } 5892134a922SPierre Ossman 590ee53ab5dSPierre Ossman static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) 5911c6a0718SPierre Ossman { 5921c6a0718SPierre Ossman u8 count; 5931c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 5941c6a0718SPierre Ossman 595ee53ab5dSPierre Ossman /* 596ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 597ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 598ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 599ee53ab5dSPierre Ossman * timeout value. 600ee53ab5dSPierre Ossman */ 60111a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 602ee53ab5dSPierre Ossman return 0xE; 603e538fbe8SPierre Ossman 6041c6a0718SPierre Ossman /* timeout in us */ 6051c6a0718SPierre Ossman target_timeout = data->timeout_ns / 1000 + 6061c6a0718SPierre Ossman data->timeout_clks / host->clock; 6071c6a0718SPierre Ossman 60881b39802SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) 60981b39802SAnton Vorontsov host->timeout_clk = host->clock / 1000; 61081b39802SAnton Vorontsov 6111c6a0718SPierre Ossman /* 6121c6a0718SPierre Ossman * Figure out needed cycles. 6131c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 6141c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 6151c6a0718SPierre Ossman * minimum resolution of 6 bits: 6161c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 6171c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 6181c6a0718SPierre Ossman * => 6191c6a0718SPierre Ossman * (1) / (2) > 2^6 6201c6a0718SPierre Ossman */ 6211c6a0718SPierre Ossman count = 0; 6221c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 6231c6a0718SPierre Ossman while (current_timeout < target_timeout) { 6241c6a0718SPierre Ossman count++; 6251c6a0718SPierre Ossman current_timeout <<= 1; 6261c6a0718SPierre Ossman if (count >= 0xF) 6271c6a0718SPierre Ossman break; 6281c6a0718SPierre Ossman } 6291c6a0718SPierre Ossman 6301c6a0718SPierre Ossman if (count >= 0xF) { 6311c6a0718SPierre Ossman printk(KERN_WARNING "%s: Too large timeout requested!\n", 6321c6a0718SPierre Ossman mmc_hostname(host->mmc)); 6331c6a0718SPierre Ossman count = 0xE; 6341c6a0718SPierre Ossman } 6351c6a0718SPierre Ossman 636ee53ab5dSPierre Ossman return count; 637ee53ab5dSPierre Ossman } 638ee53ab5dSPierre Ossman 6396aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 6406aa943abSAnton Vorontsov { 6416aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 6426aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 6436aa943abSAnton Vorontsov 6446aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 6456aa943abSAnton Vorontsov sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 6466aa943abSAnton Vorontsov else 6476aa943abSAnton Vorontsov sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); 6486aa943abSAnton Vorontsov } 6496aa943abSAnton Vorontsov 650ee53ab5dSPierre Ossman static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 651ee53ab5dSPierre Ossman { 652ee53ab5dSPierre Ossman u8 count; 6532134a922SPierre Ossman u8 ctrl; 6548f1934ceSPierre Ossman int ret; 655ee53ab5dSPierre Ossman 656ee53ab5dSPierre Ossman WARN_ON(host->data); 657ee53ab5dSPierre Ossman 658ee53ab5dSPierre Ossman if (data == NULL) 659ee53ab5dSPierre Ossman return; 660ee53ab5dSPierre Ossman 661ee53ab5dSPierre Ossman /* Sanity checks */ 662ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 663ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 664ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 665ee53ab5dSPierre Ossman 666ee53ab5dSPierre Ossman host->data = data; 667ee53ab5dSPierre Ossman host->data_early = 0; 668ee53ab5dSPierre Ossman 669ee53ab5dSPierre Ossman count = sdhci_calc_timeout(host, data); 6704e4141a5SAnton Vorontsov sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 6711c6a0718SPierre Ossman 672a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) 673c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 674c9fddbc4SPierre Ossman 6752134a922SPierre Ossman /* 6762134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 6772134a922SPierre Ossman * scatterlist. 6782134a922SPierre Ossman */ 6792134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6802134a922SPierre Ossman int broken, i; 6812134a922SPierre Ossman struct scatterlist *sg; 6822134a922SPierre Ossman 6832134a922SPierre Ossman broken = 0; 6842134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6852134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 6862134a922SPierre Ossman broken = 1; 6872134a922SPierre Ossman } else { 6882134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 6892134a922SPierre Ossman broken = 1; 6902134a922SPierre Ossman } 6912134a922SPierre Ossman 6922134a922SPierre Ossman if (unlikely(broken)) { 6932134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6942134a922SPierre Ossman if (sg->length & 0x3) { 6952134a922SPierre Ossman DBG("Reverting to PIO because of " 6962134a922SPierre Ossman "transfer size (%d)\n", 6972134a922SPierre Ossman sg->length); 698c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6992134a922SPierre Ossman break; 7002134a922SPierre Ossman } 7012134a922SPierre Ossman } 7022134a922SPierre Ossman } 703c9fddbc4SPierre Ossman } 704c9fddbc4SPierre Ossman 705c9fddbc4SPierre Ossman /* 706c9fddbc4SPierre Ossman * The assumption here being that alignment is the same after 707c9fddbc4SPierre Ossman * translation to device address space. 708c9fddbc4SPierre Ossman */ 7092134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7102134a922SPierre Ossman int broken, i; 7112134a922SPierre Ossman struct scatterlist *sg; 7122134a922SPierre Ossman 7132134a922SPierre Ossman broken = 0; 7142134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7152134a922SPierre Ossman /* 7162134a922SPierre Ossman * As we use 3 byte chunks to work around 7172134a922SPierre Ossman * alignment problems, we need to check this 7182134a922SPierre Ossman * quirk. 7192134a922SPierre Ossman */ 7202134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7212134a922SPierre Ossman broken = 1; 7222134a922SPierre Ossman } else { 7232134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 7242134a922SPierre Ossman broken = 1; 7252134a922SPierre Ossman } 7262134a922SPierre Ossman 7272134a922SPierre Ossman if (unlikely(broken)) { 7282134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7292134a922SPierre Ossman if (sg->offset & 0x3) { 7302134a922SPierre Ossman DBG("Reverting to PIO because of " 7312134a922SPierre Ossman "bad alignment\n"); 732c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7332134a922SPierre Ossman break; 7342134a922SPierre Ossman } 7352134a922SPierre Ossman } 7362134a922SPierre Ossman } 7372134a922SPierre Ossman } 7382134a922SPierre Ossman 7398f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7408f1934ceSPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7418f1934ceSPierre Ossman ret = sdhci_adma_table_pre(host, data); 7428f1934ceSPierre Ossman if (ret) { 7438f1934ceSPierre Ossman /* 7448f1934ceSPierre Ossman * This only happens when someone fed 7458f1934ceSPierre Ossman * us an invalid request. 7468f1934ceSPierre Ossman */ 7478f1934ceSPierre Ossman WARN_ON(1); 748ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7498f1934ceSPierre Ossman } else { 7504e4141a5SAnton Vorontsov sdhci_writel(host, host->adma_addr, 7514e4141a5SAnton Vorontsov SDHCI_ADMA_ADDRESS); 7528f1934ceSPierre Ossman } 7538f1934ceSPierre Ossman } else { 754c8b3e02eSTomas Winkler int sg_cnt; 7558f1934ceSPierre Ossman 756c8b3e02eSTomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 7578f1934ceSPierre Ossman data->sg, data->sg_len, 7588f1934ceSPierre Ossman (data->flags & MMC_DATA_READ) ? 7598f1934ceSPierre Ossman DMA_FROM_DEVICE : 7608f1934ceSPierre Ossman DMA_TO_DEVICE); 761c8b3e02eSTomas Winkler if (sg_cnt == 0) { 7628f1934ceSPierre Ossman /* 7638f1934ceSPierre Ossman * This only happens when someone fed 7648f1934ceSPierre Ossman * us an invalid request. 7658f1934ceSPierre Ossman */ 7668f1934ceSPierre Ossman WARN_ON(1); 767ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7688f1934ceSPierre Ossman } else { 769719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 7704e4141a5SAnton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 7714e4141a5SAnton Vorontsov SDHCI_DMA_ADDRESS); 7728f1934ceSPierre Ossman } 7738f1934ceSPierre Ossman } 7748f1934ceSPierre Ossman } 7758f1934ceSPierre Ossman 7762134a922SPierre Ossman /* 7772134a922SPierre Ossman * Always adjust the DMA selection as some controllers 7782134a922SPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 7792134a922SPierre Ossman * is ADMA. 7802134a922SPierre Ossman */ 7812134a922SPierre Ossman if (host->version >= SDHCI_SPEC_200) { 7824e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 7832134a922SPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 7842134a922SPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 7852134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) 7862134a922SPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 7872134a922SPierre Ossman else 7882134a922SPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 7894e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 790c9fddbc4SPierre Ossman } 791c9fddbc4SPierre Ossman 7928f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 793da60a91dSSebastian Andrzej Siewior int flags; 794da60a91dSSebastian Andrzej Siewior 795da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 796da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 797da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 798da60a91dSSebastian Andrzej Siewior else 799da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 800da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 8017659150cSPierre Ossman host->blocks = data->blocks; 8021c6a0718SPierre Ossman } 8031c6a0718SPierre Ossman 8046aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 8056aa943abSAnton Vorontsov 8061c6a0718SPierre Ossman /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 8074e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE); 8084e4141a5SAnton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 8091c6a0718SPierre Ossman } 8101c6a0718SPierre Ossman 8111c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 8121c6a0718SPierre Ossman struct mmc_data *data) 8131c6a0718SPierre Ossman { 8141c6a0718SPierre Ossman u16 mode; 8151c6a0718SPierre Ossman 8161c6a0718SPierre Ossman if (data == NULL) 8171c6a0718SPierre Ossman return; 8181c6a0718SPierre Ossman 819e538fbe8SPierre Ossman WARN_ON(!host->data); 820e538fbe8SPierre Ossman 8211c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 822c4512f79SJerry Huang if (data->blocks > 1) { 823c4512f79SJerry Huang if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 824c4512f79SJerry Huang mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12; 825c4512f79SJerry Huang else 8261c6a0718SPierre Ossman mode |= SDHCI_TRNS_MULTI; 827c4512f79SJerry Huang } 8281c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 8291c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 830c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 8311c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 8321c6a0718SPierre Ossman 8334e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 8341c6a0718SPierre Ossman } 8351c6a0718SPierre Ossman 8361c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *host) 8371c6a0718SPierre Ossman { 8381c6a0718SPierre Ossman struct mmc_data *data; 8391c6a0718SPierre Ossman 8401c6a0718SPierre Ossman BUG_ON(!host->data); 8411c6a0718SPierre Ossman 8421c6a0718SPierre Ossman data = host->data; 8431c6a0718SPierre Ossman host->data = NULL; 8441c6a0718SPierre Ossman 845c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 8462134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 8472134a922SPierre Ossman sdhci_adma_table_post(host, data); 8482134a922SPierre Ossman else { 8492134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 8502134a922SPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 851b8c86fc5SPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 8521c6a0718SPierre Ossman } 8532134a922SPierre Ossman } 8541c6a0718SPierre Ossman 8551c6a0718SPierre Ossman /* 856c9b74c5bSPierre Ossman * The specification states that the block count register must 857c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 858c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 859c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 860c9b74c5bSPierre Ossman * in the event of an error. 8611c6a0718SPierre Ossman */ 862c9b74c5bSPierre Ossman if (data->error) 863c9b74c5bSPierre Ossman data->bytes_xfered = 0; 8641c6a0718SPierre Ossman else 865c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 8661c6a0718SPierre Ossman 8671c6a0718SPierre Ossman if (data->stop) { 8681c6a0718SPierre Ossman /* 8691c6a0718SPierre Ossman * The controller needs a reset of internal state machines 8701c6a0718SPierre Ossman * upon error conditions. 8711c6a0718SPierre Ossman */ 87217b0429dSPierre Ossman if (data->error) { 8731c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 8741c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 8751c6a0718SPierre Ossman } 8761c6a0718SPierre Ossman 8771c6a0718SPierre Ossman sdhci_send_command(host, data->stop); 8781c6a0718SPierre Ossman } else 8791c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8801c6a0718SPierre Ossman } 8811c6a0718SPierre Ossman 8821c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 8831c6a0718SPierre Ossman { 8841c6a0718SPierre Ossman int flags; 8851c6a0718SPierre Ossman u32 mask; 8861c6a0718SPierre Ossman unsigned long timeout; 8871c6a0718SPierre Ossman 8881c6a0718SPierre Ossman WARN_ON(host->cmd); 8891c6a0718SPierre Ossman 8901c6a0718SPierre Ossman /* Wait max 10 ms */ 8911c6a0718SPierre Ossman timeout = 10; 8921c6a0718SPierre Ossman 8931c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 8941c6a0718SPierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 8951c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 8961c6a0718SPierre Ossman 8971c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 8981c6a0718SPierre Ossman though they might use busy signaling */ 8991c6a0718SPierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 9001c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 9011c6a0718SPierre Ossman 9024e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 9031c6a0718SPierre Ossman if (timeout == 0) { 9041c6a0718SPierre Ossman printk(KERN_ERR "%s: Controller never released " 9051c6a0718SPierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 9061c6a0718SPierre Ossman sdhci_dumpregs(host); 90717b0429dSPierre Ossman cmd->error = -EIO; 9081c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 9091c6a0718SPierre Ossman return; 9101c6a0718SPierre Ossman } 9111c6a0718SPierre Ossman timeout--; 9121c6a0718SPierre Ossman mdelay(1); 9131c6a0718SPierre Ossman } 9141c6a0718SPierre Ossman 9151c6a0718SPierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 9161c6a0718SPierre Ossman 9171c6a0718SPierre Ossman host->cmd = cmd; 9181c6a0718SPierre Ossman 9191c6a0718SPierre Ossman sdhci_prepare_data(host, cmd->data); 9201c6a0718SPierre Ossman 9214e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 9221c6a0718SPierre Ossman 9231c6a0718SPierre Ossman sdhci_set_transfer_mode(host, cmd->data); 9241c6a0718SPierre Ossman 9251c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 9261c6a0718SPierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 9271c6a0718SPierre Ossman mmc_hostname(host->mmc)); 92817b0429dSPierre Ossman cmd->error = -EINVAL; 9291c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 9301c6a0718SPierre Ossman return; 9311c6a0718SPierre Ossman } 9321c6a0718SPierre Ossman 9331c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 9341c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 9351c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 9361c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 9371c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 9381c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 9391c6a0718SPierre Ossman else 9401c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 9411c6a0718SPierre Ossman 9421c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 9431c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 9441c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 9451c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 9461c6a0718SPierre Ossman if (cmd->data) 9471c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 9481c6a0718SPierre Ossman 9494e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 9501c6a0718SPierre Ossman } 9511c6a0718SPierre Ossman 9521c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 9531c6a0718SPierre Ossman { 9541c6a0718SPierre Ossman int i; 9551c6a0718SPierre Ossman 9561c6a0718SPierre Ossman BUG_ON(host->cmd == NULL); 9571c6a0718SPierre Ossman 9581c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 9591c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_136) { 9601c6a0718SPierre Ossman /* CRC is stripped so we need to do some shifting. */ 9611c6a0718SPierre Ossman for (i = 0;i < 4;i++) { 9624e4141a5SAnton Vorontsov host->cmd->resp[i] = sdhci_readl(host, 9631c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 9641c6a0718SPierre Ossman if (i != 3) 9651c6a0718SPierre Ossman host->cmd->resp[i] |= 9664e4141a5SAnton Vorontsov sdhci_readb(host, 9671c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 9681c6a0718SPierre Ossman } 9691c6a0718SPierre Ossman } else { 9704e4141a5SAnton Vorontsov host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 9711c6a0718SPierre Ossman } 9721c6a0718SPierre Ossman } 9731c6a0718SPierre Ossman 97417b0429dSPierre Ossman host->cmd->error = 0; 9751c6a0718SPierre Ossman 976e538fbe8SPierre Ossman if (host->data && host->data_early) 977e538fbe8SPierre Ossman sdhci_finish_data(host); 978e538fbe8SPierre Ossman 979e538fbe8SPierre Ossman if (!host->cmd->data) 9801c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 9811c6a0718SPierre Ossman 9821c6a0718SPierre Ossman host->cmd = NULL; 9831c6a0718SPierre Ossman } 9841c6a0718SPierre Ossman 9851c6a0718SPierre Ossman static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 9861c6a0718SPierre Ossman { 9871c6a0718SPierre Ossman int div; 9881c6a0718SPierre Ossman u16 clk; 9891c6a0718SPierre Ossman unsigned long timeout; 9901c6a0718SPierre Ossman 9911c6a0718SPierre Ossman if (clock == host->clock) 9921c6a0718SPierre Ossman return; 9931c6a0718SPierre Ossman 9948114634cSAnton Vorontsov if (host->ops->set_clock) { 9958114634cSAnton Vorontsov host->ops->set_clock(host, clock); 9968114634cSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) 9978114634cSAnton Vorontsov return; 9988114634cSAnton Vorontsov } 9998114634cSAnton Vorontsov 10004e4141a5SAnton Vorontsov sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 10011c6a0718SPierre Ossman 10021c6a0718SPierre Ossman if (clock == 0) 10031c6a0718SPierre Ossman goto out; 10041c6a0718SPierre Ossman 100585105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 100685105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 100785105c53SZhangfei Gao if (host->max_clk <= clock) 100885105c53SZhangfei Gao div = 1; 100985105c53SZhangfei Gao else { 10100397526dSZhangfei Gao for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { 101185105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 101285105c53SZhangfei Gao break; 101385105c53SZhangfei Gao } 101485105c53SZhangfei Gao } 101585105c53SZhangfei Gao } else { 101685105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 10170397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 10181c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 10191c6a0718SPierre Ossman break; 10201c6a0718SPierre Ossman } 102185105c53SZhangfei Gao } 10221c6a0718SPierre Ossman div >>= 1; 10231c6a0718SPierre Ossman 102485105c53SZhangfei Gao clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 102585105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 102685105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 10271c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 10284e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 10291c6a0718SPierre Ossman 103027f6cb16SChris Ball /* Wait max 20 ms */ 103127f6cb16SChris Ball timeout = 20; 10324e4141a5SAnton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 10331c6a0718SPierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 10341c6a0718SPierre Ossman if (timeout == 0) { 10351c6a0718SPierre Ossman printk(KERN_ERR "%s: Internal clock never " 10361c6a0718SPierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 10371c6a0718SPierre Ossman sdhci_dumpregs(host); 10381c6a0718SPierre Ossman return; 10391c6a0718SPierre Ossman } 10401c6a0718SPierre Ossman timeout--; 10411c6a0718SPierre Ossman mdelay(1); 10421c6a0718SPierre Ossman } 10431c6a0718SPierre Ossman 10441c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 10454e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 10461c6a0718SPierre Ossman 10471c6a0718SPierre Ossman out: 10481c6a0718SPierre Ossman host->clock = clock; 10491c6a0718SPierre Ossman } 10501c6a0718SPierre Ossman 10511c6a0718SPierre Ossman static void sdhci_set_power(struct sdhci_host *host, unsigned short power) 10521c6a0718SPierre Ossman { 10538364248aSGiuseppe Cavallaro u8 pwr = 0; 10541c6a0718SPierre Ossman 10558364248aSGiuseppe Cavallaro if (power != (unsigned short)-1) { 1056ae628903SPierre Ossman switch (1 << power) { 1057ae628903SPierre Ossman case MMC_VDD_165_195: 1058ae628903SPierre Ossman pwr = SDHCI_POWER_180; 1059ae628903SPierre Ossman break; 1060ae628903SPierre Ossman case MMC_VDD_29_30: 1061ae628903SPierre Ossman case MMC_VDD_30_31: 1062ae628903SPierre Ossman pwr = SDHCI_POWER_300; 1063ae628903SPierre Ossman break; 1064ae628903SPierre Ossman case MMC_VDD_32_33: 1065ae628903SPierre Ossman case MMC_VDD_33_34: 1066ae628903SPierre Ossman pwr = SDHCI_POWER_330; 1067ae628903SPierre Ossman break; 1068ae628903SPierre Ossman default: 1069ae628903SPierre Ossman BUG(); 1070ae628903SPierre Ossman } 1071ae628903SPierre Ossman } 1072ae628903SPierre Ossman 1073ae628903SPierre Ossman if (host->pwr == pwr) 10741c6a0718SPierre Ossman return; 10751c6a0718SPierre Ossman 1076ae628903SPierre Ossman host->pwr = pwr; 1077ae628903SPierre Ossman 1078ae628903SPierre Ossman if (pwr == 0) { 10794e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1080ae628903SPierre Ossman return; 10811c6a0718SPierre Ossman } 10821c6a0718SPierre Ossman 10831c6a0718SPierre Ossman /* 10841c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 10851c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 10861c6a0718SPierre Ossman */ 1087b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 10884e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 10891c6a0718SPierre Ossman 1090e08c1694SAndres Salomon /* 1091c71f6512SAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 1092e08c1694SAndres Salomon * and set turn on power at the same time, so set the voltage first. 1093e08c1694SAndres Salomon */ 109411a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 10954e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 10961c6a0718SPierre Ossman 1097ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 1098ae628903SPierre Ossman 1099ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1100557b0697SHarald Welte 1101557b0697SHarald Welte /* 1102557b0697SHarald Welte * Some controllers need an extra 10ms delay of 10ms before they 1103557b0697SHarald Welte * can apply clock after applying power 1104557b0697SHarald Welte */ 110511a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1106557b0697SHarald Welte mdelay(10); 11071c6a0718SPierre Ossman } 11081c6a0718SPierre Ossman 11091c6a0718SPierre Ossman /*****************************************************************************\ 11101c6a0718SPierre Ossman * * 11111c6a0718SPierre Ossman * MMC callbacks * 11121c6a0718SPierre Ossman * * 11131c6a0718SPierre Ossman \*****************************************************************************/ 11141c6a0718SPierre Ossman 11151c6a0718SPierre Ossman static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 11161c6a0718SPierre Ossman { 11171c6a0718SPierre Ossman struct sdhci_host *host; 111868d1fb7eSAnton Vorontsov bool present; 11191c6a0718SPierre Ossman unsigned long flags; 11201c6a0718SPierre Ossman 11211c6a0718SPierre Ossman host = mmc_priv(mmc); 11221c6a0718SPierre Ossman 11231c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11241c6a0718SPierre Ossman 11251c6a0718SPierre Ossman WARN_ON(host->mrq != NULL); 11261c6a0718SPierre Ossman 1127f9134319SPierre Ossman #ifndef SDHCI_USE_LEDS_CLASS 11281c6a0718SPierre Ossman sdhci_activate_led(host); 11292f730fecSPierre Ossman #endif 1130c4512f79SJerry Huang if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) { 1131c4512f79SJerry Huang if (mrq->stop) { 1132c4512f79SJerry Huang mrq->data->stop = NULL; 1133c4512f79SJerry Huang mrq->stop = NULL; 1134c4512f79SJerry Huang } 1135c4512f79SJerry Huang } 11361c6a0718SPierre Ossman 11371c6a0718SPierre Ossman host->mrq = mrq; 11381c6a0718SPierre Ossman 113968d1fb7eSAnton Vorontsov /* If polling, assume that the card is always present. */ 114068d1fb7eSAnton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 114168d1fb7eSAnton Vorontsov present = true; 114268d1fb7eSAnton Vorontsov else 114368d1fb7eSAnton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 114468d1fb7eSAnton Vorontsov SDHCI_CARD_PRESENT; 114568d1fb7eSAnton Vorontsov 114668d1fb7eSAnton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 114717b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 11481c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 11491c6a0718SPierre Ossman } else 11501c6a0718SPierre Ossman sdhci_send_command(host, mrq->cmd); 11511c6a0718SPierre Ossman 11521c6a0718SPierre Ossman mmiowb(); 11531c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 11541c6a0718SPierre Ossman } 11551c6a0718SPierre Ossman 11561c6a0718SPierre Ossman static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 11571c6a0718SPierre Ossman { 11581c6a0718SPierre Ossman struct sdhci_host *host; 11591c6a0718SPierre Ossman unsigned long flags; 11601c6a0718SPierre Ossman u8 ctrl; 11611c6a0718SPierre Ossman 11621c6a0718SPierre Ossman host = mmc_priv(mmc); 11631c6a0718SPierre Ossman 11641c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11651c6a0718SPierre Ossman 11661e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11671e72859eSPierre Ossman goto out; 11681e72859eSPierre Ossman 11691c6a0718SPierre Ossman /* 11701c6a0718SPierre Ossman * Reset the chip on each power off. 11711c6a0718SPierre Ossman * Should clear out any weird states. 11721c6a0718SPierre Ossman */ 11731c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 11744e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 11757260cf5eSAnton Vorontsov sdhci_reinit(host); 11761c6a0718SPierre Ossman } 11771c6a0718SPierre Ossman 11781c6a0718SPierre Ossman sdhci_set_clock(host, ios->clock); 11791c6a0718SPierre Ossman 11801c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) 11811c6a0718SPierre Ossman sdhci_set_power(host, -1); 11821c6a0718SPierre Ossman else 11831c6a0718SPierre Ossman sdhci_set_power(host, ios->vdd); 11841c6a0718SPierre Ossman 1185643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 1186643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1187643a81ffSPhilip Rakity 11884e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 11891c6a0718SPierre Ossman 1190ae6d6c92SKyungmin Park if (ios->bus_width == MMC_BUS_WIDTH_8) 1191ae6d6c92SKyungmin Park ctrl |= SDHCI_CTRL_8BITBUS; 1192ae6d6c92SKyungmin Park else 1193ae6d6c92SKyungmin Park ctrl &= ~SDHCI_CTRL_8BITBUS; 1194ae6d6c92SKyungmin Park 11951c6a0718SPierre Ossman if (ios->bus_width == MMC_BUS_WIDTH_4) 11961c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_4BITBUS; 11971c6a0718SPierre Ossman else 11981c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_4BITBUS; 11991c6a0718SPierre Ossman 12003ab9c8daSPhilip Rakity if ((ios->timing == MMC_TIMING_SD_HS || 12013ab9c8daSPhilip Rakity ios->timing == MMC_TIMING_MMC_HS) 12023ab9c8daSPhilip Rakity && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) 12031c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 12041c6a0718SPierre Ossman else 12051c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 12061c6a0718SPierre Ossman 12074e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 12081c6a0718SPierre Ossman 1209b8352260SLeandro Dorileo /* 1210b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1211b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1212b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 1213b8352260SLeandro Dorileo */ 1214b8c86fc5SPierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1215b8352260SLeandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1216b8352260SLeandro Dorileo 12171e72859eSPierre Ossman out: 12181c6a0718SPierre Ossman mmiowb(); 12191c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12201c6a0718SPierre Ossman } 12211c6a0718SPierre Ossman 12221c6a0718SPierre Ossman static int sdhci_get_ro(struct mmc_host *mmc) 12231c6a0718SPierre Ossman { 12241c6a0718SPierre Ossman struct sdhci_host *host; 12251c6a0718SPierre Ossman unsigned long flags; 1226*2dfb579cSWolfram Sang int is_readonly; 12271c6a0718SPierre Ossman 12281c6a0718SPierre Ossman host = mmc_priv(mmc); 12291c6a0718SPierre Ossman 12301c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 12311c6a0718SPierre Ossman 12321e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 1233*2dfb579cSWolfram Sang is_readonly = 0; 1234*2dfb579cSWolfram Sang else if (host->ops->get_ro) 1235*2dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 12361e72859eSPierre Ossman else 1237*2dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 1238*2dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 12391c6a0718SPierre Ossman 12401c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12411c6a0718SPierre Ossman 1242*2dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 1243*2dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 1244*2dfb579cSWolfram Sang !is_readonly : is_readonly; 12451c6a0718SPierre Ossman } 12461c6a0718SPierre Ossman 1247f75979b7SPierre Ossman static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1248f75979b7SPierre Ossman { 1249f75979b7SPierre Ossman struct sdhci_host *host; 1250f75979b7SPierre Ossman unsigned long flags; 1251f75979b7SPierre Ossman 1252f75979b7SPierre Ossman host = mmc_priv(mmc); 1253f75979b7SPierre Ossman 1254f75979b7SPierre Ossman spin_lock_irqsave(&host->lock, flags); 1255f75979b7SPierre Ossman 12561e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 12571e72859eSPierre Ossman goto out; 12581e72859eSPierre Ossman 1259f75979b7SPierre Ossman if (enable) 12607260cf5eSAnton Vorontsov sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); 12617260cf5eSAnton Vorontsov else 12627260cf5eSAnton Vorontsov sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); 12631e72859eSPierre Ossman out: 1264f75979b7SPierre Ossman mmiowb(); 1265f75979b7SPierre Ossman 1266f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1267f75979b7SPierre Ossman } 1268f75979b7SPierre Ossman 12691c6a0718SPierre Ossman static const struct mmc_host_ops sdhci_ops = { 12701c6a0718SPierre Ossman .request = sdhci_request, 12711c6a0718SPierre Ossman .set_ios = sdhci_set_ios, 12721c6a0718SPierre Ossman .get_ro = sdhci_get_ro, 1273f75979b7SPierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 12741c6a0718SPierre Ossman }; 12751c6a0718SPierre Ossman 12761c6a0718SPierre Ossman /*****************************************************************************\ 12771c6a0718SPierre Ossman * * 12781c6a0718SPierre Ossman * Tasklets * 12791c6a0718SPierre Ossman * * 12801c6a0718SPierre Ossman \*****************************************************************************/ 12811c6a0718SPierre Ossman 12821c6a0718SPierre Ossman static void sdhci_tasklet_card(unsigned long param) 12831c6a0718SPierre Ossman { 12841c6a0718SPierre Ossman struct sdhci_host *host; 12851c6a0718SPierre Ossman unsigned long flags; 12861c6a0718SPierre Ossman 12871c6a0718SPierre Ossman host = (struct sdhci_host*)param; 12881c6a0718SPierre Ossman 12891c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 12901c6a0718SPierre Ossman 12914e4141a5SAnton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 12921c6a0718SPierre Ossman if (host->mrq) { 12931c6a0718SPierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 12941c6a0718SPierre Ossman mmc_hostname(host->mmc)); 12951c6a0718SPierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 12961c6a0718SPierre Ossman mmc_hostname(host->mmc)); 12971c6a0718SPierre Ossman 12981c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 12991c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 13001c6a0718SPierre Ossman 130117b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 13021c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 13031c6a0718SPierre Ossman } 13041c6a0718SPierre Ossman } 13051c6a0718SPierre Ossman 13061c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 13071c6a0718SPierre Ossman 130804cf585dSPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 13091c6a0718SPierre Ossman } 13101c6a0718SPierre Ossman 13111c6a0718SPierre Ossman static void sdhci_tasklet_finish(unsigned long param) 13121c6a0718SPierre Ossman { 13131c6a0718SPierre Ossman struct sdhci_host *host; 13141c6a0718SPierre Ossman unsigned long flags; 13151c6a0718SPierre Ossman struct mmc_request *mrq; 13161c6a0718SPierre Ossman 13171c6a0718SPierre Ossman host = (struct sdhci_host*)param; 13181c6a0718SPierre Ossman 13191c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 13201c6a0718SPierre Ossman 13211c6a0718SPierre Ossman del_timer(&host->timer); 13221c6a0718SPierre Ossman 13231c6a0718SPierre Ossman mrq = host->mrq; 13241c6a0718SPierre Ossman 13251c6a0718SPierre Ossman /* 13261c6a0718SPierre Ossman * The controller needs a reset of internal state machines 13271c6a0718SPierre Ossman * upon error conditions. 13281c6a0718SPierre Ossman */ 13291e72859eSPierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 13301e72859eSPierre Ossman (mrq->cmd->error || 133117b0429dSPierre Ossman (mrq->data && (mrq->data->error || 133284c46a53SPierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 13331e72859eSPierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 13341c6a0718SPierre Ossman 13351c6a0718SPierre Ossman /* Some controllers need this kick or reset won't work here */ 1336b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 13371c6a0718SPierre Ossman unsigned int clock; 13381c6a0718SPierre Ossman 13391c6a0718SPierre Ossman /* This is to force an update */ 13401c6a0718SPierre Ossman clock = host->clock; 13411c6a0718SPierre Ossman host->clock = 0; 13421c6a0718SPierre Ossman sdhci_set_clock(host, clock); 13431c6a0718SPierre Ossman } 13441c6a0718SPierre Ossman 13451c6a0718SPierre Ossman /* Spec says we should do both at the same time, but Ricoh 13461c6a0718SPierre Ossman controllers do not like that. */ 13471c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 13481c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 13491c6a0718SPierre Ossman } 13501c6a0718SPierre Ossman 13511c6a0718SPierre Ossman host->mrq = NULL; 13521c6a0718SPierre Ossman host->cmd = NULL; 13531c6a0718SPierre Ossman host->data = NULL; 13541c6a0718SPierre Ossman 1355f9134319SPierre Ossman #ifndef SDHCI_USE_LEDS_CLASS 13561c6a0718SPierre Ossman sdhci_deactivate_led(host); 13572f730fecSPierre Ossman #endif 13581c6a0718SPierre Ossman 13591c6a0718SPierre Ossman mmiowb(); 13601c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 13611c6a0718SPierre Ossman 13621c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 13631c6a0718SPierre Ossman } 13641c6a0718SPierre Ossman 13651c6a0718SPierre Ossman static void sdhci_timeout_timer(unsigned long data) 13661c6a0718SPierre Ossman { 13671c6a0718SPierre Ossman struct sdhci_host *host; 13681c6a0718SPierre Ossman unsigned long flags; 13691c6a0718SPierre Ossman 13701c6a0718SPierre Ossman host = (struct sdhci_host*)data; 13711c6a0718SPierre Ossman 13721c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 13731c6a0718SPierre Ossman 13741c6a0718SPierre Ossman if (host->mrq) { 13751c6a0718SPierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 13761c6a0718SPierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 13771c6a0718SPierre Ossman sdhci_dumpregs(host); 13781c6a0718SPierre Ossman 13791c6a0718SPierre Ossman if (host->data) { 138017b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 13811c6a0718SPierre Ossman sdhci_finish_data(host); 13821c6a0718SPierre Ossman } else { 13831c6a0718SPierre Ossman if (host->cmd) 138417b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 13851c6a0718SPierre Ossman else 138617b0429dSPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 13871c6a0718SPierre Ossman 13881c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 13891c6a0718SPierre Ossman } 13901c6a0718SPierre Ossman } 13911c6a0718SPierre Ossman 13921c6a0718SPierre Ossman mmiowb(); 13931c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 13941c6a0718SPierre Ossman } 13951c6a0718SPierre Ossman 13961c6a0718SPierre Ossman /*****************************************************************************\ 13971c6a0718SPierre Ossman * * 13981c6a0718SPierre Ossman * Interrupt handling * 13991c6a0718SPierre Ossman * * 14001c6a0718SPierre Ossman \*****************************************************************************/ 14011c6a0718SPierre Ossman 14021c6a0718SPierre Ossman static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 14031c6a0718SPierre Ossman { 14041c6a0718SPierre Ossman BUG_ON(intmask == 0); 14051c6a0718SPierre Ossman 14061c6a0718SPierre Ossman if (!host->cmd) { 1407b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1408b67ac3f3SPierre Ossman "though no command operation was in progress.\n", 1409b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 14101c6a0718SPierre Ossman sdhci_dumpregs(host); 14111c6a0718SPierre Ossman return; 14121c6a0718SPierre Ossman } 14131c6a0718SPierre Ossman 14141c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 141517b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 141617b0429dSPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 141717b0429dSPierre Ossman SDHCI_INT_INDEX)) 141817b0429dSPierre Ossman host->cmd->error = -EILSEQ; 14191c6a0718SPierre Ossman 1420e809517fSPierre Ossman if (host->cmd->error) { 14211c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 1422e809517fSPierre Ossman return; 1423e809517fSPierre Ossman } 1424e809517fSPierre Ossman 1425e809517fSPierre Ossman /* 1426e809517fSPierre Ossman * The host can send and interrupt when the busy state has 1427e809517fSPierre Ossman * ended, allowing us to wait without wasting CPU cycles. 1428e809517fSPierre Ossman * Unfortunately this is overloaded on the "data complete" 1429e809517fSPierre Ossman * interrupt, so we need to take some care when handling 1430e809517fSPierre Ossman * it. 1431e809517fSPierre Ossman * 1432e809517fSPierre Ossman * Note: The 1.0 specification is a bit ambiguous about this 1433e809517fSPierre Ossman * feature so there might be some problems with older 1434e809517fSPierre Ossman * controllers. 1435e809517fSPierre Ossman */ 1436e809517fSPierre Ossman if (host->cmd->flags & MMC_RSP_BUSY) { 1437e809517fSPierre Ossman if (host->cmd->data) 1438e809517fSPierre Ossman DBG("Cannot wait for busy signal when also " 1439e809517fSPierre Ossman "doing a data transfer"); 1440f945405cSBen Dooks else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 1441e809517fSPierre Ossman return; 1442f945405cSBen Dooks 1443f945405cSBen Dooks /* The controller does not support the end-of-busy IRQ, 1444f945405cSBen Dooks * fall through and take the SDHCI_INT_RESPONSE */ 1445e809517fSPierre Ossman } 1446e809517fSPierre Ossman 1447e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 144843b58b36SPierre Ossman sdhci_finish_command(host); 14491c6a0718SPierre Ossman } 14501c6a0718SPierre Ossman 14510957c333SGeorge G. Davis #ifdef CONFIG_MMC_DEBUG 14526882a8c0SBen Dooks static void sdhci_show_adma_error(struct sdhci_host *host) 14536882a8c0SBen Dooks { 14546882a8c0SBen Dooks const char *name = mmc_hostname(host->mmc); 14556882a8c0SBen Dooks u8 *desc = host->adma_desc; 14566882a8c0SBen Dooks __le32 *dma; 14576882a8c0SBen Dooks __le16 *len; 14586882a8c0SBen Dooks u8 attr; 14596882a8c0SBen Dooks 14606882a8c0SBen Dooks sdhci_dumpregs(host); 14616882a8c0SBen Dooks 14626882a8c0SBen Dooks while (true) { 14636882a8c0SBen Dooks dma = (__le32 *)(desc + 4); 14646882a8c0SBen Dooks len = (__le16 *)(desc + 2); 14656882a8c0SBen Dooks attr = *desc; 14666882a8c0SBen Dooks 14676882a8c0SBen Dooks DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 14686882a8c0SBen Dooks name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); 14696882a8c0SBen Dooks 14706882a8c0SBen Dooks desc += 8; 14716882a8c0SBen Dooks 14726882a8c0SBen Dooks if (attr & 2) 14736882a8c0SBen Dooks break; 14746882a8c0SBen Dooks } 14756882a8c0SBen Dooks } 14766882a8c0SBen Dooks #else 14776882a8c0SBen Dooks static void sdhci_show_adma_error(struct sdhci_host *host) { } 14786882a8c0SBen Dooks #endif 14796882a8c0SBen Dooks 14801c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 14811c6a0718SPierre Ossman { 14821c6a0718SPierre Ossman BUG_ON(intmask == 0); 14831c6a0718SPierre Ossman 14841c6a0718SPierre Ossman if (!host->data) { 14851c6a0718SPierre Ossman /* 1486e809517fSPierre Ossman * The "data complete" interrupt is also used to 1487e809517fSPierre Ossman * indicate that a busy state has ended. See comment 1488e809517fSPierre Ossman * above in sdhci_cmd_irq(). 14891c6a0718SPierre Ossman */ 1490e809517fSPierre Ossman if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { 1491e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1492e809517fSPierre Ossman sdhci_finish_command(host); 14931c6a0718SPierre Ossman return; 1494e809517fSPierre Ossman } 1495e809517fSPierre Ossman } 14961c6a0718SPierre Ossman 1497b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 1498b67ac3f3SPierre Ossman "though no data operation was in progress.\n", 1499b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 15001c6a0718SPierre Ossman sdhci_dumpregs(host); 15011c6a0718SPierre Ossman 15021c6a0718SPierre Ossman return; 15031c6a0718SPierre Ossman } 15041c6a0718SPierre Ossman 15051c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 150617b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 150717b0429dSPierre Ossman else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 150817b0429dSPierre Ossman host->data->error = -EILSEQ; 15096882a8c0SBen Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 15106882a8c0SBen Dooks printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); 15116882a8c0SBen Dooks sdhci_show_adma_error(host); 15122134a922SPierre Ossman host->data->error = -EIO; 15136882a8c0SBen Dooks } 15141c6a0718SPierre Ossman 151517b0429dSPierre Ossman if (host->data->error) 15161c6a0718SPierre Ossman sdhci_finish_data(host); 15171c6a0718SPierre Ossman else { 15181c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 15191c6a0718SPierre Ossman sdhci_transfer_pio(host); 15201c6a0718SPierre Ossman 15216ba736a1SPierre Ossman /* 15226ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 15236ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 15246ba736a1SPierre Ossman * we need to at least restart the transfer. 15256ba736a1SPierre Ossman */ 15266ba736a1SPierre Ossman if (intmask & SDHCI_INT_DMA_END) 15274e4141a5SAnton Vorontsov sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS), 15284e4141a5SAnton Vorontsov SDHCI_DMA_ADDRESS); 15296ba736a1SPierre Ossman 1530e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1531e538fbe8SPierre Ossman if (host->cmd) { 1532e538fbe8SPierre Ossman /* 1533e538fbe8SPierre Ossman * Data managed to finish before the 1534e538fbe8SPierre Ossman * command completed. Make sure we do 1535e538fbe8SPierre Ossman * things in the proper order. 1536e538fbe8SPierre Ossman */ 1537e538fbe8SPierre Ossman host->data_early = 1; 1538e538fbe8SPierre Ossman } else { 15391c6a0718SPierre Ossman sdhci_finish_data(host); 15401c6a0718SPierre Ossman } 15411c6a0718SPierre Ossman } 1542e538fbe8SPierre Ossman } 1543e538fbe8SPierre Ossman } 15441c6a0718SPierre Ossman 15451c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 15461c6a0718SPierre Ossman { 15471c6a0718SPierre Ossman irqreturn_t result; 15481c6a0718SPierre Ossman struct sdhci_host* host = dev_id; 15491c6a0718SPierre Ossman u32 intmask; 1550f75979b7SPierre Ossman int cardint = 0; 15511c6a0718SPierre Ossman 15521c6a0718SPierre Ossman spin_lock(&host->lock); 15531c6a0718SPierre Ossman 15544e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 15551c6a0718SPierre Ossman 15561c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 15571c6a0718SPierre Ossman result = IRQ_NONE; 15581c6a0718SPierre Ossman goto out; 15591c6a0718SPierre Ossman } 15601c6a0718SPierre Ossman 1561b69c9058SPierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 1562b69c9058SPierre Ossman mmc_hostname(host->mmc), intmask); 15631c6a0718SPierre Ossman 15641c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 15654e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 15664e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 15671c6a0718SPierre Ossman tasklet_schedule(&host->card_tasklet); 15681c6a0718SPierre Ossman } 15691c6a0718SPierre Ossman 15701c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 15711c6a0718SPierre Ossman 15721c6a0718SPierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 15734e4141a5SAnton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 15744e4141a5SAnton Vorontsov SDHCI_INT_STATUS); 15751c6a0718SPierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 15761c6a0718SPierre Ossman } 15771c6a0718SPierre Ossman 15781c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 15794e4141a5SAnton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, 15804e4141a5SAnton Vorontsov SDHCI_INT_STATUS); 15811c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 15821c6a0718SPierre Ossman } 15831c6a0718SPierre Ossman 15841c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 15851c6a0718SPierre Ossman 1586964f9ce2SPierre Ossman intmask &= ~SDHCI_INT_ERROR; 1587964f9ce2SPierre Ossman 15881c6a0718SPierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 15891c6a0718SPierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 15901c6a0718SPierre Ossman mmc_hostname(host->mmc)); 15914e4141a5SAnton Vorontsov sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); 15921c6a0718SPierre Ossman } 15931c6a0718SPierre Ossman 15949d26a5d3SRolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 15951c6a0718SPierre Ossman 1596f75979b7SPierre Ossman if (intmask & SDHCI_INT_CARD_INT) 1597f75979b7SPierre Ossman cardint = 1; 1598f75979b7SPierre Ossman 1599f75979b7SPierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 1600f75979b7SPierre Ossman 16011c6a0718SPierre Ossman if (intmask) { 16021c6a0718SPierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 16031c6a0718SPierre Ossman mmc_hostname(host->mmc), intmask); 16041c6a0718SPierre Ossman sdhci_dumpregs(host); 16051c6a0718SPierre Ossman 16064e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 16071c6a0718SPierre Ossman } 16081c6a0718SPierre Ossman 16091c6a0718SPierre Ossman result = IRQ_HANDLED; 16101c6a0718SPierre Ossman 16111c6a0718SPierre Ossman mmiowb(); 16121c6a0718SPierre Ossman out: 16131c6a0718SPierre Ossman spin_unlock(&host->lock); 16141c6a0718SPierre Ossman 1615f75979b7SPierre Ossman /* 1616f75979b7SPierre Ossman * We have to delay this as it calls back into the driver. 1617f75979b7SPierre Ossman */ 1618f75979b7SPierre Ossman if (cardint) 1619f75979b7SPierre Ossman mmc_signal_sdio_irq(host->mmc); 1620f75979b7SPierre Ossman 16211c6a0718SPierre Ossman return result; 16221c6a0718SPierre Ossman } 16231c6a0718SPierre Ossman 16241c6a0718SPierre Ossman /*****************************************************************************\ 16251c6a0718SPierre Ossman * * 16261c6a0718SPierre Ossman * Suspend/resume * 16271c6a0718SPierre Ossman * * 16281c6a0718SPierre Ossman \*****************************************************************************/ 16291c6a0718SPierre Ossman 16301c6a0718SPierre Ossman #ifdef CONFIG_PM 16311c6a0718SPierre Ossman 1632b8c86fc5SPierre Ossman int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 16331c6a0718SPierre Ossman { 1634b8c86fc5SPierre Ossman int ret; 16351c6a0718SPierre Ossman 16367260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 16377260cf5eSAnton Vorontsov 16381a13f8faSMatt Fleming ret = mmc_suspend_host(host->mmc); 16391c6a0718SPierre Ossman if (ret) 16401c6a0718SPierre Ossman return ret; 16411c6a0718SPierre Ossman 1642b8c86fc5SPierre Ossman free_irq(host->irq, host); 1643b8c86fc5SPierre Ossman 16449bea3c85SMarek Szyprowski if (host->vmmc) 16459bea3c85SMarek Szyprowski ret = regulator_disable(host->vmmc); 16469bea3c85SMarek Szyprowski 16479bea3c85SMarek Szyprowski return ret; 1648b8c86fc5SPierre Ossman } 1649b8c86fc5SPierre Ossman 1650b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 1651b8c86fc5SPierre Ossman 1652b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 1653b8c86fc5SPierre Ossman { 1654b8c86fc5SPierre Ossman int ret; 1655b8c86fc5SPierre Ossman 16569bea3c85SMarek Szyprowski if (host->vmmc) { 16579bea3c85SMarek Szyprowski int ret = regulator_enable(host->vmmc); 16589bea3c85SMarek Szyprowski if (ret) 16599bea3c85SMarek Szyprowski return ret; 16609bea3c85SMarek Szyprowski } 16619bea3c85SMarek Szyprowski 16629bea3c85SMarek Szyprowski 1663a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1664b8c86fc5SPierre Ossman if (host->ops->enable_dma) 1665b8c86fc5SPierre Ossman host->ops->enable_dma(host); 1666b8c86fc5SPierre Ossman } 1667b8c86fc5SPierre Ossman 1668b8c86fc5SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1669b8c86fc5SPierre Ossman mmc_hostname(host->mmc), host); 16701c6a0718SPierre Ossman if (ret) 16711c6a0718SPierre Ossman return ret; 1672b8c86fc5SPierre Ossman 16732f4cbb3dSNicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 16741c6a0718SPierre Ossman mmiowb(); 1675b8c86fc5SPierre Ossman 1676b8c86fc5SPierre Ossman ret = mmc_resume_host(host->mmc); 16777260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 16787260cf5eSAnton Vorontsov 16792f4cbb3dSNicolas Pitre return ret; 16801c6a0718SPierre Ossman } 16811c6a0718SPierre Ossman 1682b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 16831c6a0718SPierre Ossman 16841c6a0718SPierre Ossman #endif /* CONFIG_PM */ 16851c6a0718SPierre Ossman 16861c6a0718SPierre Ossman /*****************************************************************************\ 16871c6a0718SPierre Ossman * * 1688b8c86fc5SPierre Ossman * Device allocation/registration * 16891c6a0718SPierre Ossman * * 16901c6a0718SPierre Ossman \*****************************************************************************/ 16911c6a0718SPierre Ossman 1692b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 1693b8c86fc5SPierre Ossman size_t priv_size) 16941c6a0718SPierre Ossman { 16951c6a0718SPierre Ossman struct mmc_host *mmc; 16961c6a0718SPierre Ossman struct sdhci_host *host; 16971c6a0718SPierre Ossman 1698b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 16991c6a0718SPierre Ossman 1700b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 17011c6a0718SPierre Ossman if (!mmc) 1702b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 17031c6a0718SPierre Ossman 17041c6a0718SPierre Ossman host = mmc_priv(mmc); 17051c6a0718SPierre Ossman host->mmc = mmc; 17061c6a0718SPierre Ossman 1707b8c86fc5SPierre Ossman return host; 17081c6a0718SPierre Ossman } 17091c6a0718SPierre Ossman 1710b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 1711b8c86fc5SPierre Ossman 1712b8c86fc5SPierre Ossman int sdhci_add_host(struct sdhci_host *host) 1713b8c86fc5SPierre Ossman { 1714b8c86fc5SPierre Ossman struct mmc_host *mmc; 1715b8c86fc5SPierre Ossman unsigned int caps; 1716b8c86fc5SPierre Ossman int ret; 1717b8c86fc5SPierre Ossman 1718b8c86fc5SPierre Ossman WARN_ON(host == NULL); 1719b8c86fc5SPierre Ossman if (host == NULL) 1720b8c86fc5SPierre Ossman return -EINVAL; 1721b8c86fc5SPierre Ossman 1722b8c86fc5SPierre Ossman mmc = host->mmc; 1723b8c86fc5SPierre Ossman 1724b8c86fc5SPierre Ossman if (debug_quirks) 1725b8c86fc5SPierre Ossman host->quirks = debug_quirks; 1726b8c86fc5SPierre Ossman 17271c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 17281c6a0718SPierre Ossman 17294e4141a5SAnton Vorontsov host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 17302134a922SPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 17312134a922SPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 173285105c53SZhangfei Gao if (host->version > SDHCI_SPEC_300) { 17331c6a0718SPierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 1734b69c9058SPierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 17352134a922SPierre Ossman host->version); 17361c6a0718SPierre Ossman } 17371c6a0718SPierre Ossman 1738ccc92c23SMaxim Levitsky caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : 1739ccc92c23SMaxim Levitsky sdhci_readl(host, SDHCI_CAPABILITIES); 17401c6a0718SPierre Ossman 1741b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 1742a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 1743a13abc7bSRichard Röjfors else if (!(caps & SDHCI_CAN_DO_SDMA)) 1744a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 17451c6a0718SPierre Ossman else 1746a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 17471c6a0718SPierre Ossman 1748b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 1749a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 1750cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 1751a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 17527c168e3dSFeng Tang } 17537c168e3dSFeng Tang 1754a13abc7bSRichard Röjfors if ((host->version >= SDHCI_SPEC_200) && (caps & SDHCI_CAN_DO_ADMA2)) 17552134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 17562134a922SPierre Ossman 17572134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 17582134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 17592134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 17602134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17612134a922SPierre Ossman } 17622134a922SPierre Ossman 1763a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1764b8c86fc5SPierre Ossman if (host->ops->enable_dma) { 1765b8c86fc5SPierre Ossman if (host->ops->enable_dma(host)) { 1766b8c86fc5SPierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 1767b8c86fc5SPierre Ossman "available. Falling back to PIO.\n", 1768b8c86fc5SPierre Ossman mmc_hostname(mmc)); 1769a13abc7bSRichard Röjfors host->flags &= 1770a13abc7bSRichard Röjfors ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 17711c6a0718SPierre Ossman } 17721c6a0718SPierre Ossman } 1773b8c86fc5SPierre Ossman } 17741c6a0718SPierre Ossman 17752134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 17762134a922SPierre Ossman /* 17772134a922SPierre Ossman * We need to allocate descriptors for all sg entries 17782134a922SPierre Ossman * (128) and potentially one alignment transfer for 17792134a922SPierre Ossman * each of those entries. 17802134a922SPierre Ossman */ 17812134a922SPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 17822134a922SPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 17832134a922SPierre Ossman if (!host->adma_desc || !host->align_buffer) { 17842134a922SPierre Ossman kfree(host->adma_desc); 17852134a922SPierre Ossman kfree(host->align_buffer); 17862134a922SPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 17872134a922SPierre Ossman "buffers. Falling back to standard DMA.\n", 17882134a922SPierre Ossman mmc_hostname(mmc)); 17892134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17902134a922SPierre Ossman } 17912134a922SPierre Ossman } 17922134a922SPierre Ossman 17937659150cSPierre Ossman /* 17947659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 17957659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 17967659150cSPierre Ossman * mask here in that case. 17977659150cSPierre Ossman */ 1798a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 17997659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 18007659150cSPierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 18017659150cSPierre Ossman } 18021c6a0718SPierre Ossman 1803c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 1804c4687d5fSZhangfei Gao host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) 1805c4687d5fSZhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 1806c4687d5fSZhangfei Gao else 1807c4687d5fSZhangfei Gao host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) 1808c4687d5fSZhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 1809c4687d5fSZhangfei Gao 18104240ff0aSBen Dooks host->max_clk *= 1000000; 1811f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 1812f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 18134240ff0aSBen Dooks if (!host->ops->get_max_clock) { 18144240ff0aSBen Dooks printk(KERN_ERR 18154240ff0aSBen Dooks "%s: Hardware doesn't specify base clock " 1816b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1817b8c86fc5SPierre Ossman return -ENODEV; 18181c6a0718SPierre Ossman } 18194240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 18204240ff0aSBen Dooks } 18211c6a0718SPierre Ossman 18221c6a0718SPierre Ossman host->timeout_clk = 18231c6a0718SPierre Ossman (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 18241c6a0718SPierre Ossman if (host->timeout_clk == 0) { 182581b39802SAnton Vorontsov if (host->ops->get_timeout_clock) { 182681b39802SAnton Vorontsov host->timeout_clk = host->ops->get_timeout_clock(host); 182781b39802SAnton Vorontsov } else if (!(host->quirks & 182881b39802SAnton Vorontsov SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 18294240ff0aSBen Dooks printk(KERN_ERR 18304240ff0aSBen Dooks "%s: Hardware doesn't specify timeout clock " 1831b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1832b8c86fc5SPierre Ossman return -ENODEV; 18331c6a0718SPierre Ossman } 18344240ff0aSBen Dooks } 18351c6a0718SPierre Ossman if (caps & SDHCI_TIMEOUT_CLK_UNIT) 18361c6a0718SPierre Ossman host->timeout_clk *= 1000; 18371c6a0718SPierre Ossman 18381c6a0718SPierre Ossman /* 18391c6a0718SPierre Ossman * Set host parameters. 18401c6a0718SPierre Ossman */ 18411c6a0718SPierre Ossman mmc->ops = &sdhci_ops; 1842ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 1843a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 18440397526dSZhangfei Gao else if (host->version >= SDHCI_SPEC_300) 18450397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 1846a9e58f25SAnton Vorontsov else 18470397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 18481c6a0718SPierre Ossman mmc->f_max = host->max_clk; 1849c1f5977cSKyungmin Park mmc->caps |= MMC_CAP_SDIO_IRQ; 18505fe23c7fSAnton Vorontsov 18515fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 1852b08caed8SGiuseppe Cavallaro mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; 18531c6a0718SPierre Ossman 185486a6a874SPierre Ossman if (caps & SDHCI_CAN_DO_HISPD) 1855a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 18561c6a0718SPierre Ossman 1857176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 1858176d1ed4SJaehoon Chung mmc_card_is_removable(mmc)) 185968d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 186068d1fb7eSAnton Vorontsov 18611c6a0718SPierre Ossman mmc->ocr_avail = 0; 18621c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_330) 18631c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; 18641c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_300) 18651c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; 18661c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_180) 186755556da0SPhilip Langdale mmc->ocr_avail |= MMC_VDD_165_195; 18681c6a0718SPierre Ossman 18691c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 18701c6a0718SPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 1871b69c9058SPierre Ossman "support voltages.\n", mmc_hostname(mmc)); 1872b8c86fc5SPierre Ossman return -ENODEV; 18731c6a0718SPierre Ossman } 18741c6a0718SPierre Ossman 18751c6a0718SPierre Ossman spin_lock_init(&host->lock); 18761c6a0718SPierre Ossman 18771c6a0718SPierre Ossman /* 18782134a922SPierre Ossman * Maximum number of segments. Depends on if the hardware 18792134a922SPierre Ossman * can do scatter/gather or not. 18801c6a0718SPierre Ossman */ 18812134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 1882a36274e0SMartin K. Petersen mmc->max_segs = 128; 1883a13abc7bSRichard Röjfors else if (host->flags & SDHCI_USE_SDMA) 1884a36274e0SMartin K. Petersen mmc->max_segs = 1; 18852134a922SPierre Ossman else /* PIO */ 1886a36274e0SMartin K. Petersen mmc->max_segs = 128; 18871c6a0718SPierre Ossman 18881c6a0718SPierre Ossman /* 18891c6a0718SPierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 18901c6a0718SPierre Ossman * size (512KiB). 18911c6a0718SPierre Ossman */ 18921c6a0718SPierre Ossman mmc->max_req_size = 524288; 18931c6a0718SPierre Ossman 18941c6a0718SPierre Ossman /* 18951c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 18962134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 18972134a922SPierre Ossman * be larger than 64 KiB though. 18981c6a0718SPierre Ossman */ 18992134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 19002134a922SPierre Ossman mmc->max_seg_size = 65536; 19012134a922SPierre Ossman else 19021c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 19031c6a0718SPierre Ossman 19041c6a0718SPierre Ossman /* 19051c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 19061c6a0718SPierre Ossman * is specified in the capabilities register. 19071c6a0718SPierre Ossman */ 19080633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 19090633f654SAnton Vorontsov mmc->max_blk_size = 2; 19100633f654SAnton Vorontsov } else { 19110633f654SAnton Vorontsov mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> 19120633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 19131c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 1914b69c9058SPierre Ossman printk(KERN_WARNING "%s: Invalid maximum block size, " 1915b69c9058SPierre Ossman "assuming 512 bytes\n", mmc_hostname(mmc)); 19160633f654SAnton Vorontsov mmc->max_blk_size = 0; 19170633f654SAnton Vorontsov } 19180633f654SAnton Vorontsov } 19190633f654SAnton Vorontsov 19201c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 19211c6a0718SPierre Ossman 19221c6a0718SPierre Ossman /* 19231c6a0718SPierre Ossman * Maximum block count. 19241c6a0718SPierre Ossman */ 19251388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 19261c6a0718SPierre Ossman 19271c6a0718SPierre Ossman /* 19281c6a0718SPierre Ossman * Init tasklets. 19291c6a0718SPierre Ossman */ 19301c6a0718SPierre Ossman tasklet_init(&host->card_tasklet, 19311c6a0718SPierre Ossman sdhci_tasklet_card, (unsigned long)host); 19321c6a0718SPierre Ossman tasklet_init(&host->finish_tasklet, 19331c6a0718SPierre Ossman sdhci_tasklet_finish, (unsigned long)host); 19341c6a0718SPierre Ossman 19351c6a0718SPierre Ossman setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 19361c6a0718SPierre Ossman 19371c6a0718SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1938b69c9058SPierre Ossman mmc_hostname(mmc), host); 19391c6a0718SPierre Ossman if (ret) 19401c6a0718SPierre Ossman goto untasklet; 19411c6a0718SPierre Ossman 19429bea3c85SMarek Szyprowski host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); 19439bea3c85SMarek Szyprowski if (IS_ERR(host->vmmc)) { 19449bea3c85SMarek Szyprowski printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc)); 19459bea3c85SMarek Szyprowski host->vmmc = NULL; 19469bea3c85SMarek Szyprowski } else { 19479bea3c85SMarek Szyprowski regulator_enable(host->vmmc); 19489bea3c85SMarek Szyprowski } 19499bea3c85SMarek Szyprowski 19502f4cbb3dSNicolas Pitre sdhci_init(host, 0); 19511c6a0718SPierre Ossman 19521c6a0718SPierre Ossman #ifdef CONFIG_MMC_DEBUG 19531c6a0718SPierre Ossman sdhci_dumpregs(host); 19541c6a0718SPierre Ossman #endif 19551c6a0718SPierre Ossman 1956f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 19575dbace0cSHelmut Schaa snprintf(host->led_name, sizeof(host->led_name), 19585dbace0cSHelmut Schaa "%s::", mmc_hostname(mmc)); 19595dbace0cSHelmut Schaa host->led.name = host->led_name; 19602f730fecSPierre Ossman host->led.brightness = LED_OFF; 19612f730fecSPierre Ossman host->led.default_trigger = mmc_hostname(mmc); 19622f730fecSPierre Ossman host->led.brightness_set = sdhci_led_control; 19632f730fecSPierre Ossman 1964b8c86fc5SPierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 19652f730fecSPierre Ossman if (ret) 19662f730fecSPierre Ossman goto reset; 19672f730fecSPierre Ossman #endif 19682f730fecSPierre Ossman 19691c6a0718SPierre Ossman mmiowb(); 19701c6a0718SPierre Ossman 19711c6a0718SPierre Ossman mmc_add_host(mmc); 19721c6a0718SPierre Ossman 1973a13abc7bSRichard Röjfors printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n", 1974d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 1975a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_ADMA) ? "ADMA" : 1976a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 19771c6a0718SPierre Ossman 19787260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 19797260cf5eSAnton Vorontsov 19801c6a0718SPierre Ossman return 0; 19811c6a0718SPierre Ossman 1982f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 19832f730fecSPierre Ossman reset: 19842f730fecSPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 19852f730fecSPierre Ossman free_irq(host->irq, host); 19862f730fecSPierre Ossman #endif 19871c6a0718SPierre Ossman untasklet: 19881c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 19891c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 19901c6a0718SPierre Ossman 19911c6a0718SPierre Ossman return ret; 19921c6a0718SPierre Ossman } 19931c6a0718SPierre Ossman 1994b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 1995b8c86fc5SPierre Ossman 19961e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 19971c6a0718SPierre Ossman { 19981e72859eSPierre Ossman unsigned long flags; 19991e72859eSPierre Ossman 20001e72859eSPierre Ossman if (dead) { 20011e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 20021e72859eSPierre Ossman 20031e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 20041e72859eSPierre Ossman 20051e72859eSPierre Ossman if (host->mrq) { 20061e72859eSPierre Ossman printk(KERN_ERR "%s: Controller removed during " 20071e72859eSPierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 20081e72859eSPierre Ossman 20091e72859eSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 20101e72859eSPierre Ossman tasklet_schedule(&host->finish_tasklet); 20111e72859eSPierre Ossman } 20121e72859eSPierre Ossman 20131e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 20141e72859eSPierre Ossman } 20151e72859eSPierre Ossman 20167260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 20177260cf5eSAnton Vorontsov 2018b8c86fc5SPierre Ossman mmc_remove_host(host->mmc); 20191c6a0718SPierre Ossman 2020f9134319SPierre Ossman #ifdef SDHCI_USE_LEDS_CLASS 20212f730fecSPierre Ossman led_classdev_unregister(&host->led); 20222f730fecSPierre Ossman #endif 20232f730fecSPierre Ossman 20241e72859eSPierre Ossman if (!dead) 20251c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 20261c6a0718SPierre Ossman 20271c6a0718SPierre Ossman free_irq(host->irq, host); 20281c6a0718SPierre Ossman 20291c6a0718SPierre Ossman del_timer_sync(&host->timer); 20301c6a0718SPierre Ossman 20311c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 20321c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 20332134a922SPierre Ossman 20349bea3c85SMarek Szyprowski if (host->vmmc) { 20359bea3c85SMarek Szyprowski regulator_disable(host->vmmc); 20369bea3c85SMarek Szyprowski regulator_put(host->vmmc); 20379bea3c85SMarek Szyprowski } 20389bea3c85SMarek Szyprowski 20392134a922SPierre Ossman kfree(host->adma_desc); 20402134a922SPierre Ossman kfree(host->align_buffer); 20412134a922SPierre Ossman 20422134a922SPierre Ossman host->adma_desc = NULL; 20432134a922SPierre Ossman host->align_buffer = NULL; 20441c6a0718SPierre Ossman } 20451c6a0718SPierre Ossman 2046b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 2047b8c86fc5SPierre Ossman 2048b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 20491c6a0718SPierre Ossman { 2050b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 20511c6a0718SPierre Ossman } 20521c6a0718SPierre Ossman 2053b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 20541c6a0718SPierre Ossman 20551c6a0718SPierre Ossman /*****************************************************************************\ 20561c6a0718SPierre Ossman * * 20571c6a0718SPierre Ossman * Driver init/exit * 20581c6a0718SPierre Ossman * * 20591c6a0718SPierre Ossman \*****************************************************************************/ 20601c6a0718SPierre Ossman 20611c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 20621c6a0718SPierre Ossman { 20631c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME 20641c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 20651c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 20661c6a0718SPierre Ossman 2067b8c86fc5SPierre Ossman return 0; 20681c6a0718SPierre Ossman } 20691c6a0718SPierre Ossman 20701c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 20711c6a0718SPierre Ossman { 20721c6a0718SPierre Ossman } 20731c6a0718SPierre Ossman 20741c6a0718SPierre Ossman module_init(sdhci_drv_init); 20751c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 20761c6a0718SPierre Ossman 20771c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 20781c6a0718SPierre Ossman 207932710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 2080b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 20811c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 20821c6a0718SPierre Ossman 20831c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 2084