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" 22c6dbab9cSAdrian Hunter #include "host.h" 23da7fbe58SPierre Ossman #include "mmc_ops.h" 24da7fbe58SPierre Ossman 258fee476bSTrey Ramsay #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ 268fee476bSTrey Ramsay 2704cdbbfaSUlf Hansson static const u8 tuning_blk_pattern_4bit[] = { 2804cdbbfaSUlf Hansson 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, 2904cdbbfaSUlf Hansson 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, 3004cdbbfaSUlf Hansson 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, 3104cdbbfaSUlf Hansson 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, 3204cdbbfaSUlf Hansson 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, 3304cdbbfaSUlf Hansson 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, 3404cdbbfaSUlf Hansson 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, 3504cdbbfaSUlf Hansson 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, 3604cdbbfaSUlf Hansson }; 3704cdbbfaSUlf Hansson 3804cdbbfaSUlf Hansson static const u8 tuning_blk_pattern_8bit[] = { 3904cdbbfaSUlf Hansson 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 4004cdbbfaSUlf Hansson 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, 4104cdbbfaSUlf Hansson 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, 4204cdbbfaSUlf Hansson 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, 4304cdbbfaSUlf Hansson 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, 4404cdbbfaSUlf Hansson 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 4504cdbbfaSUlf Hansson 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, 4604cdbbfaSUlf Hansson 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, 4704cdbbfaSUlf Hansson 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 4804cdbbfaSUlf Hansson 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 4904cdbbfaSUlf Hansson 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 5004cdbbfaSUlf Hansson 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 5104cdbbfaSUlf Hansson 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 5204cdbbfaSUlf Hansson 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 5304cdbbfaSUlf Hansson 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 5404cdbbfaSUlf Hansson 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 5504cdbbfaSUlf Hansson }; 5604cdbbfaSUlf Hansson 57a27fbf2fSSeungwon Jeon static inline int __mmc_send_status(struct mmc_card *card, u32 *status, 58a27fbf2fSSeungwon Jeon bool ignore_crc) 59a27fbf2fSSeungwon Jeon { 60a27fbf2fSSeungwon Jeon int err; 61a27fbf2fSSeungwon Jeon struct mmc_command cmd = {0}; 62a27fbf2fSSeungwon Jeon 63a27fbf2fSSeungwon Jeon BUG_ON(!card); 64a27fbf2fSSeungwon Jeon BUG_ON(!card->host); 65a27fbf2fSSeungwon Jeon 66a27fbf2fSSeungwon Jeon cmd.opcode = MMC_SEND_STATUS; 67a27fbf2fSSeungwon Jeon if (!mmc_host_is_spi(card->host)) 68a27fbf2fSSeungwon Jeon cmd.arg = card->rca << 16; 69a27fbf2fSSeungwon Jeon cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 70a27fbf2fSSeungwon Jeon if (ignore_crc) 71a27fbf2fSSeungwon Jeon cmd.flags &= ~MMC_RSP_CRC; 72a27fbf2fSSeungwon Jeon 73a27fbf2fSSeungwon Jeon err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 74a27fbf2fSSeungwon Jeon if (err) 75a27fbf2fSSeungwon Jeon return err; 76a27fbf2fSSeungwon Jeon 77a27fbf2fSSeungwon Jeon /* NOTE: callers are required to understand the difference 78a27fbf2fSSeungwon Jeon * between "native" and SPI format status words! 79a27fbf2fSSeungwon Jeon */ 80a27fbf2fSSeungwon Jeon if (status) 81a27fbf2fSSeungwon Jeon *status = cmd.resp[0]; 82a27fbf2fSSeungwon Jeon 83a27fbf2fSSeungwon Jeon return 0; 84a27fbf2fSSeungwon Jeon } 85a27fbf2fSSeungwon Jeon 86a27fbf2fSSeungwon Jeon int mmc_send_status(struct mmc_card *card, u32 *status) 87a27fbf2fSSeungwon Jeon { 88a27fbf2fSSeungwon Jeon return __mmc_send_status(card, status, false); 89a27fbf2fSSeungwon Jeon } 90a27fbf2fSSeungwon Jeon 91da7fbe58SPierre Ossman static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) 92da7fbe58SPierre Ossman { 931278dba1SChris Ball struct mmc_command cmd = {0}; 94da7fbe58SPierre Ossman 95da7fbe58SPierre Ossman BUG_ON(!host); 96da7fbe58SPierre Ossman 97da7fbe58SPierre Ossman cmd.opcode = MMC_SELECT_CARD; 98da7fbe58SPierre Ossman 99da7fbe58SPierre Ossman if (card) { 100da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 101da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 102da7fbe58SPierre Ossman } else { 103da7fbe58SPierre Ossman cmd.arg = 0; 104da7fbe58SPierre Ossman cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; 105da7fbe58SPierre Ossman } 106da7fbe58SPierre Ossman 1070899e741SMasahiro Yamada return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 108da7fbe58SPierre Ossman } 109da7fbe58SPierre Ossman 110da7fbe58SPierre Ossman int mmc_select_card(struct mmc_card *card) 111da7fbe58SPierre Ossman { 112da7fbe58SPierre Ossman BUG_ON(!card); 113da7fbe58SPierre Ossman 114da7fbe58SPierre Ossman return _mmc_select_card(card->host, card); 115da7fbe58SPierre Ossman } 116da7fbe58SPierre Ossman 117da7fbe58SPierre Ossman int mmc_deselect_cards(struct mmc_host *host) 118da7fbe58SPierre Ossman { 119da7fbe58SPierre Ossman return _mmc_select_card(host, NULL); 120da7fbe58SPierre Ossman } 121da7fbe58SPierre Ossman 1223d705d14SSascha Hauer /* 1233d705d14SSascha Hauer * Write the value specified in the device tree or board code into the optional 1243d705d14SSascha Hauer * 16 bit Driver Stage Register. This can be used to tune raise/fall times and 1253d705d14SSascha Hauer * drive strength of the DAT and CMD outputs. The actual meaning of a given 1263d705d14SSascha Hauer * value is hardware dependant. 1273d705d14SSascha Hauer * The presence of the DSR register can be determined from the CSD register, 1283d705d14SSascha Hauer * bit 76. 1293d705d14SSascha Hauer */ 1303d705d14SSascha Hauer int mmc_set_dsr(struct mmc_host *host) 1313d705d14SSascha Hauer { 1323d705d14SSascha Hauer struct mmc_command cmd = {0}; 1333d705d14SSascha Hauer 1343d705d14SSascha Hauer cmd.opcode = MMC_SET_DSR; 1353d705d14SSascha Hauer 1363d705d14SSascha Hauer cmd.arg = (host->dsr << 16) | 0xffff; 1373d705d14SSascha Hauer cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; 1383d705d14SSascha Hauer 1393d705d14SSascha Hauer return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 1403d705d14SSascha Hauer } 1413d705d14SSascha Hauer 142da7fbe58SPierre Ossman int mmc_go_idle(struct mmc_host *host) 143da7fbe58SPierre Ossman { 144da7fbe58SPierre Ossman int err; 1451278dba1SChris Ball struct mmc_command cmd = {0}; 146da7fbe58SPierre Ossman 147af517150SDavid Brownell /* 148af517150SDavid Brownell * Non-SPI hosts need to prevent chipselect going active during 149af517150SDavid Brownell * GO_IDLE; that would put chips into SPI mode. Remind them of 150af517150SDavid Brownell * that in case of hardware that won't pull up DAT3/nCS otherwise. 151af517150SDavid Brownell * 152af517150SDavid Brownell * SPI hosts ignore ios.chip_select; it's managed according to 15325985edcSLucas De Marchi * rules that must accommodate non-MMC slaves which this layer 154af517150SDavid Brownell * won't even know about. 155af517150SDavid Brownell */ 156af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 157da7fbe58SPierre Ossman mmc_set_chip_select(host, MMC_CS_HIGH); 158da7fbe58SPierre Ossman mmc_delay(1); 159af517150SDavid Brownell } 160da7fbe58SPierre Ossman 161da7fbe58SPierre Ossman cmd.opcode = MMC_GO_IDLE_STATE; 162da7fbe58SPierre Ossman cmd.arg = 0; 163af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; 164da7fbe58SPierre Ossman 165da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 166da7fbe58SPierre Ossman 167da7fbe58SPierre Ossman mmc_delay(1); 168da7fbe58SPierre Ossman 169af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 170da7fbe58SPierre Ossman mmc_set_chip_select(host, MMC_CS_DONTCARE); 171da7fbe58SPierre Ossman mmc_delay(1); 172af517150SDavid Brownell } 173af517150SDavid Brownell 174af517150SDavid Brownell host->use_spi_crc = 0; 175da7fbe58SPierre Ossman 176da7fbe58SPierre Ossman return err; 177da7fbe58SPierre Ossman } 178da7fbe58SPierre Ossman 179da7fbe58SPierre Ossman int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) 180da7fbe58SPierre Ossman { 1811278dba1SChris Ball struct mmc_command cmd = {0}; 182da7fbe58SPierre Ossman int i, err = 0; 183da7fbe58SPierre Ossman 184da7fbe58SPierre Ossman BUG_ON(!host); 185da7fbe58SPierre Ossman 186da7fbe58SPierre Ossman cmd.opcode = MMC_SEND_OP_COND; 187af517150SDavid Brownell cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; 188af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; 189da7fbe58SPierre Ossman 190da7fbe58SPierre Ossman for (i = 100; i; i--) { 191da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 19217b0429dSPierre Ossman if (err) 193da7fbe58SPierre Ossman break; 194da7fbe58SPierre Ossman 195af517150SDavid Brownell /* if we're just probing, do a single pass */ 196af517150SDavid Brownell if (ocr == 0) 197da7fbe58SPierre Ossman break; 198da7fbe58SPierre Ossman 199af517150SDavid Brownell /* otherwise wait until reset completes */ 200af517150SDavid Brownell if (mmc_host_is_spi(host)) { 201af517150SDavid Brownell if (!(cmd.resp[0] & R1_SPI_IDLE)) 202af517150SDavid Brownell break; 203af517150SDavid Brownell } else { 204af517150SDavid Brownell if (cmd.resp[0] & MMC_CARD_BUSY) 205af517150SDavid Brownell break; 206af517150SDavid Brownell } 207af517150SDavid Brownell 20817b0429dSPierre Ossman err = -ETIMEDOUT; 209da7fbe58SPierre Ossman 210da7fbe58SPierre Ossman mmc_delay(10); 211da7fbe58SPierre Ossman } 212da7fbe58SPierre Ossman 213af517150SDavid Brownell if (rocr && !mmc_host_is_spi(host)) 214da7fbe58SPierre Ossman *rocr = cmd.resp[0]; 215da7fbe58SPierre Ossman 216da7fbe58SPierre Ossman return err; 217da7fbe58SPierre Ossman } 218da7fbe58SPierre Ossman 219da7fbe58SPierre Ossman int mmc_all_send_cid(struct mmc_host *host, u32 *cid) 220da7fbe58SPierre Ossman { 221da7fbe58SPierre Ossman int err; 2221278dba1SChris Ball struct mmc_command cmd = {0}; 223da7fbe58SPierre Ossman 224da7fbe58SPierre Ossman BUG_ON(!host); 225da7fbe58SPierre Ossman BUG_ON(!cid); 226da7fbe58SPierre Ossman 227da7fbe58SPierre Ossman cmd.opcode = MMC_ALL_SEND_CID; 228da7fbe58SPierre Ossman cmd.arg = 0; 229da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; 230da7fbe58SPierre Ossman 231da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 23217b0429dSPierre Ossman if (err) 233da7fbe58SPierre Ossman return err; 234da7fbe58SPierre Ossman 235da7fbe58SPierre Ossman memcpy(cid, cmd.resp, sizeof(u32) * 4); 236da7fbe58SPierre Ossman 23717b0429dSPierre Ossman return 0; 238da7fbe58SPierre Ossman } 239da7fbe58SPierre Ossman 240da7fbe58SPierre Ossman int mmc_set_relative_addr(struct mmc_card *card) 241da7fbe58SPierre Ossman { 2421278dba1SChris Ball struct mmc_command cmd = {0}; 243da7fbe58SPierre Ossman 244da7fbe58SPierre Ossman BUG_ON(!card); 245da7fbe58SPierre Ossman BUG_ON(!card->host); 246da7fbe58SPierre Ossman 247da7fbe58SPierre Ossman cmd.opcode = MMC_SET_RELATIVE_ADDR; 248da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 249da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 250da7fbe58SPierre Ossman 2510899e741SMasahiro Yamada return mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 252da7fbe58SPierre Ossman } 253da7fbe58SPierre Ossman 254af517150SDavid Brownell static int 255af517150SDavid Brownell mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) 256da7fbe58SPierre Ossman { 257da7fbe58SPierre Ossman int err; 2581278dba1SChris Ball struct mmc_command cmd = {0}; 259da7fbe58SPierre Ossman 260af517150SDavid Brownell BUG_ON(!host); 261af517150SDavid Brownell BUG_ON(!cxd); 262da7fbe58SPierre Ossman 263af517150SDavid Brownell cmd.opcode = opcode; 264af517150SDavid Brownell cmd.arg = arg; 265da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; 266da7fbe58SPierre Ossman 267af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 26817b0429dSPierre Ossman if (err) 269da7fbe58SPierre Ossman return err; 270da7fbe58SPierre Ossman 271af517150SDavid Brownell memcpy(cxd, cmd.resp, sizeof(u32) * 4); 272da7fbe58SPierre Ossman 27317b0429dSPierre Ossman return 0; 274da7fbe58SPierre Ossman } 275da7fbe58SPierre Ossman 2761a41313eSKyungsik Lee /* 2771a41313eSKyungsik Lee * NOTE: void *buf, caller for the buf is required to use DMA-capable 2781a41313eSKyungsik Lee * buffer or on-stack buffer (with some overhead in callee). 2791a41313eSKyungsik Lee */ 280af517150SDavid Brownell static int 281af517150SDavid Brownell mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, 282af517150SDavid Brownell u32 opcode, void *buf, unsigned len) 283da7fbe58SPierre Ossman { 284ad5fd972SVenkatraman S struct mmc_request mrq = {NULL}; 2851278dba1SChris Ball struct mmc_command cmd = {0}; 286a61ad2b4SChris Ball struct mmc_data data = {0}; 287da7fbe58SPierre Ossman struct scatterlist sg; 288da7fbe58SPierre Ossman 289da7fbe58SPierre Ossman mrq.cmd = &cmd; 290da7fbe58SPierre Ossman mrq.data = &data; 291da7fbe58SPierre Ossman 292af517150SDavid Brownell cmd.opcode = opcode; 293da7fbe58SPierre Ossman cmd.arg = 0; 294da7fbe58SPierre Ossman 295af517150SDavid Brownell /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we 296af517150SDavid Brownell * rely on callers to never use this with "native" calls for reading 297af517150SDavid Brownell * CSD or CID. Native versions of those commands use the R2 type, 298af517150SDavid Brownell * not R1 plus a data block. 299af517150SDavid Brownell */ 300af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 301af517150SDavid Brownell 302af517150SDavid Brownell data.blksz = len; 303da7fbe58SPierre Ossman data.blocks = 1; 304da7fbe58SPierre Ossman data.flags = MMC_DATA_READ; 305da7fbe58SPierre Ossman data.sg = &sg; 306da7fbe58SPierre Ossman data.sg_len = 1; 307da7fbe58SPierre Ossman 308601ed60cSUlf Hansson sg_init_one(&sg, buf, len); 309da7fbe58SPierre Ossman 310cda56ac2SAdrian Hunter if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { 3110d3e0460SMatthew Fleming /* 3120d3e0460SMatthew Fleming * The spec states that CSR and CID accesses have a timeout 3130d3e0460SMatthew Fleming * of 64 clock cycles. 3140d3e0460SMatthew Fleming */ 3150d3e0460SMatthew Fleming data.timeout_ns = 0; 3160d3e0460SMatthew Fleming data.timeout_clks = 64; 317cda56ac2SAdrian Hunter } else 318cda56ac2SAdrian Hunter mmc_set_data_timeout(&data, card); 319da7fbe58SPierre Ossman 320af517150SDavid Brownell mmc_wait_for_req(host, &mrq); 321af517150SDavid Brownell 32217b0429dSPierre Ossman if (cmd.error) 323da7fbe58SPierre Ossman return cmd.error; 32417b0429dSPierre Ossman if (data.error) 325da7fbe58SPierre Ossman return data.error; 326da7fbe58SPierre Ossman 32717b0429dSPierre Ossman return 0; 328da7fbe58SPierre Ossman } 329da7fbe58SPierre Ossman 330af517150SDavid Brownell int mmc_send_csd(struct mmc_card *card, u32 *csd) 331af517150SDavid Brownell { 33278e48073SPierre Ossman int ret, i; 3331a41313eSKyungsik Lee u32 *csd_tmp; 33478e48073SPierre Ossman 335af517150SDavid Brownell if (!mmc_host_is_spi(card->host)) 336af517150SDavid Brownell return mmc_send_cxd_native(card->host, card->rca << 16, 337af517150SDavid Brownell csd, MMC_SEND_CSD); 338af517150SDavid Brownell 33922b78700SUlf Hansson csd_tmp = kzalloc(16, GFP_KERNEL); 3401a41313eSKyungsik Lee if (!csd_tmp) 3411a41313eSKyungsik Lee return -ENOMEM; 3421a41313eSKyungsik Lee 3431a41313eSKyungsik Lee ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); 34478e48073SPierre Ossman if (ret) 3451a41313eSKyungsik Lee goto err; 34678e48073SPierre Ossman 34778e48073SPierre Ossman for (i = 0;i < 4;i++) 3481a41313eSKyungsik Lee csd[i] = be32_to_cpu(csd_tmp[i]); 34978e48073SPierre Ossman 3501a41313eSKyungsik Lee err: 3511a41313eSKyungsik Lee kfree(csd_tmp); 3521a41313eSKyungsik Lee return ret; 353af517150SDavid Brownell } 354af517150SDavid Brownell 355af517150SDavid Brownell int mmc_send_cid(struct mmc_host *host, u32 *cid) 356af517150SDavid Brownell { 35778e48073SPierre Ossman int ret, i; 3581a41313eSKyungsik Lee u32 *cid_tmp; 35978e48073SPierre Ossman 360af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 361af517150SDavid Brownell if (!host->card) 362af517150SDavid Brownell return -EINVAL; 363af517150SDavid Brownell return mmc_send_cxd_native(host, host->card->rca << 16, 364af517150SDavid Brownell cid, MMC_SEND_CID); 365af517150SDavid Brownell } 366af517150SDavid Brownell 36722b78700SUlf Hansson cid_tmp = kzalloc(16, GFP_KERNEL); 3681a41313eSKyungsik Lee if (!cid_tmp) 3691a41313eSKyungsik Lee return -ENOMEM; 3701a41313eSKyungsik Lee 3711a41313eSKyungsik Lee ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); 37278e48073SPierre Ossman if (ret) 3731a41313eSKyungsik Lee goto err; 37478e48073SPierre Ossman 37578e48073SPierre Ossman for (i = 0;i < 4;i++) 3761a41313eSKyungsik Lee cid[i] = be32_to_cpu(cid_tmp[i]); 37778e48073SPierre Ossman 3781a41313eSKyungsik Lee err: 3791a41313eSKyungsik Lee kfree(cid_tmp); 3801a41313eSKyungsik Lee return ret; 381af517150SDavid Brownell } 382af517150SDavid Brownell 383e21aa519SUlf Hansson int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) 384e21aa519SUlf Hansson { 385e21aa519SUlf Hansson int err; 386e21aa519SUlf Hansson u8 *ext_csd; 387e21aa519SUlf Hansson 388e21aa519SUlf Hansson if (!card || !new_ext_csd) 389e21aa519SUlf Hansson return -EINVAL; 390e21aa519SUlf Hansson 391e21aa519SUlf Hansson if (!mmc_can_ext_csd(card)) 392e21aa519SUlf Hansson return -EOPNOTSUPP; 393e21aa519SUlf Hansson 394e21aa519SUlf Hansson /* 395e21aa519SUlf Hansson * As the ext_csd is so large and mostly unused, we don't store the 396e21aa519SUlf Hansson * raw block in mmc_card. 397e21aa519SUlf Hansson */ 39822b78700SUlf Hansson ext_csd = kzalloc(512, GFP_KERNEL); 399e21aa519SUlf Hansson if (!ext_csd) 400e21aa519SUlf Hansson return -ENOMEM; 401e21aa519SUlf Hansson 4022fc91e8bSUlf Hansson err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd, 4032fc91e8bSUlf Hansson 512); 404e21aa519SUlf Hansson if (err) 405e21aa519SUlf Hansson kfree(ext_csd); 406e21aa519SUlf Hansson else 407e21aa519SUlf Hansson *new_ext_csd = ext_csd; 408e21aa519SUlf Hansson 409e21aa519SUlf Hansson return err; 410e21aa519SUlf Hansson } 411e21aa519SUlf Hansson EXPORT_SYMBOL_GPL(mmc_get_ext_csd); 412e21aa519SUlf Hansson 413af517150SDavid Brownell int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) 414af517150SDavid Brownell { 4151278dba1SChris Ball struct mmc_command cmd = {0}; 416af517150SDavid Brownell int err; 417af517150SDavid Brownell 418af517150SDavid Brownell cmd.opcode = MMC_SPI_READ_OCR; 419af517150SDavid Brownell cmd.arg = highcap ? (1 << 30) : 0; 420af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R3; 421af517150SDavid Brownell 422af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 423af517150SDavid Brownell 424af517150SDavid Brownell *ocrp = cmd.resp[1]; 425af517150SDavid Brownell return err; 426af517150SDavid Brownell } 427af517150SDavid Brownell 428af517150SDavid Brownell int mmc_spi_set_crc(struct mmc_host *host, int use_crc) 429af517150SDavid Brownell { 4301278dba1SChris Ball struct mmc_command cmd = {0}; 431af517150SDavid Brownell int err; 432af517150SDavid Brownell 433af517150SDavid Brownell cmd.opcode = MMC_SPI_CRC_ON_OFF; 434af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1; 435af517150SDavid Brownell cmd.arg = use_crc; 436af517150SDavid Brownell 437af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 438af517150SDavid Brownell if (!err) 439af517150SDavid Brownell host->use_spi_crc = use_crc; 440af517150SDavid Brownell return err; 441af517150SDavid Brownell } 442af517150SDavid Brownell 44320348d19SUlf Hansson static int mmc_switch_status_error(struct mmc_host *host, u32 status) 444ed16f58dSAdrian Hunter { 445ed16f58dSAdrian Hunter if (mmc_host_is_spi(host)) { 446ed16f58dSAdrian Hunter if (status & R1_SPI_ILLEGAL_COMMAND) 447ed16f58dSAdrian Hunter return -EBADMSG; 448ed16f58dSAdrian Hunter } else { 449ed16f58dSAdrian Hunter if (status & 0xFDFFA000) 450ed16f58dSAdrian Hunter pr_warn("%s: unexpected status %#x after switch\n", 451ed16f58dSAdrian Hunter mmc_hostname(host), status); 452ed16f58dSAdrian Hunter if (status & R1_SWITCH_ERROR) 453ed16f58dSAdrian Hunter return -EBADMSG; 454ed16f58dSAdrian Hunter } 455ed16f58dSAdrian Hunter return 0; 456ed16f58dSAdrian Hunter } 457ed16f58dSAdrian Hunter 45820348d19SUlf Hansson /* Caller must hold re-tuning */ 45920348d19SUlf Hansson int mmc_switch_status(struct mmc_card *card) 46020348d19SUlf Hansson { 46120348d19SUlf Hansson u32 status; 46220348d19SUlf Hansson int err; 46320348d19SUlf Hansson 46420348d19SUlf Hansson err = mmc_send_status(card, &status); 46520348d19SUlf Hansson if (err) 46620348d19SUlf Hansson return err; 46720348d19SUlf Hansson 46820348d19SUlf Hansson return mmc_switch_status_error(card->host, status); 46920348d19SUlf Hansson } 47020348d19SUlf Hansson 471716bdb89SUlf Hansson static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, 472716bdb89SUlf Hansson bool send_status, bool ignore_crc) 473716bdb89SUlf Hansson { 474716bdb89SUlf Hansson struct mmc_host *host = card->host; 475716bdb89SUlf Hansson int err; 476716bdb89SUlf Hansson unsigned long timeout; 477716bdb89SUlf Hansson u32 status = 0; 478716bdb89SUlf Hansson bool expired = false; 479716bdb89SUlf Hansson bool busy = false; 480716bdb89SUlf Hansson 481716bdb89SUlf Hansson /* We have an unspecified cmd timeout, use the fallback value. */ 482716bdb89SUlf Hansson if (!timeout_ms) 483716bdb89SUlf Hansson timeout_ms = MMC_OPS_TIMEOUT_MS; 484716bdb89SUlf Hansson 485716bdb89SUlf Hansson /* 486716bdb89SUlf Hansson * In cases when not allowed to poll by using CMD13 or because we aren't 487716bdb89SUlf Hansson * capable of polling by using ->card_busy(), then rely on waiting the 488716bdb89SUlf Hansson * stated timeout to be sufficient. 489716bdb89SUlf Hansson */ 490716bdb89SUlf Hansson if (!send_status && !host->ops->card_busy) { 491716bdb89SUlf Hansson mmc_delay(timeout_ms); 492716bdb89SUlf Hansson return 0; 493716bdb89SUlf Hansson } 494716bdb89SUlf Hansson 495716bdb89SUlf Hansson timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; 496716bdb89SUlf Hansson do { 497716bdb89SUlf Hansson /* 498716bdb89SUlf Hansson * Due to the possibility of being preempted after 499716bdb89SUlf Hansson * sending the status command, check the expiration 500716bdb89SUlf Hansson * time first. 501716bdb89SUlf Hansson */ 502716bdb89SUlf Hansson expired = time_after(jiffies, timeout); 503716bdb89SUlf Hansson if (send_status) { 504716bdb89SUlf Hansson err = __mmc_send_status(card, &status, ignore_crc); 505716bdb89SUlf Hansson if (err) 506716bdb89SUlf Hansson return err; 507716bdb89SUlf Hansson } 508716bdb89SUlf Hansson if (host->ops->card_busy) { 509716bdb89SUlf Hansson if (!host->ops->card_busy(host)) 510716bdb89SUlf Hansson break; 511716bdb89SUlf Hansson busy = true; 512716bdb89SUlf Hansson } 513716bdb89SUlf Hansson 514716bdb89SUlf Hansson /* Timeout if the device never leaves the program state. */ 515716bdb89SUlf Hansson if (expired && 516716bdb89SUlf Hansson (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) { 517716bdb89SUlf Hansson pr_err("%s: Card stuck in programming state! %s\n", 518716bdb89SUlf Hansson mmc_hostname(host), __func__); 519716bdb89SUlf Hansson return -ETIMEDOUT; 520716bdb89SUlf Hansson } 521716bdb89SUlf Hansson } while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy); 522716bdb89SUlf Hansson 523716bdb89SUlf Hansson err = mmc_switch_status_error(host, status); 524716bdb89SUlf Hansson 525716bdb89SUlf Hansson return err; 526716bdb89SUlf Hansson } 527716bdb89SUlf Hansson 528d3a8d95dSAndrei Warkentin /** 529950d56acSJaehoon Chung * __mmc_switch - modify EXT_CSD register 530d3a8d95dSAndrei Warkentin * @card: the MMC card associated with the data transfer 531d3a8d95dSAndrei Warkentin * @set: cmd set values 532d3a8d95dSAndrei Warkentin * @index: EXT_CSD register index 533d3a8d95dSAndrei Warkentin * @value: value to program into EXT_CSD register 534d3a8d95dSAndrei Warkentin * @timeout_ms: timeout (ms) for operation performed by register write, 535d3a8d95dSAndrei Warkentin * timeout of zero implies maximum possible timeout 536950d56acSJaehoon Chung * @use_busy_signal: use the busy signal as response type 537878e200bSUlf Hansson * @send_status: send status cmd to poll for busy 5384509f847SUlf Hansson * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy 539d3a8d95dSAndrei Warkentin * 540d3a8d95dSAndrei Warkentin * Modifies the EXT_CSD register for selected card. 541d3a8d95dSAndrei Warkentin */ 542950d56acSJaehoon Chung int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 5434509f847SUlf Hansson unsigned int timeout_ms, bool use_busy_signal, bool send_status, 5444509f847SUlf Hansson bool ignore_crc) 545da7fbe58SPierre Ossman { 546636bd13cSUlf Hansson struct mmc_host *host = card->host; 547da7fbe58SPierre Ossman int err; 5481278dba1SChris Ball struct mmc_command cmd = {0}; 549b9ec2616SUlf Hansson bool use_r1b_resp = use_busy_signal; 550b9ec2616SUlf Hansson 551c6dbab9cSAdrian Hunter mmc_retune_hold(host); 552c6dbab9cSAdrian Hunter 553b9ec2616SUlf Hansson /* 554b9ec2616SUlf Hansson * If the cmd timeout and the max_busy_timeout of the host are both 555b9ec2616SUlf Hansson * specified, let's validate them. A failure means we need to prevent 556b9ec2616SUlf Hansson * the host from doing hw busy detection, which is done by converting 557b9ec2616SUlf Hansson * to a R1 response instead of a R1B. 558b9ec2616SUlf Hansson */ 559b9ec2616SUlf Hansson if (timeout_ms && host->max_busy_timeout && 560b9ec2616SUlf Hansson (timeout_ms > host->max_busy_timeout)) 561b9ec2616SUlf Hansson use_r1b_resp = false; 562da7fbe58SPierre Ossman 563da7fbe58SPierre Ossman cmd.opcode = MMC_SWITCH; 564da7fbe58SPierre Ossman cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | 565da7fbe58SPierre Ossman (index << 16) | 566da7fbe58SPierre Ossman (value << 8) | 567da7fbe58SPierre Ossman set; 568950d56acSJaehoon Chung cmd.flags = MMC_CMD_AC; 569b9ec2616SUlf Hansson if (use_r1b_resp) { 570950d56acSJaehoon Chung cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; 571b9ec2616SUlf Hansson /* 572b9ec2616SUlf Hansson * A busy_timeout of zero means the host can decide to use 573b9ec2616SUlf Hansson * whatever value it finds suitable. 574b9ec2616SUlf Hansson */ 5751d4d7744SUlf Hansson cmd.busy_timeout = timeout_ms; 576b9ec2616SUlf Hansson } else { 577b9ec2616SUlf Hansson cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; 578b9ec2616SUlf Hansson } 579b9ec2616SUlf Hansson 580775a9362SMaya Erez if (index == EXT_CSD_SANITIZE_START) 581775a9362SMaya Erez cmd.sanitize_busy = true; 582da7fbe58SPierre Ossman 583636bd13cSUlf Hansson err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 58417b0429dSPierre Ossman if (err) 585c6dbab9cSAdrian Hunter goto out; 586da7fbe58SPierre Ossman 587950d56acSJaehoon Chung /* No need to check card status in case of unblocking command */ 588950d56acSJaehoon Chung if (!use_busy_signal) 589c6dbab9cSAdrian Hunter goto out; 590950d56acSJaehoon Chung 591cb26ce06SUlf Hansson /*If SPI or used HW busy detection above, then we don't need to poll. */ 592cb26ce06SUlf Hansson if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) || 593cb26ce06SUlf Hansson mmc_host_is_spi(host)) { 594cb26ce06SUlf Hansson if (send_status) 595cb26ce06SUlf Hansson err = mmc_switch_status(card); 596cb26ce06SUlf Hansson goto out; 597cb26ce06SUlf Hansson } 598a27fbf2fSSeungwon Jeon 599716bdb89SUlf Hansson /* Let's try to poll to find out when the command is completed. */ 600716bdb89SUlf Hansson err = mmc_poll_for_busy(card, timeout_ms, send_status, ignore_crc); 601c6dbab9cSAdrian Hunter out: 602c6dbab9cSAdrian Hunter mmc_retune_release(host); 603ef0b27d4SAdrian Hunter 604c6dbab9cSAdrian Hunter return err; 605da7fbe58SPierre Ossman } 606950d56acSJaehoon Chung 607950d56acSJaehoon Chung int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 608950d56acSJaehoon Chung unsigned int timeout_ms) 609950d56acSJaehoon Chung { 6104509f847SUlf Hansson return __mmc_switch(card, set, index, value, timeout_ms, true, true, 6114509f847SUlf Hansson false); 612950d56acSJaehoon Chung } 613d3a8d95dSAndrei Warkentin EXPORT_SYMBOL_GPL(mmc_switch); 614da7fbe58SPierre Ossman 6159979dbe5SChaotian Jing int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error) 616996903deSMinda Chen { 617996903deSMinda Chen struct mmc_request mrq = {NULL}; 618996903deSMinda Chen struct mmc_command cmd = {0}; 619996903deSMinda Chen struct mmc_data data = {0}; 620996903deSMinda Chen struct scatterlist sg; 621fe5afb13SUlf Hansson struct mmc_ios *ios = &host->ios; 622996903deSMinda Chen const u8 *tuning_block_pattern; 623996903deSMinda Chen int size, err = 0; 624996903deSMinda Chen u8 *data_buf; 625996903deSMinda Chen 626996903deSMinda Chen if (ios->bus_width == MMC_BUS_WIDTH_8) { 627996903deSMinda Chen tuning_block_pattern = tuning_blk_pattern_8bit; 628996903deSMinda Chen size = sizeof(tuning_blk_pattern_8bit); 629996903deSMinda Chen } else if (ios->bus_width == MMC_BUS_WIDTH_4) { 630996903deSMinda Chen tuning_block_pattern = tuning_blk_pattern_4bit; 631996903deSMinda Chen size = sizeof(tuning_blk_pattern_4bit); 632996903deSMinda Chen } else 633996903deSMinda Chen return -EINVAL; 634996903deSMinda Chen 635996903deSMinda Chen data_buf = kzalloc(size, GFP_KERNEL); 636996903deSMinda Chen if (!data_buf) 637996903deSMinda Chen return -ENOMEM; 638996903deSMinda Chen 639996903deSMinda Chen mrq.cmd = &cmd; 640996903deSMinda Chen mrq.data = &data; 641996903deSMinda Chen 642996903deSMinda Chen cmd.opcode = opcode; 643996903deSMinda Chen cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 644996903deSMinda Chen 645996903deSMinda Chen data.blksz = size; 646996903deSMinda Chen data.blocks = 1; 647996903deSMinda Chen data.flags = MMC_DATA_READ; 648996903deSMinda Chen 649996903deSMinda Chen /* 650996903deSMinda Chen * According to the tuning specs, Tuning process 651996903deSMinda Chen * is normally shorter 40 executions of CMD19, 652996903deSMinda Chen * and timeout value should be shorter than 150 ms 653996903deSMinda Chen */ 654996903deSMinda Chen data.timeout_ns = 150 * NSEC_PER_MSEC; 655996903deSMinda Chen 656996903deSMinda Chen data.sg = &sg; 657996903deSMinda Chen data.sg_len = 1; 658996903deSMinda Chen sg_init_one(&sg, data_buf, size); 659996903deSMinda Chen 660fe5afb13SUlf Hansson mmc_wait_for_req(host, &mrq); 661996903deSMinda Chen 6629979dbe5SChaotian Jing if (cmd_error) 6639979dbe5SChaotian Jing *cmd_error = cmd.error; 6649979dbe5SChaotian Jing 665996903deSMinda Chen if (cmd.error) { 666996903deSMinda Chen err = cmd.error; 667996903deSMinda Chen goto out; 668996903deSMinda Chen } 669996903deSMinda Chen 670996903deSMinda Chen if (data.error) { 671996903deSMinda Chen err = data.error; 672996903deSMinda Chen goto out; 673996903deSMinda Chen } 674996903deSMinda Chen 675996903deSMinda Chen if (memcmp(data_buf, tuning_block_pattern, size)) 676996903deSMinda Chen err = -EIO; 677996903deSMinda Chen 678996903deSMinda Chen out: 679996903deSMinda Chen kfree(data_buf); 680996903deSMinda Chen return err; 681996903deSMinda Chen } 682996903deSMinda Chen EXPORT_SYMBOL_GPL(mmc_send_tuning); 683996903deSMinda Chen 68422113efdSAries Lee static int 68522113efdSAries Lee mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, 68622113efdSAries Lee u8 len) 68722113efdSAries Lee { 688ad5fd972SVenkatraman S struct mmc_request mrq = {NULL}; 6891278dba1SChris Ball struct mmc_command cmd = {0}; 690a61ad2b4SChris Ball struct mmc_data data = {0}; 69122113efdSAries Lee struct scatterlist sg; 69222113efdSAries Lee u8 *data_buf; 69322113efdSAries Lee u8 *test_buf; 69422113efdSAries Lee int i, err; 69522113efdSAries Lee static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 }; 69622113efdSAries Lee static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 }; 69722113efdSAries Lee 69822113efdSAries Lee /* dma onto stack is unsafe/nonportable, but callers to this 69922113efdSAries Lee * routine normally provide temporary on-stack buffers ... 70022113efdSAries Lee */ 70122113efdSAries Lee data_buf = kmalloc(len, GFP_KERNEL); 70222113efdSAries Lee if (!data_buf) 70322113efdSAries Lee return -ENOMEM; 70422113efdSAries Lee 70522113efdSAries Lee if (len == 8) 70622113efdSAries Lee test_buf = testdata_8bit; 70722113efdSAries Lee else if (len == 4) 70822113efdSAries Lee test_buf = testdata_4bit; 70922113efdSAries Lee else { 710a3c76eb9SGirish K S pr_err("%s: Invalid bus_width %d\n", 71122113efdSAries Lee mmc_hostname(host), len); 71222113efdSAries Lee kfree(data_buf); 71322113efdSAries Lee return -EINVAL; 71422113efdSAries Lee } 71522113efdSAries Lee 71622113efdSAries Lee if (opcode == MMC_BUS_TEST_W) 71722113efdSAries Lee memcpy(data_buf, test_buf, len); 71822113efdSAries Lee 71922113efdSAries Lee mrq.cmd = &cmd; 72022113efdSAries Lee mrq.data = &data; 72122113efdSAries Lee cmd.opcode = opcode; 72222113efdSAries Lee cmd.arg = 0; 72322113efdSAries Lee 72422113efdSAries Lee /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we 72522113efdSAries Lee * rely on callers to never use this with "native" calls for reading 72622113efdSAries Lee * CSD or CID. Native versions of those commands use the R2 type, 72722113efdSAries Lee * not R1 plus a data block. 72822113efdSAries Lee */ 72922113efdSAries Lee cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 73022113efdSAries Lee 73122113efdSAries Lee data.blksz = len; 73222113efdSAries Lee data.blocks = 1; 73322113efdSAries Lee if (opcode == MMC_BUS_TEST_R) 73422113efdSAries Lee data.flags = MMC_DATA_READ; 73522113efdSAries Lee else 73622113efdSAries Lee data.flags = MMC_DATA_WRITE; 73722113efdSAries Lee 73822113efdSAries Lee data.sg = &sg; 73922113efdSAries Lee data.sg_len = 1; 74084532e33SMinjian Wu mmc_set_data_timeout(&data, card); 74122113efdSAries Lee sg_init_one(&sg, data_buf, len); 74222113efdSAries Lee mmc_wait_for_req(host, &mrq); 74322113efdSAries Lee err = 0; 74422113efdSAries Lee if (opcode == MMC_BUS_TEST_R) { 74522113efdSAries Lee for (i = 0; i < len / 4; i++) 74622113efdSAries Lee if ((test_buf[i] ^ data_buf[i]) != 0xff) { 74722113efdSAries Lee err = -EIO; 74822113efdSAries Lee break; 74922113efdSAries Lee } 75022113efdSAries Lee } 75122113efdSAries Lee kfree(data_buf); 75222113efdSAries Lee 75322113efdSAries Lee if (cmd.error) 75422113efdSAries Lee return cmd.error; 75522113efdSAries Lee if (data.error) 75622113efdSAries Lee return data.error; 75722113efdSAries Lee 75822113efdSAries Lee return err; 75922113efdSAries Lee } 76022113efdSAries Lee 76122113efdSAries Lee int mmc_bus_test(struct mmc_card *card, u8 bus_width) 76222113efdSAries Lee { 7630899e741SMasahiro Yamada int width; 76422113efdSAries Lee 76522113efdSAries Lee if (bus_width == MMC_BUS_WIDTH_8) 76622113efdSAries Lee width = 8; 76722113efdSAries Lee else if (bus_width == MMC_BUS_WIDTH_4) 76822113efdSAries Lee width = 4; 76922113efdSAries Lee else if (bus_width == MMC_BUS_WIDTH_1) 77022113efdSAries Lee return 0; /* no need for test */ 77122113efdSAries Lee else 77222113efdSAries Lee return -EINVAL; 77322113efdSAries Lee 77422113efdSAries Lee /* 77522113efdSAries Lee * Ignore errors from BUS_TEST_W. BUS_TEST_R will fail if there 77622113efdSAries Lee * is a problem. This improves chances that the test will work. 77722113efdSAries Lee */ 77822113efdSAries Lee mmc_send_bus_test(card, card->host, MMC_BUS_TEST_W, width); 7790899e741SMasahiro Yamada return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); 78022113efdSAries Lee } 781eb0d8f13SJaehoon Chung 782eb0d8f13SJaehoon Chung int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) 783eb0d8f13SJaehoon Chung { 784eb0d8f13SJaehoon Chung struct mmc_command cmd = {0}; 785eb0d8f13SJaehoon Chung unsigned int opcode; 786eb0d8f13SJaehoon Chung int err; 787eb0d8f13SJaehoon Chung 7882378975bSJaehoon Chung if (!card->ext_csd.hpi) { 7896606110dSJoe Perches pr_warn("%s: Card didn't support HPI command\n", 7902378975bSJaehoon Chung mmc_hostname(card->host)); 7912378975bSJaehoon Chung return -EINVAL; 7922378975bSJaehoon Chung } 7932378975bSJaehoon Chung 794eb0d8f13SJaehoon Chung opcode = card->ext_csd.hpi_cmd; 795eb0d8f13SJaehoon Chung if (opcode == MMC_STOP_TRANSMISSION) 7962378975bSJaehoon Chung cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 797eb0d8f13SJaehoon Chung else if (opcode == MMC_SEND_STATUS) 7982378975bSJaehoon Chung cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 799eb0d8f13SJaehoon Chung 800eb0d8f13SJaehoon Chung cmd.opcode = opcode; 801eb0d8f13SJaehoon Chung cmd.arg = card->rca << 16 | 1; 802eb0d8f13SJaehoon Chung 803eb0d8f13SJaehoon Chung err = mmc_wait_for_cmd(card->host, &cmd, 0); 804eb0d8f13SJaehoon Chung if (err) { 805eb0d8f13SJaehoon Chung pr_warn("%s: error %d interrupting operation. " 806eb0d8f13SJaehoon Chung "HPI command response %#x\n", mmc_hostname(card->host), 807eb0d8f13SJaehoon Chung err, cmd.resp[0]); 808eb0d8f13SJaehoon Chung return err; 809eb0d8f13SJaehoon Chung } 810eb0d8f13SJaehoon Chung if (status) 811eb0d8f13SJaehoon Chung *status = cmd.resp[0]; 812eb0d8f13SJaehoon Chung 813eb0d8f13SJaehoon Chung return 0; 814eb0d8f13SJaehoon Chung } 815148bcab2SUlf Hansson 816148bcab2SUlf Hansson int mmc_can_ext_csd(struct mmc_card *card) 817148bcab2SUlf Hansson { 818148bcab2SUlf Hansson return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); 819148bcab2SUlf Hansson } 820