12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2da7fbe58SPierre Ossman /*
370f10482SPierre Ossman * linux/drivers/mmc/core/sd_ops.h
4da7fbe58SPierre Ossman *
5da7fbe58SPierre Ossman * Copyright 2006-2007 Pierre Ossman
6da7fbe58SPierre Ossman */
7da7fbe58SPierre Ossman
84f665cb6SYoshihiro Shimoda #include <linux/slab.h>
9da7fbe58SPierre Ossman #include <linux/types.h>
103ef77af1SPaul Gortmaker #include <linux/export.h>
11da7fbe58SPierre Ossman #include <linux/scatterlist.h>
12da7fbe58SPierre Ossman
13da7fbe58SPierre Ossman #include <linux/mmc/host.h>
14da7fbe58SPierre Ossman #include <linux/mmc/card.h>
15da7fbe58SPierre Ossman #include <linux/mmc/mmc.h>
16da7fbe58SPierre Ossman #include <linux/mmc/sd.h>
17da7fbe58SPierre Ossman
18da7fbe58SPierre Ossman #include "core.h"
19da7fbe58SPierre Ossman #include "sd_ops.h"
2041e84fe1SUlf Hansson #include "mmc_ops.h"
21da7fbe58SPierre Ossman
mmc_app_cmd(struct mmc_host * host,struct mmc_card * card)22cb87ea28SJohn Calixto int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
2339361851SAdrian Bunk {
2439361851SAdrian Bunk int err;
25c7836d15SMasahiro Yamada struct mmc_command cmd = {};
2639361851SAdrian Bunk
27349583d6SShawn Lin if (WARN_ON(card && card->host != host))
28349583d6SShawn Lin return -EINVAL;
2939361851SAdrian Bunk
3039361851SAdrian Bunk cmd.opcode = MMC_APP_CMD;
3139361851SAdrian Bunk
3239361851SAdrian Bunk if (card) {
3339361851SAdrian Bunk cmd.arg = card->rca << 16;
34af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
3539361851SAdrian Bunk } else {
3639361851SAdrian Bunk cmd.arg = 0;
37af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_BCR;
3839361851SAdrian Bunk }
3939361851SAdrian Bunk
4039361851SAdrian Bunk err = mmc_wait_for_cmd(host, &cmd, 0);
4117b0429dSPierre Ossman if (err)
4239361851SAdrian Bunk return err;
4339361851SAdrian Bunk
4439361851SAdrian Bunk /* Check that card supported application commands */
45af517150SDavid Brownell if (!mmc_host_is_spi(host) && !(cmd.resp[0] & R1_APP_CMD))
4617b0429dSPierre Ossman return -EOPNOTSUPP;
4739361851SAdrian Bunk
4817b0429dSPierre Ossman return 0;
4939361851SAdrian Bunk }
50cb87ea28SJohn Calixto EXPORT_SYMBOL_GPL(mmc_app_cmd);
5139361851SAdrian Bunk
mmc_wait_for_app_cmd(struct mmc_host * host,struct mmc_card * card,struct mmc_command * cmd)529a4b869bSUlf Hansson static int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
5303cd5c05SUlf Hansson struct mmc_command *cmd)
54da7fbe58SPierre Ossman {
55c7836d15SMasahiro Yamada struct mmc_request mrq = {};
5603cd5c05SUlf Hansson int i, err = -EIO;
57da7fbe58SPierre Ossman
58da7fbe58SPierre Ossman /*
59da7fbe58SPierre Ossman * We have to resend MMC_APP_CMD for each attempt so
60da7fbe58SPierre Ossman * we cannot use the retries field in mmc_command.
61da7fbe58SPierre Ossman */
6203cd5c05SUlf Hansson for (i = 0; i <= MMC_CMD_RETRIES; i++) {
63da7fbe58SPierre Ossman err = mmc_app_cmd(host, card);
64af517150SDavid Brownell if (err) {
65af517150SDavid Brownell /* no point in retrying; no APP commands allowed */
66af517150SDavid Brownell if (mmc_host_is_spi(host)) {
67af517150SDavid Brownell if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
68af517150SDavid Brownell break;
69af517150SDavid Brownell }
70da7fbe58SPierre Ossman continue;
71af517150SDavid Brownell }
72da7fbe58SPierre Ossman
73da7fbe58SPierre Ossman memset(&mrq, 0, sizeof(struct mmc_request));
74da7fbe58SPierre Ossman
75da7fbe58SPierre Ossman memset(cmd->resp, 0, sizeof(cmd->resp));
76da7fbe58SPierre Ossman cmd->retries = 0;
77da7fbe58SPierre Ossman
78da7fbe58SPierre Ossman mrq.cmd = cmd;
79da7fbe58SPierre Ossman cmd->data = NULL;
80da7fbe58SPierre Ossman
81da7fbe58SPierre Ossman mmc_wait_for_req(host, &mrq);
82da7fbe58SPierre Ossman
83da7fbe58SPierre Ossman err = cmd->error;
8417b0429dSPierre Ossman if (!cmd->error)
85da7fbe58SPierre Ossman break;
86af517150SDavid Brownell
87af517150SDavid Brownell /* no point in retrying illegal APP commands */
88af517150SDavid Brownell if (mmc_host_is_spi(host)) {
89af517150SDavid Brownell if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
90af517150SDavid Brownell break;
91af517150SDavid Brownell }
92da7fbe58SPierre Ossman }
93da7fbe58SPierre Ossman
94da7fbe58SPierre Ossman return err;
95da7fbe58SPierre Ossman }
96da7fbe58SPierre Ossman
mmc_app_set_bus_width(struct mmc_card * card,int width)97da7fbe58SPierre Ossman int mmc_app_set_bus_width(struct mmc_card *card, int width)
98da7fbe58SPierre Ossman {
99c7836d15SMasahiro Yamada struct mmc_command cmd = {};
100da7fbe58SPierre Ossman
101da7fbe58SPierre Ossman cmd.opcode = SD_APP_SET_BUS_WIDTH;
102da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
103da7fbe58SPierre Ossman
104da7fbe58SPierre Ossman switch (width) {
105da7fbe58SPierre Ossman case MMC_BUS_WIDTH_1:
106da7fbe58SPierre Ossman cmd.arg = SD_BUS_WIDTH_1;
107da7fbe58SPierre Ossman break;
108da7fbe58SPierre Ossman case MMC_BUS_WIDTH_4:
109da7fbe58SPierre Ossman cmd.arg = SD_BUS_WIDTH_4;
110da7fbe58SPierre Ossman break;
111da7fbe58SPierre Ossman default:
11217b0429dSPierre Ossman return -EINVAL;
113da7fbe58SPierre Ossman }
114da7fbe58SPierre Ossman
11503cd5c05SUlf Hansson return mmc_wait_for_app_cmd(card->host, card, &cmd);
116da7fbe58SPierre Ossman }
117da7fbe58SPierre Ossman
mmc_send_app_op_cond(struct mmc_host * host,u32 ocr,u32 * rocr)118da7fbe58SPierre Ossman int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
119da7fbe58SPierre Ossman {
120c7836d15SMasahiro Yamada struct mmc_command cmd = {};
121da7fbe58SPierre Ossman int i, err = 0;
122da7fbe58SPierre Ossman
123da7fbe58SPierre Ossman cmd.opcode = SD_APP_OP_COND;
124af517150SDavid Brownell if (mmc_host_is_spi(host))
125af517150SDavid Brownell cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
126af517150SDavid Brownell else
127da7fbe58SPierre Ossman cmd.arg = ocr;
128af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
129da7fbe58SPierre Ossman
130da7fbe58SPierre Ossman for (i = 100; i; i--) {
13103cd5c05SUlf Hansson err = mmc_wait_for_app_cmd(host, NULL, &cmd);
13217b0429dSPierre Ossman if (err)
133da7fbe58SPierre Ossman break;
134da7fbe58SPierre Ossman
135af517150SDavid Brownell /* if we're just probing, do a single pass */
136af517150SDavid Brownell if (ocr == 0)
137da7fbe58SPierre Ossman break;
138da7fbe58SPierre Ossman
139af517150SDavid Brownell /* otherwise wait until reset completes */
140af517150SDavid Brownell if (mmc_host_is_spi(host)) {
141af517150SDavid Brownell if (!(cmd.resp[0] & R1_SPI_IDLE))
142af517150SDavid Brownell break;
143af517150SDavid Brownell } else {
144af517150SDavid Brownell if (cmd.resp[0] & MMC_CARD_BUSY)
145af517150SDavid Brownell break;
146af517150SDavid Brownell }
147af517150SDavid Brownell
14817b0429dSPierre Ossman err = -ETIMEDOUT;
149da7fbe58SPierre Ossman
150da7fbe58SPierre Ossman mmc_delay(10);
151da7fbe58SPierre Ossman }
152da7fbe58SPierre Ossman
1535e863662SJohan Rudholm if (!i)
1545e863662SJohan Rudholm pr_err("%s: card never left busy state\n", mmc_hostname(host));
1555e863662SJohan Rudholm
156af517150SDavid Brownell if (rocr && !mmc_host_is_spi(host))
157da7fbe58SPierre Ossman *rocr = cmd.resp[0];
158da7fbe58SPierre Ossman
159da7fbe58SPierre Ossman return err;
160da7fbe58SPierre Ossman }
161da7fbe58SPierre Ossman
__mmc_send_if_cond(struct mmc_host * host,u32 ocr,u8 pcie_bits,u32 * resp)162ead49373SUlf Hansson static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits,
163ead49373SUlf Hansson u32 *resp)
164da7fbe58SPierre Ossman {
165c7836d15SMasahiro Yamada struct mmc_command cmd = {};
166da7fbe58SPierre Ossman int err;
167da7fbe58SPierre Ossman static const u8 test_pattern = 0xAA;
168af517150SDavid Brownell u8 result_pattern;
169da7fbe58SPierre Ossman
170da7fbe58SPierre Ossman /*
171da7fbe58SPierre Ossman * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
172da7fbe58SPierre Ossman * before SD_APP_OP_COND. This command will harmlessly fail for
173da7fbe58SPierre Ossman * SD 1.0 cards.
174da7fbe58SPierre Ossman */
175da7fbe58SPierre Ossman cmd.opcode = SD_SEND_IF_COND;
176ead49373SUlf Hansson cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 | test_pattern;
177af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR;
178da7fbe58SPierre Ossman
179da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, 0);
18017b0429dSPierre Ossman if (err)
181da7fbe58SPierre Ossman return err;
182da7fbe58SPierre Ossman
183af517150SDavid Brownell if (mmc_host_is_spi(host))
184af517150SDavid Brownell result_pattern = cmd.resp[1] & 0xFF;
185af517150SDavid Brownell else
186af517150SDavid Brownell result_pattern = cmd.resp[0] & 0xFF;
187af517150SDavid Brownell
188af517150SDavid Brownell if (result_pattern != test_pattern)
18917b0429dSPierre Ossman return -EIO;
190da7fbe58SPierre Ossman
191ead49373SUlf Hansson if (resp)
192ead49373SUlf Hansson *resp = cmd.resp[0];
193ead49373SUlf Hansson
194ead49373SUlf Hansson return 0;
195ead49373SUlf Hansson }
196ead49373SUlf Hansson
mmc_send_if_cond(struct mmc_host * host,u32 ocr)197ead49373SUlf Hansson int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
198ead49373SUlf Hansson {
199ead49373SUlf Hansson return __mmc_send_if_cond(host, ocr, 0, NULL);
200ead49373SUlf Hansson }
201ead49373SUlf Hansson
mmc_send_if_cond_pcie(struct mmc_host * host,u32 ocr)202ead49373SUlf Hansson int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr)
203ead49373SUlf Hansson {
204ead49373SUlf Hansson u32 resp = 0;
205ead49373SUlf Hansson u8 pcie_bits = 0;
206ead49373SUlf Hansson int ret;
207ead49373SUlf Hansson
208ead49373SUlf Hansson if (host->caps2 & MMC_CAP2_SD_EXP) {
209ead49373SUlf Hansson /* Probe card for SD express support via PCIe. */
210ead49373SUlf Hansson pcie_bits = 0x10;
211ead49373SUlf Hansson if (host->caps2 & MMC_CAP2_SD_EXP_1_2V)
212ead49373SUlf Hansson /* Probe also for 1.2V support. */
213ead49373SUlf Hansson pcie_bits = 0x30;
214ead49373SUlf Hansson }
215ead49373SUlf Hansson
216ead49373SUlf Hansson ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp);
217ead49373SUlf Hansson if (ret)
218ead49373SUlf Hansson return 0;
219ead49373SUlf Hansson
220ead49373SUlf Hansson /* Continue with the SD express init, if the card supports it. */
221ead49373SUlf Hansson resp &= 0x3000;
222ead49373SUlf Hansson if (pcie_bits && resp) {
223ead49373SUlf Hansson if (resp == 0x3000)
224ead49373SUlf Hansson host->ios.timing = MMC_TIMING_SD_EXP_1_2V;
225ead49373SUlf Hansson else
226ead49373SUlf Hansson host->ios.timing = MMC_TIMING_SD_EXP;
227ead49373SUlf Hansson
228ead49373SUlf Hansson /*
229ead49373SUlf Hansson * According to the spec the clock shall also be gated, but
230ead49373SUlf Hansson * let's leave this to the host driver for more flexibility.
231ead49373SUlf Hansson */
232ead49373SUlf Hansson return host->ops->init_sd_express(host, &host->ios);
233ead49373SUlf Hansson }
234ead49373SUlf Hansson
23517b0429dSPierre Ossman return 0;
236da7fbe58SPierre Ossman }
237da7fbe58SPierre Ossman
mmc_send_relative_addr(struct mmc_host * host,unsigned int * rca)238da7fbe58SPierre Ossman int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
239da7fbe58SPierre Ossman {
240da7fbe58SPierre Ossman int err;
241c7836d15SMasahiro Yamada struct mmc_command cmd = {};
242da7fbe58SPierre Ossman
243da7fbe58SPierre Ossman cmd.opcode = SD_SEND_RELATIVE_ADDR;
244da7fbe58SPierre Ossman cmd.arg = 0;
245da7fbe58SPierre Ossman cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
246da7fbe58SPierre Ossman
247da7fbe58SPierre Ossman err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
24817b0429dSPierre Ossman if (err)
249da7fbe58SPierre Ossman return err;
250da7fbe58SPierre Ossman
251da7fbe58SPierre Ossman *rca = cmd.resp[0] >> 16;
252da7fbe58SPierre Ossman
25317b0429dSPierre Ossman return 0;
254da7fbe58SPierre Ossman }
255da7fbe58SPierre Ossman
mmc_app_send_scr(struct mmc_card * card)25606c9ccb7SWinkler, Tomas int mmc_app_send_scr(struct mmc_card *card)
257da7fbe58SPierre Ossman {
258da7fbe58SPierre Ossman int err;
259c7836d15SMasahiro Yamada struct mmc_request mrq = {};
260c7836d15SMasahiro Yamada struct mmc_command cmd = {};
261c7836d15SMasahiro Yamada struct mmc_data data = {};
262da7fbe58SPierre Ossman struct scatterlist sg;
26306c9ccb7SWinkler, Tomas __be32 *scr;
264da7fbe58SPierre Ossman
265af517150SDavid Brownell /* NOTE: caller guarantees scr is heap-allocated */
266af517150SDavid Brownell
267da7fbe58SPierre Ossman err = mmc_app_cmd(card->host, card);
26817b0429dSPierre Ossman if (err)
269da7fbe58SPierre Ossman return err;
270da7fbe58SPierre Ossman
2714f665cb6SYoshihiro Shimoda /* dma onto stack is unsafe/nonportable, but callers to this
2724f665cb6SYoshihiro Shimoda * routine normally provide temporary on-stack buffers ...
2734f665cb6SYoshihiro Shimoda */
27406c9ccb7SWinkler, Tomas scr = kmalloc(sizeof(card->raw_scr), GFP_KERNEL);
27506c9ccb7SWinkler, Tomas if (!scr)
2764f665cb6SYoshihiro Shimoda return -ENOMEM;
2774f665cb6SYoshihiro Shimoda
278da7fbe58SPierre Ossman mrq.cmd = &cmd;
279da7fbe58SPierre Ossman mrq.data = &data;
280da7fbe58SPierre Ossman
281da7fbe58SPierre Ossman cmd.opcode = SD_APP_SEND_SCR;
282da7fbe58SPierre Ossman cmd.arg = 0;
283af517150SDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
284da7fbe58SPierre Ossman
285da7fbe58SPierre Ossman data.blksz = 8;
286da7fbe58SPierre Ossman data.blocks = 1;
287da7fbe58SPierre Ossman data.flags = MMC_DATA_READ;
288da7fbe58SPierre Ossman data.sg = &sg;
289da7fbe58SPierre Ossman data.sg_len = 1;
290da7fbe58SPierre Ossman
29106c9ccb7SWinkler, Tomas sg_init_one(&sg, scr, 8);
292da7fbe58SPierre Ossman
293b146d26aSPierre Ossman mmc_set_data_timeout(&data, card);
294da7fbe58SPierre Ossman
295da7fbe58SPierre Ossman mmc_wait_for_req(card->host, &mrq);
296da7fbe58SPierre Ossman
29706c9ccb7SWinkler, Tomas card->raw_scr[0] = be32_to_cpu(scr[0]);
29806c9ccb7SWinkler, Tomas card->raw_scr[1] = be32_to_cpu(scr[1]);
29906c9ccb7SWinkler, Tomas
30006c9ccb7SWinkler, Tomas kfree(scr);
3014f665cb6SYoshihiro Shimoda
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
mmc_sd_switch(struct mmc_card * card,int mode,int group,u8 value,u8 * resp)310da7fbe58SPierre Ossman int mmc_sd_switch(struct mmc_card *card, int mode, int group,
311da7fbe58SPierre Ossman u8 value, u8 *resp)
312da7fbe58SPierre Ossman {
31341e84fe1SUlf Hansson u32 cmd_args;
314da7fbe58SPierre Ossman
315af517150SDavid Brownell /* NOTE: caller guarantees resp is heap-allocated */
316af517150SDavid Brownell
317da7fbe58SPierre Ossman mode = !!mode;
318da7fbe58SPierre Ossman value &= 0xF;
31941e84fe1SUlf Hansson cmd_args = mode << 31 | 0x00FFFFFF;
32041e84fe1SUlf Hansson cmd_args &= ~(0xF << (group * 4));
32141e84fe1SUlf Hansson cmd_args |= value << (group * 4);
322da7fbe58SPierre Ossman
32341e84fe1SUlf Hansson return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp,
32441e84fe1SUlf Hansson 64);
325da7fbe58SPierre Ossman }
326*bac80683SWenchao Chen EXPORT_SYMBOL_GPL(mmc_sd_switch);
327da7fbe58SPierre Ossman
mmc_app_sd_status(struct mmc_card * card,void * ssr)328dfe86cbaSAdrian Hunter int mmc_app_sd_status(struct mmc_card *card, void *ssr)
329dfe86cbaSAdrian Hunter {
330dfe86cbaSAdrian Hunter int err;
331c7836d15SMasahiro Yamada struct mmc_request mrq = {};
332c7836d15SMasahiro Yamada struct mmc_command cmd = {};
333c7836d15SMasahiro Yamada struct mmc_data data = {};
334dfe86cbaSAdrian Hunter struct scatterlist sg;
335dfe86cbaSAdrian Hunter
336dfe86cbaSAdrian Hunter /* NOTE: caller guarantees ssr is heap-allocated */
337dfe86cbaSAdrian Hunter
338dfe86cbaSAdrian Hunter err = mmc_app_cmd(card->host, card);
339dfe86cbaSAdrian Hunter if (err)
340dfe86cbaSAdrian Hunter return err;
341dfe86cbaSAdrian Hunter
342dfe86cbaSAdrian Hunter mrq.cmd = &cmd;
343dfe86cbaSAdrian Hunter mrq.data = &data;
344dfe86cbaSAdrian Hunter
345dfe86cbaSAdrian Hunter cmd.opcode = SD_APP_SD_STATUS;
346dfe86cbaSAdrian Hunter cmd.arg = 0;
347dfe86cbaSAdrian Hunter cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_ADTC;
348dfe86cbaSAdrian Hunter
349dfe86cbaSAdrian Hunter data.blksz = 64;
350dfe86cbaSAdrian Hunter data.blocks = 1;
351dfe86cbaSAdrian Hunter data.flags = MMC_DATA_READ;
352dfe86cbaSAdrian Hunter data.sg = &sg;
353dfe86cbaSAdrian Hunter data.sg_len = 1;
354dfe86cbaSAdrian Hunter
355dfe86cbaSAdrian Hunter sg_init_one(&sg, ssr, 64);
356dfe86cbaSAdrian Hunter
357dfe86cbaSAdrian Hunter mmc_set_data_timeout(&data, card);
358dfe86cbaSAdrian Hunter
359dfe86cbaSAdrian Hunter mmc_wait_for_req(card->host, &mrq);
360dfe86cbaSAdrian Hunter
361dfe86cbaSAdrian Hunter if (cmd.error)
362dfe86cbaSAdrian Hunter return cmd.error;
363dfe86cbaSAdrian Hunter if (data.error)
364dfe86cbaSAdrian Hunter return data.error;
365dfe86cbaSAdrian Hunter
366dfe86cbaSAdrian Hunter return 0;
367dfe86cbaSAdrian Hunter }
368