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