1da7fbe58SPierre Ossman /* 270f10482SPierre Ossman * linux/drivers/mmc/core/mmc_ops.h 3da7fbe58SPierre Ossman * 4da7fbe58SPierre Ossman * Copyright 2006-2007 Pierre Ossman 5da7fbe58SPierre Ossman * 6da7fbe58SPierre Ossman * This program is free software; you can redistribute it and/or modify 7da7fbe58SPierre Ossman * it under the terms of the GNU General Public License as published by 8da7fbe58SPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 9da7fbe58SPierre Ossman * your option) any later version. 10da7fbe58SPierre Ossman */ 11da7fbe58SPierre Ossman 125a0e3ad6STejun Heo #include <linux/slab.h> 133ef77af1SPaul Gortmaker #include <linux/export.h> 14da7fbe58SPierre Ossman #include <linux/types.h> 15da7fbe58SPierre Ossman #include <linux/scatterlist.h> 16da7fbe58SPierre Ossman 17da7fbe58SPierre Ossman #include <linux/mmc/host.h> 18da7fbe58SPierre Ossman #include <linux/mmc/card.h> 19da7fbe58SPierre Ossman #include <linux/mmc/mmc.h> 20da7fbe58SPierre Ossman 21da7fbe58SPierre Ossman #include "core.h" 22da7fbe58SPierre Ossman #include "mmc_ops.h" 23da7fbe58SPierre Ossman 248fee476bSTrey Ramsay #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ 258fee476bSTrey Ramsay 26a27fbf2fSSeungwon Jeon static inline int __mmc_send_status(struct mmc_card *card, u32 *status, 27a27fbf2fSSeungwon Jeon bool ignore_crc) 28a27fbf2fSSeungwon Jeon { 29a27fbf2fSSeungwon Jeon int err; 30a27fbf2fSSeungwon Jeon struct mmc_command cmd = {0}; 31a27fbf2fSSeungwon Jeon 32a27fbf2fSSeungwon Jeon BUG_ON(!card); 33a27fbf2fSSeungwon Jeon BUG_ON(!card->host); 34a27fbf2fSSeungwon Jeon 35a27fbf2fSSeungwon Jeon cmd.opcode = MMC_SEND_STATUS; 36a27fbf2fSSeungwon Jeon if (!mmc_host_is_spi(card->host)) 37a27fbf2fSSeungwon Jeon cmd.arg = card->rca << 16; 38a27fbf2fSSeungwon Jeon cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 39a27fbf2fSSeungwon Jeon if (ignore_crc) 40a27fbf2fSSeungwon Jeon cmd.flags &= ~MMC_RSP_CRC; 41a27fbf2fSSeungwon Jeon 42a27fbf2fSSeungwon Jeon err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 43a27fbf2fSSeungwon Jeon if (err) 44a27fbf2fSSeungwon Jeon return err; 45a27fbf2fSSeungwon Jeon 46a27fbf2fSSeungwon Jeon /* NOTE: callers are required to understand the difference 47a27fbf2fSSeungwon Jeon * between "native" and SPI format status words! 48a27fbf2fSSeungwon Jeon */ 49a27fbf2fSSeungwon Jeon if (status) 50a27fbf2fSSeungwon Jeon *status = cmd.resp[0]; 51a27fbf2fSSeungwon Jeon 52a27fbf2fSSeungwon Jeon return 0; 53a27fbf2fSSeungwon Jeon } 54a27fbf2fSSeungwon Jeon 55a27fbf2fSSeungwon Jeon int mmc_send_status(struct mmc_card *card, u32 *status) 56a27fbf2fSSeungwon Jeon { 57a27fbf2fSSeungwon Jeon return __mmc_send_status(card, status, false); 58a27fbf2fSSeungwon Jeon } 59a27fbf2fSSeungwon Jeon 60da7fbe58SPierre Ossman static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) 61da7fbe58SPierre Ossman { 62da7fbe58SPierre Ossman int err; 631278dba1SChris Ball struct mmc_command cmd = {0}; 64da7fbe58SPierre Ossman 65da7fbe58SPierre Ossman BUG_ON(!host); 66da7fbe58SPierre Ossman 67da7fbe58SPierre Ossman cmd.opcode = MMC_SELECT_CARD; 68da7fbe58SPierre Ossman 69da7fbe58SPierre Ossman if (card) { 70da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 71da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 72da7fbe58SPierre Ossman } else { 73da7fbe58SPierre Ossman cmd.arg = 0; 74da7fbe58SPierre Ossman cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; 75da7fbe58SPierre Ossman } 76da7fbe58SPierre Ossman 77da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 7817b0429dSPierre Ossman if (err) 79da7fbe58SPierre Ossman return err; 80da7fbe58SPierre Ossman 8117b0429dSPierre Ossman return 0; 82da7fbe58SPierre Ossman } 83da7fbe58SPierre Ossman 84da7fbe58SPierre Ossman int mmc_select_card(struct mmc_card *card) 85da7fbe58SPierre Ossman { 86da7fbe58SPierre Ossman BUG_ON(!card); 87da7fbe58SPierre Ossman 88da7fbe58SPierre Ossman return _mmc_select_card(card->host, card); 89da7fbe58SPierre Ossman } 90da7fbe58SPierre Ossman 91da7fbe58SPierre Ossman int mmc_deselect_cards(struct mmc_host *host) 92da7fbe58SPierre Ossman { 93da7fbe58SPierre Ossman return _mmc_select_card(host, NULL); 94da7fbe58SPierre Ossman } 95da7fbe58SPierre Ossman 96da7fbe58SPierre Ossman int mmc_go_idle(struct mmc_host *host) 97da7fbe58SPierre Ossman { 98da7fbe58SPierre Ossman int err; 991278dba1SChris Ball struct mmc_command cmd = {0}; 100da7fbe58SPierre Ossman 101af517150SDavid Brownell /* 102af517150SDavid Brownell * Non-SPI hosts need to prevent chipselect going active during 103af517150SDavid Brownell * GO_IDLE; that would put chips into SPI mode. Remind them of 104af517150SDavid Brownell * that in case of hardware that won't pull up DAT3/nCS otherwise. 105af517150SDavid Brownell * 106af517150SDavid Brownell * SPI hosts ignore ios.chip_select; it's managed according to 10725985edcSLucas De Marchi * rules that must accommodate non-MMC slaves which this layer 108af517150SDavid Brownell * won't even know about. 109af517150SDavid Brownell */ 110af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 111da7fbe58SPierre Ossman mmc_set_chip_select(host, MMC_CS_HIGH); 112da7fbe58SPierre Ossman mmc_delay(1); 113af517150SDavid Brownell } 114da7fbe58SPierre Ossman 115da7fbe58SPierre Ossman cmd.opcode = MMC_GO_IDLE_STATE; 116da7fbe58SPierre Ossman cmd.arg = 0; 117af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; 118da7fbe58SPierre Ossman 119da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 120da7fbe58SPierre Ossman 121da7fbe58SPierre Ossman mmc_delay(1); 122da7fbe58SPierre Ossman 123af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 124da7fbe58SPierre Ossman mmc_set_chip_select(host, MMC_CS_DONTCARE); 125da7fbe58SPierre Ossman mmc_delay(1); 126af517150SDavid Brownell } 127af517150SDavid Brownell 128af517150SDavid Brownell host->use_spi_crc = 0; 129da7fbe58SPierre Ossman 130da7fbe58SPierre Ossman return err; 131da7fbe58SPierre Ossman } 132da7fbe58SPierre Ossman 133da7fbe58SPierre Ossman int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) 134da7fbe58SPierre Ossman { 1351278dba1SChris Ball struct mmc_command cmd = {0}; 136da7fbe58SPierre Ossman int i, err = 0; 137da7fbe58SPierre Ossman 138da7fbe58SPierre Ossman BUG_ON(!host); 139da7fbe58SPierre Ossman 140da7fbe58SPierre Ossman cmd.opcode = MMC_SEND_OP_COND; 141af517150SDavid Brownell cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; 142af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; 143da7fbe58SPierre Ossman 144da7fbe58SPierre Ossman for (i = 100; i; i--) { 145da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 14617b0429dSPierre Ossman if (err) 147da7fbe58SPierre Ossman break; 148da7fbe58SPierre Ossman 149af517150SDavid Brownell /* if we're just probing, do a single pass */ 150af517150SDavid Brownell if (ocr == 0) 151da7fbe58SPierre Ossman break; 152da7fbe58SPierre Ossman 153af517150SDavid Brownell /* otherwise wait until reset completes */ 154af517150SDavid Brownell if (mmc_host_is_spi(host)) { 155af517150SDavid Brownell if (!(cmd.resp[0] & R1_SPI_IDLE)) 156af517150SDavid Brownell break; 157af517150SDavid Brownell } else { 158af517150SDavid Brownell if (cmd.resp[0] & MMC_CARD_BUSY) 159af517150SDavid Brownell break; 160af517150SDavid Brownell } 161af517150SDavid Brownell 16217b0429dSPierre Ossman err = -ETIMEDOUT; 163da7fbe58SPierre Ossman 164da7fbe58SPierre Ossman mmc_delay(10); 165da7fbe58SPierre Ossman } 166da7fbe58SPierre Ossman 167af517150SDavid Brownell if (rocr && !mmc_host_is_spi(host)) 168da7fbe58SPierre Ossman *rocr = cmd.resp[0]; 169da7fbe58SPierre Ossman 170da7fbe58SPierre Ossman return err; 171da7fbe58SPierre Ossman } 172da7fbe58SPierre Ossman 173da7fbe58SPierre Ossman int mmc_all_send_cid(struct mmc_host *host, u32 *cid) 174da7fbe58SPierre Ossman { 175da7fbe58SPierre Ossman int err; 1761278dba1SChris Ball struct mmc_command cmd = {0}; 177da7fbe58SPierre Ossman 178da7fbe58SPierre Ossman BUG_ON(!host); 179da7fbe58SPierre Ossman BUG_ON(!cid); 180da7fbe58SPierre Ossman 181da7fbe58SPierre Ossman cmd.opcode = MMC_ALL_SEND_CID; 182da7fbe58SPierre Ossman cmd.arg = 0; 183da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; 184da7fbe58SPierre Ossman 185da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 18617b0429dSPierre Ossman if (err) 187da7fbe58SPierre Ossman return err; 188da7fbe58SPierre Ossman 189da7fbe58SPierre Ossman memcpy(cid, cmd.resp, sizeof(u32) * 4); 190da7fbe58SPierre Ossman 19117b0429dSPierre Ossman return 0; 192da7fbe58SPierre Ossman } 193da7fbe58SPierre Ossman 194da7fbe58SPierre Ossman int mmc_set_relative_addr(struct mmc_card *card) 195da7fbe58SPierre Ossman { 196da7fbe58SPierre Ossman int err; 1971278dba1SChris Ball struct mmc_command cmd = {0}; 198da7fbe58SPierre Ossman 199da7fbe58SPierre Ossman BUG_ON(!card); 200da7fbe58SPierre Ossman BUG_ON(!card->host); 201da7fbe58SPierre Ossman 202da7fbe58SPierre Ossman cmd.opcode = MMC_SET_RELATIVE_ADDR; 203da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 204da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 205da7fbe58SPierre Ossman 206da7fbe58SPierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 20717b0429dSPierre Ossman if (err) 208da7fbe58SPierre Ossman return err; 209da7fbe58SPierre Ossman 21017b0429dSPierre Ossman return 0; 211da7fbe58SPierre Ossman } 212da7fbe58SPierre Ossman 213af517150SDavid Brownell static int 214af517150SDavid Brownell mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) 215da7fbe58SPierre Ossman { 216da7fbe58SPierre Ossman int err; 2171278dba1SChris Ball struct mmc_command cmd = {0}; 218da7fbe58SPierre Ossman 219af517150SDavid Brownell BUG_ON(!host); 220af517150SDavid Brownell BUG_ON(!cxd); 221da7fbe58SPierre Ossman 222af517150SDavid Brownell cmd.opcode = opcode; 223af517150SDavid Brownell cmd.arg = arg; 224da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; 225da7fbe58SPierre Ossman 226af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 22717b0429dSPierre Ossman if (err) 228da7fbe58SPierre Ossman return err; 229da7fbe58SPierre Ossman 230af517150SDavid Brownell memcpy(cxd, cmd.resp, sizeof(u32) * 4); 231da7fbe58SPierre Ossman 23217b0429dSPierre Ossman return 0; 233da7fbe58SPierre Ossman } 234da7fbe58SPierre Ossman 2351a41313eSKyungsik Lee /* 2361a41313eSKyungsik Lee * NOTE: void *buf, caller for the buf is required to use DMA-capable 2371a41313eSKyungsik Lee * buffer or on-stack buffer (with some overhead in callee). 2381a41313eSKyungsik Lee */ 239af517150SDavid Brownell static int 240af517150SDavid Brownell mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, 241af517150SDavid Brownell u32 opcode, void *buf, unsigned len) 242da7fbe58SPierre Ossman { 243ad5fd972SVenkatraman S struct mmc_request mrq = {NULL}; 2441278dba1SChris Ball struct mmc_command cmd = {0}; 245a61ad2b4SChris Ball struct mmc_data data = {0}; 246da7fbe58SPierre Ossman struct scatterlist sg; 247af517150SDavid Brownell void *data_buf; 2481a41313eSKyungsik Lee int is_on_stack; 249da7fbe58SPierre Ossman 2501a41313eSKyungsik Lee is_on_stack = object_is_on_stack(buf); 2511a41313eSKyungsik Lee if (is_on_stack) { 2521a41313eSKyungsik Lee /* 2531a41313eSKyungsik Lee * dma onto stack is unsafe/nonportable, but callers to this 254af517150SDavid Brownell * routine normally provide temporary on-stack buffers ... 255af517150SDavid Brownell */ 256af517150SDavid Brownell data_buf = kmalloc(len, GFP_KERNEL); 2571a41313eSKyungsik Lee if (!data_buf) 258af517150SDavid Brownell return -ENOMEM; 2591a41313eSKyungsik Lee } else 2601a41313eSKyungsik Lee data_buf = buf; 261da7fbe58SPierre Ossman 262da7fbe58SPierre Ossman mrq.cmd = &cmd; 263da7fbe58SPierre Ossman mrq.data = &data; 264da7fbe58SPierre Ossman 265af517150SDavid Brownell cmd.opcode = opcode; 266da7fbe58SPierre Ossman cmd.arg = 0; 267da7fbe58SPierre Ossman 268af517150SDavid Brownell /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we 269af517150SDavid Brownell * rely on callers to never use this with "native" calls for reading 270af517150SDavid Brownell * CSD or CID. Native versions of those commands use the R2 type, 271af517150SDavid Brownell * not R1 plus a data block. 272af517150SDavid Brownell */ 273af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 274af517150SDavid Brownell 275af517150SDavid Brownell data.blksz = len; 276da7fbe58SPierre Ossman data.blocks = 1; 277da7fbe58SPierre Ossman data.flags = MMC_DATA_READ; 278da7fbe58SPierre Ossman data.sg = &sg; 279da7fbe58SPierre Ossman data.sg_len = 1; 280da7fbe58SPierre Ossman 281af517150SDavid Brownell sg_init_one(&sg, data_buf, len); 282da7fbe58SPierre Ossman 283cda56ac2SAdrian Hunter if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { 2840d3e0460SMatthew Fleming /* 2850d3e0460SMatthew Fleming * The spec states that CSR and CID accesses have a timeout 2860d3e0460SMatthew Fleming * of 64 clock cycles. 2870d3e0460SMatthew Fleming */ 2880d3e0460SMatthew Fleming data.timeout_ns = 0; 2890d3e0460SMatthew Fleming data.timeout_clks = 64; 290cda56ac2SAdrian Hunter } else 291cda56ac2SAdrian Hunter mmc_set_data_timeout(&data, card); 292da7fbe58SPierre Ossman 293af517150SDavid Brownell mmc_wait_for_req(host, &mrq); 294af517150SDavid Brownell 2951a41313eSKyungsik Lee if (is_on_stack) { 296af517150SDavid Brownell memcpy(buf, data_buf, len); 297af517150SDavid Brownell kfree(data_buf); 2981a41313eSKyungsik Lee } 299da7fbe58SPierre Ossman 30017b0429dSPierre Ossman if (cmd.error) 301da7fbe58SPierre Ossman return cmd.error; 30217b0429dSPierre Ossman if (data.error) 303da7fbe58SPierre Ossman return data.error; 304da7fbe58SPierre Ossman 30517b0429dSPierre Ossman return 0; 306da7fbe58SPierre Ossman } 307da7fbe58SPierre Ossman 308af517150SDavid Brownell int mmc_send_csd(struct mmc_card *card, u32 *csd) 309af517150SDavid Brownell { 31078e48073SPierre Ossman int ret, i; 3111a41313eSKyungsik Lee u32 *csd_tmp; 31278e48073SPierre Ossman 313af517150SDavid Brownell if (!mmc_host_is_spi(card->host)) 314af517150SDavid Brownell return mmc_send_cxd_native(card->host, card->rca << 16, 315af517150SDavid Brownell csd, MMC_SEND_CSD); 316af517150SDavid Brownell 3171a41313eSKyungsik Lee csd_tmp = kmalloc(16, GFP_KERNEL); 3181a41313eSKyungsik Lee if (!csd_tmp) 3191a41313eSKyungsik Lee return -ENOMEM; 3201a41313eSKyungsik Lee 3211a41313eSKyungsik Lee ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); 32278e48073SPierre Ossman if (ret) 3231a41313eSKyungsik Lee goto err; 32478e48073SPierre Ossman 32578e48073SPierre Ossman for (i = 0;i < 4;i++) 3261a41313eSKyungsik Lee csd[i] = be32_to_cpu(csd_tmp[i]); 32778e48073SPierre Ossman 3281a41313eSKyungsik Lee err: 3291a41313eSKyungsik Lee kfree(csd_tmp); 3301a41313eSKyungsik Lee return ret; 331af517150SDavid Brownell } 332af517150SDavid Brownell 333af517150SDavid Brownell int mmc_send_cid(struct mmc_host *host, u32 *cid) 334af517150SDavid Brownell { 33578e48073SPierre Ossman int ret, i; 3361a41313eSKyungsik Lee u32 *cid_tmp; 33778e48073SPierre Ossman 338af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 339af517150SDavid Brownell if (!host->card) 340af517150SDavid Brownell return -EINVAL; 341af517150SDavid Brownell return mmc_send_cxd_native(host, host->card->rca << 16, 342af517150SDavid Brownell cid, MMC_SEND_CID); 343af517150SDavid Brownell } 344af517150SDavid Brownell 3451a41313eSKyungsik Lee cid_tmp = kmalloc(16, GFP_KERNEL); 3461a41313eSKyungsik Lee if (!cid_tmp) 3471a41313eSKyungsik Lee return -ENOMEM; 3481a41313eSKyungsik Lee 3491a41313eSKyungsik Lee ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); 35078e48073SPierre Ossman if (ret) 3511a41313eSKyungsik Lee goto err; 35278e48073SPierre Ossman 35378e48073SPierre Ossman for (i = 0;i < 4;i++) 3541a41313eSKyungsik Lee cid[i] = be32_to_cpu(cid_tmp[i]); 35578e48073SPierre Ossman 3561a41313eSKyungsik Lee err: 3571a41313eSKyungsik Lee kfree(cid_tmp); 3581a41313eSKyungsik Lee return ret; 359af517150SDavid Brownell } 360af517150SDavid Brownell 361af517150SDavid Brownell int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) 362af517150SDavid Brownell { 363af517150SDavid Brownell return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, 364af517150SDavid Brownell ext_csd, 512); 365af517150SDavid Brownell } 366ce39f9d1SSeungwon Jeon EXPORT_SYMBOL_GPL(mmc_send_ext_csd); 367af517150SDavid Brownell 368af517150SDavid Brownell int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) 369af517150SDavid Brownell { 3701278dba1SChris Ball struct mmc_command cmd = {0}; 371af517150SDavid Brownell int err; 372af517150SDavid Brownell 373af517150SDavid Brownell cmd.opcode = MMC_SPI_READ_OCR; 374af517150SDavid Brownell cmd.arg = highcap ? (1 << 30) : 0; 375af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R3; 376af517150SDavid Brownell 377af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 378af517150SDavid Brownell 379af517150SDavid Brownell *ocrp = cmd.resp[1]; 380af517150SDavid Brownell return err; 381af517150SDavid Brownell } 382af517150SDavid Brownell 383af517150SDavid Brownell int mmc_spi_set_crc(struct mmc_host *host, int use_crc) 384af517150SDavid Brownell { 3851278dba1SChris Ball struct mmc_command cmd = {0}; 386af517150SDavid Brownell int err; 387af517150SDavid Brownell 388af517150SDavid Brownell cmd.opcode = MMC_SPI_CRC_ON_OFF; 389af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1; 390af517150SDavid Brownell cmd.arg = use_crc; 391af517150SDavid Brownell 392af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 393af517150SDavid Brownell if (!err) 394af517150SDavid Brownell host->use_spi_crc = use_crc; 395af517150SDavid Brownell return err; 396af517150SDavid Brownell } 397af517150SDavid Brownell 398d3a8d95dSAndrei Warkentin /** 399950d56acSJaehoon Chung * __mmc_switch - modify EXT_CSD register 400d3a8d95dSAndrei Warkentin * @card: the MMC card associated with the data transfer 401d3a8d95dSAndrei Warkentin * @set: cmd set values 402d3a8d95dSAndrei Warkentin * @index: EXT_CSD register index 403d3a8d95dSAndrei Warkentin * @value: value to program into EXT_CSD register 404d3a8d95dSAndrei Warkentin * @timeout_ms: timeout (ms) for operation performed by register write, 405d3a8d95dSAndrei Warkentin * timeout of zero implies maximum possible timeout 406950d56acSJaehoon Chung * @use_busy_signal: use the busy signal as response type 407878e200bSUlf Hansson * @send_status: send status cmd to poll for busy 4084509f847SUlf Hansson * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy 409d3a8d95dSAndrei Warkentin * 410d3a8d95dSAndrei Warkentin * Modifies the EXT_CSD register for selected card. 411d3a8d95dSAndrei Warkentin */ 412950d56acSJaehoon Chung int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 4134509f847SUlf Hansson unsigned int timeout_ms, bool use_busy_signal, bool send_status, 4144509f847SUlf Hansson bool ignore_crc) 415da7fbe58SPierre Ossman { 416636bd13cSUlf Hansson struct mmc_host *host = card->host; 417da7fbe58SPierre Ossman int err; 4181278dba1SChris Ball struct mmc_command cmd = {0}; 4198fee476bSTrey Ramsay unsigned long timeout; 420ecd3a7daSUlf Hansson u32 status = 0; 421da7fbe58SPierre Ossman 422da7fbe58SPierre Ossman cmd.opcode = MMC_SWITCH; 423da7fbe58SPierre Ossman cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | 424da7fbe58SPierre Ossman (index << 16) | 425da7fbe58SPierre Ossman (value << 8) | 426da7fbe58SPierre Ossman set; 427950d56acSJaehoon Chung cmd.flags = MMC_CMD_AC; 428950d56acSJaehoon Chung if (use_busy_signal) 429950d56acSJaehoon Chung cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; 430950d56acSJaehoon Chung else 431950d56acSJaehoon Chung cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; 432950d56acSJaehoon Chung 433950d56acSJaehoon Chung 4341d4d7744SUlf Hansson cmd.busy_timeout = timeout_ms; 435775a9362SMaya Erez if (index == EXT_CSD_SANITIZE_START) 436775a9362SMaya Erez cmd.sanitize_busy = true; 437da7fbe58SPierre Ossman 438636bd13cSUlf Hansson err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 43917b0429dSPierre Ossman if (err) 440da7fbe58SPierre Ossman return err; 441da7fbe58SPierre Ossman 442950d56acSJaehoon Chung /* No need to check card status in case of unblocking command */ 443950d56acSJaehoon Chung if (!use_busy_signal) 444950d56acSJaehoon Chung return 0; 445950d56acSJaehoon Chung 446a27fbf2fSSeungwon Jeon /* 4474509f847SUlf Hansson * CRC errors shall only be ignored in cases were CMD13 is used to poll 4484509f847SUlf Hansson * to detect busy completion. 449a27fbf2fSSeungwon Jeon */ 450636bd13cSUlf Hansson if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) 4514509f847SUlf Hansson ignore_crc = false; 452a27fbf2fSSeungwon Jeon 4534509f847SUlf Hansson /* Must check status to be sure of no errors. */ 4548fee476bSTrey Ramsay timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); 455ef0b27d4SAdrian Hunter do { 456878e200bSUlf Hansson if (send_status) { 457a27fbf2fSSeungwon Jeon err = __mmc_send_status(card, &status, ignore_crc); 458ef0b27d4SAdrian Hunter if (err) 459ef0b27d4SAdrian Hunter return err; 460878e200bSUlf Hansson } 461636bd13cSUlf Hansson if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) 462ef0b27d4SAdrian Hunter break; 463636bd13cSUlf Hansson if (mmc_host_is_spi(host)) 464ef0b27d4SAdrian Hunter break; 4658fee476bSTrey Ramsay 466878e200bSUlf Hansson /* 467878e200bSUlf Hansson * We are not allowed to issue a status command and the host 468878e200bSUlf Hansson * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only 469878e200bSUlf Hansson * rely on waiting for the stated timeout to be sufficient. 470878e200bSUlf Hansson */ 471878e200bSUlf Hansson if (!send_status) { 472878e200bSUlf Hansson mmc_delay(timeout_ms); 473878e200bSUlf Hansson return 0; 474878e200bSUlf Hansson } 475878e200bSUlf Hansson 4768fee476bSTrey Ramsay /* Timeout if the device never leaves the program state. */ 4778fee476bSTrey Ramsay if (time_after(jiffies, timeout)) { 4788fee476bSTrey Ramsay pr_err("%s: Card stuck in programming state! %s\n", 479636bd13cSUlf Hansson mmc_hostname(host), __func__); 4808fee476bSTrey Ramsay return -ETIMEDOUT; 4818fee476bSTrey Ramsay } 4827435bb79SJaehoon Chung } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); 483ef0b27d4SAdrian Hunter 484636bd13cSUlf Hansson if (mmc_host_is_spi(host)) { 485ef0b27d4SAdrian Hunter if (status & R1_SPI_ILLEGAL_COMMAND) 486ef0b27d4SAdrian Hunter return -EBADMSG; 487ef0b27d4SAdrian Hunter } else { 488ef0b27d4SAdrian Hunter if (status & 0xFDFFA000) 489636bd13cSUlf Hansson pr_warn("%s: unexpected status %#x after switch\n", 490636bd13cSUlf Hansson mmc_hostname(host), status); 491ef0b27d4SAdrian Hunter if (status & R1_SWITCH_ERROR) 492ef0b27d4SAdrian Hunter return -EBADMSG; 493ef0b27d4SAdrian Hunter } 494ef0b27d4SAdrian Hunter 49517b0429dSPierre Ossman return 0; 496da7fbe58SPierre Ossman } 497950d56acSJaehoon Chung EXPORT_SYMBOL_GPL(__mmc_switch); 498950d56acSJaehoon Chung 499950d56acSJaehoon Chung int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 500950d56acSJaehoon Chung unsigned int timeout_ms) 501950d56acSJaehoon Chung { 5024509f847SUlf Hansson return __mmc_switch(card, set, index, value, timeout_ms, true, true, 5034509f847SUlf Hansson false); 504950d56acSJaehoon Chung } 505d3a8d95dSAndrei Warkentin EXPORT_SYMBOL_GPL(mmc_switch); 506da7fbe58SPierre Ossman 50722113efdSAries Lee static int 50822113efdSAries Lee mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, 50922113efdSAries Lee u8 len) 51022113efdSAries Lee { 511ad5fd972SVenkatraman S struct mmc_request mrq = {NULL}; 5121278dba1SChris Ball struct mmc_command cmd = {0}; 513a61ad2b4SChris Ball struct mmc_data data = {0}; 51422113efdSAries Lee struct scatterlist sg; 51522113efdSAries Lee u8 *data_buf; 51622113efdSAries Lee u8 *test_buf; 51722113efdSAries Lee int i, err; 51822113efdSAries Lee static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 }; 51922113efdSAries Lee static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 }; 52022113efdSAries Lee 52122113efdSAries Lee /* dma onto stack is unsafe/nonportable, but callers to this 52222113efdSAries Lee * routine normally provide temporary on-stack buffers ... 52322113efdSAries Lee */ 52422113efdSAries Lee data_buf = kmalloc(len, GFP_KERNEL); 52522113efdSAries Lee if (!data_buf) 52622113efdSAries Lee return -ENOMEM; 52722113efdSAries Lee 52822113efdSAries Lee if (len == 8) 52922113efdSAries Lee test_buf = testdata_8bit; 53022113efdSAries Lee else if (len == 4) 53122113efdSAries Lee test_buf = testdata_4bit; 53222113efdSAries Lee else { 533a3c76eb9SGirish K S pr_err("%s: Invalid bus_width %d\n", 53422113efdSAries Lee mmc_hostname(host), len); 53522113efdSAries Lee kfree(data_buf); 53622113efdSAries Lee return -EINVAL; 53722113efdSAries Lee } 53822113efdSAries Lee 53922113efdSAries Lee if (opcode == MMC_BUS_TEST_W) 54022113efdSAries Lee memcpy(data_buf, test_buf, len); 54122113efdSAries Lee 54222113efdSAries Lee mrq.cmd = &cmd; 54322113efdSAries Lee mrq.data = &data; 54422113efdSAries Lee cmd.opcode = opcode; 54522113efdSAries Lee cmd.arg = 0; 54622113efdSAries Lee 54722113efdSAries Lee /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we 54822113efdSAries Lee * rely on callers to never use this with "native" calls for reading 54922113efdSAries Lee * CSD or CID. Native versions of those commands use the R2 type, 55022113efdSAries Lee * not R1 plus a data block. 55122113efdSAries Lee */ 55222113efdSAries Lee cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 55322113efdSAries Lee 55422113efdSAries Lee data.blksz = len; 55522113efdSAries Lee data.blocks = 1; 55622113efdSAries Lee if (opcode == MMC_BUS_TEST_R) 55722113efdSAries Lee data.flags = MMC_DATA_READ; 55822113efdSAries Lee else 55922113efdSAries Lee data.flags = MMC_DATA_WRITE; 56022113efdSAries Lee 56122113efdSAries Lee data.sg = &sg; 56222113efdSAries Lee data.sg_len = 1; 56384532e33SMinjian Wu mmc_set_data_timeout(&data, card); 56422113efdSAries Lee sg_init_one(&sg, data_buf, len); 56522113efdSAries Lee mmc_wait_for_req(host, &mrq); 56622113efdSAries Lee err = 0; 56722113efdSAries Lee if (opcode == MMC_BUS_TEST_R) { 56822113efdSAries Lee for (i = 0; i < len / 4; i++) 56922113efdSAries Lee if ((test_buf[i] ^ data_buf[i]) != 0xff) { 57022113efdSAries Lee err = -EIO; 57122113efdSAries Lee break; 57222113efdSAries Lee } 57322113efdSAries Lee } 57422113efdSAries Lee kfree(data_buf); 57522113efdSAries Lee 57622113efdSAries Lee if (cmd.error) 57722113efdSAries Lee return cmd.error; 57822113efdSAries Lee if (data.error) 57922113efdSAries Lee return data.error; 58022113efdSAries Lee 58122113efdSAries Lee return err; 58222113efdSAries Lee } 58322113efdSAries Lee 58422113efdSAries Lee int mmc_bus_test(struct mmc_card *card, u8 bus_width) 58522113efdSAries Lee { 58622113efdSAries Lee int err, width; 58722113efdSAries Lee 58822113efdSAries Lee if (bus_width == MMC_BUS_WIDTH_8) 58922113efdSAries Lee width = 8; 59022113efdSAries Lee else if (bus_width == MMC_BUS_WIDTH_4) 59122113efdSAries Lee width = 4; 59222113efdSAries Lee else if (bus_width == MMC_BUS_WIDTH_1) 59322113efdSAries Lee return 0; /* no need for test */ 59422113efdSAries Lee else 59522113efdSAries Lee return -EINVAL; 59622113efdSAries Lee 59722113efdSAries Lee /* 59822113efdSAries Lee * Ignore errors from BUS_TEST_W. BUS_TEST_R will fail if there 59922113efdSAries Lee * is a problem. This improves chances that the test will work. 60022113efdSAries Lee */ 60122113efdSAries Lee mmc_send_bus_test(card, card->host, MMC_BUS_TEST_W, width); 60222113efdSAries Lee err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); 60322113efdSAries Lee return err; 60422113efdSAries Lee } 605eb0d8f13SJaehoon Chung 606eb0d8f13SJaehoon Chung int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) 607eb0d8f13SJaehoon Chung { 608eb0d8f13SJaehoon Chung struct mmc_command cmd = {0}; 609eb0d8f13SJaehoon Chung unsigned int opcode; 610eb0d8f13SJaehoon Chung int err; 611eb0d8f13SJaehoon Chung 6122378975bSJaehoon Chung if (!card->ext_csd.hpi) { 6132378975bSJaehoon Chung pr_warning("%s: Card didn't support HPI command\n", 6142378975bSJaehoon Chung mmc_hostname(card->host)); 6152378975bSJaehoon Chung return -EINVAL; 6162378975bSJaehoon Chung } 6172378975bSJaehoon Chung 618eb0d8f13SJaehoon Chung opcode = card->ext_csd.hpi_cmd; 619eb0d8f13SJaehoon Chung if (opcode == MMC_STOP_TRANSMISSION) 6202378975bSJaehoon Chung cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 621eb0d8f13SJaehoon Chung else if (opcode == MMC_SEND_STATUS) 6222378975bSJaehoon Chung cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 623eb0d8f13SJaehoon Chung 624eb0d8f13SJaehoon Chung cmd.opcode = opcode; 625eb0d8f13SJaehoon Chung cmd.arg = card->rca << 16 | 1; 626eb0d8f13SJaehoon Chung 627eb0d8f13SJaehoon Chung err = mmc_wait_for_cmd(card->host, &cmd, 0); 628eb0d8f13SJaehoon Chung if (err) { 629eb0d8f13SJaehoon Chung pr_warn("%s: error %d interrupting operation. " 630eb0d8f13SJaehoon Chung "HPI command response %#x\n", mmc_hostname(card->host), 631eb0d8f13SJaehoon Chung err, cmd.resp[0]); 632eb0d8f13SJaehoon Chung return err; 633eb0d8f13SJaehoon Chung } 634eb0d8f13SJaehoon Chung if (status) 635eb0d8f13SJaehoon Chung *status = cmd.resp[0]; 636eb0d8f13SJaehoon Chung 637eb0d8f13SJaehoon Chung return 0; 638eb0d8f13SJaehoon Chung } 639