sdhci.c revision 5f619704d18b93869d045abc49e09cdba109b04b
1d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/* 270f10482c668301c483acded13bf68780ad352b9Pierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver 3d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * 4b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. 5d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * 6d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * This program is free software; you can redistribute it and/or modify 7643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * it under the terms of the GNU General Public License as published by 8643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 9643f720cea989d2913fc0120a2384fecc1be1f9aPierre Ossman * your option) any later version. 1084c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * 1184c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * Thanks to the following companies for their support: 1284c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * 1384c46a53fc4ea4ff36df783a20187b2f65dd21ccPierre Ossman * - JMicron (hardware and technical support) 14d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 15d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/delay.h> 17d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/highmem.h> 18b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman#include <linux/io.h> 19d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/dma-mapping.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 21117636092a87a28a013a4acb5de5492645ed620fRalf Baechle#include <linux/scatterlist.h> 229bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski#include <linux/regulator/consumer.h> 23d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 242f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#include <linux/leds.h> 252f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 26d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include <linux/mmc/host.h> 27d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 28d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#include "sdhci.h" 29d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 30d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DRIVER_NAME "sdhci" 31d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 32d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#define DBG(f, x...) \ 33c65631781eb0f2e81865017c1484e9aef76e1b61Russell King pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) 34d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 35f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 36f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman defined(CONFIG_MMC_SDHCI_MODULE)) 37f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#define SDHCI_USE_LEDS_CLASS 38f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#endif 39f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman 40df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanstatic unsigned int debug_quirks = 0; 416743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 42d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); 43d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *); 44d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 45d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 46d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *); 47d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 48d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_dumpregs(struct sdhci_host *host) 49d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 50412ab659b2bdad6afac8f84daf2a8a393145dcaePhilip Rakity printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", 51412ab659b2bdad6afac8f84daf2a8a393145dcaePhilip Rakity mmc_hostname(host->mmc)); 52d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 53d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", 544e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 554e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 56d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", 574e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 584e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 59d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", 604e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 614e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 62d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", 634e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 644e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 65d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", 664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 674e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 68d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", 694e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 71d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", 724e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 734e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 74d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", 754e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 764e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 77d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", 784e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_ACMD12_ERR), 794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 80d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", 814e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 824e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 83d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 84be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks if (host->flags & SDHCI_USE_ADMA) 85be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 86be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ERROR), 87be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); 88be3f4ae0c0c56aab903aceaceed4b9d8418e180eBen Dooks 89d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); 90d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 91d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 92d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 93d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 94d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Low level functions * 95d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 96d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 97d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 987260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 997260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1007260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 ier; 1017260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1027260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 1037260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier &= ~clear; 1047260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov ier |= set; 1057260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_INT_ENABLE); 1067260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 1077260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1087260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1097260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) 1107260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1117260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, 0, irqs); 1127260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1137260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1147260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) 1157260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1167260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, irqs, 0); 1177260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1187260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1197260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1207260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1217260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 1227260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 12368d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 12468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov return; 12568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 1267260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov if (enable) 1277260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, irqs); 1287260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 1297260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, irqs); 1307260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1317260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1327260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_enable_card_detection(struct sdhci_host *host) 1337260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1347260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, true); 1357260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1367260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1377260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_disable_card_detection(struct sdhci_host *host) 1387260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 1397260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_set_card_detection(host, false); 1407260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 1417260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 142d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_reset(struct sdhci_host *host, u8 mask) 143d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 144e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman unsigned long timeout; 145063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov u32 uninitialized_var(ier); 146e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 147b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 1484e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & 1498a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman SDHCI_CARD_PRESENT)) 1508a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman return; 1518a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman } 1528a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 153063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 154063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov ier = sdhci_readl(host, SDHCI_INT_ENABLE); 155063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 1564e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 157d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 158e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (mask & SDHCI_RESET_ALL) 159d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = 0; 160d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 161e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* Wait max 100 ms */ 162e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout = 100; 163e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman 164e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman /* hw clears the bit when it's done */ 1654e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 166e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman if (timeout == 0) { 167acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Reset 0x%x never completed.\n", 168e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mmc_hostname(host->mmc), (int)mask); 169e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman sdhci_dumpregs(host); 170e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman return; 171e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman } 172e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman timeout--; 173e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman mdelay(1); 174d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 175063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov 176063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) 177063a9dbbce5559770b7e2e2f51bd29adf3ab9b1eAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 178d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 179d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1802f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitrestatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); 1812f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre 1822f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitrestatic void sdhci_init(struct sdhci_host *host, int soft) 183d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1842f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre if (soft) 1852f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); 1862f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre else 1872f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_reset(host, SDHCI_RESET_ALL); 188d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1897260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 1907260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 1913192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 1923192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 1936aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 1942f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre 1952f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre if (soft) { 1962f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre /* force clock reconfiguration */ 1972f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre host->clock = 0; 1982f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_set_ios(host->mmc, &host->mmc->ios); 1992f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre } 2007260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov} 201d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2027260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsovstatic void sdhci_reinit(struct sdhci_host *host) 2037260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov{ 2042f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, 0); 2057260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 206d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 207d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 208d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_activate_led(struct sdhci_host *host) 209d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 210d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 211d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2124e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 213d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl |= SDHCI_CTRL_LED; 2144e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 215d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 216d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 217d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_deactivate_led(struct sdhci_host *host) 218d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 219d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2214e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl &= ~SDHCI_CTRL_LED; 2234e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 224d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 225d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 226f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 2272f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanstatic void sdhci_led_control(struct led_classdev *led, 2282f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman enum led_brightness brightness) 2292f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman{ 2302f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 2312f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman unsigned long flags; 2322f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2332f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_lock_irqsave(&host->lock, flags); 2342f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2352f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (brightness == LED_OFF) 2362f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_deactivate_led(host); 2372f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman else 2382f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_activate_led(host); 2392f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 2402f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2412f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman} 2422f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 2432f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 244d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 245d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 246d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Core functions * 247d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 248d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 249d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 250a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_read_block_pio(struct sdhci_host *host) 251d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2527659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 2537659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 2547244b85bd17313d7d300ee93ec7bfbca1f4ccf3dSteven Noonan u32 uninitialized_var(scratch); 2557659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 256d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 257a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO reading\n"); 258d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 259a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 2607659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 261d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2627659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 263d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 264a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 2657659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 2667659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 267d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2687659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 269d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2707659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 2717659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 27214d836e7499c53a1f6a65086c3d11600e871a971Alex Dubov 2737659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 274d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2757659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 2767659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (chunk == 0) { 2774e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 2787659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 4; 279a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 2807659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2817659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman *buf = scratch & 0xFF; 2827659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2837659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 2847659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch >>= 8; 2857659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk--; 2867659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 287d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 288a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 2897659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2907659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 2917659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 2927659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 293a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 294d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 295a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_write_block_pio(struct sdhci_host *host) 296a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 2977659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman unsigned long flags; 2987659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman size_t blksize, len, chunk; 2997659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u32 scratch; 3007659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman u8 *buf; 301d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 302a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO writing\n"); 303a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 304a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman blksize = host->data->blksz; 3057659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 3067659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 307d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3087659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_save(flags); 309d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 310a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman while (blksize) { 3117659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (!sg_miter_next(&host->sg_miter)) 3127659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman BUG(); 313a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3147659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len = min(host->sg_miter.length, blksize); 3157659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3167659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman blksize -= len; 3177659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->sg_miter.consumed = len; 3187659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3197659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf = host->sg_miter.addr; 320d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3217659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman while (len) { 3227659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch |= (u32)*buf << (chunk * 8); 3237659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3247659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman buf++; 3257659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk++; 3267659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman len--; 3277659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3287659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 3294e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 3307659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman chunk = 0; 3317659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman scratch = 0; 332d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 333d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 334d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 3357659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3367659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman sg_miter_stop(&host->sg_miter); 3377659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman 3387659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman local_irq_restore(flags); 339a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman} 340a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 341a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_transfer_pio(struct sdhci_host *host) 342a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{ 343a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman u32 mask; 344a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 345a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman BUG_ON(!host->data); 346a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3477659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 348a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman return; 349a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 350a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 351a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_DATA_AVAILABLE; 352a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 353a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman mask = SDHCI_SPACE_AVAILABLE; 354a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman 3554a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman /* 3564a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 3574a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * for transfers < 4 bytes. As long as it is just one block, 3584a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman * we can ignore the bits. 3594a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman */ 3604a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 3614a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman (host->data->blocks == 1)) 3624a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman mask = ~0; 3634a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman 3644e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 3653e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 3663e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov udelay(100); 3673e3bf20756aeee57a40fd37b923263c9a51b8c68Anton Vorontsov 368a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (host->data->flags & MMC_DATA_READ) 369a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_read_block_pio(host); 370a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman else 371a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman sdhci_write_block_pio(host); 372d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3737659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks--; 3747659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman if (host->blocks == 0) 375a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman break; 376a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman } 377d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 378a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman DBG("PIO transfer complete.\n"); 379d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 380d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 3812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 3822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_save(*flags); 3842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; 3852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 3862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 3872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 3882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 3892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kunmap_atomic(buffer, KM_BIO_SRC_IRQ); 3902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman local_irq_restore(*flags); 3912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 3922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 393118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooksstatic void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd) 394118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks{ 3959e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks __le32 *dataddr = (__le32 __force *)(desc + 4); 3969e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks __le16 *cmdlen = (__le16 __force *)desc; 397118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 3989e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks /* SDHCI specification says ADMA descriptors should be 4 byte 3999e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks * aligned, so using 16 or 32bit operations should be safe. */ 400118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 4019e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks cmdlen[0] = cpu_to_le16(cmd); 4029e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks cmdlen[1] = cpu_to_le16(len); 4039e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks 4049e506f35b1dc327c448d4791bc098f07b9b2efe9Ben Dooks dataddr[0] = cpu_to_le32(addr); 405118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks} 406118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks 4078f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanstatic int sdhci_adma_table_pre(struct sdhci_host *host, 4082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 4092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 4102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 4112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *desc; 4132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 4142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t addr; 4152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_addr_t align_addr; 4162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int len, offset; 4172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 4192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i; 4202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 4212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 4222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The spec does not specify endianness of descriptor table. 4252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We currently guess that it is LE. 4262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 4292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 4302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 4312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 4322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The ADMA descriptor table is mapped further down as we 4352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * need to fill it with data first. 4362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr = dma_map_single(mmc_dev(host->mmc), 4392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer, 128 * 4, direction); 4408d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 4418f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto fail; 4422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->align_addr & 0x3); 4432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->sg_count = dma_map_sg(mmc_dev(host->mmc), 4452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg, data->sg_len, direction); 4468f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->sg_count == 0) 4478f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_align; 4482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc = host->adma_desc; 4502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 4512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr = host->align_addr; 4532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 4552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr = sg_dma_address(sg); 4562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len = sg_dma_len(sg); 4572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * The SDHCI specification states that ADMA 4602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * addresses must be 32-bit aligned. If they 4612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * aren't, then we use a bounce buffer for 4622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * the (up to three) bytes that screw up the 4632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment. 4642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman offset = (4 - (addr & 0x3)) & 0x3; 4662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (offset) { 4672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 4682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 4696cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 4702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(align, buffer, offset); 4712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 4722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 474118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks /* tran, valid */ 475118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks sdhci_set_adma_desc(desc, align_addr, offset, 0x21); 4762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(offset > 65536); 4782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 4802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align_addr += 4; 4812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 4832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman addr += offset; 4852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman len -= offset; 4862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 4872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(len > 65536); 4892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 490118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks /* tran, valid */ 491118cd17d4137f34c747c32765c1cb4d3910c04d4Ben Dooks sdhci_set_adma_desc(desc, addr, len, 0x21); 4922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman desc += 8; 4932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 4942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 4952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * If this triggers then we have a calculation bug 4962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * somewhere. :/ 4972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 4982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 4992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 50170764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 50270764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* 50370764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham * Mark the last descriptor as the terminating descriptor 50470764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham */ 50570764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham if (desc != host->adma_desc) { 50670764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham desc -= 8; 50770764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham desc[0] |= 0x2; /* end */ 50870764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } 50970764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } else { 51070764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* 51170764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham * Add a terminating entry. 51270764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham */ 5132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 51470764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham /* nop, end, valid */ 51570764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham sdhci_set_adma_desc(desc, 0, 0, 0x3); 51670764a905785ebacc8d44fed7a12fba3db267ae6Thomas Abraham } 5172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 5192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Resync align buffer as we might have changed it. 5202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 5212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_WRITE) { 5222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_single_for_device(mmc_dev(host->mmc), 5232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_addr, 128 * 4, direction); 5242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_addr = dma_map_single(mmc_dev(host->mmc), 5272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 528980167b7fb20fb181766218b4771fc7420a7bbb4Pierre Ossman if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) 5298f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman goto unmap_entries; 5302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman BUG_ON(host->adma_addr & 0x3); 5318f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5328f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return 0; 5338f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 5348f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_entries: 5358f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5368f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg_len, direction); 5378f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_align: 5388f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5398f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 128 * 4, direction); 5408f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanfail: 5418f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman return -EINVAL; 5422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 5432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_adma_table_post(struct sdhci_host *host, 5452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct mmc_data *data) 5462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{ 5472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int direction; 5482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 5502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int i, size; 5512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 *align; 5522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman char *buffer; 5532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman unsigned long flags; 5542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) 5562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_FROM_DEVICE; 5572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 5582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman direction = DMA_TO_DEVICE; 5592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, 5612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (128 * 2 + 1) * 4, DMA_TO_DEVICE); 5622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_single(mmc_dev(host->mmc), host->align_addr, 5642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 128 * 4, direction); 5652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (data->flags & MMC_DATA_READ) { 5672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 5682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 5692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align = host->align_buffer; 5712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 5732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg_dma_address(sg) & 0x3) { 5742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman size = 4 - (sg_dma_address(sg) & 0x3); 5752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 5776cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); 5782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman memcpy(buffer, align, size); 5792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 5802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman align += 4; 5822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 5852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 5862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 5872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, direction); 5882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman} 5892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 590ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) 591d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 5921c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman u8 count; 5931c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman unsigned target_timeout, current_timeout; 594d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 595ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* 596ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * If the host controller provides us with an incorrect timeout 597ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * value, just skip the check and use 0xE. The hardware may take 598ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * longer to time out, but that's much better than having a too-short 599ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman * timeout value. 600ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman */ 60111a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 602ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return 0xE; 603e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 6041c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman /* timeout in us */ 6051c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman target_timeout = data->timeout_ns / 1000 + 6061c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman data->timeout_clks / host->clock; 607d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 60881b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) 60981b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov host->timeout_clk = host->clock / 1000; 61081b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov 6111c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman /* 6121c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * Figure out needed cycles. 6131c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * We do this in steps in order to fit inside a 32 bit int. 6141c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * The first step is the minimum timeout, which will have a 6151c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * minimum resolution of 6 bits: 6161c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) 2^13*1000 > 2^22, 6171c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (2) host->timeout_clk < 2^16 6181c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * => 6191c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman * (1) / (2) > 2^6 6201c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman */ 6211c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0; 6221c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 6231c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman while (current_timeout < target_timeout) { 6241c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count++; 6251c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman current_timeout <<= 1; 6261c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) 6271c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman break; 6281c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6291c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 6301c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (count >= 0xF) { 6311c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman printk(KERN_WARNING "%s: Too large timeout requested!\n", 6321c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman mmc_hostname(host->mmc)); 6331c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman count = 0xE; 6341c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 6351c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman 636ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return count; 637ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman} 638ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 6396aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsovstatic void sdhci_set_transfer_irqs(struct sdhci_host *host) 6406aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov{ 6416aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 6426aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 6436aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 6446aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 6456aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 6466aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov else 6476aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); 6486aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov} 6496aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 650ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 651ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman{ 652ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman u8 count; 6532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman u8 ctrl; 6548f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman int ret; 655ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 656ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman WARN_ON(host->data); 657ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 658ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman if (data == NULL) 659ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman return; 660ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 661ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman /* Sanity checks */ 662ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 663ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 664ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman BUG_ON(data->blocks > 65535); 665ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 666ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data = data; 667ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman host->data_early = 0; 668ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman 669ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman count = sdhci_calc_timeout(host, data); 6704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 671d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 672a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) 673c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 674c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 6752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 6762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * FIXME: This doesn't account for merging when mapping the 6772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * scatterlist. 6782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 6792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 6802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 6812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 6822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 6842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 6852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 6862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 6872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 6882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 6892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 6902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 6912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 6922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 6932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 6942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->length & 0x3) { 6952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 6962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "transfer size (%d)\n", 6972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sg->length); 6982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 6992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 7002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 703c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 704c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 705c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman /* 706c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * The assumption here being that alignment is the same after 707c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman * translation to device address space. 708c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman */ 7092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman int broken, i; 7112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman struct scatterlist *sg; 7122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 0; 7142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * As we use 3 byte chunks to work around 7172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * alignment problems, we need to check this 7182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * quirk. 7192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) 7212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } else { 7232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 7242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman broken = 1; 7252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (unlikely(broken)) { 7282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 7292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (sg->offset & 0x3) { 7302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Reverting to PIO because of " 7312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "bad alignment\n"); 7322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman break; 7342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 7382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 7398f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 7408f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (host->flags & SDHCI_USE_ADMA) { 7418f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman ret = sdhci_adma_table_pre(host, data); 7428f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (ret) { 7438f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7448f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7458f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7468f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7478f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 748ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7498f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 7504e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, host->adma_addr, 7514e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_ADMA_ADDRESS); 7528f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7538f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 754c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler int sg_cnt; 7558f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 756c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler sg_cnt = dma_map_sg(mmc_dev(host->mmc), 7578f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman data->sg, data->sg_len, 7588f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman (data->flags & MMC_DATA_READ) ? 7598f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_FROM_DEVICE : 7608f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman DMA_TO_DEVICE); 761c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler if (sg_cnt == 0) { 7628f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman /* 7638f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * This only happens when someone fed 7648f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman * us an invalid request. 7658f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman */ 7668f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman WARN_ON(1); 767ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 7688f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } else { 769719a61b452ff74cf81a96e4212748d9d63bcc924Pierre Ossman WARN_ON(sg_cnt != 1); 7704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, sg_dma_address(data->sg), 7714e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_DMA_ADDRESS); 7728f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7738f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7748f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman } 7758f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman 7762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 7772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Always adjust the DMA selection as some controllers 7782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (e.g. JMicron) can't do PIO properly when the selection 7792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * is ADMA. 7802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 7812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->version >= SDHCI_SPEC_200) { 7824e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 7832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl &= ~SDHCI_CTRL_DMA_MASK; 7842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->flags & SDHCI_REQ_USE_DMA) && 7852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) 7862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_ADMA32; 7872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 7882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman ctrl |= SDHCI_CTRL_SDMA; 7894e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 790c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman } 791c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman 7928f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 793da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior int flags; 794da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior 795da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 796da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 797da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 798da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior else 799da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 800da60a91d012bcb10bc5bcd86d585c4281742832cSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 8017659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->blocks = data->blocks; 802d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 803c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 8046aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov sdhci_set_transfer_irqs(host); 8056aa943ab8994fe6e4ccba22c5bc8150a84268bddAnton Vorontsov 806bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 8074e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE); 8084e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 809c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman} 810c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 811c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossmanstatic void sdhci_set_transfer_mode(struct sdhci_host *host, 812c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman struct mmc_data *data) 813c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman{ 814c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman u16 mode; 815c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 816c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data == NULL) 817c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman return; 818c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 819e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman WARN_ON(!host->data); 820e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 821c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 822c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang if (data->blocks > 1) { 823c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 824c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12; 825c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang else 826c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mode |= SDHCI_TRNS_MULTI; 827c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 828c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman if (data->flags & MMC_DATA_READ) 829c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_READ; 830c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 831c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman mode |= SDHCI_TRNS_DMA; 832c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 8334e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 834d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 835d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 836d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *host) 837d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 838d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_data *data; 839d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 840d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(!host->data); 841d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 842d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman data = host->data; 843d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 844d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 845c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 8462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 8472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman sdhci_adma_table_post(host, data); 8482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else { 8492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman dma_unmap_sg(mmc_dev(host->mmc), data->sg, 8502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman data->sg_len, (data->flags & MMC_DATA_READ) ? 8512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DMA_FROM_DEVICE : DMA_TO_DEVICE); 8522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 853d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 854d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 855d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 856c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * The specification states that the block count register must 857c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * be updated, but it does not specify at what point in the 858c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * data flow. That makes the register entirely useless to read 859c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * back so we have to assume that nothing made it to the card 860c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman * in the event of an error. 861d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 862c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman if (data->error) 863c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = 0; 864d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 865c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman data->bytes_xfered = data->blksz * data->blocks; 866d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 867d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (data->stop) { 868d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 869d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 870d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 871d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 87217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (data->error) { 873d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 874d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 875d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 876d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 877d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_send_command(host, data->stop); 878d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else 879d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 880d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 881d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 882d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 883d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 884d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int flags; 885fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman u32 mask; 8867cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 887d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 888d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->cmd); 889d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 890d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* Wait max 10 ms */ 8917cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout = 10; 892fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 893fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask = SDHCI_CMD_INHIBIT; 894fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 895fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask |= SDHCI_DATA_INHIBIT; 896fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 897fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 898fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman though they might use busy signaling */ 899fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman if (host->mrq->data && (cmd == host->mrq->data->stop)) 900fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 901fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman 9024e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 9037cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Controller never released " 905acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "inhibit bit(s).\n", mmc_hostname(host->mmc)); 906d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 90717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EIO; 908d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 909d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 910d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 9117cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 9127cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 9137cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 914d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 915d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mod_timer(&host->timer, jiffies + 10 * HZ); 916d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = cmd; 918d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 919d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_prepare_data(host, cmd->data); 920d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9214e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 922d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 923c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman sdhci_set_transfer_mode(host, cmd->data); 924c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman 925d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 926acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unsupported response type!\n", 927d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 92817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EINVAL; 929d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 930d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 931d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 932d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 933d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 934d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_NONE; 935d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_136) 936d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_LONG; 937d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 938d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 939d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 940d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags = SDHCI_CMD_RESP_SHORT; 941d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 942d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_CRC) 943d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_CRC; 944d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 945d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_INDEX; 946d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (cmd->data) 947d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman flags |= SDHCI_CMD_DATA; 948d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9494e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 950d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 951d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 952d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *host) 953d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 954d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int i; 955d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 956d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(host->cmd == NULL); 957d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 958d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_PRESENT) { 959d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd->flags & MMC_RSP_136) { 960d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* CRC is stripped so we need to do some shifting. */ 961d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman for (i = 0;i < 4;i++) { 9624e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[i] = sdhci_readl(host, 963d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4) << 8; 964d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (i != 3) 965d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd->resp[i] |= 9664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_readb(host, 967d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman SDHCI_RESPONSE + (3-i)*4-1); 968d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 969d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 9704e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 971d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 972d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 973d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 97417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = 0; 975d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 976e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (host->data && host->data_early) 977e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman sdhci_finish_data(host); 978e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman 979e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (!host->cmd->data) 980d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 982d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = NULL; 983d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 984d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 985d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 986d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman int div; 988d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u16 clk; 9897cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman unsigned long timeout; 990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 991d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == host->clock) 992d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 993d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 9948114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->ops->set_clock) { 9958114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov host->ops->set_clock(host, clock); 9968114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) 9978114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov return; 9988114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov } 9998114634ccb54d67a8c01e5825d95bff4e7f7b357Anton Vorontsov 10004e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 1001d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1002d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (clock == 0) 1003d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 1004d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 100585105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 100685105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 100785105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if (host->max_clk <= clock) 100885105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao div = 1; 100985105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao else { 10100397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { 101185105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if ((host->max_clk / div) <= clock) 101285105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao break; 101385105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 101485105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 101585105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } else { 101685105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 10170397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 101885105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if ((host->max_clk / div) <= clock) 101985105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao break; 102085105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao } 1021d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1022d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman div >>= 1; 1023d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 102485105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 102585105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 102685105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1027d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_INT_EN; 10284e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1029d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 103027f6cb160b71b342b7a47d28a4b6c422ea74ccd1Chris Ball /* Wait max 20 ms */ 103127f6cb160b71b342b7a47d28a4b6c422ea74ccd1Chris Ball timeout = 20; 10324e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 10337cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman & SDHCI_CLOCK_INT_STABLE)) { 10347cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman if (timeout == 0) { 1035acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Internal clock never " 1036acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "stabilised.\n", mmc_hostname(host->mmc)); 1037d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1038d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1039d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 10407cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman timeout--; 10417cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman mdelay(1); 10427cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman } 1043d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1044d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 10454e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 1046d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1047d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 1048d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->clock = clock; 1049d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1050d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1051146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossmanstatic void sdhci_set_power(struct sdhci_host *host, unsigned short power) 1052146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman{ 10538364248a829d50495a796e7561aaf9a6976f846cGiuseppe Cavallaro u8 pwr = 0; 1054146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 10558364248a829d50495a796e7561aaf9a6976f846cGiuseppe Cavallaro if (power != (unsigned short)-1) { 1056ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman switch (1 << power) { 1057ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_165_195: 1058ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_180; 1059ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1060ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_29_30: 1061ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_30_31: 1062ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_300; 1063ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1064ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_32_33: 1065ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman case MMC_VDD_33_34: 1066ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr = SDHCI_POWER_330; 1067ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman break; 1068ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman default: 1069ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman BUG(); 1070ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1071ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman } 1072ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1073ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (host->pwr == pwr) 1074146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman return; 1075146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1076ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman host->pwr = pwr; 1077ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman 1078ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman if (pwr == 0) { 10794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1080ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman return; 10819e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt } 10829e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt 10839e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt /* 10849e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * Spec says that we should clear the power reg before setting 10859e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt * a new value. Some controllers don't seem to like this though. 10869e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt */ 1087b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 10884e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1089146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1090e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon /* 1091c71f65129a1fb67bc6b9b8d03b493675b5c9302bAndres Salomon * At least the Marvell CaFe chip gets confused if we set the voltage 1092e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon * and set turn on power at the same time, so set the voltage first. 1093e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon */ 109411a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 1095ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1096e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon 1097ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman pwr |= SDHCI_POWER_ON; 1098146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1099ae628903ab6cc9a04fdf8d4ff3f0c5b2ffa6f939Pierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1100557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte 1101557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte /* 1102557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * Some controllers need an extra 10ms delay of 10ms before they 1103557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte * can apply clock after applying power 1104557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte */ 110511a2f1b78a43d0c2bd026d79b952742c7588f529Pierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 1106557b06971b1f05cbadec2f376a305ee1954e9b0dHarald Welte mdelay(10); 1107146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman} 1108146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1109d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1110d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1111d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * MMC callbacks * 1112d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1113d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1114d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1115d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 1116d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1117d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 111868d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov bool present; 1119d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1120d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1121d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1122d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1123d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1124d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1125d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman WARN_ON(host->mrq != NULL); 1126d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1127f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1128d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_activate_led(host); 11292f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1130c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) { 1131c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang if (mrq->stop) { 1132c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mrq->data->stop = NULL; 1133c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang mrq->stop = NULL; 1134c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 1135c4512f79dcb236c8dc2afae176a0dc520096f0bcJerry Huang } 1136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1137d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = mrq; 1138d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 113968d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov /* If polling, assume that the card is always present. */ 114068d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 114168d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = true; 114268d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov else 114368d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 114468d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov SDHCI_CARD_PRESENT; 114568d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 114668d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov if (!present || host->flags & SDHCI_DEVICE_DEAD) { 114717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1148d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1149d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else 1150d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_send_command(host, mrq->cmd); 1151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11525f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1153d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1154d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1155d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1156d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1157d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1158d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1159d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1160d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u8 ctrl; 1161d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1162d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1163d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1164d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1165d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 11661e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 11671e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 11681e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1169d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1170d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Reset the chip on each power off. 1171d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Should clear out any weird states. 1172d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1173d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 11744e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 11757260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_reinit(host); 1176d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1178d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_set_clock(host, ios->clock); 1179d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1180d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->power_mode == MMC_POWER_OFF) 1181146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, -1); 1182d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 1183146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman sdhci_set_power(host, ios->vdd); 1184d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1185643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity if (host->ops->platform_send_init_74_clocks) 1186643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1187643a81ff3c5a89ae5c0768f89b29d3e1d08be5c3Philip Rakity 11884e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 1189cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 1190ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park if (ios->bus_width == MMC_BUS_WIDTH_8) 1191ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park ctrl |= SDHCI_CTRL_8BITBUS; 1192ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park else 1193ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park ctrl &= ~SDHCI_CTRL_8BITBUS; 1194ae6d6c92212e94b12ab9365c23fb73acc2c3c2e7Kyungmin Park 1195d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ios->bus_width == MMC_BUS_WIDTH_4) 1196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl |= SDHCI_CTRL_4BITBUS; 1197d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 1198d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman ctrl &= ~SDHCI_CTRL_4BITBUS; 1199cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 12003ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity if ((ios->timing == MMC_TIMING_SD_HS || 12013ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity ios->timing == MMC_TIMING_MMC_HS) 12023ab9c8dad6444007700b5949ec80cfdc823d31b4Philip Rakity && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) 1203cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl |= SDHCI_CTRL_HISPD; 1204cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman else 1205cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 1206cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 12074e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 1208d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1209b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo /* 1210b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 1211b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 1212b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo * it on each ios seems to solve the problem. 1213b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo */ 1214b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 1215b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1216b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo 12171e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 12185f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1219d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1221d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int sdhci_get_ro(struct mmc_host *mmc) 1223d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1224d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1225d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 12262dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang int is_readonly; 1227d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1228d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1229d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1231d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12321e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 12332dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = 0; 12342dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang else if (host->ops->get_ro) 12352dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = host->ops->get_ro(host); 12361e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman else 12372dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 12382dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang & SDHCI_WRITE_PROTECT); 1239d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1240d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1241d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12422dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 12432dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 12442dfb579c7da171f6153cd58e8fbf7dcfe684778dWolfram Sang !is_readonly : is_readonly; 1245d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1246d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1247f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossmanstatic void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 1248f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman{ 1249f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman struct sdhci_host *host; 1250f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman unsigned long flags; 1251f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1252f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman host = mmc_priv(mmc); 1253f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1254f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1255f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 12561e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 12571e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman goto out; 12581e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 1259f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (enable) 12607260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); 12617260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov else 12627260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); 12631e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout: 1264f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmiowb(); 1265f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1266f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1267f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman} 1268f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1269ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops sdhci_ops = { 1270d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .request = sdhci_request, 1271d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .set_ios = sdhci_set_ios, 1272d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman .get_ro = sdhci_get_ro, 1273f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman .enable_sdio_irq = sdhci_enable_sdio_irq, 1274d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}; 1275d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1276d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1277d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1278d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Tasklets * 1279d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1280d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1281d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1282d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_card(unsigned long param) 1283d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1284d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1285d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1286d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1287d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1288d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1289d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1290d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 12914e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { 1292d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1293d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Card removed during transfer!\n", 1294d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1295d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_ERR "%s: Resetting controller.\n", 1296d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 1297d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1298d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1299d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1300d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 130117b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 1302d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1303d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1304d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1305d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1306d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1307d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 130804cf585d2902404ed06861c6dc27897100340dbaPierre Ossman mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 1309d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1310d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1311d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_finish(unsigned long param) 1312d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1313d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1314d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1315d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_request *mrq; 1316d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1317d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)param; 1318d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1319d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1320d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1321d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer(&host->timer); 1322d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1323d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mrq = host->mrq; 1324d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1325d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1326d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * The controller needs a reset of internal state machines 1327d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * upon error conditions. 1328d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 13291e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!(host->flags & SDHCI_DEVICE_DEAD) && 13301e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->cmd->error || 13311e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data && (mrq->data->error || 13321e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (mrq->data->stop && mrq->data->stop->error))) || 13331e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { 1334645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1335645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Some controllers need this kick or reset won't work here */ 1336b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { 1337645289dca5021224279e67b4655796cafdfdad00Pierre Ossman unsigned int clock; 1338645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1339645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* This is to force an update */ 1340645289dca5021224279e67b4655796cafdfdad00Pierre Ossman clock = host->clock; 1341645289dca5021224279e67b4655796cafdfdad00Pierre Ossman host->clock = 0; 1342645289dca5021224279e67b4655796cafdfdad00Pierre Ossman sdhci_set_clock(host, clock); 1343645289dca5021224279e67b4655796cafdfdad00Pierre Ossman } 1344645289dca5021224279e67b4655796cafdfdad00Pierre Ossman 1345645289dca5021224279e67b4655796cafdfdad00Pierre Ossman /* Spec says we should do both at the same time, but Ricoh 1346645289dca5021224279e67b4655796cafdfdad00Pierre Ossman controllers do not like that. */ 1347d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_CMD); 1348d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_reset(host, SDHCI_RESET_DATA); 1349d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1350d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1351d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mrq = NULL; 1352d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->cmd = NULL; 1353d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->data = NULL; 1354d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1355f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifndef SDHCI_USE_LEDS_CLASS 1356d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_deactivate_led(host); 13572f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 1358d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 13595f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1360d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1361d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1362d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_request_done(host->mmc, mrq); 1363d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1364d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1365d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_timeout_timer(unsigned long data) 1366d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1367d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1368d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman unsigned long flags; 1369d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1370d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = (struct sdhci_host*)data; 1371d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1372d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_irqsave(&host->lock, flags); 1373d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1374d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->mrq) { 1375acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Timeout waiting for hardware " 1376acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman "interrupt.\n", mmc_hostname(host->mmc)); 1377d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1378d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1379d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->data) { 138017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 1381d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 1382d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } else { 1383d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (host->cmd) 138417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 1385d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else 138617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->mrq->cmd->error = -ETIMEDOUT; 1387d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1388d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1389d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1390d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1391d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 13925f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1393d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1394d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1395d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1396d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1397d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1398d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Interrupt handling * 1399d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1400d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1401d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1402d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) 1403d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1404d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 1405d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1406d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->cmd) { 1407b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got command interrupt 0x%08x even " 1408b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no command operation was in progress.\n", 1409b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 1410d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1411d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1412d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1413d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 141443b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 141517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -ETIMEDOUT; 141617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | 141717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman SDHCI_INT_INDEX)) 141817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->cmd->error = -EILSEQ; 141943b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman 1420e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->error) { 1421d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->finish_tasklet); 1422e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1423e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1424e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 1425e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman /* 1426e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The host can send and interrupt when the busy state has 1427e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * ended, allowing us to wait without wasting CPU cycles. 1428e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Unfortunately this is overloaded on the "data complete" 1429e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * interrupt, so we need to take some care when handling 1430e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * it. 1431e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * 1432e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * Note: The 1.0 specification is a bit ambiguous about this 1433e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * feature so there might be some problems with older 1434e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * controllers. 1435e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman */ 1436e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->flags & MMC_RSP_BUSY) { 1437e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd->data) 1438e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman DBG("Cannot wait for busy signal when also " 1439e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman "doing a data transfer"); 1440f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 1441e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1442f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks 1443f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks /* The controller does not support the end-of-busy IRQ, 1444f945405cdecd9e0ae3e58ff84cabd19b4522965eBen Dooks * fall through and take the SDHCI_INT_RESPONSE */ 1445e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1446e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman 1447e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 144843b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman sdhci_finish_command(host); 1449d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1450d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 14510957c3339efa333b7895157eb18b9b578394f80cGeorge G. Davis#ifdef CONFIG_MMC_DEBUG 14526882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) 14536882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks{ 14546882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks const char *name = mmc_hostname(host->mmc); 14556882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 *desc = host->adma_desc; 14566882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le32 *dma; 14576882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks __le16 *len; 14586882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks u8 attr; 14596882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14606882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_dumpregs(host); 14616882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14626882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks while (true) { 14636882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks dma = (__le32 *)(desc + 4); 14646882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks len = (__le16 *)(desc + 2); 14656882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks attr = *desc; 14666882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14676882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 14686882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); 14696882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14706882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks desc += 8; 14716882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 14726882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks if (attr & 2) 14736882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks break; 14746882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 14756882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks} 14766882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#else 14776882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooksstatic void sdhci_show_adma_error(struct sdhci_host *host) { } 14786882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks#endif 14796882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks 1480d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 1481d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1482d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman BUG_ON(intmask == 0); 1483d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1484d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!host->data) { 1485d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1486e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * The "data complete" interrupt is also used to 1487e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * indicate that a busy state has ended. See comment 1488e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman * above in sdhci_cmd_irq(). 1489d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1490e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { 1491e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1492e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman sdhci_finish_command(host); 1493e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman return; 1494e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1495e809517f6fa5803a5a1cd56026f0e2190fc13d5cPierre Ossman } 1496d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1497b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman printk(KERN_ERR "%s: Got data interrupt 0x%08x even " 1498b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman "though no data operation was in progress.\n", 1499b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 1500d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1501d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1502d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return; 1503d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1504d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1505d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 150617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -ETIMEDOUT; 150717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 150817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman host->data->error = -EILSEQ; 15096882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 15106882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); 15116882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks sdhci_show_adma_error(host); 15122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->data->error = -EIO; 15136882a8c071d609f4c088bee41e79572c7cfc1790Ben Dooks } 1514d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 151517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (host->data->error) 1516d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_finish_data(host); 1517d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman else { 1518a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 1519d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_transfer_pio(host); 1520d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15216ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman /* 15226ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * We currently don't do anything fancy with DMA 15236ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * boundaries, but as we can't disable the feature 15246ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman * we need to at least restart the transfer. 15256ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman */ 15266ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman if (intmask & SDHCI_INT_DMA_END) 15274e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS), 15284e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_DMA_ADDRESS); 15296ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman 1530e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 1531e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman if (host->cmd) { 1532e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman /* 1533e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * Data managed to finish before the 1534e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * command completed. Make sure we do 1535e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman * things in the proper order. 1536e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman */ 1537e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman host->data_early = 1; 1538e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } else { 1539e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman sdhci_finish_data(host); 1540e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 1541e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman } 1542d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1543d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1544d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15457d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sdhci_irq(int irq, void *dev_id) 1546d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1547d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman irqreturn_t result; 1548d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host* host = dev_id; 1549d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman u32 intmask; 1550f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman int cardint = 0; 1551d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1552d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock(&host->lock); 1553d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15544e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 1555d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 155662df67a523acd7a22d936bf946b1889dbd60ca98Mark Lord if (!intmask || intmask == 0xffffffff) { 1557d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_NONE; 1558d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman goto out; 1559d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1560d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1561b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman DBG("*** %s got interrupt: 0x%08x\n", 1562b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(host->mmc), intmask); 1563d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15643192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 15654e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 15664e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 1567d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_schedule(&host->card_tasklet); 15683192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 1569d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15703192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 1571d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15723192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask & SDHCI_INT_CMD_MASK) { 15734e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 15744e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 15753192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); 1576d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1577d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1578d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_DATA_MASK) { 15794e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, 15804e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov SDHCI_INT_STATUS); 15813192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 1582d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1583d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1584d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); 1585d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1586964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman intmask &= ~SDHCI_INT_ERROR; 1587964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman 1588d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (intmask & SDHCI_INT_BUS_POWER) { 15893192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman printk(KERN_ERR "%s: Card is consuming too much power!\n", 1590d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_hostname(host->mmc)); 15914e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); 1592d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1593d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 15949d26a5d3f2b9c4fe4b2ba491683c6989ecd6ae04Rolf Eike Beer intmask &= ~SDHCI_INT_BUS_POWER; 15953192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman 1596f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (intmask & SDHCI_INT_CARD_INT) 1597f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman cardint = 1; 1598f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1599f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman intmask &= ~SDHCI_INT_CARD_INT; 1600f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 16013192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman if (intmask) { 1602acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 16033192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman mmc_hostname(host->mmc), intmask); 1604d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1605d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16064e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 16073192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman } 1608d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1609d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman result = IRQ_HANDLED; 1610d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16115f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 1612d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout: 1613d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_unlock(&host->lock); 1614d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1615f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman /* 1616f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman * We have to delay this as it calls back into the driver. 1617f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman */ 1618f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman if (cardint) 1619f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman mmc_signal_sdio_irq(host->mmc); 1620f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman 1621d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return result; 1622d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1623d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1624d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1625d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1626d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Suspend/resume * 1627d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1628d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1629d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1630d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_PM 1631d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1632b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) 1633d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1634b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1635a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 16367260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 16377260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 16381a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming ret = mmc_suspend_host(host->mmc); 1639b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (ret) 1640b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ret; 1641a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman 1642b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman free_irq(host->irq, host); 1643d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16449bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) 16459bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski ret = regulator_disable(host->vmmc); 16469bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 16479bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski return ret; 1648d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1649d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1650b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_suspend_host); 1651d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1652b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_resume_host(struct sdhci_host *host) 1653b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 1654b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1655d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16569bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) { 16579bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski int ret = regulator_enable(host->vmmc); 16589bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (ret) 16599bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski return ret; 16609bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 16619bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 16629bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 1663a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1664b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) 1665b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->ops->enable_dma(host); 1666b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 1667d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1668b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1669b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(host->mmc), host); 1670df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman if (ret) 1671df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman return ret; 1672d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16732f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 1674b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmiowb(); 1675b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman 1676b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = mmc_resume_host(host->mmc); 16777260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 16787260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 16792f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre return ret; 1680d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 1681d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1682b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_resume_host); 1683d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 16845f619704d18b93869d045abc49e09cdba109b04bDaniel Drakevoid sdhci_enable_irq_wakeups(struct sdhci_host *host) 16855f619704d18b93869d045abc49e09cdba109b04bDaniel Drake{ 16865f619704d18b93869d045abc49e09cdba109b04bDaniel Drake u8 val; 16875f619704d18b93869d045abc49e09cdba109b04bDaniel Drake val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 16885f619704d18b93869d045abc49e09cdba109b04bDaniel Drake val |= SDHCI_WAKE_ON_INT; 16895f619704d18b93869d045abc49e09cdba109b04bDaniel Drake sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 16905f619704d18b93869d045abc49e09cdba109b04bDaniel Drake} 16915f619704d18b93869d045abc49e09cdba109b04bDaniel Drake 16925f619704d18b93869d045abc49e09cdba109b04bDaniel DrakeEXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); 16935f619704d18b93869d045abc49e09cdba109b04bDaniel Drake 1694d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif /* CONFIG_PM */ 1695d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1696d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 1697d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1698b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman * Device allocation/registration * 1699d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 1700d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 1701d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1702b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanstruct sdhci_host *sdhci_alloc_host(struct device *dev, 1703b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman size_t priv_size) 1704d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 1705d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct mmc_host *mmc; 1706d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman struct sdhci_host *host; 1707d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1708b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(dev == NULL); 1709d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1710b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 1711d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (!mmc) 1712b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return ERR_PTR(-ENOMEM); 1713d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1714d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host = mmc_priv(mmc); 1715d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman host->mmc = mmc; 1716d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1717b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return host; 1718b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman} 17198a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman 1720b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_alloc_host); 1721d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1722b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_add_host(struct sdhci_host *host) 1723b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 1724b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman struct mmc_host *mmc; 1725b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman unsigned int caps; 1726b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman int ret; 1727d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1728b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman WARN_ON(host == NULL); 1729b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host == NULL) 1730b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -EINVAL; 1731d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1732b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc = host->mmc; 1733d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1734b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (debug_quirks) 1735b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman host->quirks = debug_quirks; 1736d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1737d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 1738d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman 17394e4141a526dd7f5ac3ce1458ae79ea6e5a515b06Anton Vorontsov host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 17402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version = (host->version & SDHCI_SPEC_VER_MASK) 17412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman >> SDHCI_SPEC_VER_SHIFT; 174285105c53b0ce70a277160379f9d89309cefc0bfdZhangfei Gao if (host->version > SDHCI_SPEC_300) { 17434a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman printk(KERN_ERR "%s: Unknown controller version (%d). " 1744b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "You may experience problems.\n", mmc_hostname(mmc), 17452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->version); 17464a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman } 17474a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman 1748ccc92c23240cdf952ef7cc39ba563910dcbc9cbeMaxim Levitsky caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : 1749ccc92c23240cdf952ef7cc39ba563910dcbc9cbeMaxim Levitsky sdhci_readl(host, SDHCI_CAPABILITIES); 1750d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1751b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 1752a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_SDMA; 1753a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors else if (!(caps & SDHCI_CAN_DO_SDMA)) 1754a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors DBG("Controller doesn't have SDMA capability\n"); 17556743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman else 1756a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_SDMA; 1757d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1758b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 1759a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_SDMA)) { 1760cee687ce4ab1197e20d4dacc09df01531362fdbdRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 1761a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags &= ~SDHCI_USE_SDMA; 17627c168e3db7d900008ee304574057e0dc1a8505afFeng Tang } 17637c168e3db7d900008ee304574057e0dc1a8505afFeng Tang 1764a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if ((host->version >= SDHCI_SPEC_200) && (caps & SDHCI_CAN_DO_ADMA2)) 1765a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags |= SDHCI_USE_ADMA; 17662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 17672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 17682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 17692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 17702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 17712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 17722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 1773a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1774b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma) { 1775b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman if (host->ops->enable_dma(host)) { 1776b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman printk(KERN_WARNING "%s: No suitable DMA " 1777b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman "available. Falling back to PIO.\n", 1778b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_hostname(mmc)); 1779a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors host->flags &= 1780a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 1781b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman } 1782d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1783d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman } 1784d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 17852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 17862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman /* 17872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * We need to allocate descriptors for all sg entries 17882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * (128) and potentially one alignment transfer for 17892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * each of those entries. 17902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman */ 17912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); 17922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); 17932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (!host->adma_desc || !host->align_buffer) { 17942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 17952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 17962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman printk(KERN_WARNING "%s: Unable to allocate ADMA " 17972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman "buffers. Falling back to standard DMA.\n", 17982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc_hostname(mmc)); 17992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 18002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 18012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman } 18022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 18037659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman /* 18047659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * If we use DMA, then it's up to the caller to set the DMA 18057659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask, but PIO does not need the hw shim so we set a new 18067659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman * mask here in that case. 18077659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman */ 1808a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 18097659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman host->dma_mask = DMA_BIT_MASK(64); 18107659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman mmc_dev(host->mmc)->dma_mask = &host->dma_mask; 18117659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman } 1812d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1813c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao if (host->version >= SDHCI_SPEC_300) 1814c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) 1815c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 1816c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao else 1817c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) 1818c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao >> SDHCI_CLOCK_BASE_SHIFT; 1819c4687d5f601be3f928b815b46964f7426c31aec7Zhangfei Gao 18204240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk *= 1000000; 1821f27f47ef5b67106ff1cdeebf061387a7b30c12bcAnton Vorontsov if (host->max_clk == 0 || host->quirks & 1822f27f47ef5b67106ff1cdeebf061387a7b30c12bcAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 18234240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks if (!host->ops->get_max_clock) { 18244240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 18254240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify base clock " 18264240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 18274240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 18284240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 18294240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks host->max_clk = host->ops->get_max_clock(host); 18308ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman } 1831d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 18321c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk = 18331c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; 18341c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (host->timeout_clk == 0) { 183581b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov if (host->ops->get_timeout_clock) { 183681b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov host->timeout_clk = host->ops->get_timeout_clock(host); 183781b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov } else if (!(host->quirks & 183881b39802468fe4bf5c6b038837319b608acfdd3eAnton Vorontsov SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 18394240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks printk(KERN_ERR 18404240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "%s: Hardware doesn't specify timeout clock " 18414240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks "frequency.\n", mmc_hostname(mmc)); 18424240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks return -ENODEV; 18434240ff0a02cb52f7d10dc1df6d82ba9c27dba07bBen Dooks } 18441c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman } 18451c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman if (caps & SDHCI_TIMEOUT_CLK_UNIT) 18461c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman host->timeout_clk *= 1000; 1847d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1848d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1849d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Set host parameters. 1850d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1851d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->ops = &sdhci_ops; 1852ce5f036bbbfc6c21d7b55b8fdaa2e2bd56392d94Marek Szyprowski if (host->ops->get_min_clock) 1853a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 18540397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao else if (host->version >= SDHCI_SPEC_300) 18550397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 1856a9e58f25734e153b8c6516d904e2398fb8b0b23dAnton Vorontsov else 18570397526d6ae2518b6c53efd1ff1e81b7d24c91daZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 1858d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc->f_max = host->max_clk; 1859c1f5977c6a136acbf525c634c8511e19d0c1f195Kyungmin Park mmc->caps |= MMC_CAP_SDIO_IRQ; 18605fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov 18615fe23c7f51def59f66bc6aeee988ef1a467a2c8cAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 1862b08caed8659ab27199db51c63a35c5ee067fc7efGiuseppe Cavallaro mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; 1863d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 186486a6a8749d5b8fd5c2b544fe9fd11101e3d0550fPierre Ossman if (caps & SDHCI_CAN_DO_HISPD) 1865a29e7e18bddde778deb2cb101dbceca56b15e05eZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 1866cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 1867176d1ed426a2a73a87c62a8aa05f6d002353cd50Jaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 1868176d1ed426a2a73a87c62a8aa05f6d002353cd50Jaehoon Chung mmc_card_is_removable(mmc)) 186968d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 187068d1fb7e229c6f95be4fbbe3eb46b24e41184924Anton Vorontsov 1871146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail = 0; 1872146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman if (caps & SDHCI_CAN_VDD_330) 1873146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; 1874c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman if (caps & SDHCI_CAN_VDD_300) 1875146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; 1876c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman if (caps & SDHCI_CAN_VDD_180) 187755556da01284af8c2174b786b3eca8e11301b656Philip Langdale mmc->ocr_avail |= MMC_VDD_165_195; 1878146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1879146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman if (mmc->ocr_avail == 0) { 1880146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman printk(KERN_ERR "%s: Hardware doesn't report any " 1881b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman "support voltages.\n", mmc_hostname(mmc)); 1882b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return -ENODEV; 1883146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman } 1884146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman 1885d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman spin_lock_init(&host->lock); 1886d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1887d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 18882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * Maximum number of segments. Depends on if the hardware 18892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * can do scatter/gather or not. 1890d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 18912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 1892a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 128; 1893a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors else if (host->flags & SDHCI_USE_SDMA) 1894a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 1; 18952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else /* PIO */ 1896a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = 128; 1897d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1898d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1899bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman * Maximum number of sectors in one transfer. Limited by DMA boundary 190055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * size (512KiB). 1901d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 190255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_req_size = 524288; 1903d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1905d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Maximum segment size. Could be one segment with the maximum number 19062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 19072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman * be larger than 64 KiB though. 1908d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 19092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman if (host->flags & SDHCI_USE_ADMA) 19102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_seg_size = 65536; 19112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman else 19122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman mmc->max_seg_size = mmc->max_req_size; 1913d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1914d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman /* 1915fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * Maximum block size. This varies from controller to controller and 1916fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * is specified in the capabilities register. 1917fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman */ 19180633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 19190633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 2; 19200633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } else { 19210633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> 19220633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 19230633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov if (mmc->max_blk_size >= 3) { 19240633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov printk(KERN_WARNING "%s: Invalid maximum block size, " 19250633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov "assuming 512 bytes\n", mmc_hostname(mmc)); 19260633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 0; 19270633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 19280633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov } 19290633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov 19300633f654241483edc8a235ab87264ff6bbcd08d5Anton Vorontsov mmc->max_blk_size = 512 << mmc->max_blk_size; 1931fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 1932fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman /* 193355db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * Maximum block count. 193455db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman */ 19351388eefd5a5e6aaa3cb04070bfc2b944c1d24b82Ben Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 193655db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 193755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman /* 1938d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Init tasklets. 1939d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman */ 1940d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->card_tasklet, 1941d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_card, (unsigned long)host); 1942d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_init(&host->finish_tasklet, 1943d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_tasklet_finish, (unsigned long)host); 1944d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1945e4cad1b5a4851c90c1bcf460062074a2fa10815bAl Viro setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); 1946d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1947dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 1948b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman mmc_hostname(mmc), host); 1949d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman if (ret) 19508ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman goto untasklet; 1951d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19529bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); 19539bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (IS_ERR(host->vmmc)) { 19549bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc)); 19559bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski host->vmmc = NULL; 19569bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } else { 19579bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_enable(host->vmmc); 19589bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 19599bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 19602f4cbb3d834922ffa0309b6a08fa42dac87ef9d2Nicolas Pitre sdhci_init(host, 0); 1961d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1962d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_MMC_DEBUG 1963d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman sdhci_dumpregs(host); 1964d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif 1965d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1966f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 19675dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa snprintf(host->led_name, sizeof(host->led_name), 19685dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa "%s::", mmc_hostname(mmc)); 19695dbace0c9ba110c1a3810a89fa6bf12b7574b5a3Helmut Schaa host->led.name = host->led_name; 19702f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness = LED_OFF; 19712f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.default_trigger = mmc_hostname(mmc); 19722f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman host->led.brightness_set = sdhci_led_control; 19732f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 1974b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman ret = led_classdev_register(mmc_dev(mmc), &host->led); 19752f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman if (ret) 19762f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman goto reset; 19772f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 19782f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 19795f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman mmiowb(); 19805f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman 1981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman mmc_add_host(mmc); 1982d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1983a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n", 1984d1b268630875a7713b5d468a0c03403c5b721c8eKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 1985a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_ADMA) ? "ADMA" : 1986a13abc7b0814da7733c531453a207729b542ecf8Richard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 1987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 19887260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_enable_card_detection(host); 19897260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 1990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return 0; 1991d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 1992f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 19932f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanreset: 19942f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 19952f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman free_irq(host->irq, host); 19962f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 19978ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossmanuntasklet: 1998d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 1999d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 2000d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2001d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman return ret; 2002d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2003d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2004b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_add_host); 2005d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 20061e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanvoid sdhci_remove_host(struct sdhci_host *host, int dead) 2007b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{ 20081e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman unsigned long flags; 20091e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20101e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (dead) { 20111e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_lock_irqsave(&host->lock, flags); 20121e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20131e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 20141e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20151e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (host->mrq) { 20161e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman printk(KERN_ERR "%s: Controller removed during " 20171e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman " transfer!\n", mmc_hostname(host->mmc)); 20181e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20191e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman host->mrq->cmd->error = -ENOMEDIUM; 20201e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman tasklet_schedule(&host->finish_tasklet); 20211e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 20221e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20231e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman spin_unlock_irqrestore(&host->lock, flags); 20241e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman } 20251e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman 20267260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov sdhci_disable_card_detection(host); 20277260cf5e12393536ce61d184c3fc750fb2ba635aAnton Vorontsov 2028b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_remove_host(host->mmc); 2029d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2030f9134319c81c6c56e0ddf38e7adac2492b243d9bPierre Ossman#ifdef SDHCI_USE_LEDS_CLASS 20312f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman led_classdev_unregister(&host->led); 20322f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif 20332f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman 20341e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman if (!dead) 20351e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman sdhci_reset(host, SDHCI_RESET_ALL); 2036d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2037d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman free_irq(host->irq, host); 2038d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2039d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman del_timer_sync(&host->timer); 2040d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2041d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->card_tasklet); 2042d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman tasklet_kill(&host->finish_tasklet); 20432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 20449bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski if (host->vmmc) { 20459bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_disable(host->vmmc); 20469bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski regulator_put(host->vmmc); 20479bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski } 20489bea3c850dbff2296892298614388bdc71ad2170Marek Szyprowski 20492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->adma_desc); 20502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman kfree(host->align_buffer); 20512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman 20522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->adma_desc = NULL; 20532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman host->align_buffer = NULL; 2054d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2055d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2056b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_remove_host); 2057d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2058b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanvoid sdhci_free_host(struct sdhci_host *host) 2059d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2060b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman mmc_free_host(host->mmc); 2061d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2062d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2063b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_free_host); 2064d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2065d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\ 2066d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2067d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Driver init/exit * 2068d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * * 2069d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/ 2070d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2071d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int __init sdhci_drv_init(void) 2072d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2073d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME 207452fbf9c976b36654e08e94c3107ddbaac7e2da33Pierre Ossman ": Secure Digital Host Controller Interface driver\n"); 2075d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 2076d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2077b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman return 0; 2078d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2079d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2080d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void __exit sdhci_drv_exit(void) 2081d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{ 2082d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman} 2083d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2084d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_init(sdhci_drv_init); 2085d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_exit(sdhci_drv_exit); 2086d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman 2087df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanmodule_param(debug_quirks, uint, 0444); 20886743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 208932710e8fd537adeb53f98dec92e4a77caac512f5Pierre OssmanMODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 2090b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanMODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 2091d129bceb1d44ed3c23b99164849193703372bab4Pierre OssmanMODULE_LICENSE("GPL"); 20926743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman 2093df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre OssmanMODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 2094