mmc_ops.c 7.9 KB
Newer Older
P
Pierre Ossman 已提交
1
/*
P
Pierre Ossman 已提交
2
 *  linux/drivers/mmc/core/mmc_ops.h
P
Pierre Ossman 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 *  Copyright 2006-2007 Pierre Ossman
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 */

#include <linux/types.h>
#include <linux/scatterlist.h>

#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>

#include "core.h"
#include "mmc_ops.h"

static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
	int err;
	struct mmc_command cmd;

	BUG_ON(!host);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SELECT_CARD;

	if (card) {
		cmd.arg = card->rca << 16;
		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
	} else {
		cmd.arg = 0;
		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
	}

	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
42
	if (err)
P
Pierre Ossman 已提交
43 44
		return err;

P
Pierre Ossman 已提交
45
	return 0;
P
Pierre Ossman 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
}

int mmc_select_card(struct mmc_card *card)
{
	BUG_ON(!card);

	return _mmc_select_card(card->host, card);
}

int mmc_deselect_cards(struct mmc_host *host)
{
	return _mmc_select_card(host, NULL);
}

int mmc_go_idle(struct mmc_host *host)
{
	int err;
	struct mmc_command cmd;

D
David Brownell 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77
	/*
	 * Non-SPI hosts need to prevent chipselect going active during
	 * GO_IDLE; that would put chips into SPI mode.  Remind them of
	 * that in case of hardware that won't pull up DAT3/nCS otherwise.
	 *
	 * SPI hosts ignore ios.chip_select; it's managed according to
	 * rules that must accomodate non-MMC slaves which this layer
	 * won't even know about.
	 */
	if (!mmc_host_is_spi(host)) {
		mmc_set_chip_select(host, MMC_CS_HIGH);
		mmc_delay(1);
	}
P
Pierre Ossman 已提交
78 79 80 81 82

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_GO_IDLE_STATE;
	cmd.arg = 0;
D
David Brownell 已提交
83
	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
P
Pierre Ossman 已提交
84 85 86 87 88

	err = mmc_wait_for_cmd(host, &cmd, 0);

	mmc_delay(1);

D
David Brownell 已提交
89 90 91 92
	if (!mmc_host_is_spi(host)) {
		mmc_set_chip_select(host, MMC_CS_DONTCARE);
		mmc_delay(1);
	}
P
Pierre Ossman 已提交
93

D
David Brownell 已提交
94
	host->use_spi_crc = 0;
P
Pierre Ossman 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108

	return err;
}

int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
{
	struct mmc_command cmd;
	int i, err = 0;

	BUG_ON(!host);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SEND_OP_COND;
D
David Brownell 已提交
109 110
	cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
P
Pierre Ossman 已提交
111 112 113

	for (i = 100; i; i--) {
		err = mmc_wait_for_cmd(host, &cmd, 0);
P
Pierre Ossman 已提交
114
		if (err)
P
Pierre Ossman 已提交
115 116
			break;

D
David Brownell 已提交
117 118
		/* if we're just probing, do a single pass */
		if (ocr == 0)
P
Pierre Ossman 已提交
119 120
			break;

D
David Brownell 已提交
121 122 123 124 125 126 127 128 129
		/* otherwise wait until reset completes */
		if (mmc_host_is_spi(host)) {
			if (!(cmd.resp[0] & R1_SPI_IDLE))
				break;
		} else {
			if (cmd.resp[0] & MMC_CARD_BUSY)
				break;
		}

P
Pierre Ossman 已提交
130
		err = -ETIMEDOUT;
P
Pierre Ossman 已提交
131 132 133 134

		mmc_delay(10);
	}

D
David Brownell 已提交
135
	if (rocr && !mmc_host_is_spi(host))
P
Pierre Ossman 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
		*rocr = cmd.resp[0];

	return err;
}

int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
{
	int err;
	struct mmc_command cmd;

	BUG_ON(!host);
	BUG_ON(!cid);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_ALL_SEND_CID;
	cmd.arg = 0;
	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;

	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
156
	if (err)
P
Pierre Ossman 已提交
157 158 159 160
		return err;

	memcpy(cid, cmd.resp, sizeof(u32) * 4);

P
Pierre Ossman 已提交
161
	return 0;
P
Pierre Ossman 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
}

int mmc_set_relative_addr(struct mmc_card *card)
{
	int err;
	struct mmc_command cmd;

	BUG_ON(!card);
	BUG_ON(!card->host);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SET_RELATIVE_ADDR;
	cmd.arg = card->rca << 16;
	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;

	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
179
	if (err)
P
Pierre Ossman 已提交
180 181
		return err;

P
Pierre Ossman 已提交
182
	return 0;
P
Pierre Ossman 已提交
183 184
}

D
David Brownell 已提交
185 186
static int
mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
P
Pierre Ossman 已提交
187 188 189 190
{
	int err;
	struct mmc_command cmd;

D
David Brownell 已提交
191 192
	BUG_ON(!host);
	BUG_ON(!cxd);
P
Pierre Ossman 已提交
193 194 195

	memset(&cmd, 0, sizeof(struct mmc_command));

D
David Brownell 已提交
196 197
	cmd.opcode = opcode;
	cmd.arg = arg;
P
Pierre Ossman 已提交
198 199
	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;

D
David Brownell 已提交
200
	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
201
	if (err)
P
Pierre Ossman 已提交
202 203
		return err;

D
David Brownell 已提交
204
	memcpy(cxd, cmd.resp, sizeof(u32) * 4);
P
Pierre Ossman 已提交
205

P
Pierre Ossman 已提交
206
	return 0;
P
Pierre Ossman 已提交
207 208
}

D
David Brownell 已提交
209 210 211
static int
mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
		u32 opcode, void *buf, unsigned len)
P
Pierre Ossman 已提交
212 213 214 215 216
{
	struct mmc_request mrq;
	struct mmc_command cmd;
	struct mmc_data data;
	struct scatterlist sg;
D
David Brownell 已提交
217
	void *data_buf;
P
Pierre Ossman 已提交
218

D
David Brownell 已提交
219 220 221 222 223 224
	/* dma onto stack is unsafe/nonportable, but callers to this
	 * routine normally provide temporary on-stack buffers ...
	 */
	data_buf = kmalloc(len, GFP_KERNEL);
	if (data_buf == NULL)
		return -ENOMEM;
P
Pierre Ossman 已提交
225 226 227 228 229 230 231 232

	memset(&mrq, 0, sizeof(struct mmc_request));
	memset(&cmd, 0, sizeof(struct mmc_command));
	memset(&data, 0, sizeof(struct mmc_data));

	mrq.cmd = &cmd;
	mrq.data = &data;

D
David Brownell 已提交
233
	cmd.opcode = opcode;
P
Pierre Ossman 已提交
234 235
	cmd.arg = 0;

D
David Brownell 已提交
236 237 238 239 240 241 242 243
	/* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
	 * rely on callers to never use this with "native" calls for reading
	 * CSD or CID.  Native versions of those commands use the R2 type,
	 * not R1 plus a data block.
	 */
	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;

	data.blksz = len;
P
Pierre Ossman 已提交
244 245 246 247 248
	data.blocks = 1;
	data.flags = MMC_DATA_READ;
	data.sg = &sg;
	data.sg_len = 1;

D
David Brownell 已提交
249
	sg_init_one(&sg, data_buf, len);
P
Pierre Ossman 已提交
250

251 252 253 254 255 256 257 258 259
	if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
		/*
		 * The spec states that CSR and CID accesses have a timeout
		 * of 64 clock cycles.
		 */
		data.timeout_ns = 0;
		data.timeout_clks = 64;
	} else
		mmc_set_data_timeout(&data, card);
P
Pierre Ossman 已提交
260

D
David Brownell 已提交
261 262 263 264
	mmc_wait_for_req(host, &mrq);

	memcpy(buf, data_buf, len);
	kfree(data_buf);
P
Pierre Ossman 已提交
265

P
Pierre Ossman 已提交
266
	if (cmd.error)
P
Pierre Ossman 已提交
267
		return cmd.error;
P
Pierre Ossman 已提交
268
	if (data.error)
P
Pierre Ossman 已提交
269 270
		return data.error;

P
Pierre Ossman 已提交
271
	return 0;
P
Pierre Ossman 已提交
272 273
}

D
David Brownell 已提交
274 275
int mmc_send_csd(struct mmc_card *card, u32 *csd)
{
P
Pierre Ossman 已提交
276 277
	int ret, i;

D
David Brownell 已提交
278 279 280 281
	if (!mmc_host_is_spi(card->host))
		return mmc_send_cxd_native(card->host, card->rca << 16,
				csd, MMC_SEND_CSD);

P
Pierre Ossman 已提交
282 283 284 285 286 287 288 289
	ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
	if (ret)
		return ret;

	for (i = 0;i < 4;i++)
		csd[i] = be32_to_cpu(csd[i]);

	return 0;
D
David Brownell 已提交
290 291 292 293
}

int mmc_send_cid(struct mmc_host *host, u32 *cid)
{
P
Pierre Ossman 已提交
294 295
	int ret, i;

D
David Brownell 已提交
296 297 298 299 300 301 302
	if (!mmc_host_is_spi(host)) {
		if (!host->card)
			return -EINVAL;
		return mmc_send_cxd_native(host, host->card->rca << 16,
				cid, MMC_SEND_CID);
	}

P
Pierre Ossman 已提交
303 304 305 306 307 308 309 310
	ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
	if (ret)
		return ret;

	for (i = 0;i < 4;i++)
		cid[i] = be32_to_cpu(cid[i]);

	return 0;
D
David Brownell 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
}

int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
{
	return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
			ext_csd, 512);
}

int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
{
	struct mmc_command cmd;
	int err;

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SPI_READ_OCR;
	cmd.arg = highcap ? (1 << 30) : 0;
	cmd.flags = MMC_RSP_SPI_R3;

	err = mmc_wait_for_cmd(host, &cmd, 0);

	*ocrp = cmd.resp[1];
	return err;
}

int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
{
	struct mmc_command cmd;
	int err;

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SPI_CRC_ON_OFF;
	cmd.flags = MMC_RSP_SPI_R1;
	cmd.arg = use_crc;

	err = mmc_wait_for_cmd(host, &cmd, 0);
	if (!err)
		host->use_spi_crc = use_crc;
	return err;
}

P
Pierre Ossman 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
{
	int err;
	struct mmc_command cmd;

	BUG_ON(!card);
	BUG_ON(!card->host);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SWITCH;
	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
		  (index << 16) |
		  (value << 8) |
		  set;
D
David Brownell 已提交
368
	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
P
Pierre Ossman 已提交
369 370

	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
371
	if (err)
P
Pierre Ossman 已提交
372 373
		return err;

P
Pierre Ossman 已提交
374
	return 0;
P
Pierre Ossman 已提交
375 376 377 378 379 380 381 382 383 384 385 386 387
}

int mmc_send_status(struct mmc_card *card, u32 *status)
{
	int err;
	struct mmc_command cmd;

	BUG_ON(!card);
	BUG_ON(!card->host);

	memset(&cmd, 0, sizeof(struct mmc_command));

	cmd.opcode = MMC_SEND_STATUS;
D
David Brownell 已提交
388 389 390
	if (!mmc_host_is_spi(card->host))
		cmd.arg = card->rca << 16;
	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
P
Pierre Ossman 已提交
391 392

	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
P
Pierre Ossman 已提交
393
	if (err)
P
Pierre Ossman 已提交
394 395
		return err;

D
David Brownell 已提交
396 397 398
	/* NOTE: callers are required to understand the difference
	 * between "native" and SPI format status words!
	 */
P
Pierre Ossman 已提交
399 400 401
	if (status)
		*status = cmd.resp[0];

P
Pierre Ossman 已提交
402
	return 0;
P
Pierre Ossman 已提交
403 404
}