forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/mmc/host/sdricoh_cs.c
....@@ -1,23 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * sdricoh_cs.c - driver for Ricoh Secure Digital Card Readers that can be
34 * found on some Ricoh RL5c476 II cardbus bridge
45 *
56 * Copyright (C) 2006 - 2008 Sascha Sommer <saschasommer@freenet.de>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
- *
217 */
228
239 /*
....@@ -29,6 +15,7 @@
2915 #include <linux/module.h>
3016 #include <linux/pci.h>
3117 #include <linux/ioport.h>
18
+#include <linux/iopoll.h>
3219 #include <linux/scatterlist.h>
3320
3421 #include <pcmcia/cistpl.h>
....@@ -36,6 +23,7 @@
3623 #include <linux/io.h>
3724
3825 #include <linux/mmc/host.h>
26
+#include <linux/mmc/mmc.h>
3927
4028 #define DRIVER_NAME "sdricoh_cs"
4129
....@@ -71,10 +59,8 @@
7159 #define STATUS_BUSY 0x40000000
7260
7361 /* timeouts */
74
-#define INIT_TIMEOUT 100
75
-#define CMD_TIMEOUT 100000
76
-#define TRANSFER_TIMEOUT 100000
77
-#define BUSY_TIMEOUT 32767
62
+#define SDRICOH_CMD_TIMEOUT_US 1000000
63
+#define SDRICOH_DATA_TIMEOUT_US 1000000
7864
7965 /* list of supported pcmcia devices */
8066 static const struct pcmcia_device_id pcmcia_ids[] = {
....@@ -138,19 +124,24 @@
138124 return value;
139125 }
140126
141
-static int sdricoh_query_status(struct sdricoh_host *host, unsigned int wanted,
142
- unsigned int timeout){
143
- unsigned int loop;
127
+static bool sdricoh_status_ok(struct sdricoh_host *host, unsigned int status,
128
+ unsigned int wanted)
129
+{
130
+ sdricoh_writel(host, R2E4_STATUS_RESP, status);
131
+ return status & wanted;
132
+}
133
+
134
+static int sdricoh_query_status(struct sdricoh_host *host, unsigned int wanted)
135
+{
136
+ int ret;
144137 unsigned int status = 0;
145138 struct device *dev = host->dev;
146
- for (loop = 0; loop < timeout; loop++) {
147
- status = sdricoh_readl(host, R21C_STATUS);
148
- sdricoh_writel(host, R2E4_STATUS_RESP, status);
149
- if (status & wanted)
150
- break;
151
- }
152139
153
- if (loop == timeout) {
140
+ ret = read_poll_timeout(sdricoh_readl, status,
141
+ sdricoh_status_ok(host, status, wanted),
142
+ 32, SDRICOH_DATA_TIMEOUT_US, false,
143
+ host, R21C_STATUS);
144
+ if (ret) {
154145 dev_err(dev, "query_status: timeout waiting for %x\n", wanted);
155146 return -ETIMEDOUT;
156147 }
....@@ -164,35 +155,46 @@
164155
165156 }
166157
167
-static int sdricoh_mmc_cmd(struct sdricoh_host *host, unsigned char opcode,
168
- unsigned int arg)
158
+static int sdricoh_mmc_cmd(struct sdricoh_host *host, struct mmc_command *cmd)
169159 {
170
- unsigned int status;
171
- int result = 0;
172
- unsigned int loop = 0;
160
+ unsigned int status, timeout_us;
161
+ int ret;
162
+ unsigned char opcode = cmd->opcode;
163
+
173164 /* reset status reg? */
174165 sdricoh_writel(host, R21C_STATUS, 0x18);
166
+
167
+ /* MMC_APP_CMDs need some special handling */
168
+ if (host->app_cmd) {
169
+ opcode |= 64;
170
+ host->app_cmd = 0;
171
+ } else if (opcode == MMC_APP_CMD)
172
+ host->app_cmd = 1;
173
+
175174 /* fill parameters */
176
- sdricoh_writel(host, R204_CMD_ARG, arg);
175
+ sdricoh_writel(host, R204_CMD_ARG, cmd->arg);
177176 sdricoh_writel(host, R200_CMD, (0x10000 << 8) | opcode);
177
+
178178 /* wait for command completion */
179
- if (opcode) {
180
- for (loop = 0; loop < CMD_TIMEOUT; loop++) {
181
- status = sdricoh_readl(host, R21C_STATUS);
182
- sdricoh_writel(host, R2E4_STATUS_RESP, status);
183
- if (status & STATUS_CMD_FINISHED)
184
- break;
185
- }
186
- /* don't check for timeout in the loop it is not always
187
- reset correctly
188
- */
189
- if (loop == CMD_TIMEOUT || status & STATUS_CMD_TIMEOUT)
190
- result = -ETIMEDOUT;
179
+ if (!opcode)
180
+ return 0;
191181
192
- }
182
+ timeout_us = cmd->busy_timeout ? cmd->busy_timeout * 1000 :
183
+ SDRICOH_CMD_TIMEOUT_US;
193184
194
- return result;
185
+ ret = read_poll_timeout(sdricoh_readl, status,
186
+ sdricoh_status_ok(host, status, STATUS_CMD_FINISHED),
187
+ 32, timeout_us, false,
188
+ host, R21C_STATUS);
195189
190
+ /*
191
+ * Don't check for timeout status in the loop, as it's not always reset
192
+ * correctly.
193
+ */
194
+ if (ret || status & STATUS_CMD_TIMEOUT)
195
+ return -ETIMEDOUT;
196
+
197
+ return 0;
196198 }
197199
198200 static int sdricoh_reset(struct sdricoh_host *host)
....@@ -221,8 +223,7 @@
221223 u32 data = 0;
222224 /* wait until the data is available */
223225 if (read) {
224
- if (sdricoh_query_status(host, STATUS_READY_TO_READ,
225
- TRANSFER_TIMEOUT))
226
+ if (sdricoh_query_status(host, STATUS_READY_TO_READ))
226227 return -ETIMEDOUT;
227228 sdricoh_writel(host, R21C_STATUS, 0x18);
228229 /* read data */
....@@ -238,8 +239,7 @@
238239 }
239240 }
240241 } else {
241
- if (sdricoh_query_status(host, STATUS_READY_TO_WRITE,
242
- TRANSFER_TIMEOUT))
242
+ if (sdricoh_query_status(host, STATUS_READY_TO_WRITE))
243243 return -ETIMEDOUT;
244244 sdricoh_writel(host, R21C_STATUS, 0x18);
245245 /* write data */
....@@ -265,20 +265,12 @@
265265 struct mmc_command *cmd = mrq->cmd;
266266 struct mmc_data *data = cmd->data;
267267 struct device *dev = host->dev;
268
- unsigned char opcode = cmd->opcode;
269268 int i;
270269
271270 dev_dbg(dev, "=============================\n");
272
- dev_dbg(dev, "sdricoh_request opcode=%i\n", opcode);
271
+ dev_dbg(dev, "sdricoh_request opcode=%i\n", cmd->opcode);
273272
274273 sdricoh_writel(host, R21C_STATUS, 0x18);
275
-
276
- /* MMC_APP_CMDs need some special handling */
277
- if (host->app_cmd) {
278
- opcode |= 64;
279
- host->app_cmd = 0;
280
- } else if (opcode == 55)
281
- host->app_cmd = 1;
282274
283275 /* read/write commands seem to require this */
284276 if (data) {
....@@ -286,7 +278,7 @@
286278 sdricoh_writel(host, R208_DATAIO, 0);
287279 }
288280
289
- cmd->error = sdricoh_mmc_cmd(host, opcode, cmd->arg);
281
+ cmd->error = sdricoh_mmc_cmd(host, cmd);
290282
291283 /* read response buffer */
292284 if (cmd->flags & MMC_RSP_PRESENT) {
....@@ -337,8 +329,7 @@
337329
338330 sdricoh_writel(host, R208_DATAIO, 1);
339331
340
- if (sdricoh_query_status(host, STATUS_TRANSFER_FINISHED,
341
- TRANSFER_TIMEOUT)) {
332
+ if (sdricoh_query_status(host, STATUS_TRANSFER_FINISHED)) {
342333 dev_err(dev, "sdricoh_request: transfer end error\n");
343334 cmd->error = -EINVAL;
344335 }