sdhci.c revision 4f3d3e9b50931a3ec70f324d53fb7437e2a39388
1d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/* 270f10482c668301c483acded13bf68780ad352b9Pierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver 3d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * 4b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. 5d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * 6d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * This program is free software; you can redistribute it and/or modify 7643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * it under the terms of the GNU General Public License as published by 8643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 9643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * your option) any later version. 1084c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * 1184c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * Thanks to the following companies for their support: 1284c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * 1384c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * - JMicron (hardware and technical support) 14d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 15d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/delay.h> 17d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/highmem.h> 18b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman#include <linux/io.h> 19d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/dma-mapping.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 21117636092a87a28a013a4acb5de5492645ed620fRalf Baechle#include <linux/scatterlist.h> 229bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski#include <linux/regulator/consumer.h> 23d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 242f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#include <linux/leds.h> 252f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2622113efd00491310da802f3b1a9a66cfcf415facAries Lee#include <linux/mmc/mmc.h> 27d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/mmc/host.h> 28d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 29d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include "sdhci.h" 30d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 31d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DRIVER_NAME "sdhci" 32d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 33d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DBG(f, x...) \ 34c65631781eb0f2e81865017c1484e9aef76e1b61Russell King pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 35d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 36f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 37f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman defined(CONFIG_MMC_SDHCI_MODULE)) 38f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#define SDHCI_USE_LEDS_CLASS 39f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#endif 40f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman 41b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath#define MAX_TUNING_LOOP 40 42b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 43df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanstatic unsigned int debug_quirks = 0; 446743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 45d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *); 46d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 47d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 48d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *); 49cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nathstatic int sdhci_execute_tuning(struct mmc_host *mmc); 50cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nathstatic void sdhci_tuning_timer(unsigned long data); 51d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 52d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_dumpregs(struct sdhci_host *host) 53d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 54412ab659b2bdad6afac8f84daf2a8a393145dcaePhilip Rakity printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", 55412ab659b2bdad6afac8f84daf2a8a393145dcaePhilip Rakity mmc_hostname(host->mmc)); 56d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 57d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 584e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 594e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 60d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 614e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 624e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 63d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 644e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 654e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 66d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 674e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 684e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 69d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 714e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 72d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 734e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 744e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 75d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 764e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 774e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 78d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 804e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 81d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 824e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 834e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 84e8120ad129c160ff5b2e2b197d025a2cd661c2f2Philip Rakity printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", 854e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 86e8120ad129c160ff5b2e2b197d025a2cd661c2f2Philip Rakity sdhci_readl(host, SDHCI_CAPABILITIES_1)); 87e8120ad129c160ff5b2e2b197d025a2cd661c2f2Philip Rakity printk(KERN_DEBUG DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n", 88e8120ad129c160ff5b2e2b197d025a2cd661c2f2Philip Rakity sdhci_readw(host, SDHCI_COMMAND), 894e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 90f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath printk(KERN_DEBUG DRIVER_NAME ": Host ctl2: 0x%08x\n", 91f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_readw(host, SDHCI_HOST_CONTROL2)); 92d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 93be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks if (host->flags & SDHCI_USE_ADMA) 94be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 95be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ERROR), 96be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); 97be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks 98d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 99d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 100d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 101d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 102d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 103d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Low level functions * 104d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 105d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 106d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1077260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 1087260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1097260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 ier; 1107260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1117260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1127260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier &= ~clear; 1137260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier |= set; 1147260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_INT_ENABLE); 1157260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 1167260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1177260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1187260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) 1197260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1207260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, 0, irqs); 1217260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1227260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1237260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) 1247260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1257260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, irqs, 0); 1267260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1277260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1287260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1297260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1307260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 1317260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 13268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 13368d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov return; 13468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 1357260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov if (enable) 1367260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, irqs); 1377260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 1387260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, irqs); 1397260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1407260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1417260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_enable_card_detection(struct sdhci_host *host) 1427260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1437260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, true); 1447260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1457260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1467260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_disable_card_detection(struct sdhci_host *host) 1477260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1487260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, false); 1497260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1507260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_reset(struct sdhci_host *host, u8 mask) 152d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 153e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman unsigned long timeout; 154063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov u32 uninitialized_var(ier); 155e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 156b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 1574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & 1588a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman SDHCI_CARD_PRESENT)) 1598a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman return; 1608a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman } 1618a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 162063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 163063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 164063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 165393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity if (host->ops->platform_reset_enter) 166393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity host->ops->platform_reset_enter(host, mask); 167393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity 1684e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 169d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 170e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (mask & SDHCI_RESET_ALL) 171d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = 0; 172d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 173e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* Wait max 100 ms */ 174e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout = 100; 175e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 176e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* hw clears the bit when it's done */ 1774e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 178e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (timeout == 0) { 179acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 180e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mmc_hostname(host->mmc), (int)mask); 181e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman sdhci_dumpregs(host); 182e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman return; 183e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman } 184e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout--; 185e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mdelay(1); 186d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 187063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 188393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity if (host->ops->platform_reset_exit) 189393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity host->ops->platform_reset_exit(host, mask); 190393c1a34dd852dbf0c409ec94dd48057100480eaPhilip Rakity 191063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 192063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 193d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 194d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1952f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitrestatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); 1962f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre 1972f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitrestatic void sdhci_init(struct sdhci_host *host, int soft) 198d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1992f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre if (soft) 2002f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); 2012f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre else 2022f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_reset(host, SDHCI_RESET_ALL); 203d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2047260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 2057260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 2063192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 2073192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 2086aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 2092f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre 2102f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre if (soft) { 2112f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre /* force clock reconfiguration */ 2122f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre host->clock = 0; 2132f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_set_ios(host->mmc, &host->mmc->ios); 2142f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre } 2157260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 216d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2177260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_reinit(struct sdhci_host *host) 2187260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 2192f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, 0); 2207260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 221d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 223d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_activate_led(struct sdhci_host *host) 224d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 225d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 226d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2274e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 228d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl |= SDHCI_CTRL_LED; 2294e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 231d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 232d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_deactivate_led(struct sdhci_host *host) 233d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 234d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 235d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2364e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 237d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2384e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 239d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 240d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 241f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 2422f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanstatic void sdhci_led_control(struct led_classdev *led, 2432f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman enum led_brightness brightness) 2442f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman{ 2452f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2462f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman unsigned long flags; 2472f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2482f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_lock_irqsave(&host->lock, flags); 2492f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2502f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (brightness == LED_OFF) 2512f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_deactivate_led(host); 2522f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman else 2532f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_activate_led(host); 2542f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2552f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2562f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman} 2572f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 2582f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 259d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 260d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 261d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Core functions * 262d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 263d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 264d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 265a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_read_block_pio(struct sdhci_host *host) 266d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2677659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 2687659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 2697244b85bd17313d7d300ee93ec7bfbca1f4ccf3dSteven Noonan u32 uninitialized_var(scratch); 2707659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 271d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 272a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO reading\n"); 273d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 274a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 2757659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 276d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2777659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 278d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 279a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 2807659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 2817659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 282d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2837659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 284d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2857659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 2867659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 28714d836e7499c53a1f6a65086c3d11600e871a971Alex Dubov 2887659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 289d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2907659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 2917659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (chunk == 0) { 2924e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 2937659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 4; 294a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 2957659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2967659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman *buf = scratch & 0xFF; 2977659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2987659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 2997659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch >>= 8; 3007659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk--; 3017659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 302d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 303a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 3047659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3057659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 3067659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3077659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 308a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 309d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 310a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_write_block_pio(struct sdhci_host *host) 311a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 3127659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 3137659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 3147659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u32 scratch; 3157659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 316d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 317a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO writing\n"); 318a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 319a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 3207659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 3217659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 322d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3237659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 324d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 325a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 3267659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 3277659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 328a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3297659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 3307659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3317659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 3327659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 3337659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3347659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 335d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3367659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 3377659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch |= (u32)*buf << (chunk * 8); 3387659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3397659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 3407659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk++; 3417659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 3427659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3437659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 3444e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 3457659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 3467659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 347d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 348d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 349d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 3507659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3517659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 3527659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3537659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 354a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 355a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 356a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_transfer_pio(struct sdhci_host *host) 357a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 358a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman u32 mask; 359a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 360a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman BUG_ON(!host->data); 361a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3627659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 363a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman return; 364a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 365a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 366a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_DATA_AVAILABLE; 367a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 368a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_SPACE_AVAILABLE; 369a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3704a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman /* 3714a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 3724a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * for transfers < 4 bytes. As long as it is just one block, 3734a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * we can ignore the bits. 3744a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman */ 3754a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 3764a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman (host->data->blocks == 1)) 3774a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman mask = ~0; 3784a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman 3794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 3803e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 3813e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov udelay(100); 3823e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov 383a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 384a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_read_block_pio(host); 385a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 386a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_write_block_pio(host); 387d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3887659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks--; 3897659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 390a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman break; 391a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 392d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 393a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO transfer complete.\n"); 394d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 395d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_save(*flags); 3992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 4002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 4012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 4032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 4042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 4052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_restore(*flags); 4062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 4072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 408118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooksstatic void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd) 409118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks{ 4109e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks __le32 *dataddr = (__le32 __force *)(desc + 4); 4119e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks __le16 *cmdlen = (__le16 __force *)desc; 412118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 4139e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks /* SDHCI specification says ADMA descriptors should be 4 byte 4149e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks * aligned, so using 16 or 32bit operations should be safe. */ 415118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 4169e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks cmdlen[0] = cpu_to_le16(cmd); 4179e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks cmdlen[1] = cpu_to_le16(len); 4189e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks 4199e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks dataddr[0] = cpu_to_le32(addr); 420118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks} 421118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 4228f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanstatic int sdhci_adma_table_pre(struct sdhci_host *host, 4232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 4242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 4252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 4262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *desc; 4282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 4292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t addr; 4302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t align_addr; 4312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int len, offset; 4322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 4342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i; 4352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 4362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 4372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The spec does not specify endianness of descriptor table. 4402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We currently guess that it is LE. 4412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 4442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 4452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 4462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 4472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The ADMA descriptor table is mapped further down as we 4502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * need to fill it with data first. 4512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 4542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer, 128 * 4, direction); 4558d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4568f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto fail; 4572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->align_addr & 0x3); 4582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 4602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg, data->sg_len, direction); 4618f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->sg_count == 0) 4628f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_align; 4632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc = host->adma_desc; 4652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 4662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr = host->align_addr; 4682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr = sg_dma_address(sg); 4712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len = sg_dma_len(sg); 4722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The SDHCI specification states that ADMA 4752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * addresses must be 32-bit aligned. If they 4762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * aren't, then we use a bounce buffer for 4772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * the (up to three) bytes that screw up the 4782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment. 4792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 4812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (offset) { 4822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 4846cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 4852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(align, buffer, offset); 4862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 4872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 489118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks /* tran, valid */ 490118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks sdhci_set_adma_desc(desc, align_addr, offset, 0x21); 4912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(offset > 65536); 4932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 4952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr += 4; 4962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 4982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr += offset; 5002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len -= offset; 5012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(len > 65536); 5042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 505118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks /* tran, valid */ 506118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks sdhci_set_adma_desc(desc, addr, len, 0x21); 5072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 5082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 5102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * If this triggers then we have a calculation bug 5112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * somewhere. :/ 5122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 5132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 5142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 51670764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 51770764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* 51870764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham * Mark the last descriptor as the terminating descriptor 51970764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham */ 52070764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham if (desc != host->adma_desc) { 52170764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham desc -= 8; 52270764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham desc[0] |= 0x2; /* end */ 52370764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } 52470764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } else { 52570764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* 52670764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham * Add a terminating entry. 52770764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham */ 5282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 52970764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* nop, end, valid */ 53070764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham sdhci_set_adma_desc(desc, 0, 0, 0x3); 53170764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } 5322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 5342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Resync align buffer as we might have changed it. 5352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 5362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 5382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr, 128 * 4, direction); 5392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 5422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 543980167b7fb20fb181766218b4771fc7420a7bbb4Pierre Ossman if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) 5448f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_entries; 5452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->adma_addr & 0x3); 5468f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5478f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return 0; 5488f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5498f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_entries: 5508f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5518f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg_len, direction); 5528f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_align: 5538f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5548f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 128 * 4, direction); 5558f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanfail: 5568f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return -EINVAL; 5572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 5582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_adma_table_post(struct sdhci_host *host, 5602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 5612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 5622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 5632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 5652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i, size; 5662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 5672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 5682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 5692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 5712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 5722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 5732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 5742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 5762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 5772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 128 * 4, direction); 5802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) { 5822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 5832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 5842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 5862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg_dma_address(sg) & 0x3) { 5892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 5902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5926cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(buffer, align, size); 5942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 5972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 6002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 6022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 6032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 6042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 605a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentinstatic u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) 606d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 6071c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman u8 count; 608a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin struct mmc_data *data = cmd->data; 6091c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman unsigned target_timeout, current_timeout; 610d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 611ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* 612ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * If the host controller provides us with an incorrect timeout 613ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * value, just skip the check and use 0xE. The hardware may take 614ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * longer to time out, but that's much better than having a too-short 615ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * timeout value. 616ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman */ 61711a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 618ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return 0xE; 619e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 620a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin /* Unspecified timeout, assume max */ 621a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin if (!data && !cmd->cmd_timeout_ms) 622a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin return 0xE; 623d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 624a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin /* timeout in us */ 625a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin if (!data) 626a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin target_timeout = cmd->cmd_timeout_ms * 1000; 627a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin else 628a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin target_timeout = data->timeout_ns / 1000 + 629a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin data->timeout_clks / host->clock; 63081b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov 6314b01681c77642c62a833187066c35e71e59caaf5Mark Brown if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) 6324b01681c77642c62a833187066c35e71e59caaf5Mark Brown host->timeout_clk = host->clock / 1000; 6334b01681c77642c62a833187066c35e71e59caaf5Mark Brown 6341c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman /* 6351c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * Figure out needed cycles. 6361c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * We do this in steps in order to fit inside a 32 bit int. 6371c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * The first step is the minimum timeout, which will have a 6381c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * minimum resolution of 6 bits: 6391c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) 2^13*1000 > 2^22, 6401c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (2) host->timeout_clk < 2^16 6411c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * => 6421c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) / (2) > 2^6 6431c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman */ 6444b01681c77642c62a833187066c35e71e59caaf5Mark Brown BUG_ON(!host->timeout_clk); 6451c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0; 6461c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 6471c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman while (current_timeout < target_timeout) { 6481c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count++; 6491c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout <<= 1; 6501c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) 6511c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman break; 6521c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6531c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 6541c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) { 655a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n", 656a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin mmc_hostname(host->mmc), cmd->opcode); 6571c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0xE; 6581c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6591c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 660ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return count; 661ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman} 662ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 6636aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsovstatic void sdhci_set_transfer_irqs(struct sdhci_host *host) 6646aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov{ 6656aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 6666aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 6676aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 6686aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 6696aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 6706aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov else 6716aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); 6726aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov} 6736aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 674a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentinstatic void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 675ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman{ 676ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman u8 count; 6772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 ctrl; 678a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin struct mmc_data *data = cmd->data; 6798f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman int ret; 680ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 681ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman WARN_ON(host->data); 682ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 683a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin if (data || (cmd->flags & MMC_RSP_BUSY)) { 684a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin count = sdhci_calc_timeout(host, cmd); 685a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 686a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin } 687a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin 688a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin if (!data) 689ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return; 690ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 691ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* Sanity checks */ 692ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 693ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 694ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blocks > 65535); 695ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 696ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data = data; 697ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data_early = 0; 698f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni host->data->bytes_xfered = 0; 699ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 700a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) 701c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 702c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 7032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * FIXME: This doesn't account for merging when mapping the 7052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * scatterlist. 7062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 7092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 7102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 7122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 7162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 7172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 7212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->length & 0x3) { 7232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 7242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "transfer size (%d)\n", 7252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sg->length); 7262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 7282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 731c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 732c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 733c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman /* 734c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * The assumption here being that alignment is the same after 735c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * translation to device address space. 736c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman */ 7372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 7392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 7402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 7422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * As we use 3 byte chunks to work around 7452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment problems, we need to check this 7462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * quirk. 7472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 7512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 7522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 7562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->offset & 0x3) { 7582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 7592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "bad alignment\n"); 7602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 7622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7678f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7688f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7698f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman ret = sdhci_adma_table_pre(host, data); 7708f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (ret) { 7718f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7728f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7738f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7748f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7758f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 776ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7778f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 7784e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, host->adma_addr, 7794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_ADMA_ADDRESS); 7808f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7818f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 782c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler int sg_cnt; 7838f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 784c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 7858f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg, data->sg_len, 7868f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman (data->flags & MMC_DATA_READ) ? 7878f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_FROM_DEVICE : 7888f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_TO_DEVICE); 789c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler if (sg_cnt == 0) { 7908f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7918f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7928f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7938f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7948f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 795ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7968f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 797719a61b452ff74cf81a96e4212748d9d63bcc924Pierre Ossman WARN_ON(sg_cnt != 1); 7984e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 7994e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_DMA_ADDRESS); 8008f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 8018f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 8028f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 8038f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 8042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 8052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Always adjust the DMA selection as some controllers 8062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 8072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * is ADMA. 8082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 8092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->version >= SDHCI_SPEC_200) { 8104e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 8112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 8122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 8132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) 8142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 8152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 8162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 8174e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 818c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 819c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 8208f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 821da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior int flags; 822da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior 823da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 824da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 825da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 826da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior else 827da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 828da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 8297659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks = data->blocks; 830d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 831c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 8326aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_set_transfer_irqs(host); 8336aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 834f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni /* Set the DMA boundary value and block size */ 835f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 836f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni data->blksz), SDHCI_BLOCK_SIZE); 8374e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 838c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman} 839c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 840c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossmanstatic void sdhci_set_transfer_mode(struct sdhci_host *host, 841e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin struct mmc_command *cmd) 842c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman{ 843c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman u16 mode; 844e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin struct mmc_data *data = cmd->data; 845c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 846c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data == NULL) 847c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman return; 848c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 849e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman WARN_ON(!host->data); 850e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 851c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 852e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 853e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin mode |= SDHCI_TRNS_MULTI; 854e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin /* 855e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * If we are sending CMD23, CMD12 never gets sent 856e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * on successful completion (so no Auto-CMD12). 857e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin */ 858e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) 859e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin mode |= SDHCI_TRNS_AUTO_CMD12; 8608edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { 8618edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin mode |= SDHCI_TRNS_AUTO_CMD23; 8628edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin sdhci_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); 8638edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin } 864c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 8658edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin 866c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data->flags & MMC_DATA_READ) 867c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_READ; 868c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 869c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_DMA; 870c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 8714e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 872d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 873d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 874d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *host) 875d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 876d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_data *data; 877d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 878d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(!host->data); 879d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 880d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman data = host->data; 881d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 882d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 883c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 8842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 8852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_adma_table_post(host, data); 8862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else { 8872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 8882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 8892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 8902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 891d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 892d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 893d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 894c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * The specification states that the block count register must 895c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * be updated, but it does not specify at what point in the 896c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * data flow. That makes the register entirely useless to read 897c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * back so we have to assume that nothing made it to the card 898c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * in the event of an error. 899d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 900c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman if (data->error) 901c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = 0; 902d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 903c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = data->blksz * data->blocks; 904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 905e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin /* 906e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * Need to send CMD12 if - 907e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * a) open-ended multiblock transfer (no CMD23) 908e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * b) error in multiblock transfer 909e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin */ 910e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (data->stop && 911e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin (data->error || 912e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin !host->mrq->sbc)) { 913e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin 914d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 915d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 916d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 91817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (data->error) { 919d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 920d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 921d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 922d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 923d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_send_command(host, data->stop); 924d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else 925d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 926d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 927d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 928d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 929d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 930d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int flags; 931fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman u32 mask; 9327cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 933d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 934d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->cmd); 935d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 936d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* Wait max 10 ms */ 9377cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout = 10; 938fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 939fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask = SDHCI_CMD_INHIBIT; 940fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 941fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask |= SDHCI_DATA_INHIBIT; 942fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 943fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 944fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman though they might use busy signaling */ 945fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 946fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 947fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 9484e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 9497cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 950d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Controller never released " 951acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 952d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 95317b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EIO; 954d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 955d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 956d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 9577cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 9587cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 9597cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 960d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 961d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 962d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 963d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = cmd; 964d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 965a3c7778f8153b9e4eceea6738973280b9e63c618Andrei Warkentin sdhci_prepare_data(host, cmd); 966d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9674e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 968d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 969e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin sdhci_set_transfer_mode(host, cmd); 970c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 971d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 972acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 973d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 97417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EINVAL; 975d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 976d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 977d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 978d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 979d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 980d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_NONE; 981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_136) 982d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_LONG; 983d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 984d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 985d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 986d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT; 987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 988d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_CRC) 989d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_CRC; 990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 991d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_INDEX; 992b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 993b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 994b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) 995d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_DATA; 996d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9974e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 998d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 999d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1000d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *host) 1001d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1002d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int i; 1003d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1004d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(host->cmd == NULL); 1005d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1006d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 1007d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_136) { 1008d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* CRC is stripped so we need to do some shifting. */ 1009d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman for (i = 0;i < 4;i++) { 10104e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[i] = sdhci_readl(host, 1011d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 1012d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (i != 3) 1013d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd->resp[i] |= 10144e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, 1015d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 1016d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1017d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 10184e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 1019d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1020d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1021d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 102217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = 0; 1023d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1024e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin /* Finished CMD23, now send actual command. */ 1025e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (host->cmd == host->mrq->sbc) { 1026e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin host->cmd = NULL; 1027e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin sdhci_send_command(host, host->mrq->cmd); 1028e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin } else { 1029e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 1030e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin /* Processed actual command. */ 1031e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (host->data && host->data_early) 1032e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin sdhci_finish_data(host); 1033d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1034e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (!host->cmd->data) 1035e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin tasklet_schedule(&host->finish_tasklet); 1036e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin 1037e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin host->cmd = NULL; 1038e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin } 1039d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1040d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1041d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 1042d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1043c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath int div = 0; /* Initialized for compiler warning */ 1044c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath u16 clk = 0; 10457cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 1046d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1047d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == host->clock) 1048d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1049d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 10508114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->ops->set_clock) { 10518114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov host->ops->set_clock(host, clock); 10528114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) 10538114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov return; 10548114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov } 10558114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov 10564e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 1057d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1058d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == 0) 1059d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 1060d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 106185105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1062c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* 1063c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * Check if the Host Controller supports Programmable Clock 1064c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * Mode. 1065c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath */ 1066c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (host->clk_mul) { 1067c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath u16 ctrl; 1068c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath 1069c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* 1070c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * We need to figure out whether the Host Driver needs 1071c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * to select Programmable Clock Mode, or the value can 1072c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * be set automatically by the Host Controller based on 1073c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * the Preset Value registers. 1074c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath */ 1075c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1076c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (!(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { 1077c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath for (div = 1; div <= 1024; div++) { 1078c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (((host->max_clk * host->clk_mul) / 1079c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div) <= clock) 1080c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath break; 1081c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } 1082c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* 1083c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * Set Programmable Clock Mode in the Clock 1084c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * Control register. 1085c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath */ 1086c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1087c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div--; 1088c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } 1089c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } else { 1090c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* Version 3.00 divisors must be a multiple of 2. */ 1091c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (host->max_clk <= clock) 1092c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div = 1; 1093c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath else { 1094c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1095c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div += 2) { 1096c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if ((host->max_clk / div) <= clock) 1097c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath break; 1098c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } 109985105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 1100c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div >>= 1; 110185105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 110285105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } else { 110385105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 11040397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 110585105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if ((host->max_clk / div) <= clock) 110685105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao break; 110785105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 1108c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath div >>= 1; 1109d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1110d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1111c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 111285105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 111385105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1114d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_INT_EN; 11154e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1116d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 111727f6cb160b71b342b7a47d28a4b6c422ea74ccd1Chris Ball /* Wait max 20 ms */ 111827f6cb160b71b342b7a47d28a4b6c422ea74ccd1Chris Ball timeout = 20; 11194e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 11207cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 11217cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 1122acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Internal clock never " 1123acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 1124d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1125d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1126d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 11277cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 11287cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 11297cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 1130d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1131d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 11324e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1133d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1134d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 1135d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = clock; 1136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1137d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1138146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossmanstatic void sdhci_set_power(struct sdhci_host *host, unsigned short power) 1139146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman{ 11408364248a829d50495a796e7561aaf9a6976f846cGiuseppe Cavallaro u8 pwr = 0; 1141146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 11428364248a829d50495a796e7561aaf9a6976f846cGiuseppe Cavallaro if (power != (unsigned short)-1) { 1143ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman switch (1 << power) { 1144ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_165_195: 1145ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_180; 1146ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1147ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_29_30: 1148ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_30_31: 1149ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_300; 1150ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1151ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_32_33: 1152ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_33_34: 1153ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_330; 1154ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1155ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman default: 1156ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman BUG(); 1157ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1158ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1159ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1160ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (host->pwr == pwr) 1161146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman return; 1162146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1163ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman host->pwr = pwr; 1164ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1165ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (pwr == 0) { 11664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1167ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman return; 11689e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt } 11699e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt 11709e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt /* 11719e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * Spec says that we should clear the power reg before setting 11729e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * a new value. Some controllers don't seem to like this though. 11739e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt */ 1174b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 11754e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1176146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1177e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon /* 1178c71f65129a1fb67bc6b9b8d03b493675b5c9302bAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 1179e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon * and set turn on power at the same time, so set the voltage first. 1180e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon */ 118111a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 1182ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1183e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon 1184ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr |= SDHCI_POWER_ON; 1185146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1186ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1187557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte 1188557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte /* 1189557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * Some controllers need an extra 10ms delay of 10ms before they 1190557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * can apply clock after applying power 1191557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte */ 119211a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1193557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte mdelay(10); 1194146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman} 1195146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1197d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1198d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * MMC callbacks * 1199d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1200d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1201d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1202d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 1203d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1204d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 120568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov bool present; 1206d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1207d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1208d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1209d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1210d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1211d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1212d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->mrq != NULL); 1213d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1214f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1215d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_activate_led(host); 12162f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1217e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin 1218e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin /* 1219e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED 1220e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin * requests if Auto-CMD12 is enabled. 1221e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin */ 1222e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { 1223c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang if (mrq->stop) { 1224c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mrq->data->stop = NULL; 1225c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mrq->stop = NULL; 1226c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 1227c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 1228d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1229d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = mrq; 1230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 123168d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov /* If polling, assume that the card is always present. */ 123268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 123368d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = true; 123468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov else 123568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 123668d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov SDHCI_CARD_PRESENT; 123768d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 123868d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 123917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1240d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1241cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } else { 1242cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath u32 present_state; 1243cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1244cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 1245cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* 1246cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * Check if the re-tuning timer has already expired and there 1247cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * is no on-going data transfer. If so, we need to execute 1248cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * tuning procedure before sending command. 1249cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath */ 1250cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if ((host->flags & SDHCI_NEEDS_RETUNING) && 1251cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { 1252cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath spin_unlock_irqrestore(&host->lock, flags); 1253cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath sdhci_execute_tuning(mmc); 1254cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath spin_lock_irqsave(&host->lock, flags); 1255cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1256cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Restore original mmc_request structure */ 1257cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->mrq = mrq; 1258cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } 1259cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 12608edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) 1261e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin sdhci_send_command(host, mrq->sbc); 1262e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin else 1263e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin sdhci_send_command(host, mrq->cmd); 1264cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } 1265d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12665f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1267d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1268d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1269d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1270d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1271d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1272d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1273d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1274d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 1275d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1276d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1277d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1278d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1279d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12801e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 12811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 12821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1283d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1284d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Reset the chip on each power off. 1285d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Should clear out any weird states. 1286d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1287d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 12884e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 12897260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_reinit(host); 1290d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1291d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1292d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_set_clock(host, ios->clock); 1293d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1294d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) 1295146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, -1); 1296d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 1297146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, ios->vdd); 1298d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1299643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity if (host->ops->platform_send_init_74_clocks) 1300643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1301643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity 130215ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity /* 130315ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * If your platform has 8-bit width support but is not a v3 controller, 130415ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * or if it requires special setup code, you should implement that in 130515ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * platform_8bit_width(). 130615ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity */ 130715ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity if (host->ops->platform_8bit_width) 130815ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity host->ops->platform_8bit_width(host, ios->bus_width); 130915ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity else { 131015ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 131115ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity if (ios->bus_width == MMC_BUS_WIDTH_8) { 131215ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl &= ~SDHCI_CTRL_4BITBUS; 131315ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity if (host->version >= SDHCI_SPEC_300) 131415ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl |= SDHCI_CTRL_8BITBUS; 131515ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity } else { 131615ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity if (host->version >= SDHCI_SPEC_300) 131715ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl &= ~SDHCI_CTRL_8BITBUS; 131815ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity if (ios->bus_width == MMC_BUS_WIDTH_4) 131915ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl |= SDHCI_CTRL_4BITBUS; 132015ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity else 132115ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl &= ~SDHCI_CTRL_4BITBUS; 132215ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity } 132315ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 132415ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity } 1325ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park 132615ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 1327cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 13283ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity if ((ios->timing == MMC_TIMING_SD_HS || 13293ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity ios->timing == MMC_TIMING_MMC_HS) 13303ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) 1331cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl |= SDHCI_CTRL_HISPD; 1332cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman else 1333cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 1334cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 1335d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (host->version >= SDHCI_SPEC_300) { 133649c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath u16 clk, ctrl_2; 133749c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath unsigned int clock; 133849c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath 133949c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath /* In case of UHS-I modes, set High Speed Enable */ 134049c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath if ((ios->timing == MMC_TIMING_UHS_SDR50) || 134149c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath (ios->timing == MMC_TIMING_UHS_SDR104) || 134249c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath (ios->timing == MMC_TIMING_UHS_DDR50) || 134349c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath (ios->timing == MMC_TIMING_UHS_SDR25) || 134449c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath (ios->timing == MMC_TIMING_UHS_SDR12)) 134549c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath ctrl |= SDHCI_CTRL_HISPD; 1346d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath 1347d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1348d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) { 1349758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1350d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath /* 1351d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath * We only need to set Driver Strength if the 1352d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath * preset value enable is not set. 1353d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath */ 1354d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 1355d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 1356d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 1357d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 1358d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 1359d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath 1360d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 1361758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath } else { 1362758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath /* 1363758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath * According to SDHC Spec v3.00, if the Preset Value 1364758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath * Enable in the Host Control 2 register is set, we 1365758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath * need to reset SD Clock Enable before changing High 1366758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath * Speed Enable to avoid generating clock gliches. 1367758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath */ 1368758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath 1369758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath /* Reset SD Clock Enable */ 1370758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1371758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 1372758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1373758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath 1374758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1375758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath 1376758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath /* Re-enable SD Clock */ 1377758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath clock = host->clock; 1378758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath host->clock = 0; 1379758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath sdhci_set_clock(host, clock); 1380d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath } 138149c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath 138249c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath 138349c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath /* Reset SD Clock Enable */ 138449c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 138549c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 138649c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 138749c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath 13886322cdd0eb22e016aeced886c2046d115139c962Philip Rakity if (host->ops->set_uhs_signaling) 13896322cdd0eb22e016aeced886c2046d115139c962Philip Rakity host->ops->set_uhs_signaling(host, ios->timing); 13906322cdd0eb22e016aeced886c2046d115139c962Philip Rakity else { 13916322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 13926322cdd0eb22e016aeced886c2046d115139c962Philip Rakity /* Select Bus Speed Mode for host */ 13936322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 13946322cdd0eb22e016aeced886c2046d115139c962Philip Rakity if (ios->timing == MMC_TIMING_UHS_SDR12) 13956322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 13966322cdd0eb22e016aeced886c2046d115139c962Philip Rakity else if (ios->timing == MMC_TIMING_UHS_SDR25) 13976322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 13986322cdd0eb22e016aeced886c2046d115139c962Philip Rakity else if (ios->timing == MMC_TIMING_UHS_SDR50) 13996322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 14006322cdd0eb22e016aeced886c2046d115139c962Philip Rakity else if (ios->timing == MMC_TIMING_UHS_SDR104) 14016322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 14026322cdd0eb22e016aeced886c2046d115139c962Philip Rakity else if (ios->timing == MMC_TIMING_UHS_DDR50) 14036322cdd0eb22e016aeced886c2046d115139c962Philip Rakity ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 14046322cdd0eb22e016aeced886c2046d115139c962Philip Rakity sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 14056322cdd0eb22e016aeced886c2046d115139c962Philip Rakity } 140649c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath 140749c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath /* Re-enable SD Clock */ 140849c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath clock = host->clock; 140949c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath host->clock = 0; 141049c468fcf878d2c86e31920cf54aa90c88418a66Arindam Nath sdhci_set_clock(host, clock); 1411758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath } else 1412758535c4e3cdd2b5b09565d9651aaa541aac3de8Arindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1413d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath 1414b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo /* 1415b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1416b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1417b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * it on each ios seems to solve the problem. 1418b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo */ 1419b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1420b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1421b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo 14221e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 14235f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1424d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1425d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1426d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 142782b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwaistatic int check_ro(struct sdhci_host *host) 1428d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1429d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 14302dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang int is_readonly; 1431d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1432d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1433d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14341e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 14352dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = 0; 14362dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang else if (host->ops->get_ro) 14372dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = host->ops->get_ro(host); 14381e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman else 14392dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 14402dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang & SDHCI_WRITE_PROTECT); 1441d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1442d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1443d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14442dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 14452dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 14462dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang !is_readonly : is_readonly; 1447d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1448d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 144982b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai#define SAMPLE_COUNT 5 145082b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai 145182b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwaistatic int sdhci_get_ro(struct mmc_host *mmc) 145282b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai{ 145382b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai struct sdhci_host *host; 145482b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai int i, ro_count; 145582b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai 145682b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai host = mmc_priv(mmc); 145782b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai 145882b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 145982b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai return check_ro(host); 146082b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai 146182b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai ro_count = 0; 146282b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 146382b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai if (check_ro(host)) { 146482b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 146582b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai return 1; 146682b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai } 146782b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai msleep(30); 146882b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai } 146982b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai return 0; 147082b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai} 147182b0e23a295cc58d1290017ee97a40956ad68d94Takashi Iwai 1472f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossmanstatic void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1473f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman{ 1474f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman struct sdhci_host *host; 1475f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman unsigned long flags; 1476f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1477f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman host = mmc_priv(mmc); 1478f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1479f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1480f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 14811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 14821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 14831e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1484f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (enable) 14857260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); 14867260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 14877260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); 14881e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 1489f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmiowb(); 1490f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1491f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1492f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman} 1493f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1494f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nathstatic int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 1495f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath struct mmc_ios *ios) 1496f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath{ 1497f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath struct sdhci_host *host; 1498f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath u8 pwr; 1499f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath u16 clk, ctrl; 1500f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath u32 present_state; 1501f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1502f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath host = mmc_priv(mmc); 1503f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1504f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 1505f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * Signal Voltage Switching is only applicable for Host Controllers 1506f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * v3.00 and above. 1507f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 1508f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (host->version < SDHCI_SPEC_300) 1509f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return 0; 1510f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1511f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 1512f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * We first check whether the request is to set signalling voltage 1513f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * to 3.3V. If so, we change the voltage to 3.3V and return quickly. 1514f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 1515f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1516f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 1517f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 1518f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 1519f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1520f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1521f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Wait for 5ms */ 1522f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath usleep_range(5000, 5500); 1523f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1524f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 3.3V regulator output should be stable within 5 ms */ 1525f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1526f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 1527f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return 0; 1528f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath else { 1529f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath printk(KERN_INFO DRIVER_NAME ": Switching to 3.3V " 1530f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath "signalling voltage failed\n"); 1531f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return -EIO; 1532f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 1533f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } else if (!(ctrl & SDHCI_CTRL_VDD_180) && 1534f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { 1535f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Stop SDCLK */ 1536f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1537f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 1538f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1539f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1540f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Check whether DAT[3:0] is 0000 */ 1541f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 1542f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (!((present_state & SDHCI_DATA_LVL_MASK) >> 1543f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_DATA_LVL_SHIFT)) { 1544f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 1545f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * Enable 1.8V Signal Enable in the Host Control2 1546f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * register 1547f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 1548f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath ctrl |= SDHCI_CTRL_VDD_180; 1549f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1550f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1551f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Wait for 5ms */ 1552f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath usleep_range(5000, 5500); 1553f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1554f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1555f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (ctrl & SDHCI_CTRL_VDD_180) { 1556f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Provide SDCLK again and wait for 1ms*/ 1557f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1558f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath clk |= SDHCI_CLOCK_CARD_EN; 1559f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1560f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath usleep_range(1000, 1500); 1561f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1562f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 1563f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * If DAT[3:0] level is 1111b, then the card 1564f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * was successfully switched to 1.8V signaling. 1565f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 1566f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath present_state = sdhci_readl(host, 1567f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_PRESENT_STATE); 1568f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if ((present_state & SDHCI_DATA_LVL_MASK) == 1569f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_DATA_LVL_MASK) 1570f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return 0; 1571f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 1572f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 1573f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1574f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 1575f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * If we are here, that means the switch to 1.8V signaling 1576f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * failed. We power cycle the card, and retry initialization 1577f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * sequence by setting S18R to 0. 1578f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 1579f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); 1580f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath pwr &= ~SDHCI_POWER_ON; 1581f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1582f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1583f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* Wait for 1ms as per the spec */ 1584f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath usleep_range(1000, 1500); 1585f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath pwr |= SDHCI_POWER_ON; 1586f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1587f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1588f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath printk(KERN_INFO DRIVER_NAME ": Switching to 1.8V signalling " 1589f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath "voltage failed, retrying with S18R set to 0\n"); 1590f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return -EAGAIN; 1591f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } else 1592f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* No signal voltage switch required */ 1593f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath return 0; 1594f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath} 1595f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 1596b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nathstatic int sdhci_execute_tuning(struct mmc_host *mmc) 1597b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath{ 1598b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath struct sdhci_host *host; 1599b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath u16 ctrl; 1600b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath u32 ier; 1601b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath int tuning_loop_counter = MAX_TUNING_LOOP; 1602b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath unsigned long timeout; 1603b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath int err = 0; 1604b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1605b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host = mmc_priv(mmc); 1606b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1607b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath disable_irq(host->irq); 1608b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath spin_lock(&host->lock); 1609b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1610b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1611b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1612b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1613b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * Host Controller needs tuning only in case of SDR104 mode 1614b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * and for SDR50 mode when Use Tuning for SDR50 is set in 1615b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * Capabilities register. 1616b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1617b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || 1618b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && 1619b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath (host->flags & SDHCI_SDR50_NEEDS_TUNING))) 1620b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl |= SDHCI_CTRL_EXEC_TUNING; 1621b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath else { 1622b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath spin_unlock(&host->lock); 1623b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath enable_irq(host->irq); 1624b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath return 0; 1625b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 1626b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1627b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1628b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1629b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1630b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * As per the Host Controller spec v3.00, tuning command 1631b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * generates Buffer Read Ready interrupt, so enable that. 1632b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * 1633b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * Note: The spec clearly says that when tuning sequence 1634b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * is being performed, the controller does not generate 1635b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * interrupts other than Buffer Read Ready interrupt. But 1636b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * to make sure we don't hit a controller bug, we _only_ 1637b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * enable Buffer Read Ready interrupt here. 1638b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1639b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1640b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); 1641b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1642b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1643b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number 1644b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * of loops reaches 40 times or a timeout of 150ms occurs. 1645b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1646b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath timeout = 150; 1647b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath do { 1648b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath struct mmc_command cmd = {0}; 1649b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath struct mmc_request mrq = {0}; 1650b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1651b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (!tuning_loop_counter && !timeout) 1652b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath break; 1653b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1654b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.opcode = MMC_SEND_TUNING_BLOCK; 1655b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.arg = 0; 1656b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 1657b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.retries = 0; 1658b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.data = NULL; 1659b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath cmd.error = 0; 1660b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1661b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath mrq.cmd = &cmd; 1662b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->mrq = &mrq; 1663b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1664b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1665b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * In response to CMD19, the card sends 64 bytes of tuning 1666b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * block to the Host Controller. So we set the block size 1667b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * to 64 here. 1668b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1669b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); 1670b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1671b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1672b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * The tuning block is sent by the card to the host controller. 1673b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * So we set the TRNS_READ bit in the Transfer Mode register. 1674b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * This also takes care of setting DMA Enable and Multi Block 1675b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * Select in the same register to 0. 1676b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1677b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 1678b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1679b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_send_command(host, &cmd); 1680b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1681b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->cmd = NULL; 1682b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->mrq = NULL; 1683b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1684b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath spin_unlock(&host->lock); 1685b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath enable_irq(host->irq); 1686b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1687b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* Wait for Buffer Read Ready interrupt */ 1688b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath wait_event_interruptible_timeout(host->buf_ready_int, 1689b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath (host->tuning_done == 1), 1690b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath msecs_to_jiffies(50)); 1691b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath disable_irq(host->irq); 1692b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath spin_lock(&host->lock); 1693b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1694b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (!host->tuning_done) { 1695b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath printk(KERN_INFO DRIVER_NAME ": Timeout waiting for " 1696b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath "Buffer Read Ready interrupt during tuning " 1697b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath "procedure, falling back to fixed sampling " 1698b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath "clock\n"); 1699b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1700b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl &= ~SDHCI_CTRL_TUNED_CLK; 1701b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 1702b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1703b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1704b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath err = -EIO; 1705b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath goto out; 1706b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 1707b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1708b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->tuning_done = 0; 1709b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1710b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1711b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath tuning_loop_counter--; 1712b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath timeout--; 1713b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath mdelay(1); 1714b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } while (ctrl & SDHCI_CTRL_EXEC_TUNING); 1715b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1716b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* 1717b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * The Host Driver has exhausted the maximum number of loops allowed, 1718b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath * so use fixed sampling frequency. 1719b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath */ 1720b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (!tuning_loop_counter || !timeout) { 1721b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath ctrl &= ~SDHCI_CTRL_TUNED_CLK; 1722b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1723b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } else { 1724b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { 1725b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath printk(KERN_INFO DRIVER_NAME ": Tuning procedure" 1726b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath " failed, falling back to fixed sampling" 1727b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath " clock\n"); 1728b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath err = -EIO; 1729b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 1730b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 1731b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1732b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nathout: 1733cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* 1734cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * If this is the very first time we are here, we start the retuning 1735cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * timer. Since only during the first time, SDHCI_NEEDS_RETUNING 1736cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * flag won't be set, we check this condition before actually starting 1737cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * the timer. 1738cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath */ 1739cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count && 1740cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath (host->tuning_mode == SDHCI_TUNING_MODE_1)) { 1741cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath mod_timer(&host->tuning_timer, jiffies + 1742cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_count * HZ); 1743cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Tuning mode 1 limits the maximum data length to 4MB */ 1744cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath mmc->max_blk_count = (4 * 1024 * 1024) / mmc->max_blk_size; 1745cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } else { 1746cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->flags &= ~SDHCI_NEEDS_RETUNING; 1747cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Reload the new initial value for timer */ 1748cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->tuning_mode == SDHCI_TUNING_MODE_1) 1749cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath mod_timer(&host->tuning_timer, jiffies + 1750cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_count * HZ); 1751cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } 1752cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1753cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* 1754cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * In case tuning fails, host controllers which support re-tuning can 1755cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * try tuning again at a later time, when the re-tuning timer expires. 1756cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * So for these controllers, we return 0. Since there might be other 1757cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * controllers who do not have this capability, we return error for 1758cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * them. 1759cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath */ 1760cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (err && host->tuning_count && 1761cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_mode == SDHCI_TUNING_MODE_1) 1762cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath err = 0; 1763cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1764b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); 1765b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath spin_unlock(&host->lock); 1766b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath enable_irq(host->irq); 1767b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 1768b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath return err; 1769b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath} 1770b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 17714d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nathstatic void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) 17724d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath{ 17734d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath struct sdhci_host *host; 17744d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath u16 ctrl; 17754d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath unsigned long flags; 17764d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17774d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath host = mmc_priv(mmc); 17784d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17794d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath /* Host Controller v3.00 defines preset value registers */ 17804d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath if (host->version < SDHCI_SPEC_300) 17814d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath return; 17824d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17834d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath spin_lock_irqsave(&host->lock, flags); 17844d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17854d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 17864d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17874d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath /* 17884d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath * We only enable or disable Preset Value if they are not already 17894d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath * enabled or disabled respectively. Otherwise, we bail out. 17904d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath */ 17914d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { 17924d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 17934d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 17944d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { 17954d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 17964d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 17974d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath } 17984d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 17994d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath spin_unlock_irqrestore(&host->lock, flags); 18004d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath} 18014d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath 1802ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops sdhci_ops = { 1803d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .request = sdhci_request, 1804d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .set_ios = sdhci_set_ios, 1805d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .get_ro = sdhci_get_ro, 1806f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 1807f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 1808b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath .execute_tuning = sdhci_execute_tuning, 18094d55c5a13a189a80d40383f02c8026f9a87d7c87Arindam Nath .enable_preset_value = sdhci_enable_preset_value, 1810d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}; 1811d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1812d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1813d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1814d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Tasklets * 1815d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1816d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1817d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1818d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_card(unsigned long param) 1819d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1820d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1821d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1822d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1823d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1824d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1825d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1826d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 18274e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 1828d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1829d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 1830d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1831d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 1832d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1833d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1834d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1835d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1836d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 183717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1838d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1839d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1840d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1841d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1842d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1843d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 184404cf585d2902404ed06861c6dc27897100340dbaPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 1845d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1846d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1847d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_finish(unsigned long param) 1848d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1849d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1850d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1851d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_request *mrq; 1852d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1853d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1854d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 18550c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball /* 18560c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball * If this tasklet gets rescheduled while running, it will 18570c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball * be run again afterwards but without any active request. 18580c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball */ 18590c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball if (!host->mrq) 18600c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball return; 18610c9c99a765321104cc5f9c97f949382a9ba4927eChris Ball 1862d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1863d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1864d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer(&host->timer); 1865d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1866cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->version >= SDHCI_SPEC_300) 1867cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath del_timer(&host->tuning_timer); 1868cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1869d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mrq = host->mrq; 1870d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1871d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1872d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 1873d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 1874d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 18751e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 1876b7b4d3426d2b5ecab21578eb20d8e456a1aace8fBen Dooks ((mrq->cmd && mrq->cmd->error) || 18771e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data && (mrq->data->error || 18781e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 18791e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 1880645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1881645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Some controllers need this kick or reset won't work here */ 1882b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 1883645289dca5021224279e67b4655796cafdfdad00Pierre Ossman unsigned int clock; 1884645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1885645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* This is to force an update */ 1886645289dca5021224279e67b4655796cafdfdad00Pierre Ossman clock = host->clock; 1887645289dca5021224279e67b4655796cafdfdad00Pierre Ossman host->clock = 0; 1888645289dca5021224279e67b4655796cafdfdad00Pierre Ossman sdhci_set_clock(host, clock); 1889645289dca5021224279e67b4655796cafdfdad00Pierre Ossman } 1890645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1891645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Spec says we should do both at the same time, but Ricoh 1892645289dca5021224279e67b4655796cafdfdad00Pierre Ossman controllers do not like that. */ 1893d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1894d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1895d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1896d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1897d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = NULL; 1898d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = NULL; 1899d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 1900d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1901f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1902d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_deactivate_led(host); 19032f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19055f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1906d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1907d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1908d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_request_done(host->mmc, mrq); 1909d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1910d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1911d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_timeout_timer(unsigned long data) 1912d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1913d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1914d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1915d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1916d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)data; 1917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1918d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1919d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1920d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1921acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 1922acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 1923d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1924d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1925d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->data) { 192617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 1927d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 1928d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 1929d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd) 193017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 1931d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 193217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 1933d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1934d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1935d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1936d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1937d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19385f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1939d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1940d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1941d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1942cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nathstatic void sdhci_tuning_timer(unsigned long data) 1943cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath{ 1944cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath struct sdhci_host *host; 1945cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath unsigned long flags; 1946cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1947cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host = (struct sdhci_host *)data; 1948cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1949cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath spin_lock_irqsave(&host->lock, flags); 1950cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1951cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->flags |= SDHCI_NEEDS_RETUNING; 1952cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1953cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath spin_unlock_irqrestore(&host->lock, flags); 1954cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath} 1955cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 1956d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1957d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1958d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Interrupt handling * 1959d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1960d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1961d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1962d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 1963d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1964d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 1965d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1966d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->cmd) { 1967b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1968b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no command operation was in progress.\n", 1969b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 1970d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1971d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1972d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1973d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 197443b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 197517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 197617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 197717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman SDHCI_INT_INDEX)) 197817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -EILSEQ; 197943b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman 1980e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->error) { 1981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1982e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1983e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1984e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 1985e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman /* 1986e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The host can send and interrupt when the busy state has 1987e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * ended, allowing us to wait without wasting CPU cycles. 1988e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Unfortunately this is overloaded on the "data complete" 1989e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * interrupt, so we need to take some care when handling 1990e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * it. 1991e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * 1992e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Note: The 1.0 specification is a bit ambiguous about this 1993e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * feature so there might be some problems with older 1994e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * controllers. 1995e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman */ 1996e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->flags & MMC_RSP_BUSY) { 1997e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->data) 1998e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman DBG("Cannot wait for busy signal when also " 1999e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman "doing a data transfer"); 2000f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 2001e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 2002f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks 2003f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks /* The controller does not support the end-of-busy IRQ, 2004f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks * fall through and take the SDHCI_INT_RESPONSE */ 2005e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 2006e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 2007e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 200843b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman sdhci_finish_command(host); 2009d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2010d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 20110957c3339efa333b7895157eb18b9b578394f80cGeorge G. Davis#ifdef CONFIG_MMC_DEBUG 20126882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) 20136882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks{ 20146882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks const char *name = mmc_hostname(host->mmc); 20156882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 *desc = host->adma_desc; 20166882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le32 *dma; 20176882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le16 *len; 20186882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 attr; 20196882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 20206882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_dumpregs(host); 20216882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 20226882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks while (true) { 20236882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks dma = (__le32 *)(desc + 4); 20246882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks len = (__le16 *)(desc + 2); 20256882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks attr = *desc; 20266882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 20276882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 20286882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); 20296882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 20306882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks desc += 8; 20316882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 20326882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks if (attr & 2) 20336882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks break; 20346882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 20356882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks} 20366882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#else 20376882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) { } 20386882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#endif 20396882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 2040d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 2041d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2042d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 2043d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2044b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* CMD19 generates _only_ Buffer Read Ready interrupt */ 2045b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (intmask & SDHCI_INT_DATA_AVAIL) { 2046b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == 2047b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath MMC_SEND_TUNING_BLOCK) { 2048b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->tuning_done = 1; 2049b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath wake_up(&host->buf_ready_int); 2050b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath return; 2051b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 2052b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath } 2053b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 2054d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->data) { 2055d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 2056e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The "data complete" interrupt is also used to 2057e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * indicate that a busy state has ended. See comment 2058e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * above in sdhci_cmd_irq(). 2059d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 2060e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { 2061e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 2062e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman sdhci_finish_command(host); 2063e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 2064e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 2065e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 2066d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2067b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 2068b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no data operation was in progress.\n", 2069b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 2070d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 2071d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2072d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 2073d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2074d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2075d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 207617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 207722113efd00491310da802f3b1a9a66cfcf415facAries Lee else if (intmask & SDHCI_INT_DATA_END_BIT) 207822113efd00491310da802f3b1a9a66cfcf415facAries Lee host->data->error = -EILSEQ; 207922113efd00491310da802f3b1a9a66cfcf415facAries Lee else if ((intmask & SDHCI_INT_DATA_CRC) && 208022113efd00491310da802f3b1a9a66cfcf415facAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 208122113efd00491310da802f3b1a9a66cfcf415facAries Lee != MMC_BUS_TEST_R) 208217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -EILSEQ; 20836882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 20846882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); 20856882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_show_adma_error(host); 20862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->data->error = -EIO; 20876882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 2088d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 208917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (host->data->error) 2090d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 2091d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else { 2092a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 2093d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_transfer_pio(host); 2094d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 20956ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman /* 20966ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * We currently don't do anything fancy with DMA 20976ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * boundaries, but as we can't disable the feature 20986ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * we need to at least restart the transfer. 2099f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni * 2100f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 2101f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni * should return a valid address to continue from, but as 2102f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni * some controllers are faulty, don't trust them. 21036ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman */ 2104f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 2105f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni u32 dmastart, dmanow; 2106f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni dmastart = sg_dma_address(host->data->sg); 2107f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 2108f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni /* 2109f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni * Force update to the next DMA block boundary. 2110f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni */ 2111f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni dmanow = (dmanow & 2112f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 2113f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 2114f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 2115f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni DBG("%s: DMA base 0x%08x, transferred 0x%06x bytes," 2116f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni " next 0x%08x\n", 2117f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni mmc_hostname(host->mmc), dmastart, 2118f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni host->data->bytes_xfered, dmanow); 2119f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 2120f6a03cbf43e586211f8ea088148c8ecd3fc4b5beMikko Vinni } 21216ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman 2122e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 2123e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (host->cmd) { 2124e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman /* 2125e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * Data managed to finish before the 2126e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * command completed. Make sure we do 2127e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * things in the proper order. 2128e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman */ 2129e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman host->data_early = 1; 2130e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } else { 2131e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman sdhci_finish_data(host); 2132e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 2133e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 2134d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2135d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21377d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sdhci_irq(int irq, void *dev_id) 2138d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2139d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman irqreturn_t result; 2140d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host* host = dev_id; 2141d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u32 intmask; 2142f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman int cardint = 0; 2143d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2144d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock(&host->lock); 2145d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21464e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 2147d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 214862df67a523acd7a22d936bf946b1889dbd60ca98Mark Lord if (!intmask || intmask == 0xffffffff) { 2149d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_NONE; 2150d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 2151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2152d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2153b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 2154b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(host->mmc), intmask); 2155d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21563192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 21574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 21584e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 2159d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->card_tasklet); 21603192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 2161d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21623192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 2163d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21643192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 21654e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 21664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 21673192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 2168d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2169d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2170d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 21714e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, 21724e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 21733192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 2174d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2175d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2176d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 2177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2178964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman intmask &= ~SDHCI_INT_ERROR; 2179964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman 2180d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 21813192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 2182d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 21834e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); 2184d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2185d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21869d26a5d3f2b9c4fe4b2ba491683c6989ecd6ae04Rolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 21873192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman 2188f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (intmask & SDHCI_INT_CARD_INT) 2189f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman cardint = 1; 2190f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 2191f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 2192f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 21933192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask) { 2194acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 21953192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman mmc_hostname(host->mmc), intmask); 2196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 2197d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 21984e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 21993192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 2200d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2201d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_HANDLED; 2202d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 22035f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 2204d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 2205d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock(&host->lock); 2206d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2207f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman /* 2208f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman * We have to delay this as it calls back into the driver. 2209f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman */ 2210f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (cardint) 2211f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmc_signal_sdio_irq(host->mmc); 2212f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 2213d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return result; 2214d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2215d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2216d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 2217d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2218d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Suspend/resume * 2219d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 2221d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_PM 2223d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2224b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 2225d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2226b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 2227a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 22287260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 22297260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 2230cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Disable tuning since we are suspending */ 2231cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->version >= SDHCI_SPEC_300 && host->tuning_count && 2232cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_mode == SDHCI_TUNING_MODE_1) { 2233cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->flags &= ~SDHCI_NEEDS_RETUNING; 2234cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath mod_timer(&host->tuning_timer, jiffies + 2235cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_count * HZ); 2236cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } 2237cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 22381a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming ret = mmc_suspend_host(host->mmc); 2239b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (ret) 2240b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ret; 2241a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 2242b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman free_irq(host->irq, host); 2243d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 22449bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) 22459bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski ret = regulator_disable(host->vmmc); 22469bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 22479bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski return ret; 2248d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2249d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2250b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_suspend_host); 2251d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2252b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_resume_host(struct sdhci_host *host) 2253b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 2254b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 2255d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 22569bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) { 22579bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski int ret = regulator_enable(host->vmmc); 22589bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (ret) 22599bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski return ret; 22609bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 22619bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 22629bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 2263a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 2264b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) 2265b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->ops->enable_dma(host); 2266b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 2267d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2268b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 2269b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(host->mmc), host); 2270df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman if (ret) 2271df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman return ret; 2272d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 22732f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 2274b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmiowb(); 2275b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman 2276b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = mmc_resume_host(host->mmc); 22777260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 22787260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 2279cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Set the re-tuning expiration flag */ 2280cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && 2281cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath (host->tuning_mode == SDHCI_TUNING_MODE_1)) 2282cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->flags |= SDHCI_NEEDS_RETUNING; 2283cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 22842f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre return ret; 2285d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2286d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2287b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_resume_host); 2288d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 22895f619704d18b93869d045abc49e09cdba109b04bDaniel Drakevoid sdhci_enable_irq_wakeups(struct sdhci_host *host) 22905f619704d18b93869d045abc49e09cdba109b04bDaniel Drake{ 22915f619704d18b93869d045abc49e09cdba109b04bDaniel Drake u8 val; 22925f619704d18b93869d045abc49e09cdba109b04bDaniel Drake val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 22935f619704d18b93869d045abc49e09cdba109b04bDaniel Drake val |= SDHCI_WAKE_ON_INT; 22945f619704d18b93869d045abc49e09cdba109b04bDaniel Drake sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 22955f619704d18b93869d045abc49e09cdba109b04bDaniel Drake} 22965f619704d18b93869d045abc49e09cdba109b04bDaniel Drake 22975f619704d18b93869d045abc49e09cdba109b04bDaniel DrakeEXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); 22985f619704d18b93869d045abc49e09cdba109b04bDaniel Drake 2299d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif /* CONFIG_PM */ 2300d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2301d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 2302d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2303b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman * Device allocation/registration * 2304d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2305d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 2306d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2307b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanstruct sdhci_host *sdhci_alloc_host(struct device *dev, 2308b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman size_t priv_size) 2309d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2310d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_host *mmc; 2311d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 2312d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2313b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(dev == NULL); 2314d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2315b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 2316d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!mmc) 2317b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ERR_PTR(-ENOMEM); 2318d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2319d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 2320d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mmc = mmc; 2321d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2322b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return host; 2323b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman} 23248a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 2325b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_alloc_host); 2326d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2327b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_add_host(struct sdhci_host *host) 2328b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 2329b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman struct mmc_host *mmc; 2330f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath u32 caps[2]; 2331f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath u32 max_current_caps; 2332f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath unsigned int ocr_avail; 2333b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 2334d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2335b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(host == NULL); 2336b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host == NULL) 2337b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -EINVAL; 2338d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2339b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = host->mmc; 2340d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2341b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (debug_quirks) 2342b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->quirks = debug_quirks; 2343d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2344d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 2345d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman 23464e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 23472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 23482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 234985105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if (host->version > SDHCI_SPEC_300) { 23504a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 2351b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 23522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version); 23534a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman } 23544a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman 2355f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : 2356ccc92c23240cdf952ef7cc39ba563910dcbc9cbeMaxim Levitsky sdhci_readl(host, SDHCI_CAPABILITIES); 2357d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2358f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath caps[1] = (host->version >= SDHCI_SPEC_300) ? 2359f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath sdhci_readl(host, SDHCI_CAPABILITIES_1) : 0; 2360f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2361b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 2362a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_SDMA; 2363f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath else if (!(caps[0] & SDHCI_CAN_DO_SDMA)) 2364a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors DBG("Controller doesn't have SDMA capability\n"); 23656743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman else 2366a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_SDMA; 2367d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2368b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 2369a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_SDMA)) { 2370cee687ce4ab1197e20d4dacc09df01531362fdbdRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 2371a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags &= ~SDHCI_USE_SDMA; 23727c168e3db7d900008ee304574057e0dc1a8505afFeng Tang } 23737c168e3db7d900008ee304574057e0dc1a8505afFeng Tang 2374f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if ((host->version >= SDHCI_SPEC_200) && 2375f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath (caps[0] & SDHCI_CAN_DO_ADMA2)) 2376a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_ADMA; 23772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 23782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 23792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 23802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 23812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 23822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 23832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 2384a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 2385b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) { 2386b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma(host)) { 2387b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 2388b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman "available. Falling back to PIO.\n", 2389b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(mmc)); 2390a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags &= 2391a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 2392b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 2393d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2394d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 2395d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 23962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 23972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 23982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We need to allocate descriptors for all sg entries 23992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (128) and potentially one alignment transfer for 24002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * each of those entries. 24012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 24022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 24032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 24042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (!host->adma_desc || !host->align_buffer) { 24052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 24062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 24072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 24082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "buffers. Falling back to standard DMA.\n", 24092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc_hostname(mmc)); 24102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 24112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 24122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 24132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 24147659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman /* 24157659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * If we use DMA, then it's up to the caller to set the DMA 24167659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask, but PIO does not need the hw shim so we set a new 24177659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask here in that case. 24187659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman */ 2419a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 24207659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->dma_mask = DMA_BIT_MASK(64); 24217659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 24227659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman } 2423d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2424c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao if (host->version >= SDHCI_SPEC_300) 2425f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath host->max_clk = (caps[0] & SDHCI_CLOCK_V3_BASE_MASK) 2426c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 2427c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao else 2428f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath host->max_clk = (caps[0] & SDHCI_CLOCK_BASE_MASK) 2429c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 2430c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao 24314240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk *= 1000000; 2432f27f47ef5b67106ff1cdeebf061387a7b30c12bcAnton Vorontsov if (host->max_clk == 0 || host->quirks & 2433f27f47ef5b67106ff1cdeebf061387a7b30c12bcAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 24344240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks if (!host->ops->get_max_clock) { 24354240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 24364240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify base clock " 24374240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 24384240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 24394240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 24404240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk = host->ops->get_max_clock(host); 24418ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman } 2442d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 24431c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk = 2444f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 24451c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (host->timeout_clk == 0) { 244681b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov if (host->ops->get_timeout_clock) { 244781b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov host->timeout_clk = host->ops->get_timeout_clock(host); 244881b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov } else if (!(host->quirks & 244981b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 24504240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 24514240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify timeout clock " 24524240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 24534240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 24544240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 24551c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 2456f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) 24571c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk *= 1000; 2458d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2459d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 2460c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * In case of Host Controller v3.00, find out whether clock 2461c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * multiplier is supported. 2462c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath */ 2463c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath host->clk_mul = (caps[1] & SDHCI_CLOCK_MUL_MASK) >> 2464c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath SDHCI_CLOCK_MUL_SHIFT; 2465c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath 2466c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* 2467c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * In case the value in Clock Multiplier is 0, then programmable 2468c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * clock mode is not supported, otherwise the actual clock 2469c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * multiplier is one more than the value of Clock Multiplier 2470c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath * in the Capabilities Register. 2471c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath */ 2472c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (host->clk_mul) 2473c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath host->clk_mul += 1; 2474c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath 2475c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath /* 2476d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Set host parameters. 2477d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 2478d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->ops = &sdhci_ops; 2479c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath mmc->f_max = host->max_clk; 2480ce5f036bbbfc6c21d7b55b8fdaa2e2bd56392d94Marek Szyprowski if (host->ops->get_min_clock) 2481a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 2482c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath else if (host->version >= SDHCI_SPEC_300) { 2483c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath if (host->clk_mul) { 2484c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath mmc->f_min = (host->max_clk * host->clk_mul) / 1024; 2485c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath mmc->f_max = host->max_clk * host->clk_mul; 2486c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } else 2487c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 2488c3ed3877625f10d600b0eca2ca48a68c46aed660Arindam Nath } else 24890397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 249015ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity 2491e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; 2492e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin 2493e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 2494e89d456fcdde2df008c032bf928e69e628e07a28Andrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 24955fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov 24968edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin /* Auto-CMD23 stuff only works in ADMA or PIO. */ 24974f3d3e9b50931a3ec70f324d53fb7437e2a39388Andrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 24988edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 24994f3d3e9b50931a3ec70f324d53fb7437e2a39388Andrei Warkentin !(host->flags & SDHCI_USE_SDMA))) { 25008edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 25018edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc)); 25028edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin } else { 25038edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin DBG("%s: Auto-CMD23 unavailable\n", mmc_hostname(mmc)); 25048edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin } 25058edf63710bd43e62d59bfe017df542fa0713bbb3Andrei Warkentin 250615ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity /* 250715ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * A controller may support 8-bit width, but the board itself 250815ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * might not have the pins brought out. Boards that support 250915ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 251015ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * their platform code before calling sdhci_add_host(), and we 251115ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 251215ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity */ 25135fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 251415ec44611904be0dcc97b84c29fbf964e5e2b36fPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 2515d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2516f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[0] & SDHCI_CAN_DO_HISPD) 2517a29e7e18bddde778deb2cb101dbceca56b15e05eZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 2518cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 2519176d1ed426a2a73a87c62a8aa05f6d002353cd50Jaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 2520176d1ed426a2a73a87c62a8aa05f6d002353cd50Jaehoon Chung mmc_card_is_removable(mmc)) 252168d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 252268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 2523f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* UHS-I mode(s) supported by the host controller. */ 2524f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (host->version >= SDHCI_SPEC_300) 2525f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 2526f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2527f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* SDR104 supports also implies SDR50 support */ 2528f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[1] & SDHCI_SUPPORT_SDR104) 2529f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 2530f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath else if (caps[1] & SDHCI_SUPPORT_SDR50) 2531f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 2532f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2533f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[1] & SDHCI_SUPPORT_DDR50) 2534f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 2535f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2536b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath /* Does the host needs tuning for SDR50? */ 2537b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath if (caps[1] & SDHCI_USE_SDR50_TUNING) 2538b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 2539b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 2540d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 2541d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (caps[1] & SDHCI_DRIVER_TYPE_A) 2542d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 2543d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (caps[1] & SDHCI_DRIVER_TYPE_C) 2544d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 2545d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath if (caps[1] & SDHCI_DRIVER_TYPE_D) 2546d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 2547d6d50a15a2897d4133d536dd4343b5cf21163db3Arindam Nath 2548cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Initial value for re-tuning timer count */ 2549cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> 2550cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath SDHCI_RETUNING_TIMER_COUNT_SHIFT; 2551cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 2552cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* 2553cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * In case Re-tuning Timer is not disabled, the actual value of 2554cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath * re-tuning timer will be 2 ^ (n - 1). 2555cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath */ 2556cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->tuning_count) 2557cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 2558cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 2559cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Re-tuning mode supported by the Host Controller */ 2560cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_mode = (caps[1] & SDHCI_RETUNING_MODE_MASK) >> 2561cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath SDHCI_RETUNING_MODE_SHIFT; 2562cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 25638f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai ocr_avail = 0; 2564f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath /* 2565f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * According to SD Host Controller spec v3.00, if the Host System 2566f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 2567f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * the value is meaningful only if Voltage Support in the Capabilities 2568f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * register is set. The actual current value is 4 times the register 2569f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath * value. 2570f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath */ 2571f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 2572f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2573f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[0] & SDHCI_CAN_VDD_330) { 2574f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath int max_current_330; 2575f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 25768f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 2577f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2578f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath max_current_330 = ((max_current_caps & 2579f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_330_MASK) >> 2580f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_330_SHIFT) * 2581f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 2582f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2583f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (max_current_330 > 150) 2584f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_SET_XPC_330; 2585f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 2586f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[0] & SDHCI_CAN_VDD_300) { 2587f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath int max_current_300; 2588f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 25898f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 2590f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2591f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath max_current_300 = ((max_current_caps & 2592f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_300_MASK) >> 2593f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_300_SHIFT) * 2594f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 2595f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2596f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (max_current_300 > 150) 2597f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_SET_XPC_300; 2598f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 2599f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (caps[0] & SDHCI_CAN_VDD_180) { 2600f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath int max_current_180; 2601f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 26028f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai ocr_avail |= MMC_VDD_165_195; 26038f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai 2604f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath max_current_180 = ((max_current_caps & 2605f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_180_MASK) >> 2606f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_180_SHIFT) * 2607f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 2608f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 2609f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath if (max_current_180 > 150) 2610f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->caps |= MMC_CAP_SET_XPC_180; 26115371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath 26125371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath /* Maximum current capabilities of the host at 1.8V */ 26135371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath if (max_current_180 >= 800) 26145371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath mmc->caps |= MMC_CAP_MAX_CURRENT_800; 26155371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath else if (max_current_180 >= 600) 26165371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath mmc->caps |= MMC_CAP_MAX_CURRENT_600; 26175371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath else if (max_current_180 >= 400) 26185371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath mmc->caps |= MMC_CAP_MAX_CURRENT_400; 26195371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath else 26205371c927bcd06a5c9dd6785bab2d452b87d9abc6Arindam Nath mmc->caps |= MMC_CAP_MAX_CURRENT_200; 2621f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath } 2622f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath 26238f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail = ocr_avail; 26248f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 26258f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai if (host->ocr_avail_sdio) 26268f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 26278f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_sd = ocr_avail; 26288f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai if (host->ocr_avail_sd) 26298f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 26308f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai else /* normal SD controllers don't support 1.8V */ 26318f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 26328f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 26338f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai if (host->ocr_avail_mmc) 26348f230f454fe04ba326ffaead3a6b88dcf44eaf4bTakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 2635146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 2636146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman if (mmc->ocr_avail == 0) { 2637146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 2638b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "support voltages.\n", mmc_hostname(mmc)); 2639b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -ENODEV; 2640146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman } 2641146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 2642d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_init(&host->lock); 2643d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2644d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 26452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Maximum number of segments. Depends on if the hardware 26462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * can do scatter/gather or not. 2647d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 26482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 2649a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 128; 2650a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors else if (host->flags & SDHCI_USE_SDMA) 2651a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 1; 26522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else /* PIO */ 2653a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 128; 2654d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2655d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 2656bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 265755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * size (512KiB). 2658d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 265955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_req_size = 524288; 2660d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2661d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 2662d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Maximum segment size. Could be one segment with the maximum number 26632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 26642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * be larger than 64 KiB though. 2665d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 266630652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 266730652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) 266830652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson mmc->max_seg_size = 65535; 266930652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson else 267030652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson mmc->max_seg_size = 65536; 267130652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson } else { 26722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_seg_size = mmc->max_req_size; 267330652aa36b58d57fcc1a0acce51e391bbb6edf5eOlof Johansson } 2674d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2675d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 2676fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * Maximum block size. This varies from controller to controller and 2677fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * is specified in the capabilities register. 2678fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman */ 26790633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 26800633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 2; 26810633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } else { 2682f2119df6b764609af4baceb68caf1e848c1c8aa7Arindam Nath mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >> 26830633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 26840633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (mmc->max_blk_size >= 3) { 26850633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov printk(KERN_WARNING "%s: Invalid maximum block size, " 26860633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov "assuming 512 bytes\n", mmc_hostname(mmc)); 26870633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 0; 26880633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 26890633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 26900633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov 26910633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 512 << mmc->max_blk_size; 2692fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 2693fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman /* 269455db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * Maximum block count. 269555db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman */ 26961388eefd5a5e6aaa3cb04070bfc2b944c1d24b82Ben Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 269755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 269855db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman /* 2699d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Init tasklets. 2700d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 2701d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->card_tasklet, 2702d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_card, (unsigned long)host); 2703d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->finish_tasklet, 2704d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_finish, (unsigned long)host); 2705d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2706e4cad1b5a4851c90c1bcf460062074a2fa10815bAl Viro setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 2707d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2708cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->version >= SDHCI_SPEC_300) { 2709b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath init_waitqueue_head(&host->buf_ready_int); 2710b513ea250eb7c36a8afb3df938d632ca6b4df7cdArindam Nath 2711cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath /* Initialize re-tuning timer */ 2712cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath init_timer(&host->tuning_timer); 2713cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_timer.data = (unsigned long)host; 2714cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath host->tuning_timer.function = sdhci_tuning_timer; 2715cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath } 2716cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath 2717dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 2718b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(mmc), host); 2719d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ret) 27208ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman goto untasklet; 2721d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 27229bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); 27239bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (IS_ERR(host->vmmc)) { 27249bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc)); 27259bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski host->vmmc = NULL; 27269bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } else { 27279bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_enable(host->vmmc); 27289bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 27299bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 27302f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, 0); 2731d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2732d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_MMC_DEBUG 2733d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 2734d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif 2735d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2736f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 27375dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa snprintf(host->led_name, sizeof(host->led_name), 27385dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa "%s::", mmc_hostname(mmc)); 27395dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa host->led.name = host->led_name; 27402f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness = LED_OFF; 27412f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.default_trigger = mmc_hostname(mmc); 27422f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness_set = sdhci_led_control; 27432f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2744b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 27452f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (ret) 27462f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman goto reset; 27472f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 27482f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 27495f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 27505f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman 2751d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_add_host(mmc); 2752d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2753a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n", 2754d1b268630875a7713b5d468a0c03403c5b721c8eKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 2755a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_ADMA) ? "ADMA" : 2756a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 2757d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 27587260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 27597260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 2760d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return 0; 2761d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2762f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 27632f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanreset: 27642f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 27652f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman free_irq(host->irq, host); 27662f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 27678ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossmanuntasklet: 2768d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 2769d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 2770d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2771d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return ret; 2772d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2773d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2774b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_add_host); 2775d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 27761e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanvoid sdhci_remove_host(struct sdhci_host *host, int dead) 2777b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 27781e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman unsigned long flags; 27791e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27801e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (dead) { 27811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_lock_irqsave(&host->lock, flags); 27821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27831e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 27841e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27851e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->mrq) { 27861e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman printk(KERN_ERR "%s: Controller removed during " 27871e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 27881e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27891e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 27901e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman tasklet_schedule(&host->finish_tasklet); 27911e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 27921e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27931e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 27941e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 27951e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 27967260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 27977260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 2798b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_remove_host(host->mmc); 2799d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2800f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 28012f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman led_classdev_unregister(&host->led); 28022f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 28032f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 28041e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!dead) 28051e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 2806d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2807d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman free_irq(host->irq, host); 2808d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2809d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer_sync(&host->timer); 2810cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath if (host->version >= SDHCI_SPEC_300) 2811cf2b5eea1ea0ff9b3184bc6771bcb93a9fdcd1d9Arindam Nath del_timer_sync(&host->tuning_timer); 2812d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2813d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 2814d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 28152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 28169bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) { 28179bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_disable(host->vmmc); 28189bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_put(host->vmmc); 28199bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 28209bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 28212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 28222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 28232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 28242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = NULL; 28252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = NULL; 2826d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2827d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2828b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_remove_host); 2829d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2830b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanvoid sdhci_free_host(struct sdhci_host *host) 2831d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2832b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_free_host(host->mmc); 2833d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2834d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2835b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_free_host); 2836d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2837d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 2838d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2839d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Driver init/exit * 2840d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2841d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 2842d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2843d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int __init sdhci_drv_init(void) 2844d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2845d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME 284652fbf9c976b36654e08e94c3107ddbaac7e2da33Pierre Ossman ": Secure Digital Host Controller Interface driver\n"); 2847d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 2848d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2849b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return 0; 2850d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2851d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2852d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void __exit sdhci_drv_exit(void) 2853d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2854d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2855d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2856d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_init(sdhci_drv_init); 2857d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_exit(sdhci_drv_exit); 2858d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2859df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanmodule_param(debug_quirks, uint, 0444); 28606743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 286132710e8fd537adeb53f98dec92e4a77caac512f5Pierre OssmanMODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 2862b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanMODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 2863d129bceb1d44ed3c23b99164849193703372bab4Pierre OssmanMODULE_LICENSE("GPL"); 28646743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 2865df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre OssmanMODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 2866