sdhci.c revision 980167b7fb20fb181766218b4771fc7420a7bbb4
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
33df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanstatic unsigned int debug_quirks = 0;
346743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman
35d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
36d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *);
37d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
38d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
39d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *);
40d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
41d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_dumpregs(struct sdhci_host *host)
42d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
43d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
44d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
45d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
46d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_DMA_ADDRESS),
47d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_HOST_VERSION));
48d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
49d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_BLOCK_SIZE),
50d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_BLOCK_COUNT));
51d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
52d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_ARGUMENT),
53d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_TRANSFER_MODE));
54d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
55d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_PRESENT_STATE),
56d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readb(host->ioaddr + SDHCI_HOST_CONTROL));
57d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
58d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readb(host->ioaddr + SDHCI_POWER_CONTROL),
59d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
60d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
612df3b71b2746469b5b344cf7da5facecd4110cc9Nicolas Pitre		readb(host->ioaddr + SDHCI_WAKE_UP_CONTROL),
62d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
63d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
64d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
65d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_INT_STATUS));
66d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
67d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_INT_ENABLE),
68d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
69d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
70d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_ACMD12_ERR),
71d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
72d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
73d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_CAPABILITIES),
74d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		readl(host->ioaddr + SDHCI_MAX_CURRENT));
75d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
76d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
77d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
78d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
79d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
80d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
81d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Low level functions                                                       *
82d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
83d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
84d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
85d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_reset(struct sdhci_host *host, u8 mask)
86d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
87e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	unsigned long timeout;
88e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman
89b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
908a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman		if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
918a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman			SDHCI_CARD_PRESENT))
928a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman			return;
938a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman	}
948a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman
95d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
96d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
97e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	if (mask & SDHCI_RESET_ALL)
98d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		host->clock = 0;
99d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
100e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	/* Wait max 100 ms */
101e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	timeout = 100;
102e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman
103e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	/* hw clears the bit when it's done */
104e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman	while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
105e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman		if (timeout == 0) {
106acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman			printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
107e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman				mmc_hostname(host->mmc), (int)mask);
108e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman			sdhci_dumpregs(host);
109e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman			return;
110e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman		}
111e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman		timeout--;
112e16514d8d86ecbde18a2a7495cf028861b34c157Pierre Ossman		mdelay(1);
113d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
114d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
115d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
116d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_init(struct sdhci_host *host)
117d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
118d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u32 intmask;
119d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
120d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_reset(host, SDHCI_RESET_ALL);
121d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1223192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
1233192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
1243192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
1253192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
126a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
1272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
1282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		SDHCI_INT_ADMA_ERROR;
129d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
130d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
131d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
132d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
133d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
134d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_activate_led(struct sdhci_host *host)
135d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u8 ctrl;
137d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
138d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
139d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	ctrl |= SDHCI_CTRL_LED;
140d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
141d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
142d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
143d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_deactivate_led(struct sdhci_host *host)
144d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
145d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u8 ctrl;
146d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
147d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
148d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	ctrl &= ~SDHCI_CTRL_LED;
149d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
150d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1522f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifdef CONFIG_LEDS_CLASS
1532f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanstatic void sdhci_led_control(struct led_classdev *led,
1542f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	enum led_brightness brightness)
1552f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman{
1562f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	struct sdhci_host *host = container_of(led, struct sdhci_host, led);
1572f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	unsigned long flags;
1582f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
1592f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1602f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
1612f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	if (brightness == LED_OFF)
1622f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman		sdhci_deactivate_led(host);
1632f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	else
1642f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman		sdhci_activate_led(host);
1652f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
1662f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1672f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman}
1682f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
1692f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
170d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
171d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
172d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Core functions                                                            *
173d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
174d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
175d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
176a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_read_block_pio(struct sdhci_host *host)
177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1787659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	unsigned long flags;
1797659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	size_t blksize, len, chunk;
1807659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	u32 scratch;
1817659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	u8 *buf;
182d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
183a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	DBG("PIO reading\n");
184d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
185a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	blksize = host->data->blksz;
1867659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	chunk = 0;
187d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1887659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	local_irq_save(flags);
189d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
190a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	while (blksize) {
1917659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		if (!sg_miter_next(&host->sg_miter))
1927659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			BUG();
193d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1947659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		len = min(host->sg_miter.length, blksize);
195d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1967659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		blksize -= len;
1977659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		host->sg_miter.consumed = len;
19814d836e7499c53a1f6a65086c3d11600e871a971Alex Dubov
1997659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		buf = host->sg_miter.addr;
200d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
2017659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		while (len) {
2027659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			if (chunk == 0) {
2037659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman				scratch = readl(host->ioaddr + SDHCI_BUFFER);
2047659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman				chunk = 4;
205a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman			}
2067659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2077659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			*buf = scratch & 0xFF;
2087659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2097659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			buf++;
2107659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			scratch >>= 8;
2117659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			chunk--;
2127659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			len--;
213d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
214a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	}
2157659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2167659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	sg_miter_stop(&host->sg_miter);
2177659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2187659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	local_irq_restore(flags);
219a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman}
220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
221a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_write_block_pio(struct sdhci_host *host)
222a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{
2237659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	unsigned long flags;
2247659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	size_t blksize, len, chunk;
2257659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	u32 scratch;
2267659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	u8 *buf;
227d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
228a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	DBG("PIO writing\n");
229a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
230a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	blksize = host->data->blksz;
2317659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	chunk = 0;
2327659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	scratch = 0;
233d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
2347659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	local_irq_save(flags);
235d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
236a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	while (blksize) {
2377659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		if (!sg_miter_next(&host->sg_miter))
2387659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			BUG();
239a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
2407659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		len = min(host->sg_miter.length, blksize);
2417659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2427659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		blksize -= len;
2437659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		host->sg_miter.consumed = len;
2447659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2457659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		buf = host->sg_miter.addr;
246d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
2477659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		while (len) {
2487659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			scratch |= (u32)*buf << (chunk * 8);
2497659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2507659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			buf++;
2517659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			chunk++;
2527659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			len--;
2537659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2547659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
2557659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman				writel(scratch, host->ioaddr + SDHCI_BUFFER);
2567659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman				chunk = 0;
2577659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman				scratch = 0;
258d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			}
259d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
260d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
2617659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2627659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	sg_miter_stop(&host->sg_miter);
2637659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman
2647659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	local_irq_restore(flags);
265a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman}
266a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
267a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossmanstatic void sdhci_transfer_pio(struct sdhci_host *host)
268a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman{
269a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	u32 mask;
270a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
271a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	BUG_ON(!host->data);
272a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
2737659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	if (host->blocks == 0)
274a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		return;
275a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
276a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	if (host->data->flags & MMC_DATA_READ)
277a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		mask = SDHCI_DATA_AVAILABLE;
278a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	else
279a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		mask = SDHCI_SPACE_AVAILABLE;
280a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman
2814a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	/*
2824a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	 * Some controllers (JMicron JMB38x) mess up the buffer bits
2834a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	 * for transfers < 4 bytes. As long as it is just one block,
2844a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	 * we can ignore the bits.
2854a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	 */
2864a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman	if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) &&
2874a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman		(host->data->blocks == 1))
2884a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman		mask = ~0;
2894a3cba32cb514168bb2516c045b178e6660421d1Pierre Ossman
290a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
291a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		if (host->data->flags & MMC_DATA_READ)
292a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman			sdhci_read_block_pio(host);
293a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		else
294a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman			sdhci_write_block_pio(host);
295d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
2967659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		host->blocks--;
2977659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		if (host->blocks == 0)
298a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman			break;
299a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	}
300d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
301a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman	DBG("PIO transfer complete.\n");
302d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
303d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
3042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
3052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{
3062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	local_irq_save(*flags);
3072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
3082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman}
3092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
3112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{
3122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
3132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	local_irq_restore(*flags);
3142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman}
3152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3168f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanstatic int sdhci_adma_table_pre(struct sdhci_host *host,
3172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	struct mmc_data *data)
3182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{
3192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	int direction;
3202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	u8 *desc;
3222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	u8 *align;
3232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	dma_addr_t addr;
3242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	dma_addr_t align_addr;
3252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	int len, offset;
3262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	struct scatterlist *sg;
3282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	int i;
3292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	char *buffer;
3302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	unsigned long flags;
3312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
3332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * The spec does not specify endianness of descriptor table.
3342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * We currently guess that it is LE.
3352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
3362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (data->flags & MMC_DATA_READ)
3382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		direction = DMA_FROM_DEVICE;
3392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else
3402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		direction = DMA_TO_DEVICE;
3412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
3432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * The ADMA descriptor table is mapped further down as we
3442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * need to fill it with data first.
3452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
3462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->align_addr = dma_map_single(mmc_dev(host->mmc),
3482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->align_buffer, 128 * 4, direction);
3498d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
3508f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		goto fail;
3512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	BUG_ON(host->align_addr & 0x3);
3522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->sg_count = dma_map_sg(mmc_dev(host->mmc),
3542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		data->sg, data->sg_len, direction);
3558f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	if (host->sg_count == 0)
3568f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		goto unmap_align;
3572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc = host->adma_desc;
3592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	align = host->align_buffer;
3602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	align_addr = host->align_addr;
3622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	for_each_sg(data->sg, sg, host->sg_count, i) {
3642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		addr = sg_dma_address(sg);
3652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		len = sg_dma_len(sg);
3662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		/*
3682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * The SDHCI specification states that ADMA
3692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * addresses must be 32-bit aligned. If they
3702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * aren't, then we use a bounce buffer for
3712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * the (up to three) bytes that screw up the
3722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * alignment.
3732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 */
3742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		offset = (4 - (addr & 0x3)) & 0x3;
3752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (offset) {
3762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (data->flags & MMC_DATA_WRITE) {
3772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				buffer = sdhci_kmap_atomic(sg, &flags);
3786cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman				WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
3792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				memcpy(align, buffer, offset);
3802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				sdhci_kunmap_atomic(buffer, &flags);
3812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			}
3822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[7] = (align_addr >> 24) & 0xff;
3842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[6] = (align_addr >> 16) & 0xff;
3852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[5] = (align_addr >> 8) & 0xff;
3862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[4] = (align_addr >> 0) & 0xff;
3872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			BUG_ON(offset > 65536);
3892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[3] = (offset >> 8) & 0xff;
3912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[2] = (offset >> 0) & 0xff;
3922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[1] = 0x00;
3942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc[0] = 0x21; /* tran, valid */
3952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			align += 4;
3972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			align_addr += 4;
3982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
3992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			desc += 8;
4002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			addr += offset;
4022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			len -= offset;
4032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
4042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[7] = (addr >> 24) & 0xff;
4062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[6] = (addr >> 16) & 0xff;
4072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[5] = (addr >> 8) & 0xff;
4082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[4] = (addr >> 0) & 0xff;
4092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		BUG_ON(len > 65536);
4112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[3] = (len >> 8) & 0xff;
4132134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[2] = (len >> 0) & 0xff;
4142134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4152134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[1] = 0x00;
4162134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc[0] = 0x21; /* tran, valid */
4172134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		desc += 8;
4192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		/*
4212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * If this triggers then we have a calculation bug
4222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * somewhere. :/
4232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 */
4242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
4252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
4262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
4282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * Add a terminating entry.
4292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
4302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[7] = 0;
4312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[6] = 0;
4322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[5] = 0;
4332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[4] = 0;
4342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[3] = 0;
4362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[2] = 0;
4372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[1] = 0x00;
4392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	desc[0] = 0x03; /* nop, end, valid */
4402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
4422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * Resync align buffer as we might have changed it.
4432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
4442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (data->flags & MMC_DATA_WRITE) {
4452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		dma_sync_single_for_device(mmc_dev(host->mmc),
4462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			host->align_addr, 128 * 4, direction);
4472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
4482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
4502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
451980167b7fb20fb181766218b4771fc7420a7bbb4Pierre Ossman	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
4528f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		goto unmap_entries;
4532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	BUG_ON(host->adma_addr & 0x3);
4548f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman
4558f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	return 0;
4568f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman
4578f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_entries:
4588f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
4598f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		data->sg_len, direction);
4608f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanunmap_align:
4618f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
4628f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		128 * 4, direction);
4638f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossmanfail:
4648f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	return -EINVAL;
4652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman}
4662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossmanstatic void sdhci_adma_table_post(struct sdhci_host *host,
4682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	struct mmc_data *data)
4692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman{
4702134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	int direction;
4712134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4722134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	struct scatterlist *sg;
4732134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	int i, size;
4742134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	u8 *align;
4752134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	char *buffer;
4762134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	unsigned long flags;
4772134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4782134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (data->flags & MMC_DATA_READ)
4792134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		direction = DMA_FROM_DEVICE;
4802134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else
4812134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		direction = DMA_TO_DEVICE;
4822134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4832134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
4842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		(128 * 2 + 1) * 4, DMA_TO_DEVICE);
4852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
4872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		128 * 4, direction);
4882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (data->flags & MMC_DATA_READ) {
4902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
4912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			data->sg_len, direction);
4922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		align = host->align_buffer;
4942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		for_each_sg(data->sg, sg, host->sg_count, i) {
4962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (sg_dma_address(sg) & 0x3) {
4972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				size = 4 - (sg_dma_address(sg) & 0x3);
4982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
4992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				buffer = sdhci_kmap_atomic(sg, &flags);
5006cefd05f35177ad5d22d44519c680cf43f2ac86dPierre Ossman				WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
5012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				memcpy(buffer, align, size);
5022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				sdhci_kunmap_atomic(buffer, &flags);
5032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
5042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				align += 4;
5052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			}
5062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
5072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
5082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
5092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
5102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		data->sg_len, direction);
5112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman}
5122134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
513ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
514d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
5151c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	u8 count;
5161c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	unsigned target_timeout, current_timeout;
517d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
518ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	/*
519ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	 * If the host controller provides us with an incorrect timeout
520ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	 * value, just skip the check and use 0xE.  The hardware may take
521ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	 * longer to time out, but that's much better than having a too-short
522ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	 * timeout value.
523ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	 */
524ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL))
525ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman		return 0xE;
526e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman
5271c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	/* timeout in us */
5281c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	target_timeout = data->timeout_ns / 1000 +
5291c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		data->timeout_clks / host->clock;
530d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
5311c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	/*
5321c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * Figure out needed cycles.
5331c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * We do this in steps in order to fit inside a 32 bit int.
5341c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * The first step is the minimum timeout, which will have a
5351c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * minimum resolution of 6 bits:
5361c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * (1) 2^13*1000 > 2^22,
5371c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 * (2) host->timeout_clk < 2^16
5381c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 *     =>
5391c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 *     (1) / (2) > 2^6
5401c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	 */
5411c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	count = 0;
5421c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	current_timeout = (1 << 13) * 1000 / host->timeout_clk;
5431c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	while (current_timeout < target_timeout) {
5441c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		count++;
5451c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		current_timeout <<= 1;
5461c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		if (count >= 0xF)
5471c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman			break;
5481c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	}
5491c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman
5501c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	if (count >= 0xF) {
5511c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		printk(KERN_WARNING "%s: Too large timeout requested!\n",
5521c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman			mmc_hostname(host->mmc));
5531c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		count = 0xE;
5541c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	}
5551c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman
556ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	return count;
557ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman}
558ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
559ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossmanstatic void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
560ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman{
561ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	u8 count;
5622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	u8 ctrl;
5638f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	int ret;
564ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
565ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	WARN_ON(host->data);
566ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
567ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	if (data == NULL)
568ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman		return;
569ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
570ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	/* Sanity checks */
571ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	BUG_ON(data->blksz * data->blocks > 524288);
572ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	BUG_ON(data->blksz > host->mmc->max_blk_size);
573ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	BUG_ON(data->blocks > 65535);
574ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
575ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	host->data = data;
576ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	host->data_early = 0;
577ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman
578ee53ab5d73998e502801c024a08de2c39a92c52aPierre Ossman	count = sdhci_calc_timeout(host, data);
5791c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
580d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
581c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	if (host->flags & SDHCI_USE_DMA)
582c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman		host->flags |= SDHCI_REQ_USE_DMA;
583c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman
5842134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
5852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * FIXME: This doesn't account for merging when mapping the
5862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * scatterlist.
5872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
5882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_REQ_USE_DMA) {
5892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		int broken, i;
5902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		struct scatterlist *sg;
5912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
5922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		broken = 0;
5932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (host->flags & SDHCI_USE_ADMA) {
5942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
5952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				broken = 1;
5962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		} else {
5972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
5982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				broken = 1;
5992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
6002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
6012134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (unlikely(broken)) {
6022134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			for_each_sg(data->sg, sg, data->sg_len, i) {
6032134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				if (sg->length & 0x3) {
6042134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					DBG("Reverting to PIO because of "
6052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman						"transfer size (%d)\n",
6062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman						sg->length);
6072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					host->flags &= ~SDHCI_REQ_USE_DMA;
6082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					break;
6092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				}
6102134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			}
6112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
612c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	}
613c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman
614c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	/*
615c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	 * The assumption here being that alignment is the same after
616c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	 * translation to device address space.
617c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	 */
6182134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_REQ_USE_DMA) {
6192134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		int broken, i;
6202134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		struct scatterlist *sg;
6212134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
6222134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		broken = 0;
6232134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (host->flags & SDHCI_USE_ADMA) {
6242134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			/*
6252134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			 * As we use 3 byte chunks to work around
6262134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			 * alignment problems, we need to check this
6272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			 * quirk.
6282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			 */
6292134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
6302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				broken = 1;
6312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		} else {
6322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
6332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				broken = 1;
6342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
6352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
6362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (unlikely(broken)) {
6372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			for_each_sg(data->sg, sg, data->sg_len, i) {
6382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				if (sg->offset & 0x3) {
6392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					DBG("Reverting to PIO because of "
6402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman						"bad alignment\n");
6412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					host->flags &= ~SDHCI_REQ_USE_DMA;
6422134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					break;
6432134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				}
6442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			}
6452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
6462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
6472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
6488f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	if (host->flags & SDHCI_REQ_USE_DMA) {
6498f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		if (host->flags & SDHCI_USE_ADMA) {
6508f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			ret = sdhci_adma_table_pre(host, data);
6518f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			if (ret) {
6528f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				/*
6538f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 * This only happens when someone fed
6548f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 * us an invalid request.
6558f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 */
6568f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				WARN_ON(1);
657ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman				host->flags &= ~SDHCI_REQ_USE_DMA;
6588f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			} else {
6598f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				writel(host->adma_addr,
6608f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman					host->ioaddr + SDHCI_ADMA_ADDRESS);
6618f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			}
6628f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		} else {
663c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler			int sg_cnt;
6648f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman
665c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler			sg_cnt = dma_map_sg(mmc_dev(host->mmc),
6668f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman					data->sg, data->sg_len,
6678f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman					(data->flags & MMC_DATA_READ) ?
6688f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman						DMA_FROM_DEVICE :
6698f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman						DMA_TO_DEVICE);
670c8b3e02eb250ceb661437e9b198757eff0eb6fd2Tomas Winkler			if (sg_cnt == 0) {
6718f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				/*
6728f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 * This only happens when someone fed
6738f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 * us an invalid request.
6748f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				 */
6758f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				WARN_ON(1);
676ebd6d357848edb8709dd9bed4b93834d1b4d7044Pierre Ossman				host->flags &= ~SDHCI_REQ_USE_DMA;
6778f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			} else {
678719a61b452ff74cf81a96e4212748d9d63bcc924Pierre Ossman				WARN_ON(sg_cnt != 1);
6798f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman				writel(sg_dma_address(data->sg),
6808f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman					host->ioaddr + SDHCI_DMA_ADDRESS);
6818f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman			}
6828f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman		}
6838f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	}
6848f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman
6852134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	/*
6862134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * Always adjust the DMA selection as some controllers
6872134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * (e.g. JMicron) can't do PIO properly when the selection
6882134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * is ADMA.
6892134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 */
6902134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->version >= SDHCI_SPEC_200) {
6912134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
6922134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		ctrl &= ~SDHCI_CTRL_DMA_MASK;
6932134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if ((host->flags & SDHCI_REQ_USE_DMA) &&
6942134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			(host->flags & SDHCI_USE_ADMA))
6952134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			ctrl |= SDHCI_CTRL_ADMA32;
6962134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		else
6972134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			ctrl |= SDHCI_CTRL_SDMA;
6982134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
699c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	}
700c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman
7018f1934ce784bd8f2eaf06f190526500f7f3f9c74Pierre Ossman	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
7027659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		sg_miter_start(&host->sg_miter,
7037659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman			data->sg, data->sg_len, SG_MITER_ATOMIC);
7047659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		host->blocks = data->blocks;
705d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
706c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
707bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman	/* We do not handle DMA boundaries, so set it to max (512 KiB) */
708bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman	writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
709bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman		host->ioaddr + SDHCI_BLOCK_SIZE);
710c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
711c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman}
712c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
713c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossmanstatic void sdhci_set_transfer_mode(struct sdhci_host *host,
714c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	struct mmc_data *data)
715c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman{
716c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	u16 mode;
717c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
718c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	if (data == NULL)
719c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman		return;
720c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
721e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman	WARN_ON(!host->data);
722e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman
723c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	mode = SDHCI_TRNS_BLK_CNT_EN;
724c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	if (data->blocks > 1)
725c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman		mode |= SDHCI_TRNS_MULTI;
726c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	if (data->flags & MMC_DATA_READ)
727c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman		mode |= SDHCI_TRNS_READ;
728c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	if (host->flags & SDHCI_REQ_USE_DMA)
729c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman		mode |= SDHCI_TRNS_DMA;
730c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
731c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
732d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
733d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
734d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_data(struct sdhci_host *host)
735d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
736d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct mmc_data *data;
737d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
738d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	BUG_ON(!host->data);
739d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
740d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	data = host->data;
741d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->data = NULL;
742d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
743c9fddbc4f844f5a16b5957c61fe2cfcb5c12f990Pierre Ossman	if (host->flags & SDHCI_REQ_USE_DMA) {
7442134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (host->flags & SDHCI_USE_ADMA)
7452134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			sdhci_adma_table_post(host, data);
7462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		else {
7472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
7482134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				data->sg_len, (data->flags & MMC_DATA_READ) ?
7492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman					DMA_FROM_DEVICE : DMA_TO_DEVICE);
7502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
751d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
752d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
753d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
754c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	 * The specification states that the block count register must
755c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	 * be updated, but it does not specify at what point in the
756c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	 * data flow. That makes the register entirely useless to read
757c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	 * back so we have to assume that nothing made it to the card
758c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	 * in the event of an error.
759d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
760c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	if (data->error)
761c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman		data->bytes_xfered = 0;
762d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else
763c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman		data->bytes_xfered = data->blksz * data->blocks;
764d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
765d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (data->stop) {
766d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		/*
767d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 * The controller needs a reset of internal state machines
768d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 * upon error conditions.
769d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 */
77017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		if (data->error) {
771d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_reset(host, SDHCI_RESET_CMD);
772d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_reset(host, SDHCI_RESET_DATA);
773d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
774d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
775d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_send_command(host, data->stop);
776d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	} else
777d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->finish_tasklet);
778d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
779d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
780d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
781d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
782d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	int flags;
783fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	u32 mask;
7847cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	unsigned long timeout;
785d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
786d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	WARN_ON(host->cmd);
787d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
788d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/* Wait max 10 ms */
7897cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	timeout = 10;
790fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman
791fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	mask = SDHCI_CMD_INHIBIT;
792fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
793fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman		mask |= SDHCI_DATA_INHIBIT;
794fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman
795fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	/* We shouldn't wait for data inihibit for stop commands, even
796fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	   though they might use busy signaling */
797fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	if (host->mrq->data && (cmd == host->mrq->data->stop))
798fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman		mask &= ~SDHCI_DATA_INHIBIT;
799fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman
800fd2208d7c72ef5995b730f1e23b082261499e334Pierre Ossman	while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
8017cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		if (timeout == 0) {
802d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			printk(KERN_ERR "%s: Controller never released "
803acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman				"inhibit bit(s).\n", mmc_hostname(host->mmc));
804d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_dumpregs(host);
80517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			cmd->error = -EIO;
806d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			tasklet_schedule(&host->finish_tasklet);
807d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			return;
808d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
8097cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		timeout--;
8107cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		mdelay(1);
8117cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	}
812d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
813d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mod_timer(&host->timer, jiffies + 10 * HZ);
814d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
815d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->cmd = cmd;
816d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
817d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_prepare_data(host, cmd->data);
818d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
819d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
820d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
821c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman	sdhci_set_transfer_mode(host, cmd->data);
822c7fa9963ee6317b54e85b260791d603ea2feb8e3Pierre Ossman
823d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
824acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman		printk(KERN_ERR "%s: Unsupported response type!\n",
825d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			mmc_hostname(host->mmc));
82617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		cmd->error = -EINVAL;
827d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->finish_tasklet);
828d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		return;
829d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
830d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
831d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (!(cmd->flags & MMC_RSP_PRESENT))
832d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags = SDHCI_CMD_RESP_NONE;
833d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else if (cmd->flags & MMC_RSP_136)
834d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags = SDHCI_CMD_RESP_LONG;
835d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else if (cmd->flags & MMC_RSP_BUSY)
836d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags = SDHCI_CMD_RESP_SHORT_BUSY;
837d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else
838d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags = SDHCI_CMD_RESP_SHORT;
839d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
840d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (cmd->flags & MMC_RSP_CRC)
841d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags |= SDHCI_CMD_CRC;
842d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (cmd->flags & MMC_RSP_OPCODE)
843d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags |= SDHCI_CMD_INDEX;
844d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (cmd->data)
845d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		flags |= SDHCI_CMD_DATA;
846d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
847fb61e2895170920564410baadf71c5b3561dbf42Pierre Ossman	writew(SDHCI_MAKE_CMD(cmd->opcode, flags),
848d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		host->ioaddr + SDHCI_COMMAND);
849d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
850d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
851d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_finish_command(struct sdhci_host *host)
852d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
853d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	int i;
854d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
855d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	BUG_ON(host->cmd == NULL);
856d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
857d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (host->cmd->flags & MMC_RSP_PRESENT) {
858d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		if (host->cmd->flags & MMC_RSP_136) {
859d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			/* CRC is stripped so we need to do some shifting. */
860d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			for (i = 0;i < 4;i++) {
861d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman				host->cmd->resp[i] = readl(host->ioaddr +
862d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman					SDHCI_RESPONSE + (3-i)*4) << 8;
863d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman				if (i != 3)
864d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman					host->cmd->resp[i] |=
865d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman						readb(host->ioaddr +
866d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman						SDHCI_RESPONSE + (3-i)*4-1);
867d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			}
868d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		} else {
869d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
870d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
871d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
872d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
87317b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	host->cmd->error = 0;
874d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
875e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman	if (host->data && host->data_early)
876e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman		sdhci_finish_data(host);
877e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman
878e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman	if (!host->cmd->data)
879d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->finish_tasklet);
880d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
881d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->cmd = NULL;
882d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
883d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
884d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
885d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
886d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	int div;
887d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u16 clk;
8887cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	unsigned long timeout;
889d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
890d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (clock == host->clock)
891d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		return;
892d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
893d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
894d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
895d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (clock == 0)
896d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		goto out;
897d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
898d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	for (div = 1;div < 256;div *= 2) {
899d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		if ((host->max_clk / div) <= clock)
900d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			break;
901d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
902d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	div >>= 1;
903d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
904d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	clk = div << SDHCI_DIVIDER_SHIFT;
905d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	clk |= SDHCI_CLOCK_INT_EN;
906d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
907d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
908d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/* Wait max 10 ms */
9097cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	timeout = 10;
9107cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
9117cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		& SDHCI_CLOCK_INT_STABLE)) {
9127cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		if (timeout == 0) {
913acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman			printk(KERN_ERR "%s: Internal clock never "
914acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman				"stabilised.\n", mmc_hostname(host->mmc));
915d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_dumpregs(host);
916d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			return;
917d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
9187cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		timeout--;
9197cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman		mdelay(1);
9207cb2c76fa2251474e42d55b75163c9d7ed11741ePierre Ossman	}
921d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
922d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	clk |= SDHCI_CLOCK_CARD_EN;
923d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
924d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
925d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout:
926d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->clock = clock;
927d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
928d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
929146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossmanstatic void sdhci_set_power(struct sdhci_host *host, unsigned short power)
930146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman{
931146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	u8 pwr;
932146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
933146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	if (host->power == power)
934146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		return;
935146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
9369e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	if (power == (unsigned short)-1) {
9379e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt		writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
938146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		goto out;
9399e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	}
9409e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt
9419e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	/*
9429e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	 * Spec says that we should clear the power reg before setting
9439e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	 * a new value. Some controllers don't seem to like this though.
9449e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt	 */
945b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
9469e9dc5f29f2eb65153a15c4fdb12b4382e3a75b2Darren Salt		writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
947146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
948146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	pwr = SDHCI_POWER_ON;
949146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
9504be34c99a2f3aa90fa42e62c0918f07afb8a645bPhilip Langdale	switch (1 << power) {
95155556da01284af8c2174b786b3eca8e11301b656Philip Langdale	case MMC_VDD_165_195:
952146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		pwr |= SDHCI_POWER_180;
953146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		break;
9544be34c99a2f3aa90fa42e62c0918f07afb8a645bPhilip Langdale	case MMC_VDD_29_30:
9554be34c99a2f3aa90fa42e62c0918f07afb8a645bPhilip Langdale	case MMC_VDD_30_31:
956146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		pwr |= SDHCI_POWER_300;
957146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		break;
9584be34c99a2f3aa90fa42e62c0918f07afb8a645bPhilip Langdale	case MMC_VDD_32_33:
9594be34c99a2f3aa90fa42e62c0918f07afb8a645bPhilip Langdale	case MMC_VDD_33_34:
960146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		pwr |= SDHCI_POWER_330;
961146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		break;
962146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	default:
963146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		BUG();
964146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	}
965146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
966e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon	/*
967c71f65129a1fb67bc6b9b8d03b493675b5c9302bAndres Salomon	 * At least the Marvell CaFe chip gets confused if we set the voltage
968e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon	 * and set turn on power at the same time, so set the voltage first.
969e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon	 */
970b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
971e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon		writeb(pwr & ~SDHCI_POWER_ON,
972e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon				host->ioaddr + SDHCI_POWER_CONTROL);
973e08c1694d9e2138204f2b79b73f0f159074ce2f5Andres Salomon
974146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
975146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
976146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossmanout:
977146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	host->power = power;
978146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman}
979146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
980d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
981d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
982d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * MMC callbacks                                                             *
983d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
984d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
985d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
986d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
987d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
988d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
989d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
990d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
991d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = mmc_priv(mmc);
992d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
993d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
994d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
995d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	WARN_ON(host->mrq != NULL);
996d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
9972f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifndef CONFIG_LEDS_CLASS
998d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_activate_led(host);
9992f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
1000d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1001d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->mrq = mrq;
1002d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
10031e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
10041e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		|| (host->flags & SDHCI_DEVICE_DEAD)) {
100517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		host->mrq->cmd->error = -ENOMEDIUM;
1006d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->finish_tasklet);
1007d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	} else
1008d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_send_command(host, mrq->cmd);
1009d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
10105f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
1011d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1012d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1013d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1014d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1015d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1016d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1017d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
1018d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u8 ctrl;
1019d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1020d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = mmc_priv(mmc);
1021d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1022d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1023d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
10241e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (host->flags & SDHCI_DEVICE_DEAD)
10251e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		goto out;
10261e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
1027d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1028d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * Reset the chip on each power off.
1029d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * Should clear out any weird states.
1030d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
1031d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (ios->power_mode == MMC_POWER_OFF) {
1032d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
1033d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_init(host);
1034d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1035d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1036d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_set_clock(host, ios->clock);
1037d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1038d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (ios->power_mode == MMC_POWER_OFF)
1039146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		sdhci_set_power(host, -1);
1040d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else
1041146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		sdhci_set_power(host, ios->vdd);
1042d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1043d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
1044cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman
1045d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (ios->bus_width == MMC_BUS_WIDTH_4)
1046d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		ctrl |= SDHCI_CTRL_4BITBUS;
1047d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else
1048d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		ctrl &= ~SDHCI_CTRL_4BITBUS;
1049cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman
1050cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman	if (ios->timing == MMC_TIMING_SD_HS)
1051cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman		ctrl |= SDHCI_CTRL_HISPD;
1052cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman	else
1053cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman		ctrl &= ~SDHCI_CTRL_HISPD;
1054cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman
1055d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
1056d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1057b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo	/*
1058b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo	 * Some (ENE) controllers go apeshit on some ios operation,
1059b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo	 * signalling timeout and CRC errors even on CMD0. Resetting
1060b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo	 * it on each ios seems to solve the problem.
1061b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo	 */
1062b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
1063b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
1064b8352260d28b30cb2bb2df99814fb9c360e38901Leandro Dorileo
10651e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout:
10665f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
1067d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1068d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1069d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1070d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int sdhci_get_ro(struct mmc_host *mmc)
1071d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1072d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1073d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
1074d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	int present;
1075d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1076d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = mmc_priv(mmc);
1077d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1078d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1079d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
10801e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (host->flags & SDHCI_DEVICE_DEAD)
10811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		present = 0;
10821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	else
10831e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
1084d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1085d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1086d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1087d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return !(present & SDHCI_WRITE_PROTECT);
1088d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1089d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1090f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossmanstatic void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
1091f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman{
1092f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	struct sdhci_host *host;
1093f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	unsigned long flags;
1094f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	u32 ier;
1095f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1096f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	host = mmc_priv(mmc);
1097f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1098f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1099f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
11001e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (host->flags & SDHCI_DEVICE_DEAD)
11011e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		goto out;
11021e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
1103f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	ier = readl(host->ioaddr + SDHCI_INT_ENABLE);
1104f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1105f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	ier &= ~SDHCI_INT_CARD_INT;
1106f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	if (enable)
1107f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman		ier |= SDHCI_INT_CARD_INT;
1108f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1109f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	writel(ier, host->ioaddr + SDHCI_INT_ENABLE);
1110f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
1111f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
11121e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanout:
1113f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	mmiowb();
1114f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1115f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1116f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman}
1117f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1118ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops sdhci_ops = {
1119d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	.request	= sdhci_request,
1120d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	.set_ios	= sdhci_set_ios,
1121d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	.get_ro		= sdhci_get_ro,
1122f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	.enable_sdio_irq = sdhci_enable_sdio_irq,
1123d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman};
1124d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1125d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
1126d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1127d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Tasklets                                                                  *
1128d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1129d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
1130d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1131d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_card(unsigned long param)
1132d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1133d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1134d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
1135d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1136d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = (struct sdhci_host*)param;
1137d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1138d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1139d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1140d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
1141d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		if (host->mrq) {
1142d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			printk(KERN_ERR "%s: Card removed during transfer!\n",
1143d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman				mmc_hostname(host->mmc));
1144d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			printk(KERN_ERR "%s: Resetting controller.\n",
1145d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman				mmc_hostname(host->mmc));
1146d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1147d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_reset(host, SDHCI_RESET_CMD);
1148d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_reset(host, SDHCI_RESET_DATA);
1149d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
115017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			host->mrq->cmd->error = -ENOMEDIUM;
1151d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			tasklet_schedule(&host->finish_tasklet);
1152d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
1153d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1154d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1155d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1156d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1157d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
1158d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1159d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1160d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_tasklet_finish(unsigned long param)
1161d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1162d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1163d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
1164d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct mmc_request *mrq;
1165d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1166d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = (struct sdhci_host*)param;
1167d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1168d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1169d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1170d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	del_timer(&host->timer);
1171d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1172d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mrq = host->mrq;
1173d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1174d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1175d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * The controller needs a reset of internal state machines
1176d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * upon error conditions.
1177d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
11781e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (!(host->flags & SDHCI_DEVICE_DEAD) &&
11791e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		(mrq->cmd->error ||
11801e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		 (mrq->data && (mrq->data->error ||
11811e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		  (mrq->data->stop && mrq->data->stop->error))) ||
11821e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
1183645289dca5021224279e67b4655796cafdfdad00Pierre Ossman
1184645289dca5021224279e67b4655796cafdfdad00Pierre Ossman		/* Some controllers need this kick or reset won't work here */
1185b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
1186645289dca5021224279e67b4655796cafdfdad00Pierre Ossman			unsigned int clock;
1187645289dca5021224279e67b4655796cafdfdad00Pierre Ossman
1188645289dca5021224279e67b4655796cafdfdad00Pierre Ossman			/* This is to force an update */
1189645289dca5021224279e67b4655796cafdfdad00Pierre Ossman			clock = host->clock;
1190645289dca5021224279e67b4655796cafdfdad00Pierre Ossman			host->clock = 0;
1191645289dca5021224279e67b4655796cafdfdad00Pierre Ossman			sdhci_set_clock(host, clock);
1192645289dca5021224279e67b4655796cafdfdad00Pierre Ossman		}
1193645289dca5021224279e67b4655796cafdfdad00Pierre Ossman
1194645289dca5021224279e67b4655796cafdfdad00Pierre Ossman		/* Spec says we should do both at the same time, but Ricoh
1195645289dca5021224279e67b4655796cafdfdad00Pierre Ossman		   controllers do not like that. */
1196d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_reset(host, SDHCI_RESET_CMD);
1197d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_reset(host, SDHCI_RESET_DATA);
1198d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1199d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1200d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->mrq = NULL;
1201d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->cmd = NULL;
1202d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->data = NULL;
1203d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
12042f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifndef CONFIG_LEDS_CLASS
1205d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_deactivate_led(host);
12062f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
1207d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
12085f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
1209d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1210d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1211d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc_request_done(host->mmc, mrq);
1212d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1213d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1214d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_timeout_timer(unsigned long data)
1215d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1216d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1217d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	unsigned long flags;
1218d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1219d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = (struct sdhci_host*)data;
1220d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1221d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_irqsave(&host->lock, flags);
1222d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1223d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (host->mrq) {
1224acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman		printk(KERN_ERR "%s: Timeout waiting for hardware "
1225acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman			"interrupt.\n", mmc_hostname(host->mmc));
1226d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_dumpregs(host);
1227d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1228d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		if (host->data) {
122917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			host->data->error = -ETIMEDOUT;
1230d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_finish_data(host);
1231d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		} else {
1232d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			if (host->cmd)
123317b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman				host->cmd->error = -ETIMEDOUT;
1234d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			else
123517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman				host->mrq->cmd->error = -ETIMEDOUT;
1236d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1237d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			tasklet_schedule(&host->finish_tasklet);
1238d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
1239d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1240d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
12415f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
1242d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock_irqrestore(&host->lock, flags);
1243d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1244d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1245d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
1246d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1247d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Interrupt handling                                                        *
1248d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1249d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
1250d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1251d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
1252d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1253d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	BUG_ON(intmask == 0);
1254d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1255d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (!host->cmd) {
1256b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman		printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
1257b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman			"though no command operation was in progress.\n",
1258b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman			mmc_hostname(host->mmc), (unsigned)intmask);
1259d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_dumpregs(host);
1260d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		return;
1261d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1262d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
126343b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman	if (intmask & SDHCI_INT_TIMEOUT)
126417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		host->cmd->error = -ETIMEDOUT;
126517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
126617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			SDHCI_INT_INDEX))
126717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		host->cmd->error = -EILSEQ;
126843b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman
126917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (host->cmd->error)
1270d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->finish_tasklet);
127143b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman	else if (intmask & SDHCI_INT_RESPONSE)
127243b58b36b7e6554b8a96be6b9f63542c583c06e5Pierre Ossman		sdhci_finish_command(host);
1273d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1274d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1275d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
1276d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1277d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	BUG_ON(intmask == 0);
1278d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1279d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (!host->data) {
1280d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		/*
1281d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 * A data end interrupt is sent together with the response
1282d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 * for the stop command.
1283d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		 */
1284d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		if (intmask & SDHCI_INT_DATA_END)
1285d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			return;
1286d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1287b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman		printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
1288b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman			"though no data operation was in progress.\n",
1289b67ac3f339c76dfea3cc75fc0285b6d13edc35faPierre Ossman			mmc_hostname(host->mmc), (unsigned)intmask);
1290d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_dumpregs(host);
1291d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1292d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		return;
1293d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1294d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1295d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (intmask & SDHCI_INT_DATA_TIMEOUT)
129617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		host->data->error = -ETIMEDOUT;
129717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
129817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		host->data->error = -EILSEQ;
12992134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else if (intmask & SDHCI_INT_ADMA_ERROR)
13002134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->data->error = -EIO;
1301d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
130217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (host->data->error)
1303d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_finish_data(host);
1304d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	else {
1305a406f5a3b68ee1db2306a2ba1c9b00dbd3505d05Pierre Ossman		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
1306d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			sdhci_transfer_pio(host);
1307d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13086ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		/*
13096ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		 * We currently don't do anything fancy with DMA
13106ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		 * boundaries, but as we can't disable the feature
13116ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		 * we need to at least restart the transfer.
13126ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		 */
13136ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman		if (intmask & SDHCI_INT_DMA_END)
13146ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman			writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
13156ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman				host->ioaddr + SDHCI_DMA_ADDRESS);
13166ba736a10e4ae63b38ccfee9f22b3263a6e5d050Pierre Ossman
1317e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman		if (intmask & SDHCI_INT_DATA_END) {
1318e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman			if (host->cmd) {
1319e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				/*
1320e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				 * Data managed to finish before the
1321e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				 * command completed. Make sure we do
1322e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				 * things in the proper order.
1323e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				 */
1324e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				host->data_early = 1;
1325e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman			} else {
1326e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman				sdhci_finish_data(host);
1327e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman			}
1328e538fbe83e374a3521128c1f4642aca037661c9dPierre Ossman		}
1329d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1330d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1331d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13327d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sdhci_irq(int irq, void *dev_id)
1333d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1334d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	irqreturn_t result;
1335d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host* host = dev_id;
1336d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	u32 intmask;
1337f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	int cardint = 0;
1338d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1339d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock(&host->lock);
1340d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1341d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
1342d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
134362df67a523acd7a22d936bf946b1889dbd60ca98Mark Lord	if (!intmask || intmask == 0xffffffff) {
1344d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		result = IRQ_NONE;
1345d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		goto out;
1346d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1347d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1348b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman	DBG("*** %s got interrupt: 0x%08x\n",
1349b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman		mmc_hostname(host->mmc), intmask);
1350d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13513192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
13523192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
13533192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman			host->ioaddr + SDHCI_INT_STATUS);
1354d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		tasklet_schedule(&host->card_tasklet);
13553192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	}
1356d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13573192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
1358d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13593192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	if (intmask & SDHCI_INT_CMD_MASK) {
1360d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		writel(intmask & SDHCI_INT_CMD_MASK,
1361d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			host->ioaddr + SDHCI_INT_STATUS);
13623192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
1363d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1364d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1365d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (intmask & SDHCI_INT_DATA_MASK) {
1366d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		writel(intmask & SDHCI_INT_DATA_MASK,
1367d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			host->ioaddr + SDHCI_INT_STATUS);
13683192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
1369d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1370d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1371d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
1372d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1373964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman	intmask &= ~SDHCI_INT_ERROR;
1374964f9ce2ff42dc47cf40fbd2f5c81cd60689e384Pierre Ossman
1375d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (intmask & SDHCI_INT_BUS_POWER) {
13763192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		printk(KERN_ERR "%s: Card is consuming too much power!\n",
1377d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman			mmc_hostname(host->mmc));
13783192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman		writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
1379d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1380d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13819d26a5d3f2b9c4fe4b2ba491683c6989ecd6ae04Rolf Eike Beer	intmask &= ~SDHCI_INT_BUS_POWER;
13823192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman
1383f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	if (intmask & SDHCI_INT_CARD_INT)
1384f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman		cardint = 1;
1385f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1386f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	intmask &= ~SDHCI_INT_CARD_INT;
1387f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
13883192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	if (intmask) {
1389acf1da4522add3771f4851c09c7fe6bcf1dd6636Pierre Ossman		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
13903192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman			mmc_hostname(host->mmc), intmask);
1391d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_dumpregs(host);
1392d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1393d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
13943192a28f7d34ea8f1d0fef8ca5bc0314b5b5bb19Pierre Ossman	}
1395d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1396d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	result = IRQ_HANDLED;
1397d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
13985f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
1399d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanout:
1400d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_unlock(&host->lock);
1401d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1402f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	/*
1403f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	 * We have to delay this as it calls back into the driver.
1404f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	 */
1405f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman	if (cardint)
1406f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman		mmc_signal_sdio_irq(host->mmc);
1407f75979b77fb20b01522d8fab96dfc76cc9f42420Pierre Ossman
1408d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return result;
1409d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1410d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1411d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
1412d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1413d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Suspend/resume                                                            *
1414d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1415d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
1416d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1417d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_PM
1418d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1419b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
1420d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1421b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	int ret;
1422a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman
1423b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	ret = mmc_suspend_host(host->mmc, state);
1424b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (ret)
1425b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return ret;
1426a715dfc7b9ef15ed5b398b185bd84cc015ff37f6Pierre Ossman
1427b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	free_irq(host->irq, host);
1428d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1429d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return 0;
1430d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1431d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1432b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_suspend_host);
1433d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1434b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_resume_host(struct sdhci_host *host)
1435b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{
1436b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	int ret;
1437d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1438b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (host->flags & SDHCI_USE_DMA) {
1439b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		if (host->ops->enable_dma)
1440b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman			host->ops->enable_dma(host);
1441b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	}
1442d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1443b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
1444b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman			  mmc_hostname(host->mmc), host);
1445df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman	if (ret)
1446df1c4b7bf7f3b3a48d78c6e5c2fc5b9a1c01b821Pierre Ossman		return ret;
1447d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1448b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	sdhci_init(host);
1449b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	mmiowb();
1450b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman
1451b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	ret = mmc_resume_host(host->mmc);
1452b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (ret)
1453b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return ret;
1454d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1455d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return 0;
1456d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1457d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1458b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_resume_host);
1459d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1460d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif /* CONFIG_PM */
1461d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1462d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
1463d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1464b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman * Device allocation/registration                                            *
1465d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1466d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
1467d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1468b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanstruct sdhci_host *sdhci_alloc_host(struct device *dev,
1469b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	size_t priv_size)
1470d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1471d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct mmc_host *mmc;
1472d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	struct sdhci_host *host;
1473d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1474b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	WARN_ON(dev == NULL);
1475d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1476b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
1477d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (!mmc)
1478b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return ERR_PTR(-ENOMEM);
1479d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1480d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host = mmc_priv(mmc);
1481d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->mmc = mmc;
1482d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1483b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	return host;
1484b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman}
14858a4da1430f7f2a16df3be9c7b5d55ba4e75b708cPierre Ossman
1486b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_alloc_host);
1487d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1488b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanint sdhci_add_host(struct sdhci_host *host)
1489b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{
1490b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	struct mmc_host *mmc;
1491b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	unsigned int caps;
1492b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	int ret;
1493d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1494b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	WARN_ON(host == NULL);
1495b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (host == NULL)
1496b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return -EINVAL;
1497d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1498b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	mmc = host->mmc;
1499d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1500b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (debug_quirks)
1501b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		host->quirks = debug_quirks;
1502d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1503d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman	sdhci_reset(host, SDHCI_RESET_ALL);
1504d96649ed5ace812ffc8d86252d7c663326ca47f8Pierre Ossman
15052134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->version = readw(host->ioaddr + SDHCI_HOST_VERSION);
15062134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->version = (host->version & SDHCI_SPEC_VER_MASK)
15072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				>> SDHCI_SPEC_VER_SHIFT;
15082134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->version > SDHCI_SPEC_200) {
15094a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman		printk(KERN_ERR "%s: Unknown controller version (%d). "
1510b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman			"You may experience problems.\n", mmc_hostname(mmc),
15112134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			host->version);
15124a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman	}
15134a9655051fb1efa568e53baf5dfb21e33bad6bf6Pierre Ossman
1514d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
1515d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1516b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
151798608076a21914ab12f1c858a0cdf55366260f12Pierre Ossman		host->flags |= SDHCI_USE_DMA;
15186743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman	else if (!(caps & SDHCI_CAN_DO_DMA))
15196743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman		DBG("Controller doesn't have DMA capability\n");
15206743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman	else
1521d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		host->flags |= SDHCI_USE_DMA;
1522d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1523b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
15247c168e3db7d900008ee304574057e0dc1a8505afFeng Tang		(host->flags & SDHCI_USE_DMA)) {
1525cee687ce4ab1197e20d4dacc09df01531362fdbdRolf Eike Beer		DBG("Disabling DMA as it is marked broken\n");
15267c168e3db7d900008ee304574057e0dc1a8505afFeng Tang		host->flags &= ~SDHCI_USE_DMA;
15277c168e3db7d900008ee304574057e0dc1a8505afFeng Tang	}
15287c168e3db7d900008ee304574057e0dc1a8505afFeng Tang
1529d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (host->flags & SDHCI_USE_DMA) {
15302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if ((host->version >= SDHCI_SPEC_200) &&
15312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				(caps & SDHCI_CAN_DO_ADMA2))
15322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			host->flags |= SDHCI_USE_ADMA;
15332134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
15342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
15352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
15362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		(host->flags & SDHCI_USE_ADMA)) {
15372134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		DBG("Disabling ADMA as it is marked broken\n");
15382134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->flags &= ~SDHCI_USE_ADMA;
15392134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
15402134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
15412134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_USE_DMA) {
1542b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		if (host->ops->enable_dma) {
1543b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman			if (host->ops->enable_dma(host)) {
1544b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman				printk(KERN_WARNING "%s: No suitable DMA "
1545b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman					"available. Falling back to PIO.\n",
1546b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman					mmc_hostname(mmc));
15472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA);
1548b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman			}
1549d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		}
1550d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	}
1551d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
15522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_USE_ADMA) {
15532134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		/*
15542134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * We need to allocate descriptors for all sg entries
15552134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * (128) and potentially one alignment transfer for
15562134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 * each of those entries.
15572134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		 */
15582134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
15592134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
15602134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		if (!host->adma_desc || !host->align_buffer) {
15612134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			kfree(host->adma_desc);
15622134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			kfree(host->align_buffer);
15632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			printk(KERN_WARNING "%s: Unable to allocate ADMA "
15642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				"buffers. Falling back to standard DMA.\n",
15652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman				mmc_hostname(mmc));
15662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman			host->flags &= ~SDHCI_USE_ADMA;
15672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		}
15682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	}
15692134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
15707659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	/*
15717659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	 * If we use DMA, then it's up to the caller to set the DMA
15727659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	 * mask, but PIO does not need the hw shim so we set a new
15737659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	 * mask here in that case.
15747659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	 */
15757659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	if (!(host->flags & SDHCI_USE_DMA)) {
15767659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		host->dma_mask = DMA_BIT_MASK(64);
15777659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman		mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
15787659150c60839a2bd31f74e866374abb9be17e43Pierre Ossman	}
1579d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
15808ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman	host->max_clk =
15818ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman		(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
15828ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman	if (host->max_clk == 0) {
15838ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman		printk(KERN_ERR "%s: Hardware doesn't specify base clock "
1584b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman			"frequency.\n", mmc_hostname(mmc));
1585b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return -ENODEV;
15868ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman	}
1587d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	host->max_clk *= 1000000;
1588d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
15891c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	host->timeout_clk =
15901c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
15911c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	if (host->timeout_clk == 0) {
15921c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
1593b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman			"frequency.\n", mmc_hostname(mmc));
1594b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return -ENODEV;
15951c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	}
15961c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
15971c8cde92fa5c57daa9ff58d970ca6374f8d484a2Pierre Ossman		host->timeout_clk *= 1000;
1598d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1599d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1600d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * Set host parameters.
1601d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
1602d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc->ops = &sdhci_ops;
1603d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc->f_min = host->max_clk / 256;
1604d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc->f_max = host->max_clk;
1605c9b74c5b8fb807187f6b1db09012828fcd2d7e73Pierre Ossman	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
1606d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1607cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman	if (caps & SDHCI_CAN_DO_HISPD)
1608cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
1609cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman
1610146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	mmc->ocr_avail = 0;
1611146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	if (caps & SDHCI_CAN_VDD_330)
1612146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
1613c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman	if (caps & SDHCI_CAN_VDD_300)
1614146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
1615c70840e819acdbab96b8cdf71d27cb68c6567efaPierre Ossman	if (caps & SDHCI_CAN_VDD_180)
161655556da01284af8c2174b786b3eca8e11301b656Philip Langdale		mmc->ocr_avail |= MMC_VDD_165_195;
1617146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
1618146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	if (mmc->ocr_avail == 0) {
1619146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman		printk(KERN_ERR "%s: Hardware doesn't report any "
1620b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman			"support voltages.\n", mmc_hostname(mmc));
1621b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		return -ENODEV;
1622146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman	}
1623146ad66eac836c0b976c98f428d73e1f6a75270dPierre Ossman
1624d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	spin_lock_init(&host->lock);
1625d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1626d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
16272134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * Maximum number of segments. Depends on if the hardware
16282134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * can do scatter/gather or not.
1629d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
16302134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_USE_ADMA)
16312134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		mmc->max_hw_segs = 128;
16322134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else if (host->flags & SDHCI_USE_DMA)
1633d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		mmc->max_hw_segs = 1;
16342134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else /* PIO */
16352134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		mmc->max_hw_segs = 128;
16362134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	mmc->max_phys_segs = 128;
1637d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1638d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1639bab7696184bbf0ea48d56902bd1f9ac983079ad2Pierre Ossman	 * Maximum number of sectors in one transfer. Limited by DMA boundary
164055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	 * size (512KiB).
1641d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
164255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	mmc->max_req_size = 524288;
1643d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1644d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1645d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * Maximum segment size. Could be one segment with the maximum number
16462134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * of bytes. When doing hardware scatter/gather, each entry cannot
16472134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	 * be larger than 64 KiB though.
1648d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
16492134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	if (host->flags & SDHCI_USE_ADMA)
16502134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		mmc->max_seg_size = 65536;
16512134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	else
16522134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		mmc->max_seg_size = mmc->max_req_size;
1653d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1654d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	/*
1655fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	 * Maximum block size. This varies from controller to controller and
1656fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	 * is specified in the capabilities register.
1657fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	 */
1658fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
1659fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	if (mmc->max_blk_size >= 3) {
1660b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman		printk(KERN_WARNING "%s: Invalid maximum block size, "
1661b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman			"assuming 512 bytes\n", mmc_hostname(mmc));
166203f8590d90844f04d20488a80e75eaf4c4e0b35cDavid Vrabel		mmc->max_blk_size = 512;
166303f8590d90844f04d20488a80e75eaf4c4e0b35cDavid Vrabel	} else
166403f8590d90844f04d20488a80e75eaf4c4e0b35cDavid Vrabel		mmc->max_blk_size = 512 << mmc->max_blk_size;
1665fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman
1666fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	/*
166755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	 * Maximum block count.
166855db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	 */
166955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	mmc->max_blk_count = 65535;
167055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman
167155db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	/*
1672d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 * Init tasklets.
1673d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	 */
1674d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_init(&host->card_tasklet,
1675d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_tasklet_card, (unsigned long)host);
1676d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_init(&host->finish_tasklet,
1677d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		sdhci_tasklet_finish, (unsigned long)host);
1678d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1679e4cad1b5a4851c90c1bcf460062074a2fa10815bAl Viro	setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
1680d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1681dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
1682b69c9058907642f8e1b32076906755c6623ea060Pierre Ossman		mmc_hostname(mmc), host);
1683d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	if (ret)
16848ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossman		goto untasklet;
1685d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1686d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_init(host);
1687d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1688d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#ifdef CONFIG_MMC_DEBUG
1689d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	sdhci_dumpregs(host);
1690d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman#endif
1691d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
16922f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifdef CONFIG_LEDS_CLASS
16932f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	host->led.name = mmc_hostname(mmc);
16942f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	host->led.brightness = LED_OFF;
16952f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	host->led.default_trigger = mmc_hostname(mmc);
16962f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	host->led.brightness_set = sdhci_led_control;
16972f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
1698b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	ret = led_classdev_register(mmc_dev(mmc), &host->led);
16992f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	if (ret)
17002f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman		goto reset;
17012f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
17022f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
17035f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman	mmiowb();
17045f25a66f6bbac563c94af94f03491b3ae43c40afPierre Ossman
1705d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	mmc_add_host(mmc);
1706d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
17072134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n",
1708b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman		mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->bus_id,
17092134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman		(host->flags & SDHCI_USE_ADMA)?"A":"",
1710d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman		(host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
1711d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1712d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return 0;
1713d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
17142f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifdef CONFIG_LEDS_CLASS
17152f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossmanreset:
17162f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	sdhci_reset(host, SDHCI_RESET_ALL);
17172f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	free_irq(host->irq, host);
17182f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
17198ef1a14379e105c1419d21e96ffac53202bc0501Pierre Ossmanuntasklet:
1720d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_kill(&host->card_tasklet);
1721d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_kill(&host->finish_tasklet);
1722d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1723d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	return ret;
1724d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1725d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1726b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_add_host);
1727d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
17281e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossmanvoid sdhci_remove_host(struct sdhci_host *host, int dead)
1729b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman{
17301e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	unsigned long flags;
17311e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
17321e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (dead) {
17331e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		spin_lock_irqsave(&host->lock, flags);
17341e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
17351e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		host->flags |= SDHCI_DEVICE_DEAD;
17361e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
17371e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		if (host->mrq) {
17381e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman			printk(KERN_ERR "%s: Controller removed during "
17391e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman				" transfer!\n", mmc_hostname(host->mmc));
17401e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
17411e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman			host->mrq->cmd->error = -ENOMEDIUM;
17421e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman			tasklet_schedule(&host->finish_tasklet);
17431e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		}
17441e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
17451e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		spin_unlock_irqrestore(&host->lock, flags);
17461e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	}
17471e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman
1748b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	mmc_remove_host(host->mmc);
1749d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
17502f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#ifdef CONFIG_LEDS_CLASS
17512f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman	led_classdev_unregister(&host->led);
17522f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman#endif
17532f730fec83be76f1b3b8f0066b3447f55c50d7a0Pierre Ossman
17541e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman	if (!dead)
17551e72859e3ae16346d4007024b20d2d4ef387dcc3Pierre Ossman		sdhci_reset(host, SDHCI_RESET_ALL);
1756d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1757d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	free_irq(host->irq, host);
1758d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1759d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	del_timer_sync(&host->timer);
1760d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1761d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_kill(&host->card_tasklet);
1762d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	tasklet_kill(&host->finish_tasklet);
17632134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
17642134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	kfree(host->adma_desc);
17652134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	kfree(host->align_buffer);
17662134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman
17672134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->adma_desc = NULL;
17682134a922c6e75c779983cad5d8aae832275f5a0dPierre Ossman	host->align_buffer = NULL;
1769d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1770d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1771b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_remove_host);
1772d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1773b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossmanvoid sdhci_free_host(struct sdhci_host *host)
1774d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1775b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	mmc_free_host(host->mmc);
1776d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1777d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1778b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanEXPORT_SYMBOL_GPL(sdhci_free_host);
1779d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1780d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman/*****************************************************************************\
1781d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1782d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman * Driver init/exit                                                          *
1783d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman *                                                                           *
1784d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman\*****************************************************************************/
1785d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1786d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic int __init sdhci_drv_init(void)
1787d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1788d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_INFO DRIVER_NAME
178952fbf9c976b36654e08e94c3107ddbaac7e2da33Pierre Ossman		": Secure Digital Host Controller Interface driver\n");
1790d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
1791d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1792b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre Ossman	return 0;
1793d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1794d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1795d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanstatic void __exit sdhci_drv_exit(void)
1796d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman{
1797d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman}
1798d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1799d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_init(sdhci_drv_init);
1800d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossmanmodule_exit(sdhci_drv_exit);
1801d129bceb1d44ed3c23b99164849193703372bab4Pierre Ossman
1802df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre Ossmanmodule_param(debug_quirks, uint, 0444);
18036743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman
1804d129bceb1d44ed3c23b99164849193703372bab4Pierre OssmanMODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
1805b8c86fc5d8deaa5a6dc49c2c1ed144e6838bf0f3Pierre OssmanMODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
1806d129bceb1d44ed3c23b99164849193703372bab4Pierre OssmanMODULE_LICENSE("GPL");
18076743527441430586aa82a0dee1b2700a2a974ebcPierre Ossman
1808df673b227ce08a7706b30fd2bf6512393d9c3c29Pierre OssmanMODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
1809