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