11c6a0718SPierre Ossman /* 270f10482SPierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver 31c6a0718SPierre Ossman * 4b69c9058SPierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. 51c6a0718SPierre Ossman * 61c6a0718SPierre Ossman * This program is free software; you can redistribute it and/or modify 71c6a0718SPierre Ossman * it under the terms of the GNU General Public License as published by 81c6a0718SPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 91c6a0718SPierre Ossman * your option) any later version. 1084c46a53SPierre Ossman * 1184c46a53SPierre Ossman * Thanks to the following companies for their support: 1284c46a53SPierre Ossman * 1384c46a53SPierre Ossman * - JMicron (hardware and technical support) 141c6a0718SPierre Ossman */ 151c6a0718SPierre Ossman 161c6a0718SPierre Ossman #include <linux/delay.h> 171c6a0718SPierre Ossman #include <linux/highmem.h> 18b8c86fc5SPierre Ossman #include <linux/io.h> 191c6a0718SPierre Ossman #include <linux/dma-mapping.h> 2011763609SRalf Baechle #include <linux/scatterlist.h> 211c6a0718SPierre Ossman 222f730fecSPierre Ossman #include <linux/leds.h> 232f730fecSPierre Ossman 241c6a0718SPierre Ossman #include <linux/mmc/host.h> 251c6a0718SPierre Ossman 261c6a0718SPierre Ossman #include "sdhci.h" 271c6a0718SPierre Ossman 281c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 291c6a0718SPierre Ossman 301c6a0718SPierre Ossman #define DBG(f, x...) \ 311c6a0718SPierre Ossman pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 321c6a0718SPierre Ossman 331c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 341c6a0718SPierre Ossman 351c6a0718SPierre Ossman static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); 361c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *); 371c6a0718SPierre Ossman 381c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 391c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *); 401c6a0718SPierre Ossman 411c6a0718SPierre Ossman static void sdhci_dumpregs(struct sdhci_host *host) 421c6a0718SPierre Ossman { 431c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); 441c6a0718SPierre Ossman 451c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 461c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_DMA_ADDRESS), 471c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_HOST_VERSION)); 481c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 491c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_BLOCK_SIZE), 501c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_BLOCK_COUNT)); 511c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 521c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_ARGUMENT), 531c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_TRANSFER_MODE)); 541c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 551c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_PRESENT_STATE), 561c6a0718SPierre Ossman readb(host->ioaddr + SDHCI_HOST_CONTROL)); 571c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 581c6a0718SPierre Ossman readb(host->ioaddr + SDHCI_POWER_CONTROL), 591c6a0718SPierre Ossman readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL)); 601c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 612df3b71bSNicolas Pitre readb(host->ioaddr + SDHCI_WAKE_UP_CONTROL), 621c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_CLOCK_CONTROL)); 631c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 641c6a0718SPierre Ossman readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL), 651c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_INT_STATUS)); 661c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 671c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_INT_ENABLE), 681c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_SIGNAL_ENABLE)); 691c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 701c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_ACMD12_ERR), 711c6a0718SPierre Ossman readw(host->ioaddr + SDHCI_SLOT_INT_STATUS)); 721c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", 731c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_CAPABILITIES), 741c6a0718SPierre Ossman readl(host->ioaddr + SDHCI_MAX_CURRENT)); 751c6a0718SPierre Ossman 761c6a0718SPierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 771c6a0718SPierre Ossman } 781c6a0718SPierre Ossman 791c6a0718SPierre Ossman /*****************************************************************************\ 801c6a0718SPierre Ossman * * 811c6a0718SPierre Ossman * Low level functions * 821c6a0718SPierre Ossman * * 831c6a0718SPierre Ossman \*****************************************************************************/ 841c6a0718SPierre Ossman 851c6a0718SPierre Ossman static void sdhci_reset(struct sdhci_host *host, u8 mask) 861c6a0718SPierre Ossman { 871c6a0718SPierre Ossman unsigned long timeout; 881c6a0718SPierre Ossman 89b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 901c6a0718SPierre Ossman if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & 911c6a0718SPierre Ossman SDHCI_CARD_PRESENT)) 921c6a0718SPierre Ossman return; 931c6a0718SPierre Ossman } 941c6a0718SPierre Ossman 951c6a0718SPierre Ossman writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET); 961c6a0718SPierre Ossman 971c6a0718SPierre Ossman if (mask & SDHCI_RESET_ALL) 981c6a0718SPierre Ossman host->clock = 0; 991c6a0718SPierre Ossman 1001c6a0718SPierre Ossman /* Wait max 100 ms */ 1011c6a0718SPierre Ossman timeout = 100; 1021c6a0718SPierre Ossman 1031c6a0718SPierre Ossman /* hw clears the bit when it's done */ 1041c6a0718SPierre Ossman while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) { 1051c6a0718SPierre Ossman if (timeout == 0) { 1061c6a0718SPierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 1071c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 1081c6a0718SPierre Ossman sdhci_dumpregs(host); 1091c6a0718SPierre Ossman return; 1101c6a0718SPierre Ossman } 1111c6a0718SPierre Ossman timeout--; 1121c6a0718SPierre Ossman mdelay(1); 1131c6a0718SPierre Ossman } 1141c6a0718SPierre Ossman } 1151c6a0718SPierre Ossman 1161c6a0718SPierre Ossman static void sdhci_init(struct sdhci_host *host) 1171c6a0718SPierre Ossman { 1181c6a0718SPierre Ossman u32 intmask; 1191c6a0718SPierre Ossman 1201c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1211c6a0718SPierre Ossman 1221c6a0718SPierre Ossman intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 1231c6a0718SPierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 1241c6a0718SPierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 1251c6a0718SPierre Ossman SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT | 1261c6a0718SPierre Ossman SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | 1272134a922SPierre Ossman SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE | 1282134a922SPierre Ossman SDHCI_INT_ADMA_ERROR; 1291c6a0718SPierre Ossman 1301c6a0718SPierre Ossman writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); 1311c6a0718SPierre Ossman writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); 1321c6a0718SPierre Ossman } 1331c6a0718SPierre Ossman 1341c6a0718SPierre Ossman static void sdhci_activate_led(struct sdhci_host *host) 1351c6a0718SPierre Ossman { 1361c6a0718SPierre Ossman u8 ctrl; 1371c6a0718SPierre Ossman 1381c6a0718SPierre Ossman ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); 1391c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 1401c6a0718SPierre Ossman writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); 1411c6a0718SPierre Ossman } 1421c6a0718SPierre Ossman 1431c6a0718SPierre Ossman static void sdhci_deactivate_led(struct sdhci_host *host) 1441c6a0718SPierre Ossman { 1451c6a0718SPierre Ossman u8 ctrl; 1461c6a0718SPierre Ossman 1471c6a0718SPierre Ossman ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); 1481c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 1491c6a0718SPierre Ossman writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); 1501c6a0718SPierre Ossman } 1511c6a0718SPierre Ossman 1522f730fecSPierre Ossman #ifdef CONFIG_LEDS_CLASS 1532f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 1542f730fecSPierre Ossman enum led_brightness brightness) 1552f730fecSPierre Ossman { 1562f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 1572f730fecSPierre Ossman unsigned long flags; 1582f730fecSPierre Ossman 1592f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 1602f730fecSPierre Ossman 1612f730fecSPierre Ossman if (brightness == LED_OFF) 1622f730fecSPierre Ossman sdhci_deactivate_led(host); 1632f730fecSPierre Ossman else 1642f730fecSPierre Ossman sdhci_activate_led(host); 1652f730fecSPierre Ossman 1662f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1672f730fecSPierre Ossman } 1682f730fecSPierre Ossman #endif 1692f730fecSPierre Ossman 1701c6a0718SPierre Ossman /*****************************************************************************\ 1711c6a0718SPierre Ossman * * 1721c6a0718SPierre Ossman * Core functions * 1731c6a0718SPierre Ossman * * 1741c6a0718SPierre Ossman \*****************************************************************************/ 1751c6a0718SPierre Ossman 1761c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 1771c6a0718SPierre Ossman { 1787659150cSPierre Ossman unsigned long flags; 1797659150cSPierre Ossman size_t blksize, len, chunk; 1807659150cSPierre Ossman u32 scratch; 1817659150cSPierre Ossman u8 *buf; 1821c6a0718SPierre Ossman 1831c6a0718SPierre Ossman DBG("PIO reading\n"); 1841c6a0718SPierre Ossman 1851c6a0718SPierre Ossman blksize = host->data->blksz; 1867659150cSPierre Ossman chunk = 0; 1871c6a0718SPierre Ossman 1887659150cSPierre Ossman local_irq_save(flags); 1891c6a0718SPierre Ossman 1901c6a0718SPierre Ossman while (blksize) { 1917659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 1927659150cSPierre Ossman BUG(); 1937659150cSPierre Ossman 1947659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 1957659150cSPierre Ossman 1967659150cSPierre Ossman blksize -= len; 1977659150cSPierre Ossman host->sg_miter.consumed = len; 1987659150cSPierre Ossman 1997659150cSPierre Ossman buf = host->sg_miter.addr; 2007659150cSPierre Ossman 2017659150cSPierre Ossman while (len) { 2027659150cSPierre Ossman if (chunk == 0) { 2037659150cSPierre Ossman scratch = readl(host->ioaddr + SDHCI_BUFFER); 2047659150cSPierre Ossman chunk = 4; 2051c6a0718SPierre Ossman } 2061c6a0718SPierre Ossman 2077659150cSPierre Ossman *buf = scratch & 0xFF; 2081c6a0718SPierre Ossman 2097659150cSPierre Ossman buf++; 2107659150cSPierre Ossman scratch >>= 8; 2117659150cSPierre Ossman chunk--; 2127659150cSPierre Ossman len--; 2137659150cSPierre Ossman } 2141c6a0718SPierre Ossman } 2151c6a0718SPierre Ossman 2167659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 2177659150cSPierre Ossman 2187659150cSPierre Ossman local_irq_restore(flags); 2191c6a0718SPierre Ossman } 2201c6a0718SPierre Ossman 2211c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 2221c6a0718SPierre Ossman { 2237659150cSPierre Ossman unsigned long flags; 2247659150cSPierre Ossman size_t blksize, len, chunk; 2257659150cSPierre Ossman u32 scratch; 2267659150cSPierre Ossman u8 *buf; 2271c6a0718SPierre Ossman 2281c6a0718SPierre Ossman DBG("PIO writing\n"); 2291c6a0718SPierre Ossman 2301c6a0718SPierre Ossman blksize = host->data->blksz; 2317659150cSPierre Ossman chunk = 0; 2327659150cSPierre Ossman scratch = 0; 2331c6a0718SPierre Ossman 2347659150cSPierre Ossman local_irq_save(flags); 2351c6a0718SPierre Ossman 2361c6a0718SPierre Ossman while (blksize) { 2377659150cSPierre Ossman if (!sg_miter_next(&host->sg_miter)) 2387659150cSPierre Ossman BUG(); 2391c6a0718SPierre Ossman 2407659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 2411c6a0718SPierre Ossman 2427659150cSPierre Ossman blksize -= len; 2437659150cSPierre Ossman host->sg_miter.consumed = len; 2447659150cSPierre Ossman 2457659150cSPierre Ossman buf = host->sg_miter.addr; 2467659150cSPierre Ossman 2477659150cSPierre Ossman while (len) { 2487659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 2497659150cSPierre Ossman 2507659150cSPierre Ossman buf++; 2517659150cSPierre Ossman chunk++; 2527659150cSPierre Ossman len--; 2537659150cSPierre Ossman 2547659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 2557659150cSPierre Ossman writel(scratch, host->ioaddr + SDHCI_BUFFER); 2567659150cSPierre Ossman chunk = 0; 2577659150cSPierre Ossman scratch = 0; 2587659150cSPierre Ossman } 2597659150cSPierre Ossman } 2601c6a0718SPierre Ossman } 2611c6a0718SPierre Ossman 2627659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 2631c6a0718SPierre Ossman 2647659150cSPierre Ossman local_irq_restore(flags); 2651c6a0718SPierre Ossman } 2661c6a0718SPierre Ossman 2671c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 2681c6a0718SPierre Ossman { 2691c6a0718SPierre Ossman u32 mask; 2701c6a0718SPierre Ossman 2711c6a0718SPierre Ossman BUG_ON(!host->data); 2721c6a0718SPierre Ossman 2737659150cSPierre Ossman if (host->blocks == 0) 2741c6a0718SPierre Ossman return; 2751c6a0718SPierre Ossman 2761c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 2771c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 2781c6a0718SPierre Ossman else 2791c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 2801c6a0718SPierre Ossman 2814a3cba32SPierre Ossman /* 2824a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 2834a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 2844a3cba32SPierre Ossman * we can ignore the bits. 2854a3cba32SPierre Ossman */ 2864a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 2874a3cba32SPierre Ossman (host->data->blocks == 1)) 2884a3cba32SPierre Ossman mask = ~0; 2894a3cba32SPierre Ossman 2901c6a0718SPierre Ossman while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { 2911c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 2921c6a0718SPierre Ossman sdhci_read_block_pio(host); 2931c6a0718SPierre Ossman else 2941c6a0718SPierre Ossman sdhci_write_block_pio(host); 2951c6a0718SPierre Ossman 2967659150cSPierre Ossman host->blocks--; 2977659150cSPierre Ossman if (host->blocks == 0) 2981c6a0718SPierre Ossman break; 2991c6a0718SPierre Ossman } 3001c6a0718SPierre Ossman 3011c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 3021c6a0718SPierre Ossman } 3031c6a0718SPierre Ossman 3042134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3052134a922SPierre Ossman { 3062134a922SPierre Ossman local_irq_save(*flags); 3072134a922SPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 3082134a922SPierre Ossman } 3092134a922SPierre Ossman 3102134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 3112134a922SPierre Ossman { 3122134a922SPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 3132134a922SPierre Ossman local_irq_restore(*flags); 3142134a922SPierre Ossman } 3152134a922SPierre Ossman 3168f1934ceSPierre Ossman static int sdhci_adma_table_pre(struct sdhci_host *host, 3172134a922SPierre Ossman struct mmc_data *data) 3182134a922SPierre Ossman { 3192134a922SPierre Ossman int direction; 3202134a922SPierre Ossman 3212134a922SPierre Ossman u8 *desc; 3222134a922SPierre Ossman u8 *align; 3232134a922SPierre Ossman dma_addr_t addr; 3242134a922SPierre Ossman dma_addr_t align_addr; 3252134a922SPierre Ossman int len, offset; 3262134a922SPierre Ossman 3272134a922SPierre Ossman struct scatterlist *sg; 3282134a922SPierre Ossman int i; 3292134a922SPierre Ossman char *buffer; 3302134a922SPierre Ossman unsigned long flags; 3312134a922SPierre Ossman 3322134a922SPierre Ossman /* 3332134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 3342134a922SPierre Ossman * We currently guess that it is LE. 3352134a922SPierre Ossman */ 3362134a922SPierre Ossman 3372134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 3382134a922SPierre Ossman direction = DMA_FROM_DEVICE; 3392134a922SPierre Ossman else 3402134a922SPierre Ossman direction = DMA_TO_DEVICE; 3412134a922SPierre Ossman 3422134a922SPierre Ossman /* 3432134a922SPierre Ossman * The ADMA descriptor table is mapped further down as we 3442134a922SPierre Ossman * need to fill it with data first. 3452134a922SPierre Ossman */ 3462134a922SPierre Ossman 3472134a922SPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 3482134a922SPierre Ossman host->align_buffer, 128 * 4, direction); 3498d8bb39bSFUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 3508f1934ceSPierre Ossman goto fail; 3512134a922SPierre Ossman BUG_ON(host->align_addr & 0x3); 3522134a922SPierre Ossman 3532134a922SPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 3542134a922SPierre Ossman data->sg, data->sg_len, direction); 3558f1934ceSPierre Ossman if (host->sg_count == 0) 3568f1934ceSPierre Ossman goto unmap_align; 3572134a922SPierre Ossman 3582134a922SPierre Ossman desc = host->adma_desc; 3592134a922SPierre Ossman align = host->align_buffer; 3602134a922SPierre Ossman 3612134a922SPierre Ossman align_addr = host->align_addr; 3622134a922SPierre Ossman 3632134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 3642134a922SPierre Ossman addr = sg_dma_address(sg); 3652134a922SPierre Ossman len = sg_dma_len(sg); 3662134a922SPierre Ossman 3672134a922SPierre Ossman /* 3682134a922SPierre Ossman * The SDHCI specification states that ADMA 3692134a922SPierre Ossman * addresses must be 32-bit aligned. If they 3702134a922SPierre Ossman * aren't, then we use a bounce buffer for 3712134a922SPierre Ossman * the (up to three) bytes that screw up the 3722134a922SPierre Ossman * alignment. 3732134a922SPierre Ossman */ 3742134a922SPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 3752134a922SPierre Ossman if (offset) { 3762134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 3772134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 3786cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 3792134a922SPierre Ossman memcpy(align, buffer, offset); 3802134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 3812134a922SPierre Ossman } 3822134a922SPierre Ossman 3832134a922SPierre Ossman desc[7] = (align_addr >> 24) & 0xff; 3842134a922SPierre Ossman desc[6] = (align_addr >> 16) & 0xff; 3852134a922SPierre Ossman desc[5] = (align_addr >> 8) & 0xff; 3862134a922SPierre Ossman desc[4] = (align_addr >> 0) & 0xff; 3872134a922SPierre Ossman 3882134a922SPierre Ossman BUG_ON(offset > 65536); 3892134a922SPierre Ossman 3902134a922SPierre Ossman desc[3] = (offset >> 8) & 0xff; 3912134a922SPierre Ossman desc[2] = (offset >> 0) & 0xff; 3922134a922SPierre Ossman 3932134a922SPierre Ossman desc[1] = 0x00; 3942134a922SPierre Ossman desc[0] = 0x21; /* tran, valid */ 3952134a922SPierre Ossman 3962134a922SPierre Ossman align += 4; 3972134a922SPierre Ossman align_addr += 4; 3982134a922SPierre Ossman 3992134a922SPierre Ossman desc += 8; 4002134a922SPierre Ossman 4012134a922SPierre Ossman addr += offset; 4022134a922SPierre Ossman len -= offset; 4032134a922SPierre Ossman } 4042134a922SPierre Ossman 4052134a922SPierre Ossman desc[7] = (addr >> 24) & 0xff; 4062134a922SPierre Ossman desc[6] = (addr >> 16) & 0xff; 4072134a922SPierre Ossman desc[5] = (addr >> 8) & 0xff; 4082134a922SPierre Ossman desc[4] = (addr >> 0) & 0xff; 4092134a922SPierre Ossman 4102134a922SPierre Ossman BUG_ON(len > 65536); 4112134a922SPierre Ossman 4122134a922SPierre Ossman desc[3] = (len >> 8) & 0xff; 4132134a922SPierre Ossman desc[2] = (len >> 0) & 0xff; 4142134a922SPierre Ossman 4152134a922SPierre Ossman desc[1] = 0x00; 4162134a922SPierre Ossman desc[0] = 0x21; /* tran, valid */ 4172134a922SPierre Ossman 4182134a922SPierre Ossman desc += 8; 4192134a922SPierre Ossman 4202134a922SPierre Ossman /* 4212134a922SPierre Ossman * If this triggers then we have a calculation bug 4222134a922SPierre Ossman * somewhere. :/ 4232134a922SPierre Ossman */ 4242134a922SPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 4252134a922SPierre Ossman } 4262134a922SPierre Ossman 4272134a922SPierre Ossman /* 4282134a922SPierre Ossman * Add a terminating entry. 4292134a922SPierre Ossman */ 4302134a922SPierre Ossman desc[7] = 0; 4312134a922SPierre Ossman desc[6] = 0; 4322134a922SPierre Ossman desc[5] = 0; 4332134a922SPierre Ossman desc[4] = 0; 4342134a922SPierre Ossman 4352134a922SPierre Ossman desc[3] = 0; 4362134a922SPierre Ossman desc[2] = 0; 4372134a922SPierre Ossman 4382134a922SPierre Ossman desc[1] = 0x00; 4392134a922SPierre Ossman desc[0] = 0x03; /* nop, end, valid */ 4402134a922SPierre Ossman 4412134a922SPierre Ossman /* 4422134a922SPierre Ossman * Resync align buffer as we might have changed it. 4432134a922SPierre Ossman */ 4442134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4452134a922SPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 4462134a922SPierre Ossman host->align_addr, 128 * 4, direction); 4472134a922SPierre Ossman } 4482134a922SPierre Ossman 4492134a922SPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 4502134a922SPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 4518d8bb39bSFUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4528f1934ceSPierre Ossman goto unmap_entries; 4532134a922SPierre Ossman BUG_ON(host->adma_addr & 0x3); 4548f1934ceSPierre Ossman 4558f1934ceSPierre Ossman return 0; 4568f1934ceSPierre Ossman 4578f1934ceSPierre Ossman unmap_entries: 4588f1934ceSPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 4598f1934ceSPierre Ossman data->sg_len, direction); 4608f1934ceSPierre Ossman unmap_align: 4618f1934ceSPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 4628f1934ceSPierre Ossman 128 * 4, direction); 4638f1934ceSPierre Ossman fail: 4648f1934ceSPierre Ossman return -EINVAL; 4652134a922SPierre Ossman } 4662134a922SPierre Ossman 4672134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 4682134a922SPierre Ossman struct mmc_data *data) 4692134a922SPierre Ossman { 4702134a922SPierre Ossman int direction; 4712134a922SPierre Ossman 4722134a922SPierre Ossman struct scatterlist *sg; 4732134a922SPierre Ossman int i, size; 4742134a922SPierre Ossman u8 *align; 4752134a922SPierre Ossman char *buffer; 4762134a922SPierre Ossman unsigned long flags; 4772134a922SPierre Ossman 4782134a922SPierre Ossman if (data->flags & MMC_DATA_READ) 4792134a922SPierre Ossman direction = DMA_FROM_DEVICE; 4802134a922SPierre Ossman else 4812134a922SPierre Ossman direction = DMA_TO_DEVICE; 4822134a922SPierre Ossman 4832134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 4842134a922SPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 4852134a922SPierre Ossman 4862134a922SPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 4872134a922SPierre Ossman 128 * 4, direction); 4882134a922SPierre Ossman 4892134a922SPierre Ossman if (data->flags & MMC_DATA_READ) { 4902134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 4912134a922SPierre Ossman data->sg_len, direction); 4922134a922SPierre Ossman 4932134a922SPierre Ossman align = host->align_buffer; 4942134a922SPierre Ossman 4952134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4962134a922SPierre Ossman if (sg_dma_address(sg) & 0x3) { 4972134a922SPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 4982134a922SPierre Ossman 4992134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5006cefd05fSPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5012134a922SPierre Ossman memcpy(buffer, align, size); 5022134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5032134a922SPierre Ossman 5042134a922SPierre Ossman align += 4; 5052134a922SPierre Ossman } 5062134a922SPierre Ossman } 5072134a922SPierre Ossman } 5082134a922SPierre Ossman 5092134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5102134a922SPierre Ossman data->sg_len, direction); 5112134a922SPierre Ossman } 5122134a922SPierre Ossman 513ee53ab5dSPierre Ossman static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) 5141c6a0718SPierre Ossman { 5151c6a0718SPierre Ossman u8 count; 5161c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 5171c6a0718SPierre Ossman 518ee53ab5dSPierre Ossman /* 519ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 520ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 521ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 522ee53ab5dSPierre Ossman * timeout value. 523ee53ab5dSPierre Ossman */ 524ee53ab5dSPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)) 525ee53ab5dSPierre Ossman return 0xE; 526e538fbe8SPierre Ossman 5271c6a0718SPierre Ossman /* timeout in us */ 5281c6a0718SPierre Ossman target_timeout = data->timeout_ns / 1000 + 5291c6a0718SPierre Ossman data->timeout_clks / host->clock; 5301c6a0718SPierre Ossman 5311c6a0718SPierre Ossman /* 5321c6a0718SPierre Ossman * Figure out needed cycles. 5331c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 5341c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 5351c6a0718SPierre Ossman * minimum resolution of 6 bits: 5361c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 5371c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 5381c6a0718SPierre Ossman * => 5391c6a0718SPierre Ossman * (1) / (2) > 2^6 5401c6a0718SPierre Ossman */ 5411c6a0718SPierre Ossman count = 0; 5421c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 5431c6a0718SPierre Ossman while (current_timeout < target_timeout) { 5441c6a0718SPierre Ossman count++; 5451c6a0718SPierre Ossman current_timeout <<= 1; 5461c6a0718SPierre Ossman if (count >= 0xF) 5471c6a0718SPierre Ossman break; 5481c6a0718SPierre Ossman } 5491c6a0718SPierre Ossman 5501c6a0718SPierre Ossman if (count >= 0xF) { 5511c6a0718SPierre Ossman printk(KERN_WARNING "%s: Too large timeout requested!\n", 5521c6a0718SPierre Ossman mmc_hostname(host->mmc)); 5531c6a0718SPierre Ossman count = 0xE; 5541c6a0718SPierre Ossman } 5551c6a0718SPierre Ossman 556ee53ab5dSPierre Ossman return count; 557ee53ab5dSPierre Ossman } 558ee53ab5dSPierre Ossman 559ee53ab5dSPierre Ossman static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 560ee53ab5dSPierre Ossman { 561ee53ab5dSPierre Ossman u8 count; 5622134a922SPierre Ossman u8 ctrl; 5638f1934ceSPierre Ossman int ret; 564ee53ab5dSPierre Ossman 565ee53ab5dSPierre Ossman WARN_ON(host->data); 566ee53ab5dSPierre Ossman 567ee53ab5dSPierre Ossman if (data == NULL) 568ee53ab5dSPierre Ossman return; 569ee53ab5dSPierre Ossman 570ee53ab5dSPierre Ossman /* Sanity checks */ 571ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 572ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 573ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 574ee53ab5dSPierre Ossman 575ee53ab5dSPierre Ossman host->data = data; 576ee53ab5dSPierre Ossman host->data_early = 0; 577ee53ab5dSPierre Ossman 578ee53ab5dSPierre Ossman count = sdhci_calc_timeout(host, data); 5791c6a0718SPierre Ossman writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL); 5801c6a0718SPierre Ossman 581c9fddbc4SPierre Ossman if (host->flags & SDHCI_USE_DMA) 582c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 583c9fddbc4SPierre Ossman 5842134a922SPierre Ossman /* 5852134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 5862134a922SPierre Ossman * scatterlist. 5872134a922SPierre Ossman */ 5882134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 5892134a922SPierre Ossman int broken, i; 5902134a922SPierre Ossman struct scatterlist *sg; 5912134a922SPierre Ossman 5922134a922SPierre Ossman broken = 0; 5932134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 5942134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 5952134a922SPierre Ossman broken = 1; 5962134a922SPierre Ossman } else { 5972134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 5982134a922SPierre Ossman broken = 1; 5992134a922SPierre Ossman } 6002134a922SPierre Ossman 6012134a922SPierre Ossman if (unlikely(broken)) { 6022134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6032134a922SPierre Ossman if (sg->length & 0x3) { 6042134a922SPierre Ossman DBG("Reverting to PIO because of " 6052134a922SPierre Ossman "transfer size (%d)\n", 6062134a922SPierre Ossman sg->length); 607c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6082134a922SPierre Ossman break; 6092134a922SPierre Ossman } 6102134a922SPierre Ossman } 6112134a922SPierre Ossman } 612c9fddbc4SPierre Ossman } 613c9fddbc4SPierre Ossman 614c9fddbc4SPierre Ossman /* 615c9fddbc4SPierre Ossman * The assumption here being that alignment is the same after 616c9fddbc4SPierre Ossman * translation to device address space. 617c9fddbc4SPierre Ossman */ 6182134a922SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6192134a922SPierre Ossman int broken, i; 6202134a922SPierre Ossman struct scatterlist *sg; 6212134a922SPierre Ossman 6222134a922SPierre Ossman broken = 0; 6232134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6242134a922SPierre Ossman /* 6252134a922SPierre Ossman * As we use 3 byte chunks to work around 6262134a922SPierre Ossman * alignment problems, we need to check this 6272134a922SPierre Ossman * quirk. 6282134a922SPierre Ossman */ 6292134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 6302134a922SPierre Ossman broken = 1; 6312134a922SPierre Ossman } else { 6322134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 6332134a922SPierre Ossman broken = 1; 6342134a922SPierre Ossman } 6352134a922SPierre Ossman 6362134a922SPierre Ossman if (unlikely(broken)) { 6372134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6382134a922SPierre Ossman if (sg->offset & 0x3) { 6392134a922SPierre Ossman DBG("Reverting to PIO because of " 6402134a922SPierre Ossman "bad alignment\n"); 641c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6422134a922SPierre Ossman break; 6432134a922SPierre Ossman } 6442134a922SPierre Ossman } 6452134a922SPierre Ossman } 6462134a922SPierre Ossman } 6472134a922SPierre Ossman 6488f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6498f1934ceSPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6508f1934ceSPierre Ossman ret = sdhci_adma_table_pre(host, data); 6518f1934ceSPierre Ossman if (ret) { 6528f1934ceSPierre Ossman /* 6538f1934ceSPierre Ossman * This only happens when someone fed 6548f1934ceSPierre Ossman * us an invalid request. 6558f1934ceSPierre Ossman */ 6568f1934ceSPierre Ossman WARN_ON(1); 6578f1934ceSPierre Ossman host->flags &= ~SDHCI_USE_DMA; 6588f1934ceSPierre Ossman } else { 6598f1934ceSPierre Ossman writel(host->adma_addr, 6608f1934ceSPierre Ossman host->ioaddr + SDHCI_ADMA_ADDRESS); 6618f1934ceSPierre Ossman } 6628f1934ceSPierre Ossman } else { 663c8b3e02eSTomas Winkler int sg_cnt; 6648f1934ceSPierre Ossman 665c8b3e02eSTomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 6668f1934ceSPierre Ossman data->sg, data->sg_len, 6678f1934ceSPierre Ossman (data->flags & MMC_DATA_READ) ? 6688f1934ceSPierre Ossman DMA_FROM_DEVICE : 6698f1934ceSPierre Ossman DMA_TO_DEVICE); 670c8b3e02eSTomas Winkler if (sg_cnt == 0) { 6718f1934ceSPierre Ossman /* 6728f1934ceSPierre Ossman * This only happens when someone fed 6738f1934ceSPierre Ossman * us an invalid request. 6748f1934ceSPierre Ossman */ 6758f1934ceSPierre Ossman WARN_ON(1); 6768f1934ceSPierre Ossman host->flags &= ~SDHCI_USE_DMA; 6778f1934ceSPierre Ossman } else { 678719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 6798f1934ceSPierre Ossman writel(sg_dma_address(data->sg), 6808f1934ceSPierre Ossman host->ioaddr + SDHCI_DMA_ADDRESS); 6818f1934ceSPierre Ossman } 6828f1934ceSPierre Ossman } 6838f1934ceSPierre Ossman } 6848f1934ceSPierre Ossman 6852134a922SPierre Ossman /* 6862134a922SPierre Ossman * Always adjust the DMA selection as some controllers 6872134a922SPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 6882134a922SPierre Ossman * is ADMA. 6892134a922SPierre Ossman */ 6902134a922SPierre Ossman if (host->version >= SDHCI_SPEC_200) { 6912134a922SPierre Ossman ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); 6922134a922SPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 6932134a922SPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 6942134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) 6952134a922SPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 6962134a922SPierre Ossman else 6972134a922SPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 6982134a922SPierre Ossman writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); 699c9fddbc4SPierre Ossman } 700c9fddbc4SPierre Ossman 7018f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 7027659150cSPierre Ossman sg_miter_start(&host->sg_miter, 7037659150cSPierre Ossman data->sg, data->sg_len, SG_MITER_ATOMIC); 7047659150cSPierre Ossman host->blocks = data->blocks; 7051c6a0718SPierre Ossman } 7061c6a0718SPierre Ossman 7071c6a0718SPierre Ossman /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 7081c6a0718SPierre Ossman writew(SDHCI_MAKE_BLKSZ(7, data->blksz), 7091c6a0718SPierre Ossman host->ioaddr + SDHCI_BLOCK_SIZE); 7101c6a0718SPierre Ossman writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); 7111c6a0718SPierre Ossman } 7121c6a0718SPierre Ossman 7131c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 7141c6a0718SPierre Ossman struct mmc_data *data) 7151c6a0718SPierre Ossman { 7161c6a0718SPierre Ossman u16 mode; 7171c6a0718SPierre Ossman 7181c6a0718SPierre Ossman if (data == NULL) 7191c6a0718SPierre Ossman return; 7201c6a0718SPierre Ossman 721e538fbe8SPierre Ossman WARN_ON(!host->data); 722e538fbe8SPierre Ossman 7231c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 7241c6a0718SPierre Ossman if (data->blocks > 1) 7251c6a0718SPierre Ossman mode |= SDHCI_TRNS_MULTI; 7261c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 7271c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 728c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 7291c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 7301c6a0718SPierre Ossman 7311c6a0718SPierre Ossman writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); 7321c6a0718SPierre Ossman } 7331c6a0718SPierre Ossman 7341c6a0718SPierre Ossman static void sdhci_finish_data(struct sdhci_host *host) 7351c6a0718SPierre Ossman { 7361c6a0718SPierre Ossman struct mmc_data *data; 7371c6a0718SPierre Ossman 7381c6a0718SPierre Ossman BUG_ON(!host->data); 7391c6a0718SPierre Ossman 7401c6a0718SPierre Ossman data = host->data; 7411c6a0718SPierre Ossman host->data = NULL; 7421c6a0718SPierre Ossman 743c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7442134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 7452134a922SPierre Ossman sdhci_adma_table_post(host, data); 7462134a922SPierre Ossman else { 7472134a922SPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 7482134a922SPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 749b8c86fc5SPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 7501c6a0718SPierre Ossman } 7512134a922SPierre Ossman } 7521c6a0718SPierre Ossman 7531c6a0718SPierre Ossman /* 754c9b74c5bSPierre Ossman * The specification states that the block count register must 755c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 756c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 757c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 758c9b74c5bSPierre Ossman * in the event of an error. 7591c6a0718SPierre Ossman */ 760c9b74c5bSPierre Ossman if (data->error) 761c9b74c5bSPierre Ossman data->bytes_xfered = 0; 7621c6a0718SPierre Ossman else 763c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 7641c6a0718SPierre Ossman 7651c6a0718SPierre Ossman if (data->stop) { 7661c6a0718SPierre Ossman /* 7671c6a0718SPierre Ossman * The controller needs a reset of internal state machines 7681c6a0718SPierre Ossman * upon error conditions. 7691c6a0718SPierre Ossman */ 77017b0429dSPierre Ossman if (data->error) { 7711c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 7721c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 7731c6a0718SPierre Ossman } 7741c6a0718SPierre Ossman 7751c6a0718SPierre Ossman sdhci_send_command(host, data->stop); 7761c6a0718SPierre Ossman } else 7771c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 7781c6a0718SPierre Ossman } 7791c6a0718SPierre Ossman 7801c6a0718SPierre Ossman static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 7811c6a0718SPierre Ossman { 7821c6a0718SPierre Ossman int flags; 7831c6a0718SPierre Ossman u32 mask; 7841c6a0718SPierre Ossman unsigned long timeout; 7851c6a0718SPierre Ossman 7861c6a0718SPierre Ossman WARN_ON(host->cmd); 7871c6a0718SPierre Ossman 7881c6a0718SPierre Ossman /* Wait max 10 ms */ 7891c6a0718SPierre Ossman timeout = 10; 7901c6a0718SPierre Ossman 7911c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 7921c6a0718SPierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 7931c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 7941c6a0718SPierre Ossman 7951c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 7961c6a0718SPierre Ossman though they might use busy signaling */ 7971c6a0718SPierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 7981c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 7991c6a0718SPierre Ossman 8001c6a0718SPierre Ossman while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { 8011c6a0718SPierre Ossman if (timeout == 0) { 8021c6a0718SPierre Ossman printk(KERN_ERR "%s: Controller never released " 8031c6a0718SPierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 8041c6a0718SPierre Ossman sdhci_dumpregs(host); 80517b0429dSPierre Ossman cmd->error = -EIO; 8061c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8071c6a0718SPierre Ossman return; 8081c6a0718SPierre Ossman } 8091c6a0718SPierre Ossman timeout--; 8101c6a0718SPierre Ossman mdelay(1); 8111c6a0718SPierre Ossman } 8121c6a0718SPierre Ossman 8131c6a0718SPierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 8141c6a0718SPierre Ossman 8151c6a0718SPierre Ossman host->cmd = cmd; 8161c6a0718SPierre Ossman 8171c6a0718SPierre Ossman sdhci_prepare_data(host, cmd->data); 8181c6a0718SPierre Ossman 8191c6a0718SPierre Ossman writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT); 8201c6a0718SPierre Ossman 8211c6a0718SPierre Ossman sdhci_set_transfer_mode(host, cmd->data); 8221c6a0718SPierre Ossman 8231c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 8241c6a0718SPierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 8251c6a0718SPierre Ossman mmc_hostname(host->mmc)); 82617b0429dSPierre Ossman cmd->error = -EINVAL; 8271c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8281c6a0718SPierre Ossman return; 8291c6a0718SPierre Ossman } 8301c6a0718SPierre Ossman 8311c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 8321c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 8331c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 8341c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 8351c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 8361c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 8371c6a0718SPierre Ossman else 8381c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 8391c6a0718SPierre Ossman 8401c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 8411c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 8421c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 8431c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 8441c6a0718SPierre Ossman if (cmd->data) 8451c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 8461c6a0718SPierre Ossman 8471c6a0718SPierre Ossman writew(SDHCI_MAKE_CMD(cmd->opcode, flags), 8481c6a0718SPierre Ossman host->ioaddr + SDHCI_COMMAND); 8491c6a0718SPierre Ossman } 8501c6a0718SPierre Ossman 8511c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 8521c6a0718SPierre Ossman { 8531c6a0718SPierre Ossman int i; 8541c6a0718SPierre Ossman 8551c6a0718SPierre Ossman BUG_ON(host->cmd == NULL); 8561c6a0718SPierre Ossman 8571c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 8581c6a0718SPierre Ossman if (host->cmd->flags & MMC_RSP_136) { 8591c6a0718SPierre Ossman /* CRC is stripped so we need to do some shifting. */ 8601c6a0718SPierre Ossman for (i = 0;i < 4;i++) { 8611c6a0718SPierre Ossman host->cmd->resp[i] = readl(host->ioaddr + 8621c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 8631c6a0718SPierre Ossman if (i != 3) 8641c6a0718SPierre Ossman host->cmd->resp[i] |= 8651c6a0718SPierre Ossman readb(host->ioaddr + 8661c6a0718SPierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 8671c6a0718SPierre Ossman } 8681c6a0718SPierre Ossman } else { 8691c6a0718SPierre Ossman host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE); 8701c6a0718SPierre Ossman } 8711c6a0718SPierre Ossman } 8721c6a0718SPierre Ossman 87317b0429dSPierre Ossman host->cmd->error = 0; 8741c6a0718SPierre Ossman 875e538fbe8SPierre Ossman if (host->data && host->data_early) 876e538fbe8SPierre Ossman sdhci_finish_data(host); 877e538fbe8SPierre Ossman 878e538fbe8SPierre Ossman if (!host->cmd->data) 8791c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 8801c6a0718SPierre Ossman 8811c6a0718SPierre Ossman host->cmd = NULL; 8821c6a0718SPierre Ossman } 8831c6a0718SPierre Ossman 8841c6a0718SPierre Ossman static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 8851c6a0718SPierre Ossman { 8861c6a0718SPierre Ossman int div; 8871c6a0718SPierre Ossman u16 clk; 8881c6a0718SPierre Ossman unsigned long timeout; 8891c6a0718SPierre Ossman 8901c6a0718SPierre Ossman if (clock == host->clock) 8911c6a0718SPierre Ossman return; 8921c6a0718SPierre Ossman 8931c6a0718SPierre Ossman writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); 8941c6a0718SPierre Ossman 8951c6a0718SPierre Ossman if (clock == 0) 8961c6a0718SPierre Ossman goto out; 8971c6a0718SPierre Ossman 8981c6a0718SPierre Ossman for (div = 1;div < 256;div *= 2) { 8991c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 9001c6a0718SPierre Ossman break; 9011c6a0718SPierre Ossman } 9021c6a0718SPierre Ossman div >>= 1; 9031c6a0718SPierre Ossman 9041c6a0718SPierre Ossman clk = div << SDHCI_DIVIDER_SHIFT; 9051c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 9061c6a0718SPierre Ossman writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); 9071c6a0718SPierre Ossman 9081c6a0718SPierre Ossman /* Wait max 10 ms */ 9091c6a0718SPierre Ossman timeout = 10; 9101c6a0718SPierre Ossman while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL)) 9111c6a0718SPierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 9121c6a0718SPierre Ossman if (timeout == 0) { 9131c6a0718SPierre Ossman printk(KERN_ERR "%s: Internal clock never " 9141c6a0718SPierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 9151c6a0718SPierre Ossman sdhci_dumpregs(host); 9161c6a0718SPierre Ossman return; 9171c6a0718SPierre Ossman } 9181c6a0718SPierre Ossman timeout--; 9191c6a0718SPierre Ossman mdelay(1); 9201c6a0718SPierre Ossman } 9211c6a0718SPierre Ossman 9221c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 9231c6a0718SPierre Ossman writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); 9241c6a0718SPierre Ossman 9251c6a0718SPierre Ossman out: 9261c6a0718SPierre Ossman host->clock = clock; 9271c6a0718SPierre Ossman } 9281c6a0718SPierre Ossman 9291c6a0718SPierre Ossman static void sdhci_set_power(struct sdhci_host *host, unsigned short power) 9301c6a0718SPierre Ossman { 9311c6a0718SPierre Ossman u8 pwr; 9321c6a0718SPierre Ossman 9331c6a0718SPierre Ossman if (host->power == power) 9341c6a0718SPierre Ossman return; 9351c6a0718SPierre Ossman 9361c6a0718SPierre Ossman if (power == (unsigned short)-1) { 9371c6a0718SPierre Ossman writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); 9381c6a0718SPierre Ossman goto out; 9391c6a0718SPierre Ossman } 9401c6a0718SPierre Ossman 9411c6a0718SPierre Ossman /* 9421c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 9431c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 9441c6a0718SPierre Ossman */ 945b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 9461c6a0718SPierre Ossman writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); 9471c6a0718SPierre Ossman 9481c6a0718SPierre Ossman pwr = SDHCI_POWER_ON; 9491c6a0718SPierre Ossman 9504be34c99SPhilip Langdale switch (1 << power) { 95155556da0SPhilip Langdale case MMC_VDD_165_195: 9521c6a0718SPierre Ossman pwr |= SDHCI_POWER_180; 9531c6a0718SPierre Ossman break; 9544be34c99SPhilip Langdale case MMC_VDD_29_30: 9554be34c99SPhilip Langdale case MMC_VDD_30_31: 9561c6a0718SPierre Ossman pwr |= SDHCI_POWER_300; 9571c6a0718SPierre Ossman break; 9584be34c99SPhilip Langdale case MMC_VDD_32_33: 9594be34c99SPhilip Langdale case MMC_VDD_33_34: 9601c6a0718SPierre Ossman pwr |= SDHCI_POWER_330; 9611c6a0718SPierre Ossman break; 9621c6a0718SPierre Ossman default: 9631c6a0718SPierre Ossman BUG(); 9641c6a0718SPierre Ossman } 9651c6a0718SPierre Ossman 966e08c1694SAndres Salomon /* 967c71f6512SAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 968e08c1694SAndres Salomon * and set turn on power at the same time, so set the voltage first. 969e08c1694SAndres Salomon */ 970b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) 971e08c1694SAndres Salomon writeb(pwr & ~SDHCI_POWER_ON, 972e08c1694SAndres Salomon host->ioaddr + SDHCI_POWER_CONTROL); 973e08c1694SAndres Salomon 9741c6a0718SPierre Ossman writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); 9751c6a0718SPierre Ossman 9761c6a0718SPierre Ossman out: 9771c6a0718SPierre Ossman host->power = power; 9781c6a0718SPierre Ossman } 9791c6a0718SPierre Ossman 9801c6a0718SPierre Ossman /*****************************************************************************\ 9811c6a0718SPierre Ossman * * 9821c6a0718SPierre Ossman * MMC callbacks * 9831c6a0718SPierre Ossman * * 9841c6a0718SPierre Ossman \*****************************************************************************/ 9851c6a0718SPierre Ossman 9861c6a0718SPierre Ossman static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 9871c6a0718SPierre Ossman { 9881c6a0718SPierre Ossman struct sdhci_host *host; 9891c6a0718SPierre Ossman unsigned long flags; 9901c6a0718SPierre Ossman 9911c6a0718SPierre Ossman host = mmc_priv(mmc); 9921c6a0718SPierre Ossman 9931c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 9941c6a0718SPierre Ossman 9951c6a0718SPierre Ossman WARN_ON(host->mrq != NULL); 9961c6a0718SPierre Ossman 9972f730fecSPierre Ossman #ifndef CONFIG_LEDS_CLASS 9981c6a0718SPierre Ossman sdhci_activate_led(host); 9992f730fecSPierre Ossman #endif 10001c6a0718SPierre Ossman 10011c6a0718SPierre Ossman host->mrq = mrq; 10021c6a0718SPierre Ossman 10031e72859eSPierre Ossman if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) 10041e72859eSPierre Ossman || (host->flags & SDHCI_DEVICE_DEAD)) { 100517b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 10061c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 10071c6a0718SPierre Ossman } else 10081c6a0718SPierre Ossman sdhci_send_command(host, mrq->cmd); 10091c6a0718SPierre Ossman 10101c6a0718SPierre Ossman mmiowb(); 10111c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 10121c6a0718SPierre Ossman } 10131c6a0718SPierre Ossman 10141c6a0718SPierre Ossman static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 10151c6a0718SPierre Ossman { 10161c6a0718SPierre Ossman struct sdhci_host *host; 10171c6a0718SPierre Ossman unsigned long flags; 10181c6a0718SPierre Ossman u8 ctrl; 10191c6a0718SPierre Ossman 10201c6a0718SPierre Ossman host = mmc_priv(mmc); 10211c6a0718SPierre Ossman 10221c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 10231c6a0718SPierre Ossman 10241e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 10251e72859eSPierre Ossman goto out; 10261e72859eSPierre Ossman 10271c6a0718SPierre Ossman /* 10281c6a0718SPierre Ossman * Reset the chip on each power off. 10291c6a0718SPierre Ossman * Should clear out any weird states. 10301c6a0718SPierre Ossman */ 10311c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 10321c6a0718SPierre Ossman writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE); 10331c6a0718SPierre Ossman sdhci_init(host); 10341c6a0718SPierre Ossman } 10351c6a0718SPierre Ossman 10361c6a0718SPierre Ossman sdhci_set_clock(host, ios->clock); 10371c6a0718SPierre Ossman 10381c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) 10391c6a0718SPierre Ossman sdhci_set_power(host, -1); 10401c6a0718SPierre Ossman else 10411c6a0718SPierre Ossman sdhci_set_power(host, ios->vdd); 10421c6a0718SPierre Ossman 10431c6a0718SPierre Ossman ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); 10441c6a0718SPierre Ossman 10451c6a0718SPierre Ossman if (ios->bus_width == MMC_BUS_WIDTH_4) 10461c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_4BITBUS; 10471c6a0718SPierre Ossman else 10481c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_4BITBUS; 10491c6a0718SPierre Ossman 10501c6a0718SPierre Ossman if (ios->timing == MMC_TIMING_SD_HS) 10511c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 10521c6a0718SPierre Ossman else 10531c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 10541c6a0718SPierre Ossman 10551c6a0718SPierre Ossman writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); 10561c6a0718SPierre Ossman 1057b8352260SLeandro Dorileo /* 1058b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1059b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1060b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 1061b8352260SLeandro Dorileo */ 1062b8c86fc5SPierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1063b8352260SLeandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1064b8352260SLeandro Dorileo 10651e72859eSPierre Ossman out: 10661c6a0718SPierre Ossman mmiowb(); 10671c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 10681c6a0718SPierre Ossman } 10691c6a0718SPierre Ossman 10701c6a0718SPierre Ossman static int sdhci_get_ro(struct mmc_host *mmc) 10711c6a0718SPierre Ossman { 10721c6a0718SPierre Ossman struct sdhci_host *host; 10731c6a0718SPierre Ossman unsigned long flags; 10741c6a0718SPierre Ossman int present; 10751c6a0718SPierre Ossman 10761c6a0718SPierre Ossman host = mmc_priv(mmc); 10771c6a0718SPierre Ossman 10781c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 10791c6a0718SPierre Ossman 10801e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 10811e72859eSPierre Ossman present = 0; 10821e72859eSPierre Ossman else 10831c6a0718SPierre Ossman present = readl(host->ioaddr + SDHCI_PRESENT_STATE); 10841c6a0718SPierre Ossman 10851c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 10861c6a0718SPierre Ossman 10871c6a0718SPierre Ossman return !(present & SDHCI_WRITE_PROTECT); 10881c6a0718SPierre Ossman } 10891c6a0718SPierre Ossman 1090f75979b7SPierre Ossman static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1091f75979b7SPierre Ossman { 1092f75979b7SPierre Ossman struct sdhci_host *host; 1093f75979b7SPierre Ossman unsigned long flags; 1094f75979b7SPierre Ossman u32 ier; 1095f75979b7SPierre Ossman 1096f75979b7SPierre Ossman host = mmc_priv(mmc); 1097f75979b7SPierre Ossman 1098f75979b7SPierre Ossman spin_lock_irqsave(&host->lock, flags); 1099f75979b7SPierre Ossman 11001e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11011e72859eSPierre Ossman goto out; 11021e72859eSPierre Ossman 1103f75979b7SPierre Ossman ier = readl(host->ioaddr + SDHCI_INT_ENABLE); 1104f75979b7SPierre Ossman 1105f75979b7SPierre Ossman ier &= ~SDHCI_INT_CARD_INT; 1106f75979b7SPierre Ossman if (enable) 1107f75979b7SPierre Ossman ier |= SDHCI_INT_CARD_INT; 1108f75979b7SPierre Ossman 1109f75979b7SPierre Ossman writel(ier, host->ioaddr + SDHCI_INT_ENABLE); 1110f75979b7SPierre Ossman writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); 1111f75979b7SPierre Ossman 11121e72859eSPierre Ossman out: 1113f75979b7SPierre Ossman mmiowb(); 1114f75979b7SPierre Ossman 1115f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1116f75979b7SPierre Ossman } 1117f75979b7SPierre Ossman 11181c6a0718SPierre Ossman static const struct mmc_host_ops sdhci_ops = { 11191c6a0718SPierre Ossman .request = sdhci_request, 11201c6a0718SPierre Ossman .set_ios = sdhci_set_ios, 11211c6a0718SPierre Ossman .get_ro = sdhci_get_ro, 1122f75979b7SPierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 11231c6a0718SPierre Ossman }; 11241c6a0718SPierre Ossman 11251c6a0718SPierre Ossman /*****************************************************************************\ 11261c6a0718SPierre Ossman * * 11271c6a0718SPierre Ossman * Tasklets * 11281c6a0718SPierre Ossman * * 11291c6a0718SPierre Ossman \*****************************************************************************/ 11301c6a0718SPierre Ossman 11311c6a0718SPierre Ossman static void sdhci_tasklet_card(unsigned long param) 11321c6a0718SPierre Ossman { 11331c6a0718SPierre Ossman struct sdhci_host *host; 11341c6a0718SPierre Ossman unsigned long flags; 11351c6a0718SPierre Ossman 11361c6a0718SPierre Ossman host = (struct sdhci_host*)param; 11371c6a0718SPierre Ossman 11381c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11391c6a0718SPierre Ossman 11401c6a0718SPierre Ossman if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 11411c6a0718SPierre Ossman if (host->mrq) { 11421c6a0718SPierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 11431c6a0718SPierre Ossman mmc_hostname(host->mmc)); 11441c6a0718SPierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 11451c6a0718SPierre Ossman mmc_hostname(host->mmc)); 11461c6a0718SPierre Ossman 11471c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 11481c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 11491c6a0718SPierre Ossman 115017b0429dSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 11511c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 11521c6a0718SPierre Ossman } 11531c6a0718SPierre Ossman } 11541c6a0718SPierre Ossman 11551c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 11561c6a0718SPierre Ossman 11571c6a0718SPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(500)); 11581c6a0718SPierre Ossman } 11591c6a0718SPierre Ossman 11601c6a0718SPierre Ossman static void sdhci_tasklet_finish(unsigned long param) 11611c6a0718SPierre Ossman { 11621c6a0718SPierre Ossman struct sdhci_host *host; 11631c6a0718SPierre Ossman unsigned long flags; 11641c6a0718SPierre Ossman struct mmc_request *mrq; 11651c6a0718SPierre Ossman 11661c6a0718SPierre Ossman host = (struct sdhci_host*)param; 11671c6a0718SPierre Ossman 11681c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 11691c6a0718SPierre Ossman 11701c6a0718SPierre Ossman del_timer(&host->timer); 11711c6a0718SPierre Ossman 11721c6a0718SPierre Ossman mrq = host->mrq; 11731c6a0718SPierre Ossman 11741c6a0718SPierre Ossman /* 11751c6a0718SPierre Ossman * The controller needs a reset of internal state machines 11761c6a0718SPierre Ossman * upon error conditions. 11771c6a0718SPierre Ossman */ 11781e72859eSPierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 11791e72859eSPierre Ossman (mrq->cmd->error || 118017b0429dSPierre Ossman (mrq->data && (mrq->data->error || 118184c46a53SPierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 11821e72859eSPierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 11831c6a0718SPierre Ossman 11841c6a0718SPierre Ossman /* Some controllers need this kick or reset won't work here */ 1185b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 11861c6a0718SPierre Ossman unsigned int clock; 11871c6a0718SPierre Ossman 11881c6a0718SPierre Ossman /* This is to force an update */ 11891c6a0718SPierre Ossman clock = host->clock; 11901c6a0718SPierre Ossman host->clock = 0; 11911c6a0718SPierre Ossman sdhci_set_clock(host, clock); 11921c6a0718SPierre Ossman } 11931c6a0718SPierre Ossman 11941c6a0718SPierre Ossman /* Spec says we should do both at the same time, but Ricoh 11951c6a0718SPierre Ossman controllers do not like that. */ 11961c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 11971c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 11981c6a0718SPierre Ossman } 11991c6a0718SPierre Ossman 12001c6a0718SPierre Ossman host->mrq = NULL; 12011c6a0718SPierre Ossman host->cmd = NULL; 12021c6a0718SPierre Ossman host->data = NULL; 12031c6a0718SPierre Ossman 12042f730fecSPierre Ossman #ifndef CONFIG_LEDS_CLASS 12051c6a0718SPierre Ossman sdhci_deactivate_led(host); 12062f730fecSPierre Ossman #endif 12071c6a0718SPierre Ossman 12081c6a0718SPierre Ossman mmiowb(); 12091c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12101c6a0718SPierre Ossman 12111c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 12121c6a0718SPierre Ossman } 12131c6a0718SPierre Ossman 12141c6a0718SPierre Ossman static void sdhci_timeout_timer(unsigned long data) 12151c6a0718SPierre Ossman { 12161c6a0718SPierre Ossman struct sdhci_host *host; 12171c6a0718SPierre Ossman unsigned long flags; 12181c6a0718SPierre Ossman 12191c6a0718SPierre Ossman host = (struct sdhci_host*)data; 12201c6a0718SPierre Ossman 12211c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 12221c6a0718SPierre Ossman 12231c6a0718SPierre Ossman if (host->mrq) { 12241c6a0718SPierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 12251c6a0718SPierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 12261c6a0718SPierre Ossman sdhci_dumpregs(host); 12271c6a0718SPierre Ossman 12281c6a0718SPierre Ossman if (host->data) { 122917b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 12301c6a0718SPierre Ossman sdhci_finish_data(host); 12311c6a0718SPierre Ossman } else { 12321c6a0718SPierre Ossman if (host->cmd) 123317b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 12341c6a0718SPierre Ossman else 123517b0429dSPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 12361c6a0718SPierre Ossman 12371c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 12381c6a0718SPierre Ossman } 12391c6a0718SPierre Ossman } 12401c6a0718SPierre Ossman 12411c6a0718SPierre Ossman mmiowb(); 12421c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 12431c6a0718SPierre Ossman } 12441c6a0718SPierre Ossman 12451c6a0718SPierre Ossman /*****************************************************************************\ 12461c6a0718SPierre Ossman * * 12471c6a0718SPierre Ossman * Interrupt handling * 12481c6a0718SPierre Ossman * * 12491c6a0718SPierre Ossman \*****************************************************************************/ 12501c6a0718SPierre Ossman 12511c6a0718SPierre Ossman static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 12521c6a0718SPierre Ossman { 12531c6a0718SPierre Ossman BUG_ON(intmask == 0); 12541c6a0718SPierre Ossman 12551c6a0718SPierre Ossman if (!host->cmd) { 1256b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1257b67ac3f3SPierre Ossman "though no command operation was in progress.\n", 1258b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 12591c6a0718SPierre Ossman sdhci_dumpregs(host); 12601c6a0718SPierre Ossman return; 12611c6a0718SPierre Ossman } 12621c6a0718SPierre Ossman 12631c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 126417b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 126517b0429dSPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 126617b0429dSPierre Ossman SDHCI_INT_INDEX)) 126717b0429dSPierre Ossman host->cmd->error = -EILSEQ; 12681c6a0718SPierre Ossman 126917b0429dSPierre Ossman if (host->cmd->error) 12701c6a0718SPierre Ossman tasklet_schedule(&host->finish_tasklet); 127143b58b36SPierre Ossman else if (intmask & SDHCI_INT_RESPONSE) 127243b58b36SPierre Ossman sdhci_finish_command(host); 12731c6a0718SPierre Ossman } 12741c6a0718SPierre Ossman 12751c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 12761c6a0718SPierre Ossman { 12771c6a0718SPierre Ossman BUG_ON(intmask == 0); 12781c6a0718SPierre Ossman 12791c6a0718SPierre Ossman if (!host->data) { 12801c6a0718SPierre Ossman /* 12811c6a0718SPierre Ossman * A data end interrupt is sent together with the response 12821c6a0718SPierre Ossman * for the stop command. 12831c6a0718SPierre Ossman */ 12841c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_END) 12851c6a0718SPierre Ossman return; 12861c6a0718SPierre Ossman 1287b67ac3f3SPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 1288b67ac3f3SPierre Ossman "though no data operation was in progress.\n", 1289b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 12901c6a0718SPierre Ossman sdhci_dumpregs(host); 12911c6a0718SPierre Ossman 12921c6a0718SPierre Ossman return; 12931c6a0718SPierre Ossman } 12941c6a0718SPierre Ossman 12951c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 129617b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 129717b0429dSPierre Ossman else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 129817b0429dSPierre Ossman host->data->error = -EILSEQ; 12992134a922SPierre Ossman else if (intmask & SDHCI_INT_ADMA_ERROR) 13002134a922SPierre Ossman host->data->error = -EIO; 13011c6a0718SPierre Ossman 130217b0429dSPierre Ossman if (host->data->error) 13031c6a0718SPierre Ossman sdhci_finish_data(host); 13041c6a0718SPierre Ossman else { 13051c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 13061c6a0718SPierre Ossman sdhci_transfer_pio(host); 13071c6a0718SPierre Ossman 13086ba736a1SPierre Ossman /* 13096ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 13106ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 13116ba736a1SPierre Ossman * we need to at least restart the transfer. 13126ba736a1SPierre Ossman */ 13136ba736a1SPierre Ossman if (intmask & SDHCI_INT_DMA_END) 13146ba736a1SPierre Ossman writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), 13156ba736a1SPierre Ossman host->ioaddr + SDHCI_DMA_ADDRESS); 13166ba736a1SPierre Ossman 1317e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1318e538fbe8SPierre Ossman if (host->cmd) { 1319e538fbe8SPierre Ossman /* 1320e538fbe8SPierre Ossman * Data managed to finish before the 1321e538fbe8SPierre Ossman * command completed. Make sure we do 1322e538fbe8SPierre Ossman * things in the proper order. 1323e538fbe8SPierre Ossman */ 1324e538fbe8SPierre Ossman host->data_early = 1; 1325e538fbe8SPierre Ossman } else { 13261c6a0718SPierre Ossman sdhci_finish_data(host); 13271c6a0718SPierre Ossman } 13281c6a0718SPierre Ossman } 1329e538fbe8SPierre Ossman } 1330e538fbe8SPierre Ossman } 13311c6a0718SPierre Ossman 13321c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 13331c6a0718SPierre Ossman { 13341c6a0718SPierre Ossman irqreturn_t result; 13351c6a0718SPierre Ossman struct sdhci_host* host = dev_id; 13361c6a0718SPierre Ossman u32 intmask; 1337f75979b7SPierre Ossman int cardint = 0; 13381c6a0718SPierre Ossman 13391c6a0718SPierre Ossman spin_lock(&host->lock); 13401c6a0718SPierre Ossman 13411c6a0718SPierre Ossman intmask = readl(host->ioaddr + SDHCI_INT_STATUS); 13421c6a0718SPierre Ossman 13431c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 13441c6a0718SPierre Ossman result = IRQ_NONE; 13451c6a0718SPierre Ossman goto out; 13461c6a0718SPierre Ossman } 13471c6a0718SPierre Ossman 1348b69c9058SPierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 1349b69c9058SPierre Ossman mmc_hostname(host->mmc), intmask); 13501c6a0718SPierre Ossman 13511c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 13521c6a0718SPierre Ossman writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), 13531c6a0718SPierre Ossman host->ioaddr + SDHCI_INT_STATUS); 13541c6a0718SPierre Ossman tasklet_schedule(&host->card_tasklet); 13551c6a0718SPierre Ossman } 13561c6a0718SPierre Ossman 13571c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 13581c6a0718SPierre Ossman 13591c6a0718SPierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 13601c6a0718SPierre Ossman writel(intmask & SDHCI_INT_CMD_MASK, 13611c6a0718SPierre Ossman host->ioaddr + SDHCI_INT_STATUS); 13621c6a0718SPierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 13631c6a0718SPierre Ossman } 13641c6a0718SPierre Ossman 13651c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 13661c6a0718SPierre Ossman writel(intmask & SDHCI_INT_DATA_MASK, 13671c6a0718SPierre Ossman host->ioaddr + SDHCI_INT_STATUS); 13681c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 13691c6a0718SPierre Ossman } 13701c6a0718SPierre Ossman 13711c6a0718SPierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 13721c6a0718SPierre Ossman 1373964f9ce2SPierre Ossman intmask &= ~SDHCI_INT_ERROR; 1374964f9ce2SPierre Ossman 13751c6a0718SPierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 13761c6a0718SPierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 13771c6a0718SPierre Ossman mmc_hostname(host->mmc)); 13781c6a0718SPierre Ossman writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS); 13791c6a0718SPierre Ossman } 13801c6a0718SPierre Ossman 13819d26a5d3SRolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 13821c6a0718SPierre Ossman 1383f75979b7SPierre Ossman if (intmask & SDHCI_INT_CARD_INT) 1384f75979b7SPierre Ossman cardint = 1; 1385f75979b7SPierre Ossman 1386f75979b7SPierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 1387f75979b7SPierre Ossman 13881c6a0718SPierre Ossman if (intmask) { 13891c6a0718SPierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 13901c6a0718SPierre Ossman mmc_hostname(host->mmc), intmask); 13911c6a0718SPierre Ossman sdhci_dumpregs(host); 13921c6a0718SPierre Ossman 13931c6a0718SPierre Ossman writel(intmask, host->ioaddr + SDHCI_INT_STATUS); 13941c6a0718SPierre Ossman } 13951c6a0718SPierre Ossman 13961c6a0718SPierre Ossman result = IRQ_HANDLED; 13971c6a0718SPierre Ossman 13981c6a0718SPierre Ossman mmiowb(); 13991c6a0718SPierre Ossman out: 14001c6a0718SPierre Ossman spin_unlock(&host->lock); 14011c6a0718SPierre Ossman 1402f75979b7SPierre Ossman /* 1403f75979b7SPierre Ossman * We have to delay this as it calls back into the driver. 1404f75979b7SPierre Ossman */ 1405f75979b7SPierre Ossman if (cardint) 1406f75979b7SPierre Ossman mmc_signal_sdio_irq(host->mmc); 1407f75979b7SPierre Ossman 14081c6a0718SPierre Ossman return result; 14091c6a0718SPierre Ossman } 14101c6a0718SPierre Ossman 14111c6a0718SPierre Ossman /*****************************************************************************\ 14121c6a0718SPierre Ossman * * 14131c6a0718SPierre Ossman * Suspend/resume * 14141c6a0718SPierre Ossman * * 14151c6a0718SPierre Ossman \*****************************************************************************/ 14161c6a0718SPierre Ossman 14171c6a0718SPierre Ossman #ifdef CONFIG_PM 14181c6a0718SPierre Ossman 1419b8c86fc5SPierre Ossman int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 14201c6a0718SPierre Ossman { 1421b8c86fc5SPierre Ossman int ret; 14221c6a0718SPierre Ossman 1423b8c86fc5SPierre Ossman ret = mmc_suspend_host(host->mmc, state); 14241c6a0718SPierre Ossman if (ret) 14251c6a0718SPierre Ossman return ret; 14261c6a0718SPierre Ossman 1427b8c86fc5SPierre Ossman free_irq(host->irq, host); 1428b8c86fc5SPierre Ossman 1429b8c86fc5SPierre Ossman return 0; 1430b8c86fc5SPierre Ossman } 1431b8c86fc5SPierre Ossman 1432b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 1433b8c86fc5SPierre Ossman 1434b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 1435b8c86fc5SPierre Ossman { 1436b8c86fc5SPierre Ossman int ret; 1437b8c86fc5SPierre Ossman 1438b8c86fc5SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 1439b8c86fc5SPierre Ossman if (host->ops->enable_dma) 1440b8c86fc5SPierre Ossman host->ops->enable_dma(host); 1441b8c86fc5SPierre Ossman } 1442b8c86fc5SPierre Ossman 1443b8c86fc5SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1444b8c86fc5SPierre Ossman mmc_hostname(host->mmc), host); 14451c6a0718SPierre Ossman if (ret) 14461c6a0718SPierre Ossman return ret; 1447b8c86fc5SPierre Ossman 1448b8c86fc5SPierre Ossman sdhci_init(host); 14491c6a0718SPierre Ossman mmiowb(); 1450b8c86fc5SPierre Ossman 1451b8c86fc5SPierre Ossman ret = mmc_resume_host(host->mmc); 14521c6a0718SPierre Ossman if (ret) 14531c6a0718SPierre Ossman return ret; 14541c6a0718SPierre Ossman 14551c6a0718SPierre Ossman return 0; 14561c6a0718SPierre Ossman } 14571c6a0718SPierre Ossman 1458b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 14591c6a0718SPierre Ossman 14601c6a0718SPierre Ossman #endif /* CONFIG_PM */ 14611c6a0718SPierre Ossman 14621c6a0718SPierre Ossman /*****************************************************************************\ 14631c6a0718SPierre Ossman * * 1464b8c86fc5SPierre Ossman * Device allocation/registration * 14651c6a0718SPierre Ossman * * 14661c6a0718SPierre Ossman \*****************************************************************************/ 14671c6a0718SPierre Ossman 1468b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 1469b8c86fc5SPierre Ossman size_t priv_size) 14701c6a0718SPierre Ossman { 14711c6a0718SPierre Ossman struct mmc_host *mmc; 14721c6a0718SPierre Ossman struct sdhci_host *host; 14731c6a0718SPierre Ossman 1474b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 14751c6a0718SPierre Ossman 1476b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 14771c6a0718SPierre Ossman if (!mmc) 1478b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 14791c6a0718SPierre Ossman 14801c6a0718SPierre Ossman host = mmc_priv(mmc); 14811c6a0718SPierre Ossman host->mmc = mmc; 14821c6a0718SPierre Ossman 1483b8c86fc5SPierre Ossman return host; 14841c6a0718SPierre Ossman } 14851c6a0718SPierre Ossman 1486b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 1487b8c86fc5SPierre Ossman 1488b8c86fc5SPierre Ossman int sdhci_add_host(struct sdhci_host *host) 1489b8c86fc5SPierre Ossman { 1490b8c86fc5SPierre Ossman struct mmc_host *mmc; 1491b8c86fc5SPierre Ossman unsigned int caps; 1492b8c86fc5SPierre Ossman int ret; 1493b8c86fc5SPierre Ossman 1494b8c86fc5SPierre Ossman WARN_ON(host == NULL); 1495b8c86fc5SPierre Ossman if (host == NULL) 1496b8c86fc5SPierre Ossman return -EINVAL; 1497b8c86fc5SPierre Ossman 1498b8c86fc5SPierre Ossman mmc = host->mmc; 1499b8c86fc5SPierre Ossman 1500b8c86fc5SPierre Ossman if (debug_quirks) 1501b8c86fc5SPierre Ossman host->quirks = debug_quirks; 1502b8c86fc5SPierre Ossman 15031c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 15041c6a0718SPierre Ossman 15052134a922SPierre Ossman host->version = readw(host->ioaddr + SDHCI_HOST_VERSION); 15062134a922SPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 15072134a922SPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 15082134a922SPierre Ossman if (host->version > SDHCI_SPEC_200) { 15091c6a0718SPierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 1510b69c9058SPierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 15112134a922SPierre Ossman host->version); 15121c6a0718SPierre Ossman } 15131c6a0718SPierre Ossman 15141c6a0718SPierre Ossman caps = readl(host->ioaddr + SDHCI_CAPABILITIES); 15151c6a0718SPierre Ossman 1516b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 15171c6a0718SPierre Ossman host->flags |= SDHCI_USE_DMA; 15181c6a0718SPierre Ossman else if (!(caps & SDHCI_CAN_DO_DMA)) 15191c6a0718SPierre Ossman DBG("Controller doesn't have DMA capability\n"); 15201c6a0718SPierre Ossman else 15211c6a0718SPierre Ossman host->flags |= SDHCI_USE_DMA; 15221c6a0718SPierre Ossman 1523b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 15247c168e3dSFeng Tang (host->flags & SDHCI_USE_DMA)) { 1525cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 15267c168e3dSFeng Tang host->flags &= ~SDHCI_USE_DMA; 15277c168e3dSFeng Tang } 15287c168e3dSFeng Tang 15291c6a0718SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 15302134a922SPierre Ossman if ((host->version >= SDHCI_SPEC_200) && 15312134a922SPierre Ossman (caps & SDHCI_CAN_DO_ADMA2)) 15322134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 15332134a922SPierre Ossman } 15342134a922SPierre Ossman 15352134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 15362134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 15372134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 15382134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 15392134a922SPierre Ossman } 15402134a922SPierre Ossman 15412134a922SPierre Ossman if (host->flags & SDHCI_USE_DMA) { 1542b8c86fc5SPierre Ossman if (host->ops->enable_dma) { 1543b8c86fc5SPierre Ossman if (host->ops->enable_dma(host)) { 1544b8c86fc5SPierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 1545b8c86fc5SPierre Ossman "available. Falling back to PIO.\n", 1546b8c86fc5SPierre Ossman mmc_hostname(mmc)); 15472134a922SPierre Ossman host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA); 15481c6a0718SPierre Ossman } 15491c6a0718SPierre Ossman } 1550b8c86fc5SPierre Ossman } 15511c6a0718SPierre Ossman 15522134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 15532134a922SPierre Ossman /* 15542134a922SPierre Ossman * We need to allocate descriptors for all sg entries 15552134a922SPierre Ossman * (128) and potentially one alignment transfer for 15562134a922SPierre Ossman * each of those entries. 15572134a922SPierre Ossman */ 15582134a922SPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 15592134a922SPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 15602134a922SPierre Ossman if (!host->adma_desc || !host->align_buffer) { 15612134a922SPierre Ossman kfree(host->adma_desc); 15622134a922SPierre Ossman kfree(host->align_buffer); 15632134a922SPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 15642134a922SPierre Ossman "buffers. Falling back to standard DMA.\n", 15652134a922SPierre Ossman mmc_hostname(mmc)); 15662134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 15672134a922SPierre Ossman } 15682134a922SPierre Ossman } 15692134a922SPierre Ossman 15707659150cSPierre Ossman /* 15717659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 15727659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 15737659150cSPierre Ossman * mask here in that case. 15747659150cSPierre Ossman */ 15757659150cSPierre Ossman if (!(host->flags & SDHCI_USE_DMA)) { 15767659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 15777659150cSPierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 15787659150cSPierre Ossman } 15791c6a0718SPierre Ossman 15801c6a0718SPierre Ossman host->max_clk = 15811c6a0718SPierre Ossman (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 15821c6a0718SPierre Ossman if (host->max_clk == 0) { 15831c6a0718SPierre Ossman printk(KERN_ERR "%s: Hardware doesn't specify base clock " 1584b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1585b8c86fc5SPierre Ossman return -ENODEV; 15861c6a0718SPierre Ossman } 15871c6a0718SPierre Ossman host->max_clk *= 1000000; 15881c6a0718SPierre Ossman 15891c6a0718SPierre Ossman host->timeout_clk = 15901c6a0718SPierre Ossman (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 15911c6a0718SPierre Ossman if (host->timeout_clk == 0) { 15921c6a0718SPierre Ossman printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " 1593b69c9058SPierre Ossman "frequency.\n", mmc_hostname(mmc)); 1594b8c86fc5SPierre Ossman return -ENODEV; 15951c6a0718SPierre Ossman } 15961c6a0718SPierre Ossman if (caps & SDHCI_TIMEOUT_CLK_UNIT) 15971c6a0718SPierre Ossman host->timeout_clk *= 1000; 15981c6a0718SPierre Ossman 15991c6a0718SPierre Ossman /* 16001c6a0718SPierre Ossman * Set host parameters. 16011c6a0718SPierre Ossman */ 16021c6a0718SPierre Ossman mmc->ops = &sdhci_ops; 16031c6a0718SPierre Ossman mmc->f_min = host->max_clk / 256; 16041c6a0718SPierre Ossman mmc->f_max = host->max_clk; 1605c9b74c5bSPierre Ossman mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; 16061c6a0718SPierre Ossman 16071c6a0718SPierre Ossman if (caps & SDHCI_CAN_DO_HISPD) 16081c6a0718SPierre Ossman mmc->caps |= MMC_CAP_SD_HIGHSPEED; 16091c6a0718SPierre Ossman 16101c6a0718SPierre Ossman mmc->ocr_avail = 0; 16111c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_330) 16121c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; 16131c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_300) 16141c6a0718SPierre Ossman mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; 16151c6a0718SPierre Ossman if (caps & SDHCI_CAN_VDD_180) 161655556da0SPhilip Langdale mmc->ocr_avail |= MMC_VDD_165_195; 16171c6a0718SPierre Ossman 16181c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 16191c6a0718SPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 1620b69c9058SPierre Ossman "support voltages.\n", mmc_hostname(mmc)); 1621b8c86fc5SPierre Ossman return -ENODEV; 16221c6a0718SPierre Ossman } 16231c6a0718SPierre Ossman 16241c6a0718SPierre Ossman spin_lock_init(&host->lock); 16251c6a0718SPierre Ossman 16261c6a0718SPierre Ossman /* 16272134a922SPierre Ossman * Maximum number of segments. Depends on if the hardware 16282134a922SPierre Ossman * can do scatter/gather or not. 16291c6a0718SPierre Ossman */ 16302134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 16312134a922SPierre Ossman mmc->max_hw_segs = 128; 16322134a922SPierre Ossman else if (host->flags & SDHCI_USE_DMA) 16331c6a0718SPierre Ossman mmc->max_hw_segs = 1; 16342134a922SPierre Ossman else /* PIO */ 16352134a922SPierre Ossman mmc->max_hw_segs = 128; 16362134a922SPierre Ossman mmc->max_phys_segs = 128; 16371c6a0718SPierre Ossman 16381c6a0718SPierre Ossman /* 16391c6a0718SPierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 16401c6a0718SPierre Ossman * size (512KiB). 16411c6a0718SPierre Ossman */ 16421c6a0718SPierre Ossman mmc->max_req_size = 524288; 16431c6a0718SPierre Ossman 16441c6a0718SPierre Ossman /* 16451c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 16462134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 16472134a922SPierre Ossman * be larger than 64 KiB though. 16481c6a0718SPierre Ossman */ 16492134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) 16502134a922SPierre Ossman mmc->max_seg_size = 65536; 16512134a922SPierre Ossman else 16521c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 16531c6a0718SPierre Ossman 16541c6a0718SPierre Ossman /* 16551c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 16561c6a0718SPierre Ossman * is specified in the capabilities register. 16571c6a0718SPierre Ossman */ 16581c6a0718SPierre Ossman mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; 16591c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 1660b69c9058SPierre Ossman printk(KERN_WARNING "%s: Invalid maximum block size, " 1661b69c9058SPierre Ossman "assuming 512 bytes\n", mmc_hostname(mmc)); 166203f8590dSDavid Vrabel mmc->max_blk_size = 512; 166303f8590dSDavid Vrabel } else 16641c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 16651c6a0718SPierre Ossman 16661c6a0718SPierre Ossman /* 16671c6a0718SPierre Ossman * Maximum block count. 16681c6a0718SPierre Ossman */ 16691c6a0718SPierre Ossman mmc->max_blk_count = 65535; 16701c6a0718SPierre Ossman 16711c6a0718SPierre Ossman /* 16721c6a0718SPierre Ossman * Init tasklets. 16731c6a0718SPierre Ossman */ 16741c6a0718SPierre Ossman tasklet_init(&host->card_tasklet, 16751c6a0718SPierre Ossman sdhci_tasklet_card, (unsigned long)host); 16761c6a0718SPierre Ossman tasklet_init(&host->finish_tasklet, 16771c6a0718SPierre Ossman sdhci_tasklet_finish, (unsigned long)host); 16781c6a0718SPierre Ossman 16791c6a0718SPierre Ossman setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 16801c6a0718SPierre Ossman 16811c6a0718SPierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1682b69c9058SPierre Ossman mmc_hostname(mmc), host); 16831c6a0718SPierre Ossman if (ret) 16841c6a0718SPierre Ossman goto untasklet; 16851c6a0718SPierre Ossman 16861c6a0718SPierre Ossman sdhci_init(host); 16871c6a0718SPierre Ossman 16881c6a0718SPierre Ossman #ifdef CONFIG_MMC_DEBUG 16891c6a0718SPierre Ossman sdhci_dumpregs(host); 16901c6a0718SPierre Ossman #endif 16911c6a0718SPierre Ossman 16922f730fecSPierre Ossman #ifdef CONFIG_LEDS_CLASS 16932f730fecSPierre Ossman host->led.name = mmc_hostname(mmc); 16942f730fecSPierre Ossman host->led.brightness = LED_OFF; 16952f730fecSPierre Ossman host->led.default_trigger = mmc_hostname(mmc); 16962f730fecSPierre Ossman host->led.brightness_set = sdhci_led_control; 16972f730fecSPierre Ossman 1698b8c86fc5SPierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 16992f730fecSPierre Ossman if (ret) 17002f730fecSPierre Ossman goto reset; 17012f730fecSPierre Ossman #endif 17022f730fecSPierre Ossman 17031c6a0718SPierre Ossman mmiowb(); 17041c6a0718SPierre Ossman 17051c6a0718SPierre Ossman mmc_add_host(mmc); 17061c6a0718SPierre Ossman 17072134a922SPierre Ossman printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", 1708b8c86fc5SPierre Ossman mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->bus_id, 17092134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)?"A":"", 17101c6a0718SPierre Ossman (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); 17111c6a0718SPierre Ossman 17121c6a0718SPierre Ossman return 0; 17131c6a0718SPierre Ossman 17142f730fecSPierre Ossman #ifdef CONFIG_LEDS_CLASS 17152f730fecSPierre Ossman reset: 17162f730fecSPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 17172f730fecSPierre Ossman free_irq(host->irq, host); 17182f730fecSPierre Ossman #endif 17191c6a0718SPierre Ossman untasklet: 17201c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 17211c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 17221c6a0718SPierre Ossman 17231c6a0718SPierre Ossman return ret; 17241c6a0718SPierre Ossman } 17251c6a0718SPierre Ossman 1726b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 1727b8c86fc5SPierre Ossman 17281e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 17291c6a0718SPierre Ossman { 17301e72859eSPierre Ossman unsigned long flags; 17311e72859eSPierre Ossman 17321e72859eSPierre Ossman if (dead) { 17331e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 17341e72859eSPierre Ossman 17351e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 17361e72859eSPierre Ossman 17371e72859eSPierre Ossman if (host->mrq) { 17381e72859eSPierre Ossman printk(KERN_ERR "%s: Controller removed during " 17391e72859eSPierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 17401e72859eSPierre Ossman 17411e72859eSPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 17421e72859eSPierre Ossman tasklet_schedule(&host->finish_tasklet); 17431e72859eSPierre Ossman } 17441e72859eSPierre Ossman 17451e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 17461e72859eSPierre Ossman } 17471e72859eSPierre Ossman 1748b8c86fc5SPierre Ossman mmc_remove_host(host->mmc); 17491c6a0718SPierre Ossman 17502f730fecSPierre Ossman #ifdef CONFIG_LEDS_CLASS 17512f730fecSPierre Ossman led_classdev_unregister(&host->led); 17522f730fecSPierre Ossman #endif 17532f730fecSPierre Ossman 17541e72859eSPierre Ossman if (!dead) 17551c6a0718SPierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 17561c6a0718SPierre Ossman 17571c6a0718SPierre Ossman free_irq(host->irq, host); 17581c6a0718SPierre Ossman 17591c6a0718SPierre Ossman del_timer_sync(&host->timer); 17601c6a0718SPierre Ossman 17611c6a0718SPierre Ossman tasklet_kill(&host->card_tasklet); 17621c6a0718SPierre Ossman tasklet_kill(&host->finish_tasklet); 17632134a922SPierre Ossman 17642134a922SPierre Ossman kfree(host->adma_desc); 17652134a922SPierre Ossman kfree(host->align_buffer); 17662134a922SPierre Ossman 17672134a922SPierre Ossman host->adma_desc = NULL; 17682134a922SPierre Ossman host->align_buffer = NULL; 17691c6a0718SPierre Ossman } 17701c6a0718SPierre Ossman 1771b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 1772b8c86fc5SPierre Ossman 1773b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 17741c6a0718SPierre Ossman { 1775b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 17761c6a0718SPierre Ossman } 17771c6a0718SPierre Ossman 1778b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 17791c6a0718SPierre Ossman 17801c6a0718SPierre Ossman /*****************************************************************************\ 17811c6a0718SPierre Ossman * * 17821c6a0718SPierre Ossman * Driver init/exit * 17831c6a0718SPierre Ossman * * 17841c6a0718SPierre Ossman \*****************************************************************************/ 17851c6a0718SPierre Ossman 17861c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 17871c6a0718SPierre Ossman { 17881c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME 17891c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 17901c6a0718SPierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 17911c6a0718SPierre Ossman 1792b8c86fc5SPierre Ossman return 0; 17931c6a0718SPierre Ossman } 17941c6a0718SPierre Ossman 17951c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 17961c6a0718SPierre Ossman { 17971c6a0718SPierre Ossman } 17981c6a0718SPierre Ossman 17991c6a0718SPierre Ossman module_init(sdhci_drv_init); 18001c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 18011c6a0718SPierre Ossman 18021c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 18031c6a0718SPierre Ossman 18041c6a0718SPierre Ossman MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); 1805b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 18061c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 18071c6a0718SPierre Ossman 18081c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 1809