sdhci.c revision 81b39802468fe4bf5c6b038837319b608acfdd3e
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> 20117636092a87a28a013a4acb5de5492645ed620fRalf Baechle#include <linux/scatterlist.h> 21d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 222f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#include <linux/leds.h> 232f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 24d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/mmc/host.h> 25d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 26d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include "sdhci.h" 27d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 28d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DRIVER_NAME "sdhci" 29d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 30d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DBG(f, x...) \ 31c65631781eb0f2e81865017c1484e9aef76e1b61Russell King pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 32d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 33f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 34f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman defined(CONFIG_MMC_SDHCI_MODULE)) 35f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#define SDHCI_USE_LEDS_CLASS 36f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#endif 37f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman 38df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanstatic unsigned int debug_quirks = 0; 396743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 40d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); 41d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *); 42d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 43d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 44d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *); 45d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 46d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_dumpregs(struct sdhci_host *host) 47d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 48d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); 49d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 50d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 514e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 524e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 53d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 544e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 554e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 56d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 584e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 59d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 604e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 614e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 62d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 634e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 644e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 65d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 674e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 68d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 694e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 71d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 724e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 734e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 74d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 754e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 764e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 77d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", 784e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 80d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 81be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks if (host->flags & SDHCI_USE_ADMA) 82be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 83be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ERROR), 84be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); 85be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks 86d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 87d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 88d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 89d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 90d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 91d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Low level functions * 92d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 93d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 94d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 957260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 967260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 977260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 ier; 987260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 997260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1007260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier &= ~clear; 1017260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier |= set; 1027260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_INT_ENABLE); 1037260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 1047260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1057260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1067260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) 1077260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1087260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, 0, irqs); 1097260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1107260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1117260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) 1127260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1137260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, irqs, 0); 1147260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1157260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1167260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1177260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1187260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 1197260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 12068d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 12168d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov return; 12268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 1237260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov if (enable) 1247260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, irqs); 1257260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 1267260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, irqs); 1277260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1287260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1297260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_enable_card_detection(struct sdhci_host *host) 1307260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1317260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, true); 1327260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1337260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1347260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_disable_card_detection(struct sdhci_host *host) 1357260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1367260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, false); 1377260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1387260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 139d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_reset(struct sdhci_host *host, u8 mask) 140d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 141e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman unsigned long timeout; 142063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov u32 uninitialized_var(ier); 143e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 144b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 1454e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & 1468a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman SDHCI_CARD_PRESENT)) 1478a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman return; 1488a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman } 1498a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 150063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 151063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 152063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 1534e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 154d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 155e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (mask & SDHCI_RESET_ALL) 156d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = 0; 157d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 158e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* Wait max 100 ms */ 159e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout = 100; 160e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 161e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* hw clears the bit when it's done */ 1624e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 163e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (timeout == 0) { 164acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 165e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mmc_hostname(host->mmc), (int)mask); 166e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman sdhci_dumpregs(host); 167e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman return; 168e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman } 169e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout--; 170e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mdelay(1); 171d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 172063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 173063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 174063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 175d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 176d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_init(struct sdhci_host *host) 178d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 179d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 180d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1817260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 1827260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 1833192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 1843192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 1856aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 1867260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 187d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1887260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_reinit(struct sdhci_host *host) 1897260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1907260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_init(host); 1917260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 192d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 193d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 194d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_activate_led(struct sdhci_host *host) 195d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 197d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1984e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 199d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl |= SDHCI_CTRL_LED; 2004e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 201d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 202d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 203d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_deactivate_led(struct sdhci_host *host) 204d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 205d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 206d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2074e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 208d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2094e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 210d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 211d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 212f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 2132f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanstatic void sdhci_led_control(struct led_classdev *led, 2142f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman enum led_brightness brightness) 2152f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman{ 2162f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2172f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman unsigned long flags; 2182f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2192f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_lock_irqsave(&host->lock, flags); 2202f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2212f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (brightness == LED_OFF) 2222f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_deactivate_led(host); 2232f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman else 2242f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_activate_led(host); 2252f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2262f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2272f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman} 2282f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 2292f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 231d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 232d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Core functions * 233d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 234d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 235d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 236a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_read_block_pio(struct sdhci_host *host) 237d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2387659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 2397659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 2407244b85bd17313d7d300ee93ec7bfbca1f4ccf3dSteven Noonan u32 uninitialized_var(scratch); 2417659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 242d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 243a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO reading\n"); 244d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 245a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 2467659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 247d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2487659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 249d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 250a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 2517659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 2527659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 253d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2547659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 255d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2567659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 2577659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 25814d836e7499c53a1f6a65086c3d11600e871a971Alex Dubov 2597659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 260d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2617659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 2627659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (chunk == 0) { 2634e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 2647659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 4; 265a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 2667659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2677659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman *buf = scratch & 0xFF; 2687659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2697659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 2707659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch >>= 8; 2717659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk--; 2727659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 273d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 274a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 2757659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2767659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 2777659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2787659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 279a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 280d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 281a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_write_block_pio(struct sdhci_host *host) 282a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 2837659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 2847659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 2857659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u32 scratch; 2867659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 287d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 288a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO writing\n"); 289a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 290a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 2917659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 2927659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 293d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2947659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 295d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 296a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 2977659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 2987659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 299a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3007659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 3017659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3027659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 3037659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 3047659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3057659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 306d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3077659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 3087659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch |= (u32)*buf << (chunk * 8); 3097659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3107659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 3117659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk++; 3127659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 3137659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3147659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 3154e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 3167659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 3177659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 318d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 319d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 320d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 3217659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3227659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 3237659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3247659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 325a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 326a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 327a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_transfer_pio(struct sdhci_host *host) 328a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 329a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman u32 mask; 330a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 331a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman BUG_ON(!host->data); 332a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3337659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 334a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman return; 335a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 336a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 337a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_DATA_AVAILABLE; 338a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 339a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_SPACE_AVAILABLE; 340a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3414a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman /* 3424a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 3434a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * for transfers < 4 bytes. As long as it is just one block, 3444a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * we can ignore the bits. 3454a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman */ 3464a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 3474a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman (host->data->blocks == 1)) 3484a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman mask = ~0; 3494a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman 3504e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 3513e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 3523e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov udelay(100); 3533e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov 354a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 355a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_read_block_pio(host); 356a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 357a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_write_block_pio(host); 358d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3597659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks--; 3607659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 361a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman break; 362a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 363d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 364a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO transfer complete.\n"); 365d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 366d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_save(*flags); 3702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 3712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 3722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 3742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 3762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_restore(*flags); 3772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 3782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3798f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanstatic int sdhci_adma_table_pre(struct sdhci_host *host, 3802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 3812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 3832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *desc; 3852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 3862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t addr; 3872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t align_addr; 3882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int len, offset; 3892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 3912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i; 3922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 3932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 3942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 3962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The spec does not specify endianness of descriptor table. 3972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We currently guess that it is LE. 3982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 3992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 4012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 4022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 4032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 4042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The ADMA descriptor table is mapped further down as we 4072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * need to fill it with data first. 4082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 4112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer, 128 * 4, direction); 4128d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4138f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto fail; 4142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->align_addr & 0x3); 4152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 4172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg, data->sg_len, direction); 4188f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->sg_count == 0) 4198f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_align; 4202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc = host->adma_desc; 4222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 4232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr = host->align_addr; 4252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr = sg_dma_address(sg); 4282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len = sg_dma_len(sg); 4292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The SDHCI specification states that ADMA 4322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * addresses must be 32-bit aligned. If they 4332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * aren't, then we use a bounce buffer for 4342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * the (up to three) bytes that screw up the 4352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment. 4362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 4382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (offset) { 4392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 4416cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 4422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(align, buffer, offset); 4432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 4442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[7] = (align_addr >> 24) & 0xff; 4472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[6] = (align_addr >> 16) & 0xff; 4482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[5] = (align_addr >> 8) & 0xff; 4492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[4] = (align_addr >> 0) & 0xff; 4502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(offset > 65536); 4522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[3] = (offset >> 8) & 0xff; 4542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[2] = (offset >> 0) & 0xff; 4552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[1] = 0x00; 4572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[0] = 0x21; /* tran, valid */ 4582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 4602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr += 4; 4612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 4632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr += offset; 4652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len -= offset; 4662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[7] = (addr >> 24) & 0xff; 4692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[6] = (addr >> 16) & 0xff; 4702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[5] = (addr >> 8) & 0xff; 4712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[4] = (addr >> 0) & 0xff; 4722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(len > 65536); 4742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[3] = (len >> 8) & 0xff; 4762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[2] = (len >> 0) & 0xff; 4772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[1] = 0x00; 4792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[0] = 0x21; /* tran, valid */ 4802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 4822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * If this triggers then we have a calculation bug 4852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * somewhere. :/ 4862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 4882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Add a terminating entry. 4922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[7] = 0; 4942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[6] = 0; 4952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[5] = 0; 4962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[4] = 0; 4972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[3] = 0; 4992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[2] = 0; 5002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[1] = 0x00; 5022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc[0] = 0x03; /* nop, end, valid */ 5032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 5052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Resync align buffer as we might have changed it. 5062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 5072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 5092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr, 128 * 4, direction); 5102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 5132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 514980167b7fb20fb181766218b4771fc7420a7bbb4Pierre Ossman if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) 5158f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_entries; 5162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->adma_addr & 0x3); 5178f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5188f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return 0; 5198f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5208f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_entries: 5218f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5228f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg_len, direction); 5238f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_align: 5248f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5258f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 128 * 4, direction); 5268f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanfail: 5278f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return -EINVAL; 5282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 5292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_adma_table_post(struct sdhci_host *host, 5312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 5322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 5332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 5342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 5362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i, size; 5372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 5382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 5392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 5402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 5422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 5432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 5442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 5452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 5472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 5482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 128 * 4, direction); 5512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) { 5532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 5542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 5552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 5572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg_dma_address(sg) & 0x3) { 5602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 5612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5636cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(buffer, align, size); 5652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 5682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 5742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 5752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 576ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) 577d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 5781c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman u8 count; 5791c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman unsigned target_timeout, current_timeout; 580d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 581ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* 582ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * If the host controller provides us with an incorrect timeout 583ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * value, just skip the check and use 0xE. The hardware may take 584ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * longer to time out, but that's much better than having a too-short 585ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * timeout value. 586ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman */ 58711a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 588ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return 0xE; 589e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 5901c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman /* timeout in us */ 5911c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman target_timeout = data->timeout_ns / 1000 + 5921c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman data->timeout_clks / host->clock; 593d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 59481b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) 59581b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov host->timeout_clk = host->clock / 1000; 59681b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov 5971c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman /* 5981c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * Figure out needed cycles. 5991c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * We do this in steps in order to fit inside a 32 bit int. 6001c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * The first step is the minimum timeout, which will have a 6011c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * minimum resolution of 6 bits: 6021c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) 2^13*1000 > 2^22, 6031c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (2) host->timeout_clk < 2^16 6041c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * => 6051c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) / (2) > 2^6 6061c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman */ 6071c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0; 6081c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 6091c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman while (current_timeout < target_timeout) { 6101c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count++; 6111c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout <<= 1; 6121c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) 6131c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman break; 6141c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6151c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 6161c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) { 6171c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman printk(KERN_WARNING "%s: Too large timeout requested!\n", 6181c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman mmc_hostname(host->mmc)); 6191c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0xE; 6201c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6211c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 622ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return count; 623ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman} 624ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 6256aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsovstatic void sdhci_set_transfer_irqs(struct sdhci_host *host) 6266aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov{ 6276aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 6286aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 6296aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 6306aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 6316aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 6326aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov else 6336aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); 6346aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov} 6356aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 636ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 637ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman{ 638ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman u8 count; 6392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 ctrl; 6408f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman int ret; 641ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 642ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman WARN_ON(host->data); 643ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 644ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman if (data == NULL) 645ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return; 646ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 647ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* Sanity checks */ 648ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 649ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 650ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blocks > 65535); 651ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 652ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data = data; 653ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data_early = 0; 654ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 655ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman count = sdhci_calc_timeout(host, data); 6564e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 657d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 658c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_USE_DMA) 659c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 660c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 6612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 6622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * FIXME: This doesn't account for merging when mapping the 6632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * scatterlist. 6642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 6652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 6672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 6682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 6702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 6722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 6732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 6742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 6752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 6762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 6772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 6792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->length & 0x3) { 6812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 6822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "transfer size (%d)\n", 6832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sg->length); 6842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 6862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 6872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 6882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 689c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 690c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 691c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman /* 692c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * The assumption here being that alignment is the same after 693c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * translation to device address space. 694c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman */ 6952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 6972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 6982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 7002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * As we use 3 byte chunks to work around 7032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment problems, we need to check this 7042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * quirk. 7052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 7092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 7102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 7142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->offset & 0x3) { 7162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 7172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "bad alignment\n"); 7182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 7202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7258f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7268f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7278f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman ret = sdhci_adma_table_pre(host, data); 7288f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (ret) { 7298f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7308f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7318f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7328f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7338f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 734ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7358f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 7364e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, host->adma_addr, 7374e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_ADMA_ADDRESS); 7388f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7398f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 740c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler int sg_cnt; 7418f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 742c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 7438f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg, data->sg_len, 7448f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman (data->flags & MMC_DATA_READ) ? 7458f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_FROM_DEVICE : 7468f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_TO_DEVICE); 747c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler if (sg_cnt == 0) { 7488f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7498f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7508f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7518f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7528f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 753ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7548f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 755719a61b452ff74cf81a96e4212748d9d63bcc924Pierre Ossman WARN_ON(sg_cnt != 1); 7564e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 7574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_DMA_ADDRESS); 7588f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7598f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7608f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7618f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 7622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Always adjust the DMA selection as some controllers 7642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 7652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * is ADMA. 7662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->version >= SDHCI_SPEC_200) { 7684e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 7692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 7702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 7712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) 7722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 7732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 7742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 7754e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 776c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 777c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 7788f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 779da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior int flags; 780da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior 781da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 782da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 783da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 784da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior else 785da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 786da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 7877659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks = data->blocks; 788d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 789c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 7906aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_set_transfer_irqs(host); 7916aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 792bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 7934e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE); 7944e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 795c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman} 796c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 797c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossmanstatic void sdhci_set_transfer_mode(struct sdhci_host *host, 798c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman struct mmc_data *data) 799c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman{ 800c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman u16 mode; 801c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 802c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data == NULL) 803c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman return; 804c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 805e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman WARN_ON(!host->data); 806e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 807c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 808c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data->blocks > 1) 809c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_MULTI; 810c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data->flags & MMC_DATA_READ) 811c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_READ; 812c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 813c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_DMA; 814c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 8154e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 816d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 817d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 818d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *host) 819d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 820d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_data *data; 821d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 822d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(!host->data); 823d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 824d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman data = host->data; 825d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 826d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 827c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 8282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 8292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_adma_table_post(host, data); 8302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else { 8312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 8322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 8332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 8342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 835d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 836d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 837d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 838c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * The specification states that the block count register must 839c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * be updated, but it does not specify at what point in the 840c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * data flow. That makes the register entirely useless to read 841c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * back so we have to assume that nothing made it to the card 842c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * in the event of an error. 843d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 844c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman if (data->error) 845c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = 0; 846d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 847c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = data->blksz * data->blocks; 848d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 849d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (data->stop) { 850d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 851d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 852d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 853d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 85417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (data->error) { 855d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 856d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 857d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 858d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 859d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_send_command(host, data->stop); 860d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else 861d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 862d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 863d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 864d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 865d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 866d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int flags; 867fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman u32 mask; 8687cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 869d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 870d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->cmd); 871d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 872d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* Wait max 10 ms */ 8737cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout = 10; 874fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 875fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask = SDHCI_CMD_INHIBIT; 876fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 877fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask |= SDHCI_DATA_INHIBIT; 878fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 879fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 880fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman though they might use busy signaling */ 881fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 882fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 883fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 8844e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 8857cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 886d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Controller never released " 887acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 888d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 88917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EIO; 890d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 891d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 892d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 8937cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 8947cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 8957cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 896d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 897d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 898d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 899d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = cmd; 900d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 901d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_prepare_data(host, cmd->data); 902d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9034e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 905c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman sdhci_set_transfer_mode(host, cmd->data); 906c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 907d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 908acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 909d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 91017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EINVAL; 911d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 912d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 913d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 914d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 915d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 916d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_NONE; 917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_136) 918d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_LONG; 919d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 920d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 921d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 922d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT; 923d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 924d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_CRC) 925d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_CRC; 926d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 927d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_INDEX; 928d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->data) 929d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_DATA; 930d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9314e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 932d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 933d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 934d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *host) 935d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 936d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int i; 937d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 938d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(host->cmd == NULL); 939d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 940d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 941d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_136) { 942d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* CRC is stripped so we need to do some shifting. */ 943d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman for (i = 0;i < 4;i++) { 9444e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[i] = sdhci_readl(host, 945d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 946d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (i != 3) 947d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd->resp[i] |= 9484e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, 949d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 950d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 951d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 9524e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 953d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 954d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 955d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 95617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = 0; 957d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 958e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (host->data && host->data_early) 959e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman sdhci_finish_data(host); 960e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 961e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (!host->cmd->data) 962d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 963d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 964d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = NULL; 965d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 966d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 967d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 968d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 969d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int div; 970d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u16 clk; 9717cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 972d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 973d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == host->clock) 974d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 975d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9768114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->ops->set_clock) { 9778114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov host->ops->set_clock(host, clock); 9788114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) 9798114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov return; 9808114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov } 9818114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov 9824e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 983d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 984d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == 0) 985d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 986d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman for (div = 1;div < 256;div *= 2) { 988d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if ((host->max_clk / div) <= clock) 989d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman break; 990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 991d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman div >>= 1; 992d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 993d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk = div << SDHCI_DIVIDER_SHIFT; 994d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_INT_EN; 9954e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 996d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 997d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* Wait max 10 ms */ 9987cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout = 10; 9994e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 10007cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 10017cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 1002acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Internal clock never " 1003acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 1004d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1005d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1006d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 10077cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 10087cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 10097cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 1010d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1011d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 10124e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1013d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1014d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 1015d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = clock; 1016d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1017d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1018146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossmanstatic void sdhci_set_power(struct sdhci_host *host, unsigned short power) 1019146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman{ 1020146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman u8 pwr; 1021146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1022ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (power == (unsigned short)-1) 1023ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = 0; 1024ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman else { 1025ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman switch (1 << power) { 1026ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_165_195: 1027ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_180; 1028ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1029ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_29_30: 1030ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_30_31: 1031ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_300; 1032ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1033ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_32_33: 1034ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_33_34: 1035ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_330; 1036ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1037ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman default: 1038ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman BUG(); 1039ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1040ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1041ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1042ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (host->pwr == pwr) 1043146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman return; 1044146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1045ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman host->pwr = pwr; 1046ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1047ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (pwr == 0) { 10484e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1049ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman return; 10509e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt } 10519e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt 10529e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt /* 10539e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * Spec says that we should clear the power reg before setting 10549e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * a new value. Some controllers don't seem to like this though. 10559e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt */ 1056b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 10574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1058146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1059e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon /* 1060c71f65129a1fb67bc6b9b8d03b493675b5c9302bAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 1061e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon * and set turn on power at the same time, so set the voltage first. 1062e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon */ 106311a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 1064ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1065e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon 1066ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr |= SDHCI_POWER_ON; 1067146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1068ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1069557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte 1070557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte /* 1071557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * Some controllers need an extra 10ms delay of 10ms before they 1072557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * can apply clock after applying power 1073557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte */ 107411a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1075557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte mdelay(10); 1076146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman} 1077146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1078d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1079d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1080d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * MMC callbacks * 1081d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1082d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1083d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1084d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 1085d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1086d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 108768d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov bool present; 1088d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1089d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1090d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1091d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1092d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1093d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1094d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->mrq != NULL); 1095d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1096f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1097d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_activate_led(host); 10982f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1099d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1100d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = mrq; 1101d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 110268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov /* If polling, assume that the card is always present. */ 110368d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 110468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = true; 110568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov else 110668d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 110768d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov SDHCI_CARD_PRESENT; 110868d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 110968d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 111017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1111d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1112d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else 1113d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_send_command(host, mrq->cmd); 1114d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11155f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1116d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1117d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1118d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1119d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1120d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1121d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1122d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1123d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 1124d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1125d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1126d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1127d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1128d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11291e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11301e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 11311e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1132d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1133d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Reset the chip on each power off. 1134d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Should clear out any weird states. 1135d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 11374e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 11387260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_reinit(host); 1139d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1140d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1141d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_set_clock(host, ios->clock); 1142d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1143d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) 1144146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, -1); 1145d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 1146146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, ios->vdd); 1147d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11484e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 1149cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 1150d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->bus_width == MMC_BUS_WIDTH_4) 1151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl |= SDHCI_CTRL_4BITBUS; 1152d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 1153d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl &= ~SDHCI_CTRL_4BITBUS; 1154cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 1155cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman if (ios->timing == MMC_TIMING_SD_HS) 1156cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl |= SDHCI_CTRL_HISPD; 1157cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman else 1158cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 1159cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 11604e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1161d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1162b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo /* 1163b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1164b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1165b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * it on each ios seems to solve the problem. 1166b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo */ 1167b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1168b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1169b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo 11701e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 11715f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1172d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1173d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1174d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1175d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int sdhci_get_ro(struct mmc_host *mmc) 1176d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1178d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1179d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int present; 1180d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1181d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1182d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1183d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1184d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11851e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11861e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman present = 0; 11871e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman else 11884e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE); 1189d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1190d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1191d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1192c5075a1089e808d8f471ce21b02810cc98ab2692Anton Vorontsov if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT) 1193c5075a1089e808d8f471ce21b02810cc98ab2692Anton Vorontsov return !!(present & SDHCI_WRITE_PROTECT); 1194d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return !(present & SDHCI_WRITE_PROTECT); 1195d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1197f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossmanstatic void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1198f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman{ 1199f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman struct sdhci_host *host; 1200f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman unsigned long flags; 1201f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1202f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman host = mmc_priv(mmc); 1203f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1204f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1205f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 12061e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 12071e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 12081e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1209f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (enable) 12107260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); 12117260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 12127260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); 12131e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 1214f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmiowb(); 1215f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1216f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1217f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman} 1218f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1219ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops sdhci_ops = { 1220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .request = sdhci_request, 1221d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .set_ios = sdhci_set_ios, 1222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .get_ro = sdhci_get_ro, 1223f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 1224d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}; 1225d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1226d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1227d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1228d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Tasklets * 1229d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1231d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1232d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_card(unsigned long param) 1233d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1234d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1235d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1236d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1237d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1238d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1239d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1240d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12414e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 1242d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1243d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 1244d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1245d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 1246d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1247d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1248d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1249d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1250d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 125117b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1252d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1253d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1254d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1255d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1256d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1257d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 125804cf585d2902404ed06861c6dc27897100340dbaPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 1259d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1260d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1261d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_finish(unsigned long param) 1262d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1263d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1264d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1265d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_request *mrq; 1266d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1267d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1268d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1269d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1270d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1271d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer(&host->timer); 1272d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1273d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mrq = host->mrq; 1274d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1275d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1276d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 1277d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 1278d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 12791e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 12801e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->cmd->error || 12811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data && (mrq->data->error || 12821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 12831e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 1284645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1285645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Some controllers need this kick or reset won't work here */ 1286b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 1287645289dca5021224279e67b4655796cafdfdad00Pierre Ossman unsigned int clock; 1288645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1289645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* This is to force an update */ 1290645289dca5021224279e67b4655796cafdfdad00Pierre Ossman clock = host->clock; 1291645289dca5021224279e67b4655796cafdfdad00Pierre Ossman host->clock = 0; 1292645289dca5021224279e67b4655796cafdfdad00Pierre Ossman sdhci_set_clock(host, clock); 1293645289dca5021224279e67b4655796cafdfdad00Pierre Ossman } 1294645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1295645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Spec says we should do both at the same time, but Ricoh 1296645289dca5021224279e67b4655796cafdfdad00Pierre Ossman controllers do not like that. */ 1297d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1298d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1299d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1300d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1301d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = NULL; 1302d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = NULL; 1303d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 1304d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1305f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1306d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_deactivate_led(host); 13072f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1308d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 13095f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1310d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1311d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1312d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_request_done(host->mmc, mrq); 1313d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1314d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1315d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_timeout_timer(unsigned long data) 1316d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1317d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1318d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1319d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1320d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)data; 1321d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1322d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1323d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1324d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1325acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 1326acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 1327d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1328d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1329d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->data) { 133017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 1331d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 1332d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 1333d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd) 133417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 1335d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 133617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 1337d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1338d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1339d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1340d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1341d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 13425f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1343d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1344d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1345d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1346d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1347d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1348d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Interrupt handling * 1349d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1350d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1351d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1352d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 1353d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1354d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 1355d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1356d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->cmd) { 1357b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1358b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no command operation was in progress.\n", 1359b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 1360d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1361d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1362d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1363d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 136443b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 136517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 136617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 136717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman SDHCI_INT_INDEX)) 136817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -EILSEQ; 136943b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman 1370e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->error) { 1371d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1372e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1373e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1374e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 1375e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman /* 1376e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The host can send and interrupt when the busy state has 1377e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * ended, allowing us to wait without wasting CPU cycles. 1378e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Unfortunately this is overloaded on the "data complete" 1379e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * interrupt, so we need to take some care when handling 1380e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * it. 1381e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * 1382e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Note: The 1.0 specification is a bit ambiguous about this 1383e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * feature so there might be some problems with older 1384e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * controllers. 1385e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman */ 1386e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->flags & MMC_RSP_BUSY) { 1387e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->data) 1388e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman DBG("Cannot wait for busy signal when also " 1389e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman "doing a data transfer"); 1390f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 1391e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1392f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks 1393f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks /* The controller does not support the end-of-busy IRQ, 1394f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks * fall through and take the SDHCI_INT_RESPONSE */ 1395e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1396e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 1397e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 139843b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman sdhci_finish_command(host); 1399d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1400d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14016882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#ifdef DEBUG 14026882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) 14036882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks{ 14046882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks const char *name = mmc_hostname(host->mmc); 14056882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 *desc = host->adma_desc; 14066882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le32 *dma; 14076882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le16 *len; 14086882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 attr; 14096882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14106882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_dumpregs(host); 14116882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14126882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks while (true) { 14136882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks dma = (__le32 *)(desc + 4); 14146882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks len = (__le16 *)(desc + 2); 14156882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks attr = *desc; 14166882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14176882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 14186882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); 14196882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14206882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks desc += 8; 14216882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14226882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks if (attr & 2) 14236882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks break; 14246882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 14256882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks} 14266882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#else 14276882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) { } 14286882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#endif 14296882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 1430d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 1431d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1432d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 1433d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1434d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->data) { 1435d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1436e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The "data complete" interrupt is also used to 1437e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * indicate that a busy state has ended. See comment 1438e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * above in sdhci_cmd_irq(). 1439d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1440e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { 1441e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1442e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman sdhci_finish_command(host); 1443e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1444e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1445e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1446d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1447b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 1448b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no data operation was in progress.\n", 1449b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 1450d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1451d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1452d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1453d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1454d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1455d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 145617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 145717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 145817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -EILSEQ; 14596882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 14606882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); 14616882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_show_adma_error(host); 14622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->data->error = -EIO; 14636882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 1464d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 146517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (host->data->error) 1466d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 1467d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else { 1468a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 1469d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_transfer_pio(host); 1470d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14716ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman /* 14726ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * We currently don't do anything fancy with DMA 14736ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * boundaries, but as we can't disable the feature 14746ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * we need to at least restart the transfer. 14756ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman */ 14766ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman if (intmask & SDHCI_INT_DMA_END) 14774e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS), 14784e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_DMA_ADDRESS); 14796ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman 1480e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1481e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (host->cmd) { 1482e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman /* 1483e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * Data managed to finish before the 1484e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * command completed. Make sure we do 1485e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * things in the proper order. 1486e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman */ 1487e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman host->data_early = 1; 1488e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } else { 1489e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman sdhci_finish_data(host); 1490e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 1491e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 1492d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1493d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1494d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14957d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sdhci_irq(int irq, void *dev_id) 1496d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1497d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman irqreturn_t result; 1498d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host* host = dev_id; 1499d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u32 intmask; 1500f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman int cardint = 0; 1501d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1502d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock(&host->lock); 1503d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15044e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 1505d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 150662df67a523acd7a22d936bf946b1889dbd60ca98Mark Lord if (!intmask || intmask == 0xffffffff) { 1507d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_NONE; 1508d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 1509d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1510d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1511b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 1512b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(host->mmc), intmask); 1513d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15143192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 15154e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 15164e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 1517d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->card_tasklet); 15183192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 1519d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15203192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 1521d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15223192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 15234e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 15244e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 15253192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 1526d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1527d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1528d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 15294e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, 15304e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 15313192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 1532d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1533d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1534d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 1535d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1536964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman intmask &= ~SDHCI_INT_ERROR; 1537964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman 1538d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 15393192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 1540d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 15414e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); 1542d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1543d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15449d26a5d3f2b9c4fe4b2ba491683c6989ecd6ae04Rolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 15453192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman 1546f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (intmask & SDHCI_INT_CARD_INT) 1547f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman cardint = 1; 1548f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1549f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 1550f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 15513192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask) { 1552acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 15533192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman mmc_hostname(host->mmc), intmask); 1554d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1555d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15564e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 15573192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 1558d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1559d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_HANDLED; 1560d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15615f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1562d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 1563d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock(&host->lock); 1564d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1565f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman /* 1566f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman * We have to delay this as it calls back into the driver. 1567f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman */ 1568f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (cardint) 1569f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmc_signal_sdio_irq(host->mmc); 1570f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1571d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return result; 1572d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1573d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1574d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1575d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1576d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Suspend/resume * 1577d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1578d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1579d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1580d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_PM 1581d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1582b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 1583d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1584b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1585a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 15867260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 15877260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1588b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = mmc_suspend_host(host->mmc, state); 1589b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (ret) 1590b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ret; 1591a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 1592b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman free_irq(host->irq, host); 1593d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1594d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return 0; 1595d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1596d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1597b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_suspend_host); 1598d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1599b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_resume_host(struct sdhci_host *host) 1600b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 1601b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1602d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1603b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->flags & SDHCI_USE_DMA) { 1604b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) 1605b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->ops->enable_dma(host); 1606b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 1607d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1608b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1609b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(host->mmc), host); 1610df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman if (ret) 1611df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman return ret; 1612d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1613b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman sdhci_init(host); 1614b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmiowb(); 1615b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman 1616b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = mmc_resume_host(host->mmc); 1617b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (ret) 1618b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ret; 1619d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16207260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 16217260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1622d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return 0; 1623d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1624d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1625b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_resume_host); 1626d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1627d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif /* CONFIG_PM */ 1628d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1629d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1630d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1631b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman * Device allocation/registration * 1632d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1633d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1634d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1635b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanstruct sdhci_host *sdhci_alloc_host(struct device *dev, 1636b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman size_t priv_size) 1637d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1638d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_host *mmc; 1639d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1640d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1641b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(dev == NULL); 1642d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1643b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 1644d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!mmc) 1645b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ERR_PTR(-ENOMEM); 1646d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1647d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1648d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mmc = mmc; 1649d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1650b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return host; 1651b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman} 16528a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 1653b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_alloc_host); 1654d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1655b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_add_host(struct sdhci_host *host) 1656b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 1657b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman struct mmc_host *mmc; 1658b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman unsigned int caps; 1659b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1660d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1661b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(host == NULL); 1662b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host == NULL) 1663b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -EINVAL; 1664d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1665b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = host->mmc; 1666d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1667b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (debug_quirks) 1668b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->quirks = debug_quirks; 1669d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1670d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1671d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman 16724e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 16732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 16742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 16752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->version > SDHCI_SPEC_200) { 16764a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 1677b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 16782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version); 16794a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman } 16804a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman 16814e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov caps = sdhci_readl(host, SDHCI_CAPABILITIES); 1682d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1683b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 168498608076a21914ab12f1c858a0cdf55366260f12Pierre Ossman host->flags |= SDHCI_USE_DMA; 16856743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman else if (!(caps & SDHCI_CAN_DO_DMA)) 16866743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman DBG("Controller doesn't have DMA capability\n"); 16876743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman else 1688d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->flags |= SDHCI_USE_DMA; 1689d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1690b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 16917c168e3db7d900008ee304574057e0dc1a8505afFeng Tang (host->flags & SDHCI_USE_DMA)) { 1692cee687ce4ab1197e20d4dacc09df01531362fdbdRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 16937c168e3db7d900008ee304574057e0dc1a8505afFeng Tang host->flags &= ~SDHCI_USE_DMA; 16947c168e3db7d900008ee304574057e0dc1a8505afFeng Tang } 16957c168e3db7d900008ee304574057e0dc1a8505afFeng Tang 1696d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->flags & SDHCI_USE_DMA) { 16972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->version >= SDHCI_SPEC_200) && 16982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (caps & SDHCI_CAN_DO_ADMA2)) 16992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags |= SDHCI_USE_ADMA; 17002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 17012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 17022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 17032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 17042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 17052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 17072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 17082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_DMA) { 1709b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) { 1710b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma(host)) { 1711b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 1712b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman "available. Falling back to PIO.\n", 1713b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(mmc)); 17142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA); 1715b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 1716d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1717d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1718d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 17192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 17202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 17212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We need to allocate descriptors for all sg entries 17222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (128) and potentially one alignment transfer for 17232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * each of those entries. 17242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 17252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 17262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 17272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (!host->adma_desc || !host->align_buffer) { 17282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 17292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 17302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 17312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "buffers. Falling back to standard DMA.\n", 17322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc_hostname(mmc)); 17332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 17352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 17362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 17377659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman /* 17387659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * If we use DMA, then it's up to the caller to set the DMA 17397659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask, but PIO does not need the hw shim so we set a new 17407659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask here in that case. 17417659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman */ 17427659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!(host->flags & SDHCI_USE_DMA)) { 17437659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->dma_mask = DMA_BIT_MASK(64); 17447659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 17457659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman } 1746d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 17478ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman host->max_clk = 17488ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 17494240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk *= 1000000; 17508ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman if (host->max_clk == 0) { 17514240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks if (!host->ops->get_max_clock) { 17524240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 17534240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify base clock " 17544240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 17554240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 17564240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 17574240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk = host->ops->get_max_clock(host); 17588ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman } 1759d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 17601c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk = 17611c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 17621c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (host->timeout_clk == 0) { 176381b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov if (host->ops->get_timeout_clock) { 176481b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov host->timeout_clk = host->ops->get_timeout_clock(host); 176581b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov } else if (!(host->quirks & 176681b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 17674240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 17684240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify timeout clock " 17694240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 17704240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 17714240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 17721c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 17731c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (caps & SDHCI_TIMEOUT_CLK_UNIT) 17741c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk *= 1000; 1775d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1776d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1777d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Set host parameters. 1778d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1779d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->ops = &sdhci_ops; 1780e9510176ff728135383f0cdfc9c90cfe57f9e162Anton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK && 1781e9510176ff728135383f0cdfc9c90cfe57f9e162Anton Vorontsov host->ops->set_clock && host->ops->get_min_clock) 1782a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 1783a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov else 1784a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov mmc->f_min = host->max_clk / 256; 1785d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->f_max = host->max_clk; 17865fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov mmc->caps = MMC_CAP_SDIO_IRQ; 17875fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov 17885fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 17895fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov mmc->caps |= MMC_CAP_4_BIT_DATA; 1790d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 179186a6a8749d5b8fd5c2b544fe9fd11101e3d0550fPierre Ossman if (caps & SDHCI_CAN_DO_HISPD) 1792cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman mmc->caps |= MMC_CAP_SD_HIGHSPEED; 1793cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 179468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 179568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 179668d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 1797146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail = 0; 1798146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman if (caps & SDHCI_CAN_VDD_330) 1799146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; 1800c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman if (caps & SDHCI_CAN_VDD_300) 1801146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; 1802c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman if (caps & SDHCI_CAN_VDD_180) 180355556da01284af8c2174b786b3eca8e11301b656Philip Langdale mmc->ocr_avail |= MMC_VDD_165_195; 1804146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1805146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman if (mmc->ocr_avail == 0) { 1806146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 1807b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "support voltages.\n", mmc_hostname(mmc)); 1808b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -ENODEV; 1809146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman } 1810146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1811d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_init(&host->lock); 1812d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1813d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 18142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Maximum number of segments. Depends on if the hardware 18152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * can do scatter/gather or not. 1816d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 18172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 18182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_hw_segs = 128; 18192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else if (host->flags & SDHCI_USE_DMA) 1820d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->max_hw_segs = 1; 18212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else /* PIO */ 18222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_hw_segs = 128; 18232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_phys_segs = 128; 1824d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1825d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1826bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 182755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * size (512KiB). 1828d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 182955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_req_size = 524288; 1830d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1831d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1832d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Maximum segment size. Could be one segment with the maximum number 18332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 18342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * be larger than 64 KiB though. 1835d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 18362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 18372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_seg_size = 65536; 18382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 18392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_seg_size = mmc->max_req_size; 1840d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1841d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1842fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * Maximum block size. This varies from controller to controller and 1843fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * is specified in the capabilities register. 1844fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman */ 18450633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 18460633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 2; 18470633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } else { 18480633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> 18490633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 18500633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (mmc->max_blk_size >= 3) { 18510633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov printk(KERN_WARNING "%s: Invalid maximum block size, " 18520633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov "assuming 512 bytes\n", mmc_hostname(mmc)); 18530633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 0; 18540633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 18550633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 18560633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov 18570633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 512 << mmc->max_blk_size; 1858fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 1859fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman /* 186055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * Maximum block count. 186155db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman */ 18621388eefd5a5e6aaa3cb04070bfc2b944c1d24b82Ben Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 186355db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 186455db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman /* 1865d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Init tasklets. 1866d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1867d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->card_tasklet, 1868d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_card, (unsigned long)host); 1869d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->finish_tasklet, 1870d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_finish, (unsigned long)host); 1871d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1872e4cad1b5a4851c90c1bcf460062074a2fa10815bAl Viro setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 1873d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1874dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1875b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(mmc), host); 1876d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ret) 18778ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman goto untasklet; 1878d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1879d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_init(host); 1880d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1881d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_MMC_DEBUG 1882d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1883d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif 1884d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1885f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 18865dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa snprintf(host->led_name, sizeof(host->led_name), 18875dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa "%s::", mmc_hostname(mmc)); 18885dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa host->led.name = host->led_name; 18892f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness = LED_OFF; 18902f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.default_trigger = mmc_hostname(mmc); 18912f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness_set = sdhci_led_control; 18922f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 1893b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 18942f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (ret) 18952f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman goto reset; 18962f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 18972f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 18985f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 18995f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman 1900d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_add_host(mmc); 1901d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", 1903d1b268630875a7713b5d468a0c03403c5b721c8eKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 19042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)?"A":"", 1905d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); 1906d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19077260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 19087260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1909d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return 0; 1910d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1911f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 19122f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanreset: 19132f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 19142f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman free_irq(host->irq, host); 19152f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 19168ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossmanuntasklet: 1917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 1918d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 1919d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1920d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return ret; 1921d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1922d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1923b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_add_host); 1924d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19251e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanvoid sdhci_remove_host(struct sdhci_host *host, int dead) 1926b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 19271e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman unsigned long flags; 19281e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19291e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (dead) { 19301e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_lock_irqsave(&host->lock, flags); 19311e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19321e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 19331e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19341e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->mrq) { 19351e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman printk(KERN_ERR "%s: Controller removed during " 19361e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 19371e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19381e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 19391e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman tasklet_schedule(&host->finish_tasklet); 19401e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 19411e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19421e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 19431e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 19441e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 19457260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 19467260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1947b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_remove_host(host->mmc); 1948d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1949f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 19502f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman led_classdev_unregister(&host->led); 19512f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 19522f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 19531e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!dead) 19541e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1955d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1956d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman free_irq(host->irq, host); 1957d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1958d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer_sync(&host->timer); 1959d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1960d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 1961d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 19622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 19632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 19642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 19652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 19662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = NULL; 19672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = NULL; 1968d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1969d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1970b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_remove_host); 1971d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1972b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanvoid sdhci_free_host(struct sdhci_host *host) 1973d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1974b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_free_host(host->mmc); 1975d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1976d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1977b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_free_host); 1978d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1979d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1980d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Driver init/exit * 1982d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1983d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1984d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1985d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int __init sdhci_drv_init(void) 1986d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME 198852fbf9c976b36654e08e94c3107ddbaac7e2da33Pierre Ossman ": Secure Digital Host Controller Interface driver\n"); 1989d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 1990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1991b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return 0; 1992d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1993d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1994d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void __exit sdhci_drv_exit(void) 1995d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1996d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1997d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1998d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_init(sdhci_drv_init); 1999d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_exit(sdhci_drv_exit); 2000d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2001df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanmodule_param(debug_quirks, uint, 0444); 20026743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 200332710e8fd537adeb53f98dec92e4a77caac512f5Pierre OssmanMODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 2004b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanMODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 2005d129bceb1d44ed3c23b99164849193703372bab4Pierre OssmanMODULE_LICENSE("GPL"); 20066743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 2007df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre OssmanMODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 2008