1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * linux/drivers/mmc/sdio_ops.c |
4 | * |
5 | * Copyright 2006-2007 Pierre Ossman |
6 | */ |
7 | |
8 | #include <linux/scatterlist.h> |
9 | |
10 | #include <linux/mmc/host.h> |
11 | #include <linux/mmc/card.h> |
12 | #include <linux/mmc/mmc.h> |
13 | #include <linux/mmc/sdio.h> |
14 | |
15 | #include "core.h" |
16 | #include "sdio_ops.h" |
17 | |
18 | int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) |
19 | { |
20 | struct mmc_command cmd = {}; |
21 | int i, err = 0; |
22 | |
23 | cmd.opcode = SD_IO_SEND_OP_COND; |
24 | cmd.arg = ocr; |
25 | cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; |
26 | |
27 | for (i = 100; i; i--) { |
28 | err = mmc_wait_for_cmd(host, cmd: &cmd, MMC_CMD_RETRIES); |
29 | if (err) |
30 | break; |
31 | |
32 | /* if we're just probing, do a single pass */ |
33 | if (ocr == 0) |
34 | break; |
35 | |
36 | /* otherwise wait until reset completes */ |
37 | if (mmc_host_is_spi(host)) { |
38 | /* |
39 | * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate |
40 | * an initialized card under SPI, but some cards |
41 | * (Marvell's) only behave when looking at this |
42 | * one. |
43 | */ |
44 | if (cmd.resp[1] & MMC_CARD_BUSY) |
45 | break; |
46 | } else { |
47 | if (cmd.resp[0] & MMC_CARD_BUSY) |
48 | break; |
49 | } |
50 | |
51 | err = -ETIMEDOUT; |
52 | |
53 | mmc_delay(ms: 10); |
54 | } |
55 | |
56 | if (rocr) |
57 | *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0]; |
58 | |
59 | return err; |
60 | } |
61 | |
62 | static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn, |
63 | unsigned addr, u8 in, u8 *out) |
64 | { |
65 | struct mmc_command cmd = {}; |
66 | int err; |
67 | |
68 | if (fn > 7) |
69 | return -EINVAL; |
70 | |
71 | /* sanity check */ |
72 | if (addr & ~0x1FFFF) |
73 | return -EINVAL; |
74 | |
75 | cmd.opcode = SD_IO_RW_DIRECT; |
76 | cmd.arg = write ? 0x80000000 : 0x00000000; |
77 | cmd.arg |= fn << 28; |
78 | cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; |
79 | cmd.arg |= addr << 9; |
80 | cmd.arg |= in; |
81 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; |
82 | |
83 | err = mmc_wait_for_cmd(host, cmd: &cmd, retries: 0); |
84 | if (err) |
85 | return err; |
86 | |
87 | if (mmc_host_is_spi(host)) { |
88 | /* host driver already reported errors */ |
89 | } else { |
90 | if (cmd.resp[0] & R5_ERROR) |
91 | return -EIO; |
92 | if (cmd.resp[0] & R5_FUNCTION_NUMBER) |
93 | return -EINVAL; |
94 | if (cmd.resp[0] & R5_OUT_OF_RANGE) |
95 | return -ERANGE; |
96 | } |
97 | |
98 | if (out) { |
99 | if (mmc_host_is_spi(host)) |
100 | *out = (cmd.resp[0] >> 8) & 0xFF; |
101 | else |
102 | *out = cmd.resp[0] & 0xFF; |
103 | } |
104 | |
105 | return 0; |
106 | } |
107 | |
108 | int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, |
109 | unsigned addr, u8 in, u8 *out) |
110 | { |
111 | return mmc_io_rw_direct_host(host: card->host, write, fn, addr, in, out); |
112 | } |
113 | |
114 | int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, |
115 | unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) |
116 | { |
117 | struct mmc_request mrq = {}; |
118 | struct mmc_command cmd = {}; |
119 | struct mmc_data data = {}; |
120 | struct scatterlist sg, *sg_ptr; |
121 | struct sg_table sgtable; |
122 | unsigned int nents, left_size, i; |
123 | unsigned int seg_size = card->host->max_seg_size; |
124 | int err; |
125 | |
126 | WARN_ON(blksz == 0); |
127 | |
128 | /* sanity check */ |
129 | if (addr & ~0x1FFFF) |
130 | return -EINVAL; |
131 | |
132 | mrq.cmd = &cmd; |
133 | mrq.data = &data; |
134 | |
135 | cmd.opcode = SD_IO_RW_EXTENDED; |
136 | cmd.arg = write ? 0x80000000 : 0x00000000; |
137 | cmd.arg |= fn << 28; |
138 | cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; |
139 | cmd.arg |= addr << 9; |
140 | if (blocks == 0) |
141 | cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ |
142 | else |
143 | cmd.arg |= 0x08000000 | blocks; /* block mode */ |
144 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; |
145 | |
146 | data.blksz = blksz; |
147 | /* Code in host drivers/fwk assumes that "blocks" always is >=1 */ |
148 | data.blocks = blocks ? blocks : 1; |
149 | data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; |
150 | |
151 | left_size = data.blksz * data.blocks; |
152 | nents = DIV_ROUND_UP(left_size, seg_size); |
153 | if (nents > 1) { |
154 | if (sg_alloc_table(&sgtable, nents, GFP_KERNEL)) |
155 | return -ENOMEM; |
156 | |
157 | data.sg = sgtable.sgl; |
158 | data.sg_len = nents; |
159 | |
160 | for_each_sg(data.sg, sg_ptr, data.sg_len, i) { |
161 | sg_set_buf(sg: sg_ptr, buf: buf + i * seg_size, |
162 | min(seg_size, left_size)); |
163 | left_size -= seg_size; |
164 | } |
165 | } else { |
166 | data.sg = &sg; |
167 | data.sg_len = 1; |
168 | |
169 | sg_init_one(&sg, buf, left_size); |
170 | } |
171 | |
172 | mmc_set_data_timeout(data: &data, card); |
173 | |
174 | mmc_pre_req(host: card->host, mrq: &mrq); |
175 | |
176 | mmc_wait_for_req(host: card->host, mrq: &mrq); |
177 | |
178 | if (cmd.error) |
179 | err = cmd.error; |
180 | else if (data.error) |
181 | err = data.error; |
182 | else if (mmc_host_is_spi(card->host)) |
183 | /* host driver already reported errors */ |
184 | err = 0; |
185 | else if (cmd.resp[0] & R5_ERROR) |
186 | err = -EIO; |
187 | else if (cmd.resp[0] & R5_FUNCTION_NUMBER) |
188 | err = -EINVAL; |
189 | else if (cmd.resp[0] & R5_OUT_OF_RANGE) |
190 | err = -ERANGE; |
191 | else |
192 | err = 0; |
193 | |
194 | mmc_post_req(host: card->host, mrq: &mrq, err); |
195 | |
196 | if (nents > 1) |
197 | sg_free_table(&sgtable); |
198 | |
199 | return err; |
200 | } |
201 | |
202 | int sdio_reset(struct mmc_host *host) |
203 | { |
204 | int ret; |
205 | u8 abort; |
206 | |
207 | /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */ |
208 | |
209 | ret = mmc_io_rw_direct_host(host, write: 0, fn: 0, SDIO_CCCR_ABORT, in: 0, out: &abort); |
210 | if (ret) |
211 | abort = 0x08; |
212 | else |
213 | abort |= 0x08; |
214 | |
215 | return mmc_io_rw_direct_host(host, write: 1, fn: 0, SDIO_CCCR_ABORT, in: abort, NULL); |
216 | } |
217 | |
218 | |