diff options
Diffstat (limited to 'drivers/staging/rts_pstor/sd.c')
-rw-r--r-- | drivers/staging/rts_pstor/sd.c | 4570 |
1 files changed, 0 insertions, 4570 deletions
diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c deleted file mode 100644 index c6a581c..0000000 --- a/drivers/staging/rts_pstor/sd.c +++ /dev/null @@ -1,4570 +0,0 @@ -/* Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> - -#include "rtsx.h" -#include "rtsx_transport.h" -#include "rtsx_scsi.h" -#include "rtsx_card.h" -#include "sd.h" - -#define SD_MAX_RETRY_COUNT 3 - -static u16 REG_SD_CFG1; -static u16 REG_SD_CFG2; -static u16 REG_SD_CFG3; -static u16 REG_SD_STAT1; -static u16 REG_SD_STAT2; -static u16 REG_SD_BUS_STAT; -static u16 REG_SD_PAD_CTL; -static u16 REG_SD_SAMPLE_POINT_CTL; -static u16 REG_SD_PUSH_POINT_CTL; -static u16 REG_SD_CMD0; -static u16 REG_SD_CMD1; -static u16 REG_SD_CMD2; -static u16 REG_SD_CMD3; -static u16 REG_SD_CMD4; -static u16 REG_SD_CMD5; -static u16 REG_SD_BYTE_CNT_L; -static u16 REG_SD_BYTE_CNT_H; -static u16 REG_SD_BLOCK_CNT_L; -static u16 REG_SD_BLOCK_CNT_H; -static u16 REG_SD_TRANSFER; -static u16 REG_SD_VPCLK0_CTL; -static u16 REG_SD_VPCLK1_CTL; -static u16 REG_SD_DCMPS0_CTL; -static u16 REG_SD_DCMPS1_CTL; - -static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->err_code |= err_code; -} - -static inline void sd_clr_err_code(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->err_code = 0; -} - -static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - return sd_card->err_code & err_code; -} - -static void sd_init_reg_addr(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5209)) { - REG_SD_CFG1 = SD_CFG1; - REG_SD_CFG2 = SD_CFG2; - REG_SD_CFG3 = SD_CFG3; - REG_SD_STAT1 = SD_STAT1; - REG_SD_STAT2 = SD_STAT2; - REG_SD_BUS_STAT = SD_BUS_STAT; - REG_SD_PAD_CTL = SD_PAD_CTL; - REG_SD_SAMPLE_POINT_CTL = SD_SAMPLE_POINT_CTL; - REG_SD_PUSH_POINT_CTL = SD_PUSH_POINT_CTL; - REG_SD_CMD0 = SD_CMD0; - REG_SD_CMD1 = SD_CMD1; - REG_SD_CMD2 = SD_CMD2; - REG_SD_CMD3 = SD_CMD3; - REG_SD_CMD4 = SD_CMD4; - REG_SD_CMD5 = SD_CMD5; - REG_SD_BYTE_CNT_L = SD_BYTE_CNT_L; - REG_SD_BYTE_CNT_H = SD_BYTE_CNT_H; - REG_SD_BLOCK_CNT_L = SD_BLOCK_CNT_L; - REG_SD_BLOCK_CNT_H = SD_BLOCK_CNT_H; - REG_SD_TRANSFER = SD_TRANSFER; - REG_SD_VPCLK0_CTL = SD_VPCLK0_CTL; - REG_SD_VPCLK1_CTL = SD_VPCLK1_CTL; - REG_SD_DCMPS0_CTL = SD_DCMPS0_CTL; - REG_SD_DCMPS1_CTL = SD_DCMPS1_CTL; - } else { - REG_SD_CFG1 = 0xFD31; - REG_SD_CFG2 = 0xFD33; - REG_SD_CFG3 = 0xFD3E; - REG_SD_STAT1 = 0xFD30; - REG_SD_STAT2 = 0; - REG_SD_BUS_STAT = 0; - REG_SD_PAD_CTL = 0; - REG_SD_SAMPLE_POINT_CTL = 0; - REG_SD_PUSH_POINT_CTL = 0; - REG_SD_CMD0 = 0xFD34; - REG_SD_CMD1 = 0xFD35; - REG_SD_CMD2 = 0xFD36; - REG_SD_CMD3 = 0xFD37; - REG_SD_CMD4 = 0xFD38; - REG_SD_CMD5 = 0xFD5A; - REG_SD_BYTE_CNT_L = 0xFD39; - REG_SD_BYTE_CNT_H = 0xFD3A; - REG_SD_BLOCK_CNT_L = 0xFD3B; - REG_SD_BLOCK_CNT_H = 0xFD3C; - REG_SD_TRANSFER = 0xFD32; - REG_SD_VPCLK0_CTL = 0; - REG_SD_VPCLK1_CTL = 0; - REG_SD_DCMPS0_CTL = 0; - REG_SD_DCMPS1_CTL = 0; - } -} - -static int sd_check_data0_status(struct rtsx_chip *chip) -{ - u8 stat; - - if (CHECK_PID(chip, 0x5209)) - RTSX_READ_REG(chip, REG_SD_BUS_STAT, &stat); - else - RTSX_READ_REG(chip, REG_SD_STAT1, &stat); - - if (!(stat & SD_DAT0_STATUS)) { - sd_set_err_code(chip, SD_BUSY); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int timeout = 100; - u16 reg_addr; - u8 *ptr; - int stat_idx = 0; - int rty_cnt = 0; - - sd_clr_err_code(chip); - - RTSX_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 16; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 5; - } - - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - u8 val; - - rtsx_read_register(chip, REG_SD_STAT1, &val); - RTSX_DEBUGP("SD_STAT1: 0x%x\n", val); - - if (CHECK_PID(chip, 0x5209)) { - rtsx_read_register(chip, REG_SD_STAT2, &val); - RTSX_DEBUGP("SD_STAT2: 0x%x\n", val); - - if (val & SD_RSP_80CLK_TIMEOUT) { - rtsx_clear_sd_error(chip); - sd_set_err_code(chip, SD_RSP_TIMEOUT); - TRACE_RET(chip, STATUS_FAIL); - } - - rtsx_read_register(chip, REG_SD_BUS_STAT, &val); - RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val); - } else { - rtsx_read_register(chip, REG_SD_CFG3, &val); - RTSX_DEBUGP("SD_CFG3: 0x%x\n", val); - } - - if (retval == -ETIMEDOUT) { - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - TRACE_RET(chip, retval); - } - } else { - sd_set_err_code(chip, SD_TO_ERR); - } - retval = STATUS_TIMEDOUT; - } else { - retval = STATUS_FAIL; - } - rtsx_clear_sd_error(chip); - - TRACE_RET(chip, retval); - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - ptr = rtsx_get_cmd_data(chip) + 1; - - if ((ptr[0] & 0xC0) != 0) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (ptr[stat_idx] & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) { - if ((cmd_idx != SEND_RELATIVE_ADDR) && (cmd_idx != SEND_IF_COND)) { - if (cmd_idx != STOP_TRANSMISSION) { - if (ptr[1] & 0x80) - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) -#else - if (ptr[1] & 0x7F) -#endif - { - RTSX_DEBUGP("ptr[1]: 0x%02x\n", ptr[1]); - TRACE_RET(chip, STATUS_FAIL); - } - if (ptr[2] & 0xFF) { - RTSX_DEBUGP("ptr[2]: 0x%02x\n", ptr[2]); - TRACE_RET(chip, STATUS_FAIL); - } - if (ptr[3] & 0x80) { - RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]); - TRACE_RET(chip, STATUS_FAIL); - } - if (ptr[3] & 0x01) - sd_card->sd_data_buf_ready = 1; - else - sd_card->sd_data_buf_ready = 0; - } - } - - if (rsp && rsp_len) - memcpy(rsp, ptr, rsp_len); - - return STATUS_SUCCESS; -} - -static int sd_read_data(struct rtsx_chip *chip, - u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt, - u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, - int timeout) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - if (buf_len > 512) - TRACE_RET(chip, STATUS_FAIL); - - rtsx_init_cmd(chip); - - if (cmd_len) { - RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, 0xFF, cmd[i]); - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - if (trans_mode != SD_TM_AUTO_TUNING) - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - TRACE_RET(chip, STATUS_FAIL); - } - - if (buf && buf_len) { - retval = rtsx_read_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, - u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width, - u8 *buf, int buf_len, int timeout) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - if (buf_len > 512) { - /* This function can't write data more than one page */ - TRACE_RET(chip, STATUS_FAIL); - } - - if (buf && buf_len) { - retval = rtsx_write_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - rtsx_init_cmd(chip); - - if (cmd_len) { - RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - REG_SD_CMD0 + i, 0xFF, cmd[i]); - } - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - } - - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_check_csd(struct rtsx_chip *chip, char check_wp) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - u8 csd_ver, trans_speed; - u8 rsp[16]; - - for (i = 0; i < 6; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, SD_RSP_TYPE_R2, rsp, 16); - if (retval == STATUS_SUCCESS) - break; - } - - if (i == 6) - TRACE_RET(chip, STATUS_FAIL); - - memcpy(sd_card->raw_csd, rsp + 1, 15); - - if (CHECK_PID(chip, 0x5209)) - RTSX_READ_REG(chip, REG_SD_CMD5, sd_card->raw_csd + 15); - - RTSX_DEBUGP("CSD Response:\n"); - RTSX_DUMP(sd_card->raw_csd, 16); - - csd_ver = (rsp[1] & 0xc0) >> 6; - RTSX_DEBUGP("csd_ver = %d\n", csd_ver); - - trans_speed = rsp[4]; - if ((trans_speed & 0x07) == 0x02) { - if ((trans_speed & 0xf8) >= 0x30) { - if (chip->asic_code) - sd_card->sd_clock = 47; - else - sd_card->sd_clock = CLK_50; - - } else if ((trans_speed & 0xf8) == 0x28) { - if (chip->asic_code) - sd_card->sd_clock = 39; - else - sd_card->sd_clock = CLK_40; - - } else if ((trans_speed & 0xf8) == 0x20) { - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - - } else if ((trans_speed & 0xf8) >= 0x10) { - if (chip->asic_code) - sd_card->sd_clock = 23; - else - sd_card->sd_clock = CLK_20; - - } else if ((trans_speed & 0x08) >= 0x08) { - if (chip->asic_code) - sd_card->sd_clock = 19; - else - sd_card->sd_clock = CLK_20; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - if (CHK_MMC_SECTOR_MODE(sd_card)) { - sd_card->capacity = 0; - } else { - if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) { - u8 blk_size, c_size_mult; - u16 c_size; - blk_size = rsp[6] & 0x0F; - c_size = ((u16)(rsp[7] & 0x03) << 10) - + ((u16)rsp[8] << 2) - + ((u16)(rsp[9] & 0xC0) >> 6); - c_size_mult = (u8)((rsp[10] & 0x03) << 1); - c_size_mult += (rsp[11] & 0x80) >> 7; - sd_card->capacity = (((u32)(c_size + 1)) * (1 << (c_size_mult + 2))) << (blk_size - 9); - } else { - u32 total_sector = 0; - total_sector = (((u32)rsp[8] & 0x3f) << 16) | - ((u32)rsp[9] << 8) | (u32)rsp[10]; - sd_card->capacity = (total_sector + 1) << 10; - } - } - - if (check_wp) { - if (rsp[15] & 0x30) - chip->card_wp |= SD_CARD; - - RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]); - } - - return STATUS_SUCCESS; -} - -static int sd_set_sample_push_timing(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - if (CHECK_PID(chip, 0x5209)) { - if (CHK_SD_SDR104(sd_card) || CHK_SD_SDR50(sd_card)) { - RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST, - SD_30_MODE | SD_ASYNC_FIFO_NOT_RST); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); - RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF, - CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); - } else if (CHK_SD_DDR50(sd_card) || CHK_MMC_DDR52(sd_card)) { - RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST, - SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); - RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF, - CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); - RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, DDR_VAR_TX_CMD_DAT, - DDR_VAR_TX_CMD_DAT); - RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, - DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); - } else { - u8 val = 0; - - RTSX_WRITE_REG(chip, SD_CFG1, 0x0C, SD_20_MODE); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); - RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF, - CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); - RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); - - if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO) - val = SD20_TX_NEG_EDGE; - else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) - val = SD20_TX_14_AHEAD; - else - val = SD20_TX_NEG_EDGE; - - RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, SD20_TX_SEL_MASK, val); - - if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { - if (chip->asic_code) { - if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) - val = SD20_RX_14_DELAY; - else - val = SD20_RX_POS_EDGE; - } else { - val = SD20_RX_14_DELAY; - } - } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) { - val = SD20_RX_14_DELAY; - } else { - val = SD20_RX_POS_EDGE; - } - RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, SD20_RX_SEL_MASK, val); - } - } else { - u8 val = 0; - - if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) - val |= 0x10; - - if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { - if (chip->asic_code) { - if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - } else { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - - RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val); - } - - return STATUS_SUCCESS; -} - -static void sd_choose_proper_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - if (CHK_SD_SDR104(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_sdr104_clk; - else - sd_card->sd_clock = chip->fpga_sd_sdr104_clk; - - } else if (CHK_SD_DDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_ddr50_clk; - else - sd_card->sd_clock = chip->fpga_sd_ddr50_clk; - - } else if (CHK_SD_SDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_sdr50_clk; - else - sd_card->sd_clock = chip->fpga_sd_sdr50_clk; - - } else if (CHK_SD_HS(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_hs_clk; - else - sd_card->sd_clock = chip->fpga_sd_hs_clk; - - } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_mmc_52m_clk; - else - sd_card->sd_clock = chip->fpga_mmc_52m_clk; - - } else if (CHK_MMC_26M(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = 48; - else - sd_card->sd_clock = CLK_50; - } -} - -static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div) -{ - u8 mask = 0, val = 0; - - if (CHECK_PID(chip, 0x5209)) { - mask = SD_CLK_DIVIDE_MASK; - val = clk_div; - } else { - mask = 0x60; - if (clk_div == SD_CLK_DIVIDE_0) - val = 0x00; - else if (clk_div == SD_CLK_DIVIDE_128) - val = 0x40; - else if (clk_div == SD_CLK_DIVIDE_256) - val = 0x20; - } - - RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val); - - return STATUS_SUCCESS; -} - -static int sd_set_init_para(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - sd_choose_proper_clock(chip); - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int sd_select_card(struct rtsx_chip *chip, int select) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd_idx, cmd_type; - u32 addr; - - if (select) { - cmd_idx = SELECT_CARD; - cmd_type = SD_RSP_TYPE_R1; - addr = sd_card->sd_addr; - } else { - cmd_idx = DESELECT_CARD; - cmd_type = SD_RSP_TYPE_R0; - addr = 0; - } - - retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -#ifdef SUPPORT_SD_LOCK -static int sd_update_lock_status(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 rsp[5]; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (rsp[1] & 0x02) - sd_card->sd_lock_status |= SD_LOCKED; - else - sd_card->sd_lock_status &= ~SD_LOCKED; - - RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", sd_card->sd_lock_status); - - if (rsp[1] & 0x01) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} -#endif - -static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_ready, int polling_cnt) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, i; - u8 rsp[5]; - - for (i = 0; i < polling_cnt; i++) { - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready)) - return STATUS_SUCCESS; - } - - TRACE_RET(chip, STATUS_FAIL); -} - -static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) -{ - int retval; - - if (voltage == SD_IO_3V3) { - if (chip->asic_code) { - retval = rtsx_write_phy_register(chip, 0x08, 0x4FC0 | chip->phy_voltage); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0); - } - } else if (voltage == SD_IO_1V8) { - if (chip->asic_code) { - retval = rtsx_write_phy_register(chip, 0x08, 0x4C40 | chip->phy_voltage); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8); - } - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_voltage_switch(struct rtsx_chip *chip) -{ - int retval; - u8 stat; - - RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, SD_CLK_TOGGLE_EN); - - retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - udelay(chip->sd_voltage_switch_delay); - - RTSX_READ_REG(chip, SD_BUS_STAT, &stat); - if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) { - TRACE_RET(chip, STATUS_FAIL); - } - - RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP); - retval = sd_change_bank_voltage(chip, SD_IO_1V8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - wait_timeout(50); - - RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); - wait_timeout(10); - - RTSX_READ_REG(chip, SD_BUS_STAT, &stat); - if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) != - (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) { - RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", stat); - rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); - rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); - - return STATUS_SUCCESS; -} - -static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir) -{ - if (tune_dir == TUNE_RX) { - RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX); - RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX); - } else { - RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX); - RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX); - } - - return STATUS_SUCCESS; -} - -static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) -{ - struct sd_info *sd_card = &(chip->sd_card); - u16 SD_VP_CTL, SD_DCMPS_CTL; - u8 val; - int retval; - int ddr_rx = 0; - - RTSX_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n", - sample_point, tune_dir); - - if (tune_dir == TUNE_RX) { - SD_VP_CTL = SD_VPRX_CTL; - SD_DCMPS_CTL = SD_DCMPS_RX_CTL; - if (CHK_SD_DDR50(sd_card)) - ddr_rx = 1; - } else { - SD_VP_CTL = SD_VPTX_CTL; - SD_DCMPS_CTL = SD_DCMPS_TX_CTL; - } - - if (chip->asic_code) { - RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK); - RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point); - RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); - RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); - RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0); - } else { -#ifdef CONFIG_RTS_PSTOR_DEBUG - rtsx_read_register(chip, SD_VP_CTL, &val); - RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val); - rtsx_read_register(chip, SD_DCMPS_CTL, &val); - RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); -#endif - - if (ddr_rx) { - RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, PHASE_CHANGE); - udelay(50); - RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF, - PHASE_CHANGE | PHASE_NOT_RESET | sample_point); - } else { - RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK); - udelay(50); - RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF, - PHASE_NOT_RESET | sample_point); - } - udelay(100); - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, DCMPS_CHANGE); - rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, Fail); - - val = *rtsx_get_cmd_data(chip); - if (val & DCMPS_ERROR) - TRACE_GOTO(chip, Fail); - - if ((val & DCMPS_CURRENT_PHASE) != sample_point) - TRACE_GOTO(chip, Fail); - - RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - if (ddr_rx) - RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0); - else - RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0); - - udelay(50); - } - - RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); - - return STATUS_SUCCESS; - -Fail: -#ifdef CONFIG_RTS_PSTOR_DEBUG - rtsx_read_register(chip, SD_VP_CTL, &val); - RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val); - rtsx_read_register(chip, SD_DCMPS_CTL, &val); - RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); -#endif - - rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0); - wait_timeout(10); - sd_reset_dcm(chip, tune_dir); - return STATUS_FAIL; -} - -static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], buf[8]; - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - cmd[0] = 0x40 | SEND_SCR; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, buf, 8, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - memcpy(sd_card->raw_scr, buf, 8); - - if ((buf[0] & 0x0F) == 0) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, u8 func_to_switch, - u8 *buf, int buf_len) -{ - u8 support_mask = 0, query_switch = 0, switch_busy = 0; - int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0; - - if (func_group == SD_FUNC_GROUP_1) { - support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case HS_SUPPORT: - support_mask = HS_SUPPORT_MASK; - query_switch = HS_QUERY_SWITCH_OK; - switch_busy = HS_SWITCH_BUSY; - break; - - case SDR50_SUPPORT: - support_mask = SDR50_SUPPORT_MASK; - query_switch = SDR50_QUERY_SWITCH_OK; - switch_busy = SDR50_SWITCH_BUSY; - break; - - case SDR104_SUPPORT: - support_mask = SDR104_SUPPORT_MASK; - query_switch = SDR104_QUERY_SWITCH_OK; - switch_busy = SDR104_SWITCH_BUSY; - break; - - case DDR50_SUPPORT: - support_mask = DDR50_SUPPORT_MASK; - query_switch = DDR50_QUERY_SWITCH_OK; - switch_busy = DDR50_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else if (func_group == SD_FUNC_GROUP_3) { - support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case DRIVING_TYPE_A: - support_mask = DRIVING_TYPE_A_MASK; - query_switch = TYPE_A_QUERY_SWITCH_OK; - switch_busy = TYPE_A_SWITCH_BUSY; - break; - - case DRIVING_TYPE_C: - support_mask = DRIVING_TYPE_C_MASK; - query_switch = TYPE_C_QUERY_SWITCH_OK; - switch_busy = TYPE_C_SWITCH_BUSY; - break; - - case DRIVING_TYPE_D: - support_mask = DRIVING_TYPE_D_MASK; - query_switch = TYPE_D_QUERY_SWITCH_OK; - switch_busy = TYPE_D_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else if (func_group == SD_FUNC_GROUP_4) { - support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case CURRENT_LIMIT_400: - support_mask = CURRENT_LIMIT_400_MASK; - query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_600: - support_mask = CURRENT_LIMIT_600_MASK; - query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_800: - support_mask = CURRENT_LIMIT_800_MASK; - query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - if (func_group == SD_FUNC_GROUP_1) { - if (!(buf[support_offset] & support_mask) || - ((buf[query_switch_offset] & 0x0F) != query_switch)) { - TRACE_RET(chip, STATUS_FAIL); - } - } - - /* Check 'Busy Status' */ - if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) && - ((buf[check_busy_offset] & switch_busy) == switch_busy)) { - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, - u8 func_group, u8 func_to_switch, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], buf[64]; - - RTSX_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n", - mode, func_group, func_to_switch); - - cmd[0] = 0x40 | SWITCH; - cmd[1] = mode; - - if (func_group == SD_FUNC_GROUP_1) { - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xF0 + func_to_switch; - } else if (func_group == SD_FUNC_GROUP_3) { - cmd[2] = 0xFF; - cmd[3] = 0xF0 + func_to_switch; - cmd[4] = 0xFF; - } else if (func_group == SD_FUNC_GROUP_4) { - cmd[2] = 0xFF; - cmd[3] = 0x0F + (func_to_switch << 4); - cmd[4] = 0xFF; - } else { - cmd[1] = SD_CHECK_MODE; - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xFF; - } - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, buf, 64, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - RTSX_DUMP(buf, 64); - - if (func_group == NO_ARGUMENT) { - sd_card->func_group1_mask = buf[0x0D]; - sd_card->func_group2_mask = buf[0x0B]; - sd_card->func_group3_mask = buf[0x09]; - sd_card->func_group4_mask = buf[0x07]; - - RTSX_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]); - RTSX_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]); - RTSX_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]); - RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]); - } else { - /* Maximum current consumption, check whether current is acceptable; - * bit[511:496] = 0x0000 means some error happened. - */ - u16 cc = ((u16)buf[0] << 8) | buf[1]; - RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc); - if ((cc == 0) || (cc > 800)) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_query_switch_result(chip, func_group, func_to_switch, buf, 64); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) { - RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_800mA_ocp_thd); - RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK, PMOS_STRG_800mA); - } - } - - return STATUS_SUCCESS; -} - -static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch) -{ - if (func_group == SD_FUNC_GROUP_1) { - if (func_to_switch > HS_SUPPORT) - func_to_switch--; - - } else if (func_group == SD_FUNC_GROUP_4) { - if (func_to_switch > CURRENT_LIMIT_200) - func_to_switch--; - } - - return func_to_switch; -} - -static int sd_check_switch(struct rtsx_chip *chip, - u8 func_group, u8 func_to_switch, u8 bus_width) -{ - int retval; - int i; - int switch_good = 0; - - for (i = 0; i < 3; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group, - func_to_switch, bus_width); - if (retval == STATUS_SUCCESS) { - u8 stat; - - retval = sd_check_switch_mode(chip, SD_SWITCH_MODE, - func_group, func_to_switch, bus_width); - if (retval == STATUS_SUCCESS) { - switch_good = 1; - break; - } - - RTSX_READ_REG(chip, SD_STAT1, &stat); - if (stat & SD_CRC16_ERR) { - RTSX_DEBUGP("SD CRC16 error when switching mode\n"); - TRACE_RET(chip, STATUS_FAIL); - } - } - - func_to_switch = downgrade_switch_mode(func_group, func_to_switch); - - wait_timeout(20); - } - - if (!switch_good) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - u8 func_to_switch = 0; - - /* Get supported functions */ - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, - NO_ARGUMENT, NO_ARGUMENT, bus_width); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail); - - /* Function Group 1: Access Mode */ - for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_speed_prior >> (i*8))) { - case SDR104_SUPPORT: - if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) - && chip->sdr104_en) { - func_to_switch = SDR104_SUPPORT; - } - break; - - case DDR50_SUPPORT: - if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) - && chip->ddr50_en) { - func_to_switch = DDR50_SUPPORT; - } - break; - - case SDR50_SUPPORT: - if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) - && chip->sdr50_en) { - func_to_switch = SDR50_SUPPORT; - } - break; - - case HS_SUPPORT: - if (sd_card->func_group1_mask & HS_SUPPORT_MASK) - func_to_switch = HS_SUPPORT; - - break; - - default: - continue; - } - - - if (func_to_switch) - break; - - } - RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_SDR_RST) - && (DDR50_SUPPORT == func_to_switch) - && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { - func_to_switch = SDR50_SUPPORT; - RTSX_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n"); - } -#endif - - if (func_to_switch) { - retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, bus_width); - if (retval != STATUS_SUCCESS) { - if (func_to_switch == SDR104_SUPPORT) { - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK; - } else if (func_to_switch == DDR50_SUPPORT) { - sd_card->sd_switch_fail = - SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK; - } else if (func_to_switch == SDR50_SUPPORT) { - sd_card->sd_switch_fail = - SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK | - SDR50_SUPPORT_MASK; - } - TRACE_RET(chip, STATUS_FAIL); - } - - if (func_to_switch == SDR104_SUPPORT) - SET_SD_SDR104(sd_card); - else if (func_to_switch == DDR50_SUPPORT) - SET_SD_DDR50(sd_card); - else if (func_to_switch == SDR50_SUPPORT) - SET_SD_SDR50(sd_card); - else - SET_SD_HS(sd_card); - } - - if (CHK_SD_DDR50(sd_card)) { - RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04); - retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - if (!func_to_switch || (func_to_switch == HS_SUPPORT)) { - /* Do not try to switch current limit if the card doesn't - * support UHS mode or we don't want it to support UHS mode - */ - return STATUS_SUCCESS; - } - - /* Function Group 4: Current Limit */ - func_to_switch = 0xFF; - - for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_current_prior >> (i*8))) { - case CURRENT_LIMIT_800: - if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) - func_to_switch = CURRENT_LIMIT_800; - - break; - - case CURRENT_LIMIT_600: - if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) - func_to_switch = CURRENT_LIMIT_600; - - break; - - case CURRENT_LIMIT_400: - if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) - func_to_switch = CURRENT_LIMIT_400; - - break; - - case CURRENT_LIMIT_200: - if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) - func_to_switch = CURRENT_LIMIT_200; - - break; - - default: - continue; - } - - if (func_to_switch != 0xFF) - break; - } - - RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch); - - if (func_to_switch <= CURRENT_LIMIT_800) { - retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, bus_width); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - TRACE_RET(chip, STATUS_FAIL); - } - RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval); - } - - if (CHK_SD_DDR50(sd_card)) - RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0); - - return STATUS_SUCCESS; -} - -static int sd_wait_data_idle(struct rtsx_chip *chip) -{ - int retval = STATUS_TIMEDOUT; - int i; - u8 val = 0; - - for (i = 0; i < 100; i++) { - RTSX_READ_REG(chip, SD_DATA_STATE, &val); - if (val & SD_DATA_IDLE) { - retval = STATUS_SUCCESS; - break; - } - udelay(100); - } - RTSX_DEBUGP("SD_DATA_STATE: 0x%02x\n", val); - - return retval; -} - -static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - cmd[0] = 0x40 | SEND_TUNING_PATTERN; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_AUTO_TUNING, - cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_DEBUGP("sd ddr tuning rx\n"); - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - cmd[0] = 0x40 | SD_STATUS; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], bus_width; - - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_DEBUGP("mmc ddr tuning rx\n"); - - cmd[0] = 0x40 | SEND_EXT_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 0x200, 1, bus_width, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN); - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) { - rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - } - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], bus_width; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHK_SD(sd_card)) { - bus_width = SD_BUS_WIDTH_4; - } else { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN); - - cmd[0] = 0x40 | PROGRAM_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, - cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - - return STATUS_SUCCESS; -} - -static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_dir) -{ - struct sd_info *sd_card = &(chip->sd_card); - struct timing_phase_path path[MAX_PHASE + 1]; - int i, j, cont_path_cnt; - int new_block, max_len, final_path_idx; - u8 final_phase = 0xFF; - - if (phase_map == 0xFFFFFFFF) { - if (tune_dir == TUNE_RX) - final_phase = (u8)chip->sd_default_rx_phase; - else - final_phase = (u8)chip->sd_default_tx_phase; - - goto Search_Finish; - } - - cont_path_cnt = 0; - new_block = 1; - j = 0; - for (i = 0; i < MAX_PHASE + 1; i++) { - if (phase_map & (1 << i)) { - if (new_block) { - new_block = 0; - j = cont_path_cnt++; - path[j].start = i; - path[j].end = i; - } else { - path[j].end = i; - } - } else { - new_block = 1; - if (cont_path_cnt) { - int idx = cont_path_cnt - 1; - path[idx].len = path[idx].end - path[idx].start + 1; - path[idx].mid = path[idx].start + path[idx].len / 2; - } - } - } - - if (cont_path_cnt == 0) { - RTSX_DEBUGP("No continuous phase path\n"); - goto Search_Finish; - } else { - int idx = cont_path_cnt - 1; - path[idx].len = path[idx].end - path[idx].start + 1; - path[idx].mid = path[idx].start + path[idx].len / 2; - } - - if ((path[0].start == 0) && (path[cont_path_cnt - 1].end == MAX_PHASE)) { - path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; - path[0].len += path[cont_path_cnt - 1].len; - path[0].mid = path[0].start + path[0].len / 2; - if (path[0].mid < 0) - path[0].mid += MAX_PHASE + 1; - - cont_path_cnt--; - } - - max_len = 0; - final_phase = 0; - final_path_idx = 0; - for (i = 0; i < cont_path_cnt; i++) { - if (path[i].len > max_len) { - max_len = path[i].len; - final_phase = (u8)path[i].mid; - final_path_idx = i; - } - - RTSX_DEBUGP("path[%d].start = %d\n", i, path[i].start); - RTSX_DEBUGP("path[%d].end = %d\n", i, path[i].end); - RTSX_DEBUGP("path[%d].len = %d\n", i, path[i].len); - RTSX_DEBUGP("path[%d].mid = %d\n", i, path[i].mid); - RTSX_DEBUGP("\n"); - } - - if (tune_dir == TUNE_TX) { - if (CHK_SD_SDR104(sd_card)) { - if (max_len > 15) { - int temp_mid = (max_len - 16) / 2; - int temp_final_phase = - path[final_path_idx].end - (max_len - (6 + temp_mid)); - - if (temp_final_phase < 0) - final_phase = (u8)(temp_final_phase + MAX_PHASE + 1); - else - final_phase = (u8)temp_final_phase; - } - } else if (CHK_SD_SDR50(sd_card)) { - if (max_len > 12) { - int temp_mid = (max_len - 13) / 2; - int temp_final_phase = - path[final_path_idx].end - (max_len - (3 + temp_mid)); - - if (temp_final_phase < 0) - final_phase = (u8)(temp_final_phase + MAX_PHASE + 1); - else - final_phase = (u8)temp_final_phase; - } - } - } - -Search_Finish: - RTSX_DEBUGP("Final chosen phase: %d\n", final_phase); - return final_phase; -} - -static int sd_tuning_rx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_rx_cmd; - else - tuning_cmd = sd_sdr_tuning_rx_cmd; - - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = mmc_ddr_tunning_rx_cmd; - else - TRACE_RET(chip, STATUS_FAIL); - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]); - - RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX); - if (final_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_change_phase(chip, final_phase, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - u32 phase_map; - u8 final_phase; - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN); - - phase_map = 0; - for (i = MAX_PHASE; i >= 0; i--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_change_phase(chip, (u8)i, TUNE_TX); - if (retval != STATUS_SUCCESS) - continue; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) - phase_map |= 1 << i; - } - - RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase); - - return STATUS_SUCCESS; -} - -static int sd_tuning_tx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - tuning_cmd = sd_sdr_tuning_tx_cmd; - - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - TRACE_RET(chip, STATUS_FAIL); - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]); - - RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning(struct rtsx_chip *chip) -{ - int retval; - - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning(struct rtsx_chip *chip) -{ - int retval; - - if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tuning(struct rtsx_chip *chip) -{ - int retval; - - if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -int sd_switch_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int re_tuning = 0; - - retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHECK_PID(chip, 0x5209) && - (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))) { - if (sd_card->need_retune && (sd_card->sd_clock != chip->cur_clk)) { - re_tuning = 1; - sd_card->need_retune = 0; - } - } - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (re_tuning) { - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - } else { - if (CHK_MMC_DDR52(sd_card)) - retval = mmc_ddr_tuning(chip); - } - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_prepare_reset(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - - sd_card->sd_type = 0; - sd_card->seq_mode = 0; - sd_card->sd_data_buf_ready = 0; - sd_card->capacity = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->sd_io = 0; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHECK_PID(chip, 0x5209)) { - RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, - SD_CLK_DIVIDE_128 | SD_20_MODE | SD_BUS_WIDTH_1); - RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, 0xFF, SD20_RX_POS_EDGE); - RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0xFF, 0); - } else { - RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40); - } - - RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR); - - retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_pull_ctl_disable(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5209)) { - RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55); - RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55); - RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5); - } else if (CHECK_PID(chip, 0x5208)) { - RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD); - RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, - SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD); - RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, - SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); - RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); - RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); - RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55); - RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55); - RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B); - RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69); - } - } - - return STATUS_SUCCESS; -} - -int sd_pull_ctl_enable(struct rtsx_chip *chip) -{ - int retval; - - rtsx_init_cmd(chip); - - if (CHECK_PID(chip, 0x5209)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xE9); - } else if (CHECK_PID(chip, 0x5208)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA8); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x5A); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xAA); - } - } - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval < 0) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_init_power(struct rtsx_chip *chip) -{ - int retval; - - if (CHECK_PID(chip, 0x5209)) - RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF); - - retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (!chip->ft2_fast_mode) - wait_timeout(250); - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (chip->asic_code) { - retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0); - } - - if (chip->ft2_fast_mode) { - if (CHECK_PID(chip, 0x5209)) - RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON); - - } else { - retval = card_power_on(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - wait_timeout(260); - -#ifdef SUPPORT_OCP - if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { - RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat); - TRACE_RET(chip, STATUS_FAIL); - } -#endif - } - - RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); - - return STATUS_SUCCESS; -} - -static int sd_dummy_clock(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5209)) { - RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN); - wait_timeout(5); - RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00); - } else { - RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01); - wait_timeout(5); - RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0); - } - - return STATUS_SUCCESS; -} - -static int sd_read_lba0(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], bus_width; - - cmd[0] = 0x40 | READ_SINGLE_BLOCK; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - if (CHK_SD(sd_card)) { - bus_width = SD_BUS_WIDTH_4; - } else { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, - 5, 512, 1, bus_width, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_check_wp_state(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u32 val; - u16 sd_card_type; - u8 cmd[5], buf[64]; - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - cmd[0] = 0x40 | SD_STATUS; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, SD_BUS_WIDTH_4, buf, 64, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - RTSX_DEBUGP("ACMD13:\n"); - RTSX_DUMP(buf, 64); - - sd_card_type = ((u16)buf[2] << 8) | buf[3]; - RTSX_DEBUGP("sd_card_type = 0x%04x\n", sd_card_type); - if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) { - /* ROM card or OTP */ - chip->card_wp |= SD_CARD; - } - - /* Check SD Machanical Write-Protect Switch */ - val = rtsx_readl(chip, RTSX_BIPR); - if (val & SD_WRITE_PROTECT) - chip->card_wp |= SD_CARD; - - return STATUS_SUCCESS; -} - -static int reset_sd(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0; - int sd_dont_switch = 0; - int support_1v8 = 0; - int try_sdio = 1; - u8 rsp[16]; - u8 switch_bus_width; - u32 voltage = 0; - int sd20_mode = 0; - - SET_SD(sd_card); - -Switch_Fail: - - i = 0; - j = 0; - k = 0; - hi_cap_flow = 0; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto SD_UNLOCK_ENTRY; -#endif - - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_dummy_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { - int rty_cnt = 0; - - for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5); - if (retval == STATUS_SUCCESS) { - int func_num = (rsp[1] >> 4) & 0x07; - if (func_num) { - RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num); - chip->sd_io = 1; - TRACE_RET(chip, STATUS_FAIL); - } - - break; - } - - sd_init_power(chip); - - sd_dummy_clock(chip); - } - - RTSX_DEBUGP("Normal card!\n"); - } - - /* Start Initialization Process of SD Card */ -RTY_SD_RST: - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - wait_timeout(20); - - retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, SD_RSP_TYPE_R7, rsp, 5); - if (retval == STATUS_SUCCESS) { - if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) { - hi_cap_flow = 1; - if (CHECK_PID(chip, 0x5209)) { - if (sd20_mode) { - voltage = SUPPORT_VOLTAGE | - SUPPORT_HIGH_AND_EXTENDED_CAPACITY; - } else { - voltage = SUPPORT_VOLTAGE | - SUPPORT_HIGH_AND_EXTENDED_CAPACITY | - SUPPORT_MAX_POWER_PERMANCE | SUPPORT_1V8; - } - } else { - voltage = SUPPORT_VOLTAGE | 0x40000000; - } - } - } - - if (!hi_cap_flow) { - voltage = SUPPORT_VOLTAGE; - - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - wait_timeout(20); - } - - do { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - j++; - if (j < 3) - goto RTY_SD_RST; - else - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - k++; - if (k < 3) - goto RTY_SD_RST; - else - TRACE_RET(chip, STATUS_FAIL); - } - - i++; - wait_timeout(20); - } while (!(rsp[1] & 0x80) && (i < 255)); - - if (i == 255) - TRACE_RET(chip, STATUS_FAIL); - - if (hi_cap_flow) { - if (rsp[1] & 0x40) - SET_SD_HCXC(sd_card); - else - CLR_SD_HCXC(sd_card); - - if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode) - support_1v8 = (rsp[1] & 0x01) ? 1 : 0; - else - support_1v8 = 0; - } else { - CLR_SD_HCXC(sd_card); - support_1v8 = 0; - } - RTSX_DEBUGP("support_1v8 = %d\n", support_1v8); - - if (support_1v8) { - retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - for (i = 0; i < 3; i++) { - retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - sd_card->sd_addr = (u32)rsp[1] << 24; - sd_card->sd_addr += (u32)rsp[2] << 16; - - if (sd_card->sd_addr) - break; - } - - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - -#ifdef SUPPORT_SD_LOCK -SD_UNLOCK_ENTRY: - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (sd_card->sd_lock_status & SD_LOCKED) { - sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); - return STATUS_SUCCESS; - } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) { - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - } -#endif - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (support_1v8) { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - switch_bus_width = SD_BUS_WIDTH_4; - } else { - switch_bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (!(sd_card->raw_csd[4] & 0x40)) - sd_dont_switch = 1; - - if (!sd_dont_switch) { - if (sd20_mode) { - /* Set sd_switch_fail here, because we needn't - * switch to UHS mode - */ - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | - DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK; - } - - /* Check the card whether follow SD1.1 spec or higher */ - retval = sd_check_spec(chip, switch_bus_width); - if (retval == STATUS_SUCCESS) { - retval = sd_switch_function(chip, switch_bus_width); - if (retval != STATUS_SUCCESS) { - if (CHECK_PID(chip, 0x5209)) - sd_change_bank_voltage(chip, SD_IO_3V3); - - sd_init_power(chip); - sd_dont_switch = 1; - try_sdio = 0; - - goto Switch_Fail; - } - } else { - if (support_1v8) { - if (CHECK_PID(chip, 0x5209)) - sd_change_bank_voltage(chip, SD_IO_3V3); - - sd_init_power(chip); - sd_dont_switch = 1; - try_sdio = 0; - - goto Switch_Fail; - } - } - } - - if (!support_1v8) { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - - if (!sd20_mode && CHK_SD30_SPEED(sd_card)) { - int read_lba0 = 1; - - RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_1v8); - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - - if (retval != STATUS_SUCCESS) { - if (sd20_mode) { - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - try_sdio = 0; - sd20_mode = 1; - goto Switch_Fail; - } - } - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - - if (CHK_SD_DDR50(sd_card)) { - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - read_lba0 = 0; - } - - if (read_lba0) { - retval = sd_read_lba0(chip); - if (retval != STATUS_SUCCESS) { - if (sd20_mode) { - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - try_sdio = 0; - sd20_mode = 1; - goto Switch_Fail; - } - } - } - } - - retval = sd_check_wp_state(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02); - RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00); - } -#endif - - return STATUS_SUCCESS; -} - - -static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 buf[8] = {0}, bus_width, *ptr; - u16 byte_cnt; - int len; - - retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, SWITCH_FAIL); - - if (width == MMC_8BIT_BUS) { - buf[0] = 0x55; - buf[1] = 0xAA; - len = 8; - byte_cnt = 8; - bus_width = SD_BUS_WIDTH_8; - } else { - buf[0] = 0x5A; - len = 4; - byte_cnt = 4; - bus_width = SD_BUS_WIDTH_4; - } - - if (!CHECK_PID(chip, 0x5209)) { - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, SWITCH_ERR); - } - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, - NULL, 0, byte_cnt, 1, bus_width, buf, len, 100); - if (retval != STATUS_SUCCESS) { - if (CHECK_PID(chip, 0x5209)) { - u8 val1 = 0, val2 = 0; - rtsx_read_register(chip, REG_SD_STAT1, &val1); - rtsx_read_register(chip, REG_SD_STAT2, &val2); - rtsx_clear_sd_error(chip); - if ((val1 & 0xE0) || val2) - TRACE_RET(chip, SWITCH_ERR); - } else { - rtsx_clear_sd_error(chip); - rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); - TRACE_RET(chip, SWITCH_ERR); - } - } - - if (!CHECK_PID(chip, 0x5209)) { - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, SWITCH_ERR); - } - - RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R); - - if (width == MMC_8BIT_BUS) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x08); - else - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x04); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); - if (width == MMC_8BIT_BUS) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval < 0) { - rtsx_clear_sd_error(chip); - TRACE_RET(chip, SWITCH_ERR); - } - - ptr = rtsx_get_cmd_data(chip) + 1; - - if (width == MMC_8BIT_BUS) { - RTSX_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", ptr[0], ptr[1]); - if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70600; - else - arg = 0x03B70200; - - retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) - return SWITCH_SUCCESS; - } - } else { - RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]); - if (ptr[0] == 0xA5) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70500; - else - arg = 0x03B70100; - - retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) - return SWITCH_SUCCESS; - } - } - - TRACE_RET(chip, SWITCH_FAIL); -} - - -static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 *ptr, card_type, card_type_mask = 0; - - CLR_MMC_HS(sd_card); - - RTSX_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | SEND_EXT_CSD); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 1000); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - rtsx_clear_sd_error(chip); - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - TRACE_RET(chip, STATUS_FAIL); - } - - ptr = rtsx_get_cmd_data(chip); - if (ptr[0] & SD_TRANSFER_ERR) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - if (CHK_MMC_SECTOR_MODE(sd_card)) { - sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) | - ((u32)ptr[3] << 8) | ((u32)ptr[2]); - } - - if (CHECK_PID(chip, 0x5209)) { -#ifdef SUPPORT_SD_LOCK - if (!(sd_card->sd_lock_status & SD_SDR_RST) && - (chip->sd_ctl & SUPPORT_MMC_DDR_MODE)) { - card_type_mask = 0x07; - } else { - card_type_mask = 0x03; - } -#else - if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE) - card_type_mask = 0x07; - else - card_type_mask = 0x03; -#endif - } else { - card_type_mask = 0x03; - } - card_type = ptr[1] & card_type_mask; - if (card_type) { - u8 rsp[5]; - - if (card_type & 0x04) { - if (switch_ddr) - SET_MMC_DDR52(sd_card); - else - SET_MMC_52M(sd_card); - } else if (card_type & 0x02) { - SET_MMC_52M(sd_card); - } else { - SET_MMC_26M(sd_card); - } - - retval = sd_send_cmd_get_rsp(chip, SWITCH, - 0x03B90100, SD_RSP_TYPE_R1b, rsp, 5); - if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) - CLR_MMC_HS(sd_card); - } - - sd_choose_proper_clock(chip); - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - /* Test Bus Procedure */ - retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS); - if (retval == SWITCH_SUCCESS) { - SET_MMC_8BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 8; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else if (retval == SWITCH_FAIL) { - retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS); - if (retval == SWITCH_SUCCESS) { - SET_MMC_4BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else if (retval == SWITCH_FAIL) { - CLR_MMC_8BIT(sd_card); - CLR_MMC_4BIT(sd_card); - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - - -static int reset_mmc(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, i = 0, j = 0, k = 0; - int switch_ddr = 1; - u8 rsp[16]; - u8 spec_ver = 0; - u32 temp; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto MMC_UNLOCK_ENTRY; -#endif - -Switch_Fail: - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - SET_MMC(sd_card); - -RTY_MMC_RST: - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - do { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND, - (SUPPORT_VOLTAGE|0x40000000), SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_BUSY) || sd_check_err_code(chip, SD_TO_ERR)) { - k++; - if (k < 20) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } else { - j++; - if (j < 100) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - wait_timeout(20); - i++; - } while (!(rsp[1] & 0x80) && (i < 255)); - - if (i == 255) - TRACE_RET(chip, STATUS_FAIL); - - if ((rsp[1] & 0x60) == 0x40) - SET_MMC_SECTOR_MODE(sd_card); - else - CLR_MMC_SECTOR_MODE(sd_card); - - retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - sd_card->sd_addr = 0x00100000; - retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2; - - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - -#ifdef SUPPORT_SD_LOCK -MMC_UNLOCK_ENTRY: - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); -#endif - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 1; - - if (!sd_card->mmc_dont_switch_bus) { - if (spec_ver == 4) { - /* MMC 4.x Cards */ - retval = mmc_switch_timing_bus(chip, switch_ddr); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - sd_card->mmc_dont_switch_bus = 1; - TRACE_GOTO(chip, Switch_Fail); - } - } - - if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) - TRACE_RET(chip, STATUS_FAIL); - - if (switch_ddr && CHK_MMC_DDR52(sd_card)) { - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = mmc_ddr_tuning(chip); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - switch_ddr = 0; - TRACE_GOTO(chip, Switch_Fail); - } - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval == STATUS_SUCCESS) { - retval = sd_read_lba0(chip); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - switch_ddr = 0; - TRACE_GOTO(chip, Switch_Fail); - } - } - } - } - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02); - RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00); - } -#endif - - temp = rtsx_readl(chip, RTSX_BIPR); - if (temp & SD_WRITE_PROTECT) - chip->card_wp |= SD_CARD; - - return STATUS_SUCCESS; -} - -int reset_sd_card(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - sd_init_reg_addr(chip); - - memset(sd_card, 0, sizeof(struct sd_info)); - chip->capacity[chip->card2lun[SD_CARD]] = 0; - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { - if (chip->asic_code) { - retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - retval = card_share_mode(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - chip->sd_io = 1; - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (chip->sd_ctl & RESET_MMC_FIRST) { - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - TRACE_RET(chip, STATUS_FAIL); - - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - if (CHECK_PID(chip, 0x5209)) - sd_change_bank_voltage(chip, SD_IO_3V3); - - TRACE_RET(chip, STATUS_FAIL); - } - } - } else { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - TRACE_RET(chip, STATUS_FAIL); - - if (CHECK_PID(chip, 0x5209)) { - retval = sd_change_bank_voltage(chip, SD_IO_3V3); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - if (chip->sd_io) { - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); - RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type); - - return STATUS_SUCCESS; -} - -static int reset_mmc_only(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - sd_card->sd_type = 0; - sd_card->seq_mode = 0; - sd_card->sd_data_buf_ready = 0; - sd_card->capacity = 0; - sd_card->sd_switch_fail = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0; - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); - RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", sd_card->sd_type); - - return STATUS_SUCCESS; -} - -#define WAIT_DATA_READY_RTY_CNT 255 - -static int wait_data_buf_ready(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int i, retval; - - for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - sd_card->sd_data_buf_ready = 0; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (sd_card->sd_data_buf_ready) { - return sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - } - } - - sd_set_err_code(chip, SD_TO_ERR); - - TRACE_RET(chip, STATUS_FAIL); -} - -void sd_stop_seq_mode(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (sd_card->seq_mode) { - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return; - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) - sd_set_err_code(chip, SD_STS_ERR); - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - sd_set_err_code(chip, SD_STS_ERR); - - sd_card->seq_mode = 0; - - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - } -} - -static inline int sd_auto_tune_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (chip->asic_code) { - if (sd_card->sd_clock > 30) - sd_card->sd_clock -= 20; - } else { - switch (sd_card->sd_clock) { - case CLK_200: - sd_card->sd_clock = CLK_150; - break; - - case CLK_150: - sd_card->sd_clock = CLK_120; - break; - - case CLK_120: - sd_card->sd_clock = CLK_100; - break; - - case CLK_100: - sd_card->sd_clock = CLK_80; - break; - - case CLK_80: - sd_card->sd_clock = CLK_60; - break; - - case CLK_60: - sd_card->sd_clock = CLK_50; - break; - - default: - break; - } - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt) -{ - struct sd_info *sd_card = &(chip->sd_card); - u32 data_addr; - u8 cfg2; - int retval; - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - RTSX_DEBUGP("sd_rw: Read %d %s from 0x%x\n", sector_cnt, - (sector_cnt > 1) ? "sectors" : "sector", start_sector); - } else { - RTSX_DEBUGP("sd_rw: Write %d %s to 0x%x\n", sector_cnt, - (sector_cnt > 1) ? "sectors" : "sector", start_sector); - } - - sd_card->cleanup_counter = 0; - - if (!(chip->card_ready & SD_CARD)) { - sd_card->seq_mode = 0; - - retval = reset_sd_card(chip); - if (retval == STATUS_SUCCESS) { - chip->card_ready |= SD_CARD; - chip->card_fail &= ~SD_CARD; - } else { - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->rw_need_retry = 1; - TRACE_RET(chip, STATUS_FAIL); - } - } - - if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) - data_addr = start_sector << 9; - else - data_addr = start_sector; - - sd_clr_err_code(chip); - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_IO_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - if (sd_card->seq_mode && ((sd_card->pre_dir != srb->sc_data_direction) - || ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != start_sector))) { - if ((sd_card->pre_sec_cnt < 0x80) - && (sd_card->pre_dir == DMA_FROM_DEVICE) - && !CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card)) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - } - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_STS_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - sd_card->seq_mode = 0; - - retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_IO_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - if ((sd_card->pre_sec_cnt < 0x80) - && !CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card)) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - } - } - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)sector_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(sector_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - - if (CHK_MMC_8BIT(sd_card)) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - else - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_1); - - if (sd_card->seq_mode) { - cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; - if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) - cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_3 | SD_TRANSFER_START); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - } - - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - RTSX_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | READ_MULTIPLE_BLOCK); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(data_addr >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(data_addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(data_addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)data_addr); - - cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6; - if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) - cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } else { - retval = rtsx_send_cmd(chip, SD_CARD, 50); - if (retval < 0) { - rtsx_clear_sd_error(chip); - - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_TO_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - retval = wait_data_buf_ready(chip); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_TO_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK, - data_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - TRACE_GOTO(chip, RW_FAIL); - } - - rtsx_init_cmd(chip); - - cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; - if (CHECK_PID(chip, 0x5209)) { - if (!CHK_SD30_SPEED(sd_card)) - cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } - - sd_card->seq_mode = 1; - } - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb), - scsi_sg_count(srb), srb->sc_data_direction, chip->sd_timeout); - if (retval < 0) { - u8 stat = 0; - int err; - - sd_card->seq_mode = 0; - - if (retval == -ETIMEDOUT) - err = STATUS_TIMEDOUT; - else - err = STATUS_FAIL; - - rtsx_read_register(chip, REG_SD_STAT1, &stat); - rtsx_clear_sd_error(chip); - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - chip->rw_need_retry = 0; - RTSX_DEBUGP("No card exist, exit sd_rw\n"); - TRACE_RET(chip, STATUS_FAIL); - } - - chip->rw_need_retry = 1; - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) { - RTSX_DEBUGP("SD CRC error, tune clock!\n"); - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - if (err == STATUS_TIMEDOUT) { - sd_set_err_code(chip, SD_TO_ERR); - TRACE_GOTO(chip, RW_FAIL); - } - - TRACE_RET(chip, err); - } - - sd_card->pre_sec_addr = start_sector; - sd_card->pre_sec_cnt = sector_cnt; - sd_card->pre_dir = srb->sc_data_direction; - - return STATUS_SUCCESS; - -RW_FAIL: - sd_card->seq_mode = 0; - - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - chip->rw_need_retry = 0; - RTSX_DEBUGP("No card exist, exit sd_rw\n"); - TRACE_RET(chip, STATUS_FAIL); - } - - if (sd_check_err_code(chip, SD_CRC_ERR)) { - if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) { - sd_card->mmc_dont_switch_bus = 1; - reset_mmc_only(chip); - sd_card->mmc_dont_switch_bus = 0; - } else { - sd_card->need_retune = 1; - sd_auto_tune_clock(chip); - } - } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) { - retval = reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - } - } - - TRACE_RET(chip, STATUS_FAIL); -} - -#ifdef SUPPORT_CPRM -int soft_reset_sd_card(struct rtsx_chip *chip) -{ - return reset_sd(chip); -} - -int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check) -{ - int retval; - int timeout = 100; - u16 reg_addr; - u8 *ptr; - int stat_idx = 0; - int rty_cnt = 0; - - RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 17; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 6; - } - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0); - - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - rtsx_clear_sd_error(chip); - - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - sd_set_err_code(chip, SD_TO_ERR); - } - } - TRACE_RET(chip, STATUS_FAIL); - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - ptr = rtsx_get_cmd_data(chip) + 1; - - if ((ptr[0] & 0xC0) != 0) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (ptr[stat_idx] & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || - (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { - if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) { - if (ptr[1] & 0x80) - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) -#else - if (ptr[1] & 0x7F) -#endif - { - TRACE_RET(chip, STATUS_FAIL); - } - if (ptr[2] & 0xF8) - TRACE_RET(chip, STATUS_FAIL); - - if (cmd_idx == SELECT_CARD) { - if (rsp_type == SD_RSP_TYPE_R2) { - if ((ptr[3] & 0x1E) != 0x04) - TRACE_RET(chip, STATUS_FAIL); - - } else if (rsp_type == SD_RSP_TYPE_R0) { - if ((ptr[3] & 0x1E) != 0x03) - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - if (rsp && rsp_len) - memcpy(rsp, ptr, rsp_len); - - return STATUS_SUCCESS; -} - -int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type) -{ - int retval, rsp_len; - u16 reg_addr; - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - rtsx_init_cmd(chip); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - - rsp_len = 17; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - - rsp_len = 6; - } - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (rsp) { - int min_len = (rsp_len < len) ? rsp_len : len; - - memcpy(rsp, rtsx_get_cmd_data(chip), min_len); - - RTSX_DEBUGP("min_len = %d\n", min_len); - RTSX_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n", - rsp[0], rsp[1], rsp[2], rsp[3]); - } - - return STATUS_SUCCESS; -} - -int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int len; - u8 buf[18] = { - 0x00, - 0x00, - 0x00, - 0x0E, - 0x00, - 0x00, - 0x00, - 0x00, - 0x53, - 0x44, - 0x20, - 0x43, - 0x61, - 0x72, - 0x64, - 0x00, - 0x00, - 0x00, - }; - - sd_card->pre_cmd_err = 0; - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) || - (0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) || - (0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: - sd_card->sd_pass_thru_en = 0; - break; - - case 1: - sd_card->sd_pass_thru_en = 1; - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; - if (chip->card_wp & SD_CARD) - buf[5] |= 0x80; - - buf[6] = (u8)(sd_card->sd_addr >> 16); - buf[7] = (u8)(sd_card->sd_addr >> 24); - - buf[15] = chip->max_lun; - - len = min(18, (int)scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, len, srb); - - return TRANSPORT_GOOD; -} - -static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int *rsp_len) -{ - if (!rsp_type || !rsp_len) - return STATUS_FAIL; - - switch (srb->cmnd[10]) { - case 0x03: - *rsp_type = SD_RSP_TYPE_R0; - *rsp_len = 0; - break; - - case 0x04: - *rsp_type = SD_RSP_TYPE_R1; - *rsp_len = 6; - break; - - case 0x05: - *rsp_type = SD_RSP_TYPE_R1b; - *rsp_len = 6; - break; - - case 0x06: - *rsp_type = SD_RSP_TYPE_R2; - *rsp_len = 17; - break; - - case 0x07: - *rsp_type = SD_RSP_TYPE_R3; - *rsp_len = 6; - break; - - default: - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len; - u8 cmd_idx, rsp_type; - u8 standby = 0, acmd = 0; - u32 arg; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x02) - standby = 1; - - if (srb->cmnd[1] & 0x01) - acmd = 1; - - arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | - ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#else - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); -#endif - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } - -#ifdef SUPPORT_SD_LOCK - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); -#endif - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -SD_Execute_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len, i; - int cmd13_checkbit = 0, read_err = 0; - u8 cmd_idx, rsp_type, bus_width; - u8 send_cmd12 = 0, standby = 0, acmd = 0; - u32 data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = 1; - - if (srb->cmnd[1] & 0x02) - standby = 1; - - if (srb->cmnd[1] & 0x01) - acmd = 1; - - data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9]; - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } else { - bus_width = SD_BUS_WIDTH_4; - } - RTSX_DEBUGP("bus_width = %d\n", bus_width); -#else - bus_width = SD_BUS_WIDTH_4; -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (data_len <= 512) { - int min_len; - u8 *buf; - u16 byte_cnt, blk_cnt; - u8 cmd[5]; - - byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9]; - blk_cnt = 1; - - cmd[0] = 0x40 | cmd_idx; - cmd[1] = srb->cmnd[3]; - cmd[2] = srb->cmnd[4]; - cmd[3] = srb->cmnd[5]; - cmd[4] = srb->cmnd[6]; - - buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, - blk_cnt, bus_width, buf, data_len, 2000); - if (retval != STATUS_SUCCESS) { - read_err = 1; - kfree(buf); - rtsx_clear_sd_error(chip); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - min_len = min(data_len, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, min_len, srb); - - kfree(buf); - } else if (!(data_len & 0x1FF)) { - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, srb->cmnd[3]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, srb->cmnd[4]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, srb->cmnd[5]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, srb->cmnd[6]); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb), - scsi_sg_count(srb), DMA_FROM_DEVICE, 10000); - if (retval < 0) { - read_err = 1; - rtsx_clear_sd_error(chip); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - } else { - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) - cmd13_checkbit = 1; - - for (i = 0; i < 3; i++) { - retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -SD_Execute_Read_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (read_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len, i; - int cmd13_checkbit = 0, write_err = 0; - u8 cmd_idx, rsp_type; - u8 send_cmd12 = 0, standby = 0, acmd = 0; - u32 data_len, arg; -#ifdef SUPPORT_SD_LOCK - int lock_cmd_fail = 0; - u8 sd_lock_state = 0; - u8 lock_cmd_type = 0; -#endif - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = 1; - - if (srb->cmnd[1] & 0x02) - standby = 1; - - if (srb->cmnd[1] & 0x01) - acmd = 1; - - data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9]; - arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | - ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - sd_lock_state = sd_card->sd_lock_status; - sd_lock_state &= SD_LOCKED; - } -#endif - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#else - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - if (data_len <= 512) { - u16 i; - u8 *buf; - - buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - rtsx_stor_get_xfer_buf(buf, data_len, srb); - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) - lock_cmd_type = buf[0] & 0x0F; -#endif - - if (data_len > 256) { - rtsx_init_cmd(chip); - for (i = 0; i < 256; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - rtsx_init_cmd(chip); - for (i = 256; i < data_len; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - } else { - rtsx_init_cmd(chip); - for (i = 0; i < data_len; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - } - - kfree(buf); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, srb->cmnd[8] & 0x03); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, srb->cmnd[9]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 0x01); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, 250); - } else if (!(data_len & 0x1FF)) { - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb), - scsi_sg_count(srb), DMA_TO_DEVICE, 10000); - - } else { - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (retval < 0) { - write_err = 1; - rtsx_clear_sd_error(chip); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (lock_cmd_type == SD_ERASE) { - sd_card->sd_erase_status = SD_UNDER_ERASING; - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - rtsx_init_cmd(chip); - if (CHECK_PID(chip, 0x5209)) - rtsx_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, SD_DAT0_STATUS); - else - rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02); - - rtsx_send_cmd(chip, SD_CARD, 250); - - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) { - RTSX_DEBUGP("Lock command fail!\n"); - lock_cmd_fail = 1; - } - } -#endif /* SUPPORT_SD_LOCK */ - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) - cmd13_checkbit = 1; - - for (i = 0; i < 3; i++) { - retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (!lock_cmd_fail) { - RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type); - if (lock_cmd_type & SD_CLR_PWD) - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - - if (lock_cmd_type & SD_SET_PWD) - sd_card->sd_lock_status |= SD_PWD_EXIST; - } - - RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n", - sd_lock_state, sd_card->sd_lock_status); - if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) { - sd_card->sd_lock_notify = 1; - if (sd_lock_state) { - if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) { - sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST); - if (CHK_SD(sd_card)) { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - } - - sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); - } - } - } - } - - if (lock_cmd_fail) { - scsi_set_resid(srb, 0); - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - TRACE_RET(chip, TRANSPORT_FAILED); - } -#endif /* SUPPORT_SD_LOCK */ - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -SD_Execute_Write_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (write_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int count; - u16 data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8]; - - if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) { - count = (data_len < 17) ? data_len : 17; - } else { - count = (data_len < 6) ? data_len : 6; - } - rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb); - - RTSX_DEBUGP("Response length: %d\n", data_len); - RTSX_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n", - sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], sd_card->rsp[3]); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) || - (0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) || - (0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: -#ifdef SUPPORT_SD_LOCK - if (0x64 == srb->cmnd[9]) - sd_card->sd_lock_status |= SD_SDR_RST; -#endif - retval = reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - TRACE_RET(chip, TRANSPORT_FAILED); - } -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - break; - - case 1: - retval = soft_reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -void sd_cleanup_work(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - if (sd_card->seq_mode) { - RTSX_DEBUGP("SD: stop transmission\n"); - sd_stop_seq_mode(chip); - sd_card->cleanup_counter = 0; - } -} - -int sd_power_off_card3v3(struct rtsx_chip *chip) -{ - int retval; - - retval = disable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0); - - if (!chip->ft2_fast_mode) { - retval = card_power_off(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - wait_timeout(50); - } - - if (chip->asic_code) { - retval = sd_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - RTSX_WRITE_REG(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT); - } - - return STATUS_SUCCESS; -} - -int release_sd_card(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - RTSX_DEBUGP("release_sd_card\n"); - - chip->card_ready &= ~SD_CARD; - chip->card_fail &= ~SD_CARD; - chip->card_wp &= ~SD_CARD; - - chip->sd_io = 0; - chip->sd_int = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - memset(sd_card->raw_csd, 0, 16); - memset(sd_card->raw_scr, 0, 8); - - retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHECK_PID(chip, 0x5209)) { - retval = sd_change_bank_voltage(chip, SD_IO_3V3); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (CHK_SD30_SPEED(sd_card)) - RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3); - - RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_400mA_ocp_thd); - } - - return STATUS_SUCCESS; -} |