blob: b0bbb36f89889003b4972f5e84893d17f50e3c33 [file] [log] [blame]
Micky Chingfa590c22013-11-12 17:16:08 +08001/* Driver for Realtek PCI-Express card reader
2 *
3 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author:
19 * Wei WANG (wei_wang@realsil.com.cn)
20 * Micky Ching (micky_ching@realsil.com.cn)
21 */
22
23#include <linux/blkdev.h>
24#include <linux/kthread.h>
25#include <linux/sched.h>
26
27#include "rtsx.h"
Micky Chingfa590c22013-11-12 17:16:08 +080028#include "sd.h"
29
30#define SD_MAX_RETRY_COUNT 3
31
32static u16 REG_SD_CFG1;
33static u16 REG_SD_CFG2;
34static u16 REG_SD_CFG3;
35static u16 REG_SD_STAT1;
36static u16 REG_SD_STAT2;
37static u16 REG_SD_BUS_STAT;
38static u16 REG_SD_PAD_CTL;
39static u16 REG_SD_SAMPLE_POINT_CTL;
40static u16 REG_SD_PUSH_POINT_CTL;
41static u16 REG_SD_CMD0;
42static u16 REG_SD_CMD1;
43static u16 REG_SD_CMD2;
44static u16 REG_SD_CMD3;
45static u16 REG_SD_CMD4;
46static u16 REG_SD_CMD5;
47static u16 REG_SD_BYTE_CNT_L;
48static u16 REG_SD_BYTE_CNT_H;
49static u16 REG_SD_BLOCK_CNT_L;
50static u16 REG_SD_BLOCK_CNT_H;
51static u16 REG_SD_TRANSFER;
52static u16 REG_SD_VPCLK0_CTL;
53static u16 REG_SD_VPCLK1_CTL;
54static u16 REG_SD_DCMPS0_CTL;
55static u16 REG_SD_DCMPS1_CTL;
56
57static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
58{
59 struct sd_info *sd_card = &(chip->sd_card);
60
61 sd_card->err_code |= err_code;
62}
63
64static inline void sd_clr_err_code(struct rtsx_chip *chip)
65{
66 struct sd_info *sd_card = &(chip->sd_card);
67
68 sd_card->err_code = 0;
69}
70
71static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
72{
73 struct sd_info *sd_card = &(chip->sd_card);
74
75 return sd_card->err_code & err_code;
76}
77
78static void sd_init_reg_addr(struct rtsx_chip *chip)
79{
80 REG_SD_CFG1 = 0xFD31;
81 REG_SD_CFG2 = 0xFD33;
82 REG_SD_CFG3 = 0xFD3E;
83 REG_SD_STAT1 = 0xFD30;
84 REG_SD_STAT2 = 0;
85 REG_SD_BUS_STAT = 0;
86 REG_SD_PAD_CTL = 0;
87 REG_SD_SAMPLE_POINT_CTL = 0;
88 REG_SD_PUSH_POINT_CTL = 0;
89 REG_SD_CMD0 = 0xFD34;
90 REG_SD_CMD1 = 0xFD35;
91 REG_SD_CMD2 = 0xFD36;
92 REG_SD_CMD3 = 0xFD37;
93 REG_SD_CMD4 = 0xFD38;
94 REG_SD_CMD5 = 0xFD5A;
95 REG_SD_BYTE_CNT_L = 0xFD39;
96 REG_SD_BYTE_CNT_H = 0xFD3A;
97 REG_SD_BLOCK_CNT_L = 0xFD3B;
98 REG_SD_BLOCK_CNT_H = 0xFD3C;
99 REG_SD_TRANSFER = 0xFD32;
100 REG_SD_VPCLK0_CTL = 0;
101 REG_SD_VPCLK1_CTL = 0;
102 REG_SD_DCMPS0_CTL = 0;
103 REG_SD_DCMPS1_CTL = 0;
104}
105
106static int sd_check_data0_status(struct rtsx_chip *chip)
107{
Joe Perches8ee775f2015-03-25 12:54:26 -0700108 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +0800109 u8 stat;
110
Joe Perches8ee775f2015-03-25 12:54:26 -0700111 retval = rtsx_read_register(chip, REG_SD_STAT1, &stat);
112 if (retval) {
113 rtsx_trace(chip);
114 return retval;
115 }
Micky Chingfa590c22013-11-12 17:16:08 +0800116
117 if (!(stat & SD_DAT0_STATUS)) {
118 sd_set_err_code(chip, SD_BUSY);
Joe Perches031366e2015-03-25 12:54:25 -0700119 rtsx_trace(chip);
120 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800121 }
122
123 return STATUS_SUCCESS;
124}
125
126static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
127 u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
128{
129 struct sd_info *sd_card = &(chip->sd_card);
130 int retval;
131 int timeout = 100;
132 u16 reg_addr;
133 u8 *ptr;
134 int stat_idx = 0;
135 int rty_cnt = 0;
136
137 sd_clr_err_code(chip);
138
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200139 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
Micky Chingfa590c22013-11-12 17:16:08 +0800140
141 if (rsp_type == SD_RSP_TYPE_R1b)
142 timeout = 3000;
143
144RTY_SEND_CMD:
145
146 rtsx_init_cmd(chip);
147
148 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
149 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
150 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
151 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
152 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
153
154 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
155 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
156 0x01, PINGPONG_BUFFER);
157 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
158 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
159 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
160 SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE);
161
162 if (rsp_type == SD_RSP_TYPE_R2) {
163 for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
164 reg_addr++)
165 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
166
167 stat_idx = 16;
168 } else if (rsp_type != SD_RSP_TYPE_R0) {
169 for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
170 reg_addr++)
171 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
172
173 stat_idx = 5;
174 }
175
176 rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
177
178 retval = rtsx_send_cmd(chip, SD_CARD, timeout);
179 if (retval < 0) {
180 u8 val;
181
182 rtsx_read_register(chip, REG_SD_STAT1, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200183 dev_dbg(rtsx_dev(chip), "SD_STAT1: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +0800184
185 rtsx_read_register(chip, REG_SD_CFG3, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200186 dev_dbg(rtsx_dev(chip), "SD_CFG3: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +0800187
188 if (retval == -ETIMEDOUT) {
189 if (rsp_type & SD_WAIT_BUSY_END) {
190 retval = sd_check_data0_status(chip);
191 if (retval != STATUS_SUCCESS) {
192 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700193 rtsx_trace(chip);
194 return retval;
Micky Chingfa590c22013-11-12 17:16:08 +0800195 }
196 } else {
197 sd_set_err_code(chip, SD_TO_ERR);
198 }
199 retval = STATUS_TIMEDOUT;
200 } else {
201 retval = STATUS_FAIL;
202 }
203 rtsx_clear_sd_error(chip);
204
Joe Perches031366e2015-03-25 12:54:25 -0700205 rtsx_trace(chip);
206 return retval;
Micky Chingfa590c22013-11-12 17:16:08 +0800207 }
208
209 if (rsp_type == SD_RSP_TYPE_R0)
210 return STATUS_SUCCESS;
211
212 ptr = rtsx_get_cmd_data(chip) + 1;
213
214 if ((ptr[0] & 0xC0) != 0) {
215 sd_set_err_code(chip, SD_STS_ERR);
Joe Perches031366e2015-03-25 12:54:25 -0700216 rtsx_trace(chip);
217 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800218 }
219
220 if (!(rsp_type & SD_NO_CHECK_CRC7)) {
221 if (ptr[stat_idx] & SD_CRC7_ERR) {
222 if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
223 sd_set_err_code(chip, SD_CRC_ERR);
Joe Perches031366e2015-03-25 12:54:25 -0700224 rtsx_trace(chip);
225 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800226 }
227 if (rty_cnt < SD_MAX_RETRY_COUNT) {
228 wait_timeout(20);
229 rty_cnt++;
230 goto RTY_SEND_CMD;
231 } else {
232 sd_set_err_code(chip, SD_CRC_ERR);
Joe Perches031366e2015-03-25 12:54:25 -0700233 rtsx_trace(chip);
234 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800235 }
236 }
237 }
238
239 if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) {
240 if ((cmd_idx != SEND_RELATIVE_ADDR) &&
241 (cmd_idx != SEND_IF_COND)) {
242 if (cmd_idx != STOP_TRANSMISSION) {
Joe Perches031366e2015-03-25 12:54:25 -0700243 if (ptr[1] & 0x80) {
244 rtsx_trace(chip);
245 return STATUS_FAIL;
246 }
Micky Chingfa590c22013-11-12 17:16:08 +0800247 }
248#ifdef SUPPORT_SD_LOCK
Yash Shah66e6d702015-08-03 11:18:31 +0000249 if (ptr[1] & 0x7D) {
Micky Chingfa590c22013-11-12 17:16:08 +0800250#else
Yash Shah66e6d702015-08-03 11:18:31 +0000251 if (ptr[1] & 0x7F) {
Micky Chingfa590c22013-11-12 17:16:08 +0800252#endif
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200253 dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
254 ptr[1]);
Joe Perches031366e2015-03-25 12:54:25 -0700255 rtsx_trace(chip);
256 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800257 }
258 if (ptr[2] & 0xFF) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200259 dev_dbg(rtsx_dev(chip), "ptr[2]: 0x%02x\n",
260 ptr[2]);
Joe Perches031366e2015-03-25 12:54:25 -0700261 rtsx_trace(chip);
262 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800263 }
264 if (ptr[3] & 0x80) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200265 dev_dbg(rtsx_dev(chip), "ptr[3]: 0x%02x\n",
266 ptr[3]);
Joe Perches031366e2015-03-25 12:54:25 -0700267 rtsx_trace(chip);
268 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800269 }
270 if (ptr[3] & 0x01)
271 sd_card->sd_data_buf_ready = 1;
272 else
273 sd_card->sd_data_buf_ready = 0;
274 }
275 }
276
277 if (rsp && rsp_len)
278 memcpy(rsp, ptr, rsp_len);
279
280 return STATUS_SUCCESS;
281}
282
283static int sd_read_data(struct rtsx_chip *chip,
284 u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
285 u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
286 int timeout)
287{
288 struct sd_info *sd_card = &(chip->sd_card);
289 int retval;
290 int i;
291
292 sd_clr_err_code(chip);
293
294 if (!buf)
295 buf_len = 0;
296
Joe Perches031366e2015-03-25 12:54:25 -0700297 if (buf_len > 512) {
298 rtsx_trace(chip);
299 return STATUS_FAIL;
300 }
Micky Chingfa590c22013-11-12 17:16:08 +0800301
302 rtsx_init_cmd(chip);
303
304 if (cmd_len) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200305 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
Bhumika Goyaleff8bf82016-02-26 15:34:34 +0530306 for (i = 0; i < (min(cmd_len, 6)); i++)
Micky Chingfa590c22013-11-12 17:16:08 +0800307 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i,
308 0xFF, cmd[i]);
309 }
310 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
311 (u8)byte_cnt);
312 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
313 (u8)(byte_cnt >> 8));
314 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
315 (u8)blk_cnt);
316 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
317 (u8)(blk_cnt >> 8));
318
319 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
320
321 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
322 SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END|
323 SD_CHECK_CRC7 | SD_RSP_LEN_6);
324 if (trans_mode != SD_TM_AUTO_TUNING)
325 rtsx_add_cmd(chip, WRITE_REG_CMD,
326 CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
327
328 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
329 trans_mode | SD_TRANSFER_START);
330 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
331 SD_TRANSFER_END);
332
333 retval = rtsx_send_cmd(chip, SD_CARD, timeout);
334 if (retval < 0) {
335 if (retval == -ETIMEDOUT) {
336 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
337 SD_RSP_TYPE_R1, NULL, 0);
338 }
339
Joe Perches031366e2015-03-25 12:54:25 -0700340 rtsx_trace(chip);
341 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800342 }
343
344 if (buf && buf_len) {
345 retval = rtsx_read_ppbuf(chip, buf, buf_len);
Joe Perches031366e2015-03-25 12:54:25 -0700346 if (retval != STATUS_SUCCESS) {
347 rtsx_trace(chip);
348 return STATUS_FAIL;
349 }
Micky Chingfa590c22013-11-12 17:16:08 +0800350 }
351
352 return STATUS_SUCCESS;
353}
354
355static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
356 u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width,
357 u8 *buf, int buf_len, int timeout)
358{
359 struct sd_info *sd_card = &(chip->sd_card);
360 int retval;
361 int i;
362
363 sd_clr_err_code(chip);
364
365 if (!buf)
366 buf_len = 0;
367
368 if (buf_len > 512) {
369 /* This function can't write data more than one page */
Joe Perches031366e2015-03-25 12:54:25 -0700370 rtsx_trace(chip);
371 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800372 }
373
374 if (buf && buf_len) {
375 retval = rtsx_write_ppbuf(chip, buf, buf_len);
Joe Perches031366e2015-03-25 12:54:25 -0700376 if (retval != STATUS_SUCCESS) {
377 rtsx_trace(chip);
378 return STATUS_FAIL;
379 }
Micky Chingfa590c22013-11-12 17:16:08 +0800380 }
381
382 rtsx_init_cmd(chip);
383
384 if (cmd_len) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200385 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
Bhumika Goyaleff8bf82016-02-26 15:34:34 +0530386 for (i = 0; i < (min(cmd_len, 6)); i++) {
Micky Chingfa590c22013-11-12 17:16:08 +0800387 rtsx_add_cmd(chip, WRITE_REG_CMD,
388 REG_SD_CMD0 + i, 0xFF, cmd[i]);
389 }
390 }
391 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
392 (u8)byte_cnt);
393 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
394 (u8)(byte_cnt >> 8));
395 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
396 (u8)blk_cnt);
397 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
398 (u8)(blk_cnt >> 8));
399
400 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
401
402 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
403 SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
404 SD_CHECK_CRC7 | SD_RSP_LEN_6);
405
406 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
407 trans_mode | SD_TRANSFER_START);
408 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
409 SD_TRANSFER_END);
410
411 retval = rtsx_send_cmd(chip, SD_CARD, timeout);
412 if (retval < 0) {
413 if (retval == -ETIMEDOUT) {
414 sd_send_cmd_get_rsp(chip, SEND_STATUS,
415 sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
416 }
417
Joe Perches031366e2015-03-25 12:54:25 -0700418 rtsx_trace(chip);
419 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800420 }
421
422 return STATUS_SUCCESS;
423}
424
425static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
426{
427 struct sd_info *sd_card = &(chip->sd_card);
428 int retval;
429 int i;
430 u8 csd_ver, trans_speed;
431 u8 rsp[16];
432
433 for (i = 0; i < 6; i++) {
434 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
435 sd_set_err_code(chip, SD_NO_CARD);
Joe Perches031366e2015-03-25 12:54:25 -0700436 rtsx_trace(chip);
437 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800438 }
439
440 retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr,
441 SD_RSP_TYPE_R2, rsp, 16);
442 if (retval == STATUS_SUCCESS)
443 break;
444 }
445
Joe Perches031366e2015-03-25 12:54:25 -0700446 if (i == 6) {
447 rtsx_trace(chip);
448 return STATUS_FAIL;
449 }
Micky Chingfa590c22013-11-12 17:16:08 +0800450
451 memcpy(sd_card->raw_csd, rsp + 1, 15);
452
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200453 dev_dbg(rtsx_dev(chip), "CSD Response:\n");
Fabio Falzoi69b8b222014-08-05 23:24:17 +0200454 dev_dbg(rtsx_dev(chip), "%*ph\n", 16, sd_card->raw_csd);
Micky Chingfa590c22013-11-12 17:16:08 +0800455
456 csd_ver = (rsp[1] & 0xc0) >> 6;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200457 dev_dbg(rtsx_dev(chip), "csd_ver = %d\n", csd_ver);
Micky Chingfa590c22013-11-12 17:16:08 +0800458
459 trans_speed = rsp[4];
460 if ((trans_speed & 0x07) == 0x02) {
461 if ((trans_speed & 0xf8) >= 0x30) {
462 if (chip->asic_code)
463 sd_card->sd_clock = 47;
464 else
465 sd_card->sd_clock = CLK_50;
466
467 } else if ((trans_speed & 0xf8) == 0x28) {
468 if (chip->asic_code)
469 sd_card->sd_clock = 39;
470 else
471 sd_card->sd_clock = CLK_40;
472
473 } else if ((trans_speed & 0xf8) == 0x20) {
474 if (chip->asic_code)
475 sd_card->sd_clock = 29;
476 else
477 sd_card->sd_clock = CLK_30;
478
479 } else if ((trans_speed & 0xf8) >= 0x10) {
480 if (chip->asic_code)
481 sd_card->sd_clock = 23;
482 else
483 sd_card->sd_clock = CLK_20;
484
485 } else if ((trans_speed & 0x08) >= 0x08) {
486 if (chip->asic_code)
487 sd_card->sd_clock = 19;
488 else
489 sd_card->sd_clock = CLK_20;
490 } else {
Joe Perches031366e2015-03-25 12:54:25 -0700491 rtsx_trace(chip);
492 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800493 }
494 } else {
Joe Perches031366e2015-03-25 12:54:25 -0700495 rtsx_trace(chip);
496 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800497 }
498
499 if (CHK_MMC_SECTOR_MODE(sd_card)) {
500 sd_card->capacity = 0;
501 } else {
502 if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) {
503 u8 blk_size, c_size_mult;
504 u16 c_size;
Tina Johnson767c6a52014-09-21 11:38:11 +0530505
Micky Chingfa590c22013-11-12 17:16:08 +0800506 blk_size = rsp[6] & 0x0F;
507 c_size = ((u16)(rsp[7] & 0x03) << 10)
508 + ((u16)rsp[8] << 2)
509 + ((u16)(rsp[9] & 0xC0) >> 6);
510 c_size_mult = (u8)((rsp[10] & 0x03) << 1);
511 c_size_mult += (rsp[11] & 0x80) >> 7;
512 sd_card->capacity = (((u32)(c_size + 1)) *
513 (1 << (c_size_mult + 2)))
514 << (blk_size - 9);
515 } else {
516 u32 total_sector = 0;
Tina Johnson767c6a52014-09-21 11:38:11 +0530517
Micky Chingfa590c22013-11-12 17:16:08 +0800518 total_sector = (((u32)rsp[8] & 0x3f) << 16) |
519 ((u32)rsp[9] << 8) | (u32)rsp[10];
520 sd_card->capacity = (total_sector + 1) << 10;
521 }
522 }
523
524 if (check_wp) {
525 if (rsp[15] & 0x30)
526 chip->card_wp |= SD_CARD;
527
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200528 dev_dbg(rtsx_dev(chip), "CSD WP Status: 0x%x\n", rsp[15]);
Micky Chingfa590c22013-11-12 17:16:08 +0800529 }
530
531 return STATUS_SUCCESS;
532}
533
534static int sd_set_sample_push_timing(struct rtsx_chip *chip)
535{
Joe Perches8ee775f2015-03-25 12:54:26 -0700536 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +0800537 struct sd_info *sd_card = &(chip->sd_card);
Micky Chingfa590c22013-11-12 17:16:08 +0800538 u8 val = 0;
539
540 if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
541 val |= 0x10;
542
543 if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
544 if (chip->asic_code) {
545 if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
546 if (val & 0x10)
547 val |= 0x04;
548 else
549 val |= 0x08;
550 }
551 } else {
552 if (val & 0x10)
553 val |= 0x04;
554 else
555 val |= 0x08;
556 }
557 } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) ==
558 SD_SAMPLE_POINT_DELAY) {
559 if (val & 0x10)
560 val |= 0x04;
561 else
562 val |= 0x08;
563 }
564
Joe Perches8ee775f2015-03-25 12:54:26 -0700565 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x1C, val);
566 if (retval) {
567 rtsx_trace(chip);
568 return retval;
569 }
Micky Chingfa590c22013-11-12 17:16:08 +0800570
571 return STATUS_SUCCESS;
572}
573
574static void sd_choose_proper_clock(struct rtsx_chip *chip)
575{
576 struct sd_info *sd_card = &(chip->sd_card);
577
578 if (CHK_SD_SDR104(sd_card)) {
579 if (chip->asic_code)
580 sd_card->sd_clock = chip->asic_sd_sdr104_clk;
581 else
582 sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
583
584 } else if (CHK_SD_DDR50(sd_card)) {
585 if (chip->asic_code)
586 sd_card->sd_clock = chip->asic_sd_ddr50_clk;
587 else
588 sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
589
590 } else if (CHK_SD_SDR50(sd_card)) {
591 if (chip->asic_code)
592 sd_card->sd_clock = chip->asic_sd_sdr50_clk;
593 else
594 sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
595
596 } else if (CHK_SD_HS(sd_card)) {
597 if (chip->asic_code)
598 sd_card->sd_clock = chip->asic_sd_hs_clk;
599 else
600 sd_card->sd_clock = chip->fpga_sd_hs_clk;
601
602 } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
603 if (chip->asic_code)
604 sd_card->sd_clock = chip->asic_mmc_52m_clk;
605 else
606 sd_card->sd_clock = chip->fpga_mmc_52m_clk;
607
608 } else if (CHK_MMC_26M(sd_card)) {
609 if (chip->asic_code)
610 sd_card->sd_clock = 48;
611 else
612 sd_card->sd_clock = CLK_50;
613 }
614}
615
616static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
617{
Joe Perches8ee775f2015-03-25 12:54:26 -0700618 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +0800619 u8 mask = 0, val = 0;
620
621 mask = 0x60;
622 if (clk_div == SD_CLK_DIVIDE_0)
623 val = 0x00;
624 else if (clk_div == SD_CLK_DIVIDE_128)
625 val = 0x40;
626 else if (clk_div == SD_CLK_DIVIDE_256)
627 val = 0x20;
628
Joe Perches8ee775f2015-03-25 12:54:26 -0700629 retval = rtsx_write_register(chip, REG_SD_CFG1, mask, val);
630 if (retval) {
631 rtsx_trace(chip);
632 return retval;
633 }
Micky Chingfa590c22013-11-12 17:16:08 +0800634
635 return STATUS_SUCCESS;
636}
637
638static int sd_set_init_para(struct rtsx_chip *chip)
639{
640 struct sd_info *sd_card = &(chip->sd_card);
641 int retval;
642
643 retval = sd_set_sample_push_timing(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700644 if (retval != STATUS_SUCCESS) {
645 rtsx_trace(chip);
646 return STATUS_FAIL;
647 }
Micky Chingfa590c22013-11-12 17:16:08 +0800648
649 sd_choose_proper_clock(chip);
650
651 retval = switch_clock(chip, sd_card->sd_clock);
Joe Perches031366e2015-03-25 12:54:25 -0700652 if (retval != STATUS_SUCCESS) {
653 rtsx_trace(chip);
654 return STATUS_FAIL;
655 }
Micky Chingfa590c22013-11-12 17:16:08 +0800656
657 return STATUS_SUCCESS;
658}
659
660int sd_select_card(struct rtsx_chip *chip, int select)
661{
662 struct sd_info *sd_card = &(chip->sd_card);
663 int retval;
664 u8 cmd_idx, cmd_type;
665 u32 addr;
666
667 if (select) {
668 cmd_idx = SELECT_CARD;
669 cmd_type = SD_RSP_TYPE_R1;
670 addr = sd_card->sd_addr;
671 } else {
672 cmd_idx = DESELECT_CARD;
673 cmd_type = SD_RSP_TYPE_R0;
674 addr = 0;
675 }
676
677 retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -0700678 if (retval != STATUS_SUCCESS) {
679 rtsx_trace(chip);
680 return STATUS_FAIL;
681 }
Micky Chingfa590c22013-11-12 17:16:08 +0800682
683 return STATUS_SUCCESS;
684}
685
686#ifdef SUPPORT_SD_LOCK
687static int sd_update_lock_status(struct rtsx_chip *chip)
688{
689 struct sd_info *sd_card = &(chip->sd_card);
690 int retval;
691 u8 rsp[5];
692
693 retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
694 SD_RSP_TYPE_R1, rsp, 5);
Joe Perches031366e2015-03-25 12:54:25 -0700695 if (retval != STATUS_SUCCESS) {
696 rtsx_trace(chip);
697 return STATUS_FAIL;
698 }
Micky Chingfa590c22013-11-12 17:16:08 +0800699
700 if (rsp[1] & 0x02)
701 sd_card->sd_lock_status |= SD_LOCKED;
702 else
703 sd_card->sd_lock_status &= ~SD_LOCKED;
704
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200705 dev_dbg(rtsx_dev(chip), "sd_card->sd_lock_status = 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +0800706 sd_card->sd_lock_status);
707
Joe Perches031366e2015-03-25 12:54:25 -0700708 if (rsp[1] & 0x01) {
709 rtsx_trace(chip);
710 return STATUS_FAIL;
711 }
Micky Chingfa590c22013-11-12 17:16:08 +0800712
713 return STATUS_SUCCESS;
714}
715#endif
716
717static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state,
718 u8 data_ready, int polling_cnt)
719{
720 struct sd_info *sd_card = &(chip->sd_card);
721 int retval, i;
722 u8 rsp[5];
723
724 for (i = 0; i < polling_cnt; i++) {
725 retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
726 sd_card->sd_addr, SD_RSP_TYPE_R1, rsp,
727 5);
Joe Perches031366e2015-03-25 12:54:25 -0700728 if (retval != STATUS_SUCCESS) {
729 rtsx_trace(chip);
730 return STATUS_FAIL;
731 }
Micky Chingfa590c22013-11-12 17:16:08 +0800732
733 if (((rsp[3] & 0x1E) == state) &&
734 ((rsp[3] & 0x01) == data_ready))
735 return STATUS_SUCCESS;
736 }
737
Joe Perches031366e2015-03-25 12:54:25 -0700738 rtsx_trace(chip);
739 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800740}
741
742static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
743{
744 int retval;
745
746 if (voltage == SD_IO_3V3) {
747 if (chip->asic_code) {
748 retval = rtsx_write_phy_register(chip, 0x08,
749 0x4FC0 |
750 chip->phy_voltage);
Joe Perches031366e2015-03-25 12:54:25 -0700751 if (retval != STATUS_SUCCESS) {
752 rtsx_trace(chip);
753 return STATUS_FAIL;
754 }
Micky Chingfa590c22013-11-12 17:16:08 +0800755 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700756 retval = rtsx_write_register(chip, SD_PAD_CTL,
757 SD_IO_USING_1V8, 0);
758 if (retval) {
759 rtsx_trace(chip);
760 return retval;
761 }
Micky Chingfa590c22013-11-12 17:16:08 +0800762 }
763 } else if (voltage == SD_IO_1V8) {
764 if (chip->asic_code) {
765 retval = rtsx_write_phy_register(chip, 0x08,
766 0x4C40 |
767 chip->phy_voltage);
Joe Perches031366e2015-03-25 12:54:25 -0700768 if (retval != STATUS_SUCCESS) {
769 rtsx_trace(chip);
770 return STATUS_FAIL;
771 }
Micky Chingfa590c22013-11-12 17:16:08 +0800772 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700773 retval = rtsx_write_register(chip, SD_PAD_CTL,
774 SD_IO_USING_1V8,
775 SD_IO_USING_1V8);
776 if (retval) {
777 rtsx_trace(chip);
778 return retval;
779 }
Micky Chingfa590c22013-11-12 17:16:08 +0800780 }
781 } else {
Joe Perches031366e2015-03-25 12:54:25 -0700782 rtsx_trace(chip);
783 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800784 }
785
786 return STATUS_SUCCESS;
787}
788
789static int sd_voltage_switch(struct rtsx_chip *chip)
790{
791 int retval;
792 u8 stat;
793
Joe Perches8ee775f2015-03-25 12:54:26 -0700794 retval = rtsx_write_register(chip, SD_BUS_STAT,
795 SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
796 SD_CLK_TOGGLE_EN);
797 if (retval) {
798 rtsx_trace(chip);
799 return retval;
800 }
Micky Chingfa590c22013-11-12 17:16:08 +0800801
802 retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1,
803 NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -0700804 if (retval != STATUS_SUCCESS) {
805 rtsx_trace(chip);
806 return STATUS_FAIL;
807 }
Micky Chingfa590c22013-11-12 17:16:08 +0800808
809 udelay(chip->sd_voltage_switch_delay);
810
Joe Perches8ee775f2015-03-25 12:54:26 -0700811 retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
812 if (retval) {
813 rtsx_trace(chip);
814 return retval;
815 }
Micky Chingfa590c22013-11-12 17:16:08 +0800816 if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
817 SD_DAT1_STATUS | SD_DAT0_STATUS)) {
Joe Perches031366e2015-03-25 12:54:25 -0700818 rtsx_trace(chip);
819 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800820 }
821
Joe Perches8ee775f2015-03-25 12:54:26 -0700822 retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
823 SD_CLK_FORCE_STOP);
824 if (retval) {
825 rtsx_trace(chip);
826 return retval;
827 }
Micky Chingfa590c22013-11-12 17:16:08 +0800828 retval = sd_change_bank_voltage(chip, SD_IO_1V8);
Joe Perches031366e2015-03-25 12:54:25 -0700829 if (retval != STATUS_SUCCESS) {
830 rtsx_trace(chip);
831 return STATUS_FAIL;
832 }
Micky Chingfa590c22013-11-12 17:16:08 +0800833
834 wait_timeout(50);
835
Joe Perches8ee775f2015-03-25 12:54:26 -0700836 retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
837 SD_CLK_TOGGLE_EN);
838 if (retval) {
839 rtsx_trace(chip);
840 return retval;
841 }
Micky Chingfa590c22013-11-12 17:16:08 +0800842 wait_timeout(10);
843
Joe Perches8ee775f2015-03-25 12:54:26 -0700844 retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
845 if (retval) {
846 rtsx_trace(chip);
847 return retval;
848 }
Micky Chingfa590c22013-11-12 17:16:08 +0800849 if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
850 SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
851 (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
852 SD_DAT1_STATUS | SD_DAT0_STATUS)) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200853 dev_dbg(rtsx_dev(chip), "SD_BUS_STAT: 0x%x\n", stat);
Micky Chingfa590c22013-11-12 17:16:08 +0800854 rtsx_write_register(chip, SD_BUS_STAT,
855 SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
856 rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
Joe Perches031366e2015-03-25 12:54:25 -0700857 rtsx_trace(chip);
858 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +0800859 }
860
Joe Perches8ee775f2015-03-25 12:54:26 -0700861 retval = rtsx_write_register(chip, SD_BUS_STAT,
862 SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
863 if (retval) {
864 rtsx_trace(chip);
865 return retval;
866 }
Micky Chingfa590c22013-11-12 17:16:08 +0800867
868 return STATUS_SUCCESS;
869}
870
871static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
872{
Joe Perches8ee775f2015-03-25 12:54:26 -0700873 int retval;
874
Micky Chingfa590c22013-11-12 17:16:08 +0800875 if (tune_dir == TUNE_RX) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700876 retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
877 DCM_RESET | DCM_RX);
878 if (retval) {
879 rtsx_trace(chip);
880 return retval;
881 }
882 retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
883 if (retval) {
884 rtsx_trace(chip);
885 return retval;
886 }
Micky Chingfa590c22013-11-12 17:16:08 +0800887 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700888 retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
889 DCM_RESET | DCM_TX);
890 if (retval) {
891 rtsx_trace(chip);
892 return retval;
893 }
894 retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
895 if (retval) {
896 rtsx_trace(chip);
897 return retval;
898 }
Micky Chingfa590c22013-11-12 17:16:08 +0800899 }
900
901 return STATUS_SUCCESS;
902}
903
904static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
905{
906 struct sd_info *sd_card = &(chip->sd_card);
907 u16 SD_VP_CTL, SD_DCMPS_CTL;
908 u8 val;
909 int retval;
Quentin Lambertde904bf2015-03-04 11:31:01 +0100910 bool ddr_rx = false;
Micky Chingfa590c22013-11-12 17:16:08 +0800911
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200912 dev_dbg(rtsx_dev(chip), "sd_change_phase (sample_point = %d, tune_dir = %d)\n",
913 sample_point, tune_dir);
Micky Chingfa590c22013-11-12 17:16:08 +0800914
915 if (tune_dir == TUNE_RX) {
916 SD_VP_CTL = SD_VPRX_CTL;
917 SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
918 if (CHK_SD_DDR50(sd_card))
Quentin Lambertde904bf2015-03-04 11:31:01 +0100919 ddr_rx = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800920 } else {
921 SD_VP_CTL = SD_VPTX_CTL;
922 SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
923 }
924
925 if (chip->asic_code) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700926 retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK,
927 CHANGE_CLK);
928 if (retval) {
929 rtsx_trace(chip);
930 return retval;
931 }
932 retval = rtsx_write_register(chip, SD_VP_CTL, 0x1F,
933 sample_point);
934 if (retval) {
935 rtsx_trace(chip);
936 return retval;
937 }
938 retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
939 PHASE_NOT_RESET, 0);
940 if (retval) {
941 rtsx_trace(chip);
942 return retval;
943 }
944 retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
945 PHASE_NOT_RESET, PHASE_NOT_RESET);
946 if (retval) {
947 rtsx_trace(chip);
948 return retval;
949 }
950 retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, 0);
951 if (retval) {
952 rtsx_trace(chip);
953 return retval;
954 }
Micky Chingfa590c22013-11-12 17:16:08 +0800955 } else {
Micky Chingfa590c22013-11-12 17:16:08 +0800956 rtsx_read_register(chip, SD_VP_CTL, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200957 dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +0800958 rtsx_read_register(chip, SD_DCMPS_CTL, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200959 dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +0800960
961 if (ddr_rx) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700962 retval = rtsx_write_register(chip, SD_VP_CTL,
963 PHASE_CHANGE,
964 PHASE_CHANGE);
965 if (retval) {
966 rtsx_trace(chip);
967 return retval;
968 }
Micky Chingfa590c22013-11-12 17:16:08 +0800969 udelay(50);
Joe Perches8ee775f2015-03-25 12:54:26 -0700970 retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
971 PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
972 if (retval) {
973 rtsx_trace(chip);
974 return retval;
975 }
Micky Chingfa590c22013-11-12 17:16:08 +0800976 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700977 retval = rtsx_write_register(chip, CLK_CTL,
978 CHANGE_CLK, CHANGE_CLK);
979 if (retval) {
980 rtsx_trace(chip);
981 return retval;
982 }
Micky Chingfa590c22013-11-12 17:16:08 +0800983 udelay(50);
Joe Perches8ee775f2015-03-25 12:54:26 -0700984 retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
985 PHASE_NOT_RESET | sample_point);
986 if (retval) {
987 rtsx_trace(chip);
988 return retval;
989 }
Micky Chingfa590c22013-11-12 17:16:08 +0800990 }
991 udelay(100);
992
993 rtsx_init_cmd(chip);
994 rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE,
995 DCMPS_CHANGE);
996 rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL,
997 DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
998 retval = rtsx_send_cmd(chip, SD_CARD, 100);
Joe Perches031366e2015-03-25 12:54:25 -0700999 if (retval != STATUS_SUCCESS) {
1000 rtsx_trace(chip);
1001 goto Fail;
1002 }
Micky Chingfa590c22013-11-12 17:16:08 +08001003
1004 val = *rtsx_get_cmd_data(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001005 if (val & DCMPS_ERROR) {
1006 rtsx_trace(chip);
1007 goto Fail;
1008 }
Micky Chingfa590c22013-11-12 17:16:08 +08001009
Joe Perches031366e2015-03-25 12:54:25 -07001010 if ((val & DCMPS_CURRENT_PHASE) != sample_point) {
1011 rtsx_trace(chip);
1012 goto Fail;
1013 }
Micky Chingfa590c22013-11-12 17:16:08 +08001014
Joe Perches8ee775f2015-03-25 12:54:26 -07001015 retval = rtsx_write_register(chip, SD_DCMPS_CTL,
1016 DCMPS_CHANGE, 0);
1017 if (retval) {
1018 rtsx_trace(chip);
1019 return retval;
1020 }
1021 if (ddr_rx) {
1022 retval = rtsx_write_register(chip, SD_VP_CTL,
1023 PHASE_CHANGE, 0);
1024 if (retval) {
1025 rtsx_trace(chip);
1026 return retval;
1027 }
1028 } else {
1029 retval = rtsx_write_register(chip, CLK_CTL,
1030 CHANGE_CLK, 0);
1031 if (retval) {
1032 rtsx_trace(chip);
1033 return retval;
1034 }
1035 }
Micky Chingfa590c22013-11-12 17:16:08 +08001036
1037 udelay(50);
1038 }
1039
Joe Perches8ee775f2015-03-25 12:54:26 -07001040 retval = rtsx_write_register(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
1041 if (retval) {
1042 rtsx_trace(chip);
1043 return retval;
1044 }
Micky Chingfa590c22013-11-12 17:16:08 +08001045
1046 return STATUS_SUCCESS;
1047
1048Fail:
Micky Chingfa590c22013-11-12 17:16:08 +08001049 rtsx_read_register(chip, SD_VP_CTL, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001050 dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +08001051 rtsx_read_register(chip, SD_DCMPS_CTL, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001052 dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
Fabio Falzoia8558612014-08-05 23:24:18 +02001053
Micky Chingfa590c22013-11-12 17:16:08 +08001054 rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
1055 rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
1056 wait_timeout(10);
1057 sd_reset_dcm(chip, tune_dir);
1058 return STATUS_FAIL;
1059}
1060
1061static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
1062{
1063 struct sd_info *sd_card = &(chip->sd_card);
1064 int retval;
1065 u8 cmd[5], buf[8];
1066
1067 retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
1068 SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07001069 if (retval != STATUS_SUCCESS) {
1070 rtsx_trace(chip);
1071 return STATUS_FAIL;
1072 }
Micky Chingfa590c22013-11-12 17:16:08 +08001073
1074 cmd[0] = 0x40 | SEND_SCR;
1075 cmd[1] = 0;
1076 cmd[2] = 0;
1077 cmd[3] = 0;
1078 cmd[4] = 0;
1079
1080 retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width,
1081 buf, 8, 250);
1082 if (retval != STATUS_SUCCESS) {
1083 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001084 rtsx_trace(chip);
1085 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001086 }
1087
1088 memcpy(sd_card->raw_scr, buf, 8);
1089
Joe Perches031366e2015-03-25 12:54:25 -07001090 if ((buf[0] & 0x0F) == 0) {
1091 rtsx_trace(chip);
1092 return STATUS_FAIL;
1093 }
Micky Chingfa590c22013-11-12 17:16:08 +08001094
1095 return STATUS_SUCCESS;
1096}
1097
1098static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
1099 u8 func_to_switch, u8 *buf, int buf_len)
1100{
1101 u8 support_mask = 0, query_switch = 0, switch_busy = 0;
1102 int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
1103
1104 if (func_group == SD_FUNC_GROUP_1) {
1105 support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
1106 query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
1107 check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
1108
1109 switch (func_to_switch) {
1110 case HS_SUPPORT:
1111 support_mask = HS_SUPPORT_MASK;
1112 query_switch = HS_QUERY_SWITCH_OK;
1113 switch_busy = HS_SWITCH_BUSY;
1114 break;
1115
1116 case SDR50_SUPPORT:
1117 support_mask = SDR50_SUPPORT_MASK;
1118 query_switch = SDR50_QUERY_SWITCH_OK;
1119 switch_busy = SDR50_SWITCH_BUSY;
1120 break;
1121
1122 case SDR104_SUPPORT:
1123 support_mask = SDR104_SUPPORT_MASK;
1124 query_switch = SDR104_QUERY_SWITCH_OK;
1125 switch_busy = SDR104_SWITCH_BUSY;
1126 break;
1127
1128 case DDR50_SUPPORT:
1129 support_mask = DDR50_SUPPORT_MASK;
1130 query_switch = DDR50_QUERY_SWITCH_OK;
1131 switch_busy = DDR50_SWITCH_BUSY;
1132 break;
1133
1134 default:
Joe Perches031366e2015-03-25 12:54:25 -07001135 rtsx_trace(chip);
1136 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001137 }
1138 } else if (func_group == SD_FUNC_GROUP_3) {
1139 support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
1140 query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
1141 check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
1142
1143 switch (func_to_switch) {
1144 case DRIVING_TYPE_A:
1145 support_mask = DRIVING_TYPE_A_MASK;
1146 query_switch = TYPE_A_QUERY_SWITCH_OK;
1147 switch_busy = TYPE_A_SWITCH_BUSY;
1148 break;
1149
1150 case DRIVING_TYPE_C:
1151 support_mask = DRIVING_TYPE_C_MASK;
1152 query_switch = TYPE_C_QUERY_SWITCH_OK;
1153 switch_busy = TYPE_C_SWITCH_BUSY;
1154 break;
1155
1156 case DRIVING_TYPE_D:
1157 support_mask = DRIVING_TYPE_D_MASK;
1158 query_switch = TYPE_D_QUERY_SWITCH_OK;
1159 switch_busy = TYPE_D_SWITCH_BUSY;
1160 break;
1161
1162 default:
Joe Perches031366e2015-03-25 12:54:25 -07001163 rtsx_trace(chip);
1164 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001165 }
1166 } else if (func_group == SD_FUNC_GROUP_4) {
1167 support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
1168 query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
1169 check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
1170
1171 switch (func_to_switch) {
1172 case CURRENT_LIMIT_400:
1173 support_mask = CURRENT_LIMIT_400_MASK;
1174 query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
1175 switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
1176 break;
1177
1178 case CURRENT_LIMIT_600:
1179 support_mask = CURRENT_LIMIT_600_MASK;
1180 query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
1181 switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
1182 break;
1183
1184 case CURRENT_LIMIT_800:
1185 support_mask = CURRENT_LIMIT_800_MASK;
1186 query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
1187 switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
1188 break;
1189
1190 default:
Joe Perches031366e2015-03-25 12:54:25 -07001191 rtsx_trace(chip);
1192 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001193 }
1194 } else {
Joe Perches031366e2015-03-25 12:54:25 -07001195 rtsx_trace(chip);
1196 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001197 }
1198
1199 if (func_group == SD_FUNC_GROUP_1) {
1200 if (!(buf[support_offset] & support_mask) ||
1201 ((buf[query_switch_offset] & 0x0F) != query_switch)) {
Joe Perches031366e2015-03-25 12:54:25 -07001202 rtsx_trace(chip);
1203 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001204 }
1205 }
1206
1207 /* Check 'Busy Status' */
1208 if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) &&
1209 ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
Joe Perches031366e2015-03-25 12:54:25 -07001210 rtsx_trace(chip);
1211 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001212 }
1213
1214 return STATUS_SUCCESS;
1215}
1216
1217static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
1218 u8 func_group, u8 func_to_switch, u8 bus_width)
1219{
1220 struct sd_info *sd_card = &(chip->sd_card);
1221 int retval;
1222 u8 cmd[5], buf[64];
1223
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001224 dev_dbg(rtsx_dev(chip), "sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n",
1225 mode, func_group, func_to_switch);
Micky Chingfa590c22013-11-12 17:16:08 +08001226
1227 cmd[0] = 0x40 | SWITCH;
1228 cmd[1] = mode;
1229
1230 if (func_group == SD_FUNC_GROUP_1) {
1231 cmd[2] = 0xFF;
1232 cmd[3] = 0xFF;
1233 cmd[4] = 0xF0 + func_to_switch;
1234 } else if (func_group == SD_FUNC_GROUP_3) {
1235 cmd[2] = 0xFF;
1236 cmd[3] = 0xF0 + func_to_switch;
1237 cmd[4] = 0xFF;
1238 } else if (func_group == SD_FUNC_GROUP_4) {
1239 cmd[2] = 0xFF;
1240 cmd[3] = 0x0F + (func_to_switch << 4);
1241 cmd[4] = 0xFF;
1242 } else {
1243 cmd[1] = SD_CHECK_MODE;
1244 cmd[2] = 0xFF;
1245 cmd[3] = 0xFF;
1246 cmd[4] = 0xFF;
1247 }
1248
1249 retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width,
1250 buf, 64, 250);
1251 if (retval != STATUS_SUCCESS) {
1252 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001253 rtsx_trace(chip);
1254 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001255 }
1256
Fabio Falzoi69b8b222014-08-05 23:24:17 +02001257 dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
Micky Chingfa590c22013-11-12 17:16:08 +08001258
1259 if (func_group == NO_ARGUMENT) {
1260 sd_card->func_group1_mask = buf[0x0D];
1261 sd_card->func_group2_mask = buf[0x0B];
1262 sd_card->func_group3_mask = buf[0x09];
1263 sd_card->func_group4_mask = buf[0x07];
1264
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001265 dev_dbg(rtsx_dev(chip), "func_group1_mask = 0x%02x\n",
1266 buf[0x0D]);
1267 dev_dbg(rtsx_dev(chip), "func_group2_mask = 0x%02x\n",
1268 buf[0x0B]);
1269 dev_dbg(rtsx_dev(chip), "func_group3_mask = 0x%02x\n",
1270 buf[0x09]);
1271 dev_dbg(rtsx_dev(chip), "func_group4_mask = 0x%02x\n",
1272 buf[0x07]);
Micky Chingfa590c22013-11-12 17:16:08 +08001273 } else {
1274 /* Maximum current consumption, check whether current is
1275 * acceptable; bit[511:496] = 0x0000 means some error happened.
1276 */
1277 u16 cc = ((u16)buf[0] << 8) | buf[1];
Tina Johnson767c6a52014-09-21 11:38:11 +05301278
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001279 dev_dbg(rtsx_dev(chip), "Maximum current consumption: %dmA\n",
1280 cc);
Joe Perches031366e2015-03-25 12:54:25 -07001281 if ((cc == 0) || (cc > 800)) {
1282 rtsx_trace(chip);
1283 return STATUS_FAIL;
1284 }
Micky Chingfa590c22013-11-12 17:16:08 +08001285
1286 retval = sd_query_switch_result(chip, func_group,
1287 func_to_switch, buf, 64);
Joe Perches031366e2015-03-25 12:54:25 -07001288 if (retval != STATUS_SUCCESS) {
1289 rtsx_trace(chip);
1290 return STATUS_FAIL;
1291 }
Micky Chingfa590c22013-11-12 17:16:08 +08001292
1293 if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001294 retval = rtsx_write_register(chip, OCPPARA2,
1295 SD_OCP_THD_MASK,
1296 chip->sd_800mA_ocp_thd);
1297 if (retval) {
1298 rtsx_trace(chip);
1299 return retval;
1300 }
1301 retval = rtsx_write_register(chip, CARD_PWR_CTL,
1302 PMOS_STRG_MASK,
1303 PMOS_STRG_800mA);
1304 if (retval) {
1305 rtsx_trace(chip);
1306 return retval;
1307 }
Micky Chingfa590c22013-11-12 17:16:08 +08001308 }
1309 }
1310
1311 return STATUS_SUCCESS;
1312}
1313
1314static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
1315{
1316 if (func_group == SD_FUNC_GROUP_1) {
1317 if (func_to_switch > HS_SUPPORT)
1318 func_to_switch--;
1319
1320 } else if (func_group == SD_FUNC_GROUP_4) {
1321 if (func_to_switch > CURRENT_LIMIT_200)
1322 func_to_switch--;
1323 }
1324
1325 return func_to_switch;
1326}
1327
1328static int sd_check_switch(struct rtsx_chip *chip,
1329 u8 func_group, u8 func_to_switch, u8 bus_width)
1330{
1331 int retval;
1332 int i;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001333 bool switch_good = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001334
1335 for (i = 0; i < 3; i++) {
1336 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
1337 sd_set_err_code(chip, SD_NO_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07001338 rtsx_trace(chip);
1339 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001340 }
1341
1342 retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
1343 func_to_switch, bus_width);
1344 if (retval == STATUS_SUCCESS) {
1345 u8 stat;
1346
1347 retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
1348 func_group, func_to_switch, bus_width);
1349 if (retval == STATUS_SUCCESS) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001350 switch_good = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001351 break;
1352 }
1353
Joe Perches8ee775f2015-03-25 12:54:26 -07001354 retval = rtsx_read_register(chip, SD_STAT1, &stat);
1355 if (retval) {
1356 rtsx_trace(chip);
1357 return retval;
1358 }
Micky Chingfa590c22013-11-12 17:16:08 +08001359 if (stat & SD_CRC16_ERR) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001360 dev_dbg(rtsx_dev(chip), "SD CRC16 error when switching mode\n");
Joe Perches031366e2015-03-25 12:54:25 -07001361 rtsx_trace(chip);
1362 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001363 }
1364 }
1365
1366 func_to_switch = downgrade_switch_mode(func_group,
1367 func_to_switch);
1368
1369 wait_timeout(20);
1370 }
1371
Joe Perches031366e2015-03-25 12:54:25 -07001372 if (!switch_good) {
1373 rtsx_trace(chip);
1374 return STATUS_FAIL;
1375 }
Micky Chingfa590c22013-11-12 17:16:08 +08001376
1377 return STATUS_SUCCESS;
1378}
1379
1380static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
1381{
1382 struct sd_info *sd_card = &(chip->sd_card);
1383 int retval;
1384 int i;
1385 u8 func_to_switch = 0;
1386
1387 /* Get supported functions */
1388 retval = sd_check_switch_mode(chip, SD_CHECK_MODE,
1389 NO_ARGUMENT, NO_ARGUMENT, bus_width);
Joe Perches031366e2015-03-25 12:54:25 -07001390 if (retval != STATUS_SUCCESS) {
1391 rtsx_trace(chip);
1392 return STATUS_FAIL;
1393 }
Micky Chingfa590c22013-11-12 17:16:08 +08001394
1395 sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
1396
1397 /* Function Group 1: Access Mode */
1398 for (i = 0; i < 4; i++) {
1399 switch ((u8)(chip->sd_speed_prior >> (i*8))) {
1400 case SDR104_SUPPORT:
1401 if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK)
1402 && chip->sdr104_en) {
1403 func_to_switch = SDR104_SUPPORT;
1404 }
1405 break;
1406
1407 case DDR50_SUPPORT:
1408 if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK)
1409 && chip->ddr50_en) {
1410 func_to_switch = DDR50_SUPPORT;
1411 }
1412 break;
1413
1414 case SDR50_SUPPORT:
1415 if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK)
1416 && chip->sdr50_en) {
1417 func_to_switch = SDR50_SUPPORT;
1418 }
1419 break;
1420
1421 case HS_SUPPORT:
1422 if (sd_card->func_group1_mask & HS_SUPPORT_MASK)
1423 func_to_switch = HS_SUPPORT;
1424
1425 break;
1426
1427 default:
1428 continue;
1429 }
1430
Micky Chingfa590c22013-11-12 17:16:08 +08001431 if (func_to_switch)
1432 break;
1433
1434 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001435 dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_1: func_to_switch = 0x%02x",
1436 func_to_switch);
Micky Chingfa590c22013-11-12 17:16:08 +08001437
1438#ifdef SUPPORT_SD_LOCK
Rehas Sachdeva03282172016-09-20 16:45:48 +05301439 if ((sd_card->sd_lock_status & SD_SDR_RST) &&
1440 (func_to_switch == DDR50_SUPPORT) &&
1441 (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
Micky Chingfa590c22013-11-12 17:16:08 +08001442 func_to_switch = SDR50_SUPPORT;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001443 dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001444 }
1445#endif
1446
1447 if (func_to_switch) {
1448 retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch,
1449 bus_width);
1450 if (retval != STATUS_SUCCESS) {
1451 if (func_to_switch == SDR104_SUPPORT) {
1452 sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
1453 } else if (func_to_switch == DDR50_SUPPORT) {
1454 sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
1455 DDR50_SUPPORT_MASK;
1456 } else if (func_to_switch == SDR50_SUPPORT) {
1457 sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
1458 DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
1459 }
Joe Perches031366e2015-03-25 12:54:25 -07001460 rtsx_trace(chip);
1461 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001462 }
1463
1464 if (func_to_switch == SDR104_SUPPORT)
1465 SET_SD_SDR104(sd_card);
1466 else if (func_to_switch == DDR50_SUPPORT)
1467 SET_SD_DDR50(sd_card);
1468 else if (func_to_switch == SDR50_SUPPORT)
1469 SET_SD_SDR50(sd_card);
1470 else
1471 SET_SD_HS(sd_card);
1472 }
1473
1474 if (CHK_SD_DDR50(sd_card)) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001475 retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06,
1476 0x04);
1477 if (retval) {
1478 rtsx_trace(chip);
1479 return retval;
1480 }
Micky Chingfa590c22013-11-12 17:16:08 +08001481 retval = sd_set_sample_push_timing(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001482 if (retval != STATUS_SUCCESS) {
1483 rtsx_trace(chip);
1484 return STATUS_FAIL;
1485 }
Micky Chingfa590c22013-11-12 17:16:08 +08001486 }
1487
1488 if (!func_to_switch || (func_to_switch == HS_SUPPORT)) {
1489 /* Do not try to switch current limit if the card doesn't
1490 * support UHS mode or we don't want it to support UHS mode
1491 */
1492 return STATUS_SUCCESS;
1493 }
1494
1495 /* Function Group 4: Current Limit */
1496 func_to_switch = 0xFF;
1497
1498 for (i = 0; i < 4; i++) {
1499 switch ((u8)(chip->sd_current_prior >> (i*8))) {
1500 case CURRENT_LIMIT_800:
1501 if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK)
1502 func_to_switch = CURRENT_LIMIT_800;
1503
1504 break;
1505
1506 case CURRENT_LIMIT_600:
1507 if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK)
1508 func_to_switch = CURRENT_LIMIT_600;
1509
1510 break;
1511
1512 case CURRENT_LIMIT_400:
1513 if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK)
1514 func_to_switch = CURRENT_LIMIT_400;
1515
1516 break;
1517
1518 case CURRENT_LIMIT_200:
1519 if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK)
1520 func_to_switch = CURRENT_LIMIT_200;
1521
1522 break;
1523
1524 default:
1525 continue;
1526 }
1527
1528 if (func_to_switch != 0xFF)
1529 break;
1530 }
1531
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001532 dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_4: func_to_switch = 0x%02x",
1533 func_to_switch);
Micky Chingfa590c22013-11-12 17:16:08 +08001534
1535 if (func_to_switch <= CURRENT_LIMIT_800) {
1536 retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch,
1537 bus_width);
1538 if (retval != STATUS_SUCCESS) {
Joe Perches031366e2015-03-25 12:54:25 -07001539 if (sd_check_err_code(chip, SD_NO_CARD)) {
1540 rtsx_trace(chip);
1541 return STATUS_FAIL;
1542 }
Micky Chingfa590c22013-11-12 17:16:08 +08001543 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001544 dev_dbg(rtsx_dev(chip), "Switch current limit finished! (%d)\n",
1545 retval);
Micky Chingfa590c22013-11-12 17:16:08 +08001546 }
1547
Joe Perches8ee775f2015-03-25 12:54:26 -07001548 if (CHK_SD_DDR50(sd_card)) {
1549 retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, 0);
1550 if (retval) {
1551 rtsx_trace(chip);
1552 return retval;
1553 }
1554 }
Micky Chingfa590c22013-11-12 17:16:08 +08001555
1556 return STATUS_SUCCESS;
1557}
1558
1559static int sd_wait_data_idle(struct rtsx_chip *chip)
1560{
1561 int retval = STATUS_TIMEDOUT;
1562 int i;
1563 u8 val = 0;
1564
1565 for (i = 0; i < 100; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001566 retval = rtsx_read_register(chip, SD_DATA_STATE, &val);
1567 if (retval) {
1568 rtsx_trace(chip);
1569 return retval;
1570 }
Micky Chingfa590c22013-11-12 17:16:08 +08001571 if (val & SD_DATA_IDLE) {
1572 retval = STATUS_SUCCESS;
1573 break;
1574 }
1575 udelay(100);
1576 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001577 dev_dbg(rtsx_dev(chip), "SD_DATA_STATE: 0x%02x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +08001578
1579 return retval;
1580}
1581
1582static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
1583{
1584 int retval;
1585 u8 cmd[5];
1586
1587 retval = sd_change_phase(chip, sample_point, TUNE_RX);
Joe Perches031366e2015-03-25 12:54:25 -07001588 if (retval != STATUS_SUCCESS) {
1589 rtsx_trace(chip);
1590 return STATUS_FAIL;
1591 }
Micky Chingfa590c22013-11-12 17:16:08 +08001592
1593 cmd[0] = 0x40 | SEND_TUNING_PATTERN;
1594 cmd[1] = 0;
1595 cmd[2] = 0;
1596 cmd[3] = 0;
1597 cmd[4] = 0;
1598
1599 retval = sd_read_data(chip, SD_TM_AUTO_TUNING,
1600 cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
1601 if (retval != STATUS_SUCCESS) {
1602 (void)sd_wait_data_idle(chip);
1603
1604 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001605 rtsx_trace(chip);
1606 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001607 }
1608
1609 return STATUS_SUCCESS;
1610}
1611
1612static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
1613{
1614 struct sd_info *sd_card = &(chip->sd_card);
1615 int retval;
1616 u8 cmd[5];
1617
1618 retval = sd_change_phase(chip, sample_point, TUNE_RX);
Joe Perches031366e2015-03-25 12:54:25 -07001619 if (retval != STATUS_SUCCESS) {
1620 rtsx_trace(chip);
1621 return STATUS_FAIL;
1622 }
Micky Chingfa590c22013-11-12 17:16:08 +08001623
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001624 dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001625
1626 retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
1627 SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07001628 if (retval != STATUS_SUCCESS) {
1629 rtsx_trace(chip);
1630 return STATUS_FAIL;
1631 }
Micky Chingfa590c22013-11-12 17:16:08 +08001632
1633 cmd[0] = 0x40 | SD_STATUS;
1634 cmd[1] = 0;
1635 cmd[2] = 0;
1636 cmd[3] = 0;
1637 cmd[4] = 0;
1638
1639 retval = sd_read_data(chip, SD_TM_NORMAL_READ,
1640 cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
1641 if (retval != STATUS_SUCCESS) {
1642 (void)sd_wait_data_idle(chip);
1643
1644 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001645 rtsx_trace(chip);
1646 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001647 }
1648
1649 return STATUS_SUCCESS;
1650}
1651
1652static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
1653{
1654 struct sd_info *sd_card = &(chip->sd_card);
1655 int retval;
1656 u8 cmd[5], bus_width;
1657
1658 if (CHK_MMC_8BIT(sd_card))
1659 bus_width = SD_BUS_WIDTH_8;
1660 else if (CHK_MMC_4BIT(sd_card))
1661 bus_width = SD_BUS_WIDTH_4;
1662 else
1663 bus_width = SD_BUS_WIDTH_1;
1664
1665 retval = sd_change_phase(chip, sample_point, TUNE_RX);
Joe Perches031366e2015-03-25 12:54:25 -07001666 if (retval != STATUS_SUCCESS) {
1667 rtsx_trace(chip);
1668 return STATUS_FAIL;
1669 }
Micky Chingfa590c22013-11-12 17:16:08 +08001670
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001671 dev_dbg(rtsx_dev(chip), "mmc ddr tuning rx\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001672
1673 cmd[0] = 0x40 | SEND_EXT_CSD;
1674 cmd[1] = 0;
1675 cmd[2] = 0;
1676 cmd[3] = 0;
1677 cmd[4] = 0;
1678
1679 retval = sd_read_data(chip, SD_TM_NORMAL_READ,
1680 cmd, 5, 0x200, 1, bus_width, NULL, 0, 100);
1681 if (retval != STATUS_SUCCESS) {
1682 (void)sd_wait_data_idle(chip);
1683
1684 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001685 rtsx_trace(chip);
1686 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001687 }
1688
1689 return STATUS_SUCCESS;
1690}
1691
1692static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
1693{
1694 struct sd_info *sd_card = &(chip->sd_card);
1695 int retval;
1696
1697 retval = sd_change_phase(chip, sample_point, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07001698 if (retval != STATUS_SUCCESS) {
1699 rtsx_trace(chip);
1700 return STATUS_FAIL;
1701 }
Micky Chingfa590c22013-11-12 17:16:08 +08001702
Joe Perches8ee775f2015-03-25 12:54:26 -07001703 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
1704 SD_RSP_80CLK_TIMEOUT_EN);
1705 if (retval) {
1706 rtsx_trace(chip);
1707 return retval;
1708 }
Micky Chingfa590c22013-11-12 17:16:08 +08001709
1710 retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
1711 SD_RSP_TYPE_R1, NULL, 0);
1712 if (retval != STATUS_SUCCESS) {
1713 if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
1714 rtsx_write_register(chip, SD_CFG3,
1715 SD_RSP_80CLK_TIMEOUT_EN, 0);
Joe Perches031366e2015-03-25 12:54:25 -07001716 rtsx_trace(chip);
1717 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001718 }
1719 }
1720
Joe Perches8ee775f2015-03-25 12:54:26 -07001721 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
1722 0);
1723 if (retval) {
1724 rtsx_trace(chip);
1725 return retval;
1726 }
Micky Chingfa590c22013-11-12 17:16:08 +08001727
1728 return STATUS_SUCCESS;
1729}
1730
1731static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
1732{
1733 struct sd_info *sd_card = &(chip->sd_card);
1734 int retval;
1735 u8 cmd[5], bus_width;
1736
1737 retval = sd_change_phase(chip, sample_point, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07001738 if (retval != STATUS_SUCCESS) {
1739 rtsx_trace(chip);
1740 return STATUS_FAIL;
1741 }
Micky Chingfa590c22013-11-12 17:16:08 +08001742
1743 if (CHK_SD(sd_card)) {
1744 bus_width = SD_BUS_WIDTH_4;
1745 } else {
1746 if (CHK_MMC_8BIT(sd_card))
1747 bus_width = SD_BUS_WIDTH_8;
1748 else if (CHK_MMC_4BIT(sd_card))
1749 bus_width = SD_BUS_WIDTH_4;
1750 else
1751 bus_width = SD_BUS_WIDTH_1;
1752 }
1753
1754 retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
Joe Perches031366e2015-03-25 12:54:25 -07001755 if (retval != STATUS_SUCCESS) {
1756 rtsx_trace(chip);
1757 return STATUS_FAIL;
1758 }
Micky Chingfa590c22013-11-12 17:16:08 +08001759
Joe Perches8ee775f2015-03-25 12:54:26 -07001760 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
1761 SD_RSP_80CLK_TIMEOUT_EN);
1762 if (retval) {
1763 rtsx_trace(chip);
1764 return retval;
1765 }
Micky Chingfa590c22013-11-12 17:16:08 +08001766
1767 cmd[0] = 0x40 | PROGRAM_CSD;
1768 cmd[1] = 0;
1769 cmd[2] = 0;
1770 cmd[3] = 0;
1771 cmd[4] = 0;
1772
1773 retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2,
1774 cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100);
1775 if (retval != STATUS_SUCCESS) {
1776 rtsx_clear_sd_error(chip);
1777 rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
Joe Perches031366e2015-03-25 12:54:25 -07001778 rtsx_trace(chip);
1779 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001780 }
1781
Joe Perches8ee775f2015-03-25 12:54:26 -07001782 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
1783 0);
1784 if (retval) {
1785 rtsx_trace(chip);
1786 return retval;
1787 }
Micky Chingfa590c22013-11-12 17:16:08 +08001788
1789 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1,
1790 NULL, 0);
1791
1792 return STATUS_SUCCESS;
1793}
1794
1795static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
1796 u8 tune_dir)
1797{
1798 struct sd_info *sd_card = &(chip->sd_card);
1799 struct timing_phase_path path[MAX_PHASE + 1];
1800 int i, j, cont_path_cnt;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001801 bool new_block;
1802 int max_len, final_path_idx;
Micky Chingfa590c22013-11-12 17:16:08 +08001803 u8 final_phase = 0xFF;
1804
1805 if (phase_map == 0xFFFFFFFF) {
1806 if (tune_dir == TUNE_RX)
1807 final_phase = (u8)chip->sd_default_rx_phase;
1808 else
1809 final_phase = (u8)chip->sd_default_tx_phase;
1810
1811 goto Search_Finish;
1812 }
1813
1814 cont_path_cnt = 0;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001815 new_block = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001816 j = 0;
1817 for (i = 0; i < MAX_PHASE + 1; i++) {
1818 if (phase_map & (1 << i)) {
1819 if (new_block) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001820 new_block = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001821 j = cont_path_cnt++;
1822 path[j].start = i;
1823 path[j].end = i;
1824 } else {
1825 path[j].end = i;
1826 }
1827 } else {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001828 new_block = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001829 if (cont_path_cnt) {
1830 int idx = cont_path_cnt - 1;
Tina Johnson767c6a52014-09-21 11:38:11 +05301831
Micky Chingfa590c22013-11-12 17:16:08 +08001832 path[idx].len = path[idx].end -
1833 path[idx].start + 1;
1834 path[idx].mid = path[idx].start +
1835 path[idx].len / 2;
1836 }
1837 }
1838 }
1839
1840 if (cont_path_cnt == 0) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001841 dev_dbg(rtsx_dev(chip), "No continuous phase path\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001842 goto Search_Finish;
1843 } else {
1844 int idx = cont_path_cnt - 1;
Tina Johnson767c6a52014-09-21 11:38:11 +05301845
Micky Chingfa590c22013-11-12 17:16:08 +08001846 path[idx].len = path[idx].end - path[idx].start + 1;
1847 path[idx].mid = path[idx].start + path[idx].len / 2;
1848 }
1849
1850 if ((path[0].start == 0) &&
1851 (path[cont_path_cnt - 1].end == MAX_PHASE)) {
1852 path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
1853 path[0].len += path[cont_path_cnt - 1].len;
1854 path[0].mid = path[0].start + path[0].len / 2;
1855 if (path[0].mid < 0)
1856 path[0].mid += MAX_PHASE + 1;
1857
1858 cont_path_cnt--;
1859 }
1860
1861 max_len = 0;
1862 final_phase = 0;
1863 final_path_idx = 0;
1864 for (i = 0; i < cont_path_cnt; i++) {
1865 if (path[i].len > max_len) {
1866 max_len = path[i].len;
1867 final_phase = (u8)path[i].mid;
1868 final_path_idx = i;
1869 }
1870
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001871 dev_dbg(rtsx_dev(chip), "path[%d].start = %d\n",
1872 i, path[i].start);
1873 dev_dbg(rtsx_dev(chip), "path[%d].end = %d\n", i, path[i].end);
1874 dev_dbg(rtsx_dev(chip), "path[%d].len = %d\n", i, path[i].len);
1875 dev_dbg(rtsx_dev(chip), "path[%d].mid = %d\n", i, path[i].mid);
1876 dev_dbg(rtsx_dev(chip), "\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001877 }
1878
1879 if (tune_dir == TUNE_TX) {
1880 if (CHK_SD_SDR104(sd_card)) {
1881 if (max_len > 15) {
1882 int temp_mid = (max_len - 16) / 2;
1883 int temp_final_phase =
1884 path[final_path_idx].end -
1885 (max_len - (6 + temp_mid));
1886
1887 if (temp_final_phase < 0)
1888 final_phase = (u8)(temp_final_phase +
1889 MAX_PHASE + 1);
1890 else
1891 final_phase = (u8)temp_final_phase;
1892 }
1893 } else if (CHK_SD_SDR50(sd_card)) {
1894 if (max_len > 12) {
1895 int temp_mid = (max_len - 13) / 2;
1896 int temp_final_phase =
1897 path[final_path_idx].end -
1898 (max_len - (3 + temp_mid));
1899
1900 if (temp_final_phase < 0)
1901 final_phase = (u8)(temp_final_phase +
1902 MAX_PHASE + 1);
1903 else
1904 final_phase = (u8)temp_final_phase;
1905 }
1906 }
1907 }
1908
1909Search_Finish:
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001910 dev_dbg(rtsx_dev(chip), "Final chosen phase: %d\n", final_phase);
Micky Chingfa590c22013-11-12 17:16:08 +08001911 return final_phase;
1912}
1913
1914static int sd_tuning_rx(struct rtsx_chip *chip)
1915{
1916 struct sd_info *sd_card = &(chip->sd_card);
1917 int retval;
1918 int i, j;
1919 u32 raw_phase_map[3], phase_map;
1920 u8 final_phase;
1921 int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
1922
1923 if (CHK_SD(sd_card)) {
1924 if (CHK_SD_DDR50(sd_card))
1925 tuning_cmd = sd_ddr_tuning_rx_cmd;
1926 else
1927 tuning_cmd = sd_sdr_tuning_rx_cmd;
1928
1929 } else {
Nicholas Sim649b55b2016-04-05 17:47:35 +01001930 if (CHK_MMC_DDR52(sd_card)) {
Micky Chingfa590c22013-11-12 17:16:08 +08001931 tuning_cmd = mmc_ddr_tunning_rx_cmd;
Nicholas Sim649b55b2016-04-05 17:47:35 +01001932 } else {
Joe Perches031366e2015-03-25 12:54:25 -07001933 rtsx_trace(chip);
1934 return STATUS_FAIL;
1935 }
Micky Chingfa590c22013-11-12 17:16:08 +08001936 }
1937
1938 for (i = 0; i < 3; i++) {
1939 raw_phase_map[i] = 0;
1940 for (j = MAX_PHASE; j >= 0; j--) {
1941 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
1942 sd_set_err_code(chip, SD_NO_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07001943 rtsx_trace(chip);
1944 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001945 }
1946
1947 retval = tuning_cmd(chip, (u8)j);
1948 if (retval == STATUS_SUCCESS)
1949 raw_phase_map[i] |= 1 << j;
1950 }
1951 }
1952
1953 phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
1954 for (i = 0; i < 3; i++)
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001955 dev_dbg(rtsx_dev(chip), "RX raw_phase_map[%d] = 0x%08x\n",
1956 i, raw_phase_map[i]);
Micky Chingfa590c22013-11-12 17:16:08 +08001957
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001958 dev_dbg(rtsx_dev(chip), "RX phase_map = 0x%08x\n", phase_map);
Micky Chingfa590c22013-11-12 17:16:08 +08001959
1960 final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
Joe Perches031366e2015-03-25 12:54:25 -07001961 if (final_phase == 0xFF) {
1962 rtsx_trace(chip);
1963 return STATUS_FAIL;
1964 }
Micky Chingfa590c22013-11-12 17:16:08 +08001965
1966 retval = sd_change_phase(chip, final_phase, TUNE_RX);
Joe Perches031366e2015-03-25 12:54:25 -07001967 if (retval != STATUS_SUCCESS) {
1968 rtsx_trace(chip);
1969 return STATUS_FAIL;
1970 }
Micky Chingfa590c22013-11-12 17:16:08 +08001971
1972 return STATUS_SUCCESS;
1973}
1974
1975static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
1976{
1977 struct sd_info *sd_card = &(chip->sd_card);
1978 int retval;
1979 int i;
1980 u32 phase_map;
1981 u8 final_phase;
1982
Joe Perches8ee775f2015-03-25 12:54:26 -07001983 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
1984 SD_RSP_80CLK_TIMEOUT_EN);
1985 if (retval) {
1986 rtsx_trace(chip);
1987 return retval;
1988 }
Micky Chingfa590c22013-11-12 17:16:08 +08001989
1990 phase_map = 0;
1991 for (i = MAX_PHASE; i >= 0; i--) {
1992 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
1993 sd_set_err_code(chip, SD_NO_CARD);
1994 rtsx_write_register(chip, SD_CFG3,
1995 SD_RSP_80CLK_TIMEOUT_EN, 0);
Joe Perches031366e2015-03-25 12:54:25 -07001996 rtsx_trace(chip);
1997 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001998 }
1999
2000 retval = sd_change_phase(chip, (u8)i, TUNE_TX);
2001 if (retval != STATUS_SUCCESS)
2002 continue;
2003
2004 retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
2005 sd_card->sd_addr, SD_RSP_TYPE_R1, NULL,
2006 0);
2007 if ((retval == STATUS_SUCCESS) ||
2008 !sd_check_err_code(chip, SD_RSP_TIMEOUT))
2009 phase_map |= 1 << i;
2010 }
2011
Joe Perches8ee775f2015-03-25 12:54:26 -07002012 retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
2013 0);
2014 if (retval) {
2015 rtsx_trace(chip);
2016 return retval;
2017 }
Micky Chingfa590c22013-11-12 17:16:08 +08002018
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002019 dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase_map = 0x%08x\n",
2020 phase_map);
Micky Chingfa590c22013-11-12 17:16:08 +08002021
2022 final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002023 if (final_phase == 0xFF) {
2024 rtsx_trace(chip);
2025 return STATUS_FAIL;
2026 }
Micky Chingfa590c22013-11-12 17:16:08 +08002027
2028 retval = sd_change_phase(chip, final_phase, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002029 if (retval != STATUS_SUCCESS) {
2030 rtsx_trace(chip);
2031 return STATUS_FAIL;
2032 }
Micky Chingfa590c22013-11-12 17:16:08 +08002033
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002034 dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase: %d\n",
2035 (int)final_phase);
Micky Chingfa590c22013-11-12 17:16:08 +08002036
2037 return STATUS_SUCCESS;
2038}
2039
2040static int sd_tuning_tx(struct rtsx_chip *chip)
2041{
2042 struct sd_info *sd_card = &(chip->sd_card);
2043 int retval;
2044 int i, j;
2045 u32 raw_phase_map[3], phase_map;
2046 u8 final_phase;
2047 int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
2048
2049 if (CHK_SD(sd_card)) {
2050 if (CHK_SD_DDR50(sd_card))
2051 tuning_cmd = sd_ddr_tuning_tx_cmd;
2052 else
2053 tuning_cmd = sd_sdr_tuning_tx_cmd;
2054
2055 } else {
Nicholas Sim649b55b2016-04-05 17:47:35 +01002056 if (CHK_MMC_DDR52(sd_card)) {
Micky Chingfa590c22013-11-12 17:16:08 +08002057 tuning_cmd = sd_ddr_tuning_tx_cmd;
Nicholas Sim649b55b2016-04-05 17:47:35 +01002058 } else {
Joe Perches031366e2015-03-25 12:54:25 -07002059 rtsx_trace(chip);
2060 return STATUS_FAIL;
2061 }
Micky Chingfa590c22013-11-12 17:16:08 +08002062 }
2063
2064 for (i = 0; i < 3; i++) {
2065 raw_phase_map[i] = 0;
2066 for (j = MAX_PHASE; j >= 0; j--) {
2067 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
2068 sd_set_err_code(chip, SD_NO_CARD);
2069 rtsx_write_register(chip, SD_CFG3,
2070 SD_RSP_80CLK_TIMEOUT_EN, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002071 rtsx_trace(chip);
2072 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08002073 }
2074
2075 retval = tuning_cmd(chip, (u8)j);
2076 if (retval == STATUS_SUCCESS)
2077 raw_phase_map[i] |= 1 << j;
2078 }
2079 }
2080
2081 phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
2082 for (i = 0; i < 3; i++)
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002083 dev_dbg(rtsx_dev(chip), "TX raw_phase_map[%d] = 0x%08x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08002084 i, raw_phase_map[i]);
2085
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002086 dev_dbg(rtsx_dev(chip), "TX phase_map = 0x%08x\n", phase_map);
Micky Chingfa590c22013-11-12 17:16:08 +08002087
2088 final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002089 if (final_phase == 0xFF) {
2090 rtsx_trace(chip);
2091 return STATUS_FAIL;
2092 }
Micky Chingfa590c22013-11-12 17:16:08 +08002093
2094 retval = sd_change_phase(chip, final_phase, TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002095 if (retval != STATUS_SUCCESS) {
2096 rtsx_trace(chip);
2097 return STATUS_FAIL;
2098 }
Micky Chingfa590c22013-11-12 17:16:08 +08002099
2100 return STATUS_SUCCESS;
2101}
2102
2103static int sd_sdr_tuning(struct rtsx_chip *chip)
2104{
2105 int retval;
2106
2107 retval = sd_tuning_tx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002108 if (retval != STATUS_SUCCESS) {
2109 rtsx_trace(chip);
2110 return STATUS_FAIL;
2111 }
Micky Chingfa590c22013-11-12 17:16:08 +08002112
2113 retval = sd_tuning_rx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002114 if (retval != STATUS_SUCCESS) {
2115 rtsx_trace(chip);
2116 return STATUS_FAIL;
2117 }
Micky Chingfa590c22013-11-12 17:16:08 +08002118
2119 return STATUS_SUCCESS;
2120}
2121
2122static int sd_ddr_tuning(struct rtsx_chip *chip)
2123{
2124 int retval;
2125
2126 if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
2127 retval = sd_ddr_pre_tuning_tx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002128 if (retval != STATUS_SUCCESS) {
2129 rtsx_trace(chip);
2130 return STATUS_FAIL;
2131 }
Micky Chingfa590c22013-11-12 17:16:08 +08002132 } else {
2133 retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase,
2134 TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002135 if (retval != STATUS_SUCCESS) {
2136 rtsx_trace(chip);
2137 return STATUS_FAIL;
2138 }
Micky Chingfa590c22013-11-12 17:16:08 +08002139 }
2140
2141 retval = sd_tuning_rx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002142 if (retval != STATUS_SUCCESS) {
2143 rtsx_trace(chip);
2144 return STATUS_FAIL;
2145 }
Micky Chingfa590c22013-11-12 17:16:08 +08002146
2147 if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
2148 retval = sd_tuning_tx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002149 if (retval != STATUS_SUCCESS) {
2150 rtsx_trace(chip);
2151 return STATUS_FAIL;
2152 }
Micky Chingfa590c22013-11-12 17:16:08 +08002153 }
2154
2155 return STATUS_SUCCESS;
2156}
2157
2158static int mmc_ddr_tuning(struct rtsx_chip *chip)
2159{
2160 int retval;
2161
2162 if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
2163 retval = sd_ddr_pre_tuning_tx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002164 if (retval != STATUS_SUCCESS) {
2165 rtsx_trace(chip);
2166 return STATUS_FAIL;
2167 }
Micky Chingfa590c22013-11-12 17:16:08 +08002168 } else {
2169 retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase,
2170 TUNE_TX);
Joe Perches031366e2015-03-25 12:54:25 -07002171 if (retval != STATUS_SUCCESS) {
2172 rtsx_trace(chip);
2173 return STATUS_FAIL;
2174 }
Micky Chingfa590c22013-11-12 17:16:08 +08002175 }
2176
2177 retval = sd_tuning_rx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002178 if (retval != STATUS_SUCCESS) {
2179 rtsx_trace(chip);
2180 return STATUS_FAIL;
2181 }
Micky Chingfa590c22013-11-12 17:16:08 +08002182
2183 if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
2184 retval = sd_tuning_tx(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002185 if (retval != STATUS_SUCCESS) {
2186 rtsx_trace(chip);
2187 return STATUS_FAIL;
2188 }
Micky Chingfa590c22013-11-12 17:16:08 +08002189 }
2190
2191 return STATUS_SUCCESS;
2192}
2193
2194int sd_switch_clock(struct rtsx_chip *chip)
2195{
2196 struct sd_info *sd_card = &(chip->sd_card);
2197 int retval;
2198 int re_tuning = 0;
2199
2200 retval = select_card(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07002201 if (retval != STATUS_SUCCESS) {
2202 rtsx_trace(chip);
2203 return STATUS_FAIL;
2204 }
Micky Chingfa590c22013-11-12 17:16:08 +08002205
2206 retval = switch_clock(chip, sd_card->sd_clock);
Joe Perches031366e2015-03-25 12:54:25 -07002207 if (retval != STATUS_SUCCESS) {
2208 rtsx_trace(chip);
2209 return STATUS_FAIL;
2210 }
Micky Chingfa590c22013-11-12 17:16:08 +08002211
2212 if (re_tuning) {
2213 if (CHK_SD(sd_card)) {
2214 if (CHK_SD_DDR50(sd_card))
2215 retval = sd_ddr_tuning(chip);
2216 else
2217 retval = sd_sdr_tuning(chip);
2218 } else {
2219 if (CHK_MMC_DDR52(sd_card))
2220 retval = mmc_ddr_tuning(chip);
2221 }
2222
Joe Perches031366e2015-03-25 12:54:25 -07002223 if (retval != STATUS_SUCCESS) {
2224 rtsx_trace(chip);
2225 return STATUS_FAIL;
2226 }
Micky Chingfa590c22013-11-12 17:16:08 +08002227 }
2228
2229 return STATUS_SUCCESS;
2230}
2231
2232static int sd_prepare_reset(struct rtsx_chip *chip)
2233{
2234 struct sd_info *sd_card = &(chip->sd_card);
2235 int retval;
2236
2237 if (chip->asic_code)
2238 sd_card->sd_clock = 29;
2239 else
2240 sd_card->sd_clock = CLK_30;
2241
2242 sd_card->sd_type = 0;
2243 sd_card->seq_mode = 0;
2244 sd_card->sd_data_buf_ready = 0;
2245 sd_card->capacity = 0;
2246
2247#ifdef SUPPORT_SD_LOCK
2248 sd_card->sd_lock_status = 0;
2249 sd_card->sd_erase_status = 0;
2250#endif
2251
2252 chip->capacity[chip->card2lun[SD_CARD]] = 0;
2253 chip->sd_io = 0;
2254
2255 retval = sd_set_init_para(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002256 if (retval != STATUS_SUCCESS) {
2257 rtsx_trace(chip);
2258 return retval;
2259 }
Micky Chingfa590c22013-11-12 17:16:08 +08002260
Joe Perches8ee775f2015-03-25 12:54:26 -07002261 retval = rtsx_write_register(chip, REG_SD_CFG1, 0xFF, 0x40);
2262 if (retval) {
2263 rtsx_trace(chip);
2264 return retval;
2265 }
Micky Chingfa590c22013-11-12 17:16:08 +08002266
Joe Perches8ee775f2015-03-25 12:54:26 -07002267 retval = rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
2268 SD_STOP | SD_CLR_ERR);
2269 if (retval) {
2270 rtsx_trace(chip);
2271 return retval;
2272 }
Micky Chingfa590c22013-11-12 17:16:08 +08002273
2274 retval = select_card(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07002275 if (retval != STATUS_SUCCESS) {
2276 rtsx_trace(chip);
2277 return STATUS_FAIL;
2278 }
Micky Chingfa590c22013-11-12 17:16:08 +08002279
2280 return STATUS_SUCCESS;
2281}
2282
2283static int sd_pull_ctl_disable(struct rtsx_chip *chip)
2284{
Joe Perches8ee775f2015-03-25 12:54:26 -07002285 int retval;
2286
Micky Chingfa590c22013-11-12 17:16:08 +08002287 if (CHECK_PID(chip, 0x5208)) {
Joe Perches8ee775f2015-03-25 12:54:26 -07002288 retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
2289 XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
2290 if (retval) {
2291 rtsx_trace(chip);
2292 return retval;
2293 }
2294 retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
2295 SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
2296 if (retval) {
2297 rtsx_trace(chip);
2298 return retval;
2299 }
2300 retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
2301 SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
2302 if (retval) {
2303 rtsx_trace(chip);
2304 return retval;
2305 }
2306 retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
2307 XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
2308 if (retval) {
2309 rtsx_trace(chip);
2310 return retval;
2311 }
2312 retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
2313 MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
2314 if (retval) {
2315 rtsx_trace(chip);
2316 return retval;
2317 }
2318 retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
2319 MS_D5_PD | MS_D4_PD);
2320 if (retval) {
2321 rtsx_trace(chip);
2322 return retval;
2323 }
Micky Chingfa590c22013-11-12 17:16:08 +08002324 } else if (CHECK_PID(chip, 0x5288)) {
2325 if (CHECK_BARO_PKG(chip, QFN)) {
Joe Perches8ee775f2015-03-25 12:54:26 -07002326 retval = rtsx_write_register(chip, CARD_PULL_CTL1,
2327 0xFF, 0x55);
2328 if (retval) {
2329 rtsx_trace(chip);
2330 return retval;
2331 }
2332 retval = rtsx_write_register(chip, CARD_PULL_CTL2,
2333 0xFF, 0x55);
2334 if (retval) {
2335 rtsx_trace(chip);
2336 return retval;
2337 }
2338 retval = rtsx_write_register(chip, CARD_PULL_CTL3,
2339 0xFF, 0x4B);
2340 if (retval) {
2341 rtsx_trace(chip);
2342 return retval;
2343 }
2344 retval = rtsx_write_register(chip, CARD_PULL_CTL4,
2345 0xFF, 0x69);
2346 if (retval) {
2347 rtsx_trace(chip);
2348 return retval;
2349 }
Micky Chingfa590c22013-11-12 17:16:08 +08002350 }
2351 }
2352
2353 return STATUS_SUCCESS;
2354}
2355
2356int sd_pull_ctl_enable(struct rtsx_chip *chip)
2357{
2358 int retval;
2359
2360 rtsx_init_cmd(chip);
2361
2362 if (CHECK_PID(chip, 0x5208)) {
2363 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
2364 XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
2365 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
2366 SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
2367 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
2368 SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
2369 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
2370 XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
2371 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
2372 MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
2373 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
2374 MS_D5_PD | MS_D4_PD);
2375 } else if (CHECK_PID(chip, 0x5288)) {
2376 if (CHECK_BARO_PKG(chip, QFN)) {
2377 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
2378 0xA8);
2379 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
2380 0x5A);
2381 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
2382 0x95);
2383 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
2384 0xAA);
2385 }
2386 }
2387
2388 retval = rtsx_send_cmd(chip, SD_CARD, 100);
Joe Perches031366e2015-03-25 12:54:25 -07002389 if (retval < 0) {
2390 rtsx_trace(chip);
2391 return STATUS_FAIL;
2392 }
Micky Chingfa590c22013-11-12 17:16:08 +08002393
2394 return STATUS_SUCCESS;
2395}
2396
2397static int sd_init_power(struct rtsx_chip *chip)
2398{
2399 int retval;
2400
2401 retval = sd_power_off_card3v3(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002402 if (retval != STATUS_SUCCESS) {
2403 rtsx_trace(chip);
2404 return STATUS_FAIL;
2405 }
Micky Chingfa590c22013-11-12 17:16:08 +08002406
2407 if (!chip->ft2_fast_mode)
2408 wait_timeout(250);
2409
2410 retval = enable_card_clock(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07002411 if (retval != STATUS_SUCCESS) {
2412 rtsx_trace(chip);
2413 return STATUS_FAIL;
2414 }
Micky Chingfa590c22013-11-12 17:16:08 +08002415
2416 if (chip->asic_code) {
2417 retval = sd_pull_ctl_enable(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002418 if (retval != STATUS_SUCCESS) {
2419 rtsx_trace(chip);
2420 return STATUS_FAIL;
2421 }
Micky Chingfa590c22013-11-12 17:16:08 +08002422 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -07002423 retval = rtsx_write_register(chip, FPGA_PULL_CTL,
2424 FPGA_SD_PULL_CTL_BIT | 0x20, 0);
2425 if (retval) {
2426 rtsx_trace(chip);
2427 return retval;
2428 }
Micky Chingfa590c22013-11-12 17:16:08 +08002429 }
2430
2431 if (!chip->ft2_fast_mode) {
2432 retval = card_power_on(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07002433 if (retval != STATUS_SUCCESS) {
2434 rtsx_trace(chip);
2435 return STATUS_FAIL;
2436 }
Micky Chingfa590c22013-11-12 17:16:08 +08002437
2438 wait_timeout(260);
2439
2440#ifdef SUPPORT_OCP
2441 if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002442 dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08002443 chip->ocp_stat);
Joe Perches031366e2015-03-25 12:54:25 -07002444 rtsx_trace(chip);
2445 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08002446 }
2447#endif
2448 }
2449
Joe Perches8ee775f2015-03-25 12:54:26 -07002450 retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
2451 SD_OUTPUT_EN);
2452 if (retval) {
2453 rtsx_trace(chip);
2454 return retval;
2455 }
Micky Chingfa590c22013-11-12 17:16:08 +08002456
2457 return STATUS_SUCCESS;
2458}
2459
2460static int sd_dummy_clock(struct rtsx_chip *chip)
2461{
Joe Perches8ee775f2015-03-25 12:54:26 -07002462 int retval;
2463
2464 retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0x01);
2465 if (retval) {
2466 rtsx_trace(chip);
2467 return retval;
2468 }
Micky Chingfa590c22013-11-12 17:16:08 +08002469 wait_timeout(5);
Joe Perches8ee775f2015-03-25 12:54:26 -07002470 retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0);
2471 if (retval) {
2472 rtsx_trace(chip);
2473 return retval;
2474 }
Micky Chingfa590c22013-11-12 17:16:08 +08002475
2476 return STATUS_SUCCESS;
2477}
2478
2479static int sd_read_lba0(struct rtsx_chip *chip)
2480{
2481 struct sd_info *sd_card = &(chip->sd_card);
2482 int retval;
2483 u8 cmd[5], bus_width;
2484
2485 cmd[0] = 0x40 | READ_SINGLE_BLOCK;
2486 cmd[1] = 0;
2487 cmd[2] = 0;
2488 cmd[3] = 0;
2489 cmd[4] = 0;
2490
2491 if (CHK_SD(sd_card)) {
2492 bus_width = SD_BUS_WIDTH_4;
2493 } else {
2494 if (CHK_MMC_8BIT(sd_card))
2495 bus_width = SD_BUS_WIDTH_8;
2496 else if (CHK_MMC_4BIT(sd_card))
2497 bus_width = SD_BUS_WIDTH_4;
2498 else
2499 bus_width = SD_BUS_WIDTH_1;
2500 }
2501
2502 retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd,
2503 5, 512, 1, bus_width, NULL, 0, 100);
2504 if (retval != STATUS_SUCCESS) {
2505 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07002506 rtsx_trace(chip);
2507 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08002508 }
2509
2510 return STATUS_SUCCESS;
2511}
2512
2513static int sd_check_wp_state(struct rtsx_chip *chip)
2514{
2515 struct sd_info *sd_card = &(chip->sd_card);
2516 int retval;
2517 u32 val;
2518 u16 sd_card_type;
2519 u8 cmd[5], buf[64];
2520
2521 retval = sd_send_cmd_get_rsp(chip, APP_CMD,
2522 sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002523 if (retval != STATUS_SUCCESS) {
2524 rtsx_trace(chip);
2525 return STATUS_FAIL;
2526 }
Micky Chingfa590c22013-11-12 17:16:08 +08002527
2528 cmd[0] = 0x40 | SD_STATUS;
2529 cmd[1] = 0;
2530 cmd[2] = 0;
2531 cmd[3] = 0;
2532 cmd[4] = 0;
2533
2534 retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1,
2535 SD_BUS_WIDTH_4, buf, 64, 250);
2536 if (retval != STATUS_SUCCESS) {
2537 rtsx_clear_sd_error(chip);
2538
2539 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
2540 SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002541 rtsx_trace(chip);
2542 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08002543 }
2544
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002545 dev_dbg(rtsx_dev(chip), "ACMD13:\n");
Fabio Falzoi69b8b222014-08-05 23:24:17 +02002546 dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
Micky Chingfa590c22013-11-12 17:16:08 +08002547
2548 sd_card_type = ((u16)buf[2] << 8) | buf[3];
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002549 dev_dbg(rtsx_dev(chip), "sd_card_type = 0x%04x\n", sd_card_type);
Micky Chingfa590c22013-11-12 17:16:08 +08002550 if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) {
2551 /* ROM card or OTP */
2552 chip->card_wp |= SD_CARD;
2553 }
2554
2555 /* Check SD Machanical Write-Protect Switch */
2556 val = rtsx_readl(chip, RTSX_BIPR);
2557 if (val & SD_WRITE_PROTECT)
2558 chip->card_wp |= SD_CARD;
2559
2560 return STATUS_SUCCESS;
2561}
2562
2563static int reset_sd(struct rtsx_chip *chip)
2564{
2565 struct sd_info *sd_card = &(chip->sd_card);
Quentin Lambertde904bf2015-03-04 11:31:01 +01002566 bool hi_cap_flow = false;
2567 int retval, i = 0, j = 0, k = 0;
2568 bool sd_dont_switch = false;
2569 bool support_1v8 = false;
2570 bool try_sdio = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002571 u8 rsp[16];
2572 u8 switch_bus_width;
2573 u32 voltage = 0;
Quentin Lambertde904bf2015-03-04 11:31:01 +01002574 bool sd20_mode = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002575
2576 SET_SD(sd_card);
2577
2578Switch_Fail:
2579
2580 i = 0;
2581 j = 0;
2582 k = 0;
Quentin Lambertde904bf2015-03-04 11:31:01 +01002583 hi_cap_flow = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002584
2585#ifdef SUPPORT_SD_LOCK
2586 if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
2587 goto SD_UNLOCK_ENTRY;
2588#endif
2589
2590 retval = sd_prepare_reset(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002591 if (retval != STATUS_SUCCESS)
2592 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002593
2594 retval = sd_dummy_clock(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002595 if (retval != STATUS_SUCCESS)
2596 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002597
2598 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
2599 int rty_cnt = 0;
2600
2601 for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
2602 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
2603 sd_set_err_code(chip, SD_NO_CARD);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002604 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002605 }
2606
2607 retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0,
2608 SD_RSP_TYPE_R4, rsp, 5);
2609 if (retval == STATUS_SUCCESS) {
2610 int func_num = (rsp[1] >> 4) & 0x07;
Tina Johnson767c6a52014-09-21 11:38:11 +05302611
Micky Chingfa590c22013-11-12 17:16:08 +08002612 if (func_num) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002613 dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n",
2614 func_num);
Micky Chingfa590c22013-11-12 17:16:08 +08002615 chip->sd_io = 1;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002616 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002617 }
2618
2619 break;
2620 }
2621
2622 sd_init_power(chip);
2623
2624 sd_dummy_clock(chip);
2625 }
2626
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002627 dev_dbg(rtsx_dev(chip), "Normal card!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002628 }
2629
2630 /* Start Initialization Process of SD Card */
2631RTY_SD_RST:
2632 retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
2633 NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002634 if (retval != STATUS_SUCCESS)
2635 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002636
2637 wait_timeout(20);
2638
2639 retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA,
2640 SD_RSP_TYPE_R7, rsp, 5);
2641 if (retval == STATUS_SUCCESS) {
2642 if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01002643 hi_cap_flow = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002644 voltage = SUPPORT_VOLTAGE | 0x40000000;
2645 }
2646 }
2647
2648 if (!hi_cap_flow) {
2649 voltage = SUPPORT_VOLTAGE;
2650
2651 retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0,
2652 SD_RSP_TYPE_R0, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002653 if (retval != STATUS_SUCCESS)
2654 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002655
2656 wait_timeout(20);
2657 }
2658
2659 do {
2660 retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1,
2661 NULL, 0);
2662 if (retval != STATUS_SUCCESS) {
2663 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
2664 sd_set_err_code(chip, SD_NO_CARD);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002665 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002666 }
2667
2668 j++;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002669 if (j < 3)
Micky Chingfa590c22013-11-12 17:16:08 +08002670 goto RTY_SD_RST;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002671 else
2672 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002673 }
2674
2675 retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage,
2676 SD_RSP_TYPE_R3, rsp, 5);
2677 if (retval != STATUS_SUCCESS) {
2678 k++;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002679 if (k < 3)
Micky Chingfa590c22013-11-12 17:16:08 +08002680 goto RTY_SD_RST;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002681 else
2682 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002683 }
2684
2685 i++;
2686 wait_timeout(20);
2687 } while (!(rsp[1] & 0x80) && (i < 255));
2688
Sergio Paracuellose040b622016-09-23 16:12:13 +02002689 if (i == 255)
2690 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002691
2692 if (hi_cap_flow) {
2693 if (rsp[1] & 0x40)
2694 SET_SD_HCXC(sd_card);
2695 else
2696 CLR_SD_HCXC(sd_card);
2697
Quentin Lambertde904bf2015-03-04 11:31:01 +01002698 support_1v8 = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002699 } else {
2700 CLR_SD_HCXC(sd_card);
Quentin Lambertde904bf2015-03-04 11:31:01 +01002701 support_1v8 = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002702 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002703 dev_dbg(rtsx_dev(chip), "support_1v8 = %d\n", support_1v8);
Micky Chingfa590c22013-11-12 17:16:08 +08002704
2705 if (support_1v8) {
2706 retval = sd_voltage_switch(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002707 if (retval != STATUS_SUCCESS)
2708 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002709 }
2710
2711 retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
2712 NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002713 if (retval != STATUS_SUCCESS)
2714 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002715
2716 for (i = 0; i < 3; i++) {
2717 retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0,
2718 SD_RSP_TYPE_R6, rsp, 5);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002719 if (retval != STATUS_SUCCESS)
2720 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002721
2722 sd_card->sd_addr = (u32)rsp[1] << 24;
2723 sd_card->sd_addr += (u32)rsp[2] << 16;
2724
2725 if (sd_card->sd_addr)
2726 break;
2727 }
2728
2729 retval = sd_check_csd(chip, 1);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002730 if (retval != STATUS_SUCCESS)
2731 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002732
2733 retval = sd_select_card(chip, 1);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002734 if (retval != STATUS_SUCCESS)
2735 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002736
2737#ifdef SUPPORT_SD_LOCK
2738SD_UNLOCK_ENTRY:
2739 retval = sd_update_lock_status(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002740 if (retval != STATUS_SUCCESS)
2741 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002742
2743 if (sd_card->sd_lock_status & SD_LOCKED) {
2744 sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
2745 return STATUS_SUCCESS;
2746 } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
2747 sd_card->sd_lock_status &= ~SD_PWD_EXIST;
2748 }
2749#endif
2750
2751 retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
2752 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002753 if (retval != STATUS_SUCCESS)
2754 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002755
2756 retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0,
2757 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002758 if (retval != STATUS_SUCCESS)
2759 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002760
2761 if (support_1v8) {
2762 retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
2763 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002764 if (retval != STATUS_SUCCESS)
2765 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002766
2767 retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
2768 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002769 if (retval != STATUS_SUCCESS)
2770 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002771
2772 switch_bus_width = SD_BUS_WIDTH_4;
2773 } else {
2774 switch_bus_width = SD_BUS_WIDTH_1;
2775 }
2776
2777 retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
2778 NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002779 if (retval != STATUS_SUCCESS)
2780 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002781
2782 retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002783 if (retval != STATUS_SUCCESS)
2784 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002785
2786 if (!(sd_card->raw_csd[4] & 0x40))
Quentin Lambertde904bf2015-03-04 11:31:01 +01002787 sd_dont_switch = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002788
2789 if (!sd_dont_switch) {
2790 if (sd20_mode) {
2791 /* Set sd_switch_fail here, because we needn't
2792 * switch to UHS mode
2793 */
2794 sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
2795 DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
2796 }
2797
2798 /* Check the card whether follow SD1.1 spec or higher */
2799 retval = sd_check_spec(chip, switch_bus_width);
2800 if (retval == STATUS_SUCCESS) {
2801 retval = sd_switch_function(chip, switch_bus_width);
2802 if (retval != STATUS_SUCCESS) {
2803 sd_init_power(chip);
Quentin Lambertde904bf2015-03-04 11:31:01 +01002804 sd_dont_switch = true;
2805 try_sdio = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002806
2807 goto Switch_Fail;
2808 }
2809 } else {
2810 if (support_1v8) {
2811 sd_init_power(chip);
Quentin Lambertde904bf2015-03-04 11:31:01 +01002812 sd_dont_switch = true;
2813 try_sdio = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002814
2815 goto Switch_Fail;
2816 }
2817 }
2818 }
2819
2820 if (!support_1v8) {
2821 retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
2822 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002823 if (retval != STATUS_SUCCESS)
2824 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002825
2826 retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
2827 SD_RSP_TYPE_R1, NULL, 0);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002828 if (retval != STATUS_SUCCESS)
2829 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002830 }
2831
2832#ifdef SUPPORT_SD_LOCK
2833 sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
2834#endif
2835
2836 if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
2837 int read_lba0 = 1;
2838
Joe Perches8ee775f2015-03-25 12:54:26 -07002839 retval = rtsx_write_register(chip, SD30_DRIVE_SEL, 0x07,
2840 chip->sd30_drive_sel_1v8);
2841 if (retval) {
2842 rtsx_trace(chip);
2843 return retval;
2844 }
Micky Chingfa590c22013-11-12 17:16:08 +08002845
2846 retval = sd_set_init_para(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002847 if (retval != STATUS_SUCCESS)
2848 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002849
2850 if (CHK_SD_DDR50(sd_card))
2851 retval = sd_ddr_tuning(chip);
2852 else
2853 retval = sd_sdr_tuning(chip);
2854
2855 if (retval != STATUS_SUCCESS) {
2856 if (sd20_mode) {
Sergio Paracuellose040b622016-09-23 16:12:13 +02002857 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002858 } else {
2859 retval = sd_init_power(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002860 if (retval != STATUS_SUCCESS)
2861 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002862
Quentin Lambertde904bf2015-03-04 11:31:01 +01002863 try_sdio = false;
2864 sd20_mode = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002865 goto Switch_Fail;
2866 }
2867 }
2868
2869 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
2870 SD_RSP_TYPE_R1, NULL, 0);
2871
2872 if (CHK_SD_DDR50(sd_card)) {
2873 retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
2874 if (retval != STATUS_SUCCESS)
2875 read_lba0 = 0;
2876 }
2877
2878 if (read_lba0) {
2879 retval = sd_read_lba0(chip);
2880 if (retval != STATUS_SUCCESS) {
2881 if (sd20_mode) {
Sergio Paracuellose040b622016-09-23 16:12:13 +02002882 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002883 } else {
2884 retval = sd_init_power(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002885 if (retval != STATUS_SUCCESS)
2886 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002887
Quentin Lambertde904bf2015-03-04 11:31:01 +01002888 try_sdio = false;
2889 sd20_mode = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002890 goto Switch_Fail;
2891 }
2892 }
2893 }
2894 }
2895
2896 retval = sd_check_wp_state(chip);
Sergio Paracuellose040b622016-09-23 16:12:13 +02002897 if (retval != STATUS_SUCCESS)
2898 goto Status_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08002899
2900 chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
2901
2902#ifdef SUPPORT_SD_LOCK
2903 if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
Joe Perches8ee775f2015-03-25 12:54:26 -07002904 retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
2905 0x02);
2906 if (retval) {
2907 rtsx_trace(chip);
2908 return retval;
2909 }
2910 retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
2911 0x00);
2912 if (retval) {
2913 rtsx_trace(chip);
2914 return retval;
2915 }
Micky Chingfa590c22013-11-12 17:16:08 +08002916 }
2917#endif
2918
2919 return STATUS_SUCCESS;
Sergio Paracuellose040b622016-09-23 16:12:13 +02002920
2921Status_Fail:
2922 rtsx_trace(chip);
2923 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08002924}
2925
Micky Chingfa590c22013-11-12 17:16:08 +08002926static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
2927{
2928 struct sd_info *sd_card = &(chip->sd_card);
2929 int retval;
2930 u8 buf[8] = {0}, bus_width, *ptr;
2931 u16 byte_cnt;
2932 int len;
2933
2934 retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL,
2935 0);
Joe Perches031366e2015-03-25 12:54:25 -07002936 if (retval != STATUS_SUCCESS) {
2937 rtsx_trace(chip);
2938 return SWITCH_FAIL;
2939 }
Micky Chingfa590c22013-11-12 17:16:08 +08002940
2941 if (width == MMC_8BIT_BUS) {
2942 buf[0] = 0x55;
2943 buf[1] = 0xAA;
2944 len = 8;
2945 byte_cnt = 8;
2946 bus_width = SD_BUS_WIDTH_8;
2947 } else {
2948 buf[0] = 0x5A;
2949 len = 4;
2950 byte_cnt = 4;
2951 bus_width = SD_BUS_WIDTH_4;
2952 }
2953
2954 retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
Joe Perches031366e2015-03-25 12:54:25 -07002955 if (retval != STATUS_SUCCESS) {
2956 rtsx_trace(chip);
2957 return SWITCH_ERR;
2958 }
Micky Chingfa590c22013-11-12 17:16:08 +08002959
2960 retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
2961 NULL, 0, byte_cnt, 1, bus_width, buf, len, 100);
2962 if (retval != STATUS_SUCCESS) {
2963 rtsx_clear_sd_error(chip);
2964 rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002965 rtsx_trace(chip);
2966 return SWITCH_ERR;
Micky Chingfa590c22013-11-12 17:16:08 +08002967 }
2968
2969 retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002970 if (retval != STATUS_SUCCESS) {
2971 rtsx_trace(chip);
2972 return SWITCH_ERR;
2973 }
Micky Chingfa590c22013-11-12 17:16:08 +08002974
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002975 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", BUSTEST_R);
Micky Chingfa590c22013-11-12 17:16:08 +08002976
2977 rtsx_init_cmd(chip);
2978
2979 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
2980
2981 if (width == MMC_8BIT_BUS)
2982 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
2983 0xFF, 0x08);
2984 else
2985 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
2986 0xFF, 0x04);
2987
2988 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
2989 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
2990
2991 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
2992 SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END|
2993 SD_CHECK_CRC7 | SD_RSP_LEN_6);
2994 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
2995 PINGPONG_BUFFER);
2996 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
2997 SD_TM_NORMAL_READ | SD_TRANSFER_START);
2998 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
2999 SD_TRANSFER_END);
3000
3001 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
3002 if (width == MMC_8BIT_BUS)
3003 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
3004
3005 retval = rtsx_send_cmd(chip, SD_CARD, 100);
3006 if (retval < 0) {
3007 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003008 rtsx_trace(chip);
3009 return SWITCH_ERR;
Micky Chingfa590c22013-11-12 17:16:08 +08003010 }
3011
3012 ptr = rtsx_get_cmd_data(chip) + 1;
3013
3014 if (width == MMC_8BIT_BUS) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003015 dev_dbg(rtsx_dev(chip), "BUSTEST_R [8bits]: 0x%02x 0x%02x\n",
3016 ptr[0], ptr[1]);
Micky Chingfa590c22013-11-12 17:16:08 +08003017 if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) {
3018 u8 rsp[5];
3019 u32 arg;
3020
3021 if (CHK_MMC_DDR52(sd_card))
3022 arg = 0x03B70600;
3023 else
3024 arg = 0x03B70200;
3025
3026 retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
3027 SD_RSP_TYPE_R1b, rsp, 5);
3028 if ((retval == STATUS_SUCCESS) &&
3029 !(rsp[4] & MMC_SWITCH_ERR))
3030 return SWITCH_SUCCESS;
3031 }
3032 } else {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003033 dev_dbg(rtsx_dev(chip), "BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
Micky Chingfa590c22013-11-12 17:16:08 +08003034 if (ptr[0] == 0xA5) {
3035 u8 rsp[5];
3036 u32 arg;
3037
3038 if (CHK_MMC_DDR52(sd_card))
3039 arg = 0x03B70500;
3040 else
3041 arg = 0x03B70100;
3042
3043 retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
3044 SD_RSP_TYPE_R1b, rsp, 5);
3045 if ((retval == STATUS_SUCCESS) &&
3046 !(rsp[4] & MMC_SWITCH_ERR))
3047 return SWITCH_SUCCESS;
3048 }
3049 }
3050
Joe Perches031366e2015-03-25 12:54:25 -07003051 rtsx_trace(chip);
3052 return SWITCH_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003053}
3054
Quentin Lambert11201762015-03-04 11:31:53 +01003055static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr)
Micky Chingfa590c22013-11-12 17:16:08 +08003056{
3057 struct sd_info *sd_card = &(chip->sd_card);
3058 int retval;
3059 u8 *ptr, card_type, card_type_mask = 0;
3060
3061 CLR_MMC_HS(sd_card);
3062
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003063 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", SEND_EXT_CSD);
Micky Chingfa590c22013-11-12 17:16:08 +08003064
3065 rtsx_init_cmd(chip);
3066
3067 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
3068 0x40 | SEND_EXT_CSD);
3069 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
3070 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
3071 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
3072 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
3073
3074 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
3075 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
3076 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
3077 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
3078
3079 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
3080 SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END|
3081 SD_CHECK_CRC7 | SD_RSP_LEN_6);
3082 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
3083 PINGPONG_BUFFER);
3084 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
3085 SD_TM_NORMAL_READ | SD_TRANSFER_START);
3086 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
3087 SD_TRANSFER_END);
3088
3089 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
3090 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
3091 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
3092 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
3093 rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
3094
3095 retval = rtsx_send_cmd(chip, SD_CARD, 1000);
3096 if (retval < 0) {
3097 if (retval == -ETIMEDOUT) {
3098 rtsx_clear_sd_error(chip);
3099 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
3100 SD_RSP_TYPE_R1, NULL, 0);
3101 }
Joe Perches031366e2015-03-25 12:54:25 -07003102 rtsx_trace(chip);
3103 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003104 }
3105
3106 ptr = rtsx_get_cmd_data(chip);
3107 if (ptr[0] & SD_TRANSFER_ERR) {
3108 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
3109 SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003110 rtsx_trace(chip);
3111 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003112 }
3113
3114 if (CHK_MMC_SECTOR_MODE(sd_card)) {
3115 sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
3116 ((u32)ptr[3] << 8) | ((u32)ptr[2]);
3117 }
3118
3119 card_type_mask = 0x03;
3120 card_type = ptr[1] & card_type_mask;
3121 if (card_type) {
3122 u8 rsp[5];
3123
3124 if (card_type & 0x04) {
3125 if (switch_ddr)
3126 SET_MMC_DDR52(sd_card);
3127 else
3128 SET_MMC_52M(sd_card);
3129 } else if (card_type & 0x02) {
3130 SET_MMC_52M(sd_card);
3131 } else {
3132 SET_MMC_26M(sd_card);
3133 }
3134
3135 retval = sd_send_cmd_get_rsp(chip, SWITCH,
3136 0x03B90100, SD_RSP_TYPE_R1b, rsp, 5);
3137 if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR))
3138 CLR_MMC_HS(sd_card);
3139 }
3140
3141 sd_choose_proper_clock(chip);
3142 retval = switch_clock(chip, sd_card->sd_clock);
Joe Perches031366e2015-03-25 12:54:25 -07003143 if (retval != STATUS_SUCCESS) {
3144 rtsx_trace(chip);
3145 return STATUS_FAIL;
3146 }
Micky Chingfa590c22013-11-12 17:16:08 +08003147
3148 /* Test Bus Procedure */
3149 retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
3150 if (retval == SWITCH_SUCCESS) {
3151 SET_MMC_8BIT(sd_card);
3152 chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
3153#ifdef SUPPORT_SD_LOCK
3154 sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
3155#endif
3156 } else if (retval == SWITCH_FAIL) {
3157 retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
3158 if (retval == SWITCH_SUCCESS) {
3159 SET_MMC_4BIT(sd_card);
3160 chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
3161#ifdef SUPPORT_SD_LOCK
3162 sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
3163#endif
3164 } else if (retval == SWITCH_FAIL) {
3165 CLR_MMC_8BIT(sd_card);
3166 CLR_MMC_4BIT(sd_card);
3167 } else {
Joe Perches031366e2015-03-25 12:54:25 -07003168 rtsx_trace(chip);
3169 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003170 }
3171 } else {
Joe Perches031366e2015-03-25 12:54:25 -07003172 rtsx_trace(chip);
3173 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003174 }
3175
3176 return STATUS_SUCCESS;
3177}
3178
Micky Chingfa590c22013-11-12 17:16:08 +08003179static int reset_mmc(struct rtsx_chip *chip)
3180{
3181 struct sd_info *sd_card = &(chip->sd_card);
3182 int retval, i = 0, j = 0, k = 0;
Quentin Lambert11201762015-03-04 11:31:53 +01003183 bool switch_ddr = true;
Micky Chingfa590c22013-11-12 17:16:08 +08003184 u8 rsp[16];
3185 u8 spec_ver = 0;
3186 u32 temp;
3187
3188#ifdef SUPPORT_SD_LOCK
3189 if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
3190 goto MMC_UNLOCK_ENTRY;
3191#endif
3192
3193Switch_Fail:
3194 retval = sd_prepare_reset(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003195 if (retval != STATUS_SUCCESS) {
3196 rtsx_trace(chip);
3197 return retval;
3198 }
Micky Chingfa590c22013-11-12 17:16:08 +08003199
3200 SET_MMC(sd_card);
3201
3202RTY_MMC_RST:
3203 retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
3204 NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003205 if (retval != STATUS_SUCCESS) {
3206 rtsx_trace(chip);
3207 return STATUS_FAIL;
3208 }
Micky Chingfa590c22013-11-12 17:16:08 +08003209
3210 do {
3211 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
3212 sd_set_err_code(chip, SD_NO_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07003213 rtsx_trace(chip);
3214 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003215 }
3216
3217 retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
3218 (SUPPORT_VOLTAGE | 0x40000000),
3219 SD_RSP_TYPE_R3, rsp, 5);
3220 if (retval != STATUS_SUCCESS) {
3221 if (sd_check_err_code(chip, SD_BUSY) ||
3222 sd_check_err_code(chip, SD_TO_ERR)) {
3223 k++;
3224 if (k < 20) {
3225 sd_clr_err_code(chip);
3226 goto RTY_MMC_RST;
3227 } else {
Joe Perches031366e2015-03-25 12:54:25 -07003228 rtsx_trace(chip);
3229 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003230 }
3231 } else {
3232 j++;
3233 if (j < 100) {
3234 sd_clr_err_code(chip);
3235 goto RTY_MMC_RST;
3236 } else {
Joe Perches031366e2015-03-25 12:54:25 -07003237 rtsx_trace(chip);
3238 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003239 }
3240 }
3241 }
3242
3243 wait_timeout(20);
3244 i++;
3245 } while (!(rsp[1] & 0x80) && (i < 255));
3246
Joe Perches031366e2015-03-25 12:54:25 -07003247 if (i == 255) {
3248 rtsx_trace(chip);
3249 return STATUS_FAIL;
3250 }
Micky Chingfa590c22013-11-12 17:16:08 +08003251
3252 if ((rsp[1] & 0x60) == 0x40)
3253 SET_MMC_SECTOR_MODE(sd_card);
3254 else
3255 CLR_MMC_SECTOR_MODE(sd_card);
3256
3257 retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
3258 NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003259 if (retval != STATUS_SUCCESS) {
3260 rtsx_trace(chip);
3261 return STATUS_FAIL;
3262 }
Micky Chingfa590c22013-11-12 17:16:08 +08003263
3264 sd_card->sd_addr = 0x00100000;
3265 retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr,
3266 SD_RSP_TYPE_R6, rsp, 5);
Joe Perches031366e2015-03-25 12:54:25 -07003267 if (retval != STATUS_SUCCESS) {
3268 rtsx_trace(chip);
3269 return STATUS_FAIL;
3270 }
Micky Chingfa590c22013-11-12 17:16:08 +08003271
3272 retval = sd_check_csd(chip, 1);
Joe Perches031366e2015-03-25 12:54:25 -07003273 if (retval != STATUS_SUCCESS) {
3274 rtsx_trace(chip);
3275 return STATUS_FAIL;
3276 }
Micky Chingfa590c22013-11-12 17:16:08 +08003277
3278 spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
3279
3280 retval = sd_select_card(chip, 1);
Joe Perches031366e2015-03-25 12:54:25 -07003281 if (retval != STATUS_SUCCESS) {
3282 rtsx_trace(chip);
3283 return STATUS_FAIL;
3284 }
Micky Chingfa590c22013-11-12 17:16:08 +08003285
3286 retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
3287 NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003288 if (retval != STATUS_SUCCESS) {
3289 rtsx_trace(chip);
3290 return STATUS_FAIL;
3291 }
Micky Chingfa590c22013-11-12 17:16:08 +08003292
3293#ifdef SUPPORT_SD_LOCK
3294MMC_UNLOCK_ENTRY:
3295 retval = sd_update_lock_status(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003296 if (retval != STATUS_SUCCESS) {
3297 rtsx_trace(chip);
3298 return STATUS_FAIL;
3299 }
Micky Chingfa590c22013-11-12 17:16:08 +08003300#endif
3301
3302 retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
Joe Perches031366e2015-03-25 12:54:25 -07003303 if (retval != STATUS_SUCCESS) {
3304 rtsx_trace(chip);
3305 return STATUS_FAIL;
3306 }
Micky Chingfa590c22013-11-12 17:16:08 +08003307
3308 chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
3309
3310 if (!sd_card->mmc_dont_switch_bus) {
3311 if (spec_ver == 4) {
3312 /* MMC 4.x Cards */
3313 retval = mmc_switch_timing_bus(chip, switch_ddr);
3314 if (retval != STATUS_SUCCESS) {
3315 retval = sd_init_power(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003316 if (retval != STATUS_SUCCESS) {
3317 rtsx_trace(chip);
3318 return STATUS_FAIL;
3319 }
Micky Chingfa590c22013-11-12 17:16:08 +08003320 sd_card->mmc_dont_switch_bus = 1;
Joe Perches031366e2015-03-25 12:54:25 -07003321 rtsx_trace(chip);
3322 goto Switch_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08003323 }
3324 }
3325
Joe Perches031366e2015-03-25 12:54:25 -07003326 if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
3327 rtsx_trace(chip);
3328 return STATUS_FAIL;
3329 }
Micky Chingfa590c22013-11-12 17:16:08 +08003330
3331 if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
3332 retval = sd_set_init_para(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003333 if (retval != STATUS_SUCCESS) {
3334 rtsx_trace(chip);
3335 return STATUS_FAIL;
3336 }
Micky Chingfa590c22013-11-12 17:16:08 +08003337
3338 retval = mmc_ddr_tuning(chip);
3339 if (retval != STATUS_SUCCESS) {
3340 retval = sd_init_power(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003341 if (retval != STATUS_SUCCESS) {
3342 rtsx_trace(chip);
3343 return STATUS_FAIL;
3344 }
Micky Chingfa590c22013-11-12 17:16:08 +08003345
Quentin Lambert11201762015-03-04 11:31:53 +01003346 switch_ddr = false;
Joe Perches031366e2015-03-25 12:54:25 -07003347 rtsx_trace(chip);
3348 goto Switch_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08003349 }
3350
3351 retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
3352 if (retval == STATUS_SUCCESS) {
3353 retval = sd_read_lba0(chip);
3354 if (retval != STATUS_SUCCESS) {
3355 retval = sd_init_power(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003356 if (retval != STATUS_SUCCESS) {
3357 rtsx_trace(chip);
3358 return STATUS_FAIL;
3359 }
Micky Chingfa590c22013-11-12 17:16:08 +08003360
Quentin Lambert11201762015-03-04 11:31:53 +01003361 switch_ddr = false;
Joe Perches031366e2015-03-25 12:54:25 -07003362 rtsx_trace(chip);
3363 goto Switch_Fail;
Micky Chingfa590c22013-11-12 17:16:08 +08003364 }
3365 }
3366 }
3367 }
3368
3369#ifdef SUPPORT_SD_LOCK
3370 if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
Joe Perches8ee775f2015-03-25 12:54:26 -07003371 retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
3372 0x02);
3373 if (retval) {
3374 rtsx_trace(chip);
3375 return retval;
3376 }
3377 retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
3378 0x00);
3379 if (retval) {
3380 rtsx_trace(chip);
3381 return retval;
3382 }
Micky Chingfa590c22013-11-12 17:16:08 +08003383 }
3384#endif
3385
3386 temp = rtsx_readl(chip, RTSX_BIPR);
3387 if (temp & SD_WRITE_PROTECT)
3388 chip->card_wp |= SD_CARD;
3389
3390 return STATUS_SUCCESS;
3391}
3392
3393int reset_sd_card(struct rtsx_chip *chip)
3394{
3395 struct sd_info *sd_card = &(chip->sd_card);
3396 int retval;
3397
3398 sd_init_reg_addr(chip);
3399
3400 memset(sd_card, 0, sizeof(struct sd_info));
3401 chip->capacity[chip->card2lun[SD_CARD]] = 0;
3402
3403 retval = enable_card_clock(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07003404 if (retval != STATUS_SUCCESS) {
3405 rtsx_trace(chip);
3406 return STATUS_FAIL;
3407 }
Micky Chingfa590c22013-11-12 17:16:08 +08003408
3409 if (chip->ignore_sd && CHK_SDIO_EXIST(chip) &&
3410 !CHK_SDIO_IGNORED(chip)) {
3411 if (chip->asic_code) {
3412 retval = sd_pull_ctl_enable(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003413 if (retval != STATUS_SUCCESS) {
3414 rtsx_trace(chip);
3415 return STATUS_FAIL;
3416 }
Micky Chingfa590c22013-11-12 17:16:08 +08003417 } else {
3418 retval = rtsx_write_register(chip, FPGA_PULL_CTL,
3419 FPGA_SD_PULL_CTL_BIT | 0x20, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003420 if (retval != STATUS_SUCCESS) {
3421 rtsx_trace(chip);
3422 return STATUS_FAIL;
3423 }
Micky Chingfa590c22013-11-12 17:16:08 +08003424 }
3425 retval = card_share_mode(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07003426 if (retval != STATUS_SUCCESS) {
3427 rtsx_trace(chip);
3428 return STATUS_FAIL;
3429 }
Micky Chingfa590c22013-11-12 17:16:08 +08003430
3431 chip->sd_io = 1;
Joe Perches031366e2015-03-25 12:54:25 -07003432 rtsx_trace(chip);
3433 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003434 }
3435
3436 retval = sd_init_power(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003437 if (retval != STATUS_SUCCESS) {
3438 rtsx_trace(chip);
3439 return STATUS_FAIL;
3440 }
Micky Chingfa590c22013-11-12 17:16:08 +08003441
3442 if (chip->sd_ctl & RESET_MMC_FIRST) {
3443 retval = reset_mmc(chip);
3444 if (retval != STATUS_SUCCESS) {
Joe Perches031366e2015-03-25 12:54:25 -07003445 if (sd_check_err_code(chip, SD_NO_CARD)) {
3446 rtsx_trace(chip);
3447 return STATUS_FAIL;
3448 }
Micky Chingfa590c22013-11-12 17:16:08 +08003449
3450 retval = reset_sd(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003451 if (retval != STATUS_SUCCESS) {
3452 rtsx_trace(chip);
3453 return STATUS_FAIL;
3454 }
Micky Chingfa590c22013-11-12 17:16:08 +08003455 }
3456 } else {
3457 retval = reset_sd(chip);
3458 if (retval != STATUS_SUCCESS) {
Joe Perches031366e2015-03-25 12:54:25 -07003459 if (sd_check_err_code(chip, SD_NO_CARD)) {
3460 rtsx_trace(chip);
3461 return STATUS_FAIL;
3462 }
Micky Chingfa590c22013-11-12 17:16:08 +08003463
3464 if (chip->sd_io) {
Joe Perches031366e2015-03-25 12:54:25 -07003465 rtsx_trace(chip);
3466 return STATUS_FAIL;
Leung Timothy Chi King364b91b2015-07-01 09:44:13 -07003467 }
3468 retval = reset_mmc(chip);
3469 if (retval != STATUS_SUCCESS) {
3470 rtsx_trace(chip);
3471 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003472 }
3473 }
3474 }
3475
3476 retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
Joe Perches031366e2015-03-25 12:54:25 -07003477 if (retval != STATUS_SUCCESS) {
3478 rtsx_trace(chip);
3479 return STATUS_FAIL;
3480 }
Micky Chingfa590c22013-11-12 17:16:08 +08003481
Joe Perches8ee775f2015-03-25 12:54:26 -07003482 retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
3483 if (retval) {
3484 rtsx_trace(chip);
3485 return retval;
3486 }
3487 retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
3488 if (retval) {
3489 rtsx_trace(chip);
3490 return retval;
3491 }
Micky Chingfa590c22013-11-12 17:16:08 +08003492
3493 chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
3494
3495 retval = sd_set_init_para(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003496 if (retval != STATUS_SUCCESS) {
3497 rtsx_trace(chip);
3498 return STATUS_FAIL;
3499 }
Micky Chingfa590c22013-11-12 17:16:08 +08003500
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003501 dev_dbg(rtsx_dev(chip), "sd_card->sd_type = 0x%x\n", sd_card->sd_type);
Micky Chingfa590c22013-11-12 17:16:08 +08003502
3503 return STATUS_SUCCESS;
3504}
3505
3506static int reset_mmc_only(struct rtsx_chip *chip)
3507{
3508 struct sd_info *sd_card = &(chip->sd_card);
3509 int retval;
3510
3511 sd_card->sd_type = 0;
3512 sd_card->seq_mode = 0;
3513 sd_card->sd_data_buf_ready = 0;
3514 sd_card->capacity = 0;
3515 sd_card->sd_switch_fail = 0;
3516
3517#ifdef SUPPORT_SD_LOCK
3518 sd_card->sd_lock_status = 0;
3519 sd_card->sd_erase_status = 0;
3520#endif
3521
3522 chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
3523
3524 retval = enable_card_clock(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07003525 if (retval != STATUS_SUCCESS) {
3526 rtsx_trace(chip);
3527 return STATUS_FAIL;
3528 }
Micky Chingfa590c22013-11-12 17:16:08 +08003529
3530 retval = sd_init_power(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003531 if (retval != STATUS_SUCCESS) {
3532 rtsx_trace(chip);
3533 return STATUS_FAIL;
3534 }
Micky Chingfa590c22013-11-12 17:16:08 +08003535
3536 retval = reset_mmc(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003537 if (retval != STATUS_SUCCESS) {
3538 rtsx_trace(chip);
3539 return STATUS_FAIL;
3540 }
Micky Chingfa590c22013-11-12 17:16:08 +08003541
3542 retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
Joe Perches031366e2015-03-25 12:54:25 -07003543 if (retval != STATUS_SUCCESS) {
3544 rtsx_trace(chip);
3545 return STATUS_FAIL;
3546 }
Micky Chingfa590c22013-11-12 17:16:08 +08003547
Joe Perches8ee775f2015-03-25 12:54:26 -07003548 retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
3549 if (retval) {
3550 rtsx_trace(chip);
3551 return retval;
3552 }
3553 retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
3554 if (retval) {
3555 rtsx_trace(chip);
3556 return retval;
3557 }
Micky Chingfa590c22013-11-12 17:16:08 +08003558
3559 chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
3560
3561 retval = sd_set_init_para(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003562 if (retval != STATUS_SUCCESS) {
3563 rtsx_trace(chip);
3564 return STATUS_FAIL;
3565 }
Micky Chingfa590c22013-11-12 17:16:08 +08003566
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003567 dev_dbg(rtsx_dev(chip), "In reset_mmc_only, sd_card->sd_type = 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08003568 sd_card->sd_type);
3569
3570 return STATUS_SUCCESS;
3571}
3572
3573#define WAIT_DATA_READY_RTY_CNT 255
3574
3575static int wait_data_buf_ready(struct rtsx_chip *chip)
3576{
3577 struct sd_info *sd_card = &(chip->sd_card);
3578 int i, retval;
3579
3580 for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
3581 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
3582 sd_set_err_code(chip, SD_NO_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07003583 rtsx_trace(chip);
3584 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003585 }
3586
3587 sd_card->sd_data_buf_ready = 0;
3588
3589 retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
3590 sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
Joe Perches031366e2015-03-25 12:54:25 -07003591 if (retval != STATUS_SUCCESS) {
3592 rtsx_trace(chip);
3593 return STATUS_FAIL;
3594 }
Micky Chingfa590c22013-11-12 17:16:08 +08003595
3596 if (sd_card->sd_data_buf_ready) {
3597 return sd_send_cmd_get_rsp(chip, SEND_STATUS,
3598 sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
3599 }
3600 }
3601
3602 sd_set_err_code(chip, SD_TO_ERR);
3603
Joe Perches031366e2015-03-25 12:54:25 -07003604 rtsx_trace(chip);
3605 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003606}
3607
3608void sd_stop_seq_mode(struct rtsx_chip *chip)
3609{
3610 struct sd_info *sd_card = &(chip->sd_card);
3611 int retval;
3612
3613 if (sd_card->seq_mode) {
3614 retval = sd_switch_clock(chip);
3615 if (retval != STATUS_SUCCESS)
3616 return;
3617
3618 retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
3619 SD_RSP_TYPE_R1b, NULL, 0);
3620 if (retval != STATUS_SUCCESS)
3621 sd_set_err_code(chip, SD_STS_ERR);
3622
3623 retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
3624 if (retval != STATUS_SUCCESS)
3625 sd_set_err_code(chip, SD_STS_ERR);
3626
3627 sd_card->seq_mode = 0;
3628
3629 rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
3630 }
3631}
3632
3633static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
3634{
3635 struct sd_info *sd_card = &(chip->sd_card);
3636 int retval;
3637
3638 if (chip->asic_code) {
3639 if (sd_card->sd_clock > 30)
3640 sd_card->sd_clock -= 20;
3641 } else {
3642 switch (sd_card->sd_clock) {
3643 case CLK_200:
3644 sd_card->sd_clock = CLK_150;
3645 break;
3646
3647 case CLK_150:
3648 sd_card->sd_clock = CLK_120;
3649 break;
3650
3651 case CLK_120:
3652 sd_card->sd_clock = CLK_100;
3653 break;
3654
3655 case CLK_100:
3656 sd_card->sd_clock = CLK_80;
3657 break;
3658
3659 case CLK_80:
3660 sd_card->sd_clock = CLK_60;
3661 break;
3662
3663 case CLK_60:
3664 sd_card->sd_clock = CLK_50;
3665 break;
3666
3667 default:
3668 break;
3669 }
3670 }
3671
3672 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07003673 if (retval != STATUS_SUCCESS) {
3674 rtsx_trace(chip);
3675 return STATUS_FAIL;
3676 }
Micky Chingfa590c22013-11-12 17:16:08 +08003677
3678 return STATUS_SUCCESS;
3679}
3680
3681int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
3682 u16 sector_cnt)
3683{
3684 struct sd_info *sd_card = &(chip->sd_card);
3685 u32 data_addr;
3686 u8 cfg2;
3687 int retval;
3688
3689 if (srb->sc_data_direction == DMA_FROM_DEVICE) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003690 dev_dbg(rtsx_dev(chip), "sd_rw: Read %d %s from 0x%x\n",
3691 sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
3692 start_sector);
Micky Chingfa590c22013-11-12 17:16:08 +08003693 } else {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003694 dev_dbg(rtsx_dev(chip), "sd_rw: Write %d %s to 0x%x\n",
3695 sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
3696 start_sector);
Micky Chingfa590c22013-11-12 17:16:08 +08003697 }
3698
3699 sd_card->cleanup_counter = 0;
3700
3701 if (!(chip->card_ready & SD_CARD)) {
3702 sd_card->seq_mode = 0;
3703
3704 retval = reset_sd_card(chip);
3705 if (retval == STATUS_SUCCESS) {
3706 chip->card_ready |= SD_CARD;
3707 chip->card_fail &= ~SD_CARD;
3708 } else {
3709 chip->card_ready &= ~SD_CARD;
3710 chip->card_fail |= SD_CARD;
3711 chip->capacity[chip->card2lun[SD_CARD]] = 0;
3712 chip->rw_need_retry = 1;
Joe Perches031366e2015-03-25 12:54:25 -07003713 rtsx_trace(chip);
3714 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003715 }
3716 }
3717
3718 if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card))
3719 data_addr = start_sector << 9;
3720 else
3721 data_addr = start_sector;
3722
3723 sd_clr_err_code(chip);
3724
3725 retval = sd_switch_clock(chip);
3726 if (retval != STATUS_SUCCESS) {
3727 sd_set_err_code(chip, SD_IO_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003728 rtsx_trace(chip);
3729 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003730 }
3731
3732 if (sd_card->seq_mode &&
3733 ((sd_card->pre_dir != srb->sc_data_direction) ||
3734 ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) !=
3735 start_sector))) {
3736 if ((sd_card->pre_sec_cnt < 0x80)
3737 && (sd_card->pre_dir == DMA_FROM_DEVICE)
3738 && !CHK_SD30_SPEED(sd_card)
3739 && !CHK_SD_HS(sd_card)
3740 && !CHK_MMC_HS(sd_card)) {
3741 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
3742 SD_RSP_TYPE_R1, NULL, 0);
3743 }
3744
3745 retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
3746 0, SD_RSP_TYPE_R1b, NULL, 0);
3747 if (retval != STATUS_SUCCESS) {
3748 chip->rw_need_retry = 1;
3749 sd_set_err_code(chip, SD_STS_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003750 rtsx_trace(chip);
3751 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003752 }
3753
3754 sd_card->seq_mode = 0;
3755
3756 retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
3757 if (retval != STATUS_SUCCESS) {
3758 sd_set_err_code(chip, SD_IO_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003759 rtsx_trace(chip);
3760 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003761 }
3762
3763 if ((sd_card->pre_sec_cnt < 0x80)
3764 && !CHK_SD30_SPEED(sd_card)
3765 && !CHK_SD_HS(sd_card)
3766 && !CHK_MMC_HS(sd_card)) {
3767 sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
3768 SD_RSP_TYPE_R1, NULL, 0);
3769 }
3770 }
3771
3772 rtsx_init_cmd(chip);
3773
3774 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
3775 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
3776 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
3777 (u8)sector_cnt);
3778 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
3779 (u8)(sector_cnt >> 8));
3780
3781 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
3782
3783 if (CHK_MMC_8BIT(sd_card))
3784 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
3785 0x03, SD_BUS_WIDTH_8);
3786 else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card))
3787 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
3788 0x03, SD_BUS_WIDTH_4);
3789 else
3790 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
3791 0x03, SD_BUS_WIDTH_1);
3792
3793 if (sd_card->seq_mode) {
3794 cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16|
3795 SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
3796 SD_RSP_LEN_0;
3797 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
3798
3799 trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
3800 DMA_512);
3801
3802 if (srb->sc_data_direction == DMA_FROM_DEVICE) {
3803 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
3804 SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
3805 } else {
3806 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
3807 SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
3808 }
3809
3810 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
3811 SD_TRANSFER_END, SD_TRANSFER_END);
3812
3813 rtsx_send_cmd_no_wait(chip);
3814 } else {
3815 if (srb->sc_data_direction == DMA_FROM_DEVICE) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003816 dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n",
3817 READ_MULTIPLE_BLOCK);
Micky Chingfa590c22013-11-12 17:16:08 +08003818 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
3819 0x40 | READ_MULTIPLE_BLOCK);
3820 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
3821 (u8)(data_addr >> 24));
3822 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
3823 (u8)(data_addr >> 16));
3824 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
3825 (u8)(data_addr >> 8));
3826 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
3827 (u8)data_addr);
3828
3829 cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
3830 SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 |
3831 SD_RSP_LEN_6;
3832 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
3833 cfg2);
3834
3835 trans_dma_enable(srb->sc_data_direction, chip,
3836 sector_cnt * 512, DMA_512);
3837
3838 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
3839 SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
3840 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
3841 SD_TRANSFER_END, SD_TRANSFER_END);
3842
3843 rtsx_send_cmd_no_wait(chip);
3844 } else {
3845 retval = rtsx_send_cmd(chip, SD_CARD, 50);
3846 if (retval < 0) {
3847 rtsx_clear_sd_error(chip);
3848
3849 chip->rw_need_retry = 1;
3850 sd_set_err_code(chip, SD_TO_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003851 rtsx_trace(chip);
3852 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003853 }
3854
3855 retval = wait_data_buf_ready(chip);
3856 if (retval != STATUS_SUCCESS) {
3857 chip->rw_need_retry = 1;
3858 sd_set_err_code(chip, SD_TO_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003859 rtsx_trace(chip);
3860 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003861 }
3862
3863 retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
3864 data_addr, SD_RSP_TYPE_R1, NULL, 0);
3865 if (retval != STATUS_SUCCESS) {
3866 chip->rw_need_retry = 1;
Joe Perches031366e2015-03-25 12:54:25 -07003867 rtsx_trace(chip);
3868 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003869 }
3870
3871 rtsx_init_cmd(chip);
3872
3873 cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
3874 SD_NO_WAIT_BUSY_END |
3875 SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
3876 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
3877 cfg2);
3878
3879 trans_dma_enable(srb->sc_data_direction, chip,
3880 sector_cnt * 512, DMA_512);
3881
3882 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
3883 SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
3884 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
3885 SD_TRANSFER_END, SD_TRANSFER_END);
3886
3887 rtsx_send_cmd_no_wait(chip);
3888 }
3889
3890 sd_card->seq_mode = 1;
3891 }
3892
3893 retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
3894 scsi_bufflen(srb), scsi_sg_count(srb),
3895 srb->sc_data_direction, chip->sd_timeout);
3896 if (retval < 0) {
3897 u8 stat = 0;
3898 int err;
3899
3900 sd_card->seq_mode = 0;
3901
3902 if (retval == -ETIMEDOUT)
3903 err = STATUS_TIMEDOUT;
3904 else
3905 err = STATUS_FAIL;
3906
3907 rtsx_read_register(chip, REG_SD_STAT1, &stat);
3908 rtsx_clear_sd_error(chip);
3909 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
3910 chip->rw_need_retry = 0;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003911 dev_dbg(rtsx_dev(chip), "No card exist, exit sd_rw\n");
Joe Perches031366e2015-03-25 12:54:25 -07003912 rtsx_trace(chip);
3913 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003914 }
3915
3916 chip->rw_need_retry = 1;
3917
3918 retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
3919 SD_RSP_TYPE_R1b, NULL, 0);
3920 if (retval != STATUS_SUCCESS) {
3921 sd_set_err_code(chip, SD_STS_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003922 rtsx_trace(chip);
3923 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003924 }
3925
3926 if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003927 dev_dbg(rtsx_dev(chip), "SD CRC error, tune clock!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08003928 sd_set_err_code(chip, SD_CRC_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003929 rtsx_trace(chip);
3930 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003931 }
3932
3933 if (err == STATUS_TIMEDOUT) {
3934 sd_set_err_code(chip, SD_TO_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07003935 rtsx_trace(chip);
3936 goto RW_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003937 }
3938
Joe Perches031366e2015-03-25 12:54:25 -07003939 rtsx_trace(chip);
3940 return err;
Micky Chingfa590c22013-11-12 17:16:08 +08003941 }
3942
3943 sd_card->pre_sec_addr = start_sector;
3944 sd_card->pre_sec_cnt = sector_cnt;
3945 sd_card->pre_dir = srb->sc_data_direction;
3946
3947 return STATUS_SUCCESS;
3948
3949RW_FAIL:
3950 sd_card->seq_mode = 0;
3951
3952 if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
3953 chip->rw_need_retry = 0;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003954 dev_dbg(rtsx_dev(chip), "No card exist, exit sd_rw\n");
Joe Perches031366e2015-03-25 12:54:25 -07003955 rtsx_trace(chip);
3956 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003957 }
3958
3959 if (sd_check_err_code(chip, SD_CRC_ERR)) {
3960 if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
3961 sd_card->mmc_dont_switch_bus = 1;
3962 reset_mmc_only(chip);
3963 sd_card->mmc_dont_switch_bus = 0;
3964 } else {
3965 sd_card->need_retune = 1;
3966 sd_auto_tune_clock(chip);
3967 }
3968 } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
3969 retval = reset_sd_card(chip);
3970 if (retval != STATUS_SUCCESS) {
3971 chip->card_ready &= ~SD_CARD;
3972 chip->card_fail |= SD_CARD;
3973 chip->capacity[chip->card2lun[SD_CARD]] = 0;
3974 }
3975 }
3976
Joe Perches031366e2015-03-25 12:54:25 -07003977 rtsx_trace(chip);
3978 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08003979}
3980
3981#ifdef SUPPORT_CPRM
3982int soft_reset_sd_card(struct rtsx_chip *chip)
3983{
3984 return reset_sd(chip);
3985}
3986
3987int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
Quentin Lambert11201762015-03-04 11:31:53 +01003988 u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, bool special_check)
Micky Chingfa590c22013-11-12 17:16:08 +08003989{
3990 int retval;
3991 int timeout = 100;
3992 u16 reg_addr;
3993 u8 *ptr;
3994 int stat_idx = 0;
3995 int rty_cnt = 0;
3996
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02003997 dev_dbg(rtsx_dev(chip), "EXT SD/MMC CMD %d\n", cmd_idx);
Micky Chingfa590c22013-11-12 17:16:08 +08003998
3999 if (rsp_type == SD_RSP_TYPE_R1b)
4000 timeout = 3000;
4001
4002RTY_SEND_CMD:
4003
4004 rtsx_init_cmd(chip);
4005
4006 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
4007 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
4008 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
4009 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
4010 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
4011
4012 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
4013 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
4014 0x01, PINGPONG_BUFFER);
4015 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
4016 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
4017 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
4018 SD_TRANSFER_END);
4019
4020 if (rsp_type == SD_RSP_TYPE_R2) {
4021 for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
4022 reg_addr++)
4023 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
4024
4025 stat_idx = 17;
4026 } else if (rsp_type != SD_RSP_TYPE_R0) {
4027 for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
4028 reg_addr++)
4029 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
4030
4031 stat_idx = 6;
4032 }
4033 rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
4034
4035 rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
4036
4037 retval = rtsx_send_cmd(chip, SD_CARD, timeout);
4038 if (retval < 0) {
4039 if (retval == -ETIMEDOUT) {
4040 rtsx_clear_sd_error(chip);
4041
4042 if (rsp_type & SD_WAIT_BUSY_END) {
4043 retval = sd_check_data0_status(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004044 if (retval != STATUS_SUCCESS) {
4045 rtsx_trace(chip);
4046 return retval;
4047 }
Micky Chingfa590c22013-11-12 17:16:08 +08004048 } else {
4049 sd_set_err_code(chip, SD_TO_ERR);
4050 }
4051 }
Joe Perches031366e2015-03-25 12:54:25 -07004052 rtsx_trace(chip);
4053 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08004054 }
4055
4056 if (rsp_type == SD_RSP_TYPE_R0)
4057 return STATUS_SUCCESS;
4058
4059 ptr = rtsx_get_cmd_data(chip) + 1;
4060
4061 if ((ptr[0] & 0xC0) != 0) {
4062 sd_set_err_code(chip, SD_STS_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07004063 rtsx_trace(chip);
4064 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08004065 }
4066
4067 if (!(rsp_type & SD_NO_CHECK_CRC7)) {
4068 if (ptr[stat_idx] & SD_CRC7_ERR) {
4069 if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
4070 sd_set_err_code(chip, SD_CRC_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07004071 rtsx_trace(chip);
4072 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08004073 }
4074 if (rty_cnt < SD_MAX_RETRY_COUNT) {
4075 wait_timeout(20);
4076 rty_cnt++;
4077 goto RTY_SEND_CMD;
4078 } else {
4079 sd_set_err_code(chip, SD_CRC_ERR);
Joe Perches031366e2015-03-25 12:54:25 -07004080 rtsx_trace(chip);
4081 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08004082 }
4083 }
4084 }
4085
4086 if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
4087 (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
Quentin Lambert11201762015-03-04 11:31:53 +01004088 if ((cmd_idx != STOP_TRANSMISSION) && !special_check) {
Joe Perches031366e2015-03-25 12:54:25 -07004089 if (ptr[1] & 0x80) {
4090 rtsx_trace(chip);
4091 return STATUS_FAIL;
4092 }
Micky Chingfa590c22013-11-12 17:16:08 +08004093 }
4094#ifdef SUPPORT_SD_LOCK
Yash Shah66e6d702015-08-03 11:18:31 +00004095 if (ptr[1] & 0x7D) {
Micky Chingfa590c22013-11-12 17:16:08 +08004096#else
Yash Shah66e6d702015-08-03 11:18:31 +00004097 if (ptr[1] & 0x7F) {
Micky Chingfa590c22013-11-12 17:16:08 +08004098#endif
Joe Perches031366e2015-03-25 12:54:25 -07004099 rtsx_trace(chip);
4100 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08004101 }
Joe Perches031366e2015-03-25 12:54:25 -07004102 if (ptr[2] & 0xF8) {
4103 rtsx_trace(chip);
4104 return STATUS_FAIL;
4105 }
Micky Chingfa590c22013-11-12 17:16:08 +08004106
4107 if (cmd_idx == SELECT_CARD) {
4108 if (rsp_type == SD_RSP_TYPE_R2) {
Joe Perches031366e2015-03-25 12:54:25 -07004109 if ((ptr[3] & 0x1E) != 0x04) {
4110 rtsx_trace(chip);
4111 return STATUS_FAIL;
4112 }
Micky Chingfa590c22013-11-12 17:16:08 +08004113
4114 } else if (rsp_type == SD_RSP_TYPE_R0) {
Joe Perches031366e2015-03-25 12:54:25 -07004115 if ((ptr[3] & 0x1E) != 0x03) {
4116 rtsx_trace(chip);
4117 return STATUS_FAIL;
4118 }
Micky Chingfa590c22013-11-12 17:16:08 +08004119 }
4120 }
4121 }
4122
4123 if (rsp && rsp_len)
4124 memcpy(rsp, ptr, rsp_len);
4125
4126 return STATUS_SUCCESS;
4127}
4128
4129int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
4130{
4131 int retval, rsp_len;
4132 u16 reg_addr;
4133
4134 if (rsp_type == SD_RSP_TYPE_R0)
4135 return STATUS_SUCCESS;
4136
4137 rtsx_init_cmd(chip);
4138
4139 if (rsp_type == SD_RSP_TYPE_R2) {
4140 for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
4141 reg_addr++)
4142 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
4143
4144 rsp_len = 17;
4145 } else if (rsp_type != SD_RSP_TYPE_R0) {
4146 for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
4147 reg_addr++)
4148 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
4149
4150 rsp_len = 6;
4151 }
4152 rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
4153
4154 retval = rtsx_send_cmd(chip, SD_CARD, 100);
Joe Perches031366e2015-03-25 12:54:25 -07004155 if (retval != STATUS_SUCCESS) {
4156 rtsx_trace(chip);
4157 return STATUS_FAIL;
4158 }
Micky Chingfa590c22013-11-12 17:16:08 +08004159
4160 if (rsp) {
4161 int min_len = (rsp_len < len) ? rsp_len : len;
4162
4163 memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
4164
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02004165 dev_dbg(rtsx_dev(chip), "min_len = %d\n", min_len);
4166 dev_dbg(rtsx_dev(chip), "Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08004167 rsp[0], rsp[1], rsp[2], rsp[3]);
4168 }
4169
4170 return STATUS_SUCCESS;
4171}
4172
4173int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
4174{
4175 struct sd_info *sd_card = &(chip->sd_card);
4176 unsigned int lun = SCSI_LUN(srb);
4177 int len;
4178 u8 buf[18] = {
4179 0x00,
4180 0x00,
4181 0x00,
4182 0x0E,
4183 0x00,
4184 0x00,
4185 0x00,
4186 0x00,
4187 0x53,
4188 0x44,
4189 0x20,
4190 0x43,
4191 0x61,
4192 0x72,
4193 0x64,
4194 0x00,
4195 0x00,
4196 0x00,
4197 };
4198
4199 sd_card->pre_cmd_err = 0;
4200
4201 if (!(CHK_BIT(chip->lun_mc, lun))) {
4202 SET_BIT(chip->lun_mc, lun);
4203 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07004204 rtsx_trace(chip);
4205 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004206 }
4207
Janani Ravichandran3b15cfb2016-02-13 21:57:51 -05004208 if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) ||
4209 (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) ||
4210 (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) ||
4211 (srb->cmnd[8] != 0x64)) {
Micky Chingfa590c22013-11-12 17:16:08 +08004212 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004213 rtsx_trace(chip);
4214 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004215 }
4216
4217 switch (srb->cmnd[1] & 0x0F) {
4218 case 0:
4219 sd_card->sd_pass_thru_en = 0;
4220 break;
4221
4222 case 1:
4223 sd_card->sd_pass_thru_en = 1;
4224 break;
4225
4226 default:
4227 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004228 rtsx_trace(chip);
4229 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004230 }
4231
Janani Ravichandran3b15cfb2016-02-13 21:57:51 -05004232 buf[5] = (CHK_SD(sd_card) == 1) ? 0x01 : 0x02;
Micky Chingfa590c22013-11-12 17:16:08 +08004233 if (chip->card_wp & SD_CARD)
4234 buf[5] |= 0x80;
4235
4236 buf[6] = (u8)(sd_card->sd_addr >> 16);
4237 buf[7] = (u8)(sd_card->sd_addr >> 24);
4238
4239 buf[15] = chip->max_lun;
4240
4241 len = min_t(int, 18, scsi_bufflen(srb));
4242 rtsx_stor_set_xfer_buf(buf, len, srb);
4243
4244 return TRANSPORT_GOOD;
4245}
4246
4247static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type,
4248 int *rsp_len)
4249{
4250 if (!rsp_type || !rsp_len)
4251 return STATUS_FAIL;
4252
4253 switch (srb->cmnd[10]) {
4254 case 0x03:
4255 *rsp_type = SD_RSP_TYPE_R0;
4256 *rsp_len = 0;
4257 break;
4258
4259 case 0x04:
4260 *rsp_type = SD_RSP_TYPE_R1;
4261 *rsp_len = 6;
4262 break;
4263
4264 case 0x05:
4265 *rsp_type = SD_RSP_TYPE_R1b;
4266 *rsp_len = 6;
4267 break;
4268
4269 case 0x06:
4270 *rsp_type = SD_RSP_TYPE_R2;
4271 *rsp_len = 17;
4272 break;
4273
4274 case 0x07:
4275 *rsp_type = SD_RSP_TYPE_R3;
4276 *rsp_len = 6;
4277 break;
4278
4279 default:
4280 return STATUS_FAIL;
4281 }
4282
4283 return STATUS_SUCCESS;
4284}
4285
4286int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
4287{
4288 struct sd_info *sd_card = &(chip->sd_card);
4289 unsigned int lun = SCSI_LUN(srb);
4290 int retval, rsp_len;
4291 u8 cmd_idx, rsp_type;
Quentin Lambertde904bf2015-03-04 11:31:01 +01004292 bool standby = false, acmd = false;
Micky Chingfa590c22013-11-12 17:16:08 +08004293 u32 arg;
4294
4295 if (!sd_card->sd_pass_thru_en) {
4296 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004297 rtsx_trace(chip);
4298 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004299 }
4300
4301 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004302 if (retval != STATUS_SUCCESS) {
4303 rtsx_trace(chip);
4304 return TRANSPORT_FAILED;
4305 }
Micky Chingfa590c22013-11-12 17:16:08 +08004306
4307 if (sd_card->pre_cmd_err) {
4308 sd_card->pre_cmd_err = 0;
4309 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07004310 rtsx_trace(chip);
4311 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004312 }
4313
4314 cmd_idx = srb->cmnd[2] & 0x3F;
4315 if (srb->cmnd[1] & 0x02)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004316 standby = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004317
4318 if (srb->cmnd[1] & 0x01)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004319 acmd = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004320
4321 arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
4322 ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
4323
4324 retval = get_rsp_type(srb, &rsp_type, &rsp_len);
4325 if (retval != STATUS_SUCCESS) {
4326 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004327 rtsx_trace(chip);
4328 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004329 }
4330 sd_card->last_rsp_type = rsp_type;
4331
4332 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004333 if (retval != STATUS_SUCCESS) {
4334 rtsx_trace(chip);
4335 return TRANSPORT_FAILED;
4336 }
Micky Chingfa590c22013-11-12 17:16:08 +08004337
4338#ifdef SUPPORT_SD_LOCK
4339 if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
4340 if (CHK_MMC_8BIT(sd_card)) {
4341 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
4342 SD_BUS_WIDTH_8);
Joe Perches031366e2015-03-25 12:54:25 -07004343 if (retval != STATUS_SUCCESS) {
4344 rtsx_trace(chip);
4345 return TRANSPORT_FAILED;
4346 }
Micky Chingfa590c22013-11-12 17:16:08 +08004347
4348 } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
4349 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
4350 SD_BUS_WIDTH_4);
Joe Perches031366e2015-03-25 12:54:25 -07004351 if (retval != STATUS_SUCCESS) {
4352 rtsx_trace(chip);
4353 return TRANSPORT_FAILED;
4354 }
Micky Chingfa590c22013-11-12 17:16:08 +08004355 }
4356 }
4357#else
4358 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
Joe Perches031366e2015-03-25 12:54:25 -07004359 if (retval != STATUS_SUCCESS) {
4360 rtsx_trace(chip);
4361 return TRANSPORT_FAILED;
4362 }
Micky Chingfa590c22013-11-12 17:16:08 +08004363#endif
4364
4365 if (standby) {
4366 retval = sd_select_card(chip, 0);
Joe Perches031366e2015-03-25 12:54:25 -07004367 if (retval != STATUS_SUCCESS) {
4368 rtsx_trace(chip);
4369 goto SD_Execute_Cmd_Failed;
4370 }
Micky Chingfa590c22013-11-12 17:16:08 +08004371 }
4372
4373 if (acmd) {
4374 retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
4375 sd_card->sd_addr,
Quentin Lambert11201762015-03-04 11:31:53 +01004376 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004377 if (retval != STATUS_SUCCESS) {
4378 rtsx_trace(chip);
4379 goto SD_Execute_Cmd_Failed;
4380 }
Micky Chingfa590c22013-11-12 17:16:08 +08004381 }
4382
4383 retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
Quentin Lambert11201762015-03-04 11:31:53 +01004384 sd_card->rsp, rsp_len, false);
Joe Perches031366e2015-03-25 12:54:25 -07004385 if (retval != STATUS_SUCCESS) {
4386 rtsx_trace(chip);
4387 goto SD_Execute_Cmd_Failed;
4388 }
Micky Chingfa590c22013-11-12 17:16:08 +08004389
4390 if (standby) {
4391 retval = sd_select_card(chip, 1);
Joe Perches031366e2015-03-25 12:54:25 -07004392 if (retval != STATUS_SUCCESS) {
4393 rtsx_trace(chip);
4394 goto SD_Execute_Cmd_Failed;
4395 }
Micky Chingfa590c22013-11-12 17:16:08 +08004396 }
4397
4398#ifdef SUPPORT_SD_LOCK
4399 retval = sd_update_lock_status(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004400 if (retval != STATUS_SUCCESS) {
4401 rtsx_trace(chip);
4402 goto SD_Execute_Cmd_Failed;
4403 }
Micky Chingfa590c22013-11-12 17:16:08 +08004404#endif
4405
4406 scsi_set_resid(srb, 0);
4407 return TRANSPORT_GOOD;
4408
4409SD_Execute_Cmd_Failed:
4410 sd_card->pre_cmd_err = 1;
4411 set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
4412 release_sd_card(chip);
4413 do_reset_sd_card(chip);
4414 if (!(chip->card_ready & SD_CARD))
4415 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
4416
Joe Perches031366e2015-03-25 12:54:25 -07004417 rtsx_trace(chip);
4418 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004419}
4420
4421int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
4422{
4423 struct sd_info *sd_card = &(chip->sd_card);
4424 unsigned int lun = SCSI_LUN(srb);
4425 int retval, rsp_len, i;
Quentin Lambert11201762015-03-04 11:31:53 +01004426 bool read_err = false, cmd13_checkbit = false;
Micky Chingfa590c22013-11-12 17:16:08 +08004427 u8 cmd_idx, rsp_type, bus_width;
Quentin Lambertde904bf2015-03-04 11:31:01 +01004428 bool standby = false, send_cmd12 = false, acmd = false;
Micky Chingfa590c22013-11-12 17:16:08 +08004429 u32 data_len;
4430
4431 if (!sd_card->sd_pass_thru_en) {
4432 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004433 rtsx_trace(chip);
4434 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004435 }
4436
4437 if (sd_card->pre_cmd_err) {
4438 sd_card->pre_cmd_err = 0;
4439 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07004440 rtsx_trace(chip);
4441 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004442 }
4443
4444 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004445 if (retval != STATUS_SUCCESS) {
4446 rtsx_trace(chip);
4447 return TRANSPORT_FAILED;
4448 }
Micky Chingfa590c22013-11-12 17:16:08 +08004449
4450 cmd_idx = srb->cmnd[2] & 0x3F;
4451 if (srb->cmnd[1] & 0x04)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004452 send_cmd12 = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004453
4454 if (srb->cmnd[1] & 0x02)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004455 standby = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004456
4457 if (srb->cmnd[1] & 0x01)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004458 acmd = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004459
4460 data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
4461 << 8) | srb->cmnd[9];
4462
4463 retval = get_rsp_type(srb, &rsp_type, &rsp_len);
4464 if (retval != STATUS_SUCCESS) {
4465 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004466 rtsx_trace(chip);
4467 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004468 }
4469 sd_card->last_rsp_type = rsp_type;
4470
4471 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004472 if (retval != STATUS_SUCCESS) {
4473 rtsx_trace(chip);
4474 return TRANSPORT_FAILED;
4475 }
Micky Chingfa590c22013-11-12 17:16:08 +08004476
4477#ifdef SUPPORT_SD_LOCK
4478 if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
4479 if (CHK_MMC_8BIT(sd_card))
4480 bus_width = SD_BUS_WIDTH_8;
4481 else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
4482 bus_width = SD_BUS_WIDTH_4;
4483 else
4484 bus_width = SD_BUS_WIDTH_1;
4485 } else {
4486 bus_width = SD_BUS_WIDTH_4;
4487 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02004488 dev_dbg(rtsx_dev(chip), "bus_width = %d\n", bus_width);
Micky Chingfa590c22013-11-12 17:16:08 +08004489#else
4490 bus_width = SD_BUS_WIDTH_4;
4491#endif
4492
4493 if (data_len < 512) {
4494 retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
Quentin Lambert11201762015-03-04 11:31:53 +01004495 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004496 if (retval != STATUS_SUCCESS) {
4497 rtsx_trace(chip);
4498 goto SD_Execute_Read_Cmd_Failed;
4499 }
Micky Chingfa590c22013-11-12 17:16:08 +08004500 }
4501
4502 if (standby) {
4503 retval = sd_select_card(chip, 0);
Joe Perches031366e2015-03-25 12:54:25 -07004504 if (retval != STATUS_SUCCESS) {
4505 rtsx_trace(chip);
4506 goto SD_Execute_Read_Cmd_Failed;
4507 }
Micky Chingfa590c22013-11-12 17:16:08 +08004508 }
4509
4510 if (acmd) {
4511 retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
4512 sd_card->sd_addr,
Quentin Lambert11201762015-03-04 11:31:53 +01004513 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004514 if (retval != STATUS_SUCCESS) {
4515 rtsx_trace(chip);
4516 goto SD_Execute_Read_Cmd_Failed;
4517 }
Micky Chingfa590c22013-11-12 17:16:08 +08004518 }
4519
4520 if (data_len <= 512) {
4521 int min_len;
4522 u8 *buf;
4523 u16 byte_cnt, blk_cnt;
4524 u8 cmd[5];
4525
4526 byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
4527 blk_cnt = 1;
4528
4529 cmd[0] = 0x40 | cmd_idx;
4530 cmd[1] = srb->cmnd[3];
4531 cmd[2] = srb->cmnd[4];
4532 cmd[3] = srb->cmnd[5];
4533 cmd[4] = srb->cmnd[6];
4534
4535 buf = kmalloc(data_len, GFP_KERNEL);
Eva Rachel Retuya75861702016-02-27 20:39:24 +08004536 if (!buf) {
Joe Perches031366e2015-03-25 12:54:25 -07004537 rtsx_trace(chip);
4538 return TRANSPORT_ERROR;
4539 }
Micky Chingfa590c22013-11-12 17:16:08 +08004540
4541 retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
4542 blk_cnt, bus_width, buf, data_len, 2000);
4543 if (retval != STATUS_SUCCESS) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01004544 read_err = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004545 kfree(buf);
4546 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004547 rtsx_trace(chip);
4548 goto SD_Execute_Read_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004549 }
4550
4551 min_len = min(data_len, scsi_bufflen(srb));
4552 rtsx_stor_set_xfer_buf(buf, min_len, srb);
4553
4554 kfree(buf);
4555 } else if (!(data_len & 0x1FF)) {
4556 rtsx_init_cmd(chip);
4557
4558 trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
4559
4560 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
4561 0x02);
4562 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
4563 0x00);
4564 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
4565 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
4566 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
4567 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
4568
4569 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
4570 0x40 | cmd_idx);
4571 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
4572 srb->cmnd[3]);
4573 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
4574 srb->cmnd[4]);
4575 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
4576 srb->cmnd[5]);
4577 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
4578 srb->cmnd[6]);
4579
4580 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
4581 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
4582
4583 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
4584 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
4585 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
4586 SD_TRANSFER_END, SD_TRANSFER_END);
4587
4588 rtsx_send_cmd_no_wait(chip);
4589
4590 retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
4591 scsi_bufflen(srb), scsi_sg_count(srb),
4592 DMA_FROM_DEVICE, 10000);
4593 if (retval < 0) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01004594 read_err = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004595 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004596 rtsx_trace(chip);
4597 goto SD_Execute_Read_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004598 }
4599
4600 } else {
Joe Perches031366e2015-03-25 12:54:25 -07004601 rtsx_trace(chip);
4602 goto SD_Execute_Read_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004603 }
4604
4605 retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
Joe Perches031366e2015-03-25 12:54:25 -07004606 if (retval != STATUS_SUCCESS) {
4607 rtsx_trace(chip);
4608 goto SD_Execute_Read_Cmd_Failed;
4609 }
Micky Chingfa590c22013-11-12 17:16:08 +08004610
4611 if (standby) {
4612 retval = sd_select_card(chip, 1);
Joe Perches031366e2015-03-25 12:54:25 -07004613 if (retval != STATUS_SUCCESS) {
4614 rtsx_trace(chip);
4615 goto SD_Execute_Read_Cmd_Failed;
4616 }
Micky Chingfa590c22013-11-12 17:16:08 +08004617 }
4618
4619 if (send_cmd12) {
4620 retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
Quentin Lambert11201762015-03-04 11:31:53 +01004621 0, SD_RSP_TYPE_R1b, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004622 if (retval != STATUS_SUCCESS) {
4623 rtsx_trace(chip);
4624 goto SD_Execute_Read_Cmd_Failed;
4625 }
Micky Chingfa590c22013-11-12 17:16:08 +08004626 }
4627
4628 if (data_len < 512) {
4629 retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
Quentin Lambert11201762015-03-04 11:31:53 +01004630 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004631 if (retval != STATUS_SUCCESS) {
4632 rtsx_trace(chip);
4633 goto SD_Execute_Read_Cmd_Failed;
4634 }
Micky Chingfa590c22013-11-12 17:16:08 +08004635
4636 retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
Joe Perches031366e2015-03-25 12:54:25 -07004637 if (retval != STATUS_SUCCESS) {
4638 rtsx_trace(chip);
4639 goto SD_Execute_Read_Cmd_Failed;
4640 }
Micky Chingfa590c22013-11-12 17:16:08 +08004641
4642 retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
Joe Perches031366e2015-03-25 12:54:25 -07004643 if (retval != STATUS_SUCCESS) {
4644 rtsx_trace(chip);
4645 goto SD_Execute_Read_Cmd_Failed;
4646 }
Micky Chingfa590c22013-11-12 17:16:08 +08004647 }
4648
4649 if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
Quentin Lambert11201762015-03-04 11:31:53 +01004650 cmd13_checkbit = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004651
4652 for (i = 0; i < 3; i++) {
4653 retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
4654 sd_card->sd_addr,
4655 SD_RSP_TYPE_R1, NULL, 0,
4656 cmd13_checkbit);
4657 if (retval == STATUS_SUCCESS)
4658 break;
4659 }
Joe Perches031366e2015-03-25 12:54:25 -07004660 if (retval != STATUS_SUCCESS) {
4661 rtsx_trace(chip);
4662 goto SD_Execute_Read_Cmd_Failed;
4663 }
Micky Chingfa590c22013-11-12 17:16:08 +08004664
4665 scsi_set_resid(srb, 0);
4666 return TRANSPORT_GOOD;
4667
4668SD_Execute_Read_Cmd_Failed:
4669 sd_card->pre_cmd_err = 1;
4670 set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
4671 if (read_err)
4672 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
4673
4674 release_sd_card(chip);
4675 do_reset_sd_card(chip);
4676 if (!(chip->card_ready & SD_CARD))
4677 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
4678
Joe Perches031366e2015-03-25 12:54:25 -07004679 rtsx_trace(chip);
4680 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004681}
4682
4683int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
4684{
4685 struct sd_info *sd_card = &(chip->sd_card);
4686 unsigned int lun = SCSI_LUN(srb);
4687 int retval, rsp_len, i;
Quentin Lambert11201762015-03-04 11:31:53 +01004688 bool write_err = false, cmd13_checkbit = false;
Micky Chingfa590c22013-11-12 17:16:08 +08004689 u8 cmd_idx, rsp_type;
Quentin Lambertde904bf2015-03-04 11:31:01 +01004690 bool standby = false, send_cmd12 = false, acmd = false;
Micky Chingfa590c22013-11-12 17:16:08 +08004691 u32 data_len, arg;
4692#ifdef SUPPORT_SD_LOCK
4693 int lock_cmd_fail = 0;
4694 u8 sd_lock_state = 0;
4695 u8 lock_cmd_type = 0;
4696#endif
4697
4698 if (!sd_card->sd_pass_thru_en) {
4699 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004700 rtsx_trace(chip);
4701 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004702 }
4703
4704 if (sd_card->pre_cmd_err) {
4705 sd_card->pre_cmd_err = 0;
4706 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07004707 rtsx_trace(chip);
4708 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004709 }
4710
4711 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004712 if (retval != STATUS_SUCCESS) {
4713 rtsx_trace(chip);
4714 return TRANSPORT_FAILED;
4715 }
Micky Chingfa590c22013-11-12 17:16:08 +08004716
4717 cmd_idx = srb->cmnd[2] & 0x3F;
4718 if (srb->cmnd[1] & 0x04)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004719 send_cmd12 = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004720
4721 if (srb->cmnd[1] & 0x02)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004722 standby = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004723
4724 if (srb->cmnd[1] & 0x01)
Quentin Lambertde904bf2015-03-04 11:31:01 +01004725 acmd = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004726
4727 data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
4728 << 8) | srb->cmnd[9];
4729 arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
4730 ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
4731
4732#ifdef SUPPORT_SD_LOCK
4733 if (cmd_idx == LOCK_UNLOCK) {
4734 sd_lock_state = sd_card->sd_lock_status;
4735 sd_lock_state &= SD_LOCKED;
4736 }
4737#endif
4738
4739 retval = get_rsp_type(srb, &rsp_type, &rsp_len);
4740 if (retval != STATUS_SUCCESS) {
4741 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07004742 rtsx_trace(chip);
4743 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08004744 }
4745 sd_card->last_rsp_type = rsp_type;
4746
4747 retval = sd_switch_clock(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004748 if (retval != STATUS_SUCCESS) {
4749 rtsx_trace(chip);
4750 return TRANSPORT_FAILED;
4751 }
Micky Chingfa590c22013-11-12 17:16:08 +08004752
4753#ifdef SUPPORT_SD_LOCK
4754 if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
4755 if (CHK_MMC_8BIT(sd_card)) {
4756 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
4757 SD_BUS_WIDTH_8);
Joe Perches031366e2015-03-25 12:54:25 -07004758 if (retval != STATUS_SUCCESS) {
4759 rtsx_trace(chip);
4760 return TRANSPORT_FAILED;
4761 }
Micky Chingfa590c22013-11-12 17:16:08 +08004762
4763 } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
4764 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
4765 SD_BUS_WIDTH_4);
Joe Perches031366e2015-03-25 12:54:25 -07004766 if (retval != STATUS_SUCCESS) {
4767 rtsx_trace(chip);
4768 return TRANSPORT_FAILED;
4769 }
Micky Chingfa590c22013-11-12 17:16:08 +08004770 }
4771 }
4772#else
4773 retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
Joe Perches031366e2015-03-25 12:54:25 -07004774 if (retval != STATUS_SUCCESS) {
4775 rtsx_trace(chip);
4776 return TRANSPORT_FAILED;
4777 }
Micky Chingfa590c22013-11-12 17:16:08 +08004778#endif
4779
4780 if (data_len < 512) {
4781 retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
Quentin Lambert11201762015-03-04 11:31:53 +01004782 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004783 if (retval != STATUS_SUCCESS) {
4784 rtsx_trace(chip);
4785 goto SD_Execute_Write_Cmd_Failed;
4786 }
Micky Chingfa590c22013-11-12 17:16:08 +08004787 }
4788
4789 if (standby) {
4790 retval = sd_select_card(chip, 0);
Joe Perches031366e2015-03-25 12:54:25 -07004791 if (retval != STATUS_SUCCESS) {
4792 rtsx_trace(chip);
4793 goto SD_Execute_Write_Cmd_Failed;
4794 }
Micky Chingfa590c22013-11-12 17:16:08 +08004795 }
4796
4797 if (acmd) {
4798 retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
4799 sd_card->sd_addr,
Quentin Lambert11201762015-03-04 11:31:53 +01004800 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004801 if (retval != STATUS_SUCCESS) {
4802 rtsx_trace(chip);
4803 goto SD_Execute_Write_Cmd_Failed;
4804 }
Micky Chingfa590c22013-11-12 17:16:08 +08004805 }
4806
4807 retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
Quentin Lambert11201762015-03-04 11:31:53 +01004808 sd_card->rsp, rsp_len, false);
Joe Perches031366e2015-03-25 12:54:25 -07004809 if (retval != STATUS_SUCCESS) {
4810 rtsx_trace(chip);
4811 goto SD_Execute_Write_Cmd_Failed;
4812 }
Micky Chingfa590c22013-11-12 17:16:08 +08004813
4814 if (data_len <= 512) {
4815 u16 i;
4816 u8 *buf;
4817
4818 buf = kmalloc(data_len, GFP_KERNEL);
Eva Rachel Retuya75861702016-02-27 20:39:24 +08004819 if (!buf) {
Joe Perches031366e2015-03-25 12:54:25 -07004820 rtsx_trace(chip);
4821 return TRANSPORT_ERROR;
4822 }
Micky Chingfa590c22013-11-12 17:16:08 +08004823
4824 rtsx_stor_get_xfer_buf(buf, data_len, srb);
4825
4826#ifdef SUPPORT_SD_LOCK
4827 if (cmd_idx == LOCK_UNLOCK)
4828 lock_cmd_type = buf[0] & 0x0F;
4829#endif
4830
4831 if (data_len > 256) {
4832 rtsx_init_cmd(chip);
4833 for (i = 0; i < 256; i++) {
4834 rtsx_add_cmd(chip, WRITE_REG_CMD,
4835 PPBUF_BASE2 + i, 0xFF, buf[i]);
4836 }
4837 retval = rtsx_send_cmd(chip, 0, 250);
4838 if (retval != STATUS_SUCCESS) {
4839 kfree(buf);
Joe Perches031366e2015-03-25 12:54:25 -07004840 rtsx_trace(chip);
4841 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004842 }
4843
4844 rtsx_init_cmd(chip);
4845 for (i = 256; i < data_len; i++) {
4846 rtsx_add_cmd(chip, WRITE_REG_CMD,
4847 PPBUF_BASE2 + i, 0xFF, buf[i]);
4848 }
4849 retval = rtsx_send_cmd(chip, 0, 250);
4850 if (retval != STATUS_SUCCESS) {
4851 kfree(buf);
Joe Perches031366e2015-03-25 12:54:25 -07004852 rtsx_trace(chip);
4853 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004854 }
4855 } else {
4856 rtsx_init_cmd(chip);
4857 for (i = 0; i < data_len; i++) {
4858 rtsx_add_cmd(chip, WRITE_REG_CMD,
4859 PPBUF_BASE2 + i, 0xFF, buf[i]);
4860 }
4861 retval = rtsx_send_cmd(chip, 0, 250);
4862 if (retval != STATUS_SUCCESS) {
4863 kfree(buf);
Joe Perches031366e2015-03-25 12:54:25 -07004864 rtsx_trace(chip);
4865 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004866 }
4867 }
4868
4869 kfree(buf);
4870
4871 rtsx_init_cmd(chip);
4872
4873 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
4874 srb->cmnd[8] & 0x03);
4875 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
4876 srb->cmnd[9]);
4877 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
4878 0x00);
4879 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
4880 0x01);
4881 rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
4882 PINGPONG_BUFFER);
4883
4884 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
4885 SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
4886 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
4887 SD_TRANSFER_END, SD_TRANSFER_END);
4888
4889 retval = rtsx_send_cmd(chip, SD_CARD, 250);
4890 } else if (!(data_len & 0x1FF)) {
4891 rtsx_init_cmd(chip);
4892
4893 trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
4894
4895 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
4896 0x02);
4897 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
4898 0x00);
4899 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
4900 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
4901 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
4902 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
4903
4904 rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
4905 SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
4906 rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
4907 SD_TRANSFER_END, SD_TRANSFER_END);
4908
4909 rtsx_send_cmd_no_wait(chip);
4910
4911 retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
4912 scsi_bufflen(srb), scsi_sg_count(srb),
4913 DMA_TO_DEVICE, 10000);
4914
4915 } else {
Joe Perches031366e2015-03-25 12:54:25 -07004916 rtsx_trace(chip);
4917 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004918 }
4919
4920 if (retval < 0) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01004921 write_err = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004922 rtsx_clear_sd_error(chip);
Joe Perches031366e2015-03-25 12:54:25 -07004923 rtsx_trace(chip);
4924 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08004925 }
4926
4927#ifdef SUPPORT_SD_LOCK
4928 if (cmd_idx == LOCK_UNLOCK) {
4929 if (lock_cmd_type == SD_ERASE) {
4930 sd_card->sd_erase_status = SD_UNDER_ERASING;
4931 scsi_set_resid(srb, 0);
4932 return TRANSPORT_GOOD;
4933 }
4934
4935 rtsx_init_cmd(chip);
4936 rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
4937
4938 rtsx_send_cmd(chip, SD_CARD, 250);
4939
4940 retval = sd_update_lock_status(chip);
4941 if (retval != STATUS_SUCCESS) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02004942 dev_dbg(rtsx_dev(chip), "Lock command fail!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08004943 lock_cmd_fail = 1;
4944 }
4945 }
4946#endif /* SUPPORT_SD_LOCK */
4947
4948 if (standby) {
4949 retval = sd_select_card(chip, 1);
Joe Perches031366e2015-03-25 12:54:25 -07004950 if (retval != STATUS_SUCCESS) {
4951 rtsx_trace(chip);
4952 goto SD_Execute_Write_Cmd_Failed;
4953 }
Micky Chingfa590c22013-11-12 17:16:08 +08004954 }
4955
4956 if (send_cmd12) {
4957 retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
Quentin Lambert11201762015-03-04 11:31:53 +01004958 0, SD_RSP_TYPE_R1b, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004959 if (retval != STATUS_SUCCESS) {
4960 rtsx_trace(chip);
4961 goto SD_Execute_Write_Cmd_Failed;
4962 }
Micky Chingfa590c22013-11-12 17:16:08 +08004963 }
4964
4965 if (data_len < 512) {
4966 retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
Quentin Lambert11201762015-03-04 11:31:53 +01004967 SD_RSP_TYPE_R1, NULL, 0, false);
Joe Perches031366e2015-03-25 12:54:25 -07004968 if (retval != STATUS_SUCCESS) {
4969 rtsx_trace(chip);
4970 goto SD_Execute_Write_Cmd_Failed;
4971 }
Micky Chingfa590c22013-11-12 17:16:08 +08004972
4973 retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
Joe Perches031366e2015-03-25 12:54:25 -07004974 if (retval != STATUS_SUCCESS) {
4975 rtsx_trace(chip);
4976 goto SD_Execute_Write_Cmd_Failed;
4977 }
Micky Chingfa590c22013-11-12 17:16:08 +08004978
4979 rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
Joe Perches031366e2015-03-25 12:54:25 -07004980 if (retval != STATUS_SUCCESS) {
4981 rtsx_trace(chip);
4982 goto SD_Execute_Write_Cmd_Failed;
4983 }
Micky Chingfa590c22013-11-12 17:16:08 +08004984 }
4985
4986 if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
Quentin Lambert11201762015-03-04 11:31:53 +01004987 cmd13_checkbit = true;
Micky Chingfa590c22013-11-12 17:16:08 +08004988
4989 for (i = 0; i < 3; i++) {
4990 retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
4991 sd_card->sd_addr,
4992 SD_RSP_TYPE_R1, NULL, 0,
4993 cmd13_checkbit);
4994 if (retval == STATUS_SUCCESS)
4995 break;
4996 }
Joe Perches031366e2015-03-25 12:54:25 -07004997 if (retval != STATUS_SUCCESS) {
4998 rtsx_trace(chip);
4999 goto SD_Execute_Write_Cmd_Failed;
5000 }
Micky Chingfa590c22013-11-12 17:16:08 +08005001
5002#ifdef SUPPORT_SD_LOCK
5003 if (cmd_idx == LOCK_UNLOCK) {
5004 if (!lock_cmd_fail) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02005005 dev_dbg(rtsx_dev(chip), "lock_cmd_type = 0x%x\n",
5006 lock_cmd_type);
Micky Chingfa590c22013-11-12 17:16:08 +08005007 if (lock_cmd_type & SD_CLR_PWD)
5008 sd_card->sd_lock_status &= ~SD_PWD_EXIST;
5009
5010 if (lock_cmd_type & SD_SET_PWD)
5011 sd_card->sd_lock_status |= SD_PWD_EXIST;
5012 }
5013
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02005014 dev_dbg(rtsx_dev(chip), "sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
5015 sd_lock_state, sd_card->sd_lock_status);
Micky Chingfa590c22013-11-12 17:16:08 +08005016 if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
5017 sd_card->sd_lock_notify = 1;
5018 if (sd_lock_state) {
5019 if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) {
5020 sd_card->sd_lock_status |= (
5021 SD_UNLOCK_POW_ON | SD_SDR_RST);
5022 if (CHK_SD(sd_card)) {
5023 retval = reset_sd(chip);
5024 if (retval != STATUS_SUCCESS) {
5025 sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
Joe Perches031366e2015-03-25 12:54:25 -07005026 rtsx_trace(chip);
5027 goto SD_Execute_Write_Cmd_Failed;
Micky Chingfa590c22013-11-12 17:16:08 +08005028 }
5029 }
5030
5031 sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
5032 }
5033 }
5034 }
5035 }
5036
5037 if (lock_cmd_fail) {
5038 scsi_set_resid(srb, 0);
5039 set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
Joe Perches031366e2015-03-25 12:54:25 -07005040 rtsx_trace(chip);
5041 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005042 }
5043#endif /* SUPPORT_SD_LOCK */
5044
5045 scsi_set_resid(srb, 0);
5046 return TRANSPORT_GOOD;
5047
5048SD_Execute_Write_Cmd_Failed:
5049 sd_card->pre_cmd_err = 1;
5050 set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
5051 if (write_err)
5052 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
5053
5054 release_sd_card(chip);
5055 do_reset_sd_card(chip);
5056 if (!(chip->card_ready & SD_CARD))
5057 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
5058
Joe Perches031366e2015-03-25 12:54:25 -07005059 rtsx_trace(chip);
5060 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005061}
5062
5063int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
5064{
5065 struct sd_info *sd_card = &(chip->sd_card);
5066 unsigned int lun = SCSI_LUN(srb);
5067 int count;
5068 u16 data_len;
5069
5070 if (!sd_card->sd_pass_thru_en) {
5071 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07005072 rtsx_trace(chip);
5073 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005074 }
5075
5076 if (sd_card->pre_cmd_err) {
5077 sd_card->pre_cmd_err = 0;
5078 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07005079 rtsx_trace(chip);
5080 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005081 }
5082
5083 data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
5084
5085 if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
5086 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07005087 rtsx_trace(chip);
5088 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005089 } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
5090 count = (data_len < 17) ? data_len : 17;
5091 } else {
5092 count = (data_len < 6) ? data_len : 6;
5093 }
5094 rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
5095
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02005096 dev_dbg(rtsx_dev(chip), "Response length: %d\n", data_len);
5097 dev_dbg(rtsx_dev(chip), "Response: 0x%x 0x%x 0x%x 0x%x\n",
5098 sd_card->rsp[0], sd_card->rsp[1],
5099 sd_card->rsp[2], sd_card->rsp[3]);
Micky Chingfa590c22013-11-12 17:16:08 +08005100
5101 scsi_set_resid(srb, 0);
5102 return TRANSPORT_GOOD;
5103}
5104
5105int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
5106{
5107 struct sd_info *sd_card = &(chip->sd_card);
5108 unsigned int lun = SCSI_LUN(srb);
5109 int retval;
5110
5111 if (!sd_card->sd_pass_thru_en) {
5112 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07005113 rtsx_trace(chip);
5114 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005115 }
5116
5117 if (sd_card->pre_cmd_err) {
5118 sd_card->pre_cmd_err = 0;
5119 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
Joe Perches031366e2015-03-25 12:54:25 -07005120 rtsx_trace(chip);
5121 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005122 }
5123
Janani Ravichandran3b15cfb2016-02-13 21:57:51 -05005124 if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) ||
5125 (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) ||
5126 (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) ||
5127 (srb->cmnd[8] != 0x64)) {
Micky Chingfa590c22013-11-12 17:16:08 +08005128 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07005129 rtsx_trace(chip);
5130 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005131 }
5132
5133 switch (srb->cmnd[1] & 0x0F) {
5134 case 0:
5135#ifdef SUPPORT_SD_LOCK
Janani Ravichandran3b15cfb2016-02-13 21:57:51 -05005136 if (srb->cmnd[9] == 0x64)
Micky Chingfa590c22013-11-12 17:16:08 +08005137 sd_card->sd_lock_status |= SD_SDR_RST;
5138#endif
5139 retval = reset_sd_card(chip);
5140 if (retval != STATUS_SUCCESS) {
5141#ifdef SUPPORT_SD_LOCK
5142 sd_card->sd_lock_status &= ~SD_SDR_RST;
5143#endif
5144 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
5145 sd_card->pre_cmd_err = 1;
Joe Perches031366e2015-03-25 12:54:25 -07005146 rtsx_trace(chip);
5147 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005148 }
5149#ifdef SUPPORT_SD_LOCK
5150 sd_card->sd_lock_status &= ~SD_SDR_RST;
5151#endif
5152 break;
5153
5154 case 1:
5155 retval = soft_reset_sd_card(chip);
5156 if (retval != STATUS_SUCCESS) {
5157 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
5158 sd_card->pre_cmd_err = 1;
Joe Perches031366e2015-03-25 12:54:25 -07005159 rtsx_trace(chip);
5160 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005161 }
5162 break;
5163
5164 default:
5165 set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
Joe Perches031366e2015-03-25 12:54:25 -07005166 rtsx_trace(chip);
5167 return TRANSPORT_FAILED;
Micky Chingfa590c22013-11-12 17:16:08 +08005168 }
5169
5170 scsi_set_resid(srb, 0);
5171 return TRANSPORT_GOOD;
5172}
5173#endif
5174
5175void sd_cleanup_work(struct rtsx_chip *chip)
5176{
5177 struct sd_info *sd_card = &(chip->sd_card);
5178
5179 if (sd_card->seq_mode) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02005180 dev_dbg(rtsx_dev(chip), "SD: stop transmission\n");
Micky Chingfa590c22013-11-12 17:16:08 +08005181 sd_stop_seq_mode(chip);
5182 sd_card->cleanup_counter = 0;
5183 }
5184}
5185
5186int sd_power_off_card3v3(struct rtsx_chip *chip)
5187{
5188 int retval;
5189
5190 retval = disable_card_clock(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07005191 if (retval != STATUS_SUCCESS) {
5192 rtsx_trace(chip);
5193 return STATUS_FAIL;
5194 }
Micky Chingfa590c22013-11-12 17:16:08 +08005195
Joe Perches8ee775f2015-03-25 12:54:26 -07005196 retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
5197 if (retval) {
5198 rtsx_trace(chip);
5199 return retval;
5200 }
Micky Chingfa590c22013-11-12 17:16:08 +08005201
5202 if (!chip->ft2_fast_mode) {
5203 retval = card_power_off(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -07005204 if (retval != STATUS_SUCCESS) {
5205 rtsx_trace(chip);
5206 return STATUS_FAIL;
5207 }
Micky Chingfa590c22013-11-12 17:16:08 +08005208
5209 wait_timeout(50);
5210 }
5211
5212 if (chip->asic_code) {
5213 retval = sd_pull_ctl_disable(chip);
Joe Perches031366e2015-03-25 12:54:25 -07005214 if (retval != STATUS_SUCCESS) {
5215 rtsx_trace(chip);
5216 return STATUS_FAIL;
5217 }
Micky Chingfa590c22013-11-12 17:16:08 +08005218 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -07005219 retval = rtsx_write_register(chip, FPGA_PULL_CTL,
5220 FPGA_SD_PULL_CTL_BIT | 0x20,
5221 FPGA_SD_PULL_CTL_BIT);
5222 if (retval) {
5223 rtsx_trace(chip);
5224 return retval;
5225 }
Micky Chingfa590c22013-11-12 17:16:08 +08005226 }
5227
5228 return STATUS_SUCCESS;
5229}
5230
5231int release_sd_card(struct rtsx_chip *chip)
5232{
5233 struct sd_info *sd_card = &(chip->sd_card);
5234 int retval;
5235
Micky Chingfa590c22013-11-12 17:16:08 +08005236 chip->card_ready &= ~SD_CARD;
5237 chip->card_fail &= ~SD_CARD;
5238 chip->card_wp &= ~SD_CARD;
5239
5240 chip->sd_io = 0;
5241 chip->sd_int = 0;
5242
5243#ifdef SUPPORT_SD_LOCK
5244 sd_card->sd_lock_status = 0;
5245 sd_card->sd_erase_status = 0;
5246#endif
5247
5248 memset(sd_card->raw_csd, 0, 16);
5249 memset(sd_card->raw_scr, 0, 8);
5250
5251 retval = sd_power_off_card3v3(chip);
Joe Perches031366e2015-03-25 12:54:25 -07005252 if (retval != STATUS_SUCCESS) {
5253 rtsx_trace(chip);
5254 return STATUS_FAIL;
5255 }
Micky Chingfa590c22013-11-12 17:16:08 +08005256
5257 return STATUS_SUCCESS;
5258}