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 12da7fbe58SPierre Ossman #include <linux/types.h> 13da7fbe58SPierre Ossman #include <linux/scatterlist.h> 14da7fbe58SPierre Ossman 15da7fbe58SPierre Ossman #include <linux/mmc/host.h> 16da7fbe58SPierre Ossman #include <linux/mmc/card.h> 17da7fbe58SPierre Ossman #include <linux/mmc/mmc.h> 18da7fbe58SPierre Ossman 19da7fbe58SPierre Ossman #include "core.h" 20da7fbe58SPierre Ossman #include "mmc_ops.h" 21da7fbe58SPierre Ossman 22da7fbe58SPierre Ossman static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) 23da7fbe58SPierre Ossman { 24da7fbe58SPierre Ossman int err; 25da7fbe58SPierre Ossman struct mmc_command cmd; 26da7fbe58SPierre Ossman 27da7fbe58SPierre Ossman BUG_ON(!host); 28da7fbe58SPierre Ossman 29da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 30da7fbe58SPierre Ossman 31da7fbe58SPierre Ossman cmd.opcode = MMC_SELECT_CARD; 32da7fbe58SPierre Ossman 33da7fbe58SPierre Ossman if (card) { 34da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 35da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 36da7fbe58SPierre Ossman } else { 37da7fbe58SPierre Ossman cmd.arg = 0; 38da7fbe58SPierre Ossman cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; 39da7fbe58SPierre Ossman } 40da7fbe58SPierre Ossman 41da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 4217b0429dSPierre Ossman if (err) 43da7fbe58SPierre Ossman return err; 44da7fbe58SPierre Ossman 4517b0429dSPierre Ossman return 0; 46da7fbe58SPierre Ossman } 47da7fbe58SPierre Ossman 48da7fbe58SPierre Ossman int mmc_select_card(struct mmc_card *card) 49da7fbe58SPierre Ossman { 50da7fbe58SPierre Ossman BUG_ON(!card); 51da7fbe58SPierre Ossman 52da7fbe58SPierre Ossman return _mmc_select_card(card->host, card); 53da7fbe58SPierre Ossman } 54da7fbe58SPierre Ossman 55da7fbe58SPierre Ossman int mmc_deselect_cards(struct mmc_host *host) 56da7fbe58SPierre Ossman { 57da7fbe58SPierre Ossman return _mmc_select_card(host, NULL); 58da7fbe58SPierre Ossman } 59da7fbe58SPierre Ossman 60b1ebe384SJarkko Lavinen int mmc_card_sleepawake(struct mmc_host *host, int sleep) 61b1ebe384SJarkko Lavinen { 62b1ebe384SJarkko Lavinen struct mmc_command cmd; 63b1ebe384SJarkko Lavinen struct mmc_card *card = host->card; 64b1ebe384SJarkko Lavinen int err; 65b1ebe384SJarkko Lavinen 66b1ebe384SJarkko Lavinen if (sleep) 67b1ebe384SJarkko Lavinen mmc_deselect_cards(host); 68b1ebe384SJarkko Lavinen 69b1ebe384SJarkko Lavinen memset(&cmd, 0, sizeof(struct mmc_command)); 70b1ebe384SJarkko Lavinen 71b1ebe384SJarkko Lavinen cmd.opcode = MMC_SLEEP_AWAKE; 72b1ebe384SJarkko Lavinen cmd.arg = card->rca << 16; 73b1ebe384SJarkko Lavinen if (sleep) 74b1ebe384SJarkko Lavinen cmd.arg |= 1 << 15; 75b1ebe384SJarkko Lavinen 76b1ebe384SJarkko Lavinen cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 77b1ebe384SJarkko Lavinen err = mmc_wait_for_cmd(host, &cmd, 0); 78b1ebe384SJarkko Lavinen if (err) 79b1ebe384SJarkko Lavinen return err; 80b1ebe384SJarkko Lavinen 81b1ebe384SJarkko Lavinen /* 82b1ebe384SJarkko Lavinen * If the host does not wait while the card signals busy, then we will 83b1ebe384SJarkko Lavinen * will have to wait the sleep/awake timeout. Note, we cannot use the 84b1ebe384SJarkko Lavinen * SEND_STATUS command to poll the status because that command (and most 85b1ebe384SJarkko Lavinen * others) is invalid while the card sleeps. 86b1ebe384SJarkko Lavinen */ 87b1ebe384SJarkko Lavinen if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) 88b1ebe384SJarkko Lavinen mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); 89b1ebe384SJarkko Lavinen 90b1ebe384SJarkko Lavinen if (!sleep) 91b1ebe384SJarkko Lavinen err = mmc_select_card(card); 92b1ebe384SJarkko Lavinen 93b1ebe384SJarkko Lavinen return err; 94b1ebe384SJarkko Lavinen } 95b1ebe384SJarkko Lavinen 96da7fbe58SPierre Ossman int mmc_go_idle(struct mmc_host *host) 97da7fbe58SPierre Ossman { 98da7fbe58SPierre Ossman int err; 99da7fbe58SPierre Ossman struct mmc_command cmd; 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 107af517150SDavid Brownell * rules that must accomodate 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 memset(&cmd, 0, sizeof(struct mmc_command)); 116da7fbe58SPierre Ossman 117da7fbe58SPierre Ossman cmd.opcode = MMC_GO_IDLE_STATE; 118da7fbe58SPierre Ossman cmd.arg = 0; 119af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; 120da7fbe58SPierre Ossman 121da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 122da7fbe58SPierre Ossman 123da7fbe58SPierre Ossman mmc_delay(1); 124da7fbe58SPierre Ossman 125af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 126da7fbe58SPierre Ossman mmc_set_chip_select(host, MMC_CS_DONTCARE); 127da7fbe58SPierre Ossman mmc_delay(1); 128af517150SDavid Brownell } 129af517150SDavid Brownell 130af517150SDavid Brownell host->use_spi_crc = 0; 131da7fbe58SPierre Ossman 132da7fbe58SPierre Ossman return err; 133da7fbe58SPierre Ossman } 134da7fbe58SPierre Ossman 135da7fbe58SPierre Ossman int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) 136da7fbe58SPierre Ossman { 137da7fbe58SPierre Ossman struct mmc_command cmd; 138da7fbe58SPierre Ossman int i, err = 0; 139da7fbe58SPierre Ossman 140da7fbe58SPierre Ossman BUG_ON(!host); 141da7fbe58SPierre Ossman 142da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 143da7fbe58SPierre Ossman 144da7fbe58SPierre Ossman cmd.opcode = MMC_SEND_OP_COND; 145af517150SDavid Brownell cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; 146af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; 147da7fbe58SPierre Ossman 148da7fbe58SPierre Ossman for (i = 100; i; i--) { 149da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0); 15017b0429dSPierre Ossman if (err) 151da7fbe58SPierre Ossman break; 152da7fbe58SPierre Ossman 153af517150SDavid Brownell /* if we're just probing, do a single pass */ 154af517150SDavid Brownell if (ocr == 0) 155da7fbe58SPierre Ossman break; 156da7fbe58SPierre Ossman 157af517150SDavid Brownell /* otherwise wait until reset completes */ 158af517150SDavid Brownell if (mmc_host_is_spi(host)) { 159af517150SDavid Brownell if (!(cmd.resp[0] & R1_SPI_IDLE)) 160af517150SDavid Brownell break; 161af517150SDavid Brownell } else { 162af517150SDavid Brownell if (cmd.resp[0] & MMC_CARD_BUSY) 163af517150SDavid Brownell break; 164af517150SDavid Brownell } 165af517150SDavid Brownell 16617b0429dSPierre Ossman err = -ETIMEDOUT; 167da7fbe58SPierre Ossman 168da7fbe58SPierre Ossman mmc_delay(10); 169da7fbe58SPierre Ossman } 170da7fbe58SPierre Ossman 171af517150SDavid Brownell if (rocr && !mmc_host_is_spi(host)) 172da7fbe58SPierre Ossman *rocr = cmd.resp[0]; 173da7fbe58SPierre Ossman 174da7fbe58SPierre Ossman return err; 175da7fbe58SPierre Ossman } 176da7fbe58SPierre Ossman 177da7fbe58SPierre Ossman int mmc_all_send_cid(struct mmc_host *host, u32 *cid) 178da7fbe58SPierre Ossman { 179da7fbe58SPierre Ossman int err; 180da7fbe58SPierre Ossman struct mmc_command cmd; 181da7fbe58SPierre Ossman 182da7fbe58SPierre Ossman BUG_ON(!host); 183da7fbe58SPierre Ossman BUG_ON(!cid); 184da7fbe58SPierre Ossman 185da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 186da7fbe58SPierre Ossman 187da7fbe58SPierre Ossman cmd.opcode = MMC_ALL_SEND_CID; 188da7fbe58SPierre Ossman cmd.arg = 0; 189da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; 190da7fbe58SPierre Ossman 191da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 19217b0429dSPierre Ossman if (err) 193da7fbe58SPierre Ossman return err; 194da7fbe58SPierre Ossman 195da7fbe58SPierre Ossman memcpy(cid, cmd.resp, sizeof(u32) * 4); 196da7fbe58SPierre Ossman 19717b0429dSPierre Ossman return 0; 198da7fbe58SPierre Ossman } 199da7fbe58SPierre Ossman 200da7fbe58SPierre Ossman int mmc_set_relative_addr(struct mmc_card *card) 201da7fbe58SPierre Ossman { 202da7fbe58SPierre Ossman int err; 203da7fbe58SPierre Ossman struct mmc_command cmd; 204da7fbe58SPierre Ossman 205da7fbe58SPierre Ossman BUG_ON(!card); 206da7fbe58SPierre Ossman BUG_ON(!card->host); 207da7fbe58SPierre Ossman 208da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 209da7fbe58SPierre Ossman 210da7fbe58SPierre Ossman cmd.opcode = MMC_SET_RELATIVE_ADDR; 211da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 212da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 213da7fbe58SPierre Ossman 214da7fbe58SPierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 21517b0429dSPierre Ossman if (err) 216da7fbe58SPierre Ossman return err; 217da7fbe58SPierre Ossman 21817b0429dSPierre Ossman return 0; 219da7fbe58SPierre Ossman } 220da7fbe58SPierre Ossman 221af517150SDavid Brownell static int 222af517150SDavid Brownell mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) 223da7fbe58SPierre Ossman { 224da7fbe58SPierre Ossman int err; 225da7fbe58SPierre Ossman struct mmc_command cmd; 226da7fbe58SPierre Ossman 227af517150SDavid Brownell BUG_ON(!host); 228af517150SDavid Brownell BUG_ON(!cxd); 229da7fbe58SPierre Ossman 230da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 231da7fbe58SPierre Ossman 232af517150SDavid Brownell cmd.opcode = opcode; 233af517150SDavid Brownell cmd.arg = arg; 234da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; 235da7fbe58SPierre Ossman 236af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 23717b0429dSPierre Ossman if (err) 238da7fbe58SPierre Ossman return err; 239da7fbe58SPierre Ossman 240af517150SDavid Brownell memcpy(cxd, cmd.resp, sizeof(u32) * 4); 241da7fbe58SPierre Ossman 24217b0429dSPierre Ossman return 0; 243da7fbe58SPierre Ossman } 244da7fbe58SPierre Ossman 245af517150SDavid Brownell static int 246af517150SDavid Brownell mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, 247af517150SDavid Brownell u32 opcode, void *buf, unsigned len) 248da7fbe58SPierre Ossman { 249da7fbe58SPierre Ossman struct mmc_request mrq; 250da7fbe58SPierre Ossman struct mmc_command cmd; 251da7fbe58SPierre Ossman struct mmc_data data; 252da7fbe58SPierre Ossman struct scatterlist sg; 253af517150SDavid Brownell void *data_buf; 254da7fbe58SPierre Ossman 255af517150SDavid Brownell /* dma onto stack is unsafe/nonportable, but callers to this 256af517150SDavid Brownell * routine normally provide temporary on-stack buffers ... 257af517150SDavid Brownell */ 258af517150SDavid Brownell data_buf = kmalloc(len, GFP_KERNEL); 259af517150SDavid Brownell if (data_buf == NULL) 260af517150SDavid Brownell return -ENOMEM; 261da7fbe58SPierre Ossman 262da7fbe58SPierre Ossman memset(&mrq, 0, sizeof(struct mmc_request)); 263da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 264da7fbe58SPierre Ossman memset(&data, 0, sizeof(struct mmc_data)); 265da7fbe58SPierre Ossman 266da7fbe58SPierre Ossman mrq.cmd = &cmd; 267da7fbe58SPierre Ossman mrq.data = &data; 268da7fbe58SPierre Ossman 269af517150SDavid Brownell cmd.opcode = opcode; 270da7fbe58SPierre Ossman cmd.arg = 0; 271da7fbe58SPierre Ossman 272af517150SDavid Brownell /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we 273af517150SDavid Brownell * rely on callers to never use this with "native" calls for reading 274af517150SDavid Brownell * CSD or CID. Native versions of those commands use the R2 type, 275af517150SDavid Brownell * not R1 plus a data block. 276af517150SDavid Brownell */ 277af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 278af517150SDavid Brownell 279af517150SDavid Brownell data.blksz = len; 280da7fbe58SPierre Ossman data.blocks = 1; 281da7fbe58SPierre Ossman data.flags = MMC_DATA_READ; 282da7fbe58SPierre Ossman data.sg = &sg; 283da7fbe58SPierre Ossman data.sg_len = 1; 284da7fbe58SPierre Ossman 285af517150SDavid Brownell sg_init_one(&sg, data_buf, len); 286da7fbe58SPierre Ossman 287cda56ac2SAdrian Hunter if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { 2880d3e0460SMatthew Fleming /* 2890d3e0460SMatthew Fleming * The spec states that CSR and CID accesses have a timeout 2900d3e0460SMatthew Fleming * of 64 clock cycles. 2910d3e0460SMatthew Fleming */ 2920d3e0460SMatthew Fleming data.timeout_ns = 0; 2930d3e0460SMatthew Fleming data.timeout_clks = 64; 294cda56ac2SAdrian Hunter } else 295cda56ac2SAdrian Hunter mmc_set_data_timeout(&data, card); 296da7fbe58SPierre Ossman 297af517150SDavid Brownell mmc_wait_for_req(host, &mrq); 298af517150SDavid Brownell 299af517150SDavid Brownell memcpy(buf, data_buf, len); 300af517150SDavid Brownell kfree(data_buf); 301da7fbe58SPierre Ossman 30217b0429dSPierre Ossman if (cmd.error) 303da7fbe58SPierre Ossman return cmd.error; 30417b0429dSPierre Ossman if (data.error) 305da7fbe58SPierre Ossman return data.error; 306da7fbe58SPierre Ossman 30717b0429dSPierre Ossman return 0; 308da7fbe58SPierre Ossman } 309da7fbe58SPierre Ossman 310af517150SDavid Brownell int mmc_send_csd(struct mmc_card *card, u32 *csd) 311af517150SDavid Brownell { 31278e48073SPierre Ossman int ret, i; 31378e48073SPierre Ossman 314af517150SDavid Brownell if (!mmc_host_is_spi(card->host)) 315af517150SDavid Brownell return mmc_send_cxd_native(card->host, card->rca << 16, 316af517150SDavid Brownell csd, MMC_SEND_CSD); 317af517150SDavid Brownell 31878e48073SPierre Ossman ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); 31978e48073SPierre Ossman if (ret) 32078e48073SPierre Ossman return ret; 32178e48073SPierre Ossman 32278e48073SPierre Ossman for (i = 0;i < 4;i++) 32378e48073SPierre Ossman csd[i] = be32_to_cpu(csd[i]); 32478e48073SPierre Ossman 32578e48073SPierre Ossman return 0; 326af517150SDavid Brownell } 327af517150SDavid Brownell 328af517150SDavid Brownell int mmc_send_cid(struct mmc_host *host, u32 *cid) 329af517150SDavid Brownell { 33078e48073SPierre Ossman int ret, i; 33178e48073SPierre Ossman 332af517150SDavid Brownell if (!mmc_host_is_spi(host)) { 333af517150SDavid Brownell if (!host->card) 334af517150SDavid Brownell return -EINVAL; 335af517150SDavid Brownell return mmc_send_cxd_native(host, host->card->rca << 16, 336af517150SDavid Brownell cid, MMC_SEND_CID); 337af517150SDavid Brownell } 338af517150SDavid Brownell 33978e48073SPierre Ossman ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); 34078e48073SPierre Ossman if (ret) 34178e48073SPierre Ossman return ret; 34278e48073SPierre Ossman 34378e48073SPierre Ossman for (i = 0;i < 4;i++) 34478e48073SPierre Ossman cid[i] = be32_to_cpu(cid[i]); 34578e48073SPierre Ossman 34678e48073SPierre Ossman return 0; 347af517150SDavid Brownell } 348af517150SDavid Brownell 349af517150SDavid Brownell int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) 350af517150SDavid Brownell { 351af517150SDavid Brownell return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, 352af517150SDavid Brownell ext_csd, 512); 353af517150SDavid Brownell } 354af517150SDavid Brownell 355af517150SDavid Brownell int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) 356af517150SDavid Brownell { 357af517150SDavid Brownell struct mmc_command cmd; 358af517150SDavid Brownell int err; 359af517150SDavid Brownell 360af517150SDavid Brownell memset(&cmd, 0, sizeof(struct mmc_command)); 361af517150SDavid Brownell 362af517150SDavid Brownell cmd.opcode = MMC_SPI_READ_OCR; 363af517150SDavid Brownell cmd.arg = highcap ? (1 << 30) : 0; 364af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R3; 365af517150SDavid Brownell 366af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 367af517150SDavid Brownell 368af517150SDavid Brownell *ocrp = cmd.resp[1]; 369af517150SDavid Brownell return err; 370af517150SDavid Brownell } 371af517150SDavid Brownell 372af517150SDavid Brownell int mmc_spi_set_crc(struct mmc_host *host, int use_crc) 373af517150SDavid Brownell { 374af517150SDavid Brownell struct mmc_command cmd; 375af517150SDavid Brownell int err; 376af517150SDavid Brownell 377af517150SDavid Brownell memset(&cmd, 0, sizeof(struct mmc_command)); 378af517150SDavid Brownell 379af517150SDavid Brownell cmd.opcode = MMC_SPI_CRC_ON_OFF; 380af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1; 381af517150SDavid Brownell cmd.arg = use_crc; 382af517150SDavid Brownell 383af517150SDavid Brownell err = mmc_wait_for_cmd(host, &cmd, 0); 384af517150SDavid Brownell if (!err) 385af517150SDavid Brownell host->use_spi_crc = use_crc; 386af517150SDavid Brownell return err; 387af517150SDavid Brownell } 388af517150SDavid Brownell 389da7fbe58SPierre Ossman int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) 390da7fbe58SPierre Ossman { 391da7fbe58SPierre Ossman int err; 392da7fbe58SPierre Ossman struct mmc_command cmd; 393ef0b27d4SAdrian Hunter u32 status; 394da7fbe58SPierre Ossman 395da7fbe58SPierre Ossman BUG_ON(!card); 396da7fbe58SPierre Ossman BUG_ON(!card->host); 397da7fbe58SPierre Ossman 398da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 399da7fbe58SPierre Ossman 400da7fbe58SPierre Ossman cmd.opcode = MMC_SWITCH; 401da7fbe58SPierre Ossman cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | 402da7fbe58SPierre Ossman (index << 16) | 403da7fbe58SPierre Ossman (value << 8) | 404da7fbe58SPierre Ossman set; 405af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 406da7fbe58SPierre Ossman 407da7fbe58SPierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 40817b0429dSPierre Ossman if (err) 409da7fbe58SPierre Ossman return err; 410da7fbe58SPierre Ossman 411ef0b27d4SAdrian Hunter /* Must check status to be sure of no errors */ 412ef0b27d4SAdrian Hunter do { 413ef0b27d4SAdrian Hunter err = mmc_send_status(card, &status); 414ef0b27d4SAdrian Hunter if (err) 415ef0b27d4SAdrian Hunter return err; 416ef0b27d4SAdrian Hunter if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) 417ef0b27d4SAdrian Hunter break; 418ef0b27d4SAdrian Hunter if (mmc_host_is_spi(card->host)) 419ef0b27d4SAdrian Hunter break; 420ef0b27d4SAdrian Hunter } while (R1_CURRENT_STATE(status) == 7); 421ef0b27d4SAdrian Hunter 422ef0b27d4SAdrian Hunter if (mmc_host_is_spi(card->host)) { 423ef0b27d4SAdrian Hunter if (status & R1_SPI_ILLEGAL_COMMAND) 424ef0b27d4SAdrian Hunter return -EBADMSG; 425ef0b27d4SAdrian Hunter } else { 426ef0b27d4SAdrian Hunter if (status & 0xFDFFA000) 427ef0b27d4SAdrian Hunter printk(KERN_WARNING "%s: unexpected status %#x after " 428ef0b27d4SAdrian Hunter "switch", mmc_hostname(card->host), status); 429ef0b27d4SAdrian Hunter if (status & R1_SWITCH_ERROR) 430ef0b27d4SAdrian Hunter return -EBADMSG; 431ef0b27d4SAdrian Hunter } 432ef0b27d4SAdrian Hunter 43317b0429dSPierre Ossman return 0; 434da7fbe58SPierre Ossman } 435da7fbe58SPierre Ossman 436da7fbe58SPierre Ossman int mmc_send_status(struct mmc_card *card, u32 *status) 437da7fbe58SPierre Ossman { 438da7fbe58SPierre Ossman int err; 439da7fbe58SPierre Ossman struct mmc_command cmd; 440da7fbe58SPierre Ossman 441da7fbe58SPierre Ossman BUG_ON(!card); 442da7fbe58SPierre Ossman BUG_ON(!card->host); 443da7fbe58SPierre Ossman 444da7fbe58SPierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 445da7fbe58SPierre Ossman 446da7fbe58SPierre Ossman cmd.opcode = MMC_SEND_STATUS; 447af517150SDavid Brownell if (!mmc_host_is_spi(card->host)) 448da7fbe58SPierre Ossman cmd.arg = card->rca << 16; 449af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 450da7fbe58SPierre Ossman 451da7fbe58SPierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 45217b0429dSPierre Ossman if (err) 453da7fbe58SPierre Ossman return err; 454da7fbe58SPierre Ossman 455af517150SDavid Brownell /* NOTE: callers are required to understand the difference 456af517150SDavid Brownell * between "native" and SPI format status words! 457af517150SDavid Brownell */ 458da7fbe58SPierre Ossman if (status) 459da7fbe58SPierre Ossman *status = cmd.resp[0]; 460da7fbe58SPierre Ossman 46117b0429dSPierre Ossman return 0; 462da7fbe58SPierre Ossman } 463da7fbe58SPierre Ossman 464