177d89b08766c878a2594b15d203e513acf952340wwang/* Driver for Realtek PCI-Express card reader
277d89b08766c878a2594b15d203e513acf952340wwang *
377d89b08766c878a2594b15d203e513acf952340wwang * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
477d89b08766c878a2594b15d203e513acf952340wwang *
577d89b08766c878a2594b15d203e513acf952340wwang * This program is free software; you can redistribute it and/or modify it
677d89b08766c878a2594b15d203e513acf952340wwang * under the terms of the GNU General Public License as published by the
777d89b08766c878a2594b15d203e513acf952340wwang * Free Software Foundation; either version 2, or (at your option) any
877d89b08766c878a2594b15d203e513acf952340wwang * later version.
977d89b08766c878a2594b15d203e513acf952340wwang *
1077d89b08766c878a2594b15d203e513acf952340wwang * This program is distributed in the hope that it will be useful, but
1177d89b08766c878a2594b15d203e513acf952340wwang * WITHOUT ANY WARRANTY; without even the implied warranty of
1277d89b08766c878a2594b15d203e513acf952340wwang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1377d89b08766c878a2594b15d203e513acf952340wwang * General Public License for more details.
1477d89b08766c878a2594b15d203e513acf952340wwang *
1577d89b08766c878a2594b15d203e513acf952340wwang * You should have received a copy of the GNU General Public License along
1677d89b08766c878a2594b15d203e513acf952340wwang * with this program; if not, see <http://www.gnu.org/licenses/>.
1777d89b08766c878a2594b15d203e513acf952340wwang *
1877d89b08766c878a2594b15d203e513acf952340wwang * Author:
1977d89b08766c878a2594b15d203e513acf952340wwang *   wwang (wei_wang@realsil.com.cn)
2077d89b08766c878a2594b15d203e513acf952340wwang *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
2177d89b08766c878a2594b15d203e513acf952340wwang */
2277d89b08766c878a2594b15d203e513acf952340wwang
2377d89b08766c878a2594b15d203e513acf952340wwang#include <linux/blkdev.h>
2477d89b08766c878a2594b15d203e513acf952340wwang#include <linux/kthread.h>
2577d89b08766c878a2594b15d203e513acf952340wwang#include <linux/sched.h>
2677d89b08766c878a2594b15d203e513acf952340wwang
2777d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx.h"
2877d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_transport.h"
2977d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_scsi.h"
3077d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_card.h"
3177d89b08766c878a2594b15d203e513acf952340wwang#include "sd.h"
3277d89b08766c878a2594b15d203e513acf952340wwang
3377d89b08766c878a2594b15d203e513acf952340wwang#define SD_MAX_RETRY_COUNT	3
3477d89b08766c878a2594b15d203e513acf952340wwang
356680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CFG1;
366680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CFG2;
376680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CFG3;
386680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_STAT1;
396680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_STAT2;
406680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_BUS_STAT;
416680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_PAD_CTL;
426680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_SAMPLE_POINT_CTL;
436680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_PUSH_POINT_CTL;
446680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD0;
456680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD1;
466680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD2;
476680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD3;
486680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD4;
496680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_CMD5;
506680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_BYTE_CNT_L;
516680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_BYTE_CNT_H;
526680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_BLOCK_CNT_L;
536680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_BLOCK_CNT_H;
546680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_TRANSFER;
556680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_VPCLK0_CTL;
566680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_VPCLK1_CTL;
576680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_DCMPS0_CTL;
586680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic u16 REG_SD_DCMPS1_CTL;
5977d89b08766c878a2594b15d203e513acf952340wwang
6077d89b08766c878a2594b15d203e513acf952340wwangstatic inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
6177d89b08766c878a2594b15d203e513acf952340wwang{
6277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
6377d89b08766c878a2594b15d203e513acf952340wwang
6477d89b08766c878a2594b15d203e513acf952340wwang	sd_card->err_code |= err_code;
6577d89b08766c878a2594b15d203e513acf952340wwang}
6677d89b08766c878a2594b15d203e513acf952340wwang
6777d89b08766c878a2594b15d203e513acf952340wwangstatic inline void sd_clr_err_code(struct rtsx_chip *chip)
6877d89b08766c878a2594b15d203e513acf952340wwang{
6977d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
7077d89b08766c878a2594b15d203e513acf952340wwang
7177d89b08766c878a2594b15d203e513acf952340wwang	sd_card->err_code = 0;
7277d89b08766c878a2594b15d203e513acf952340wwang}
7377d89b08766c878a2594b15d203e513acf952340wwang
7477d89b08766c878a2594b15d203e513acf952340wwangstatic inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
7577d89b08766c878a2594b15d203e513acf952340wwang{
7677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
7777d89b08766c878a2594b15d203e513acf952340wwang
7877d89b08766c878a2594b15d203e513acf952340wwang	return sd_card->err_code & err_code;
7977d89b08766c878a2594b15d203e513acf952340wwang}
8077d89b08766c878a2594b15d203e513acf952340wwang
8177d89b08766c878a2594b15d203e513acf952340wwangstatic void sd_init_reg_addr(struct rtsx_chip *chip)
8277d89b08766c878a2594b15d203e513acf952340wwang{
8377d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
8477d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG1 = SD_CFG1;
8577d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG2 = SD_CFG2;
8677d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG3 = SD_CFG3;
8777d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_STAT1 = SD_STAT1;
8877d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_STAT2 = SD_STAT2;
8977d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BUS_STAT = SD_BUS_STAT;
9077d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_PAD_CTL = SD_PAD_CTL;
9177d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_SAMPLE_POINT_CTL = SD_SAMPLE_POINT_CTL;
9277d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_PUSH_POINT_CTL = SD_PUSH_POINT_CTL;
9377d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD0 = SD_CMD0;
9477d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD1 = SD_CMD1;
9577d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD2 = SD_CMD2;
9677d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD3 = SD_CMD3;
9777d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD4 = SD_CMD4;
9877d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD5 = SD_CMD5;
9977d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BYTE_CNT_L = SD_BYTE_CNT_L;
10077d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BYTE_CNT_H = SD_BYTE_CNT_H;
10177d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BLOCK_CNT_L = SD_BLOCK_CNT_L;
10277d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BLOCK_CNT_H = SD_BLOCK_CNT_H;
10377d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_TRANSFER = SD_TRANSFER;
10477d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_VPCLK0_CTL = SD_VPCLK0_CTL;
10577d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_VPCLK1_CTL = SD_VPCLK1_CTL;
10677d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_DCMPS0_CTL = SD_DCMPS0_CTL;
10777d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_DCMPS1_CTL = SD_DCMPS1_CTL;
10877d89b08766c878a2594b15d203e513acf952340wwang	} else {
10977d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG1 = 0xFD31;
11077d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG2 = 0xFD33;
11177d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CFG3 = 0xFD3E;
11277d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_STAT1 = 0xFD30;
11377d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_STAT2 = 0;
11477d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BUS_STAT = 0;
11577d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_PAD_CTL = 0;
11677d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_SAMPLE_POINT_CTL = 0;
11777d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_PUSH_POINT_CTL = 0;
11877d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD0 = 0xFD34;
11977d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD1 = 0xFD35;
12077d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD2 = 0xFD36;
12177d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD3 = 0xFD37;
12277d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD4 = 0xFD38;
12377d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_CMD5 = 0xFD5A;
12477d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BYTE_CNT_L = 0xFD39;
12577d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BYTE_CNT_H = 0xFD3A;
12677d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BLOCK_CNT_L = 0xFD3B;
12777d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_BLOCK_CNT_H = 0xFD3C;
12877d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_TRANSFER = 0xFD32;
12977d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_VPCLK0_CTL = 0;
13077d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_VPCLK1_CTL = 0;
13177d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_DCMPS0_CTL = 0;
13277d89b08766c878a2594b15d203e513acf952340wwang		REG_SD_DCMPS1_CTL = 0;
13377d89b08766c878a2594b15d203e513acf952340wwang	}
13477d89b08766c878a2594b15d203e513acf952340wwang}
13577d89b08766c878a2594b15d203e513acf952340wwang
13677d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_data0_status(struct rtsx_chip *chip)
13777d89b08766c878a2594b15d203e513acf952340wwang{
13877d89b08766c878a2594b15d203e513acf952340wwang	u8 stat;
13977d89b08766c878a2594b15d203e513acf952340wwang
14077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
14177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_READ_REG(chip, REG_SD_BUS_STAT, &stat);
14277d89b08766c878a2594b15d203e513acf952340wwang	} else {
14377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_READ_REG(chip, REG_SD_STAT1, &stat);
14477d89b08766c878a2594b15d203e513acf952340wwang	}
14577d89b08766c878a2594b15d203e513acf952340wwang
14677d89b08766c878a2594b15d203e513acf952340wwang	if (!(stat & SD_DAT0_STATUS)) {
14777d89b08766c878a2594b15d203e513acf952340wwang		sd_set_err_code(chip, SD_BUSY);
14877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
14977d89b08766c878a2594b15d203e513acf952340wwang	}
15077d89b08766c878a2594b15d203e513acf952340wwang
15177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
15277d89b08766c878a2594b15d203e513acf952340wwang}
15377d89b08766c878a2594b15d203e513acf952340wwang
15477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
15577d89b08766c878a2594b15d203e513acf952340wwang		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
15677d89b08766c878a2594b15d203e513acf952340wwang{
15777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
15877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
15977d89b08766c878a2594b15d203e513acf952340wwang	int timeout = 100;
16077d89b08766c878a2594b15d203e513acf952340wwang	u16 reg_addr;
16177d89b08766c878a2594b15d203e513acf952340wwang	u8 *ptr;
16277d89b08766c878a2594b15d203e513acf952340wwang	int stat_idx = 0;
16377d89b08766c878a2594b15d203e513acf952340wwang	int rty_cnt = 0;
16477d89b08766c878a2594b15d203e513acf952340wwang
16577d89b08766c878a2594b15d203e513acf952340wwang	sd_clr_err_code(chip);
16677d89b08766c878a2594b15d203e513acf952340wwang
16777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
16877d89b08766c878a2594b15d203e513acf952340wwang
16977d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R1b)
17077d89b08766c878a2594b15d203e513acf952340wwang		timeout = 3000;
17177d89b08766c878a2594b15d203e513acf952340wwang
17277d89b08766c878a2594b15d203e513acf952340wwangRTY_SEND_CMD:
17377d89b08766c878a2594b15d203e513acf952340wwang
17477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
17577d89b08766c878a2594b15d203e513acf952340wwang
17677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
17777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
17877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
17977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
18077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
18177d89b08766c878a2594b15d203e513acf952340wwang
18277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
18377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
18477d89b08766c878a2594b15d203e513acf952340wwang			0x01, PINGPONG_BUFFER);
18577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
18677d89b08766c878a2594b15d203e513acf952340wwang			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
18777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
18877d89b08766c878a2594b15d203e513acf952340wwang		     SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE);
18977d89b08766c878a2594b15d203e513acf952340wwang
19077d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R2) {
19177d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
19277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
19377d89b08766c878a2594b15d203e513acf952340wwang		}
19477d89b08766c878a2594b15d203e513acf952340wwang		stat_idx = 16;
19577d89b08766c878a2594b15d203e513acf952340wwang	} else if (rsp_type != SD_RSP_TYPE_R0) {
19677d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
19777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
19877d89b08766c878a2594b15d203e513acf952340wwang		}
19977d89b08766c878a2594b15d203e513acf952340wwang		stat_idx = 5;
20077d89b08766c878a2594b15d203e513acf952340wwang	}
20177d89b08766c878a2594b15d203e513acf952340wwang
20277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
20377d89b08766c878a2594b15d203e513acf952340wwang
20477d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
20577d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
20677d89b08766c878a2594b15d203e513acf952340wwang		u8 val;
20777d89b08766c878a2594b15d203e513acf952340wwang
20877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_read_register(chip, REG_SD_STAT1, &val);
20977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD_STAT1: 0x%x\n", val);
21077d89b08766c878a2594b15d203e513acf952340wwang
21177d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209)) {
21277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_read_register(chip, REG_SD_STAT2, &val);
21377d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD_STAT2: 0x%x\n", val);
21477d89b08766c878a2594b15d203e513acf952340wwang
21577d89b08766c878a2594b15d203e513acf952340wwang			if (val & SD_RSP_80CLK_TIMEOUT) {
21677d89b08766c878a2594b15d203e513acf952340wwang				rtsx_clear_sd_error(chip);
21777d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_RSP_TIMEOUT);
21877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
21977d89b08766c878a2594b15d203e513acf952340wwang			}
22077d89b08766c878a2594b15d203e513acf952340wwang
22177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_read_register(chip, REG_SD_BUS_STAT, &val);
22277d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val);
22377d89b08766c878a2594b15d203e513acf952340wwang		} else {
22477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_read_register(chip, REG_SD_CFG3, &val);
22577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD_CFG3: 0x%x\n", val);
22677d89b08766c878a2594b15d203e513acf952340wwang		}
22777d89b08766c878a2594b15d203e513acf952340wwang
22877d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
22977d89b08766c878a2594b15d203e513acf952340wwang			if (rsp_type & SD_WAIT_BUSY_END) {
23077d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_check_data0_status(chip);
23177d89b08766c878a2594b15d203e513acf952340wwang				if (retval != STATUS_SUCCESS) {
23277d89b08766c878a2594b15d203e513acf952340wwang					rtsx_clear_sd_error(chip);
23377d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, retval);
23477d89b08766c878a2594b15d203e513acf952340wwang				}
23577d89b08766c878a2594b15d203e513acf952340wwang			} else {
23677d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_TO_ERR);
23777d89b08766c878a2594b15d203e513acf952340wwang			}
23877d89b08766c878a2594b15d203e513acf952340wwang			retval = STATUS_TIMEDOUT;
23977d89b08766c878a2594b15d203e513acf952340wwang		} else {
24077d89b08766c878a2594b15d203e513acf952340wwang			retval = STATUS_FAIL;
24177d89b08766c878a2594b15d203e513acf952340wwang		}
24277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
24377d89b08766c878a2594b15d203e513acf952340wwang
24477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, retval);
24577d89b08766c878a2594b15d203e513acf952340wwang	}
24677d89b08766c878a2594b15d203e513acf952340wwang
24777d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R0)
24877d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_SUCCESS;
24977d89b08766c878a2594b15d203e513acf952340wwang
25077d89b08766c878a2594b15d203e513acf952340wwang	ptr = rtsx_get_cmd_data(chip) + 1;
25177d89b08766c878a2594b15d203e513acf952340wwang
25277d89b08766c878a2594b15d203e513acf952340wwang	if ((ptr[0] & 0xC0) != 0) {
25377d89b08766c878a2594b15d203e513acf952340wwang		sd_set_err_code(chip, SD_STS_ERR);
25477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
25577d89b08766c878a2594b15d203e513acf952340wwang	}
25677d89b08766c878a2594b15d203e513acf952340wwang
25777d89b08766c878a2594b15d203e513acf952340wwang	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
25877d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[stat_idx] & SD_CRC7_ERR) {
25977d89b08766c878a2594b15d203e513acf952340wwang			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
26077d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_CRC_ERR);
26177d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
26277d89b08766c878a2594b15d203e513acf952340wwang			}
26377d89b08766c878a2594b15d203e513acf952340wwang			if (rty_cnt < SD_MAX_RETRY_COUNT) {
26477d89b08766c878a2594b15d203e513acf952340wwang				wait_timeout(20);
26577d89b08766c878a2594b15d203e513acf952340wwang				rty_cnt++;
26677d89b08766c878a2594b15d203e513acf952340wwang				goto RTY_SEND_CMD;
26777d89b08766c878a2594b15d203e513acf952340wwang			} else {
26877d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_CRC_ERR);
26977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
27077d89b08766c878a2594b15d203e513acf952340wwang			}
27177d89b08766c878a2594b15d203e513acf952340wwang		}
27277d89b08766c878a2594b15d203e513acf952340wwang	}
27377d89b08766c878a2594b15d203e513acf952340wwang
27477d89b08766c878a2594b15d203e513acf952340wwang	if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) {
27577d89b08766c878a2594b15d203e513acf952340wwang		if ((cmd_idx != SEND_RELATIVE_ADDR) && (cmd_idx != SEND_IF_COND)) {
27677d89b08766c878a2594b15d203e513acf952340wwang			if (cmd_idx != STOP_TRANSMISSION) {
27777d89b08766c878a2594b15d203e513acf952340wwang				if (ptr[1] & 0x80) {
27877d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
27977d89b08766c878a2594b15d203e513acf952340wwang				}
28077d89b08766c878a2594b15d203e513acf952340wwang			}
28177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
28277d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[1] & 0x7D)
28377d89b08766c878a2594b15d203e513acf952340wwang#else
28477d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[1] & 0x7F)
28577d89b08766c878a2594b15d203e513acf952340wwang#endif
28677d89b08766c878a2594b15d203e513acf952340wwang			{
28777d89b08766c878a2594b15d203e513acf952340wwang				RTSX_DEBUGP("ptr[1]: 0x%02x\n", ptr[1]);
28877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
28977d89b08766c878a2594b15d203e513acf952340wwang			}
29077d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[2] & 0xFF) {
29177d89b08766c878a2594b15d203e513acf952340wwang				RTSX_DEBUGP("ptr[2]: 0x%02x\n", ptr[2]);
29277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
29377d89b08766c878a2594b15d203e513acf952340wwang			}
29477d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[3] & 0x80) {
29577d89b08766c878a2594b15d203e513acf952340wwang				RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]);
29677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
29777d89b08766c878a2594b15d203e513acf952340wwang			}
29877d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[3] & 0x01) {
29977d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_data_buf_ready = 1;
30077d89b08766c878a2594b15d203e513acf952340wwang			} else {
30177d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_data_buf_ready = 0;
30277d89b08766c878a2594b15d203e513acf952340wwang			}
30377d89b08766c878a2594b15d203e513acf952340wwang		}
30477d89b08766c878a2594b15d203e513acf952340wwang	}
30577d89b08766c878a2594b15d203e513acf952340wwang
30677d89b08766c878a2594b15d203e513acf952340wwang	if (rsp && rsp_len)
30777d89b08766c878a2594b15d203e513acf952340wwang		memcpy(rsp, ptr, rsp_len);
30877d89b08766c878a2594b15d203e513acf952340wwang
30977d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
31077d89b08766c878a2594b15d203e513acf952340wwang}
31177d89b08766c878a2594b15d203e513acf952340wwang
31277d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_read_data(struct rtsx_chip *chip,
31377d89b08766c878a2594b15d203e513acf952340wwang			u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
31477d89b08766c878a2594b15d203e513acf952340wwang			u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
31577d89b08766c878a2594b15d203e513acf952340wwang			int timeout)
31677d89b08766c878a2594b15d203e513acf952340wwang{
31777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
31877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
31977d89b08766c878a2594b15d203e513acf952340wwang	int i;
32077d89b08766c878a2594b15d203e513acf952340wwang
32177d89b08766c878a2594b15d203e513acf952340wwang	sd_clr_err_code(chip);
32277d89b08766c878a2594b15d203e513acf952340wwang
32377d89b08766c878a2594b15d203e513acf952340wwang	if (!buf)
32477d89b08766c878a2594b15d203e513acf952340wwang		buf_len = 0;
32577d89b08766c878a2594b15d203e513acf952340wwang
32677d89b08766c878a2594b15d203e513acf952340wwang	if (buf_len > 512) {
32777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
32877d89b08766c878a2594b15d203e513acf952340wwang	}
32977d89b08766c878a2594b15d203e513acf952340wwang
33077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
33177d89b08766c878a2594b15d203e513acf952340wwang
33277d89b08766c878a2594b15d203e513acf952340wwang	if (cmd_len) {
33377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
33477d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) {
33577d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, 0xFF, cmd[i]);
33677d89b08766c878a2594b15d203e513acf952340wwang		}
33777d89b08766c878a2594b15d203e513acf952340wwang	}
33877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
33977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
34077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
34177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
34277d89b08766c878a2594b15d203e513acf952340wwang
34377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
34477d89b08766c878a2594b15d203e513acf952340wwang
34577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
34677d89b08766c878a2594b15d203e513acf952340wwang			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
34777d89b08766c878a2594b15d203e513acf952340wwang			SD_CHECK_CRC7 | SD_RSP_LEN_6);
34877d89b08766c878a2594b15d203e513acf952340wwang	if (trans_mode != SD_TM_AUTO_TUNING) {
34977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
35077d89b08766c878a2594b15d203e513acf952340wwang	}
35177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
35277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
35377d89b08766c878a2594b15d203e513acf952340wwang
35477d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
35577d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
35677d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
35777d89b08766c878a2594b15d203e513acf952340wwang			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
35877d89b08766c878a2594b15d203e513acf952340wwang					    SD_RSP_TYPE_R1, NULL, 0);
35977d89b08766c878a2594b15d203e513acf952340wwang		}
36077d89b08766c878a2594b15d203e513acf952340wwang
36177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
36277d89b08766c878a2594b15d203e513acf952340wwang	}
36377d89b08766c878a2594b15d203e513acf952340wwang
36477d89b08766c878a2594b15d203e513acf952340wwang	if (buf && buf_len) {
36577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_ppbuf(chip, buf, buf_len);
36677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
36777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
36877d89b08766c878a2594b15d203e513acf952340wwang		}
36977d89b08766c878a2594b15d203e513acf952340wwang	}
37077d89b08766c878a2594b15d203e513acf952340wwang
37177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
37277d89b08766c878a2594b15d203e513acf952340wwang}
37377d89b08766c878a2594b15d203e513acf952340wwang
37477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
37577d89b08766c878a2594b15d203e513acf952340wwang		u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width,
37677d89b08766c878a2594b15d203e513acf952340wwang		u8 *buf, int buf_len, int timeout)
37777d89b08766c878a2594b15d203e513acf952340wwang{
37877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
37977d89b08766c878a2594b15d203e513acf952340wwang	int retval;
38077d89b08766c878a2594b15d203e513acf952340wwang	int i;
38177d89b08766c878a2594b15d203e513acf952340wwang
38277d89b08766c878a2594b15d203e513acf952340wwang	sd_clr_err_code(chip);
38377d89b08766c878a2594b15d203e513acf952340wwang
38477d89b08766c878a2594b15d203e513acf952340wwang	if (!buf)
38577d89b08766c878a2594b15d203e513acf952340wwang		buf_len = 0;
38677d89b08766c878a2594b15d203e513acf952340wwang
38777d89b08766c878a2594b15d203e513acf952340wwang	if (buf_len > 512) {
38877d89b08766c878a2594b15d203e513acf952340wwang		/* This function can't write data more than one page */
38977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
39077d89b08766c878a2594b15d203e513acf952340wwang	}
39177d89b08766c878a2594b15d203e513acf952340wwang
39277d89b08766c878a2594b15d203e513acf952340wwang	if (buf && buf_len) {
39377d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_ppbuf(chip, buf, buf_len);
39477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
39577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
39677d89b08766c878a2594b15d203e513acf952340wwang		}
39777d89b08766c878a2594b15d203e513acf952340wwang	}
39877d89b08766c878a2594b15d203e513acf952340wwang
39977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
40077d89b08766c878a2594b15d203e513acf952340wwang
40177d89b08766c878a2594b15d203e513acf952340wwang	if (cmd_len) {
40277d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
40377d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) {
40477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD,
40577d89b08766c878a2594b15d203e513acf952340wwang				     REG_SD_CMD0 + i, 0xFF, cmd[i]);
40677d89b08766c878a2594b15d203e513acf952340wwang		}
40777d89b08766c878a2594b15d203e513acf952340wwang	}
40877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
40977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
41077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
41177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
41277d89b08766c878a2594b15d203e513acf952340wwang
41377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
41477d89b08766c878a2594b15d203e513acf952340wwang
41577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
41677d89b08766c878a2594b15d203e513acf952340wwang		SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
41777d89b08766c878a2594b15d203e513acf952340wwang		SD_CHECK_CRC7 | SD_RSP_LEN_6);
41877d89b08766c878a2594b15d203e513acf952340wwang
41977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
42077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
42177d89b08766c878a2594b15d203e513acf952340wwang
42277d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
42377d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
42477d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
42577d89b08766c878a2594b15d203e513acf952340wwang			sd_send_cmd_get_rsp(chip, SEND_STATUS,
42677d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
42777d89b08766c878a2594b15d203e513acf952340wwang		}
42877d89b08766c878a2594b15d203e513acf952340wwang
42977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
43077d89b08766c878a2594b15d203e513acf952340wwang	}
43177d89b08766c878a2594b15d203e513acf952340wwang
43277d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
43377d89b08766c878a2594b15d203e513acf952340wwang}
43477d89b08766c878a2594b15d203e513acf952340wwang
43577d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_csd(struct rtsx_chip *chip, char check_wp)
43677d89b08766c878a2594b15d203e513acf952340wwang{
43777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
43877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
43977d89b08766c878a2594b15d203e513acf952340wwang	int i;
44077d89b08766c878a2594b15d203e513acf952340wwang	u8 csd_ver, trans_speed;
44177d89b08766c878a2594b15d203e513acf952340wwang	u8 rsp[16];
44277d89b08766c878a2594b15d203e513acf952340wwang
44377d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 6; i++) {
44477d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
44577d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_NO_CARD);
44677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
44777d89b08766c878a2594b15d203e513acf952340wwang		}
44877d89b08766c878a2594b15d203e513acf952340wwang
44977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, SD_RSP_TYPE_R2, rsp, 16);
45077d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS)
45177d89b08766c878a2594b15d203e513acf952340wwang			break;
45277d89b08766c878a2594b15d203e513acf952340wwang	}
45377d89b08766c878a2594b15d203e513acf952340wwang
45477d89b08766c878a2594b15d203e513acf952340wwang	if (i == 6) {
45577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
45677d89b08766c878a2594b15d203e513acf952340wwang	}
45777d89b08766c878a2594b15d203e513acf952340wwang
45877d89b08766c878a2594b15d203e513acf952340wwang	memcpy(sd_card->raw_csd, rsp + 1, 15);
45977d89b08766c878a2594b15d203e513acf952340wwang
46077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
46177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_READ_REG(chip, REG_SD_CMD5, sd_card->raw_csd + 15);
46277d89b08766c878a2594b15d203e513acf952340wwang	}
46377d89b08766c878a2594b15d203e513acf952340wwang
46477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("CSD Response:\n");
46577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DUMP(sd_card->raw_csd, 16);
46677d89b08766c878a2594b15d203e513acf952340wwang
46777d89b08766c878a2594b15d203e513acf952340wwang	csd_ver = (rsp[1] & 0xc0) >> 6;
46877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("csd_ver = %d\n", csd_ver);
46977d89b08766c878a2594b15d203e513acf952340wwang
47077d89b08766c878a2594b15d203e513acf952340wwang	trans_speed = rsp[4];
47177d89b08766c878a2594b15d203e513acf952340wwang	if ((trans_speed & 0x07) == 0x02) {
47277d89b08766c878a2594b15d203e513acf952340wwang		if ((trans_speed & 0xf8) >= 0x30) {
47377d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
47477d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = 47;
47577d89b08766c878a2594b15d203e513acf952340wwang			} else {
47677d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = CLK_50;
47777d89b08766c878a2594b15d203e513acf952340wwang			}
47877d89b08766c878a2594b15d203e513acf952340wwang		} else if ((trans_speed & 0xf8) == 0x28) {
47977d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
48077d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = 39;
48177d89b08766c878a2594b15d203e513acf952340wwang			} else {
48277d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = CLK_40;
48377d89b08766c878a2594b15d203e513acf952340wwang			}
48477d89b08766c878a2594b15d203e513acf952340wwang		} else if ((trans_speed & 0xf8) == 0x20) {
48577d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
48677d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = 29;
48777d89b08766c878a2594b15d203e513acf952340wwang			} else {
48877d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = CLK_30;
48977d89b08766c878a2594b15d203e513acf952340wwang			}
49077d89b08766c878a2594b15d203e513acf952340wwang		} else if ((trans_speed & 0xf8) >= 0x10) {
49177d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
49277d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = 23;
49377d89b08766c878a2594b15d203e513acf952340wwang			} else {
49477d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = CLK_20;
49577d89b08766c878a2594b15d203e513acf952340wwang			}
49677d89b08766c878a2594b15d203e513acf952340wwang		} else if ((trans_speed & 0x08) >= 0x08) {
49777d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
49877d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = 19;
49977d89b08766c878a2594b15d203e513acf952340wwang			} else {
50077d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_clock = CLK_20;
50177d89b08766c878a2594b15d203e513acf952340wwang			}
50277d89b08766c878a2594b15d203e513acf952340wwang		} else {
50377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
50477d89b08766c878a2594b15d203e513acf952340wwang		}
50577d89b08766c878a2594b15d203e513acf952340wwang	} else {
50677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
50777d89b08766c878a2594b15d203e513acf952340wwang	}
50877d89b08766c878a2594b15d203e513acf952340wwang
50977d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_MMC_SECTOR_MODE(sd_card)) {
51077d89b08766c878a2594b15d203e513acf952340wwang		sd_card->capacity = 0;
51177d89b08766c878a2594b15d203e513acf952340wwang	} else {
51277d89b08766c878a2594b15d203e513acf952340wwang		if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) {
51377d89b08766c878a2594b15d203e513acf952340wwang			u8 blk_size, c_size_mult;
51477d89b08766c878a2594b15d203e513acf952340wwang			u16 c_size;
51577d89b08766c878a2594b15d203e513acf952340wwang			blk_size = rsp[6] & 0x0F;
51677d89b08766c878a2594b15d203e513acf952340wwang			c_size =  ((u16)(rsp[7] & 0x03) << 10)
51777d89b08766c878a2594b15d203e513acf952340wwang					+ ((u16)rsp[8] << 2)
51877d89b08766c878a2594b15d203e513acf952340wwang					+ ((u16)(rsp[9] & 0xC0) >> 6);
51977d89b08766c878a2594b15d203e513acf952340wwang			c_size_mult = (u8)((rsp[10] & 0x03) << 1);
52077d89b08766c878a2594b15d203e513acf952340wwang			c_size_mult += (rsp[11] & 0x80) >> 7;
52177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->capacity = (((u32)(c_size + 1)) * (1 << (c_size_mult + 2))) << (blk_size - 9);
52277d89b08766c878a2594b15d203e513acf952340wwang		} else {
52377d89b08766c878a2594b15d203e513acf952340wwang			u32 total_sector = 0;
52477d89b08766c878a2594b15d203e513acf952340wwang			total_sector = (((u32)rsp[8] & 0x3f) << 16) |
52577d89b08766c878a2594b15d203e513acf952340wwang				((u32)rsp[9] << 8) | (u32)rsp[10];
52677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->capacity = (total_sector + 1) << 10;
52777d89b08766c878a2594b15d203e513acf952340wwang		}
52877d89b08766c878a2594b15d203e513acf952340wwang	}
52977d89b08766c878a2594b15d203e513acf952340wwang
53077d89b08766c878a2594b15d203e513acf952340wwang	if (check_wp) {
53177d89b08766c878a2594b15d203e513acf952340wwang		if (rsp[15] & 0x30) {
53277d89b08766c878a2594b15d203e513acf952340wwang			chip->card_wp |= SD_CARD;
53377d89b08766c878a2594b15d203e513acf952340wwang		}
53477d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]);
53577d89b08766c878a2594b15d203e513acf952340wwang	}
53677d89b08766c878a2594b15d203e513acf952340wwang
53777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
53877d89b08766c878a2594b15d203e513acf952340wwang}
53977d89b08766c878a2594b15d203e513acf952340wwang
54077d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_set_sample_push_timing(struct rtsx_chip *chip)
54177d89b08766c878a2594b15d203e513acf952340wwang{
54277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
54377d89b08766c878a2594b15d203e513acf952340wwang
54477d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
54577d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_SDR104(sd_card) || CHK_SD_SDR50(sd_card)) {
54677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
54777d89b08766c878a2594b15d203e513acf952340wwang					SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
54877d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
54977d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
55077d89b08766c878a2594b15d203e513acf952340wwang					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
55177d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
55277d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_SD_DDR50(sd_card) || CHK_MMC_DDR52(sd_card)) {
55377d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
55477d89b08766c878a2594b15d203e513acf952340wwang					SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
55577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
55677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
55777d89b08766c878a2594b15d203e513acf952340wwang					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
55877d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
55977d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, DDR_VAR_TX_CMD_DAT,
56077d89b08766c878a2594b15d203e513acf952340wwang					DDR_VAR_TX_CMD_DAT);
56177d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
56277d89b08766c878a2594b15d203e513acf952340wwang					DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
56377d89b08766c878a2594b15d203e513acf952340wwang		} else {
56477d89b08766c878a2594b15d203e513acf952340wwang			u8 val = 0;
56577d89b08766c878a2594b15d203e513acf952340wwang
56677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C, SD_20_MODE);
56777d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
56877d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
56977d89b08766c878a2594b15d203e513acf952340wwang					CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
57077d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
57177d89b08766c878a2594b15d203e513acf952340wwang
57277d89b08766c878a2594b15d203e513acf952340wwang			if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO) {
57377d89b08766c878a2594b15d203e513acf952340wwang				val = SD20_TX_NEG_EDGE;
57477d89b08766c878a2594b15d203e513acf952340wwang			} else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) {
57577d89b08766c878a2594b15d203e513acf952340wwang				val = SD20_TX_14_AHEAD;
57677d89b08766c878a2594b15d203e513acf952340wwang			} else {
57777d89b08766c878a2594b15d203e513acf952340wwang				val = SD20_TX_NEG_EDGE;
57877d89b08766c878a2594b15d203e513acf952340wwang			}
57977d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, SD20_TX_SEL_MASK, val);
58077d89b08766c878a2594b15d203e513acf952340wwang
58177d89b08766c878a2594b15d203e513acf952340wwang			if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
58277d89b08766c878a2594b15d203e513acf952340wwang				if (chip->asic_code) {
58377d89b08766c878a2594b15d203e513acf952340wwang					if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
58477d89b08766c878a2594b15d203e513acf952340wwang						val = SD20_RX_14_DELAY;
58577d89b08766c878a2594b15d203e513acf952340wwang					} else {
58677d89b08766c878a2594b15d203e513acf952340wwang						val = SD20_RX_POS_EDGE;
58777d89b08766c878a2594b15d203e513acf952340wwang					}
58877d89b08766c878a2594b15d203e513acf952340wwang				} else {
58977d89b08766c878a2594b15d203e513acf952340wwang					val = SD20_RX_14_DELAY;
59077d89b08766c878a2594b15d203e513acf952340wwang				}
59177d89b08766c878a2594b15d203e513acf952340wwang			} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
59277d89b08766c878a2594b15d203e513acf952340wwang				val = SD20_RX_14_DELAY;
59377d89b08766c878a2594b15d203e513acf952340wwang			} else {
59477d89b08766c878a2594b15d203e513acf952340wwang				val = SD20_RX_POS_EDGE;
59577d89b08766c878a2594b15d203e513acf952340wwang			}
59677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, SD20_RX_SEL_MASK, val);
59777d89b08766c878a2594b15d203e513acf952340wwang		}
59877d89b08766c878a2594b15d203e513acf952340wwang	} else {
59977d89b08766c878a2594b15d203e513acf952340wwang		u8 val = 0;
60077d89b08766c878a2594b15d203e513acf952340wwang
60177d89b08766c878a2594b15d203e513acf952340wwang		if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) {
60277d89b08766c878a2594b15d203e513acf952340wwang			val |= 0x10;
60377d89b08766c878a2594b15d203e513acf952340wwang		}
60477d89b08766c878a2594b15d203e513acf952340wwang
60577d89b08766c878a2594b15d203e513acf952340wwang		if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
60677d89b08766c878a2594b15d203e513acf952340wwang			if (chip->asic_code) {
60777d89b08766c878a2594b15d203e513acf952340wwang				if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
60877d89b08766c878a2594b15d203e513acf952340wwang					if (val & 0x10) {
60977d89b08766c878a2594b15d203e513acf952340wwang						val |= 0x04;
61077d89b08766c878a2594b15d203e513acf952340wwang					} else {
61177d89b08766c878a2594b15d203e513acf952340wwang						val |= 0x08;
61277d89b08766c878a2594b15d203e513acf952340wwang					}
61377d89b08766c878a2594b15d203e513acf952340wwang				}
61477d89b08766c878a2594b15d203e513acf952340wwang			} else {
61577d89b08766c878a2594b15d203e513acf952340wwang				if (val & 0x10) {
61677d89b08766c878a2594b15d203e513acf952340wwang					val |= 0x04;
61777d89b08766c878a2594b15d203e513acf952340wwang				} else {
61877d89b08766c878a2594b15d203e513acf952340wwang					val |= 0x08;
61977d89b08766c878a2594b15d203e513acf952340wwang				}
62077d89b08766c878a2594b15d203e513acf952340wwang			}
62177d89b08766c878a2594b15d203e513acf952340wwang		} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
62277d89b08766c878a2594b15d203e513acf952340wwang			if (val & 0x10) {
62377d89b08766c878a2594b15d203e513acf952340wwang				val |= 0x04;
62477d89b08766c878a2594b15d203e513acf952340wwang			} else {
62577d89b08766c878a2594b15d203e513acf952340wwang				val |= 0x08;
62677d89b08766c878a2594b15d203e513acf952340wwang			}
62777d89b08766c878a2594b15d203e513acf952340wwang		}
62877d89b08766c878a2594b15d203e513acf952340wwang
62977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val);
63077d89b08766c878a2594b15d203e513acf952340wwang	}
63177d89b08766c878a2594b15d203e513acf952340wwang
63277d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
63377d89b08766c878a2594b15d203e513acf952340wwang}
63477d89b08766c878a2594b15d203e513acf952340wwang
63577d89b08766c878a2594b15d203e513acf952340wwangstatic void sd_choose_proper_clock(struct rtsx_chip *chip)
63677d89b08766c878a2594b15d203e513acf952340wwang{
63777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
63877d89b08766c878a2594b15d203e513acf952340wwang
63977d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD_SDR104(sd_card)) {
64077d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
64177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->asic_sd_sdr104_clk;
64277d89b08766c878a2594b15d203e513acf952340wwang		} else {
64377d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
64477d89b08766c878a2594b15d203e513acf952340wwang		}
64577d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_SD_DDR50(sd_card)) {
64677d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
64777d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->asic_sd_ddr50_clk;
64877d89b08766c878a2594b15d203e513acf952340wwang		} else {
64977d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
65077d89b08766c878a2594b15d203e513acf952340wwang		}
65177d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_SD_SDR50(sd_card)) {
65277d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
65377d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->asic_sd_sdr50_clk;
65477d89b08766c878a2594b15d203e513acf952340wwang		} else {
65577d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
65677d89b08766c878a2594b15d203e513acf952340wwang		}
65777d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_SD_HS(sd_card)) {
65877d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
65977d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->asic_sd_hs_clk;
66077d89b08766c878a2594b15d203e513acf952340wwang		} else {
66177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->fpga_sd_hs_clk;
66277d89b08766c878a2594b15d203e513acf952340wwang		}
66377d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
66477d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
66577d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->asic_mmc_52m_clk;
66677d89b08766c878a2594b15d203e513acf952340wwang		} else {
66777d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = chip->fpga_mmc_52m_clk;
66877d89b08766c878a2594b15d203e513acf952340wwang		}
66977d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_MMC_26M(sd_card)) {
67077d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
67177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = 48;
67277d89b08766c878a2594b15d203e513acf952340wwang		} else {
67377d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_50;
67477d89b08766c878a2594b15d203e513acf952340wwang		}
67577d89b08766c878a2594b15d203e513acf952340wwang	}
67677d89b08766c878a2594b15d203e513acf952340wwang}
67777d89b08766c878a2594b15d203e513acf952340wwang
67877d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
67977d89b08766c878a2594b15d203e513acf952340wwang{
68077d89b08766c878a2594b15d203e513acf952340wwang	u8 mask = 0, val = 0;
68177d89b08766c878a2594b15d203e513acf952340wwang
68277d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
68377d89b08766c878a2594b15d203e513acf952340wwang		mask = SD_CLK_DIVIDE_MASK;
68477d89b08766c878a2594b15d203e513acf952340wwang		val = clk_div;
68577d89b08766c878a2594b15d203e513acf952340wwang	} else {
68677d89b08766c878a2594b15d203e513acf952340wwang		mask = 0x60;
68777d89b08766c878a2594b15d203e513acf952340wwang		if (clk_div == SD_CLK_DIVIDE_0) {
68877d89b08766c878a2594b15d203e513acf952340wwang			val = 0x00;
68977d89b08766c878a2594b15d203e513acf952340wwang		} else if (clk_div == SD_CLK_DIVIDE_128) {
69077d89b08766c878a2594b15d203e513acf952340wwang			val = 0x40;
69177d89b08766c878a2594b15d203e513acf952340wwang		} else if (clk_div == SD_CLK_DIVIDE_256) {
69277d89b08766c878a2594b15d203e513acf952340wwang			val = 0x20;
69377d89b08766c878a2594b15d203e513acf952340wwang		}
69477d89b08766c878a2594b15d203e513acf952340wwang	}
69577d89b08766c878a2594b15d203e513acf952340wwang
69677d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val);
69777d89b08766c878a2594b15d203e513acf952340wwang
69877d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
69977d89b08766c878a2594b15d203e513acf952340wwang}
70077d89b08766c878a2594b15d203e513acf952340wwang
70177d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_set_init_para(struct rtsx_chip *chip)
70277d89b08766c878a2594b15d203e513acf952340wwang{
70377d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
70477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
70577d89b08766c878a2594b15d203e513acf952340wwang
70677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_sample_push_timing(chip);
70777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
70877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
70977d89b08766c878a2594b15d203e513acf952340wwang	}
71077d89b08766c878a2594b15d203e513acf952340wwang
71177d89b08766c878a2594b15d203e513acf952340wwang	sd_choose_proper_clock(chip);
71277d89b08766c878a2594b15d203e513acf952340wwang
71377d89b08766c878a2594b15d203e513acf952340wwang	retval = switch_clock(chip, sd_card->sd_clock);
71477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
71577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
71677d89b08766c878a2594b15d203e513acf952340wwang	}
71777d89b08766c878a2594b15d203e513acf952340wwang
71877d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
71977d89b08766c878a2594b15d203e513acf952340wwang}
72077d89b08766c878a2594b15d203e513acf952340wwang
72177d89b08766c878a2594b15d203e513acf952340wwangint sd_select_card(struct rtsx_chip *chip, int select)
72277d89b08766c878a2594b15d203e513acf952340wwang{
72377d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
72477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
72577d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd_idx, cmd_type;
72677d89b08766c878a2594b15d203e513acf952340wwang	u32 addr;
72777d89b08766c878a2594b15d203e513acf952340wwang
72877d89b08766c878a2594b15d203e513acf952340wwang	if (select) {
72977d89b08766c878a2594b15d203e513acf952340wwang		cmd_idx = SELECT_CARD;
73077d89b08766c878a2594b15d203e513acf952340wwang		cmd_type = SD_RSP_TYPE_R1;
73177d89b08766c878a2594b15d203e513acf952340wwang		addr = sd_card->sd_addr;
73277d89b08766c878a2594b15d203e513acf952340wwang	} else {
73377d89b08766c878a2594b15d203e513acf952340wwang		cmd_idx = DESELECT_CARD;
73477d89b08766c878a2594b15d203e513acf952340wwang		cmd_type = SD_RSP_TYPE_R0;
73577d89b08766c878a2594b15d203e513acf952340wwang		addr = 0;
73677d89b08766c878a2594b15d203e513acf952340wwang	}
73777d89b08766c878a2594b15d203e513acf952340wwang
73877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
73977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
74077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
74177d89b08766c878a2594b15d203e513acf952340wwang	}
74277d89b08766c878a2594b15d203e513acf952340wwang
74377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
74477d89b08766c878a2594b15d203e513acf952340wwang}
74577d89b08766c878a2594b15d203e513acf952340wwang
74677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
74777d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_update_lock_status(struct rtsx_chip *chip)
74877d89b08766c878a2594b15d203e513acf952340wwang{
74977d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
75077d89b08766c878a2594b15d203e513acf952340wwang	int retval;
75177d89b08766c878a2594b15d203e513acf952340wwang	u8 rsp[5];
75277d89b08766c878a2594b15d203e513acf952340wwang
75377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
75477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
75577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
75677d89b08766c878a2594b15d203e513acf952340wwang	}
75777d89b08766c878a2594b15d203e513acf952340wwang
75877d89b08766c878a2594b15d203e513acf952340wwang	if (rsp[1] & 0x02) {
75977d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status |= SD_LOCKED;
76077d89b08766c878a2594b15d203e513acf952340wwang	} else {
76177d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status &= ~SD_LOCKED;
76277d89b08766c878a2594b15d203e513acf952340wwang	}
76377d89b08766c878a2594b15d203e513acf952340wwang
76477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", sd_card->sd_lock_status);
76577d89b08766c878a2594b15d203e513acf952340wwang
76677d89b08766c878a2594b15d203e513acf952340wwang	if (rsp[1] & 0x01) {
76777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
76877d89b08766c878a2594b15d203e513acf952340wwang	}
76977d89b08766c878a2594b15d203e513acf952340wwang
77077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
77177d89b08766c878a2594b15d203e513acf952340wwang}
77277d89b08766c878a2594b15d203e513acf952340wwang#endif
77377d89b08766c878a2594b15d203e513acf952340wwang
77477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_ready, int polling_cnt)
77577d89b08766c878a2594b15d203e513acf952340wwang{
77677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
77777d89b08766c878a2594b15d203e513acf952340wwang	int retval, i;
77877d89b08766c878a2594b15d203e513acf952340wwang	u8 rsp[5];
77977d89b08766c878a2594b15d203e513acf952340wwang
78077d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < polling_cnt; i++) {
78177d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
78277d89b08766c878a2594b15d203e513acf952340wwang					     sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
78377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
78477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
78577d89b08766c878a2594b15d203e513acf952340wwang		}
78677d89b08766c878a2594b15d203e513acf952340wwang
78777d89b08766c878a2594b15d203e513acf952340wwang		if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready)) {
78877d89b08766c878a2594b15d203e513acf952340wwang			return STATUS_SUCCESS;
78977d89b08766c878a2594b15d203e513acf952340wwang		}
79077d89b08766c878a2594b15d203e513acf952340wwang	}
79177d89b08766c878a2594b15d203e513acf952340wwang
79277d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, STATUS_FAIL);
79377d89b08766c878a2594b15d203e513acf952340wwang}
79477d89b08766c878a2594b15d203e513acf952340wwang
79577d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
79677d89b08766c878a2594b15d203e513acf952340wwang{
79777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
79877d89b08766c878a2594b15d203e513acf952340wwang
79977d89b08766c878a2594b15d203e513acf952340wwang	if (voltage == SD_IO_3V3) {
80077d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
80177d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_phy_register(chip, 0x08, 0x4FC0 | chip->phy_voltage);
80277d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
80377d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
80477d89b08766c878a2594b15d203e513acf952340wwang			}
80577d89b08766c878a2594b15d203e513acf952340wwang		} else {
80677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0);
80777d89b08766c878a2594b15d203e513acf952340wwang		}
80877d89b08766c878a2594b15d203e513acf952340wwang	} else if (voltage == SD_IO_1V8) {
80977d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
81077d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_phy_register(chip, 0x08, 0x4C40 | chip->phy_voltage);
81177d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
81277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
81377d89b08766c878a2594b15d203e513acf952340wwang			}
81477d89b08766c878a2594b15d203e513acf952340wwang		} else {
81577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8);
81677d89b08766c878a2594b15d203e513acf952340wwang		}
81777d89b08766c878a2594b15d203e513acf952340wwang	} else {
81877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
81977d89b08766c878a2594b15d203e513acf952340wwang	}
82077d89b08766c878a2594b15d203e513acf952340wwang
82177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
82277d89b08766c878a2594b15d203e513acf952340wwang}
82377d89b08766c878a2594b15d203e513acf952340wwang
82477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_voltage_switch(struct rtsx_chip *chip)
82577d89b08766c878a2594b15d203e513acf952340wwang{
82677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
82777d89b08766c878a2594b15d203e513acf952340wwang	u8 stat;
82877d89b08766c878a2594b15d203e513acf952340wwang
82977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, SD_CLK_TOGGLE_EN);
83077d89b08766c878a2594b15d203e513acf952340wwang
83177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, 0);
83277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
83377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
83477d89b08766c878a2594b15d203e513acf952340wwang	}
83577d89b08766c878a2594b15d203e513acf952340wwang
83677d89b08766c878a2594b15d203e513acf952340wwang	udelay(chip->sd_voltage_switch_delay);
83777d89b08766c878a2594b15d203e513acf952340wwang
83877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
83977d89b08766c878a2594b15d203e513acf952340wwang	if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
84077d89b08766c878a2594b15d203e513acf952340wwang				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
84177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
84277d89b08766c878a2594b15d203e513acf952340wwang	}
84377d89b08766c878a2594b15d203e513acf952340wwang
84477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP);
84577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_bank_voltage(chip, SD_IO_1V8);
84677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
84777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
84877d89b08766c878a2594b15d203e513acf952340wwang	}
84977d89b08766c878a2594b15d203e513acf952340wwang	wait_timeout(50);
85077d89b08766c878a2594b15d203e513acf952340wwang
85177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
85277d89b08766c878a2594b15d203e513acf952340wwang	wait_timeout(10);
85377d89b08766c878a2594b15d203e513acf952340wwang
85477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
85577d89b08766c878a2594b15d203e513acf952340wwang	if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
85677d89b08766c878a2594b15d203e513acf952340wwang				SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
85777d89b08766c878a2594b15d203e513acf952340wwang			(SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
85877d89b08766c878a2594b15d203e513acf952340wwang				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
85977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", stat);
86077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
86177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
86277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
86377d89b08766c878a2594b15d203e513acf952340wwang	}
86477d89b08766c878a2594b15d203e513acf952340wwang
86577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
86677d89b08766c878a2594b15d203e513acf952340wwang
86777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
86877d89b08766c878a2594b15d203e513acf952340wwang}
86977d89b08766c878a2594b15d203e513acf952340wwang
87077d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
87177d89b08766c878a2594b15d203e513acf952340wwang{
87277d89b08766c878a2594b15d203e513acf952340wwang	if (tune_dir == TUNE_RX) {
87377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX);
87477d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
87577d89b08766c878a2594b15d203e513acf952340wwang	} else {
87677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX);
87777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
87877d89b08766c878a2594b15d203e513acf952340wwang	}
87977d89b08766c878a2594b15d203e513acf952340wwang
88077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
88177d89b08766c878a2594b15d203e513acf952340wwang}
88277d89b08766c878a2594b15d203e513acf952340wwang
88377d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
88477d89b08766c878a2594b15d203e513acf952340wwang{
88577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
88677d89b08766c878a2594b15d203e513acf952340wwang	u16 SD_VP_CTL, SD_DCMPS_CTL;
88777d89b08766c878a2594b15d203e513acf952340wwang	u8 val;
88877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
88977d89b08766c878a2594b15d203e513acf952340wwang	int ddr_rx = 0;
89077d89b08766c878a2594b15d203e513acf952340wwang
89177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n",
89277d89b08766c878a2594b15d203e513acf952340wwang				sample_point, tune_dir);
89377d89b08766c878a2594b15d203e513acf952340wwang
89477d89b08766c878a2594b15d203e513acf952340wwang	if (tune_dir == TUNE_RX) {
89577d89b08766c878a2594b15d203e513acf952340wwang		SD_VP_CTL = SD_VPRX_CTL;
89677d89b08766c878a2594b15d203e513acf952340wwang		SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
89777d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_DDR50(sd_card)) {
89877d89b08766c878a2594b15d203e513acf952340wwang			ddr_rx = 1;
89977d89b08766c878a2594b15d203e513acf952340wwang		}
90077d89b08766c878a2594b15d203e513acf952340wwang	} else {
90177d89b08766c878a2594b15d203e513acf952340wwang		SD_VP_CTL = SD_VPTX_CTL;
90277d89b08766c878a2594b15d203e513acf952340wwang		SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
90377d89b08766c878a2594b15d203e513acf952340wwang	}
90477d89b08766c878a2594b15d203e513acf952340wwang
90577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
90677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
90777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point);
90877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
90977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
91077d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
91177d89b08766c878a2594b15d203e513acf952340wwang	} else {
9121035117d2a47583f9539c28bf6ce5f677946e172Jeff Mahoney#ifdef CONFIG_RTS_PSTOR_DEBUG
91377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_read_register(chip, SD_VP_CTL, &val);
91477d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
91577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_read_register(chip, SD_DCMPS_CTL, &val);
91677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
91777d89b08766c878a2594b15d203e513acf952340wwang#endif
91877d89b08766c878a2594b15d203e513acf952340wwang
91977d89b08766c878a2594b15d203e513acf952340wwang		if (ddr_rx) {
92077d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, PHASE_CHANGE);
92177d89b08766c878a2594b15d203e513acf952340wwang			udelay(50);
92277d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
92377d89b08766c878a2594b15d203e513acf952340wwang					PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
92477d89b08766c878a2594b15d203e513acf952340wwang		} else {
92577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
92677d89b08766c878a2594b15d203e513acf952340wwang			udelay(50);
92777d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
92877d89b08766c878a2594b15d203e513acf952340wwang					PHASE_NOT_RESET | sample_point);
92977d89b08766c878a2594b15d203e513acf952340wwang		}
93077d89b08766c878a2594b15d203e513acf952340wwang		udelay(100);
93177d89b08766c878a2594b15d203e513acf952340wwang
93277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
93377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, DCMPS_CHANGE);
93477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
93577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_send_cmd(chip, SD_CARD, 100);
93677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
93777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, Fail);
93877d89b08766c878a2594b15d203e513acf952340wwang		}
93977d89b08766c878a2594b15d203e513acf952340wwang
94077d89b08766c878a2594b15d203e513acf952340wwang		val = *rtsx_get_cmd_data(chip);
94177d89b08766c878a2594b15d203e513acf952340wwang		if (val & DCMPS_ERROR) {
94277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, Fail);
94377d89b08766c878a2594b15d203e513acf952340wwang		}
94477d89b08766c878a2594b15d203e513acf952340wwang		if ((val & DCMPS_CURRENT_PHASE) != sample_point) {
94577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, Fail);
94677d89b08766c878a2594b15d203e513acf952340wwang		}
94777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
94877d89b08766c878a2594b15d203e513acf952340wwang		if (ddr_rx) {
94977d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0);
95077d89b08766c878a2594b15d203e513acf952340wwang		} else {
95177d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
95277d89b08766c878a2594b15d203e513acf952340wwang		}
95377d89b08766c878a2594b15d203e513acf952340wwang		udelay(50);
95477d89b08766c878a2594b15d203e513acf952340wwang	}
95577d89b08766c878a2594b15d203e513acf952340wwang
95677d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
95777d89b08766c878a2594b15d203e513acf952340wwang
95877d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
95977d89b08766c878a2594b15d203e513acf952340wwang
96077d89b08766c878a2594b15d203e513acf952340wwangFail:
9611035117d2a47583f9539c28bf6ce5f677946e172Jeff Mahoney#ifdef CONFIG_RTS_PSTOR_DEBUG
96277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_read_register(chip, SD_VP_CTL, &val);
96377d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
96477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_read_register(chip, SD_DCMPS_CTL, &val);
96577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
96677d89b08766c878a2594b15d203e513acf952340wwang#endif
96777d89b08766c878a2594b15d203e513acf952340wwang
96877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
96977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
97077d89b08766c878a2594b15d203e513acf952340wwang	wait_timeout(10);
97177d89b08766c878a2594b15d203e513acf952340wwang	sd_reset_dcm(chip, tune_dir);
97277d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_FAIL;
97377d89b08766c878a2594b15d203e513acf952340wwang}
97477d89b08766c878a2594b15d203e513acf952340wwang
97577d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
97677d89b08766c878a2594b15d203e513acf952340wwang{
97777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
97877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
97977d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], buf[8];
98077d89b08766c878a2594b15d203e513acf952340wwang
98177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
98277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
98377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
98477d89b08766c878a2594b15d203e513acf952340wwang	}
98577d89b08766c878a2594b15d203e513acf952340wwang
98677d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SEND_SCR;
98777d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
98877d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
98977d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
99077d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
99177d89b08766c878a2594b15d203e513acf952340wwang
99277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, buf, 8, 250);
99377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
99477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
99577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
99677d89b08766c878a2594b15d203e513acf952340wwang	}
99777d89b08766c878a2594b15d203e513acf952340wwang
99877d89b08766c878a2594b15d203e513acf952340wwang	memcpy(sd_card->raw_scr, buf, 8);
99977d89b08766c878a2594b15d203e513acf952340wwang
100077d89b08766c878a2594b15d203e513acf952340wwang	if ((buf[0] & 0x0F) == 0) {
100177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
100277d89b08766c878a2594b15d203e513acf952340wwang	}
100377d89b08766c878a2594b15d203e513acf952340wwang
100477d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
100577d89b08766c878a2594b15d203e513acf952340wwang}
100677d89b08766c878a2594b15d203e513acf952340wwang
100777d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, u8 func_to_switch,
100877d89b08766c878a2594b15d203e513acf952340wwang		u8 *buf, int buf_len)
100977d89b08766c878a2594b15d203e513acf952340wwang{
101077d89b08766c878a2594b15d203e513acf952340wwang	u8 support_mask = 0, query_switch = 0, switch_busy = 0;
101177d89b08766c878a2594b15d203e513acf952340wwang	int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
101277d89b08766c878a2594b15d203e513acf952340wwang
101377d89b08766c878a2594b15d203e513acf952340wwang	if (func_group == SD_FUNC_GROUP_1) {
101477d89b08766c878a2594b15d203e513acf952340wwang		support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
101577d89b08766c878a2594b15d203e513acf952340wwang		query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
101677d89b08766c878a2594b15d203e513acf952340wwang		check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
101777d89b08766c878a2594b15d203e513acf952340wwang
101877d89b08766c878a2594b15d203e513acf952340wwang		switch (func_to_switch) {
101977d89b08766c878a2594b15d203e513acf952340wwang		case HS_SUPPORT:
102077d89b08766c878a2594b15d203e513acf952340wwang			support_mask = HS_SUPPORT_MASK;
102177d89b08766c878a2594b15d203e513acf952340wwang			query_switch = HS_QUERY_SWITCH_OK;
102277d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = HS_SWITCH_BUSY;
102377d89b08766c878a2594b15d203e513acf952340wwang			break;
102477d89b08766c878a2594b15d203e513acf952340wwang
102577d89b08766c878a2594b15d203e513acf952340wwang		case SDR50_SUPPORT:
102677d89b08766c878a2594b15d203e513acf952340wwang			support_mask = SDR50_SUPPORT_MASK;
102777d89b08766c878a2594b15d203e513acf952340wwang			query_switch = SDR50_QUERY_SWITCH_OK;
102877d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = SDR50_SWITCH_BUSY;
102977d89b08766c878a2594b15d203e513acf952340wwang			break;
103077d89b08766c878a2594b15d203e513acf952340wwang
103177d89b08766c878a2594b15d203e513acf952340wwang		case SDR104_SUPPORT:
103277d89b08766c878a2594b15d203e513acf952340wwang			support_mask = SDR104_SUPPORT_MASK;
103377d89b08766c878a2594b15d203e513acf952340wwang			query_switch = SDR104_QUERY_SWITCH_OK;
103477d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = SDR104_SWITCH_BUSY;
103577d89b08766c878a2594b15d203e513acf952340wwang			break;
103677d89b08766c878a2594b15d203e513acf952340wwang
103777d89b08766c878a2594b15d203e513acf952340wwang		case DDR50_SUPPORT:
103877d89b08766c878a2594b15d203e513acf952340wwang			support_mask = DDR50_SUPPORT_MASK;
103977d89b08766c878a2594b15d203e513acf952340wwang			query_switch = DDR50_QUERY_SWITCH_OK;
104077d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = DDR50_SWITCH_BUSY;
104177d89b08766c878a2594b15d203e513acf952340wwang			break;
104277d89b08766c878a2594b15d203e513acf952340wwang
104377d89b08766c878a2594b15d203e513acf952340wwang		default:
104477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
104577d89b08766c878a2594b15d203e513acf952340wwang		}
104677d89b08766c878a2594b15d203e513acf952340wwang	} else if (func_group == SD_FUNC_GROUP_3) {
104777d89b08766c878a2594b15d203e513acf952340wwang		support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
104877d89b08766c878a2594b15d203e513acf952340wwang		query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
104977d89b08766c878a2594b15d203e513acf952340wwang		check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
105077d89b08766c878a2594b15d203e513acf952340wwang
105177d89b08766c878a2594b15d203e513acf952340wwang		switch (func_to_switch) {
105277d89b08766c878a2594b15d203e513acf952340wwang		case DRIVING_TYPE_A:
105377d89b08766c878a2594b15d203e513acf952340wwang			support_mask = DRIVING_TYPE_A_MASK;
105477d89b08766c878a2594b15d203e513acf952340wwang			query_switch = TYPE_A_QUERY_SWITCH_OK;
105577d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = TYPE_A_SWITCH_BUSY;
105677d89b08766c878a2594b15d203e513acf952340wwang			break;
105777d89b08766c878a2594b15d203e513acf952340wwang
105877d89b08766c878a2594b15d203e513acf952340wwang		case DRIVING_TYPE_C:
105977d89b08766c878a2594b15d203e513acf952340wwang			support_mask = DRIVING_TYPE_C_MASK;
106077d89b08766c878a2594b15d203e513acf952340wwang			query_switch = TYPE_C_QUERY_SWITCH_OK;
106177d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = TYPE_C_SWITCH_BUSY;
106277d89b08766c878a2594b15d203e513acf952340wwang			break;
106377d89b08766c878a2594b15d203e513acf952340wwang
106477d89b08766c878a2594b15d203e513acf952340wwang		case DRIVING_TYPE_D:
106577d89b08766c878a2594b15d203e513acf952340wwang			support_mask = DRIVING_TYPE_D_MASK;
106677d89b08766c878a2594b15d203e513acf952340wwang			query_switch = TYPE_D_QUERY_SWITCH_OK;
106777d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = TYPE_D_SWITCH_BUSY;
106877d89b08766c878a2594b15d203e513acf952340wwang			break;
106977d89b08766c878a2594b15d203e513acf952340wwang
107077d89b08766c878a2594b15d203e513acf952340wwang		default:
107177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
107277d89b08766c878a2594b15d203e513acf952340wwang		}
107377d89b08766c878a2594b15d203e513acf952340wwang	} else if (func_group == SD_FUNC_GROUP_4) {
107477d89b08766c878a2594b15d203e513acf952340wwang		support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
107577d89b08766c878a2594b15d203e513acf952340wwang		query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
107677d89b08766c878a2594b15d203e513acf952340wwang		check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
107777d89b08766c878a2594b15d203e513acf952340wwang
107877d89b08766c878a2594b15d203e513acf952340wwang		switch (func_to_switch) {
107977d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_400:
108077d89b08766c878a2594b15d203e513acf952340wwang			support_mask = CURRENT_LIMIT_400_MASK;
108177d89b08766c878a2594b15d203e513acf952340wwang			query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
108277d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
108377d89b08766c878a2594b15d203e513acf952340wwang			break;
108477d89b08766c878a2594b15d203e513acf952340wwang
108577d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_600:
108677d89b08766c878a2594b15d203e513acf952340wwang			support_mask = CURRENT_LIMIT_600_MASK;
108777d89b08766c878a2594b15d203e513acf952340wwang			query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
108877d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
108977d89b08766c878a2594b15d203e513acf952340wwang			break;
109077d89b08766c878a2594b15d203e513acf952340wwang
109177d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_800:
109277d89b08766c878a2594b15d203e513acf952340wwang			support_mask = CURRENT_LIMIT_800_MASK;
109377d89b08766c878a2594b15d203e513acf952340wwang			query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
109477d89b08766c878a2594b15d203e513acf952340wwang			switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
109577d89b08766c878a2594b15d203e513acf952340wwang			break;
109677d89b08766c878a2594b15d203e513acf952340wwang
109777d89b08766c878a2594b15d203e513acf952340wwang		default:
109877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
109977d89b08766c878a2594b15d203e513acf952340wwang		}
110077d89b08766c878a2594b15d203e513acf952340wwang	} else {
110177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
110277d89b08766c878a2594b15d203e513acf952340wwang	}
110377d89b08766c878a2594b15d203e513acf952340wwang
110477d89b08766c878a2594b15d203e513acf952340wwang	if (func_group == SD_FUNC_GROUP_1) {
110577d89b08766c878a2594b15d203e513acf952340wwang		if (!(buf[support_offset] & support_mask) ||
110677d89b08766c878a2594b15d203e513acf952340wwang				((buf[query_switch_offset] & 0x0F) != query_switch)) {
110777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
110877d89b08766c878a2594b15d203e513acf952340wwang		}
110977d89b08766c878a2594b15d203e513acf952340wwang	}
111077d89b08766c878a2594b15d203e513acf952340wwang
111177d89b08766c878a2594b15d203e513acf952340wwang	/* Check 'Busy Status' */
111277d89b08766c878a2594b15d203e513acf952340wwang	if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) &&
111377d89b08766c878a2594b15d203e513acf952340wwang		    ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
111477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
111577d89b08766c878a2594b15d203e513acf952340wwang	}
111677d89b08766c878a2594b15d203e513acf952340wwang
111777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
111877d89b08766c878a2594b15d203e513acf952340wwang}
111977d89b08766c878a2594b15d203e513acf952340wwang
112077d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
112177d89b08766c878a2594b15d203e513acf952340wwang		u8 func_group, u8 func_to_switch, u8 bus_width)
112277d89b08766c878a2594b15d203e513acf952340wwang{
112377d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
112477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
112577d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], buf[64];
112677d89b08766c878a2594b15d203e513acf952340wwang
112777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n",
112877d89b08766c878a2594b15d203e513acf952340wwang			mode, func_group, func_to_switch);
112977d89b08766c878a2594b15d203e513acf952340wwang
113077d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SWITCH;
113177d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = mode;
113277d89b08766c878a2594b15d203e513acf952340wwang
113377d89b08766c878a2594b15d203e513acf952340wwang	if (func_group == SD_FUNC_GROUP_1) {
113477d89b08766c878a2594b15d203e513acf952340wwang		cmd[2] = 0xFF;
113577d89b08766c878a2594b15d203e513acf952340wwang		cmd[3] = 0xFF;
113677d89b08766c878a2594b15d203e513acf952340wwang		cmd[4] = 0xF0 + func_to_switch;
113777d89b08766c878a2594b15d203e513acf952340wwang	} else if (func_group == SD_FUNC_GROUP_3) {
113877d89b08766c878a2594b15d203e513acf952340wwang		cmd[2] = 0xFF;
113977d89b08766c878a2594b15d203e513acf952340wwang		cmd[3] = 0xF0 + func_to_switch;
114077d89b08766c878a2594b15d203e513acf952340wwang		cmd[4] = 0xFF;
114177d89b08766c878a2594b15d203e513acf952340wwang	} else if (func_group == SD_FUNC_GROUP_4) {
114277d89b08766c878a2594b15d203e513acf952340wwang		cmd[2] = 0xFF;
114377d89b08766c878a2594b15d203e513acf952340wwang		cmd[3] = 0x0F + (func_to_switch << 4);
114477d89b08766c878a2594b15d203e513acf952340wwang		cmd[4] = 0xFF;
114577d89b08766c878a2594b15d203e513acf952340wwang	} else {
114677d89b08766c878a2594b15d203e513acf952340wwang		cmd[1] = SD_CHECK_MODE;
114777d89b08766c878a2594b15d203e513acf952340wwang		cmd[2] = 0xFF;
114877d89b08766c878a2594b15d203e513acf952340wwang		cmd[3] = 0xFF;
114977d89b08766c878a2594b15d203e513acf952340wwang		cmd[4] = 0xFF;
115077d89b08766c878a2594b15d203e513acf952340wwang	}
115177d89b08766c878a2594b15d203e513acf952340wwang
115277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, buf, 64, 250);
115377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
115477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
115577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
115677d89b08766c878a2594b15d203e513acf952340wwang	}
115777d89b08766c878a2594b15d203e513acf952340wwang
115877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DUMP(buf, 64);
115977d89b08766c878a2594b15d203e513acf952340wwang
116077d89b08766c878a2594b15d203e513acf952340wwang	if (func_group == NO_ARGUMENT) {
116177d89b08766c878a2594b15d203e513acf952340wwang		sd_card->func_group1_mask = buf[0x0D];
116277d89b08766c878a2594b15d203e513acf952340wwang		sd_card->func_group2_mask = buf[0x0B];
116377d89b08766c878a2594b15d203e513acf952340wwang		sd_card->func_group3_mask = buf[0x09];
116477d89b08766c878a2594b15d203e513acf952340wwang		sd_card->func_group4_mask = buf[0x07];
116577d89b08766c878a2594b15d203e513acf952340wwang
116677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]);
116777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]);
116877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]);
116977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]);
117077d89b08766c878a2594b15d203e513acf952340wwang	} else {
117177d89b08766c878a2594b15d203e513acf952340wwang		/* Maximum current consumption, check whether current is acceptable;
117277d89b08766c878a2594b15d203e513acf952340wwang		 * bit[511:496] = 0x0000 means some error happaned.
117377d89b08766c878a2594b15d203e513acf952340wwang		 */
117477d89b08766c878a2594b15d203e513acf952340wwang		u16 cc = ((u16)buf[0] << 8) | buf[1];
117577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc);
117677d89b08766c878a2594b15d203e513acf952340wwang		if ((cc == 0) || (cc > 800)) {
117777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
117877d89b08766c878a2594b15d203e513acf952340wwang		}
117977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_query_switch_result(chip, func_group, func_to_switch, buf, 64);
118077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
118177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
118277d89b08766c878a2594b15d203e513acf952340wwang		}
118377d89b08766c878a2594b15d203e513acf952340wwang
118477d89b08766c878a2594b15d203e513acf952340wwang		if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) {
118577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_800mA_ocp_thd);
118677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK, PMOS_STRG_800mA);
118777d89b08766c878a2594b15d203e513acf952340wwang		}
118877d89b08766c878a2594b15d203e513acf952340wwang	}
118977d89b08766c878a2594b15d203e513acf952340wwang
119077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
119177d89b08766c878a2594b15d203e513acf952340wwang}
119277d89b08766c878a2594b15d203e513acf952340wwang
119377d89b08766c878a2594b15d203e513acf952340wwangstatic u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
119477d89b08766c878a2594b15d203e513acf952340wwang{
119577d89b08766c878a2594b15d203e513acf952340wwang	if (func_group == SD_FUNC_GROUP_1) {
119677d89b08766c878a2594b15d203e513acf952340wwang		if (func_to_switch > HS_SUPPORT) {
119777d89b08766c878a2594b15d203e513acf952340wwang			func_to_switch--;
119877d89b08766c878a2594b15d203e513acf952340wwang		}
119977d89b08766c878a2594b15d203e513acf952340wwang	} else if (func_group == SD_FUNC_GROUP_4) {
120077d89b08766c878a2594b15d203e513acf952340wwang		if (func_to_switch > CURRENT_LIMIT_200) {
120177d89b08766c878a2594b15d203e513acf952340wwang			func_to_switch--;
120277d89b08766c878a2594b15d203e513acf952340wwang		}
120377d89b08766c878a2594b15d203e513acf952340wwang	}
120477d89b08766c878a2594b15d203e513acf952340wwang
120577d89b08766c878a2594b15d203e513acf952340wwang	return func_to_switch;
120677d89b08766c878a2594b15d203e513acf952340wwang}
120777d89b08766c878a2594b15d203e513acf952340wwang
120877d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_switch(struct rtsx_chip *chip,
120977d89b08766c878a2594b15d203e513acf952340wwang		u8 func_group, u8 func_to_switch, u8 bus_width)
121077d89b08766c878a2594b15d203e513acf952340wwang{
121177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
121277d89b08766c878a2594b15d203e513acf952340wwang	int i;
121377d89b08766c878a2594b15d203e513acf952340wwang	int switch_good = 0;
121477d89b08766c878a2594b15d203e513acf952340wwang
121577d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
121677d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
121777d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_NO_CARD);
121877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
121977d89b08766c878a2594b15d203e513acf952340wwang		}
122077d89b08766c878a2594b15d203e513acf952340wwang
122177d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
122277d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch, bus_width);
122377d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS) {
122477d89b08766c878a2594b15d203e513acf952340wwang			u8 stat;
122577d89b08766c878a2594b15d203e513acf952340wwang
122677d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
122777d89b08766c878a2594b15d203e513acf952340wwang					func_group, func_to_switch, bus_width);
122877d89b08766c878a2594b15d203e513acf952340wwang			if (retval == STATUS_SUCCESS) {
122977d89b08766c878a2594b15d203e513acf952340wwang				switch_good = 1;
123077d89b08766c878a2594b15d203e513acf952340wwang				break;
123177d89b08766c878a2594b15d203e513acf952340wwang			}
123277d89b08766c878a2594b15d203e513acf952340wwang
123377d89b08766c878a2594b15d203e513acf952340wwang			RTSX_READ_REG(chip, SD_STAT1, &stat);
123477d89b08766c878a2594b15d203e513acf952340wwang			if (stat & SD_CRC16_ERR) {
123577d89b08766c878a2594b15d203e513acf952340wwang				RTSX_DEBUGP("SD CRC16 error when switching mode\n");
123677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
123777d89b08766c878a2594b15d203e513acf952340wwang			}
123877d89b08766c878a2594b15d203e513acf952340wwang		}
123977d89b08766c878a2594b15d203e513acf952340wwang
124077d89b08766c878a2594b15d203e513acf952340wwang		func_to_switch = downgrade_switch_mode(func_group, func_to_switch);
124177d89b08766c878a2594b15d203e513acf952340wwang
124277d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(20);
124377d89b08766c878a2594b15d203e513acf952340wwang	}
124477d89b08766c878a2594b15d203e513acf952340wwang
124577d89b08766c878a2594b15d203e513acf952340wwang	if (!switch_good) {
124677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
124777d89b08766c878a2594b15d203e513acf952340wwang	}
124877d89b08766c878a2594b15d203e513acf952340wwang
124977d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
125077d89b08766c878a2594b15d203e513acf952340wwang}
125177d89b08766c878a2594b15d203e513acf952340wwang
125277d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
125377d89b08766c878a2594b15d203e513acf952340wwang{
125477d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
125577d89b08766c878a2594b15d203e513acf952340wwang	int retval;
125677d89b08766c878a2594b15d203e513acf952340wwang	int i;
125777d89b08766c878a2594b15d203e513acf952340wwang	u8 func_to_switch = 0;
125877d89b08766c878a2594b15d203e513acf952340wwang
125977d89b08766c878a2594b15d203e513acf952340wwang	/* Get supported functions */
126077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_check_switch_mode(chip, SD_CHECK_MODE,
126177d89b08766c878a2594b15d203e513acf952340wwang			NO_ARGUMENT, NO_ARGUMENT, bus_width);
126277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
126377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
126477d89b08766c878a2594b15d203e513acf952340wwang	}
126577d89b08766c878a2594b15d203e513acf952340wwang
126677d89b08766c878a2594b15d203e513acf952340wwang	sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
126777d89b08766c878a2594b15d203e513acf952340wwang
12682d2322b269c2524996a259024f82c7e318719696wwang	/* Function Group 1: Access Mode */
126977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 4; i++) {
127077d89b08766c878a2594b15d203e513acf952340wwang		switch ((u8)(chip->sd_speed_prior >> (i*8))) {
127177d89b08766c878a2594b15d203e513acf952340wwang		case SDR104_SUPPORT:
127277d89b08766c878a2594b15d203e513acf952340wwang			if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK)
127377d89b08766c878a2594b15d203e513acf952340wwang					&& chip->sdr104_en) {
127477d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = SDR104_SUPPORT;
127577d89b08766c878a2594b15d203e513acf952340wwang			}
127677d89b08766c878a2594b15d203e513acf952340wwang			break;
127777d89b08766c878a2594b15d203e513acf952340wwang
127877d89b08766c878a2594b15d203e513acf952340wwang		case DDR50_SUPPORT:
127977d89b08766c878a2594b15d203e513acf952340wwang			if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK)
128077d89b08766c878a2594b15d203e513acf952340wwang					&& chip->ddr50_en) {
128177d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = DDR50_SUPPORT;
128277d89b08766c878a2594b15d203e513acf952340wwang			}
128377d89b08766c878a2594b15d203e513acf952340wwang			break;
128477d89b08766c878a2594b15d203e513acf952340wwang
128577d89b08766c878a2594b15d203e513acf952340wwang		case SDR50_SUPPORT:
128677d89b08766c878a2594b15d203e513acf952340wwang			if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK)
128777d89b08766c878a2594b15d203e513acf952340wwang					&& chip->sdr50_en) {
128877d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = SDR50_SUPPORT;
128977d89b08766c878a2594b15d203e513acf952340wwang			}
129077d89b08766c878a2594b15d203e513acf952340wwang			break;
129177d89b08766c878a2594b15d203e513acf952340wwang
129277d89b08766c878a2594b15d203e513acf952340wwang		case HS_SUPPORT:
129377d89b08766c878a2594b15d203e513acf952340wwang			if (sd_card->func_group1_mask & HS_SUPPORT_MASK) {
129477d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = HS_SUPPORT;
129577d89b08766c878a2594b15d203e513acf952340wwang			}
129677d89b08766c878a2594b15d203e513acf952340wwang			break;
129777d89b08766c878a2594b15d203e513acf952340wwang
129877d89b08766c878a2594b15d203e513acf952340wwang		default:
129977d89b08766c878a2594b15d203e513acf952340wwang			continue;
130077d89b08766c878a2594b15d203e513acf952340wwang		}
130177d89b08766c878a2594b15d203e513acf952340wwang
130277d89b08766c878a2594b15d203e513acf952340wwang
130377d89b08766c878a2594b15d203e513acf952340wwang		if (func_to_switch) {
130477d89b08766c878a2594b15d203e513acf952340wwang			break;
130577d89b08766c878a2594b15d203e513acf952340wwang		}
130677d89b08766c878a2594b15d203e513acf952340wwang	}
130777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch);
130877d89b08766c878a2594b15d203e513acf952340wwang
130977d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
131077d89b08766c878a2594b15d203e513acf952340wwang	if ((sd_card->sd_lock_status & SD_SDR_RST)
131177d89b08766c878a2594b15d203e513acf952340wwang			&& (DDR50_SUPPORT == func_to_switch)
131277d89b08766c878a2594b15d203e513acf952340wwang			&& (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
131377d89b08766c878a2594b15d203e513acf952340wwang		func_to_switch = SDR50_SUPPORT;
131477d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n");
131577d89b08766c878a2594b15d203e513acf952340wwang	}
131677d89b08766c878a2594b15d203e513acf952340wwang#endif
131777d89b08766c878a2594b15d203e513acf952340wwang
131877d89b08766c878a2594b15d203e513acf952340wwang	if (func_to_switch) {
131977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, bus_width);
132077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
132177d89b08766c878a2594b15d203e513acf952340wwang			if (func_to_switch == SDR104_SUPPORT) {
132277d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
132377d89b08766c878a2594b15d203e513acf952340wwang			} else if (func_to_switch == DDR50_SUPPORT) {
132477d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_switch_fail =
132577d89b08766c878a2594b15d203e513acf952340wwang					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK;
132677d89b08766c878a2594b15d203e513acf952340wwang			} else if (func_to_switch == SDR50_SUPPORT) {
132777d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_switch_fail =
132877d89b08766c878a2594b15d203e513acf952340wwang					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK |
132977d89b08766c878a2594b15d203e513acf952340wwang					SDR50_SUPPORT_MASK;
133077d89b08766c878a2594b15d203e513acf952340wwang			}
133177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
133277d89b08766c878a2594b15d203e513acf952340wwang		}
133377d89b08766c878a2594b15d203e513acf952340wwang
133477d89b08766c878a2594b15d203e513acf952340wwang		if (func_to_switch == SDR104_SUPPORT) {
133577d89b08766c878a2594b15d203e513acf952340wwang			SET_SD_SDR104(sd_card);
133677d89b08766c878a2594b15d203e513acf952340wwang		} else if (func_to_switch == DDR50_SUPPORT) {
133777d89b08766c878a2594b15d203e513acf952340wwang			SET_SD_DDR50(sd_card);
133877d89b08766c878a2594b15d203e513acf952340wwang		} else if (func_to_switch == SDR50_SUPPORT) {
133977d89b08766c878a2594b15d203e513acf952340wwang			SET_SD_SDR50(sd_card);
134077d89b08766c878a2594b15d203e513acf952340wwang		} else {
134177d89b08766c878a2594b15d203e513acf952340wwang			SET_SD_HS(sd_card);
134277d89b08766c878a2594b15d203e513acf952340wwang		}
134377d89b08766c878a2594b15d203e513acf952340wwang	}
134477d89b08766c878a2594b15d203e513acf952340wwang
134577d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD_DDR50(sd_card)) {
134677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04);
134777d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_set_sample_push_timing(chip);
134877d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
134977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
135077d89b08766c878a2594b15d203e513acf952340wwang		}
135177d89b08766c878a2594b15d203e513acf952340wwang	}
135277d89b08766c878a2594b15d203e513acf952340wwang
13532d2322b269c2524996a259024f82c7e318719696wwang	if (!func_to_switch || (func_to_switch == HS_SUPPORT)) {
13542d2322b269c2524996a259024f82c7e318719696wwang		/* Do not try to switch current limit if the card doesn't
13552d2322b269c2524996a259024f82c7e318719696wwang		 * support UHS mode or we don't want it to support UHS mode
13562d2322b269c2524996a259024f82c7e318719696wwang		 */
13572d2322b269c2524996a259024f82c7e318719696wwang		return STATUS_SUCCESS;
13582d2322b269c2524996a259024f82c7e318719696wwang	}
13592d2322b269c2524996a259024f82c7e318719696wwang
13602d2322b269c2524996a259024f82c7e318719696wwang	/* Function Group 4: Current Limit */
136177d89b08766c878a2594b15d203e513acf952340wwang	func_to_switch = 0xFF;
136277d89b08766c878a2594b15d203e513acf952340wwang
136377d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 4; i++) {
136477d89b08766c878a2594b15d203e513acf952340wwang		switch ((u8)(chip->sd_current_prior >> (i*8))) {
136577d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_800:
136677d89b08766c878a2594b15d203e513acf952340wwang			if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) {
136777d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = CURRENT_LIMIT_800;
136877d89b08766c878a2594b15d203e513acf952340wwang			}
136977d89b08766c878a2594b15d203e513acf952340wwang			break;
137077d89b08766c878a2594b15d203e513acf952340wwang
137177d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_600:
137277d89b08766c878a2594b15d203e513acf952340wwang			if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) {
137377d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = CURRENT_LIMIT_600;
137477d89b08766c878a2594b15d203e513acf952340wwang			}
137577d89b08766c878a2594b15d203e513acf952340wwang			break;
137677d89b08766c878a2594b15d203e513acf952340wwang
137777d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_400:
137877d89b08766c878a2594b15d203e513acf952340wwang			if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) {
137977d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = CURRENT_LIMIT_400;
138077d89b08766c878a2594b15d203e513acf952340wwang			}
138177d89b08766c878a2594b15d203e513acf952340wwang			break;
138277d89b08766c878a2594b15d203e513acf952340wwang
138377d89b08766c878a2594b15d203e513acf952340wwang		case CURRENT_LIMIT_200:
138477d89b08766c878a2594b15d203e513acf952340wwang			if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) {
138577d89b08766c878a2594b15d203e513acf952340wwang				func_to_switch = CURRENT_LIMIT_200;
138677d89b08766c878a2594b15d203e513acf952340wwang			}
138777d89b08766c878a2594b15d203e513acf952340wwang			break;
138877d89b08766c878a2594b15d203e513acf952340wwang
138977d89b08766c878a2594b15d203e513acf952340wwang		default:
139077d89b08766c878a2594b15d203e513acf952340wwang			continue;
139177d89b08766c878a2594b15d203e513acf952340wwang		}
139277d89b08766c878a2594b15d203e513acf952340wwang
139377d89b08766c878a2594b15d203e513acf952340wwang		if (func_to_switch != 0xFF) {
139477d89b08766c878a2594b15d203e513acf952340wwang			break;
139577d89b08766c878a2594b15d203e513acf952340wwang		}
139677d89b08766c878a2594b15d203e513acf952340wwang	}
139777d89b08766c878a2594b15d203e513acf952340wwang
139877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch);
139977d89b08766c878a2594b15d203e513acf952340wwang
140077d89b08766c878a2594b15d203e513acf952340wwang	if (func_to_switch <= CURRENT_LIMIT_800) {
140177d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, bus_width);
140277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
140377d89b08766c878a2594b15d203e513acf952340wwang			if (sd_check_err_code(chip, SD_NO_CARD)) {
140477d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
140577d89b08766c878a2594b15d203e513acf952340wwang			}
140677d89b08766c878a2594b15d203e513acf952340wwang		}
140777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval);
140877d89b08766c878a2594b15d203e513acf952340wwang	}
140977d89b08766c878a2594b15d203e513acf952340wwang
141077d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD_DDR50(sd_card)) {
141177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0);
141277d89b08766c878a2594b15d203e513acf952340wwang	}
141377d89b08766c878a2594b15d203e513acf952340wwang
141477d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
141577d89b08766c878a2594b15d203e513acf952340wwang}
141677d89b08766c878a2594b15d203e513acf952340wwang
141777d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_wait_data_idle(struct rtsx_chip *chip)
141877d89b08766c878a2594b15d203e513acf952340wwang{
141977d89b08766c878a2594b15d203e513acf952340wwang	int retval = STATUS_TIMEDOUT;
142077d89b08766c878a2594b15d203e513acf952340wwang	int i;
142177d89b08766c878a2594b15d203e513acf952340wwang	u8 val = 0;
142277d89b08766c878a2594b15d203e513acf952340wwang
142377d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 100; i++) {
142477d89b08766c878a2594b15d203e513acf952340wwang		RTSX_READ_REG(chip, SD_DATA_STATE, &val);
142577d89b08766c878a2594b15d203e513acf952340wwang		if (val & SD_DATA_IDLE) {
142677d89b08766c878a2594b15d203e513acf952340wwang			retval = STATUS_SUCCESS;
142777d89b08766c878a2594b15d203e513acf952340wwang			break;
142877d89b08766c878a2594b15d203e513acf952340wwang		}
142977d89b08766c878a2594b15d203e513acf952340wwang		udelay(100);
143077d89b08766c878a2594b15d203e513acf952340wwang	}
143177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD_DATA_STATE: 0x%02x\n", val);
143277d89b08766c878a2594b15d203e513acf952340wwang
143377d89b08766c878a2594b15d203e513acf952340wwang	return retval;
143477d89b08766c878a2594b15d203e513acf952340wwang}
143577d89b08766c878a2594b15d203e513acf952340wwang
143677d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
143777d89b08766c878a2594b15d203e513acf952340wwang{
143877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
143977d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5];
144077d89b08766c878a2594b15d203e513acf952340wwang
144177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, sample_point, TUNE_RX);
144277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
144377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
144477d89b08766c878a2594b15d203e513acf952340wwang	}
144577d89b08766c878a2594b15d203e513acf952340wwang
144677d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SEND_TUNING_PATTERN;
144777d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
144877d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
144977d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
145077d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
145177d89b08766c878a2594b15d203e513acf952340wwang
145277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_AUTO_TUNING,
145377d89b08766c878a2594b15d203e513acf952340wwang			cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
145477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
145577d89b08766c878a2594b15d203e513acf952340wwang		(void)sd_wait_data_idle(chip);
145677d89b08766c878a2594b15d203e513acf952340wwang
145777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
145877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
145977d89b08766c878a2594b15d203e513acf952340wwang	}
146077d89b08766c878a2594b15d203e513acf952340wwang
146177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
146277d89b08766c878a2594b15d203e513acf952340wwang}
146377d89b08766c878a2594b15d203e513acf952340wwang
146477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
146577d89b08766c878a2594b15d203e513acf952340wwang{
146677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
146777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
146877d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5];
146977d89b08766c878a2594b15d203e513acf952340wwang
147077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, sample_point, TUNE_RX);
147177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
147277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
147377d89b08766c878a2594b15d203e513acf952340wwang	}
147477d89b08766c878a2594b15d203e513acf952340wwang
147577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd ddr tuning rx\n");
147677d89b08766c878a2594b15d203e513acf952340wwang
147777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
147877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
147977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
148077d89b08766c878a2594b15d203e513acf952340wwang	}
148177d89b08766c878a2594b15d203e513acf952340wwang
148277d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SD_STATUS;
148377d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
148477d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
148577d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
148677d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
148777d89b08766c878a2594b15d203e513acf952340wwang
148877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
148977d89b08766c878a2594b15d203e513acf952340wwang			cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
149077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
149177d89b08766c878a2594b15d203e513acf952340wwang		(void)sd_wait_data_idle(chip);
149277d89b08766c878a2594b15d203e513acf952340wwang
149377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
149477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
149577d89b08766c878a2594b15d203e513acf952340wwang	}
149677d89b08766c878a2594b15d203e513acf952340wwang
149777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
149877d89b08766c878a2594b15d203e513acf952340wwang}
149977d89b08766c878a2594b15d203e513acf952340wwang
150077d89b08766c878a2594b15d203e513acf952340wwangstatic int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
150177d89b08766c878a2594b15d203e513acf952340wwang{
150277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
150377d89b08766c878a2594b15d203e513acf952340wwang	int retval;
150477d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], bus_width;
150577d89b08766c878a2594b15d203e513acf952340wwang
150677d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_MMC_8BIT(sd_card)) {
150777d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_8;
150877d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_MMC_4BIT(sd_card)) {
150977d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_4;
151077d89b08766c878a2594b15d203e513acf952340wwang	} else {
151177d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_1;
151277d89b08766c878a2594b15d203e513acf952340wwang	}
151377d89b08766c878a2594b15d203e513acf952340wwang
151477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, sample_point, TUNE_RX);
151577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
151677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
151777d89b08766c878a2594b15d203e513acf952340wwang	}
151877d89b08766c878a2594b15d203e513acf952340wwang
151977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("mmc ddr tuning rx\n");
152077d89b08766c878a2594b15d203e513acf952340wwang
152177d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SEND_EXT_CSD;
152277d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
152377d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
152477d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
152577d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
152677d89b08766c878a2594b15d203e513acf952340wwang
152777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
152877d89b08766c878a2594b15d203e513acf952340wwang			cmd, 5, 0x200, 1, bus_width, NULL, 0, 100);
152977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
153077d89b08766c878a2594b15d203e513acf952340wwang		(void)sd_wait_data_idle(chip);
153177d89b08766c878a2594b15d203e513acf952340wwang
153277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
153377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
153477d89b08766c878a2594b15d203e513acf952340wwang	}
153577d89b08766c878a2594b15d203e513acf952340wwang
153677d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
153777d89b08766c878a2594b15d203e513acf952340wwang}
153877d89b08766c878a2594b15d203e513acf952340wwang
153977d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
154077d89b08766c878a2594b15d203e513acf952340wwang{
154177d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
154277d89b08766c878a2594b15d203e513acf952340wwang	int retval;
154377d89b08766c878a2594b15d203e513acf952340wwang
154477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, sample_point, TUNE_TX);
154577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
154677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
154777d89b08766c878a2594b15d203e513acf952340wwang	}
154877d89b08766c878a2594b15d203e513acf952340wwang
154977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
155077d89b08766c878a2594b15d203e513acf952340wwang
155177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
155277d89b08766c878a2594b15d203e513acf952340wwang		SD_RSP_TYPE_R1, NULL, 0);
155377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
155477d89b08766c878a2594b15d203e513acf952340wwang		if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
155577d89b08766c878a2594b15d203e513acf952340wwang			rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
155677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
155777d89b08766c878a2594b15d203e513acf952340wwang		}
155877d89b08766c878a2594b15d203e513acf952340wwang	}
155977d89b08766c878a2594b15d203e513acf952340wwang
156077d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
156177d89b08766c878a2594b15d203e513acf952340wwang
156277d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
156377d89b08766c878a2594b15d203e513acf952340wwang}
156477d89b08766c878a2594b15d203e513acf952340wwang
156577d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
156677d89b08766c878a2594b15d203e513acf952340wwang{
156777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
156877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
156977d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], bus_width;
157077d89b08766c878a2594b15d203e513acf952340wwang
157177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, sample_point, TUNE_TX);
157277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
157377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
157477d89b08766c878a2594b15d203e513acf952340wwang	}
157577d89b08766c878a2594b15d203e513acf952340wwang
157677d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD(sd_card)) {
157777d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_4;
157877d89b08766c878a2594b15d203e513acf952340wwang	} else {
157977d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_8BIT(sd_card)) {
158077d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_8;
158177d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_MMC_4BIT(sd_card)) {
158277d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_4;
158377d89b08766c878a2594b15d203e513acf952340wwang		} else {
158477d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_1;
158577d89b08766c878a2594b15d203e513acf952340wwang		}
158677d89b08766c878a2594b15d203e513acf952340wwang	}
158777d89b08766c878a2594b15d203e513acf952340wwang
158877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
158977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
159077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
159177d89b08766c878a2594b15d203e513acf952340wwang	}
159277d89b08766c878a2594b15d203e513acf952340wwang
159377d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
159477d89b08766c878a2594b15d203e513acf952340wwang
159577d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | PROGRAM_CSD;
159677d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
159777d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
159877d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
159977d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
160077d89b08766c878a2594b15d203e513acf952340wwang
160177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2,
160277d89b08766c878a2594b15d203e513acf952340wwang			cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100);
160377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
160477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
160577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
160677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
160777d89b08766c878a2594b15d203e513acf952340wwang	}
160877d89b08766c878a2594b15d203e513acf952340wwang
160977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
161077d89b08766c878a2594b15d203e513acf952340wwang
161177d89b08766c878a2594b15d203e513acf952340wwang	sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
161277d89b08766c878a2594b15d203e513acf952340wwang
161377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
161477d89b08766c878a2594b15d203e513acf952340wwang}
161577d89b08766c878a2594b15d203e513acf952340wwang
161677d89b08766c878a2594b15d203e513acf952340wwangstatic u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_dir)
161777d89b08766c878a2594b15d203e513acf952340wwang{
161877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
161977d89b08766c878a2594b15d203e513acf952340wwang	struct timing_phase_path path[MAX_PHASE + 1];
162077d89b08766c878a2594b15d203e513acf952340wwang	int i, j, cont_path_cnt;
162177d89b08766c878a2594b15d203e513acf952340wwang	int new_block, max_len, final_path_idx;
162277d89b08766c878a2594b15d203e513acf952340wwang	u8 final_phase = 0xFF;
162377d89b08766c878a2594b15d203e513acf952340wwang
162477d89b08766c878a2594b15d203e513acf952340wwang	if (phase_map == 0xFFFFFFFF) {
162577d89b08766c878a2594b15d203e513acf952340wwang		if (tune_dir == TUNE_RX) {
162677d89b08766c878a2594b15d203e513acf952340wwang			final_phase = (u8)chip->sd_default_rx_phase;
162777d89b08766c878a2594b15d203e513acf952340wwang		} else {
162877d89b08766c878a2594b15d203e513acf952340wwang			final_phase = (u8)chip->sd_default_tx_phase;
162977d89b08766c878a2594b15d203e513acf952340wwang		}
163077d89b08766c878a2594b15d203e513acf952340wwang
163177d89b08766c878a2594b15d203e513acf952340wwang		goto Search_Finish;
163277d89b08766c878a2594b15d203e513acf952340wwang	}
163377d89b08766c878a2594b15d203e513acf952340wwang
163477d89b08766c878a2594b15d203e513acf952340wwang	cont_path_cnt = 0;
163577d89b08766c878a2594b15d203e513acf952340wwang	new_block = 1;
163677d89b08766c878a2594b15d203e513acf952340wwang	j = 0;
163777d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < MAX_PHASE + 1; i++) {
163877d89b08766c878a2594b15d203e513acf952340wwang		if (phase_map & (1 << i)) {
163977d89b08766c878a2594b15d203e513acf952340wwang			if (new_block) {
164077d89b08766c878a2594b15d203e513acf952340wwang				new_block = 0;
164177d89b08766c878a2594b15d203e513acf952340wwang				j = cont_path_cnt++;
164277d89b08766c878a2594b15d203e513acf952340wwang				path[j].start = i;
164377d89b08766c878a2594b15d203e513acf952340wwang				path[j].end = i;
164477d89b08766c878a2594b15d203e513acf952340wwang			} else {
164577d89b08766c878a2594b15d203e513acf952340wwang				path[j].end = i;
164677d89b08766c878a2594b15d203e513acf952340wwang			}
164777d89b08766c878a2594b15d203e513acf952340wwang		} else {
164877d89b08766c878a2594b15d203e513acf952340wwang			new_block = 1;
164977d89b08766c878a2594b15d203e513acf952340wwang			if (cont_path_cnt) {
165077d89b08766c878a2594b15d203e513acf952340wwang				int idx = cont_path_cnt - 1;
165177d89b08766c878a2594b15d203e513acf952340wwang				path[idx].len = path[idx].end - path[idx].start + 1;
165277d89b08766c878a2594b15d203e513acf952340wwang				path[idx].mid = path[idx].start + path[idx].len / 2;
165377d89b08766c878a2594b15d203e513acf952340wwang			}
165477d89b08766c878a2594b15d203e513acf952340wwang		}
165577d89b08766c878a2594b15d203e513acf952340wwang	}
165677d89b08766c878a2594b15d203e513acf952340wwang
165777d89b08766c878a2594b15d203e513acf952340wwang	if (cont_path_cnt == 0) {
165877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("No continuous phase path\n");
165977d89b08766c878a2594b15d203e513acf952340wwang		goto Search_Finish;
166077d89b08766c878a2594b15d203e513acf952340wwang	} else {
166177d89b08766c878a2594b15d203e513acf952340wwang		int idx = cont_path_cnt - 1;
166277d89b08766c878a2594b15d203e513acf952340wwang		path[idx].len = path[idx].end - path[idx].start + 1;
166377d89b08766c878a2594b15d203e513acf952340wwang		path[idx].mid = path[idx].start + path[idx].len / 2;
166477d89b08766c878a2594b15d203e513acf952340wwang	}
166577d89b08766c878a2594b15d203e513acf952340wwang
166677d89b08766c878a2594b15d203e513acf952340wwang	if ((path[0].start == 0) && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
166777d89b08766c878a2594b15d203e513acf952340wwang		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
166877d89b08766c878a2594b15d203e513acf952340wwang		path[0].len += path[cont_path_cnt - 1].len;
166977d89b08766c878a2594b15d203e513acf952340wwang		path[0].mid = path[0].start + path[0].len / 2;
167077d89b08766c878a2594b15d203e513acf952340wwang		if (path[0].mid < 0) {
167177d89b08766c878a2594b15d203e513acf952340wwang			path[0].mid += MAX_PHASE + 1;
167277d89b08766c878a2594b15d203e513acf952340wwang		}
167377d89b08766c878a2594b15d203e513acf952340wwang		cont_path_cnt--;
167477d89b08766c878a2594b15d203e513acf952340wwang	}
167577d89b08766c878a2594b15d203e513acf952340wwang
167677d89b08766c878a2594b15d203e513acf952340wwang	max_len = 0;
167777d89b08766c878a2594b15d203e513acf952340wwang	final_phase = 0;
167877d89b08766c878a2594b15d203e513acf952340wwang	final_path_idx = 0;
167977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < cont_path_cnt; i++) {
168077d89b08766c878a2594b15d203e513acf952340wwang		if (path[i].len > max_len) {
168177d89b08766c878a2594b15d203e513acf952340wwang			max_len = path[i].len;
168277d89b08766c878a2594b15d203e513acf952340wwang			final_phase = (u8)path[i].mid;
168377d89b08766c878a2594b15d203e513acf952340wwang			final_path_idx = i;
168477d89b08766c878a2594b15d203e513acf952340wwang		}
168577d89b08766c878a2594b15d203e513acf952340wwang
168677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("path[%d].start = %d\n", i, path[i].start);
168777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("path[%d].end = %d\n", i, path[i].end);
168877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("path[%d].len = %d\n", i, path[i].len);
168977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("path[%d].mid = %d\n", i, path[i].mid);
169077d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("\n");
169177d89b08766c878a2594b15d203e513acf952340wwang	}
169277d89b08766c878a2594b15d203e513acf952340wwang
169377d89b08766c878a2594b15d203e513acf952340wwang	if (tune_dir == TUNE_TX) {
169477d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_SDR104(sd_card)) {
169577d89b08766c878a2594b15d203e513acf952340wwang			if (max_len > 15) {
169677d89b08766c878a2594b15d203e513acf952340wwang				int temp_mid = (max_len - 16) / 2;
169777d89b08766c878a2594b15d203e513acf952340wwang				int temp_final_phase =
169877d89b08766c878a2594b15d203e513acf952340wwang					path[final_path_idx].end - (max_len - (6 + temp_mid));
169977d89b08766c878a2594b15d203e513acf952340wwang
170077d89b08766c878a2594b15d203e513acf952340wwang				if (temp_final_phase < 0) {
170177d89b08766c878a2594b15d203e513acf952340wwang					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
170277d89b08766c878a2594b15d203e513acf952340wwang				} else {
170377d89b08766c878a2594b15d203e513acf952340wwang					final_phase = (u8)temp_final_phase;
170477d89b08766c878a2594b15d203e513acf952340wwang				}
170577d89b08766c878a2594b15d203e513acf952340wwang			}
170677d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_SD_SDR50(sd_card)) {
170777d89b08766c878a2594b15d203e513acf952340wwang			if (max_len > 12) {
170877d89b08766c878a2594b15d203e513acf952340wwang				int temp_mid = (max_len - 13) / 2;
170977d89b08766c878a2594b15d203e513acf952340wwang				int temp_final_phase =
171077d89b08766c878a2594b15d203e513acf952340wwang					path[final_path_idx].end - (max_len - (3 + temp_mid));
171177d89b08766c878a2594b15d203e513acf952340wwang
171277d89b08766c878a2594b15d203e513acf952340wwang				if (temp_final_phase < 0) {
171377d89b08766c878a2594b15d203e513acf952340wwang					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
171477d89b08766c878a2594b15d203e513acf952340wwang				} else {
171577d89b08766c878a2594b15d203e513acf952340wwang					final_phase = (u8)temp_final_phase;
171677d89b08766c878a2594b15d203e513acf952340wwang				}
171777d89b08766c878a2594b15d203e513acf952340wwang			}
171877d89b08766c878a2594b15d203e513acf952340wwang		}
171977d89b08766c878a2594b15d203e513acf952340wwang	}
172077d89b08766c878a2594b15d203e513acf952340wwang
172177d89b08766c878a2594b15d203e513acf952340wwangSearch_Finish:
172225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	RTSX_DEBUGP("Final chosen phase: %d\n", final_phase);
172377d89b08766c878a2594b15d203e513acf952340wwang	return final_phase;
172477d89b08766c878a2594b15d203e513acf952340wwang}
172577d89b08766c878a2594b15d203e513acf952340wwang
172677d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_tuning_rx(struct rtsx_chip *chip)
172777d89b08766c878a2594b15d203e513acf952340wwang{
172877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
172977d89b08766c878a2594b15d203e513acf952340wwang	int retval;
173077d89b08766c878a2594b15d203e513acf952340wwang	int i, j;
173177d89b08766c878a2594b15d203e513acf952340wwang	u32 raw_phase_map[3], phase_map;
173277d89b08766c878a2594b15d203e513acf952340wwang	u8 final_phase;
173377d89b08766c878a2594b15d203e513acf952340wwang	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
173477d89b08766c878a2594b15d203e513acf952340wwang
173577d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD(sd_card)) {
173677d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_DDR50(sd_card)) {
173777d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = sd_ddr_tuning_rx_cmd;
173877d89b08766c878a2594b15d203e513acf952340wwang		} else {
173977d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = sd_sdr_tuning_rx_cmd;
174077d89b08766c878a2594b15d203e513acf952340wwang		}
174177d89b08766c878a2594b15d203e513acf952340wwang	} else {
174277d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_DDR52(sd_card)) {
174377d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = mmc_ddr_tunning_rx_cmd;
174477d89b08766c878a2594b15d203e513acf952340wwang		} else {
174577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
174677d89b08766c878a2594b15d203e513acf952340wwang		}
174777d89b08766c878a2594b15d203e513acf952340wwang	}
174877d89b08766c878a2594b15d203e513acf952340wwang
174977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
175077d89b08766c878a2594b15d203e513acf952340wwang		raw_phase_map[i] = 0;
175177d89b08766c878a2594b15d203e513acf952340wwang		for (j = MAX_PHASE; j >= 0; j--) {
175277d89b08766c878a2594b15d203e513acf952340wwang			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
175377d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_NO_CARD);
175477d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
175577d89b08766c878a2594b15d203e513acf952340wwang			}
175677d89b08766c878a2594b15d203e513acf952340wwang
175777d89b08766c878a2594b15d203e513acf952340wwang			retval = tuning_cmd(chip, (u8)j);
175877d89b08766c878a2594b15d203e513acf952340wwang			if (retval == STATUS_SUCCESS) {
175977d89b08766c878a2594b15d203e513acf952340wwang				raw_phase_map[i] |= 1 << j;
176077d89b08766c878a2594b15d203e513acf952340wwang			}
176177d89b08766c878a2594b15d203e513acf952340wwang		}
176277d89b08766c878a2594b15d203e513acf952340wwang	}
176377d89b08766c878a2594b15d203e513acf952340wwang
176477d89b08766c878a2594b15d203e513acf952340wwang	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
176577d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
176677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
176777d89b08766c878a2594b15d203e513acf952340wwang	}
176877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map);
176977d89b08766c878a2594b15d203e513acf952340wwang
177077d89b08766c878a2594b15d203e513acf952340wwang	final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
177177d89b08766c878a2594b15d203e513acf952340wwang	if (final_phase == 0xFF) {
177277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
177377d89b08766c878a2594b15d203e513acf952340wwang	}
177477d89b08766c878a2594b15d203e513acf952340wwang
177577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, final_phase, TUNE_RX);
177677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
177777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
177877d89b08766c878a2594b15d203e513acf952340wwang	}
177977d89b08766c878a2594b15d203e513acf952340wwang
178077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
178177d89b08766c878a2594b15d203e513acf952340wwang}
178277d89b08766c878a2594b15d203e513acf952340wwang
178377d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
178477d89b08766c878a2594b15d203e513acf952340wwang{
178577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
178677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
178777d89b08766c878a2594b15d203e513acf952340wwang	int i;
178877d89b08766c878a2594b15d203e513acf952340wwang	u32 phase_map;
178977d89b08766c878a2594b15d203e513acf952340wwang	u8 final_phase;
179077d89b08766c878a2594b15d203e513acf952340wwang
179177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
179277d89b08766c878a2594b15d203e513acf952340wwang
179377d89b08766c878a2594b15d203e513acf952340wwang	phase_map = 0;
179477d89b08766c878a2594b15d203e513acf952340wwang	for (i = MAX_PHASE; i >= 0; i--) {
179577d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
179677d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_NO_CARD);
179777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_write_register(chip, SD_CFG3,
179877d89b08766c878a2594b15d203e513acf952340wwang						SD_RSP_80CLK_TIMEOUT_EN, 0);
179977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
180077d89b08766c878a2594b15d203e513acf952340wwang		}
180177d89b08766c878a2594b15d203e513acf952340wwang
180277d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_change_phase(chip, (u8)i, TUNE_TX);
180377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
180477d89b08766c878a2594b15d203e513acf952340wwang			continue;
180577d89b08766c878a2594b15d203e513acf952340wwang		}
180677d89b08766c878a2594b15d203e513acf952340wwang
180777d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
180877d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0);
180977d89b08766c878a2594b15d203e513acf952340wwang		if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
181077d89b08766c878a2594b15d203e513acf952340wwang			phase_map |= 1 << i;
181177d89b08766c878a2594b15d203e513acf952340wwang		}
181277d89b08766c878a2594b15d203e513acf952340wwang	}
181377d89b08766c878a2594b15d203e513acf952340wwang
181477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
181577d89b08766c878a2594b15d203e513acf952340wwang
181677d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map);
181777d89b08766c878a2594b15d203e513acf952340wwang
181877d89b08766c878a2594b15d203e513acf952340wwang	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
181977d89b08766c878a2594b15d203e513acf952340wwang	if (final_phase == 0xFF) {
182077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
182177d89b08766c878a2594b15d203e513acf952340wwang	}
182277d89b08766c878a2594b15d203e513acf952340wwang
182377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, final_phase, TUNE_TX);
182477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
182577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
182677d89b08766c878a2594b15d203e513acf952340wwang	}
182777d89b08766c878a2594b15d203e513acf952340wwang
182877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase);
182977d89b08766c878a2594b15d203e513acf952340wwang
183077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
183177d89b08766c878a2594b15d203e513acf952340wwang}
183277d89b08766c878a2594b15d203e513acf952340wwang
183377d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_tuning_tx(struct rtsx_chip *chip)
183477d89b08766c878a2594b15d203e513acf952340wwang{
183577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
183677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
183777d89b08766c878a2594b15d203e513acf952340wwang	int i, j;
183877d89b08766c878a2594b15d203e513acf952340wwang	u32 raw_phase_map[3], phase_map;
183977d89b08766c878a2594b15d203e513acf952340wwang	u8 final_phase;
184077d89b08766c878a2594b15d203e513acf952340wwang	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
184177d89b08766c878a2594b15d203e513acf952340wwang
184277d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD(sd_card)) {
184377d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_DDR50(sd_card)) {
184477d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = sd_ddr_tuning_tx_cmd;
184577d89b08766c878a2594b15d203e513acf952340wwang		} else {
184677d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = sd_sdr_tuning_tx_cmd;
184777d89b08766c878a2594b15d203e513acf952340wwang		}
184877d89b08766c878a2594b15d203e513acf952340wwang	} else {
184977d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_DDR52(sd_card)) {
185077d89b08766c878a2594b15d203e513acf952340wwang			tuning_cmd = sd_ddr_tuning_tx_cmd;
185177d89b08766c878a2594b15d203e513acf952340wwang		} else {
185277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
185377d89b08766c878a2594b15d203e513acf952340wwang		}
185477d89b08766c878a2594b15d203e513acf952340wwang	}
185577d89b08766c878a2594b15d203e513acf952340wwang
185677d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
185777d89b08766c878a2594b15d203e513acf952340wwang		raw_phase_map[i] = 0;
185877d89b08766c878a2594b15d203e513acf952340wwang		for (j = MAX_PHASE; j >= 0; j--) {
185977d89b08766c878a2594b15d203e513acf952340wwang			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
186077d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_NO_CARD);
186177d89b08766c878a2594b15d203e513acf952340wwang				rtsx_write_register(chip, SD_CFG3,
186277d89b08766c878a2594b15d203e513acf952340wwang						    SD_RSP_80CLK_TIMEOUT_EN, 0);
186377d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
186477d89b08766c878a2594b15d203e513acf952340wwang			}
186577d89b08766c878a2594b15d203e513acf952340wwang
186677d89b08766c878a2594b15d203e513acf952340wwang			retval = tuning_cmd(chip, (u8)j);
186777d89b08766c878a2594b15d203e513acf952340wwang			if (retval == STATUS_SUCCESS) {
186877d89b08766c878a2594b15d203e513acf952340wwang				raw_phase_map[i] |= 1 << j;
186977d89b08766c878a2594b15d203e513acf952340wwang			}
187077d89b08766c878a2594b15d203e513acf952340wwang		}
187177d89b08766c878a2594b15d203e513acf952340wwang	}
187277d89b08766c878a2594b15d203e513acf952340wwang
187377d89b08766c878a2594b15d203e513acf952340wwang	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
187477d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
187577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
187677d89b08766c878a2594b15d203e513acf952340wwang	}
187777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map);
187877d89b08766c878a2594b15d203e513acf952340wwang
187977d89b08766c878a2594b15d203e513acf952340wwang	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
188077d89b08766c878a2594b15d203e513acf952340wwang	if (final_phase == 0xFF) {
188177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
188277d89b08766c878a2594b15d203e513acf952340wwang	}
188377d89b08766c878a2594b15d203e513acf952340wwang
188477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_change_phase(chip, final_phase, TUNE_TX);
188577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
188677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
188777d89b08766c878a2594b15d203e513acf952340wwang	}
188877d89b08766c878a2594b15d203e513acf952340wwang
188977d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
189077d89b08766c878a2594b15d203e513acf952340wwang}
189177d89b08766c878a2594b15d203e513acf952340wwang
189277d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_sdr_tuning(struct rtsx_chip *chip)
189377d89b08766c878a2594b15d203e513acf952340wwang{
189477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
189577d89b08766c878a2594b15d203e513acf952340wwang
189677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_tuning_tx(chip);
189777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
189877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
189977d89b08766c878a2594b15d203e513acf952340wwang	}
190077d89b08766c878a2594b15d203e513acf952340wwang
190177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_tuning_rx(chip);
190277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
190377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
190477d89b08766c878a2594b15d203e513acf952340wwang	}
190577d89b08766c878a2594b15d203e513acf952340wwang
190677d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
190777d89b08766c878a2594b15d203e513acf952340wwang}
190877d89b08766c878a2594b15d203e513acf952340wwang
190977d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_ddr_tuning(struct rtsx_chip *chip)
191077d89b08766c878a2594b15d203e513acf952340wwang{
191177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
191277d89b08766c878a2594b15d203e513acf952340wwang
191377d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
191477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_ddr_pre_tuning_tx(chip);
191577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
191677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
191777d89b08766c878a2594b15d203e513acf952340wwang		}
191877d89b08766c878a2594b15d203e513acf952340wwang	} else {
191977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, TUNE_TX);
192077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
192177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
192277d89b08766c878a2594b15d203e513acf952340wwang		}
192377d89b08766c878a2594b15d203e513acf952340wwang	}
192477d89b08766c878a2594b15d203e513acf952340wwang
192577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_tuning_rx(chip);
192677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
192777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
192877d89b08766c878a2594b15d203e513acf952340wwang	}
192977d89b08766c878a2594b15d203e513acf952340wwang
193077d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
193177d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_tuning_tx(chip);
193277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
193377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
193477d89b08766c878a2594b15d203e513acf952340wwang		}
193577d89b08766c878a2594b15d203e513acf952340wwang	}
193677d89b08766c878a2594b15d203e513acf952340wwang
193777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
193877d89b08766c878a2594b15d203e513acf952340wwang}
193977d89b08766c878a2594b15d203e513acf952340wwang
194077d89b08766c878a2594b15d203e513acf952340wwangstatic int mmc_ddr_tuning(struct rtsx_chip *chip)
194177d89b08766c878a2594b15d203e513acf952340wwang{
194277d89b08766c878a2594b15d203e513acf952340wwang	int retval;
194377d89b08766c878a2594b15d203e513acf952340wwang
194477d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
194577d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_ddr_pre_tuning_tx(chip);
194677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
194777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
194877d89b08766c878a2594b15d203e513acf952340wwang		}
194977d89b08766c878a2594b15d203e513acf952340wwang	} else {
195077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, TUNE_TX);
195177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
195277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
195377d89b08766c878a2594b15d203e513acf952340wwang		}
195477d89b08766c878a2594b15d203e513acf952340wwang	}
195577d89b08766c878a2594b15d203e513acf952340wwang
195677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_tuning_rx(chip);
195777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
195877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
195977d89b08766c878a2594b15d203e513acf952340wwang	}
196077d89b08766c878a2594b15d203e513acf952340wwang
196177d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
196277d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_tuning_tx(chip);
196377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
196477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
196577d89b08766c878a2594b15d203e513acf952340wwang		}
196677d89b08766c878a2594b15d203e513acf952340wwang	}
196777d89b08766c878a2594b15d203e513acf952340wwang
196877d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
196977d89b08766c878a2594b15d203e513acf952340wwang}
197077d89b08766c878a2594b15d203e513acf952340wwang
197177d89b08766c878a2594b15d203e513acf952340wwangint sd_switch_clock(struct rtsx_chip *chip)
197277d89b08766c878a2594b15d203e513acf952340wwang{
197377d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
197477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
197577d89b08766c878a2594b15d203e513acf952340wwang	int re_tuning = 0;
197677d89b08766c878a2594b15d203e513acf952340wwang
197777d89b08766c878a2594b15d203e513acf952340wwang	retval = select_card(chip, SD_CARD);
197877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
197977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
198077d89b08766c878a2594b15d203e513acf952340wwang	}
198177d89b08766c878a2594b15d203e513acf952340wwang
198277d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209) &&
198377d89b08766c878a2594b15d203e513acf952340wwang			(CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))) {
198477d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->need_retune && (sd_card->sd_clock != chip->cur_clk)) {
198577d89b08766c878a2594b15d203e513acf952340wwang			re_tuning = 1;
198677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->need_retune = 0;
198777d89b08766c878a2594b15d203e513acf952340wwang		}
198877d89b08766c878a2594b15d203e513acf952340wwang	}
198977d89b08766c878a2594b15d203e513acf952340wwang
199077d89b08766c878a2594b15d203e513acf952340wwang	retval = switch_clock(chip, sd_card->sd_clock);
199177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
199277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
199377d89b08766c878a2594b15d203e513acf952340wwang	}
199477d89b08766c878a2594b15d203e513acf952340wwang
199577d89b08766c878a2594b15d203e513acf952340wwang	if (re_tuning) {
199677d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD(sd_card)) {
199777d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_SD_DDR50(sd_card)) {
199877d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_ddr_tuning(chip);
199977d89b08766c878a2594b15d203e513acf952340wwang			} else {
200077d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_sdr_tuning(chip);
200177d89b08766c878a2594b15d203e513acf952340wwang			}
200277d89b08766c878a2594b15d203e513acf952340wwang		} else {
200377d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_DDR52(sd_card)) {
200477d89b08766c878a2594b15d203e513acf952340wwang				retval = mmc_ddr_tuning(chip);
200577d89b08766c878a2594b15d203e513acf952340wwang			}
200677d89b08766c878a2594b15d203e513acf952340wwang		}
200777d89b08766c878a2594b15d203e513acf952340wwang
200877d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
200977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
201077d89b08766c878a2594b15d203e513acf952340wwang		}
201177d89b08766c878a2594b15d203e513acf952340wwang	}
201277d89b08766c878a2594b15d203e513acf952340wwang
201377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
201477d89b08766c878a2594b15d203e513acf952340wwang}
201577d89b08766c878a2594b15d203e513acf952340wwang
201677d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_prepare_reset(struct rtsx_chip *chip)
201777d89b08766c878a2594b15d203e513acf952340wwang{
201877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
201977d89b08766c878a2594b15d203e513acf952340wwang	int retval;
202077d89b08766c878a2594b15d203e513acf952340wwang
202177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
202277d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_clock = 29;
202377d89b08766c878a2594b15d203e513acf952340wwang	} else {
202477d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_clock = CLK_30;
202577d89b08766c878a2594b15d203e513acf952340wwang	}
202677d89b08766c878a2594b15d203e513acf952340wwang
20272d2322b269c2524996a259024f82c7e318719696wwang	sd_card->sd_type = 0;
20282d2322b269c2524996a259024f82c7e318719696wwang	sd_card->seq_mode = 0;
20292d2322b269c2524996a259024f82c7e318719696wwang	sd_card->sd_data_buf_ready = 0;
20302d2322b269c2524996a259024f82c7e318719696wwang	sd_card->capacity = 0;
20312d2322b269c2524996a259024f82c7e318719696wwang
20322d2322b269c2524996a259024f82c7e318719696wwang#ifdef SUPPORT_SD_LOCK
20332d2322b269c2524996a259024f82c7e318719696wwang	sd_card->sd_lock_status = 0;
20342d2322b269c2524996a259024f82c7e318719696wwang	sd_card->sd_erase_status = 0;
20352d2322b269c2524996a259024f82c7e318719696wwang#endif
20362d2322b269c2524996a259024f82c7e318719696wwang
20372d2322b269c2524996a259024f82c7e318719696wwang	chip->capacity[chip->card2lun[SD_CARD]] = 0;
203877d89b08766c878a2594b15d203e513acf952340wwang	chip->sd_io = 0;
203977d89b08766c878a2594b15d203e513acf952340wwang
204077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_init_para(chip);
204177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
204277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, retval);
204377d89b08766c878a2594b15d203e513acf952340wwang	}
204477d89b08766c878a2594b15d203e513acf952340wwang
204577d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
204677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF,
204777d89b08766c878a2594b15d203e513acf952340wwang			SD_CLK_DIVIDE_128 | SD_20_MODE | SD_BUS_WIDTH_1);
204877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, 0xFF, SD20_RX_POS_EDGE);
204977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0xFF, 0);
205077d89b08766c878a2594b15d203e513acf952340wwang	} else {
205177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40);
205277d89b08766c878a2594b15d203e513acf952340wwang	}
205377d89b08766c878a2594b15d203e513acf952340wwang
205477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
205577d89b08766c878a2594b15d203e513acf952340wwang
205677d89b08766c878a2594b15d203e513acf952340wwang	retval = select_card(chip, SD_CARD);
205777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
205877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
205977d89b08766c878a2594b15d203e513acf952340wwang	}
206077d89b08766c878a2594b15d203e513acf952340wwang
206177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
206277d89b08766c878a2594b15d203e513acf952340wwang}
206377d89b08766c878a2594b15d203e513acf952340wwang
206477d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_pull_ctl_disable(struct rtsx_chip *chip)
206577d89b08766c878a2594b15d203e513acf952340wwang{
206677d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
206777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
206877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
206977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5);
207077d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHECK_PID(chip, 0x5208)) {
207177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
207277d89b08766c878a2594b15d203e513acf952340wwang			XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
207377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
207477d89b08766c878a2594b15d203e513acf952340wwang			SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
207577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
207677d89b08766c878a2594b15d203e513acf952340wwang			SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
207777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
207877d89b08766c878a2594b15d203e513acf952340wwang			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
207977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
208077d89b08766c878a2594b15d203e513acf952340wwang			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
208177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
208277d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHECK_PID(chip, 0x5288)) {
208377d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_BARO_PKG(chip, QFN)) {
208477d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
208577d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
208677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
208777d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
208877d89b08766c878a2594b15d203e513acf952340wwang		}
208977d89b08766c878a2594b15d203e513acf952340wwang	}
209077d89b08766c878a2594b15d203e513acf952340wwang
209177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
209277d89b08766c878a2594b15d203e513acf952340wwang}
209377d89b08766c878a2594b15d203e513acf952340wwang
209477d89b08766c878a2594b15d203e513acf952340wwangint sd_pull_ctl_enable(struct rtsx_chip *chip)
209577d89b08766c878a2594b15d203e513acf952340wwang{
209677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
209777d89b08766c878a2594b15d203e513acf952340wwang
209877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
209977d89b08766c878a2594b15d203e513acf952340wwang
210077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
210177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
210277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
210377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xE9);
210477d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHECK_PID(chip, 0x5208)) {
210577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
210677d89b08766c878a2594b15d203e513acf952340wwang			XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
210777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
210877d89b08766c878a2594b15d203e513acf952340wwang			SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
210977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
211077d89b08766c878a2594b15d203e513acf952340wwang			SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
211177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
211277d89b08766c878a2594b15d203e513acf952340wwang			XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
211377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
211477d89b08766c878a2594b15d203e513acf952340wwang			MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
211577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
211677d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHECK_PID(chip, 0x5288)) {
211777d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_BARO_PKG(chip, QFN)) {
211877d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA8);
211977d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x5A);
212077d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
212177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xAA);
212277d89b08766c878a2594b15d203e513acf952340wwang		}
212377d89b08766c878a2594b15d203e513acf952340wwang	}
212477d89b08766c878a2594b15d203e513acf952340wwang
212577d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, 100);
212677d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
212777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
212877d89b08766c878a2594b15d203e513acf952340wwang	}
212977d89b08766c878a2594b15d203e513acf952340wwang
213077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
213177d89b08766c878a2594b15d203e513acf952340wwang}
213277d89b08766c878a2594b15d203e513acf952340wwang
213377d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_init_power(struct rtsx_chip *chip)
213477d89b08766c878a2594b15d203e513acf952340wwang{
213577d89b08766c878a2594b15d203e513acf952340wwang	int retval;
213677d89b08766c878a2594b15d203e513acf952340wwang
213777d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
213877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
213977d89b08766c878a2594b15d203e513acf952340wwang	}
214077d89b08766c878a2594b15d203e513acf952340wwang
214177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_power_off_card3v3(chip);
214277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
214377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
214477d89b08766c878a2594b15d203e513acf952340wwang	}
214577d89b08766c878a2594b15d203e513acf952340wwang
214677d89b08766c878a2594b15d203e513acf952340wwang	if (!chip->ft2_fast_mode) {
214777d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(250);
214877d89b08766c878a2594b15d203e513acf952340wwang	}
214977d89b08766c878a2594b15d203e513acf952340wwang
215077d89b08766c878a2594b15d203e513acf952340wwang	retval = enable_card_clock(chip, SD_CARD);
215177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
215277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
215377d89b08766c878a2594b15d203e513acf952340wwang	}
215477d89b08766c878a2594b15d203e513acf952340wwang
215577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
215677d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_pull_ctl_enable(chip);
215777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
215877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
215977d89b08766c878a2594b15d203e513acf952340wwang		}
216077d89b08766c878a2594b15d203e513acf952340wwang	} else {
216177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0);
216277d89b08766c878a2594b15d203e513acf952340wwang	}
216377d89b08766c878a2594b15d203e513acf952340wwang
216477d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ft2_fast_mode) {
216577d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209)) {
216677d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
216777d89b08766c878a2594b15d203e513acf952340wwang		}
216877d89b08766c878a2594b15d203e513acf952340wwang	} else {
216977d89b08766c878a2594b15d203e513acf952340wwang		retval = card_power_on(chip, SD_CARD);
217077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
217177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
217277d89b08766c878a2594b15d203e513acf952340wwang		}
217377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(260);
217477d89b08766c878a2594b15d203e513acf952340wwang
217577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_OCP
217677d89b08766c878a2594b15d203e513acf952340wwang		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
217777d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
217877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
217977d89b08766c878a2594b15d203e513acf952340wwang		}
218077d89b08766c878a2594b15d203e513acf952340wwang#endif
218177d89b08766c878a2594b15d203e513acf952340wwang	}
218277d89b08766c878a2594b15d203e513acf952340wwang
218377d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
218477d89b08766c878a2594b15d203e513acf952340wwang
218577d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
218677d89b08766c878a2594b15d203e513acf952340wwang}
218777d89b08766c878a2594b15d203e513acf952340wwang
218877d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_dummy_clock(struct rtsx_chip *chip)
218977d89b08766c878a2594b15d203e513acf952340wwang{
219077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
219177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
219277d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(5);
219377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00);
219477d89b08766c878a2594b15d203e513acf952340wwang	} else {
219577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01);
219677d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(5);
219777d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0);
219877d89b08766c878a2594b15d203e513acf952340wwang	}
219977d89b08766c878a2594b15d203e513acf952340wwang
220077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
220177d89b08766c878a2594b15d203e513acf952340wwang}
220277d89b08766c878a2594b15d203e513acf952340wwang
220377d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_read_lba0(struct rtsx_chip *chip)
220477d89b08766c878a2594b15d203e513acf952340wwang{
220577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
220677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
220777d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], bus_width;
220877d89b08766c878a2594b15d203e513acf952340wwang
220977d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | READ_SINGLE_BLOCK;
221077d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
221177d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
221277d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
221377d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
221477d89b08766c878a2594b15d203e513acf952340wwang
221577d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SD(sd_card)) {
221677d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_4;
221777d89b08766c878a2594b15d203e513acf952340wwang	} else {
221877d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_8BIT(sd_card)) {
221977d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_8;
222077d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_MMC_4BIT(sd_card)) {
222177d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_4;
222277d89b08766c878a2594b15d203e513acf952340wwang		} else {
222377d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_1;
222477d89b08766c878a2594b15d203e513acf952340wwang		}
222577d89b08766c878a2594b15d203e513acf952340wwang	}
222677d89b08766c878a2594b15d203e513acf952340wwang
222777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd,
222877d89b08766c878a2594b15d203e513acf952340wwang		5, 512, 1, bus_width, NULL, 0, 100);
222977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
2230e0ce58d7b05eba3d79ea8124d417224dae65c71fwwang		rtsx_clear_sd_error(chip);
223177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
223277d89b08766c878a2594b15d203e513acf952340wwang	}
223377d89b08766c878a2594b15d203e513acf952340wwang
223477d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
223577d89b08766c878a2594b15d203e513acf952340wwang}
223677d89b08766c878a2594b15d203e513acf952340wwang
223777d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_check_wp_state(struct rtsx_chip *chip)
223877d89b08766c878a2594b15d203e513acf952340wwang{
223977d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
224077d89b08766c878a2594b15d203e513acf952340wwang	int retval;
224177d89b08766c878a2594b15d203e513acf952340wwang	u32 val;
224277d89b08766c878a2594b15d203e513acf952340wwang	u16 sd_card_type;
224377d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd[5], buf[64];
224477d89b08766c878a2594b15d203e513acf952340wwang
224577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, APP_CMD,
224677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
224777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
224877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
224977d89b08766c878a2594b15d203e513acf952340wwang	}
225077d89b08766c878a2594b15d203e513acf952340wwang
225177d89b08766c878a2594b15d203e513acf952340wwang	cmd[0] = 0x40 | SD_STATUS;
225277d89b08766c878a2594b15d203e513acf952340wwang	cmd[1] = 0;
225377d89b08766c878a2594b15d203e513acf952340wwang	cmd[2] = 0;
225477d89b08766c878a2594b15d203e513acf952340wwang	cmd[3] = 0;
225577d89b08766c878a2594b15d203e513acf952340wwang	cmd[4] = 0;
225677d89b08766c878a2594b15d203e513acf952340wwang
225777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, SD_BUS_WIDTH_4, buf, 64, 250);
225877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
225977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
226077d89b08766c878a2594b15d203e513acf952340wwang
226177d89b08766c878a2594b15d203e513acf952340wwang		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
226277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
226377d89b08766c878a2594b15d203e513acf952340wwang	}
226477d89b08766c878a2594b15d203e513acf952340wwang
226577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("ACMD13:\n");
226677d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DUMP(buf, 64);
226777d89b08766c878a2594b15d203e513acf952340wwang
226877d89b08766c878a2594b15d203e513acf952340wwang	sd_card_type = ((u16)buf[2] << 8) | buf[3];
226977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd_card_type = 0x%04x\n", sd_card_type);
227077d89b08766c878a2594b15d203e513acf952340wwang	if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) {
227177d89b08766c878a2594b15d203e513acf952340wwang		/* ROM card or OTP */
227277d89b08766c878a2594b15d203e513acf952340wwang		chip->card_wp |= SD_CARD;
227377d89b08766c878a2594b15d203e513acf952340wwang	}
227477d89b08766c878a2594b15d203e513acf952340wwang
227577d89b08766c878a2594b15d203e513acf952340wwang	/* Check SD Machanical Write-Protect Switch */
227677d89b08766c878a2594b15d203e513acf952340wwang	val = rtsx_readl(chip, RTSX_BIPR);
227777d89b08766c878a2594b15d203e513acf952340wwang	if (val & SD_WRITE_PROTECT) {
227877d89b08766c878a2594b15d203e513acf952340wwang		chip->card_wp |= SD_CARD;
227977d89b08766c878a2594b15d203e513acf952340wwang	}
228077d89b08766c878a2594b15d203e513acf952340wwang
228177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
228277d89b08766c878a2594b15d203e513acf952340wwang}
228377d89b08766c878a2594b15d203e513acf952340wwang
228477d89b08766c878a2594b15d203e513acf952340wwangstatic int reset_sd(struct rtsx_chip *chip)
228577d89b08766c878a2594b15d203e513acf952340wwang{
228677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
228777d89b08766c878a2594b15d203e513acf952340wwang	int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0;
228877d89b08766c878a2594b15d203e513acf952340wwang	int sd_dont_switch = 0;
228977d89b08766c878a2594b15d203e513acf952340wwang	int support_1v8 = 0;
229077d89b08766c878a2594b15d203e513acf952340wwang	int try_sdio = 1;
229177d89b08766c878a2594b15d203e513acf952340wwang	u8 rsp[16];
229277d89b08766c878a2594b15d203e513acf952340wwang	u8 switch_bus_width;
229377d89b08766c878a2594b15d203e513acf952340wwang	u32 voltage = 0;
229477d89b08766c878a2594b15d203e513acf952340wwang	int sd20_mode = 0;
229577d89b08766c878a2594b15d203e513acf952340wwang
229677d89b08766c878a2594b15d203e513acf952340wwang	SET_SD(sd_card);
229777d89b08766c878a2594b15d203e513acf952340wwang
229877d89b08766c878a2594b15d203e513acf952340wwangSwitch_Fail:
229977d89b08766c878a2594b15d203e513acf952340wwang
230077d89b08766c878a2594b15d203e513acf952340wwang	i = 0;
230177d89b08766c878a2594b15d203e513acf952340wwang	j = 0;
230277d89b08766c878a2594b15d203e513acf952340wwang	k = 0;
230377d89b08766c878a2594b15d203e513acf952340wwang	hi_cap_flow = 0;
230477d89b08766c878a2594b15d203e513acf952340wwang
230577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
230677d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
230777d89b08766c878a2594b15d203e513acf952340wwang		goto SD_UNLOCK_ENTRY;
230877d89b08766c878a2594b15d203e513acf952340wwang#endif
230977d89b08766c878a2594b15d203e513acf952340wwang
231077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_prepare_reset(chip);
231177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
231277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
231377d89b08766c878a2594b15d203e513acf952340wwang	}
231477d89b08766c878a2594b15d203e513acf952340wwang
231577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_dummy_clock(chip);
231677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
231777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
231877d89b08766c878a2594b15d203e513acf952340wwang	}
231977d89b08766c878a2594b15d203e513acf952340wwang
232077d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
232177d89b08766c878a2594b15d203e513acf952340wwang		int rty_cnt = 0;
232277d89b08766c878a2594b15d203e513acf952340wwang
232377d89b08766c878a2594b15d203e513acf952340wwang		for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
232477d89b08766c878a2594b15d203e513acf952340wwang			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
232577d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_NO_CARD);
232677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
232777d89b08766c878a2594b15d203e513acf952340wwang			}
232877d89b08766c878a2594b15d203e513acf952340wwang
232977d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5);
233077d89b08766c878a2594b15d203e513acf952340wwang			if (retval == STATUS_SUCCESS) {
2331cddac88f437b0370d3c0ac4c0b2d6c1ff914522dNicolas Kaiser				int func_num = (rsp[1] >> 4) & 0x07;
233277d89b08766c878a2594b15d203e513acf952340wwang				if (func_num) {
233377d89b08766c878a2594b15d203e513acf952340wwang					RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num);
233477d89b08766c878a2594b15d203e513acf952340wwang					chip->sd_io = 1;
233577d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
233677d89b08766c878a2594b15d203e513acf952340wwang				}
233777d89b08766c878a2594b15d203e513acf952340wwang
233877d89b08766c878a2594b15d203e513acf952340wwang				break;
233977d89b08766c878a2594b15d203e513acf952340wwang			}
234077d89b08766c878a2594b15d203e513acf952340wwang
234177d89b08766c878a2594b15d203e513acf952340wwang			sd_init_power(chip);
234277d89b08766c878a2594b15d203e513acf952340wwang
234377d89b08766c878a2594b15d203e513acf952340wwang			sd_dummy_clock(chip);
234477d89b08766c878a2594b15d203e513acf952340wwang		}
234577d89b08766c878a2594b15d203e513acf952340wwang
234677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Normal card!\n");
234777d89b08766c878a2594b15d203e513acf952340wwang	}
234877d89b08766c878a2594b15d203e513acf952340wwang
234977d89b08766c878a2594b15d203e513acf952340wwang	/* Start Initialization Process of SD Card */
235077d89b08766c878a2594b15d203e513acf952340wwangRTY_SD_RST:
235177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
235277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
235377d89b08766c878a2594b15d203e513acf952340wwang	       TRACE_RET(chip, STATUS_FAIL);
235477d89b08766c878a2594b15d203e513acf952340wwang	}
235577d89b08766c878a2594b15d203e513acf952340wwang
235677d89b08766c878a2594b15d203e513acf952340wwang	wait_timeout(20);
235777d89b08766c878a2594b15d203e513acf952340wwang
235877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, SD_RSP_TYPE_R7, rsp, 5);
235977d89b08766c878a2594b15d203e513acf952340wwang	if (retval == STATUS_SUCCESS) {
236077d89b08766c878a2594b15d203e513acf952340wwang		if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) {
236177d89b08766c878a2594b15d203e513acf952340wwang			hi_cap_flow = 1;
236277d89b08766c878a2594b15d203e513acf952340wwang			if (CHECK_PID(chip, 0x5209)) {
236377d89b08766c878a2594b15d203e513acf952340wwang				if (sd20_mode) {
236477d89b08766c878a2594b15d203e513acf952340wwang					voltage = SUPPORT_VOLTAGE |
236577d89b08766c878a2594b15d203e513acf952340wwang						SUPPORT_HIGH_AND_EXTENDED_CAPACITY;
236677d89b08766c878a2594b15d203e513acf952340wwang				} else {
236777d89b08766c878a2594b15d203e513acf952340wwang					voltage = SUPPORT_VOLTAGE |
236877d89b08766c878a2594b15d203e513acf952340wwang						SUPPORT_HIGH_AND_EXTENDED_CAPACITY |
236977d89b08766c878a2594b15d203e513acf952340wwang						SUPPORT_MAX_POWER_PERMANCE | SUPPORT_1V8;
237077d89b08766c878a2594b15d203e513acf952340wwang				}
237177d89b08766c878a2594b15d203e513acf952340wwang			} else {
237277d89b08766c878a2594b15d203e513acf952340wwang				voltage = SUPPORT_VOLTAGE | 0x40000000;
237377d89b08766c878a2594b15d203e513acf952340wwang			}
237477d89b08766c878a2594b15d203e513acf952340wwang		}
237577d89b08766c878a2594b15d203e513acf952340wwang	}
237677d89b08766c878a2594b15d203e513acf952340wwang
237777d89b08766c878a2594b15d203e513acf952340wwang	if (!hi_cap_flow) {
237877d89b08766c878a2594b15d203e513acf952340wwang		voltage = SUPPORT_VOLTAGE;
237977d89b08766c878a2594b15d203e513acf952340wwang
238077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
238177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
238277d89b08766c878a2594b15d203e513acf952340wwang		       TRACE_RET(chip, STATUS_FAIL);
238377d89b08766c878a2594b15d203e513acf952340wwang		}
238477d89b08766c878a2594b15d203e513acf952340wwang
238577d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(20);
238677d89b08766c878a2594b15d203e513acf952340wwang	}
238777d89b08766c878a2594b15d203e513acf952340wwang
238877d89b08766c878a2594b15d203e513acf952340wwang	do {
238977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, NULL, 0);
239077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
239177d89b08766c878a2594b15d203e513acf952340wwang			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
239277d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_NO_CARD);
239377d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
239477d89b08766c878a2594b15d203e513acf952340wwang			}
239577d89b08766c878a2594b15d203e513acf952340wwang
239677d89b08766c878a2594b15d203e513acf952340wwang			j++;
239777d89b08766c878a2594b15d203e513acf952340wwang			if (j < 3) {
239877d89b08766c878a2594b15d203e513acf952340wwang				goto RTY_SD_RST;
239977d89b08766c878a2594b15d203e513acf952340wwang			} else {
240077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
240177d89b08766c878a2594b15d203e513acf952340wwang			}
240277d89b08766c878a2594b15d203e513acf952340wwang		}
240377d89b08766c878a2594b15d203e513acf952340wwang
240477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5);
240577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
240677d89b08766c878a2594b15d203e513acf952340wwang			k++;
240777d89b08766c878a2594b15d203e513acf952340wwang			if (k < 3) {
240877d89b08766c878a2594b15d203e513acf952340wwang				goto RTY_SD_RST;
240977d89b08766c878a2594b15d203e513acf952340wwang			} else {
241077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
241177d89b08766c878a2594b15d203e513acf952340wwang			}
241277d89b08766c878a2594b15d203e513acf952340wwang		}
241377d89b08766c878a2594b15d203e513acf952340wwang
241477d89b08766c878a2594b15d203e513acf952340wwang		i++;
241577d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(20);
241677d89b08766c878a2594b15d203e513acf952340wwang	} while (!(rsp[1] & 0x80) && (i < 255));
241777d89b08766c878a2594b15d203e513acf952340wwang
241877d89b08766c878a2594b15d203e513acf952340wwang	if (i == 255) {
241977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
242077d89b08766c878a2594b15d203e513acf952340wwang	}
242177d89b08766c878a2594b15d203e513acf952340wwang
242277d89b08766c878a2594b15d203e513acf952340wwang	if (hi_cap_flow) {
242377d89b08766c878a2594b15d203e513acf952340wwang		if (rsp[1] & 0x40) {
242477d89b08766c878a2594b15d203e513acf952340wwang			SET_SD_HCXC(sd_card);
242577d89b08766c878a2594b15d203e513acf952340wwang		} else {
242677d89b08766c878a2594b15d203e513acf952340wwang			CLR_SD_HCXC(sd_card);
242777d89b08766c878a2594b15d203e513acf952340wwang		}
242877d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode) {
242977d89b08766c878a2594b15d203e513acf952340wwang			support_1v8 = (rsp[1] & 0x01) ? 1 : 0;
243077d89b08766c878a2594b15d203e513acf952340wwang		} else {
243177d89b08766c878a2594b15d203e513acf952340wwang			support_1v8 = 0;
243277d89b08766c878a2594b15d203e513acf952340wwang		}
243377d89b08766c878a2594b15d203e513acf952340wwang	} else {
243477d89b08766c878a2594b15d203e513acf952340wwang		CLR_SD_HCXC(sd_card);
243577d89b08766c878a2594b15d203e513acf952340wwang		support_1v8 = 0;
243677d89b08766c878a2594b15d203e513acf952340wwang	}
243777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("support_1v8 = %d\n", support_1v8);
243877d89b08766c878a2594b15d203e513acf952340wwang
243977d89b08766c878a2594b15d203e513acf952340wwang	if (support_1v8) {
244077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_voltage_switch(chip);
244177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
244277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
244377d89b08766c878a2594b15d203e513acf952340wwang		}
244477d89b08766c878a2594b15d203e513acf952340wwang	}
244577d89b08766c878a2594b15d203e513acf952340wwang
244677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
244777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
244877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
244977d89b08766c878a2594b15d203e513acf952340wwang	}
245077d89b08766c878a2594b15d203e513acf952340wwang
245177d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
245277d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5);
245377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
245477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
245577d89b08766c878a2594b15d203e513acf952340wwang		}
245677d89b08766c878a2594b15d203e513acf952340wwang
245777d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_addr = (u32)rsp[1] << 24;
245877d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_addr += (u32)rsp[2] << 16;
245977d89b08766c878a2594b15d203e513acf952340wwang
246077d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_addr) {
246177d89b08766c878a2594b15d203e513acf952340wwang			break;
246277d89b08766c878a2594b15d203e513acf952340wwang		}
246377d89b08766c878a2594b15d203e513acf952340wwang	}
246477d89b08766c878a2594b15d203e513acf952340wwang
246577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_check_csd(chip, 1);
246677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
246777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
246877d89b08766c878a2594b15d203e513acf952340wwang	}
246977d89b08766c878a2594b15d203e513acf952340wwang
247077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_select_card(chip, 1);
247177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
247277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
247377d89b08766c878a2594b15d203e513acf952340wwang	}
247477d89b08766c878a2594b15d203e513acf952340wwang
247577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
247677d89b08766c878a2594b15d203e513acf952340wwangSD_UNLOCK_ENTRY:
247777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_update_lock_status(chip);
247877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
247977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
248077d89b08766c878a2594b15d203e513acf952340wwang	}
248177d89b08766c878a2594b15d203e513acf952340wwang
248277d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_lock_status & SD_LOCKED) {
248377d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
248477d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_SUCCESS;
248577d89b08766c878a2594b15d203e513acf952340wwang	} else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
248677d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status &= ~SD_PWD_EXIST;
248777d89b08766c878a2594b15d203e513acf952340wwang	}
248877d89b08766c878a2594b15d203e513acf952340wwang#endif
248977d89b08766c878a2594b15d203e513acf952340wwang
249077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
249177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
249277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
249377d89b08766c878a2594b15d203e513acf952340wwang	}
249477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0);
249577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
249677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
249777d89b08766c878a2594b15d203e513acf952340wwang	}
249877d89b08766c878a2594b15d203e513acf952340wwang
249977d89b08766c878a2594b15d203e513acf952340wwang	if (support_1v8) {
250077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
250177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
250277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
250377d89b08766c878a2594b15d203e513acf952340wwang		}
250477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
250577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
250677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
250777d89b08766c878a2594b15d203e513acf952340wwang		}
250877d89b08766c878a2594b15d203e513acf952340wwang
250977d89b08766c878a2594b15d203e513acf952340wwang		switch_bus_width = SD_BUS_WIDTH_4;
251077d89b08766c878a2594b15d203e513acf952340wwang	} else {
251177d89b08766c878a2594b15d203e513acf952340wwang		switch_bus_width = SD_BUS_WIDTH_1;
251277d89b08766c878a2594b15d203e513acf952340wwang	}
251377d89b08766c878a2594b15d203e513acf952340wwang
251477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
251577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
251677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
251777d89b08766c878a2594b15d203e513acf952340wwang	}
251877d89b08766c878a2594b15d203e513acf952340wwang
251977d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
252077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
252177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
252277d89b08766c878a2594b15d203e513acf952340wwang	}
252377d89b08766c878a2594b15d203e513acf952340wwang
252477d89b08766c878a2594b15d203e513acf952340wwang	if (!(sd_card->raw_csd[4] & 0x40))
252577d89b08766c878a2594b15d203e513acf952340wwang		sd_dont_switch = 1;
252677d89b08766c878a2594b15d203e513acf952340wwang
252777d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_dont_switch) {
25282d2322b269c2524996a259024f82c7e318719696wwang		if (sd20_mode) {
25292d2322b269c2524996a259024f82c7e318719696wwang			/* Set sd_switch_fail here, because we needn't
25302d2322b269c2524996a259024f82c7e318719696wwang			 * switch to UHS mode
25312d2322b269c2524996a259024f82c7e318719696wwang			 */
25322d2322b269c2524996a259024f82c7e318719696wwang			sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
25332d2322b269c2524996a259024f82c7e318719696wwang				DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
25342d2322b269c2524996a259024f82c7e318719696wwang		}
25352d2322b269c2524996a259024f82c7e318719696wwang
25362d2322b269c2524996a259024f82c7e318719696wwang		/* Check the card whether follow SD1.1 spec or higher */
253777d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_check_spec(chip, switch_bus_width);
253877d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS) {
253977d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_switch_function(chip, switch_bus_width);
254077d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
254177d89b08766c878a2594b15d203e513acf952340wwang				if (CHECK_PID(chip, 0x5209)) {
254277d89b08766c878a2594b15d203e513acf952340wwang					sd_change_bank_voltage(chip, SD_IO_3V3);
254377d89b08766c878a2594b15d203e513acf952340wwang				}
254477d89b08766c878a2594b15d203e513acf952340wwang				sd_init_power(chip);
254577d89b08766c878a2594b15d203e513acf952340wwang				sd_dont_switch = 1;
254677d89b08766c878a2594b15d203e513acf952340wwang				try_sdio = 0;
254777d89b08766c878a2594b15d203e513acf952340wwang
254877d89b08766c878a2594b15d203e513acf952340wwang				goto Switch_Fail;
254977d89b08766c878a2594b15d203e513acf952340wwang			}
255077d89b08766c878a2594b15d203e513acf952340wwang		} else {
255177d89b08766c878a2594b15d203e513acf952340wwang			if (support_1v8) {
255277d89b08766c878a2594b15d203e513acf952340wwang				if (CHECK_PID(chip, 0x5209)) {
255377d89b08766c878a2594b15d203e513acf952340wwang					sd_change_bank_voltage(chip, SD_IO_3V3);
255477d89b08766c878a2594b15d203e513acf952340wwang				}
255577d89b08766c878a2594b15d203e513acf952340wwang				sd_init_power(chip);
255677d89b08766c878a2594b15d203e513acf952340wwang				sd_dont_switch = 1;
255777d89b08766c878a2594b15d203e513acf952340wwang				try_sdio = 0;
255877d89b08766c878a2594b15d203e513acf952340wwang
255977d89b08766c878a2594b15d203e513acf952340wwang				goto Switch_Fail;
256077d89b08766c878a2594b15d203e513acf952340wwang			}
256177d89b08766c878a2594b15d203e513acf952340wwang		}
256277d89b08766c878a2594b15d203e513acf952340wwang	}
256377d89b08766c878a2594b15d203e513acf952340wwang
256477d89b08766c878a2594b15d203e513acf952340wwang	if (!support_1v8) {
256577d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
256677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
256777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
256877d89b08766c878a2594b15d203e513acf952340wwang		}
256977d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
257077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
257177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
257277d89b08766c878a2594b15d203e513acf952340wwang		}
257377d89b08766c878a2594b15d203e513acf952340wwang	}
257477d89b08766c878a2594b15d203e513acf952340wwang
257577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
257677d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
257777d89b08766c878a2594b15d203e513acf952340wwang#endif
257877d89b08766c878a2594b15d203e513acf952340wwang
25792d2322b269c2524996a259024f82c7e318719696wwang	if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
258077d89b08766c878a2594b15d203e513acf952340wwang		int read_lba0 = 1;
258177d89b08766c878a2594b15d203e513acf952340wwang
258277d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_1v8);
258377d89b08766c878a2594b15d203e513acf952340wwang
258477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_set_init_para(chip);
258577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
258677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
258777d89b08766c878a2594b15d203e513acf952340wwang		}
258877d89b08766c878a2594b15d203e513acf952340wwang
258977d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_DDR50(sd_card)) {
259077d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_ddr_tuning(chip);
259177d89b08766c878a2594b15d203e513acf952340wwang		} else {
259277d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_sdr_tuning(chip);
259377d89b08766c878a2594b15d203e513acf952340wwang		}
259477d89b08766c878a2594b15d203e513acf952340wwang
259577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
259677d89b08766c878a2594b15d203e513acf952340wwang			if (sd20_mode) {
259777d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
259877d89b08766c878a2594b15d203e513acf952340wwang			} else {
259977d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_init_power(chip);
260077d89b08766c878a2594b15d203e513acf952340wwang				if (retval != STATUS_SUCCESS) {
260177d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
260277d89b08766c878a2594b15d203e513acf952340wwang				}
260377d89b08766c878a2594b15d203e513acf952340wwang				try_sdio = 0;
260477d89b08766c878a2594b15d203e513acf952340wwang				sd20_mode = 1;
260577d89b08766c878a2594b15d203e513acf952340wwang				goto Switch_Fail;
260677d89b08766c878a2594b15d203e513acf952340wwang			}
260777d89b08766c878a2594b15d203e513acf952340wwang		}
260877d89b08766c878a2594b15d203e513acf952340wwang
260977d89b08766c878a2594b15d203e513acf952340wwang		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
261077d89b08766c878a2594b15d203e513acf952340wwang
261177d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD_DDR50(sd_card)) {
261277d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
261377d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
261477d89b08766c878a2594b15d203e513acf952340wwang				read_lba0 = 0;
261577d89b08766c878a2594b15d203e513acf952340wwang			}
261677d89b08766c878a2594b15d203e513acf952340wwang		}
261777d89b08766c878a2594b15d203e513acf952340wwang
261877d89b08766c878a2594b15d203e513acf952340wwang		if (read_lba0) {
261977d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_read_lba0(chip);
262077d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
262177d89b08766c878a2594b15d203e513acf952340wwang				if (sd20_mode) {
262277d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
262377d89b08766c878a2594b15d203e513acf952340wwang				} else {
262477d89b08766c878a2594b15d203e513acf952340wwang					retval = sd_init_power(chip);
262577d89b08766c878a2594b15d203e513acf952340wwang					if (retval != STATUS_SUCCESS) {
262677d89b08766c878a2594b15d203e513acf952340wwang						TRACE_RET(chip, STATUS_FAIL);
262777d89b08766c878a2594b15d203e513acf952340wwang					}
262877d89b08766c878a2594b15d203e513acf952340wwang					try_sdio = 0;
262977d89b08766c878a2594b15d203e513acf952340wwang					sd20_mode = 1;
263077d89b08766c878a2594b15d203e513acf952340wwang					goto Switch_Fail;
263177d89b08766c878a2594b15d203e513acf952340wwang				}
263277d89b08766c878a2594b15d203e513acf952340wwang			}
263377d89b08766c878a2594b15d203e513acf952340wwang		}
263477d89b08766c878a2594b15d203e513acf952340wwang	}
263577d89b08766c878a2594b15d203e513acf952340wwang
263677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_check_wp_state(chip);
263777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
263877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
263977d89b08766c878a2594b15d203e513acf952340wwang	}
264077d89b08766c878a2594b15d203e513acf952340wwang
264177d89b08766c878a2594b15d203e513acf952340wwang	chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
264277d89b08766c878a2594b15d203e513acf952340wwang
264377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
264477d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
264577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
264677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
264777d89b08766c878a2594b15d203e513acf952340wwang	}
264877d89b08766c878a2594b15d203e513acf952340wwang#endif
264977d89b08766c878a2594b15d203e513acf952340wwang
265077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
265177d89b08766c878a2594b15d203e513acf952340wwang}
265277d89b08766c878a2594b15d203e513acf952340wwang
265377d89b08766c878a2594b15d203e513acf952340wwang
265477d89b08766c878a2594b15d203e513acf952340wwangstatic int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
265577d89b08766c878a2594b15d203e513acf952340wwang{
265677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
265777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
265877d89b08766c878a2594b15d203e513acf952340wwang	u8 buf[8] = {0}, bus_width, *ptr;
265977d89b08766c878a2594b15d203e513acf952340wwang	u16 byte_cnt;
266077d89b08766c878a2594b15d203e513acf952340wwang	int len;
266177d89b08766c878a2594b15d203e513acf952340wwang
266277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0);
266377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
26642b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		TRACE_RET(chip, SWITCH_FAIL);
266577d89b08766c878a2594b15d203e513acf952340wwang	}
266677d89b08766c878a2594b15d203e513acf952340wwang
266777d89b08766c878a2594b15d203e513acf952340wwang	if (width == MMC_8BIT_BUS) {
266877d89b08766c878a2594b15d203e513acf952340wwang		buf[0] = 0x55;
266977d89b08766c878a2594b15d203e513acf952340wwang		buf[1] = 0xAA;
267077d89b08766c878a2594b15d203e513acf952340wwang		len = 8;
267177d89b08766c878a2594b15d203e513acf952340wwang		byte_cnt = 8;
267277d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_8;
267377d89b08766c878a2594b15d203e513acf952340wwang	} else {
267477d89b08766c878a2594b15d203e513acf952340wwang		buf[0] = 0x5A;
267577d89b08766c878a2594b15d203e513acf952340wwang		len = 4;
267677d89b08766c878a2594b15d203e513acf952340wwang		byte_cnt = 4;
267777d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_4;
267877d89b08766c878a2594b15d203e513acf952340wwang	}
267977d89b08766c878a2594b15d203e513acf952340wwang
268077d89b08766c878a2594b15d203e513acf952340wwang	if (!CHECK_PID(chip, 0x5209)) {
26812b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
26822b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		if (retval != STATUS_SUCCESS)
26832b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			TRACE_RET(chip, SWITCH_ERR);
268477d89b08766c878a2594b15d203e513acf952340wwang	}
268577d89b08766c878a2594b15d203e513acf952340wwang
268677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
268777d89b08766c878a2594b15d203e513acf952340wwang			NULL, 0, byte_cnt, 1, bus_width, buf, len, 100);
268877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
268977d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209)) {
269077d89b08766c878a2594b15d203e513acf952340wwang			u8 val1 = 0, val2 = 0;
269177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_read_register(chip, REG_SD_STAT1, &val1);
269277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_read_register(chip, REG_SD_STAT2, &val2);
269377d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
269477d89b08766c878a2594b15d203e513acf952340wwang			if ((val1 & 0xE0) || val2) {
26952b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				TRACE_RET(chip, SWITCH_ERR);
269677d89b08766c878a2594b15d203e513acf952340wwang			}
269777d89b08766c878a2594b15d203e513acf952340wwang		} else {
269877d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
269977d89b08766c878a2594b15d203e513acf952340wwang			rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
27002b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			TRACE_RET(chip, SWITCH_ERR);
270177d89b08766c878a2594b15d203e513acf952340wwang		}
270277d89b08766c878a2594b15d203e513acf952340wwang	}
270377d89b08766c878a2594b15d203e513acf952340wwang
270477d89b08766c878a2594b15d203e513acf952340wwang	if (!CHECK_PID(chip, 0x5209)) {
27052b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
27062b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		if (retval != STATUS_SUCCESS)
27072b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			TRACE_RET(chip, SWITCH_ERR);
270877d89b08766c878a2594b15d203e513acf952340wwang	}
270977d89b08766c878a2594b15d203e513acf952340wwang
271077d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R);
271177d89b08766c878a2594b15d203e513acf952340wwang
271277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
271377d89b08766c878a2594b15d203e513acf952340wwang
271477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
271577d89b08766c878a2594b15d203e513acf952340wwang
271677d89b08766c878a2594b15d203e513acf952340wwang	if (width == MMC_8BIT_BUS) {
271777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x08);
271877d89b08766c878a2594b15d203e513acf952340wwang	} else {
271977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x04);
272077d89b08766c878a2594b15d203e513acf952340wwang	}
272177d89b08766c878a2594b15d203e513acf952340wwang
272277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
272377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
272477d89b08766c878a2594b15d203e513acf952340wwang
272577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
272677d89b08766c878a2594b15d203e513acf952340wwang			SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
272777d89b08766c878a2594b15d203e513acf952340wwang			SD_CHECK_CRC7 | SD_RSP_LEN_6);
272877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
272977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
273077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
273177d89b08766c878a2594b15d203e513acf952340wwang
273277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
273377d89b08766c878a2594b15d203e513acf952340wwang	if (width == MMC_8BIT_BUS) {
273477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
273577d89b08766c878a2594b15d203e513acf952340wwang	}
273677d89b08766c878a2594b15d203e513acf952340wwang
273777d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, 100);
273877d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
273977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
27402b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		TRACE_RET(chip, SWITCH_ERR);
274177d89b08766c878a2594b15d203e513acf952340wwang	}
274277d89b08766c878a2594b15d203e513acf952340wwang
274377d89b08766c878a2594b15d203e513acf952340wwang	ptr = rtsx_get_cmd_data(chip) + 1;
274477d89b08766c878a2594b15d203e513acf952340wwang
274577d89b08766c878a2594b15d203e513acf952340wwang	if (width == MMC_8BIT_BUS) {
274677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", ptr[0], ptr[1]);
274777d89b08766c878a2594b15d203e513acf952340wwang		if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) {
274877d89b08766c878a2594b15d203e513acf952340wwang			u8 rsp[5];
274977d89b08766c878a2594b15d203e513acf952340wwang			u32 arg;
275077d89b08766c878a2594b15d203e513acf952340wwang
275177d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_DDR52(sd_card)) {
275277d89b08766c878a2594b15d203e513acf952340wwang				arg = 0x03B70600;
275377d89b08766c878a2594b15d203e513acf952340wwang			} else {
275477d89b08766c878a2594b15d203e513acf952340wwang				arg = 0x03B70200;
275577d89b08766c878a2594b15d203e513acf952340wwang			}
275677d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
275777d89b08766c878a2594b15d203e513acf952340wwang			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
27582b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				return SWITCH_SUCCESS;
275977d89b08766c878a2594b15d203e513acf952340wwang			}
276077d89b08766c878a2594b15d203e513acf952340wwang		}
276177d89b08766c878a2594b15d203e513acf952340wwang	} else {
276277d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
276377d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[0] == 0xA5) {
276477d89b08766c878a2594b15d203e513acf952340wwang			u8 rsp[5];
276577d89b08766c878a2594b15d203e513acf952340wwang			u32 arg;
276677d89b08766c878a2594b15d203e513acf952340wwang
276777d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_DDR52(sd_card)) {
276877d89b08766c878a2594b15d203e513acf952340wwang				arg = 0x03B70500;
276977d89b08766c878a2594b15d203e513acf952340wwang			} else {
277077d89b08766c878a2594b15d203e513acf952340wwang				arg = 0x03B70100;
277177d89b08766c878a2594b15d203e513acf952340wwang			}
277277d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
277377d89b08766c878a2594b15d203e513acf952340wwang			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
27742b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				return SWITCH_SUCCESS;
277577d89b08766c878a2594b15d203e513acf952340wwang			}
277677d89b08766c878a2594b15d203e513acf952340wwang		}
277777d89b08766c878a2594b15d203e513acf952340wwang	}
277877d89b08766c878a2594b15d203e513acf952340wwang
27792b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang	TRACE_RET(chip, SWITCH_FAIL);
278077d89b08766c878a2594b15d203e513acf952340wwang}
278177d89b08766c878a2594b15d203e513acf952340wwang
278277d89b08766c878a2594b15d203e513acf952340wwang
278377d89b08766c878a2594b15d203e513acf952340wwangstatic int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
278477d89b08766c878a2594b15d203e513acf952340wwang{
278577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
278677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
278777d89b08766c878a2594b15d203e513acf952340wwang	u8 *ptr, card_type, card_type_mask = 0;
278877d89b08766c878a2594b15d203e513acf952340wwang
278977d89b08766c878a2594b15d203e513acf952340wwang	CLR_MMC_HS(sd_card);
279077d89b08766c878a2594b15d203e513acf952340wwang
279177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD);
279277d89b08766c878a2594b15d203e513acf952340wwang
279377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
279477d89b08766c878a2594b15d203e513acf952340wwang
279577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | SEND_EXT_CSD);
279677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
279777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
279877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
279977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
280077d89b08766c878a2594b15d203e513acf952340wwang
280177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
280277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
280377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
280477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
280577d89b08766c878a2594b15d203e513acf952340wwang
280677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
280777d89b08766c878a2594b15d203e513acf952340wwang			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
280877d89b08766c878a2594b15d203e513acf952340wwang			SD_CHECK_CRC7 | SD_RSP_LEN_6);
280977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
281077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
281177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
281277d89b08766c878a2594b15d203e513acf952340wwang
281377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
281477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
281577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
281677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
281777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
281877d89b08766c878a2594b15d203e513acf952340wwang
281977d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, 1000);
282077d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
282177d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
282277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
282377d89b08766c878a2594b15d203e513acf952340wwang			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
282477d89b08766c878a2594b15d203e513acf952340wwang					SD_RSP_TYPE_R1, NULL, 0);
282577d89b08766c878a2594b15d203e513acf952340wwang		}
282677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
282777d89b08766c878a2594b15d203e513acf952340wwang	}
282877d89b08766c878a2594b15d203e513acf952340wwang
282977d89b08766c878a2594b15d203e513acf952340wwang	ptr = rtsx_get_cmd_data(chip);
283077d89b08766c878a2594b15d203e513acf952340wwang	if (ptr[0] & SD_TRANSFER_ERR) {
283177d89b08766c878a2594b15d203e513acf952340wwang		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
283277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
283377d89b08766c878a2594b15d203e513acf952340wwang	}
283477d89b08766c878a2594b15d203e513acf952340wwang
283577d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_MMC_SECTOR_MODE(sd_card)) {
283677d89b08766c878a2594b15d203e513acf952340wwang		sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
283777d89b08766c878a2594b15d203e513acf952340wwang			((u32)ptr[3] << 8) | ((u32)ptr[2]);
283877d89b08766c878a2594b15d203e513acf952340wwang	}
283977d89b08766c878a2594b15d203e513acf952340wwang
284077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
284177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
284277d89b08766c878a2594b15d203e513acf952340wwang		if (!(sd_card->sd_lock_status & SD_SDR_RST) &&
284377d89b08766c878a2594b15d203e513acf952340wwang				(chip->sd_ctl & SUPPORT_MMC_DDR_MODE)) {
284477d89b08766c878a2594b15d203e513acf952340wwang			card_type_mask = 0x07;
284577d89b08766c878a2594b15d203e513acf952340wwang		} else {
284677d89b08766c878a2594b15d203e513acf952340wwang			card_type_mask = 0x03;
284777d89b08766c878a2594b15d203e513acf952340wwang		}
284877d89b08766c878a2594b15d203e513acf952340wwang#else
284977d89b08766c878a2594b15d203e513acf952340wwang		if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE) {
285077d89b08766c878a2594b15d203e513acf952340wwang			card_type_mask = 0x07;
285177d89b08766c878a2594b15d203e513acf952340wwang		} else {
285277d89b08766c878a2594b15d203e513acf952340wwang			card_type_mask = 0x03;
285377d89b08766c878a2594b15d203e513acf952340wwang		}
285477d89b08766c878a2594b15d203e513acf952340wwang#endif
285577d89b08766c878a2594b15d203e513acf952340wwang	} else {
285677d89b08766c878a2594b15d203e513acf952340wwang		card_type_mask = 0x03;
285777d89b08766c878a2594b15d203e513acf952340wwang	}
285877d89b08766c878a2594b15d203e513acf952340wwang	card_type = ptr[1] & card_type_mask;
285977d89b08766c878a2594b15d203e513acf952340wwang	if (card_type) {
286077d89b08766c878a2594b15d203e513acf952340wwang		u8 rsp[5];
286177d89b08766c878a2594b15d203e513acf952340wwang
286277d89b08766c878a2594b15d203e513acf952340wwang		if (card_type & 0x04) {
286377d89b08766c878a2594b15d203e513acf952340wwang			if (switch_ddr) {
286477d89b08766c878a2594b15d203e513acf952340wwang				SET_MMC_DDR52(sd_card);
286577d89b08766c878a2594b15d203e513acf952340wwang			} else {
286677d89b08766c878a2594b15d203e513acf952340wwang				SET_MMC_52M(sd_card);
286777d89b08766c878a2594b15d203e513acf952340wwang			}
286877d89b08766c878a2594b15d203e513acf952340wwang		} else if (card_type & 0x02) {
286977d89b08766c878a2594b15d203e513acf952340wwang			SET_MMC_52M(sd_card);
287077d89b08766c878a2594b15d203e513acf952340wwang		} else {
287177d89b08766c878a2594b15d203e513acf952340wwang			SET_MMC_26M(sd_card);
287277d89b08766c878a2594b15d203e513acf952340wwang		}
287377d89b08766c878a2594b15d203e513acf952340wwang
287477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SWITCH,
287577d89b08766c878a2594b15d203e513acf952340wwang				0x03B90100, SD_RSP_TYPE_R1b, rsp, 5);
287677d89b08766c878a2594b15d203e513acf952340wwang		if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) {
287777d89b08766c878a2594b15d203e513acf952340wwang			CLR_MMC_HS(sd_card);
287877d89b08766c878a2594b15d203e513acf952340wwang		}
287977d89b08766c878a2594b15d203e513acf952340wwang	}
288077d89b08766c878a2594b15d203e513acf952340wwang
288177d89b08766c878a2594b15d203e513acf952340wwang	sd_choose_proper_clock(chip);
288277d89b08766c878a2594b15d203e513acf952340wwang	retval = switch_clock(chip, sd_card->sd_clock);
288377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
288477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
288577d89b08766c878a2594b15d203e513acf952340wwang	}
288677d89b08766c878a2594b15d203e513acf952340wwang
28872b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang	/* Test Bus Procedure */
28882b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang	retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
28892b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang	if (retval == SWITCH_SUCCESS) {
289077d89b08766c878a2594b15d203e513acf952340wwang		SET_MMC_8BIT(sd_card);
289177d89b08766c878a2594b15d203e513acf952340wwang		chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
289277d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
289377d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
289477d89b08766c878a2594b15d203e513acf952340wwang#endif
28952b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang	} else if (retval == SWITCH_FAIL) {
28962b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
28972b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		if (retval == SWITCH_SUCCESS) {
28982b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			SET_MMC_4BIT(sd_card);
28992b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
290077d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
29012b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
290277d89b08766c878a2594b15d203e513acf952340wwang#endif
29032b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		} else if (retval == SWITCH_FAIL) {
29042b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			CLR_MMC_8BIT(sd_card);
29052b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			CLR_MMC_4BIT(sd_card);
29062b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		} else {
29072b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			TRACE_RET(chip, STATUS_FAIL);
29082b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		}
290977d89b08766c878a2594b15d203e513acf952340wwang	} else {
29102b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang		TRACE_RET(chip, STATUS_FAIL);
291177d89b08766c878a2594b15d203e513acf952340wwang	}
291277d89b08766c878a2594b15d203e513acf952340wwang
291377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
291477d89b08766c878a2594b15d203e513acf952340wwang}
291577d89b08766c878a2594b15d203e513acf952340wwang
291677d89b08766c878a2594b15d203e513acf952340wwang
291777d89b08766c878a2594b15d203e513acf952340wwangstatic int reset_mmc(struct rtsx_chip *chip)
291877d89b08766c878a2594b15d203e513acf952340wwang{
291977d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
292077d89b08766c878a2594b15d203e513acf952340wwang	int retval, i = 0, j = 0, k = 0;
292177d89b08766c878a2594b15d203e513acf952340wwang	int switch_ddr = 1;
292277d89b08766c878a2594b15d203e513acf952340wwang	u8 rsp[16];
292377d89b08766c878a2594b15d203e513acf952340wwang	u8 spec_ver = 0;
292477d89b08766c878a2594b15d203e513acf952340wwang	u32 temp;
292577d89b08766c878a2594b15d203e513acf952340wwang
292677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
292777d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
292877d89b08766c878a2594b15d203e513acf952340wwang		goto MMC_UNLOCK_ENTRY;
292977d89b08766c878a2594b15d203e513acf952340wwang#endif
293077d89b08766c878a2594b15d203e513acf952340wwang
29312b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwangSwitch_Fail:
293277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_prepare_reset(chip);
293377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
293477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, retval);
293577d89b08766c878a2594b15d203e513acf952340wwang	}
293677d89b08766c878a2594b15d203e513acf952340wwang
293777d89b08766c878a2594b15d203e513acf952340wwang	SET_MMC(sd_card);
293877d89b08766c878a2594b15d203e513acf952340wwang
293977d89b08766c878a2594b15d203e513acf952340wwangRTY_MMC_RST:
294077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
294177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
294277d89b08766c878a2594b15d203e513acf952340wwang	       TRACE_RET(chip, STATUS_FAIL);
294377d89b08766c878a2594b15d203e513acf952340wwang	}
294477d89b08766c878a2594b15d203e513acf952340wwang
294577d89b08766c878a2594b15d203e513acf952340wwang	do {
294677d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
294777d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_NO_CARD);
294877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
294977d89b08766c878a2594b15d203e513acf952340wwang		}
295077d89b08766c878a2594b15d203e513acf952340wwang
295177d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
295277d89b08766c878a2594b15d203e513acf952340wwang				(SUPPORT_VOLTAGE|0x40000000), SD_RSP_TYPE_R3, rsp, 5);
295377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
295477d89b08766c878a2594b15d203e513acf952340wwang			if (sd_check_err_code(chip, SD_BUSY) || sd_check_err_code(chip, SD_TO_ERR)) {
295577d89b08766c878a2594b15d203e513acf952340wwang				k++;
295677d89b08766c878a2594b15d203e513acf952340wwang				if (k < 20) {
295777d89b08766c878a2594b15d203e513acf952340wwang					sd_clr_err_code(chip);
295877d89b08766c878a2594b15d203e513acf952340wwang					goto RTY_MMC_RST;
295977d89b08766c878a2594b15d203e513acf952340wwang				} else {
296077d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
296177d89b08766c878a2594b15d203e513acf952340wwang				}
296277d89b08766c878a2594b15d203e513acf952340wwang			} else {
296377d89b08766c878a2594b15d203e513acf952340wwang				j++;
296477d89b08766c878a2594b15d203e513acf952340wwang				if (j < 100) {
296577d89b08766c878a2594b15d203e513acf952340wwang					sd_clr_err_code(chip);
296677d89b08766c878a2594b15d203e513acf952340wwang					goto RTY_MMC_RST;
296777d89b08766c878a2594b15d203e513acf952340wwang				} else {
296877d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
296977d89b08766c878a2594b15d203e513acf952340wwang				}
297077d89b08766c878a2594b15d203e513acf952340wwang			}
297177d89b08766c878a2594b15d203e513acf952340wwang		}
297277d89b08766c878a2594b15d203e513acf952340wwang
297377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(20);
297477d89b08766c878a2594b15d203e513acf952340wwang		i++;
297577d89b08766c878a2594b15d203e513acf952340wwang	} while (!(rsp[1] & 0x80) && (i < 255));
297677d89b08766c878a2594b15d203e513acf952340wwang
297777d89b08766c878a2594b15d203e513acf952340wwang	if (i == 255) {
297877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
297977d89b08766c878a2594b15d203e513acf952340wwang	}
298077d89b08766c878a2594b15d203e513acf952340wwang
298177d89b08766c878a2594b15d203e513acf952340wwang	if ((rsp[1] & 0x60) == 0x40) {
298277d89b08766c878a2594b15d203e513acf952340wwang		SET_MMC_SECTOR_MODE(sd_card);
298377d89b08766c878a2594b15d203e513acf952340wwang	} else {
298477d89b08766c878a2594b15d203e513acf952340wwang		CLR_MMC_SECTOR_MODE(sd_card);
298577d89b08766c878a2594b15d203e513acf952340wwang	}
298677d89b08766c878a2594b15d203e513acf952340wwang
298777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
298877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
298977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
299077d89b08766c878a2594b15d203e513acf952340wwang	}
299177d89b08766c878a2594b15d203e513acf952340wwang
299277d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_addr = 0x00100000;
299377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, SD_RSP_TYPE_R6, rsp, 5);
299477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
299577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
299677d89b08766c878a2594b15d203e513acf952340wwang	}
299777d89b08766c878a2594b15d203e513acf952340wwang
299877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_check_csd(chip, 1);
299977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
300077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
300177d89b08766c878a2594b15d203e513acf952340wwang	}
300277d89b08766c878a2594b15d203e513acf952340wwang
300377d89b08766c878a2594b15d203e513acf952340wwang	spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
300477d89b08766c878a2594b15d203e513acf952340wwang
300577d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_select_card(chip, 1);
300677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
300777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
300877d89b08766c878a2594b15d203e513acf952340wwang	}
300977d89b08766c878a2594b15d203e513acf952340wwang
301077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
301177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
301277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
301377d89b08766c878a2594b15d203e513acf952340wwang	}
301477d89b08766c878a2594b15d203e513acf952340wwang
301577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
301677d89b08766c878a2594b15d203e513acf952340wwangMMC_UNLOCK_ENTRY:
301777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_update_lock_status(chip);
301877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
301977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
302077d89b08766c878a2594b15d203e513acf952340wwang	}
302177d89b08766c878a2594b15d203e513acf952340wwang#endif
302277d89b08766c878a2594b15d203e513acf952340wwang
302377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
302477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
302577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
302677d89b08766c878a2594b15d203e513acf952340wwang	}
302777d89b08766c878a2594b15d203e513acf952340wwang
302877d89b08766c878a2594b15d203e513acf952340wwang	chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
302977d89b08766c878a2594b15d203e513acf952340wwang
303077d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->mmc_dont_switch_bus) {
303177d89b08766c878a2594b15d203e513acf952340wwang		if (spec_ver == 4) {
30322b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			/* MMC 4.x Cards */
30332b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			retval = mmc_switch_timing_bus(chip, switch_ddr);
30342b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			if (retval != STATUS_SUCCESS) {
30352b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				retval = sd_init_power(chip);
30362b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				if (retval != STATUS_SUCCESS)
30372b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang					TRACE_RET(chip, STATUS_FAIL);
30382b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				sd_card->mmc_dont_switch_bus = 1;
30392b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				TRACE_GOTO(chip, Switch_Fail);
30402b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang			}
304177d89b08766c878a2594b15d203e513acf952340wwang		}
304277d89b08766c878a2594b15d203e513acf952340wwang
304377d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
304477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
304577d89b08766c878a2594b15d203e513acf952340wwang		}
304677d89b08766c878a2594b15d203e513acf952340wwang
304777d89b08766c878a2594b15d203e513acf952340wwang		if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
304877d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_set_init_para(chip);
304977d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
305077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
305177d89b08766c878a2594b15d203e513acf952340wwang			}
305277d89b08766c878a2594b15d203e513acf952340wwang
305377d89b08766c878a2594b15d203e513acf952340wwang			retval = mmc_ddr_tuning(chip);
305477d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
305577d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_init_power(chip);
305677d89b08766c878a2594b15d203e513acf952340wwang				if (retval != STATUS_SUCCESS) {
305777d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
305877d89b08766c878a2594b15d203e513acf952340wwang				}
305977d89b08766c878a2594b15d203e513acf952340wwang				switch_ddr = 0;
30602b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang				TRACE_GOTO(chip, Switch_Fail);
306177d89b08766c878a2594b15d203e513acf952340wwang			}
306277d89b08766c878a2594b15d203e513acf952340wwang
306377d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
306477d89b08766c878a2594b15d203e513acf952340wwang			if (retval == STATUS_SUCCESS) {
306577d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_read_lba0(chip);
306677d89b08766c878a2594b15d203e513acf952340wwang				if (retval != STATUS_SUCCESS) {
306777d89b08766c878a2594b15d203e513acf952340wwang					retval = sd_init_power(chip);
306877d89b08766c878a2594b15d203e513acf952340wwang					if (retval != STATUS_SUCCESS) {
306977d89b08766c878a2594b15d203e513acf952340wwang						TRACE_RET(chip, STATUS_FAIL);
307077d89b08766c878a2594b15d203e513acf952340wwang					}
307177d89b08766c878a2594b15d203e513acf952340wwang					switch_ddr = 0;
30722b4baab313fefc4eaef7a034f5ff8c8c08a48dafwwang					TRACE_GOTO(chip, Switch_Fail);
307377d89b08766c878a2594b15d203e513acf952340wwang				}
307477d89b08766c878a2594b15d203e513acf952340wwang			}
307577d89b08766c878a2594b15d203e513acf952340wwang		}
307677d89b08766c878a2594b15d203e513acf952340wwang	}
307777d89b08766c878a2594b15d203e513acf952340wwang
307877d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
307977d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
308077d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
308177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
308277d89b08766c878a2594b15d203e513acf952340wwang	}
308377d89b08766c878a2594b15d203e513acf952340wwang#endif
308477d89b08766c878a2594b15d203e513acf952340wwang
308577d89b08766c878a2594b15d203e513acf952340wwang	temp = rtsx_readl(chip, RTSX_BIPR);
308677d89b08766c878a2594b15d203e513acf952340wwang	if (temp & SD_WRITE_PROTECT) {
308777d89b08766c878a2594b15d203e513acf952340wwang		chip->card_wp |= SD_CARD;
308877d89b08766c878a2594b15d203e513acf952340wwang	}
308977d89b08766c878a2594b15d203e513acf952340wwang
309077d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
309177d89b08766c878a2594b15d203e513acf952340wwang}
309277d89b08766c878a2594b15d203e513acf952340wwang
309377d89b08766c878a2594b15d203e513acf952340wwangint reset_sd_card(struct rtsx_chip *chip)
309477d89b08766c878a2594b15d203e513acf952340wwang{
309577d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
309677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
309777d89b08766c878a2594b15d203e513acf952340wwang
309877d89b08766c878a2594b15d203e513acf952340wwang	sd_init_reg_addr(chip);
309977d89b08766c878a2594b15d203e513acf952340wwang
31002d2322b269c2524996a259024f82c7e318719696wwang	memset(sd_card, 0, sizeof(struct sd_info));
31012d2322b269c2524996a259024f82c7e318719696wwang	chip->capacity[chip->card2lun[SD_CARD]] = 0;
310277d89b08766c878a2594b15d203e513acf952340wwang
310377d89b08766c878a2594b15d203e513acf952340wwang	retval = enable_card_clock(chip, SD_CARD);
310477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
310577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
310677d89b08766c878a2594b15d203e513acf952340wwang	}
310777d89b08766c878a2594b15d203e513acf952340wwang
310877d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
310977d89b08766c878a2594b15d203e513acf952340wwang		if (chip->asic_code) {
311077d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_pull_ctl_enable(chip);
311177d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
311277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
311377d89b08766c878a2594b15d203e513acf952340wwang			}
311477d89b08766c878a2594b15d203e513acf952340wwang		} else {
311577d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_register(chip, FPGA_PULL_CTL,
311677d89b08766c878a2594b15d203e513acf952340wwang						     FPGA_SD_PULL_CTL_BIT | 0x20, 0);
311777d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
311877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
311977d89b08766c878a2594b15d203e513acf952340wwang			}
312077d89b08766c878a2594b15d203e513acf952340wwang		}
312177d89b08766c878a2594b15d203e513acf952340wwang		retval = card_share_mode(chip, SD_CARD);
312277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
312377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
312477d89b08766c878a2594b15d203e513acf952340wwang		}
312577d89b08766c878a2594b15d203e513acf952340wwang
312677d89b08766c878a2594b15d203e513acf952340wwang		chip->sd_io = 1;
312777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
312877d89b08766c878a2594b15d203e513acf952340wwang	}
312977d89b08766c878a2594b15d203e513acf952340wwang
313077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_init_power(chip);
313177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
313277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
313377d89b08766c878a2594b15d203e513acf952340wwang	}
313477d89b08766c878a2594b15d203e513acf952340wwang
313577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->sd_ctl & RESET_MMC_FIRST) {
313677d89b08766c878a2594b15d203e513acf952340wwang		retval = reset_mmc(chip);
3137b6fbd29c8b836246169296869c3103ccecc201adwwang		if (retval != STATUS_SUCCESS) {
3138b6fbd29c8b836246169296869c3103ccecc201adwwang			if (sd_check_err_code(chip, SD_NO_CARD))
3139b6fbd29c8b836246169296869c3103ccecc201adwwang				TRACE_RET(chip, STATUS_FAIL);
3140b6fbd29c8b836246169296869c3103ccecc201adwwang
314177d89b08766c878a2594b15d203e513acf952340wwang			retval = reset_sd(chip);
314277d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
3143b6fbd29c8b836246169296869c3103ccecc201adwwang				if (CHECK_PID(chip, 0x5209))
3144b6fbd29c8b836246169296869c3103ccecc201adwwang					sd_change_bank_voltage(chip, SD_IO_3V3);
3145b6fbd29c8b836246169296869c3103ccecc201adwwang
3146b6fbd29c8b836246169296869c3103ccecc201adwwang				TRACE_RET(chip, STATUS_FAIL);
314777d89b08766c878a2594b15d203e513acf952340wwang			}
314877d89b08766c878a2594b15d203e513acf952340wwang		}
314977d89b08766c878a2594b15d203e513acf952340wwang	} else {
315077d89b08766c878a2594b15d203e513acf952340wwang		retval = reset_sd(chip);
315177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
3152b6fbd29c8b836246169296869c3103ccecc201adwwang			if (sd_check_err_code(chip, SD_NO_CARD))
315377d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
315477d89b08766c878a2594b15d203e513acf952340wwang
315577d89b08766c878a2594b15d203e513acf952340wwang			if (CHECK_PID(chip, 0x5209)) {
315677d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_change_bank_voltage(chip, SD_IO_3V3);
3157b6fbd29c8b836246169296869c3103ccecc201adwwang				if (retval != STATUS_SUCCESS)
315877d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
315977d89b08766c878a2594b15d203e513acf952340wwang			}
316077d89b08766c878a2594b15d203e513acf952340wwang
3161b6fbd29c8b836246169296869c3103ccecc201adwwang			if (chip->sd_io) {
3162b6fbd29c8b836246169296869c3103ccecc201adwwang				TRACE_RET(chip, STATUS_FAIL);
3163b6fbd29c8b836246169296869c3103ccecc201adwwang			} else {
316477d89b08766c878a2594b15d203e513acf952340wwang				retval = reset_mmc(chip);
3165b6fbd29c8b836246169296869c3103ccecc201adwwang				if (retval != STATUS_SUCCESS)
3166b6fbd29c8b836246169296869c3103ccecc201adwwang					TRACE_RET(chip, STATUS_FAIL);
316777d89b08766c878a2594b15d203e513acf952340wwang			}
316877d89b08766c878a2594b15d203e513acf952340wwang		}
316977d89b08766c878a2594b15d203e513acf952340wwang	}
317077d89b08766c878a2594b15d203e513acf952340wwang
317177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
317277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
317377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
317477d89b08766c878a2594b15d203e513acf952340wwang	}
317577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
317677d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
317777d89b08766c878a2594b15d203e513acf952340wwang
317877d89b08766c878a2594b15d203e513acf952340wwang	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
317977d89b08766c878a2594b15d203e513acf952340wwang
318077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_init_para(chip);
318177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
318277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
318377d89b08766c878a2594b15d203e513acf952340wwang	}
318477d89b08766c878a2594b15d203e513acf952340wwang
318577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type);
318677d89b08766c878a2594b15d203e513acf952340wwang
318777d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
318877d89b08766c878a2594b15d203e513acf952340wwang}
318977d89b08766c878a2594b15d203e513acf952340wwang
319077d89b08766c878a2594b15d203e513acf952340wwangstatic int reset_mmc_only(struct rtsx_chip *chip)
319177d89b08766c878a2594b15d203e513acf952340wwang{
319277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
319377d89b08766c878a2594b15d203e513acf952340wwang	int retval;
319477d89b08766c878a2594b15d203e513acf952340wwang
319577d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_type = 0;
319677d89b08766c878a2594b15d203e513acf952340wwang	sd_card->seq_mode = 0;
319777d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_data_buf_ready = 0;
319877d89b08766c878a2594b15d203e513acf952340wwang	sd_card->capacity = 0;
319977d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_switch_fail = 0;
320077d89b08766c878a2594b15d203e513acf952340wwang
320177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
320277d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_lock_status = 0;
320377d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_erase_status = 0;
320477d89b08766c878a2594b15d203e513acf952340wwang#endif
320577d89b08766c878a2594b15d203e513acf952340wwang
320677d89b08766c878a2594b15d203e513acf952340wwang	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
320777d89b08766c878a2594b15d203e513acf952340wwang
320877d89b08766c878a2594b15d203e513acf952340wwang	retval = enable_card_clock(chip, SD_CARD);
320977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
321077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
321177d89b08766c878a2594b15d203e513acf952340wwang	}
321277d89b08766c878a2594b15d203e513acf952340wwang
321377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_init_power(chip);
321477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
321577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
321677d89b08766c878a2594b15d203e513acf952340wwang	}
321777d89b08766c878a2594b15d203e513acf952340wwang
321877d89b08766c878a2594b15d203e513acf952340wwang	retval = reset_mmc(chip);
321977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
322077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
322177d89b08766c878a2594b15d203e513acf952340wwang	}
322277d89b08766c878a2594b15d203e513acf952340wwang
322377d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
322477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
322577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
322677d89b08766c878a2594b15d203e513acf952340wwang	}
322777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
322877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
322977d89b08766c878a2594b15d203e513acf952340wwang
323077d89b08766c878a2594b15d203e513acf952340wwang	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
323177d89b08766c878a2594b15d203e513acf952340wwang
323277d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_set_init_para(chip);
323377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
323477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
323577d89b08766c878a2594b15d203e513acf952340wwang	}
323677d89b08766c878a2594b15d203e513acf952340wwang
323777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", sd_card->sd_type);
323877d89b08766c878a2594b15d203e513acf952340wwang
323977d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
324077d89b08766c878a2594b15d203e513acf952340wwang}
324177d89b08766c878a2594b15d203e513acf952340wwang
324277d89b08766c878a2594b15d203e513acf952340wwang#define WAIT_DATA_READY_RTY_CNT		255
324377d89b08766c878a2594b15d203e513acf952340wwang
324477d89b08766c878a2594b15d203e513acf952340wwangstatic int wait_data_buf_ready(struct rtsx_chip *chip)
324577d89b08766c878a2594b15d203e513acf952340wwang{
324677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
324777d89b08766c878a2594b15d203e513acf952340wwang	int i, retval;
324877d89b08766c878a2594b15d203e513acf952340wwang
324977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
325077d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
325177d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_NO_CARD);
325277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
325377d89b08766c878a2594b15d203e513acf952340wwang		}
325477d89b08766c878a2594b15d203e513acf952340wwang
325577d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_data_buf_ready = 0;
325677d89b08766c878a2594b15d203e513acf952340wwang
325777d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
325877d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
325977d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
326077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
326177d89b08766c878a2594b15d203e513acf952340wwang		}
326277d89b08766c878a2594b15d203e513acf952340wwang
326377d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_data_buf_ready) {
326477d89b08766c878a2594b15d203e513acf952340wwang			return sd_send_cmd_get_rsp(chip, SEND_STATUS,
326577d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
326677d89b08766c878a2594b15d203e513acf952340wwang		}
326777d89b08766c878a2594b15d203e513acf952340wwang	}
326877d89b08766c878a2594b15d203e513acf952340wwang
326977d89b08766c878a2594b15d203e513acf952340wwang	sd_set_err_code(chip, SD_TO_ERR);
327077d89b08766c878a2594b15d203e513acf952340wwang
327177d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, STATUS_FAIL);
327277d89b08766c878a2594b15d203e513acf952340wwang}
327377d89b08766c878a2594b15d203e513acf952340wwang
327477d89b08766c878a2594b15d203e513acf952340wwangvoid sd_stop_seq_mode(struct rtsx_chip *chip)
327577d89b08766c878a2594b15d203e513acf952340wwang{
327677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
327777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
327877d89b08766c878a2594b15d203e513acf952340wwang
327977d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->seq_mode) {
328077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_switch_clock(chip);
328177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
328277d89b08766c878a2594b15d203e513acf952340wwang			return;
328377d89b08766c878a2594b15d203e513acf952340wwang		}
328477d89b08766c878a2594b15d203e513acf952340wwang
328577d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
328677d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1b, NULL, 0);
328777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
328877d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_STS_ERR);
328977d89b08766c878a2594b15d203e513acf952340wwang		}
329077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
329177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
329277d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_STS_ERR);
329377d89b08766c878a2594b15d203e513acf952340wwang		}
329477d89b08766c878a2594b15d203e513acf952340wwang		sd_card->seq_mode = 0;
329577d89b08766c878a2594b15d203e513acf952340wwang
329677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
329777d89b08766c878a2594b15d203e513acf952340wwang	}
329877d89b08766c878a2594b15d203e513acf952340wwang}
329977d89b08766c878a2594b15d203e513acf952340wwang
330077d89b08766c878a2594b15d203e513acf952340wwangstatic inline int sd_auto_tune_clock(struct rtsx_chip *chip)
330177d89b08766c878a2594b15d203e513acf952340wwang{
330277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
330377d89b08766c878a2594b15d203e513acf952340wwang	int retval;
330477d89b08766c878a2594b15d203e513acf952340wwang
330577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
330677d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_clock > 30) {
330777d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock -= 20;
330877d89b08766c878a2594b15d203e513acf952340wwang		}
330977d89b08766c878a2594b15d203e513acf952340wwang	} else {
331077d89b08766c878a2594b15d203e513acf952340wwang		switch (sd_card->sd_clock) {
331177d89b08766c878a2594b15d203e513acf952340wwang		case CLK_200:
331277d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_150;
331377d89b08766c878a2594b15d203e513acf952340wwang			break;
331477d89b08766c878a2594b15d203e513acf952340wwang
331577d89b08766c878a2594b15d203e513acf952340wwang		case CLK_150:
331677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_120;
331777d89b08766c878a2594b15d203e513acf952340wwang			break;
331877d89b08766c878a2594b15d203e513acf952340wwang
331977d89b08766c878a2594b15d203e513acf952340wwang		case CLK_120:
332077d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_100;
332177d89b08766c878a2594b15d203e513acf952340wwang			break;
332277d89b08766c878a2594b15d203e513acf952340wwang
332377d89b08766c878a2594b15d203e513acf952340wwang		case CLK_100:
332477d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_80;
332577d89b08766c878a2594b15d203e513acf952340wwang			break;
332677d89b08766c878a2594b15d203e513acf952340wwang
332777d89b08766c878a2594b15d203e513acf952340wwang		case CLK_80:
332877d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_60;
332977d89b08766c878a2594b15d203e513acf952340wwang			break;
333077d89b08766c878a2594b15d203e513acf952340wwang
333177d89b08766c878a2594b15d203e513acf952340wwang		case CLK_60:
333277d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = CLK_50;
333377d89b08766c878a2594b15d203e513acf952340wwang			break;
333477d89b08766c878a2594b15d203e513acf952340wwang
333577d89b08766c878a2594b15d203e513acf952340wwang		default:
333677d89b08766c878a2594b15d203e513acf952340wwang			break;
333777d89b08766c878a2594b15d203e513acf952340wwang		}
333877d89b08766c878a2594b15d203e513acf952340wwang	}
333977d89b08766c878a2594b15d203e513acf952340wwang
334077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
334177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
334277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
334377d89b08766c878a2594b15d203e513acf952340wwang	}
334477d89b08766c878a2594b15d203e513acf952340wwang
334577d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
334677d89b08766c878a2594b15d203e513acf952340wwang}
334777d89b08766c878a2594b15d203e513acf952340wwang
334877d89b08766c878a2594b15d203e513acf952340wwangint sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
334977d89b08766c878a2594b15d203e513acf952340wwang{
335077d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
335177d89b08766c878a2594b15d203e513acf952340wwang	u32 data_addr;
335277d89b08766c878a2594b15d203e513acf952340wwang	u8 cfg2;
335377d89b08766c878a2594b15d203e513acf952340wwang	int retval;
335477d89b08766c878a2594b15d203e513acf952340wwang
335577d89b08766c878a2594b15d203e513acf952340wwang	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
335677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("sd_rw: Read %d %s from 0x%x\n", sector_cnt,
335777d89b08766c878a2594b15d203e513acf952340wwang			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
335877d89b08766c878a2594b15d203e513acf952340wwang	} else {
335977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("sd_rw: Write %d %s to 0x%x\n", sector_cnt,
336077d89b08766c878a2594b15d203e513acf952340wwang			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
336177d89b08766c878a2594b15d203e513acf952340wwang	}
336277d89b08766c878a2594b15d203e513acf952340wwang
336377d89b08766c878a2594b15d203e513acf952340wwang	sd_card->cleanup_counter = 0;
336477d89b08766c878a2594b15d203e513acf952340wwang
336577d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->card_ready & SD_CARD)) {
336677d89b08766c878a2594b15d203e513acf952340wwang		sd_card->seq_mode = 0;
336777d89b08766c878a2594b15d203e513acf952340wwang
336877d89b08766c878a2594b15d203e513acf952340wwang		retval = reset_sd_card(chip);
336977d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS) {
337077d89b08766c878a2594b15d203e513acf952340wwang			chip->card_ready |= SD_CARD;
337177d89b08766c878a2594b15d203e513acf952340wwang			chip->card_fail &= ~SD_CARD;
337277d89b08766c878a2594b15d203e513acf952340wwang		} else {
337377d89b08766c878a2594b15d203e513acf952340wwang			chip->card_ready &= ~SD_CARD;
337477d89b08766c878a2594b15d203e513acf952340wwang			chip->card_fail |= SD_CARD;
337577d89b08766c878a2594b15d203e513acf952340wwang			chip->capacity[chip->card2lun[SD_CARD]] = 0;
337677d89b08766c878a2594b15d203e513acf952340wwang			chip->rw_need_retry = 1;
337777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
337877d89b08766c878a2594b15d203e513acf952340wwang		}
337977d89b08766c878a2594b15d203e513acf952340wwang	}
338077d89b08766c878a2594b15d203e513acf952340wwang
338177d89b08766c878a2594b15d203e513acf952340wwang	if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) {
338277d89b08766c878a2594b15d203e513acf952340wwang		data_addr = start_sector << 9;
338377d89b08766c878a2594b15d203e513acf952340wwang	} else {
338477d89b08766c878a2594b15d203e513acf952340wwang		data_addr = start_sector;
338577d89b08766c878a2594b15d203e513acf952340wwang	}
338677d89b08766c878a2594b15d203e513acf952340wwang
338777d89b08766c878a2594b15d203e513acf952340wwang	sd_clr_err_code(chip);
338877d89b08766c878a2594b15d203e513acf952340wwang
338977d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
339077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
339177d89b08766c878a2594b15d203e513acf952340wwang		sd_set_err_code(chip, SD_IO_ERR);
339277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, RW_FAIL);
339377d89b08766c878a2594b15d203e513acf952340wwang	}
339477d89b08766c878a2594b15d203e513acf952340wwang
339577d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->seq_mode && ((sd_card->pre_dir != srb->sc_data_direction)
339677d89b08766c878a2594b15d203e513acf952340wwang			|| ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != start_sector))) {
339777d89b08766c878a2594b15d203e513acf952340wwang		if ((sd_card->pre_sec_cnt < 0x80)
339877d89b08766c878a2594b15d203e513acf952340wwang				&& (sd_card->pre_dir == DMA_FROM_DEVICE)
339977d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_SD30_SPEED(sd_card)
340077d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_SD_HS(sd_card)
340177d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_MMC_HS(sd_card)) {
340277d89b08766c878a2594b15d203e513acf952340wwang			sd_send_cmd_get_rsp(chip, SEND_STATUS,
340377d89b08766c878a2594b15d203e513acf952340wwang					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
340477d89b08766c878a2594b15d203e513acf952340wwang		}
340577d89b08766c878a2594b15d203e513acf952340wwang
340677d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
340777d89b08766c878a2594b15d203e513acf952340wwang				0, SD_RSP_TYPE_R1b, NULL, 0);
340877d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
340977d89b08766c878a2594b15d203e513acf952340wwang			chip->rw_need_retry = 1;
341077d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_STS_ERR);
341177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, RW_FAIL);
341277d89b08766c878a2594b15d203e513acf952340wwang		}
341377d89b08766c878a2594b15d203e513acf952340wwang
341477d89b08766c878a2594b15d203e513acf952340wwang		sd_card->seq_mode = 0;
341577d89b08766c878a2594b15d203e513acf952340wwang
341677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
341777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
341877d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_IO_ERR);
341977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, RW_FAIL);
342077d89b08766c878a2594b15d203e513acf952340wwang		}
342177d89b08766c878a2594b15d203e513acf952340wwang
342277d89b08766c878a2594b15d203e513acf952340wwang		if ((sd_card->pre_sec_cnt < 0x80)
342377d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_SD30_SPEED(sd_card)
342477d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_SD_HS(sd_card)
342577d89b08766c878a2594b15d203e513acf952340wwang				&& !CHK_MMC_HS(sd_card)) {
342677d89b08766c878a2594b15d203e513acf952340wwang			sd_send_cmd_get_rsp(chip, SEND_STATUS,
342777d89b08766c878a2594b15d203e513acf952340wwang					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
342877d89b08766c878a2594b15d203e513acf952340wwang		}
342977d89b08766c878a2594b15d203e513acf952340wwang	}
343077d89b08766c878a2594b15d203e513acf952340wwang
343177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
343277d89b08766c878a2594b15d203e513acf952340wwang
343377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
343477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
343577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)sector_cnt);
343677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(sector_cnt >> 8));
343777d89b08766c878a2594b15d203e513acf952340wwang
343877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
343977d89b08766c878a2594b15d203e513acf952340wwang
344077d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_MMC_8BIT(sd_card)) {
344177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
344277d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) {
344377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
344477d89b08766c878a2594b15d203e513acf952340wwang	} else {
344577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_1);
344677d89b08766c878a2594b15d203e513acf952340wwang	}
344777d89b08766c878a2594b15d203e513acf952340wwang
344877d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->seq_mode) {
344977d89b08766c878a2594b15d203e513acf952340wwang		cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
345077d89b08766c878a2594b15d203e513acf952340wwang				SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
345177d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209)) {
345277d89b08766c878a2594b15d203e513acf952340wwang			if (!CHK_SD30_SPEED(sd_card)) {
345377d89b08766c878a2594b15d203e513acf952340wwang				cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
345477d89b08766c878a2594b15d203e513acf952340wwang			}
345577d89b08766c878a2594b15d203e513acf952340wwang		}
345677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
345777d89b08766c878a2594b15d203e513acf952340wwang
345877d89b08766c878a2594b15d203e513acf952340wwang		trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
345977d89b08766c878a2594b15d203e513acf952340wwang
346077d89b08766c878a2594b15d203e513acf952340wwang		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
346177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
346277d89b08766c878a2594b15d203e513acf952340wwang				     SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
346377d89b08766c878a2594b15d203e513acf952340wwang		} else {
346477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
346577d89b08766c878a2594b15d203e513acf952340wwang				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
346677d89b08766c878a2594b15d203e513acf952340wwang		}
346777d89b08766c878a2594b15d203e513acf952340wwang
346877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
346977d89b08766c878a2594b15d203e513acf952340wwang
347077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_send_cmd_no_wait(chip);
347177d89b08766c878a2594b15d203e513acf952340wwang	} else {
347277d89b08766c878a2594b15d203e513acf952340wwang		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
347377d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK);
347477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
347577d89b08766c878a2594b15d203e513acf952340wwang				     0x40 | READ_MULTIPLE_BLOCK);
347677d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(data_addr >> 24));
347777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(data_addr >> 16));
347877d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(data_addr >> 8));
347977d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)data_addr);
348077d89b08766c878a2594b15d203e513acf952340wwang
348177d89b08766c878a2594b15d203e513acf952340wwang			cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
348277d89b08766c878a2594b15d203e513acf952340wwang					SD_CHECK_CRC7 | SD_RSP_LEN_6;
348377d89b08766c878a2594b15d203e513acf952340wwang			if (CHECK_PID(chip, 0x5209)) {
348477d89b08766c878a2594b15d203e513acf952340wwang				if (!CHK_SD30_SPEED(sd_card)) {
348577d89b08766c878a2594b15d203e513acf952340wwang					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
348677d89b08766c878a2594b15d203e513acf952340wwang				}
348777d89b08766c878a2594b15d203e513acf952340wwang			}
348877d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
348977d89b08766c878a2594b15d203e513acf952340wwang
349077d89b08766c878a2594b15d203e513acf952340wwang			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
349177d89b08766c878a2594b15d203e513acf952340wwang
349277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
349377d89b08766c878a2594b15d203e513acf952340wwang				     SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
349477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
349577d89b08766c878a2594b15d203e513acf952340wwang				     SD_TRANSFER_END, SD_TRANSFER_END);
349677d89b08766c878a2594b15d203e513acf952340wwang
349777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_send_cmd_no_wait(chip);
349877d89b08766c878a2594b15d203e513acf952340wwang		} else {
349977d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_send_cmd(chip, SD_CARD, 50);
350077d89b08766c878a2594b15d203e513acf952340wwang			if (retval < 0) {
350177d89b08766c878a2594b15d203e513acf952340wwang				rtsx_clear_sd_error(chip);
350277d89b08766c878a2594b15d203e513acf952340wwang
350377d89b08766c878a2594b15d203e513acf952340wwang				chip->rw_need_retry = 1;
350477d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_TO_ERR);
350577d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, RW_FAIL);
350677d89b08766c878a2594b15d203e513acf952340wwang			}
350777d89b08766c878a2594b15d203e513acf952340wwang
350877d89b08766c878a2594b15d203e513acf952340wwang			retval = wait_data_buf_ready(chip);
350977d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
351077d89b08766c878a2594b15d203e513acf952340wwang				chip->rw_need_retry = 1;
351177d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_TO_ERR);
351277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, RW_FAIL);
351377d89b08766c878a2594b15d203e513acf952340wwang			}
351477d89b08766c878a2594b15d203e513acf952340wwang
351577d89b08766c878a2594b15d203e513acf952340wwang			retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
351677d89b08766c878a2594b15d203e513acf952340wwang					data_addr, SD_RSP_TYPE_R1, NULL, 0);
351777d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
351877d89b08766c878a2594b15d203e513acf952340wwang				chip->rw_need_retry = 1;
351977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, RW_FAIL);
352077d89b08766c878a2594b15d203e513acf952340wwang			}
352177d89b08766c878a2594b15d203e513acf952340wwang
352277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_init_cmd(chip);
352377d89b08766c878a2594b15d203e513acf952340wwang
352477d89b08766c878a2594b15d203e513acf952340wwang			cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
352577d89b08766c878a2594b15d203e513acf952340wwang					SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
352677d89b08766c878a2594b15d203e513acf952340wwang			if (CHECK_PID(chip, 0x5209)) {
352777d89b08766c878a2594b15d203e513acf952340wwang				if (!CHK_SD30_SPEED(sd_card)) {
352877d89b08766c878a2594b15d203e513acf952340wwang					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
352977d89b08766c878a2594b15d203e513acf952340wwang				}
353077d89b08766c878a2594b15d203e513acf952340wwang			}
353177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
353277d89b08766c878a2594b15d203e513acf952340wwang
353377d89b08766c878a2594b15d203e513acf952340wwang			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
353477d89b08766c878a2594b15d203e513acf952340wwang
353577d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
353677d89b08766c878a2594b15d203e513acf952340wwang				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
353777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
353877d89b08766c878a2594b15d203e513acf952340wwang				     SD_TRANSFER_END, SD_TRANSFER_END);
353977d89b08766c878a2594b15d203e513acf952340wwang
354077d89b08766c878a2594b15d203e513acf952340wwang			rtsx_send_cmd_no_wait(chip);
354177d89b08766c878a2594b15d203e513acf952340wwang		}
354277d89b08766c878a2594b15d203e513acf952340wwang
354377d89b08766c878a2594b15d203e513acf952340wwang		sd_card->seq_mode = 1;
354477d89b08766c878a2594b15d203e513acf952340wwang	}
354577d89b08766c878a2594b15d203e513acf952340wwang
354677d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
354777d89b08766c878a2594b15d203e513acf952340wwang			scsi_sg_count(srb), srb->sc_data_direction, chip->sd_timeout);
354877d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
354977d89b08766c878a2594b15d203e513acf952340wwang		u8 stat = 0;
355077d89b08766c878a2594b15d203e513acf952340wwang		int err;
355177d89b08766c878a2594b15d203e513acf952340wwang
355277d89b08766c878a2594b15d203e513acf952340wwang		sd_card->seq_mode = 0;
355377d89b08766c878a2594b15d203e513acf952340wwang
355477d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
355577d89b08766c878a2594b15d203e513acf952340wwang			err = STATUS_TIMEDOUT;
355677d89b08766c878a2594b15d203e513acf952340wwang		} else {
355777d89b08766c878a2594b15d203e513acf952340wwang			err = STATUS_FAIL;
355877d89b08766c878a2594b15d203e513acf952340wwang		}
355977d89b08766c878a2594b15d203e513acf952340wwang
356077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_read_register(chip, REG_SD_STAT1, &stat);
356177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
356277d89b08766c878a2594b15d203e513acf952340wwang		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
356377d89b08766c878a2594b15d203e513acf952340wwang			chip->rw_need_retry = 0;
356477d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("No card exist, exit sd_rw\n");
356577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
356677d89b08766c878a2594b15d203e513acf952340wwang		}
356777d89b08766c878a2594b15d203e513acf952340wwang
356877d89b08766c878a2594b15d203e513acf952340wwang		chip->rw_need_retry = 1;
356977d89b08766c878a2594b15d203e513acf952340wwang
357077d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0);
357177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
357277d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_STS_ERR);
357377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, RW_FAIL);
357477d89b08766c878a2594b15d203e513acf952340wwang		}
357577d89b08766c878a2594b15d203e513acf952340wwang
357677d89b08766c878a2594b15d203e513acf952340wwang		if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
357777d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD CRC error, tune clock!\n");
357877d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_CRC_ERR);
357977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, RW_FAIL);
358077d89b08766c878a2594b15d203e513acf952340wwang		}
358177d89b08766c878a2594b15d203e513acf952340wwang
358277d89b08766c878a2594b15d203e513acf952340wwang		if (err == STATUS_TIMEDOUT) {
358377d89b08766c878a2594b15d203e513acf952340wwang			sd_set_err_code(chip, SD_TO_ERR);
358477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, RW_FAIL);
358577d89b08766c878a2594b15d203e513acf952340wwang		}
358677d89b08766c878a2594b15d203e513acf952340wwang
358777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, err);
358877d89b08766c878a2594b15d203e513acf952340wwang	}
358977d89b08766c878a2594b15d203e513acf952340wwang
359077d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_sec_addr = start_sector;
359177d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_sec_cnt = sector_cnt;
359277d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_dir = srb->sc_data_direction;
359377d89b08766c878a2594b15d203e513acf952340wwang
359477d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
359577d89b08766c878a2594b15d203e513acf952340wwang
359677d89b08766c878a2594b15d203e513acf952340wwangRW_FAIL:
359777d89b08766c878a2594b15d203e513acf952340wwang	sd_card->seq_mode = 0;
359877d89b08766c878a2594b15d203e513acf952340wwang
359977d89b08766c878a2594b15d203e513acf952340wwang	if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
360077d89b08766c878a2594b15d203e513acf952340wwang		chip->rw_need_retry = 0;
360177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("No card exist, exit sd_rw\n");
360277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
360377d89b08766c878a2594b15d203e513acf952340wwang	}
360477d89b08766c878a2594b15d203e513acf952340wwang
360577d89b08766c878a2594b15d203e513acf952340wwang	if (sd_check_err_code(chip, SD_CRC_ERR)) {
360677d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
360777d89b08766c878a2594b15d203e513acf952340wwang			sd_card->mmc_dont_switch_bus = 1;
360877d89b08766c878a2594b15d203e513acf952340wwang			reset_mmc_only(chip);
360977d89b08766c878a2594b15d203e513acf952340wwang			sd_card->mmc_dont_switch_bus = 0;
361077d89b08766c878a2594b15d203e513acf952340wwang		} else {
361177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->need_retune = 1;
361277d89b08766c878a2594b15d203e513acf952340wwang			sd_auto_tune_clock(chip);
361377d89b08766c878a2594b15d203e513acf952340wwang		}
361477d89b08766c878a2594b15d203e513acf952340wwang	} else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
361577d89b08766c878a2594b15d203e513acf952340wwang		retval = reset_sd_card(chip);
361677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
361777d89b08766c878a2594b15d203e513acf952340wwang			chip->card_ready &= ~SD_CARD;
361877d89b08766c878a2594b15d203e513acf952340wwang			chip->card_fail |= SD_CARD;
361977d89b08766c878a2594b15d203e513acf952340wwang			chip->capacity[chip->card2lun[SD_CARD]] = 0;
362077d89b08766c878a2594b15d203e513acf952340wwang		}
362177d89b08766c878a2594b15d203e513acf952340wwang	}
362277d89b08766c878a2594b15d203e513acf952340wwang
362377d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, STATUS_FAIL);
362477d89b08766c878a2594b15d203e513acf952340wwang}
362577d89b08766c878a2594b15d203e513acf952340wwang
362677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_CPRM
362777d89b08766c878a2594b15d203e513acf952340wwangint soft_reset_sd_card(struct rtsx_chip *chip)
362877d89b08766c878a2594b15d203e513acf952340wwang{
362977d89b08766c878a2594b15d203e513acf952340wwang	return reset_sd(chip);
363077d89b08766c878a2594b15d203e513acf952340wwang}
363177d89b08766c878a2594b15d203e513acf952340wwang
363277d89b08766c878a2594b15d203e513acf952340wwangint ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
363377d89b08766c878a2594b15d203e513acf952340wwang		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check)
363477d89b08766c878a2594b15d203e513acf952340wwang{
363577d89b08766c878a2594b15d203e513acf952340wwang	int retval;
363677d89b08766c878a2594b15d203e513acf952340wwang	int timeout = 100;
363777d89b08766c878a2594b15d203e513acf952340wwang	u16 reg_addr;
363877d89b08766c878a2594b15d203e513acf952340wwang	u8 *ptr;
363977d89b08766c878a2594b15d203e513acf952340wwang	int stat_idx = 0;
364077d89b08766c878a2594b15d203e513acf952340wwang	int rty_cnt = 0;
364177d89b08766c878a2594b15d203e513acf952340wwang
364277d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx);
364377d89b08766c878a2594b15d203e513acf952340wwang
364477d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R1b) {
364577d89b08766c878a2594b15d203e513acf952340wwang		timeout = 3000;
364677d89b08766c878a2594b15d203e513acf952340wwang	}
364777d89b08766c878a2594b15d203e513acf952340wwang
364877d89b08766c878a2594b15d203e513acf952340wwangRTY_SEND_CMD:
364977d89b08766c878a2594b15d203e513acf952340wwang
365077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
365177d89b08766c878a2594b15d203e513acf952340wwang
365277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
365377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
365477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
365577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
365677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
365777d89b08766c878a2594b15d203e513acf952340wwang
365877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
365977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
366077d89b08766c878a2594b15d203e513acf952340wwang			0x01, PINGPONG_BUFFER);
366177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
366277d89b08766c878a2594b15d203e513acf952340wwang			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
366377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
366477d89b08766c878a2594b15d203e513acf952340wwang
366577d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R2) {
366677d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
366777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
366877d89b08766c878a2594b15d203e513acf952340wwang		}
366977d89b08766c878a2594b15d203e513acf952340wwang		stat_idx = 17;
367077d89b08766c878a2594b15d203e513acf952340wwang	} else if (rsp_type != SD_RSP_TYPE_R0) {
367177d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
367277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
367377d89b08766c878a2594b15d203e513acf952340wwang		}
367477d89b08766c878a2594b15d203e513acf952340wwang		stat_idx = 6;
367577d89b08766c878a2594b15d203e513acf952340wwang	}
367677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
367777d89b08766c878a2594b15d203e513acf952340wwang
367877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
367977d89b08766c878a2594b15d203e513acf952340wwang
368077d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
368177d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
368277d89b08766c878a2594b15d203e513acf952340wwang		if (retval == -ETIMEDOUT) {
368377d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
368477d89b08766c878a2594b15d203e513acf952340wwang
368577d89b08766c878a2594b15d203e513acf952340wwang			if (rsp_type & SD_WAIT_BUSY_END) {
368677d89b08766c878a2594b15d203e513acf952340wwang				retval = sd_check_data0_status(chip);
368777d89b08766c878a2594b15d203e513acf952340wwang				if (retval != STATUS_SUCCESS) {
368877d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, retval);
368977d89b08766c878a2594b15d203e513acf952340wwang				}
369077d89b08766c878a2594b15d203e513acf952340wwang			} else {
369177d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_TO_ERR);
369277d89b08766c878a2594b15d203e513acf952340wwang			}
369377d89b08766c878a2594b15d203e513acf952340wwang		}
369477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
369577d89b08766c878a2594b15d203e513acf952340wwang	}
369677d89b08766c878a2594b15d203e513acf952340wwang
369777d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R0) {
369877d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_SUCCESS;
369977d89b08766c878a2594b15d203e513acf952340wwang	}
370077d89b08766c878a2594b15d203e513acf952340wwang
370177d89b08766c878a2594b15d203e513acf952340wwang	ptr = rtsx_get_cmd_data(chip) + 1;
370277d89b08766c878a2594b15d203e513acf952340wwang
370377d89b08766c878a2594b15d203e513acf952340wwang	if ((ptr[0] & 0xC0) != 0) {
370477d89b08766c878a2594b15d203e513acf952340wwang		sd_set_err_code(chip, SD_STS_ERR);
370577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
370677d89b08766c878a2594b15d203e513acf952340wwang	}
370777d89b08766c878a2594b15d203e513acf952340wwang
370877d89b08766c878a2594b15d203e513acf952340wwang	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
370977d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[stat_idx] & SD_CRC7_ERR) {
371077d89b08766c878a2594b15d203e513acf952340wwang			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
371177d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_CRC_ERR);
371277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
371377d89b08766c878a2594b15d203e513acf952340wwang			}
371477d89b08766c878a2594b15d203e513acf952340wwang			if (rty_cnt < SD_MAX_RETRY_COUNT) {
371577d89b08766c878a2594b15d203e513acf952340wwang				wait_timeout(20);
371677d89b08766c878a2594b15d203e513acf952340wwang				rty_cnt++;
371777d89b08766c878a2594b15d203e513acf952340wwang				goto RTY_SEND_CMD;
371877d89b08766c878a2594b15d203e513acf952340wwang			} else {
371977d89b08766c878a2594b15d203e513acf952340wwang				sd_set_err_code(chip, SD_CRC_ERR);
372077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
372177d89b08766c878a2594b15d203e513acf952340wwang			}
372277d89b08766c878a2594b15d203e513acf952340wwang		}
372377d89b08766c878a2594b15d203e513acf952340wwang	}
372477d89b08766c878a2594b15d203e513acf952340wwang
372577d89b08766c878a2594b15d203e513acf952340wwang	if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
372677d89b08766c878a2594b15d203e513acf952340wwang			(cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
372777d89b08766c878a2594b15d203e513acf952340wwang		if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) {
372877d89b08766c878a2594b15d203e513acf952340wwang			if (ptr[1] & 0x80) {
372977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, STATUS_FAIL);
373077d89b08766c878a2594b15d203e513acf952340wwang			}
373177d89b08766c878a2594b15d203e513acf952340wwang		}
373277d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
373377d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[1] & 0x7D)
373477d89b08766c878a2594b15d203e513acf952340wwang#else
373577d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[1] & 0x7F)
373677d89b08766c878a2594b15d203e513acf952340wwang#endif
373777d89b08766c878a2594b15d203e513acf952340wwang		{
373877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
373977d89b08766c878a2594b15d203e513acf952340wwang		}
374077d89b08766c878a2594b15d203e513acf952340wwang		if (ptr[2] & 0xF8) {
374177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
374277d89b08766c878a2594b15d203e513acf952340wwang		}
374377d89b08766c878a2594b15d203e513acf952340wwang
374477d89b08766c878a2594b15d203e513acf952340wwang		if (cmd_idx == SELECT_CARD) {
374577d89b08766c878a2594b15d203e513acf952340wwang			if (rsp_type == SD_RSP_TYPE_R2) {
374677d89b08766c878a2594b15d203e513acf952340wwang				if ((ptr[3] & 0x1E) != 0x04) {
374777d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
374877d89b08766c878a2594b15d203e513acf952340wwang				}
374919a3833fd4909c2d88683c0798fe039a69723194wwang			} else if (rsp_type == SD_RSP_TYPE_R0) {
375077d89b08766c878a2594b15d203e513acf952340wwang				if ((ptr[3] & 0x1E) != 0x03) {
375177d89b08766c878a2594b15d203e513acf952340wwang					TRACE_RET(chip, STATUS_FAIL);
375277d89b08766c878a2594b15d203e513acf952340wwang				}
375377d89b08766c878a2594b15d203e513acf952340wwang			}
375477d89b08766c878a2594b15d203e513acf952340wwang		}
375577d89b08766c878a2594b15d203e513acf952340wwang	}
375677d89b08766c878a2594b15d203e513acf952340wwang
375777d89b08766c878a2594b15d203e513acf952340wwang	if (rsp && rsp_len) {
375877d89b08766c878a2594b15d203e513acf952340wwang		memcpy(rsp, ptr, rsp_len);
375977d89b08766c878a2594b15d203e513acf952340wwang	}
376077d89b08766c878a2594b15d203e513acf952340wwang
376177d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
376277d89b08766c878a2594b15d203e513acf952340wwang}
376377d89b08766c878a2594b15d203e513acf952340wwang
376477d89b08766c878a2594b15d203e513acf952340wwangint ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
376577d89b08766c878a2594b15d203e513acf952340wwang{
376677d89b08766c878a2594b15d203e513acf952340wwang	int retval, rsp_len;
376777d89b08766c878a2594b15d203e513acf952340wwang	u16 reg_addr;
376877d89b08766c878a2594b15d203e513acf952340wwang
376977d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R0) {
377077d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_SUCCESS;
377177d89b08766c878a2594b15d203e513acf952340wwang	}
377277d89b08766c878a2594b15d203e513acf952340wwang
377377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_init_cmd(chip);
377477d89b08766c878a2594b15d203e513acf952340wwang
377577d89b08766c878a2594b15d203e513acf952340wwang	if (rsp_type == SD_RSP_TYPE_R2) {
377677d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
377777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
377877d89b08766c878a2594b15d203e513acf952340wwang		}
377977d89b08766c878a2594b15d203e513acf952340wwang		rsp_len = 17;
378077d89b08766c878a2594b15d203e513acf952340wwang	} else if (rsp_type != SD_RSP_TYPE_R0) {
378177d89b08766c878a2594b15d203e513acf952340wwang		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
378277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
378377d89b08766c878a2594b15d203e513acf952340wwang		}
378477d89b08766c878a2594b15d203e513acf952340wwang		rsp_len = 6;
378577d89b08766c878a2594b15d203e513acf952340wwang	}
378677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
378777d89b08766c878a2594b15d203e513acf952340wwang
378877d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_send_cmd(chip, SD_CARD, 100);
378977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
379077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
379177d89b08766c878a2594b15d203e513acf952340wwang	}
379277d89b08766c878a2594b15d203e513acf952340wwang
379377d89b08766c878a2594b15d203e513acf952340wwang	if (rsp) {
379477d89b08766c878a2594b15d203e513acf952340wwang		int min_len = (rsp_len < len) ? rsp_len : len;
379577d89b08766c878a2594b15d203e513acf952340wwang
379677d89b08766c878a2594b15d203e513acf952340wwang		memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
379777d89b08766c878a2594b15d203e513acf952340wwang
379877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("min_len = %d\n", min_len);
379977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
380077d89b08766c878a2594b15d203e513acf952340wwang			rsp[0], rsp[1], rsp[2], rsp[3]);
380177d89b08766c878a2594b15d203e513acf952340wwang	}
380277d89b08766c878a2594b15d203e513acf952340wwang
380377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
380477d89b08766c878a2594b15d203e513acf952340wwang}
380577d89b08766c878a2594b15d203e513acf952340wwang
380677d89b08766c878a2594b15d203e513acf952340wwangint sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
380777d89b08766c878a2594b15d203e513acf952340wwang{
380877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
380977d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
381077d89b08766c878a2594b15d203e513acf952340wwang	int len;
381177d89b08766c878a2594b15d203e513acf952340wwang	u8 buf[18] = {
381277d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381377d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381477d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381577d89b08766c878a2594b15d203e513acf952340wwang		0x0E,
381677d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381777d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381877d89b08766c878a2594b15d203e513acf952340wwang		0x00,
381977d89b08766c878a2594b15d203e513acf952340wwang		0x00,
382077d89b08766c878a2594b15d203e513acf952340wwang		0x53,
382177d89b08766c878a2594b15d203e513acf952340wwang		0x44,
382277d89b08766c878a2594b15d203e513acf952340wwang		0x20,
382377d89b08766c878a2594b15d203e513acf952340wwang		0x43,
382477d89b08766c878a2594b15d203e513acf952340wwang		0x61,
382577d89b08766c878a2594b15d203e513acf952340wwang		0x72,
382677d89b08766c878a2594b15d203e513acf952340wwang		0x64,
382777d89b08766c878a2594b15d203e513acf952340wwang		0x00,
382877d89b08766c878a2594b15d203e513acf952340wwang		0x00,
382977d89b08766c878a2594b15d203e513acf952340wwang		0x00,
383077d89b08766c878a2594b15d203e513acf952340wwang	};
383177d89b08766c878a2594b15d203e513acf952340wwang
383277d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_cmd_err = 0;
383377d89b08766c878a2594b15d203e513acf952340wwang
383477d89b08766c878a2594b15d203e513acf952340wwang	if (!(CHK_BIT(chip->lun_mc, lun))) {
383577d89b08766c878a2594b15d203e513acf952340wwang		SET_BIT(chip->lun_mc, lun);
383677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
383777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
383877d89b08766c878a2594b15d203e513acf952340wwang	}
383977d89b08766c878a2594b15d203e513acf952340wwang
384077d89b08766c878a2594b15d203e513acf952340wwang	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
384177d89b08766c878a2594b15d203e513acf952340wwang			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
384277d89b08766c878a2594b15d203e513acf952340wwang			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
384377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
384477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
384577d89b08766c878a2594b15d203e513acf952340wwang	}
384677d89b08766c878a2594b15d203e513acf952340wwang
384777d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[1] & 0x0F) {
384877d89b08766c878a2594b15d203e513acf952340wwang	case 0:
384977d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_pass_thru_en = 0;
385077d89b08766c878a2594b15d203e513acf952340wwang		break;
385177d89b08766c878a2594b15d203e513acf952340wwang
385277d89b08766c878a2594b15d203e513acf952340wwang	case 1:
385377d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_pass_thru_en = 1;
385477d89b08766c878a2594b15d203e513acf952340wwang		break;
385577d89b08766c878a2594b15d203e513acf952340wwang
385677d89b08766c878a2594b15d203e513acf952340wwang	default:
385777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
385877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
385977d89b08766c878a2594b15d203e513acf952340wwang	}
386077d89b08766c878a2594b15d203e513acf952340wwang
386177d89b08766c878a2594b15d203e513acf952340wwang	buf[5] = (1 == CHK_SD(sd_card)) ?  0x01 : 0x02;
386277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->card_wp & SD_CARD) {
386377d89b08766c878a2594b15d203e513acf952340wwang		buf[5] |= 0x80;
386477d89b08766c878a2594b15d203e513acf952340wwang	}
386577d89b08766c878a2594b15d203e513acf952340wwang
386677d89b08766c878a2594b15d203e513acf952340wwang	buf[6] = (u8)(sd_card->sd_addr >> 16);
386777d89b08766c878a2594b15d203e513acf952340wwang	buf[7] = (u8)(sd_card->sd_addr >> 24);
386877d89b08766c878a2594b15d203e513acf952340wwang
386977d89b08766c878a2594b15d203e513acf952340wwang	buf[15] = chip->max_lun;
387077d89b08766c878a2594b15d203e513acf952340wwang
387177d89b08766c878a2594b15d203e513acf952340wwang	len = min(18, (int)scsi_bufflen(srb));
387277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
387377d89b08766c878a2594b15d203e513acf952340wwang
387477d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
387577d89b08766c878a2594b15d203e513acf952340wwang}
387677d89b08766c878a2594b15d203e513acf952340wwang
387777d89b08766c878a2594b15d203e513acf952340wwangstatic inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int *rsp_len)
387877d89b08766c878a2594b15d203e513acf952340wwang{
387977d89b08766c878a2594b15d203e513acf952340wwang	if (!rsp_type || !rsp_len) {
388077d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_FAIL;
388177d89b08766c878a2594b15d203e513acf952340wwang	}
388277d89b08766c878a2594b15d203e513acf952340wwang
388377d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[10]) {
388477d89b08766c878a2594b15d203e513acf952340wwang	case 0x03:
388577d89b08766c878a2594b15d203e513acf952340wwang		*rsp_type = SD_RSP_TYPE_R0;
388677d89b08766c878a2594b15d203e513acf952340wwang		*rsp_len = 0;
388777d89b08766c878a2594b15d203e513acf952340wwang		break;
388877d89b08766c878a2594b15d203e513acf952340wwang
388977d89b08766c878a2594b15d203e513acf952340wwang	case 0x04:
389077d89b08766c878a2594b15d203e513acf952340wwang		*rsp_type = SD_RSP_TYPE_R1;
389177d89b08766c878a2594b15d203e513acf952340wwang		*rsp_len = 6;
389277d89b08766c878a2594b15d203e513acf952340wwang		break;
389377d89b08766c878a2594b15d203e513acf952340wwang
389477d89b08766c878a2594b15d203e513acf952340wwang	case 0x05:
389577d89b08766c878a2594b15d203e513acf952340wwang		*rsp_type = SD_RSP_TYPE_R1b;
389677d89b08766c878a2594b15d203e513acf952340wwang		*rsp_len = 6;
389777d89b08766c878a2594b15d203e513acf952340wwang		break;
389877d89b08766c878a2594b15d203e513acf952340wwang
389977d89b08766c878a2594b15d203e513acf952340wwang	case 0x06:
390077d89b08766c878a2594b15d203e513acf952340wwang		*rsp_type = SD_RSP_TYPE_R2;
390177d89b08766c878a2594b15d203e513acf952340wwang		*rsp_len = 17;
390277d89b08766c878a2594b15d203e513acf952340wwang		break;
390377d89b08766c878a2594b15d203e513acf952340wwang
390477d89b08766c878a2594b15d203e513acf952340wwang	case 0x07:
390577d89b08766c878a2594b15d203e513acf952340wwang		*rsp_type = SD_RSP_TYPE_R3;
390677d89b08766c878a2594b15d203e513acf952340wwang		*rsp_len = 6;
390777d89b08766c878a2594b15d203e513acf952340wwang		break;
390877d89b08766c878a2594b15d203e513acf952340wwang
390977d89b08766c878a2594b15d203e513acf952340wwang	default:
391077d89b08766c878a2594b15d203e513acf952340wwang		return STATUS_FAIL;
391177d89b08766c878a2594b15d203e513acf952340wwang	}
391277d89b08766c878a2594b15d203e513acf952340wwang
391377d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
391477d89b08766c878a2594b15d203e513acf952340wwang}
391577d89b08766c878a2594b15d203e513acf952340wwang
391677d89b08766c878a2594b15d203e513acf952340wwangint sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
391777d89b08766c878a2594b15d203e513acf952340wwang{
391877d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
391977d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
392077d89b08766c878a2594b15d203e513acf952340wwang	int retval, rsp_len;
392177d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd_idx, rsp_type;
392277d89b08766c878a2594b15d203e513acf952340wwang	u8 standby = 0, acmd = 0;
392377d89b08766c878a2594b15d203e513acf952340wwang	u32 arg;
392477d89b08766c878a2594b15d203e513acf952340wwang
392577d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->sd_pass_thru_en) {
392677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
392777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
392877d89b08766c878a2594b15d203e513acf952340wwang	}
392977d89b08766c878a2594b15d203e513acf952340wwang
393077d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
393177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
393277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
393377d89b08766c878a2594b15d203e513acf952340wwang	}
393477d89b08766c878a2594b15d203e513acf952340wwang
393577d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->pre_cmd_err) {
393677d89b08766c878a2594b15d203e513acf952340wwang		sd_card->pre_cmd_err = 0;
393777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
393877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
393977d89b08766c878a2594b15d203e513acf952340wwang	}
394077d89b08766c878a2594b15d203e513acf952340wwang
394177d89b08766c878a2594b15d203e513acf952340wwang	cmd_idx = srb->cmnd[2] & 0x3F;
394277d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x02) {
394377d89b08766c878a2594b15d203e513acf952340wwang		standby = 1;
394477d89b08766c878a2594b15d203e513acf952340wwang	}
394577d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x01) {
394677d89b08766c878a2594b15d203e513acf952340wwang		acmd = 1;
394777d89b08766c878a2594b15d203e513acf952340wwang	}
394877d89b08766c878a2594b15d203e513acf952340wwang
394977d89b08766c878a2594b15d203e513acf952340wwang	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
395077d89b08766c878a2594b15d203e513acf952340wwang		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
395177d89b08766c878a2594b15d203e513acf952340wwang
395277d89b08766c878a2594b15d203e513acf952340wwang	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
395377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
395477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
395577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
395677d89b08766c878a2594b15d203e513acf952340wwang	}
395777d89b08766c878a2594b15d203e513acf952340wwang	sd_card->last_rsp_type = rsp_type;
395877d89b08766c878a2594b15d203e513acf952340wwang
395977d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
396077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
396177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
396277d89b08766c878a2594b15d203e513acf952340wwang	}
396377d89b08766c878a2594b15d203e513acf952340wwang
396477d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
396577d89b08766c878a2594b15d203e513acf952340wwang	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
396677d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_8BIT(sd_card)) {
396777d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
396877d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
396977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
397077d89b08766c878a2594b15d203e513acf952340wwang			}
397177d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
397277d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
397377d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
397477d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
397577d89b08766c878a2594b15d203e513acf952340wwang			}
397677d89b08766c878a2594b15d203e513acf952340wwang		}
397777d89b08766c878a2594b15d203e513acf952340wwang	}
397877d89b08766c878a2594b15d203e513acf952340wwang#else
397977d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
398077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
398177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
398277d89b08766c878a2594b15d203e513acf952340wwang	}
398377d89b08766c878a2594b15d203e513acf952340wwang#endif
398477d89b08766c878a2594b15d203e513acf952340wwang
398577d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
398677d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 0);
398777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
398877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
398977d89b08766c878a2594b15d203e513acf952340wwang		}
399077d89b08766c878a2594b15d203e513acf952340wwang	}
399177d89b08766c878a2594b15d203e513acf952340wwang
399277d89b08766c878a2594b15d203e513acf952340wwang	if (acmd) {
399377d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
399477d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
399577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
399677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
399777d89b08766c878a2594b15d203e513acf952340wwang		}
399877d89b08766c878a2594b15d203e513acf952340wwang	}
399977d89b08766c878a2594b15d203e513acf952340wwang
400077d89b08766c878a2594b15d203e513acf952340wwang	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
400177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->rsp, rsp_len, 0);
400277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
400377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
400477d89b08766c878a2594b15d203e513acf952340wwang	}
400577d89b08766c878a2594b15d203e513acf952340wwang
400677d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
400777d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 1);
400877d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
400977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
401077d89b08766c878a2594b15d203e513acf952340wwang		}
401177d89b08766c878a2594b15d203e513acf952340wwang	}
401277d89b08766c878a2594b15d203e513acf952340wwang
401377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
401477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_update_lock_status(chip);
401577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
401677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
401777d89b08766c878a2594b15d203e513acf952340wwang	}
401877d89b08766c878a2594b15d203e513acf952340wwang#endif
401977d89b08766c878a2594b15d203e513acf952340wwang
402077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
402177d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
402277d89b08766c878a2594b15d203e513acf952340wwang
402377d89b08766c878a2594b15d203e513acf952340wwangSD_Execute_Cmd_Failed:
402477d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_cmd_err = 1;
402577d89b08766c878a2594b15d203e513acf952340wwang	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
402677d89b08766c878a2594b15d203e513acf952340wwang	release_sd_card(chip);
402777d89b08766c878a2594b15d203e513acf952340wwang	do_reset_sd_card(chip);
402877d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->card_ready & SD_CARD)) {
402977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
403077d89b08766c878a2594b15d203e513acf952340wwang	}
403177d89b08766c878a2594b15d203e513acf952340wwang
403277d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, TRANSPORT_FAILED);
403377d89b08766c878a2594b15d203e513acf952340wwang}
403477d89b08766c878a2594b15d203e513acf952340wwang
403577d89b08766c878a2594b15d203e513acf952340wwangint sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
403677d89b08766c878a2594b15d203e513acf952340wwang{
403777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
403877d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
403977d89b08766c878a2594b15d203e513acf952340wwang	int retval, rsp_len, i;
404077d89b08766c878a2594b15d203e513acf952340wwang	int cmd13_checkbit = 0, read_err = 0;
404177d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd_idx, rsp_type, bus_width;
404277d89b08766c878a2594b15d203e513acf952340wwang	u8 send_cmd12 = 0, standby = 0, acmd = 0;
404377d89b08766c878a2594b15d203e513acf952340wwang	u32 data_len;
404477d89b08766c878a2594b15d203e513acf952340wwang
404577d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->sd_pass_thru_en) {
404677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
404777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
404877d89b08766c878a2594b15d203e513acf952340wwang	}
404977d89b08766c878a2594b15d203e513acf952340wwang
405077d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->pre_cmd_err) {
405177d89b08766c878a2594b15d203e513acf952340wwang		sd_card->pre_cmd_err = 0;
405277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
405377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
405477d89b08766c878a2594b15d203e513acf952340wwang	}
405577d89b08766c878a2594b15d203e513acf952340wwang
405677d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
405777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
405877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
405977d89b08766c878a2594b15d203e513acf952340wwang	}
406077d89b08766c878a2594b15d203e513acf952340wwang
406177d89b08766c878a2594b15d203e513acf952340wwang	cmd_idx = srb->cmnd[2] & 0x3F;
406277d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x04) {
406377d89b08766c878a2594b15d203e513acf952340wwang		send_cmd12 = 1;
406477d89b08766c878a2594b15d203e513acf952340wwang	}
406577d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x02) {
406677d89b08766c878a2594b15d203e513acf952340wwang		standby = 1;
406777d89b08766c878a2594b15d203e513acf952340wwang	}
406877d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x01) {
406977d89b08766c878a2594b15d203e513acf952340wwang		acmd = 1;
407077d89b08766c878a2594b15d203e513acf952340wwang	}
407177d89b08766c878a2594b15d203e513acf952340wwang
407277d89b08766c878a2594b15d203e513acf952340wwang	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
407377d89b08766c878a2594b15d203e513acf952340wwang
407477d89b08766c878a2594b15d203e513acf952340wwang	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
407577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
407677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
407777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
407877d89b08766c878a2594b15d203e513acf952340wwang	}
407977d89b08766c878a2594b15d203e513acf952340wwang	sd_card->last_rsp_type = rsp_type;
408077d89b08766c878a2594b15d203e513acf952340wwang
408177d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
408277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
408377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
408477d89b08766c878a2594b15d203e513acf952340wwang	}
408577d89b08766c878a2594b15d203e513acf952340wwang
408677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
408777d89b08766c878a2594b15d203e513acf952340wwang	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
408877d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_8BIT(sd_card)) {
408977d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_8;
409077d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
409177d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_4;
409277d89b08766c878a2594b15d203e513acf952340wwang		} else {
409377d89b08766c878a2594b15d203e513acf952340wwang			bus_width = SD_BUS_WIDTH_1;
409477d89b08766c878a2594b15d203e513acf952340wwang		}
409577d89b08766c878a2594b15d203e513acf952340wwang	} else {
409677d89b08766c878a2594b15d203e513acf952340wwang		bus_width = SD_BUS_WIDTH_4;
409777d89b08766c878a2594b15d203e513acf952340wwang	}
409877d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("bus_width = %d\n", bus_width);
409977d89b08766c878a2594b15d203e513acf952340wwang#else
410077d89b08766c878a2594b15d203e513acf952340wwang	bus_width = SD_BUS_WIDTH_4;
410177d89b08766c878a2594b15d203e513acf952340wwang#endif
410277d89b08766c878a2594b15d203e513acf952340wwang
410377d89b08766c878a2594b15d203e513acf952340wwang	if (data_len < 512) {
410477d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
410577d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
410677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
410777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
410877d89b08766c878a2594b15d203e513acf952340wwang		}
410977d89b08766c878a2594b15d203e513acf952340wwang	}
411077d89b08766c878a2594b15d203e513acf952340wwang
411177d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
411277d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 0);
411377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
411477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
411577d89b08766c878a2594b15d203e513acf952340wwang		}
411677d89b08766c878a2594b15d203e513acf952340wwang	}
411777d89b08766c878a2594b15d203e513acf952340wwang
411877d89b08766c878a2594b15d203e513acf952340wwang	if (acmd) {
411977d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
412077d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
412177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
412277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
412377d89b08766c878a2594b15d203e513acf952340wwang		}
412477d89b08766c878a2594b15d203e513acf952340wwang	}
412577d89b08766c878a2594b15d203e513acf952340wwang
412677d89b08766c878a2594b15d203e513acf952340wwang	if (data_len <= 512) {
412777d89b08766c878a2594b15d203e513acf952340wwang		int min_len;
412877d89b08766c878a2594b15d203e513acf952340wwang		u8 *buf;
412977d89b08766c878a2594b15d203e513acf952340wwang		u16 byte_cnt, blk_cnt;
413077d89b08766c878a2594b15d203e513acf952340wwang		u8 cmd[5];
413177d89b08766c878a2594b15d203e513acf952340wwang
413277d89b08766c878a2594b15d203e513acf952340wwang		byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
413377d89b08766c878a2594b15d203e513acf952340wwang		blk_cnt = 1;
413477d89b08766c878a2594b15d203e513acf952340wwang
413577d89b08766c878a2594b15d203e513acf952340wwang		cmd[0] = 0x40 | cmd_idx;
413677d89b08766c878a2594b15d203e513acf952340wwang		cmd[1] = srb->cmnd[3];
413777d89b08766c878a2594b15d203e513acf952340wwang		cmd[2] = srb->cmnd[4];
413877d89b08766c878a2594b15d203e513acf952340wwang		cmd[3] = srb->cmnd[5];
413977d89b08766c878a2594b15d203e513acf952340wwang		cmd[4] = srb->cmnd[6];
414077d89b08766c878a2594b15d203e513acf952340wwang
414165f15e2de870dcd6c843e19eb4960a0ed6f40f6cThomas Meyer		buf = kmalloc(data_len, GFP_KERNEL);
414277d89b08766c878a2594b15d203e513acf952340wwang		if (buf == NULL) {
414377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
414477d89b08766c878a2594b15d203e513acf952340wwang		}
414577d89b08766c878a2594b15d203e513acf952340wwang
414677d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
414777d89b08766c878a2594b15d203e513acf952340wwang				       blk_cnt, bus_width, buf, data_len, 2000);
414877d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
414977d89b08766c878a2594b15d203e513acf952340wwang			read_err = 1;
415077d89b08766c878a2594b15d203e513acf952340wwang			kfree(buf);
415177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
415277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
415377d89b08766c878a2594b15d203e513acf952340wwang		}
415477d89b08766c878a2594b15d203e513acf952340wwang
415577d89b08766c878a2594b15d203e513acf952340wwang		min_len = min(data_len, scsi_bufflen(srb));
415677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(buf, min_len, srb);
415777d89b08766c878a2594b15d203e513acf952340wwang
415877d89b08766c878a2594b15d203e513acf952340wwang		kfree(buf);
415977d89b08766c878a2594b15d203e513acf952340wwang	} else if (!(data_len & 0x1FF)) {
416077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
416177d89b08766c878a2594b15d203e513acf952340wwang
416277d89b08766c878a2594b15d203e513acf952340wwang		trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
416377d89b08766c878a2594b15d203e513acf952340wwang
416477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
416577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
416677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
416777d89b08766c878a2594b15d203e513acf952340wwang				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
416877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
416977d89b08766c878a2594b15d203e513acf952340wwang				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
417077d89b08766c878a2594b15d203e513acf952340wwang
417177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
417277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, srb->cmnd[3]);
417377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, srb->cmnd[4]);
417477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, srb->cmnd[5]);
417577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, srb->cmnd[6]);
417677d89b08766c878a2594b15d203e513acf952340wwang
417777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
417877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
417977d89b08766c878a2594b15d203e513acf952340wwang
418077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
418177d89b08766c878a2594b15d203e513acf952340wwang			     0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
418277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
418377d89b08766c878a2594b15d203e513acf952340wwang
418477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_send_cmd_no_wait(chip);
418577d89b08766c878a2594b15d203e513acf952340wwang
418677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
418777d89b08766c878a2594b15d203e513acf952340wwang			scsi_sg_count(srb), DMA_FROM_DEVICE, 10000);
418877d89b08766c878a2594b15d203e513acf952340wwang		if (retval < 0) {
418977d89b08766c878a2594b15d203e513acf952340wwang			read_err = 1;
419077d89b08766c878a2594b15d203e513acf952340wwang			rtsx_clear_sd_error(chip);
419177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
419277d89b08766c878a2594b15d203e513acf952340wwang		}
419377d89b08766c878a2594b15d203e513acf952340wwang
419477d89b08766c878a2594b15d203e513acf952340wwang	} else {
419577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
419677d89b08766c878a2594b15d203e513acf952340wwang	}
419777d89b08766c878a2594b15d203e513acf952340wwang
419877d89b08766c878a2594b15d203e513acf952340wwang	retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
419977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
420077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
420177d89b08766c878a2594b15d203e513acf952340wwang	}
420277d89b08766c878a2594b15d203e513acf952340wwang
420377d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
420477d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 1);
420577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
420677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
420777d89b08766c878a2594b15d203e513acf952340wwang		}
420877d89b08766c878a2594b15d203e513acf952340wwang	}
420977d89b08766c878a2594b15d203e513acf952340wwang
421077d89b08766c878a2594b15d203e513acf952340wwang	if (send_cmd12) {
421177d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
421277d89b08766c878a2594b15d203e513acf952340wwang				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
421377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
421477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
421577d89b08766c878a2594b15d203e513acf952340wwang		}
421677d89b08766c878a2594b15d203e513acf952340wwang	}
421777d89b08766c878a2594b15d203e513acf952340wwang
421877d89b08766c878a2594b15d203e513acf952340wwang	if (data_len < 512) {
421977d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
422077d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
422177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
422277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
422377d89b08766c878a2594b15d203e513acf952340wwang		}
422477d89b08766c878a2594b15d203e513acf952340wwang
422577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
422677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
422777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
422877d89b08766c878a2594b15d203e513acf952340wwang		}
422977d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
423077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
423177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
423277d89b08766c878a2594b15d203e513acf952340wwang		}
423377d89b08766c878a2594b15d203e513acf952340wwang	}
423477d89b08766c878a2594b15d203e513acf952340wwang
423577d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) {
423677d89b08766c878a2594b15d203e513acf952340wwang		cmd13_checkbit = 1;
423777d89b08766c878a2594b15d203e513acf952340wwang	}
423877d89b08766c878a2594b15d203e513acf952340wwang
423977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
424077d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
424177d89b08766c878a2594b15d203e513acf952340wwang			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
424277d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS) {
424377d89b08766c878a2594b15d203e513acf952340wwang			break;
424477d89b08766c878a2594b15d203e513acf952340wwang		}
424577d89b08766c878a2594b15d203e513acf952340wwang	}
424677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
424777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
424877d89b08766c878a2594b15d203e513acf952340wwang	}
424977d89b08766c878a2594b15d203e513acf952340wwang
425077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
425177d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
425277d89b08766c878a2594b15d203e513acf952340wwang
425377d89b08766c878a2594b15d203e513acf952340wwangSD_Execute_Read_Cmd_Failed:
425477d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_cmd_err = 1;
425577d89b08766c878a2594b15d203e513acf952340wwang	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
425677d89b08766c878a2594b15d203e513acf952340wwang	if (read_err) {
425777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
425877d89b08766c878a2594b15d203e513acf952340wwang	}
425977d89b08766c878a2594b15d203e513acf952340wwang	release_sd_card(chip);
426077d89b08766c878a2594b15d203e513acf952340wwang	do_reset_sd_card(chip);
426177d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->card_ready & SD_CARD)) {
426277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
426377d89b08766c878a2594b15d203e513acf952340wwang	}
426477d89b08766c878a2594b15d203e513acf952340wwang
426577d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, TRANSPORT_FAILED);
426677d89b08766c878a2594b15d203e513acf952340wwang}
426777d89b08766c878a2594b15d203e513acf952340wwang
426877d89b08766c878a2594b15d203e513acf952340wwangint sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
426977d89b08766c878a2594b15d203e513acf952340wwang{
427077d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
427177d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
427277d89b08766c878a2594b15d203e513acf952340wwang	int retval, rsp_len, i;
427377d89b08766c878a2594b15d203e513acf952340wwang	int cmd13_checkbit = 0, write_err = 0;
427477d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd_idx, rsp_type;
427577d89b08766c878a2594b15d203e513acf952340wwang	u8 send_cmd12 = 0, standby = 0, acmd = 0;
427677d89b08766c878a2594b15d203e513acf952340wwang	u32 data_len, arg;
427777d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
427877d89b08766c878a2594b15d203e513acf952340wwang	int lock_cmd_fail = 0;
427977d89b08766c878a2594b15d203e513acf952340wwang	u8 sd_lock_state = 0;
428077d89b08766c878a2594b15d203e513acf952340wwang	u8 lock_cmd_type = 0;
428177d89b08766c878a2594b15d203e513acf952340wwang#endif
428277d89b08766c878a2594b15d203e513acf952340wwang
428377d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->sd_pass_thru_en) {
428477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
428577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
428677d89b08766c878a2594b15d203e513acf952340wwang	}
428777d89b08766c878a2594b15d203e513acf952340wwang
428877d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->pre_cmd_err) {
428977d89b08766c878a2594b15d203e513acf952340wwang		sd_card->pre_cmd_err = 0;
429077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
429177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
429277d89b08766c878a2594b15d203e513acf952340wwang	}
429377d89b08766c878a2594b15d203e513acf952340wwang
429477d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
429577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
429677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
429777d89b08766c878a2594b15d203e513acf952340wwang	}
429877d89b08766c878a2594b15d203e513acf952340wwang
429977d89b08766c878a2594b15d203e513acf952340wwang	cmd_idx = srb->cmnd[2] & 0x3F;
430077d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x04) {
430177d89b08766c878a2594b15d203e513acf952340wwang		send_cmd12 = 1;
430277d89b08766c878a2594b15d203e513acf952340wwang	}
430377d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x02) {
430477d89b08766c878a2594b15d203e513acf952340wwang		standby = 1;
430577d89b08766c878a2594b15d203e513acf952340wwang	}
430677d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] & 0x01) {
430777d89b08766c878a2594b15d203e513acf952340wwang		acmd = 1;
430877d89b08766c878a2594b15d203e513acf952340wwang	}
430977d89b08766c878a2594b15d203e513acf952340wwang
431077d89b08766c878a2594b15d203e513acf952340wwang	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
431177d89b08766c878a2594b15d203e513acf952340wwang	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
431277d89b08766c878a2594b15d203e513acf952340wwang		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
431377d89b08766c878a2594b15d203e513acf952340wwang
431477d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
431577d89b08766c878a2594b15d203e513acf952340wwang	if (cmd_idx == LOCK_UNLOCK) {
431677d89b08766c878a2594b15d203e513acf952340wwang		sd_lock_state = sd_card->sd_lock_status;
431777d89b08766c878a2594b15d203e513acf952340wwang		sd_lock_state &= SD_LOCKED;
431877d89b08766c878a2594b15d203e513acf952340wwang	}
431977d89b08766c878a2594b15d203e513acf952340wwang#endif
432077d89b08766c878a2594b15d203e513acf952340wwang
432177d89b08766c878a2594b15d203e513acf952340wwang	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
432277d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
432377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
432477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
432577d89b08766c878a2594b15d203e513acf952340wwang	}
432677d89b08766c878a2594b15d203e513acf952340wwang	sd_card->last_rsp_type = rsp_type;
432777d89b08766c878a2594b15d203e513acf952340wwang
432877d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_switch_clock(chip);
432977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
433077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
433177d89b08766c878a2594b15d203e513acf952340wwang	}
433277d89b08766c878a2594b15d203e513acf952340wwang
433377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
433477d89b08766c878a2594b15d203e513acf952340wwang	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
433577d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MMC_8BIT(sd_card)) {
433677d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
433777d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
433877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
433977d89b08766c878a2594b15d203e513acf952340wwang			}
434077d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
434177d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
434277d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
434377d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
434477d89b08766c878a2594b15d203e513acf952340wwang			}
434577d89b08766c878a2594b15d203e513acf952340wwang		}
434677d89b08766c878a2594b15d203e513acf952340wwang	}
434777d89b08766c878a2594b15d203e513acf952340wwang#else
434877d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
434977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
435077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
435177d89b08766c878a2594b15d203e513acf952340wwang	}
435277d89b08766c878a2594b15d203e513acf952340wwang#endif
435377d89b08766c878a2594b15d203e513acf952340wwang
435477d89b08766c878a2594b15d203e513acf952340wwang	if (data_len < 512) {
435577d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
435677d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
435777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
435877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
435977d89b08766c878a2594b15d203e513acf952340wwang		}
436077d89b08766c878a2594b15d203e513acf952340wwang	}
436177d89b08766c878a2594b15d203e513acf952340wwang
436277d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
436377d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 0);
436477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
436577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
436677d89b08766c878a2594b15d203e513acf952340wwang		}
436777d89b08766c878a2594b15d203e513acf952340wwang	}
436877d89b08766c878a2594b15d203e513acf952340wwang
436977d89b08766c878a2594b15d203e513acf952340wwang	if (acmd) {
437077d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
437177d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
437277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
437377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
437477d89b08766c878a2594b15d203e513acf952340wwang		}
437577d89b08766c878a2594b15d203e513acf952340wwang	}
437677d89b08766c878a2594b15d203e513acf952340wwang
437777d89b08766c878a2594b15d203e513acf952340wwang	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
437877d89b08766c878a2594b15d203e513acf952340wwang			sd_card->rsp, rsp_len, 0);
437977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
438077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
438177d89b08766c878a2594b15d203e513acf952340wwang	}
438277d89b08766c878a2594b15d203e513acf952340wwang
438377d89b08766c878a2594b15d203e513acf952340wwang	if (data_len <= 512) {
438477d89b08766c878a2594b15d203e513acf952340wwang		u16 i;
438577d89b08766c878a2594b15d203e513acf952340wwang		u8 *buf;
438677d89b08766c878a2594b15d203e513acf952340wwang
438765f15e2de870dcd6c843e19eb4960a0ed6f40f6cThomas Meyer		buf = kmalloc(data_len, GFP_KERNEL);
438877d89b08766c878a2594b15d203e513acf952340wwang		if (buf == NULL) {
438977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
439077d89b08766c878a2594b15d203e513acf952340wwang		}
439177d89b08766c878a2594b15d203e513acf952340wwang
439277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_get_xfer_buf(buf, data_len, srb);
439377d89b08766c878a2594b15d203e513acf952340wwang
439477d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
439577d89b08766c878a2594b15d203e513acf952340wwang		if (cmd_idx == LOCK_UNLOCK) {
439677d89b08766c878a2594b15d203e513acf952340wwang			lock_cmd_type = buf[0] & 0x0F;
439777d89b08766c878a2594b15d203e513acf952340wwang		}
439877d89b08766c878a2594b15d203e513acf952340wwang#endif
439977d89b08766c878a2594b15d203e513acf952340wwang
440077d89b08766c878a2594b15d203e513acf952340wwang		if (data_len > 256) {
440177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_init_cmd(chip);
440277d89b08766c878a2594b15d203e513acf952340wwang			for (i = 0; i < 256; i++) {
440377d89b08766c878a2594b15d203e513acf952340wwang				rtsx_add_cmd(chip, WRITE_REG_CMD,
440477d89b08766c878a2594b15d203e513acf952340wwang						PPBUF_BASE2 + i, 0xFF, buf[i]);
440577d89b08766c878a2594b15d203e513acf952340wwang			}
440677d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_send_cmd(chip, 0, 250);
440777d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
440877d89b08766c878a2594b15d203e513acf952340wwang				kfree(buf);
440977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
441077d89b08766c878a2594b15d203e513acf952340wwang			}
441177d89b08766c878a2594b15d203e513acf952340wwang
441277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_init_cmd(chip);
441377d89b08766c878a2594b15d203e513acf952340wwang			for (i = 256; i < data_len; i++) {
441477d89b08766c878a2594b15d203e513acf952340wwang				rtsx_add_cmd(chip, WRITE_REG_CMD,
441577d89b08766c878a2594b15d203e513acf952340wwang						PPBUF_BASE2 + i, 0xFF, buf[i]);
441677d89b08766c878a2594b15d203e513acf952340wwang			}
441777d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_send_cmd(chip, 0, 250);
441877d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
441977d89b08766c878a2594b15d203e513acf952340wwang				kfree(buf);
442077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
442177d89b08766c878a2594b15d203e513acf952340wwang			}
442277d89b08766c878a2594b15d203e513acf952340wwang		} else {
442377d89b08766c878a2594b15d203e513acf952340wwang			rtsx_init_cmd(chip);
442477d89b08766c878a2594b15d203e513acf952340wwang			for (i = 0; i < data_len; i++) {
442577d89b08766c878a2594b15d203e513acf952340wwang				rtsx_add_cmd(chip, WRITE_REG_CMD,
442677d89b08766c878a2594b15d203e513acf952340wwang						PPBUF_BASE2 + i, 0xFF, buf[i]);
442777d89b08766c878a2594b15d203e513acf952340wwang			}
442877d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_send_cmd(chip, 0, 250);
442977d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
443077d89b08766c878a2594b15d203e513acf952340wwang				kfree(buf);
443177d89b08766c878a2594b15d203e513acf952340wwang				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
443277d89b08766c878a2594b15d203e513acf952340wwang			}
443377d89b08766c878a2594b15d203e513acf952340wwang		}
443477d89b08766c878a2594b15d203e513acf952340wwang
443577d89b08766c878a2594b15d203e513acf952340wwang		kfree(buf);
443677d89b08766c878a2594b15d203e513acf952340wwang
443777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
443877d89b08766c878a2594b15d203e513acf952340wwang
443977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, srb->cmnd[8] & 0x03);
444077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, srb->cmnd[9]);
444177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0x00);
444277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 0x01);
444377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
444477d89b08766c878a2594b15d203e513acf952340wwang
444577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
444677d89b08766c878a2594b15d203e513acf952340wwang			     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
444777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
444877d89b08766c878a2594b15d203e513acf952340wwang
444977d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_send_cmd(chip, SD_CARD, 250);
445077d89b08766c878a2594b15d203e513acf952340wwang	} else if (!(data_len & 0x1FF)) {
445177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
445277d89b08766c878a2594b15d203e513acf952340wwang
445377d89b08766c878a2594b15d203e513acf952340wwang		trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
445477d89b08766c878a2594b15d203e513acf952340wwang
445577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
445677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
445777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
445877d89b08766c878a2594b15d203e513acf952340wwang				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
445977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
446077d89b08766c878a2594b15d203e513acf952340wwang				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
446177d89b08766c878a2594b15d203e513acf952340wwang
446277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
446377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
446477d89b08766c878a2594b15d203e513acf952340wwang
446577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_send_cmd_no_wait(chip);
446677d89b08766c878a2594b15d203e513acf952340wwang
446777d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
446877d89b08766c878a2594b15d203e513acf952340wwang			scsi_sg_count(srb), DMA_TO_DEVICE, 10000);
446977d89b08766c878a2594b15d203e513acf952340wwang
447077d89b08766c878a2594b15d203e513acf952340wwang	} else {
447177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
447277d89b08766c878a2594b15d203e513acf952340wwang	}
447377d89b08766c878a2594b15d203e513acf952340wwang
447477d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
447577d89b08766c878a2594b15d203e513acf952340wwang		write_err = 1;
447677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_clear_sd_error(chip);
447777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
447877d89b08766c878a2594b15d203e513acf952340wwang	}
447977d89b08766c878a2594b15d203e513acf952340wwang
448077d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
448177d89b08766c878a2594b15d203e513acf952340wwang	if (cmd_idx == LOCK_UNLOCK) {
448277d89b08766c878a2594b15d203e513acf952340wwang		if (lock_cmd_type == SD_ERASE) {
448377d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_erase_status = SD_UNDER_ERASING;
448477d89b08766c878a2594b15d203e513acf952340wwang			scsi_set_resid(srb, 0);
448577d89b08766c878a2594b15d203e513acf952340wwang			return TRANSPORT_GOOD;
448677d89b08766c878a2594b15d203e513acf952340wwang		}
448777d89b08766c878a2594b15d203e513acf952340wwang
448877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
448977d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209)) {
449077d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, SD_DAT0_STATUS);
449177d89b08766c878a2594b15d203e513acf952340wwang		} else {
449277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
449377d89b08766c878a2594b15d203e513acf952340wwang		}
449477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_send_cmd(chip, SD_CARD, 250);
449577d89b08766c878a2594b15d203e513acf952340wwang
449677d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_update_lock_status(chip);
449777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
449877d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("Lock command fail!\n");
449977d89b08766c878a2594b15d203e513acf952340wwang			lock_cmd_fail = 1;
450077d89b08766c878a2594b15d203e513acf952340wwang		}
450177d89b08766c878a2594b15d203e513acf952340wwang	}
450277d89b08766c878a2594b15d203e513acf952340wwang#endif /* SUPPORT_SD_LOCK */
450377d89b08766c878a2594b15d203e513acf952340wwang
450477d89b08766c878a2594b15d203e513acf952340wwang	if (standby) {
450577d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_select_card(chip, 1);
450677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
450777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
450877d89b08766c878a2594b15d203e513acf952340wwang		}
450977d89b08766c878a2594b15d203e513acf952340wwang	}
451077d89b08766c878a2594b15d203e513acf952340wwang
451177d89b08766c878a2594b15d203e513acf952340wwang	if (send_cmd12) {
451277d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
451377d89b08766c878a2594b15d203e513acf952340wwang				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
451477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
451577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
451677d89b08766c878a2594b15d203e513acf952340wwang		}
451777d89b08766c878a2594b15d203e513acf952340wwang	}
451877d89b08766c878a2594b15d203e513acf952340wwang
451977d89b08766c878a2594b15d203e513acf952340wwang	if (data_len < 512) {
452077d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
452177d89b08766c878a2594b15d203e513acf952340wwang				SD_RSP_TYPE_R1, NULL, 0, 0);
452277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
452377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
452477d89b08766c878a2594b15d203e513acf952340wwang		}
452577d89b08766c878a2594b15d203e513acf952340wwang
452677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
452777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
452877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
452977d89b08766c878a2594b15d203e513acf952340wwang		}
453077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
453177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
453277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
453377d89b08766c878a2594b15d203e513acf952340wwang		}
453477d89b08766c878a2594b15d203e513acf952340wwang	}
453577d89b08766c878a2594b15d203e513acf952340wwang
453677d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) {
453777d89b08766c878a2594b15d203e513acf952340wwang		cmd13_checkbit = 1;
453877d89b08766c878a2594b15d203e513acf952340wwang	}
453977d89b08766c878a2594b15d203e513acf952340wwang
454077d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < 3; i++) {
454177d89b08766c878a2594b15d203e513acf952340wwang		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
454277d89b08766c878a2594b15d203e513acf952340wwang			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
454377d89b08766c878a2594b15d203e513acf952340wwang		if (retval == STATUS_SUCCESS) {
454477d89b08766c878a2594b15d203e513acf952340wwang			break;
454577d89b08766c878a2594b15d203e513acf952340wwang		}
454677d89b08766c878a2594b15d203e513acf952340wwang	}
454777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
454877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
454977d89b08766c878a2594b15d203e513acf952340wwang	}
455077d89b08766c878a2594b15d203e513acf952340wwang
455177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
455277d89b08766c878a2594b15d203e513acf952340wwang	if (cmd_idx == LOCK_UNLOCK) {
455377d89b08766c878a2594b15d203e513acf952340wwang		if (!lock_cmd_fail) {
455477d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type);
455577d89b08766c878a2594b15d203e513acf952340wwang			if (lock_cmd_type & SD_CLR_PWD) {
455677d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_lock_status &= ~SD_PWD_EXIST;
455777d89b08766c878a2594b15d203e513acf952340wwang			}
455877d89b08766c878a2594b15d203e513acf952340wwang			if (lock_cmd_type & SD_SET_PWD) {
455977d89b08766c878a2594b15d203e513acf952340wwang				sd_card->sd_lock_status |= SD_PWD_EXIST;
456077d89b08766c878a2594b15d203e513acf952340wwang			}
456177d89b08766c878a2594b15d203e513acf952340wwang		}
456277d89b08766c878a2594b15d203e513acf952340wwang
456377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
456477d89b08766c878a2594b15d203e513acf952340wwang			     sd_lock_state, sd_card->sd_lock_status);
456577d89b08766c878a2594b15d203e513acf952340wwang		if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
456677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_lock_notify = 1;
456777d89b08766c878a2594b15d203e513acf952340wwang			if (sd_lock_state) {
456877d89b08766c878a2594b15d203e513acf952340wwang				if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) {
456977d89b08766c878a2594b15d203e513acf952340wwang					sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST);
457077d89b08766c878a2594b15d203e513acf952340wwang					if (CHK_SD(sd_card)) {
457177d89b08766c878a2594b15d203e513acf952340wwang						retval = reset_sd(chip);
457277d89b08766c878a2594b15d203e513acf952340wwang						if (retval != STATUS_SUCCESS) {
457377d89b08766c878a2594b15d203e513acf952340wwang							sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
457477d89b08766c878a2594b15d203e513acf952340wwang							TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
457577d89b08766c878a2594b15d203e513acf952340wwang						}
457677d89b08766c878a2594b15d203e513acf952340wwang					}
457777d89b08766c878a2594b15d203e513acf952340wwang
457877d89b08766c878a2594b15d203e513acf952340wwang					sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
457977d89b08766c878a2594b15d203e513acf952340wwang				}
458077d89b08766c878a2594b15d203e513acf952340wwang			}
458177d89b08766c878a2594b15d203e513acf952340wwang		}
458277d89b08766c878a2594b15d203e513acf952340wwang	}
458377d89b08766c878a2594b15d203e513acf952340wwang
458477d89b08766c878a2594b15d203e513acf952340wwang	if (lock_cmd_fail) {
458577d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, 0);
458677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
458777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
458877d89b08766c878a2594b15d203e513acf952340wwang	}
458977d89b08766c878a2594b15d203e513acf952340wwang#endif  /* SUPPORT_SD_LOCK */
459077d89b08766c878a2594b15d203e513acf952340wwang
459177d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
459277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
459377d89b08766c878a2594b15d203e513acf952340wwang
459477d89b08766c878a2594b15d203e513acf952340wwangSD_Execute_Write_Cmd_Failed:
459577d89b08766c878a2594b15d203e513acf952340wwang	sd_card->pre_cmd_err = 1;
459677d89b08766c878a2594b15d203e513acf952340wwang	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
459777d89b08766c878a2594b15d203e513acf952340wwang	if (write_err) {
459877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
459977d89b08766c878a2594b15d203e513acf952340wwang	}
460077d89b08766c878a2594b15d203e513acf952340wwang	release_sd_card(chip);
460177d89b08766c878a2594b15d203e513acf952340wwang	do_reset_sd_card(chip);
460277d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->card_ready & SD_CARD)) {
460377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
460477d89b08766c878a2594b15d203e513acf952340wwang	}
460577d89b08766c878a2594b15d203e513acf952340wwang
460677d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, TRANSPORT_FAILED);
460777d89b08766c878a2594b15d203e513acf952340wwang}
460877d89b08766c878a2594b15d203e513acf952340wwang
460977d89b08766c878a2594b15d203e513acf952340wwangint sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
461077d89b08766c878a2594b15d203e513acf952340wwang{
461177d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
461277d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
461377d89b08766c878a2594b15d203e513acf952340wwang	int count;
461477d89b08766c878a2594b15d203e513acf952340wwang	u16 data_len;
461577d89b08766c878a2594b15d203e513acf952340wwang
461677d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->sd_pass_thru_en) {
461777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
461877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
461977d89b08766c878a2594b15d203e513acf952340wwang	}
462077d89b08766c878a2594b15d203e513acf952340wwang
462177d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->pre_cmd_err) {
462277d89b08766c878a2594b15d203e513acf952340wwang		sd_card->pre_cmd_err = 0;
462377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
462477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
462577d89b08766c878a2594b15d203e513acf952340wwang	}
462677d89b08766c878a2594b15d203e513acf952340wwang
462777d89b08766c878a2594b15d203e513acf952340wwang	data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
462877d89b08766c878a2594b15d203e513acf952340wwang
462977d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
463077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
463177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
463277d89b08766c878a2594b15d203e513acf952340wwang	} else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
463377d89b08766c878a2594b15d203e513acf952340wwang		count = (data_len < 17) ? data_len : 17;
463477d89b08766c878a2594b15d203e513acf952340wwang	} else {
463577d89b08766c878a2594b15d203e513acf952340wwang		count = (data_len < 6) ? data_len : 6;
463677d89b08766c878a2594b15d203e513acf952340wwang	}
463777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
463877d89b08766c878a2594b15d203e513acf952340wwang
463977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("Response length: %d\n", data_len);
464077d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
464177d89b08766c878a2594b15d203e513acf952340wwang		sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], sd_card->rsp[3]);
464277d89b08766c878a2594b15d203e513acf952340wwang
464377d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
464477d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
464577d89b08766c878a2594b15d203e513acf952340wwang}
464677d89b08766c878a2594b15d203e513acf952340wwang
464777d89b08766c878a2594b15d203e513acf952340wwangint sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
464877d89b08766c878a2594b15d203e513acf952340wwang{
464977d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
465077d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
465177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
465277d89b08766c878a2594b15d203e513acf952340wwang
465377d89b08766c878a2594b15d203e513acf952340wwang	if (!sd_card->sd_pass_thru_en) {
465477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
465577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
465677d89b08766c878a2594b15d203e513acf952340wwang	}
465777d89b08766c878a2594b15d203e513acf952340wwang
465877d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->pre_cmd_err) {
465977d89b08766c878a2594b15d203e513acf952340wwang		sd_card->pre_cmd_err = 0;
466077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
466177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
466277d89b08766c878a2594b15d203e513acf952340wwang	}
466377d89b08766c878a2594b15d203e513acf952340wwang
466477d89b08766c878a2594b15d203e513acf952340wwang	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
466577d89b08766c878a2594b15d203e513acf952340wwang			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
466677d89b08766c878a2594b15d203e513acf952340wwang			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
466777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
466877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
466977d89b08766c878a2594b15d203e513acf952340wwang	}
467077d89b08766c878a2594b15d203e513acf952340wwang
467177d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[1] & 0x0F) {
467277d89b08766c878a2594b15d203e513acf952340wwang	case 0:
467377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
467477d89b08766c878a2594b15d203e513acf952340wwang		if (0x64 == srb->cmnd[9]) {
467577d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_lock_status |= SD_SDR_RST;
467677d89b08766c878a2594b15d203e513acf952340wwang		}
467777d89b08766c878a2594b15d203e513acf952340wwang#endif
467877d89b08766c878a2594b15d203e513acf952340wwang		retval = reset_sd_card(chip);
467977d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
468077d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
468177d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_lock_status &= ~SD_SDR_RST;
468277d89b08766c878a2594b15d203e513acf952340wwang#endif
468377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
468477d89b08766c878a2594b15d203e513acf952340wwang			sd_card->pre_cmd_err = 1;
468577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
468677d89b08766c878a2594b15d203e513acf952340wwang		}
468777d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
468877d89b08766c878a2594b15d203e513acf952340wwang		sd_card->sd_lock_status &= ~SD_SDR_RST;
468977d89b08766c878a2594b15d203e513acf952340wwang#endif
469077d89b08766c878a2594b15d203e513acf952340wwang		break;
469177d89b08766c878a2594b15d203e513acf952340wwang
469277d89b08766c878a2594b15d203e513acf952340wwang	case 1:
469377d89b08766c878a2594b15d203e513acf952340wwang		retval = soft_reset_sd_card(chip);
469477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
469577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
469677d89b08766c878a2594b15d203e513acf952340wwang			sd_card->pre_cmd_err = 1;
469777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
469877d89b08766c878a2594b15d203e513acf952340wwang		}
469977d89b08766c878a2594b15d203e513acf952340wwang		break;
470077d89b08766c878a2594b15d203e513acf952340wwang
470177d89b08766c878a2594b15d203e513acf952340wwang	default:
470277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
470377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
470477d89b08766c878a2594b15d203e513acf952340wwang	}
470577d89b08766c878a2594b15d203e513acf952340wwang
470677d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
470777d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
470877d89b08766c878a2594b15d203e513acf952340wwang}
470977d89b08766c878a2594b15d203e513acf952340wwang#endif
471077d89b08766c878a2594b15d203e513acf952340wwang
471177d89b08766c878a2594b15d203e513acf952340wwangvoid sd_cleanup_work(struct rtsx_chip *chip)
471277d89b08766c878a2594b15d203e513acf952340wwang{
471377d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
471477d89b08766c878a2594b15d203e513acf952340wwang
471577d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->seq_mode) {
471677d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD: stop transmission\n");
471777d89b08766c878a2594b15d203e513acf952340wwang		sd_stop_seq_mode(chip);
471877d89b08766c878a2594b15d203e513acf952340wwang		sd_card->cleanup_counter = 0;
471977d89b08766c878a2594b15d203e513acf952340wwang	}
472077d89b08766c878a2594b15d203e513acf952340wwang}
472177d89b08766c878a2594b15d203e513acf952340wwang
472277d89b08766c878a2594b15d203e513acf952340wwangint sd_power_off_card3v3(struct rtsx_chip *chip)
472377d89b08766c878a2594b15d203e513acf952340wwang{
472477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
472577d89b08766c878a2594b15d203e513acf952340wwang
472677d89b08766c878a2594b15d203e513acf952340wwang	retval = disable_card_clock(chip, SD_CARD);
472777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
472877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
472977d89b08766c878a2594b15d203e513acf952340wwang	}
473077d89b08766c878a2594b15d203e513acf952340wwang
473177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0);
473277d89b08766c878a2594b15d203e513acf952340wwang
473377d89b08766c878a2594b15d203e513acf952340wwang	if (!chip->ft2_fast_mode) {
473477d89b08766c878a2594b15d203e513acf952340wwang		retval = card_power_off(chip, SD_CARD);
473577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
473677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
473777d89b08766c878a2594b15d203e513acf952340wwang		}
473877d89b08766c878a2594b15d203e513acf952340wwang
473977d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(50);
474077d89b08766c878a2594b15d203e513acf952340wwang	}
474177d89b08766c878a2594b15d203e513acf952340wwang
474277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
474377d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_pull_ctl_disable(chip);
474477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
474577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
474677d89b08766c878a2594b15d203e513acf952340wwang		}
474777d89b08766c878a2594b15d203e513acf952340wwang	} else {
474877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
474977d89b08766c878a2594b15d203e513acf952340wwang			FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT);
475077d89b08766c878a2594b15d203e513acf952340wwang	}
475177d89b08766c878a2594b15d203e513acf952340wwang
475277d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
475377d89b08766c878a2594b15d203e513acf952340wwang}
475477d89b08766c878a2594b15d203e513acf952340wwang
475577d89b08766c878a2594b15d203e513acf952340wwangint release_sd_card(struct rtsx_chip *chip)
475677d89b08766c878a2594b15d203e513acf952340wwang{
475777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
475877d89b08766c878a2594b15d203e513acf952340wwang	int retval;
475977d89b08766c878a2594b15d203e513acf952340wwang
476077d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("release_sd_card\n");
476177d89b08766c878a2594b15d203e513acf952340wwang
476277d89b08766c878a2594b15d203e513acf952340wwang	chip->card_ready &= ~SD_CARD;
476377d89b08766c878a2594b15d203e513acf952340wwang	chip->card_fail &= ~SD_CARD;
476477d89b08766c878a2594b15d203e513acf952340wwang	chip->card_wp &= ~SD_CARD;
476577d89b08766c878a2594b15d203e513acf952340wwang
476677d89b08766c878a2594b15d203e513acf952340wwang	chip->sd_io = 0;
476777d89b08766c878a2594b15d203e513acf952340wwang	chip->sd_int = 0;
476877d89b08766c878a2594b15d203e513acf952340wwang
476977d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
477077d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_lock_status = 0;
477177d89b08766c878a2594b15d203e513acf952340wwang	sd_card->sd_erase_status = 0;
477277d89b08766c878a2594b15d203e513acf952340wwang#endif
477377d89b08766c878a2594b15d203e513acf952340wwang
477477d89b08766c878a2594b15d203e513acf952340wwang	memset(sd_card->raw_csd, 0, 16);
477577d89b08766c878a2594b15d203e513acf952340wwang	memset(sd_card->raw_scr, 0, 8);
477677d89b08766c878a2594b15d203e513acf952340wwang
477777d89b08766c878a2594b15d203e513acf952340wwang	retval = sd_power_off_card3v3(chip);
477877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
477977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, STATUS_FAIL);
478077d89b08766c878a2594b15d203e513acf952340wwang	}
478177d89b08766c878a2594b15d203e513acf952340wwang
478277d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5209)) {
478377d89b08766c878a2594b15d203e513acf952340wwang		retval = sd_change_bank_voltage(chip, SD_IO_3V3);
478477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
478577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, STATUS_FAIL);
478677d89b08766c878a2594b15d203e513acf952340wwang		}
478777d89b08766c878a2594b15d203e513acf952340wwang
478877d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD30_SPEED(sd_card)) {
478977d89b08766c878a2594b15d203e513acf952340wwang			RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3);
479077d89b08766c878a2594b15d203e513acf952340wwang		}
479177d89b08766c878a2594b15d203e513acf952340wwang
479277d89b08766c878a2594b15d203e513acf952340wwang		RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_400mA_ocp_thd);
479377d89b08766c878a2594b15d203e513acf952340wwang	}
479477d89b08766c878a2594b15d203e513acf952340wwang
479577d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
479677d89b08766c878a2594b15d203e513acf952340wwang}
4797