162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* Realtek PCI-Express SD/MMC Card Interface driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: 762306a36Sopenharmony_ci * Wei WANG <wei_wang@realsil.com.cn> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/highmem.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/platform_device.h> 1562306a36Sopenharmony_ci#include <linux/workqueue.h> 1662306a36Sopenharmony_ci#include <linux/mmc/host.h> 1762306a36Sopenharmony_ci#include <linux/mmc/mmc.h> 1862306a36Sopenharmony_ci#include <linux/mmc/sd.h> 1962306a36Sopenharmony_ci#include <linux/mmc/sdio.h> 2062306a36Sopenharmony_ci#include <linux/mmc/card.h> 2162306a36Sopenharmony_ci#include <linux/rtsx_pci.h> 2262306a36Sopenharmony_ci#include <asm/unaligned.h> 2362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct realtek_pci_sdmmc { 2662306a36Sopenharmony_ci struct platform_device *pdev; 2762306a36Sopenharmony_ci struct rtsx_pcr *pcr; 2862306a36Sopenharmony_ci struct mmc_host *mmc; 2962306a36Sopenharmony_ci struct mmc_request *mrq; 3062306a36Sopenharmony_ci#define SDMMC_WORKQ_NAME "rtsx_pci_sdmmc_workq" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci struct work_struct work; 3362306a36Sopenharmony_ci struct mutex host_mutex; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci u8 ssc_depth; 3662306a36Sopenharmony_ci unsigned int clock; 3762306a36Sopenharmony_ci bool vpclk; 3862306a36Sopenharmony_ci bool double_clk; 3962306a36Sopenharmony_ci bool eject; 4062306a36Sopenharmony_ci bool initial_mode; 4162306a36Sopenharmony_ci int prev_power_state; 4262306a36Sopenharmony_ci int sg_count; 4362306a36Sopenharmony_ci s32 cookie; 4462306a36Sopenharmony_ci int cookie_sg_count; 4562306a36Sopenharmony_ci bool using_cookie; 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return &(host->pdev->dev); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic inline void sd_clear_error(struct realtek_pci_sdmmc *host) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci rtsx_pci_write_register(host->pcr, CARD_STOP, 5862306a36Sopenharmony_ci SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#ifdef DEBUG 6262306a36Sopenharmony_cistatic void dump_reg_range(struct realtek_pci_sdmmc *host, u16 start, u16 end) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci u16 len = end - start + 1; 6562306a36Sopenharmony_ci int i; 6662306a36Sopenharmony_ci u8 data[8]; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci for (i = 0; i < len; i += 8) { 6962306a36Sopenharmony_ci int j; 7062306a36Sopenharmony_ci int n = min(8, len - i); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci memset(&data, 0, sizeof(data)); 7362306a36Sopenharmony_ci for (j = 0; j < n; j++) 7462306a36Sopenharmony_ci rtsx_pci_read_register(host->pcr, start + i + j, 7562306a36Sopenharmony_ci data + j); 7662306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "0x%04X(%d): %8ph\n", 7762306a36Sopenharmony_ci start + i, n, data); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic void sd_print_debug_regs(struct realtek_pci_sdmmc *host) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci dump_reg_range(host, 0xFDA0, 0xFDB3); 8462306a36Sopenharmony_ci dump_reg_range(host, 0xFD52, 0xFD69); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci#else 8762306a36Sopenharmony_ci#define sd_print_debug_regs(host) 8862306a36Sopenharmony_ci#endif /* DEBUG */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic inline int sd_get_cd_int(struct realtek_pci_sdmmc *host) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci return rtsx_pci_readl(host->pcr, RTSX_BIPR) & SD_EXIST; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic void sd_cmd_set_sd_cmd(struct rtsx_pcr *pcr, struct mmc_command *cmd) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 9862306a36Sopenharmony_ci SD_CMD_START | cmd->opcode); 9962306a36Sopenharmony_ci rtsx_pci_write_be32(pcr, SD_CMD1, cmd->arg); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic void sd_cmd_set_data_len(struct rtsx_pcr *pcr, u16 blocks, u16 blksz) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, blocks); 10562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, blocks >> 8); 10662306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, blksz); 10762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, blksz >> 8); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int sd_response_type(struct mmc_command *cmd) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci switch (mmc_resp_type(cmd)) { 11362306a36Sopenharmony_ci case MMC_RSP_NONE: 11462306a36Sopenharmony_ci return SD_RSP_TYPE_R0; 11562306a36Sopenharmony_ci case MMC_RSP_R1: 11662306a36Sopenharmony_ci return SD_RSP_TYPE_R1; 11762306a36Sopenharmony_ci case MMC_RSP_R1_NO_CRC: 11862306a36Sopenharmony_ci return SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; 11962306a36Sopenharmony_ci case MMC_RSP_R1B: 12062306a36Sopenharmony_ci return SD_RSP_TYPE_R1b; 12162306a36Sopenharmony_ci case MMC_RSP_R2: 12262306a36Sopenharmony_ci return SD_RSP_TYPE_R2; 12362306a36Sopenharmony_ci case MMC_RSP_R3: 12462306a36Sopenharmony_ci return SD_RSP_TYPE_R3; 12562306a36Sopenharmony_ci default: 12662306a36Sopenharmony_ci return -EINVAL; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic int sd_status_index(int resp_type) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci if (resp_type == SD_RSP_TYPE_R0) 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci else if (resp_type == SD_RSP_TYPE_R2) 13562306a36Sopenharmony_ci return 16; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return 5; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci/* 14062306a36Sopenharmony_ci * sd_pre_dma_transfer - do dma_map_sg() or using cookie 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * @pre: if called in pre_req() 14362306a36Sopenharmony_ci * return: 14462306a36Sopenharmony_ci * 0 - do dma_map_sg() 14562306a36Sopenharmony_ci * 1 - using cookie 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_cistatic int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, 14862306a36Sopenharmony_ci struct mmc_data *data, bool pre) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 15162306a36Sopenharmony_ci int read = data->flags & MMC_DATA_READ; 15262306a36Sopenharmony_ci int count = 0; 15362306a36Sopenharmony_ci int using_cookie = 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (!pre && data->host_cookie && data->host_cookie != host->cookie) { 15662306a36Sopenharmony_ci dev_err(sdmmc_dev(host), 15762306a36Sopenharmony_ci "error: data->host_cookie = %d, host->cookie = %d\n", 15862306a36Sopenharmony_ci data->host_cookie, host->cookie); 15962306a36Sopenharmony_ci data->host_cookie = 0; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci if (pre || data->host_cookie != host->cookie) { 16362306a36Sopenharmony_ci count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read); 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci count = host->cookie_sg_count; 16662306a36Sopenharmony_ci using_cookie = 1; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (pre) { 17062306a36Sopenharmony_ci host->cookie_sg_count = count; 17162306a36Sopenharmony_ci if (++host->cookie < 0) 17262306a36Sopenharmony_ci host->cookie = 1; 17362306a36Sopenharmony_ci data->host_cookie = host->cookie; 17462306a36Sopenharmony_ci } else { 17562306a36Sopenharmony_ci host->sg_count = count; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci return using_cookie; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 18462306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (data->host_cookie) { 18762306a36Sopenharmony_ci dev_err(sdmmc_dev(host), 18862306a36Sopenharmony_ci "error: reset data->host_cookie = %d\n", 18962306a36Sopenharmony_ci data->host_cookie); 19062306a36Sopenharmony_ci data->host_cookie = 0; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci sd_pre_dma_transfer(host, data, true); 19462306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count); 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 19862306a36Sopenharmony_ci int err) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 20162306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 20262306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 20362306a36Sopenharmony_ci int read = data->flags & MMC_DATA_READ; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); 20662306a36Sopenharmony_ci data->host_cookie = 0; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, 21062306a36Sopenharmony_ci struct mmc_command *cmd) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 21362306a36Sopenharmony_ci u8 cmd_idx = (u8)cmd->opcode; 21462306a36Sopenharmony_ci u32 arg = cmd->arg; 21562306a36Sopenharmony_ci int err = 0; 21662306a36Sopenharmony_ci int timeout = 100; 21762306a36Sopenharmony_ci int i; 21862306a36Sopenharmony_ci u8 *ptr; 21962306a36Sopenharmony_ci int rsp_type; 22062306a36Sopenharmony_ci int stat_idx; 22162306a36Sopenharmony_ci bool clock_toggled = false; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 22462306a36Sopenharmony_ci __func__, cmd_idx, arg); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci rsp_type = sd_response_type(cmd); 22762306a36Sopenharmony_ci if (rsp_type < 0) 22862306a36Sopenharmony_ci goto out; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci stat_idx = sd_status_index(rsp_type); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (rsp_type == SD_RSP_TYPE_R1b) 23362306a36Sopenharmony_ci timeout = cmd->busy_timeout ? cmd->busy_timeout : 3000; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (cmd->opcode == SD_SWITCH_VOLTAGE) { 23662306a36Sopenharmony_ci err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 23762306a36Sopenharmony_ci 0xFF, SD_CLK_TOGGLE_EN); 23862306a36Sopenharmony_ci if (err < 0) 23962306a36Sopenharmony_ci goto out; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci clock_toggled = true; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 24562306a36Sopenharmony_ci sd_cmd_set_sd_cmd(pcr, cmd); 24662306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); 24762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 24862306a36Sopenharmony_ci 0x01, PINGPONG_BUFFER); 24962306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 25062306a36Sopenharmony_ci 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); 25162306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, 25262306a36Sopenharmony_ci SD_TRANSFER_END | SD_STAT_IDLE, 25362306a36Sopenharmony_ci SD_TRANSFER_END | SD_STAT_IDLE); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (rsp_type == SD_RSP_TYPE_R2) { 25662306a36Sopenharmony_ci /* Read data from ping-pong buffer */ 25762306a36Sopenharmony_ci for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) 25862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); 25962306a36Sopenharmony_ci } else if (rsp_type != SD_RSP_TYPE_R0) { 26062306a36Sopenharmony_ci /* Read data from SD_CMDx registers */ 26162306a36Sopenharmony_ci for (i = SD_CMD0; i <= SD_CMD4; i++) 26262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, timeout); 26862306a36Sopenharmony_ci if (err < 0) { 26962306a36Sopenharmony_ci sd_print_debug_regs(host); 27062306a36Sopenharmony_ci sd_clear_error(host); 27162306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 27262306a36Sopenharmony_ci "rtsx_pci_send_cmd error (err = %d)\n", err); 27362306a36Sopenharmony_ci goto out; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (rsp_type == SD_RSP_TYPE_R0) { 27762306a36Sopenharmony_ci err = 0; 27862306a36Sopenharmony_ci goto out; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Eliminate returned value of CHECK_REG_CMD */ 28262306a36Sopenharmony_ci ptr = rtsx_pci_get_cmd_data(pcr) + 1; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* Check (Start,Transmission) bit of Response */ 28562306a36Sopenharmony_ci if ((ptr[0] & 0xC0) != 0) { 28662306a36Sopenharmony_ci err = -EILSEQ; 28762306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); 28862306a36Sopenharmony_ci goto out; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* Check CRC7 */ 29262306a36Sopenharmony_ci if (!(rsp_type & SD_NO_CHECK_CRC7)) { 29362306a36Sopenharmony_ci if (ptr[stat_idx] & SD_CRC7_ERR) { 29462306a36Sopenharmony_ci err = -EILSEQ; 29562306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "CRC7 error\n"); 29662306a36Sopenharmony_ci goto out; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (rsp_type == SD_RSP_TYPE_R2) { 30162306a36Sopenharmony_ci /* 30262306a36Sopenharmony_ci * The controller offloads the last byte {CRC-7, end bit 1'b1} 30362306a36Sopenharmony_ci * of response type R2. Assign dummy CRC, 0, and end bit to the 30462306a36Sopenharmony_ci * byte(ptr[16], goes into the LSB of resp[3] later). 30562306a36Sopenharmony_ci */ 30662306a36Sopenharmony_ci ptr[16] = 1; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 30962306a36Sopenharmony_ci cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); 31062306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", 31162306a36Sopenharmony_ci i, cmd->resp[i]); 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci } else { 31462306a36Sopenharmony_ci cmd->resp[0] = get_unaligned_be32(ptr + 1); 31562306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", 31662306a36Sopenharmony_ci cmd->resp[0]); 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ciout: 32062306a36Sopenharmony_ci cmd->error = err; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (err && clock_toggled) 32362306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_BUS_STAT, 32462306a36Sopenharmony_ci SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic int sd_read_data(struct realtek_pci_sdmmc *host, struct mmc_command *cmd, 32862306a36Sopenharmony_ci u16 byte_cnt, u8 *buf, int buf_len, int timeout) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 33162306a36Sopenharmony_ci int err; 33262306a36Sopenharmony_ci u8 trans_mode; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 33562306a36Sopenharmony_ci __func__, cmd->opcode, cmd->arg); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (!buf) 33862306a36Sopenharmony_ci buf_len = 0; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (cmd->opcode == MMC_SEND_TUNING_BLOCK) 34162306a36Sopenharmony_ci trans_mode = SD_TM_AUTO_TUNING; 34262306a36Sopenharmony_ci else 34362306a36Sopenharmony_ci trans_mode = SD_TM_NORMAL_READ; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 34662306a36Sopenharmony_ci sd_cmd_set_sd_cmd(pcr, cmd); 34762306a36Sopenharmony_ci sd_cmd_set_data_len(pcr, 1, byte_cnt); 34862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, 34962306a36Sopenharmony_ci SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 35062306a36Sopenharmony_ci SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); 35162306a36Sopenharmony_ci if (trans_mode != SD_TM_AUTO_TUNING) 35262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 35362306a36Sopenharmony_ci CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 35662306a36Sopenharmony_ci 0xFF, trans_mode | SD_TRANSFER_START); 35762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, 35862306a36Sopenharmony_ci SD_TRANSFER_END, SD_TRANSFER_END); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, timeout); 36162306a36Sopenharmony_ci if (err < 0) { 36262306a36Sopenharmony_ci sd_print_debug_regs(host); 36362306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 36462306a36Sopenharmony_ci "rtsx_pci_send_cmd fail (err = %d)\n", err); 36562306a36Sopenharmony_ci return err; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (buf && buf_len) { 36962306a36Sopenharmony_ci err = rtsx_pci_read_ppbuf(pcr, buf, buf_len); 37062306a36Sopenharmony_ci if (err < 0) { 37162306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 37262306a36Sopenharmony_ci "rtsx_pci_read_ppbuf fail (err = %d)\n", err); 37362306a36Sopenharmony_ci return err; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci return 0; 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic int sd_write_data(struct realtek_pci_sdmmc *host, 38162306a36Sopenharmony_ci struct mmc_command *cmd, u16 byte_cnt, u8 *buf, int buf_len, 38262306a36Sopenharmony_ci int timeout) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 38562306a36Sopenharmony_ci int err; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 38862306a36Sopenharmony_ci __func__, cmd->opcode, cmd->arg); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (!buf) 39162306a36Sopenharmony_ci buf_len = 0; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci sd_send_cmd_get_rsp(host, cmd); 39462306a36Sopenharmony_ci if (cmd->error) 39562306a36Sopenharmony_ci return cmd->error; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (buf && buf_len) { 39862306a36Sopenharmony_ci err = rtsx_pci_write_ppbuf(pcr, buf, buf_len); 39962306a36Sopenharmony_ci if (err < 0) { 40062306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 40162306a36Sopenharmony_ci "rtsx_pci_write_ppbuf fail (err = %d)\n", err); 40262306a36Sopenharmony_ci return err; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 40762306a36Sopenharmony_ci sd_cmd_set_data_len(pcr, 1, byte_cnt); 40862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, 40962306a36Sopenharmony_ci SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 41062306a36Sopenharmony_ci SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0); 41162306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 41262306a36Sopenharmony_ci SD_TRANSFER_START | SD_TM_AUTO_WRITE_3); 41362306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, 41462306a36Sopenharmony_ci SD_TRANSFER_END, SD_TRANSFER_END); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, timeout); 41762306a36Sopenharmony_ci if (err < 0) { 41862306a36Sopenharmony_ci sd_print_debug_regs(host); 41962306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 42062306a36Sopenharmony_ci "rtsx_pci_send_cmd fail (err = %d)\n", err); 42162306a36Sopenharmony_ci return err; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return 0; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic int sd_read_long_data(struct realtek_pci_sdmmc *host, 42862306a36Sopenharmony_ci struct mmc_request *mrq) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 43162306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 43262306a36Sopenharmony_ci struct mmc_card *card = mmc->card; 43362306a36Sopenharmony_ci struct mmc_command *cmd = mrq->cmd; 43462306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 43562306a36Sopenharmony_ci int uhs = mmc_card_uhs(card); 43662306a36Sopenharmony_ci u8 cfg2 = 0; 43762306a36Sopenharmony_ci int err; 43862306a36Sopenharmony_ci int resp_type; 43962306a36Sopenharmony_ci size_t data_len = data->blksz * data->blocks; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 44262306a36Sopenharmony_ci __func__, cmd->opcode, cmd->arg); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci resp_type = sd_response_type(cmd); 44562306a36Sopenharmony_ci if (resp_type < 0) 44662306a36Sopenharmony_ci return resp_type; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (!uhs) 44962306a36Sopenharmony_ci cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 45262306a36Sopenharmony_ci sd_cmd_set_sd_cmd(pcr, cmd); 45362306a36Sopenharmony_ci sd_cmd_set_data_len(pcr, data->blocks, data->blksz); 45462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, 45562306a36Sopenharmony_ci DMA_DONE_INT, DMA_DONE_INT); 45662306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 45762306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 24)); 45862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 45962306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 16)); 46062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 46162306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 8)); 46262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); 46362306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 46462306a36Sopenharmony_ci 0x03 | DMA_PACK_SIZE_MASK, 46562306a36Sopenharmony_ci DMA_DIR_FROM_CARD | DMA_EN | DMA_512); 46662306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 46762306a36Sopenharmony_ci 0x01, RING_BUFFER); 46862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2 | resp_type); 46962306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 47062306a36Sopenharmony_ci SD_TRANSFER_START | SD_TM_AUTO_READ_2); 47162306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, 47262306a36Sopenharmony_ci SD_TRANSFER_END, SD_TRANSFER_END); 47362306a36Sopenharmony_ci rtsx_pci_send_cmd_no_wait(pcr); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, 1, 10000); 47662306a36Sopenharmony_ci if (err < 0) { 47762306a36Sopenharmony_ci sd_print_debug_regs(host); 47862306a36Sopenharmony_ci sd_clear_error(host); 47962306a36Sopenharmony_ci return err; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return 0; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic int sd_write_long_data(struct realtek_pci_sdmmc *host, 48662306a36Sopenharmony_ci struct mmc_request *mrq) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 48962306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 49062306a36Sopenharmony_ci struct mmc_card *card = mmc->card; 49162306a36Sopenharmony_ci struct mmc_command *cmd = mrq->cmd; 49262306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 49362306a36Sopenharmony_ci int uhs = mmc_card_uhs(card); 49462306a36Sopenharmony_ci u8 cfg2; 49562306a36Sopenharmony_ci int err; 49662306a36Sopenharmony_ci size_t data_len = data->blksz * data->blocks; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci sd_send_cmd_get_rsp(host, cmd); 49962306a36Sopenharmony_ci if (cmd->error) 50062306a36Sopenharmony_ci return cmd->error; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 50362306a36Sopenharmony_ci __func__, cmd->opcode, cmd->arg); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | 50662306a36Sopenharmony_ci SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (!uhs) 50962306a36Sopenharmony_ci cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 51262306a36Sopenharmony_ci sd_cmd_set_data_len(pcr, data->blocks, data->blksz); 51362306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, 51462306a36Sopenharmony_ci DMA_DONE_INT, DMA_DONE_INT); 51562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 51662306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 24)); 51762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 51862306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 16)); 51962306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 52062306a36Sopenharmony_ci 0xFF, (u8)(data_len >> 8)); 52162306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); 52262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 52362306a36Sopenharmony_ci 0x03 | DMA_PACK_SIZE_MASK, 52462306a36Sopenharmony_ci DMA_DIR_TO_CARD | DMA_EN | DMA_512); 52562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 52662306a36Sopenharmony_ci 0x01, RING_BUFFER); 52762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); 52862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 52962306a36Sopenharmony_ci SD_TRANSFER_START | SD_TM_AUTO_WRITE_3); 53062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, 53162306a36Sopenharmony_ci SD_TRANSFER_END, SD_TRANSFER_END); 53262306a36Sopenharmony_ci rtsx_pci_send_cmd_no_wait(pcr); 53362306a36Sopenharmony_ci err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, 0, 10000); 53462306a36Sopenharmony_ci if (err < 0) { 53562306a36Sopenharmony_ci sd_clear_error(host); 53662306a36Sopenharmony_ci return err; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return 0; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci rtsx_pci_write_register(host->pcr, SD_CFG1, 54562306a36Sopenharmony_ci SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci rtsx_pci_write_register(host->pcr, SD_CFG1, 55162306a36Sopenharmony_ci SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 55762306a36Sopenharmony_ci int err; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (host->sg_count < 0) { 56062306a36Sopenharmony_ci data->error = host->sg_count; 56162306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: sg_count = %d is invalid\n", 56262306a36Sopenharmony_ci __func__, host->sg_count); 56362306a36Sopenharmony_ci return data->error; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (data->flags & MMC_DATA_READ) { 56762306a36Sopenharmony_ci if (host->initial_mode) 56862306a36Sopenharmony_ci sd_disable_initial_mode(host); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci err = sd_read_long_data(host, mrq); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (host->initial_mode) 57362306a36Sopenharmony_ci sd_enable_initial_mode(host); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return err; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci return sd_write_long_data(host, mrq); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic void sd_normal_rw(struct realtek_pci_sdmmc *host, 58262306a36Sopenharmony_ci struct mmc_request *mrq) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci struct mmc_command *cmd = mrq->cmd; 58562306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 58662306a36Sopenharmony_ci u8 *buf; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci buf = kzalloc(data->blksz, GFP_NOIO); 58962306a36Sopenharmony_ci if (!buf) { 59062306a36Sopenharmony_ci cmd->error = -ENOMEM; 59162306a36Sopenharmony_ci return; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (data->flags & MMC_DATA_READ) { 59562306a36Sopenharmony_ci if (host->initial_mode) 59662306a36Sopenharmony_ci sd_disable_initial_mode(host); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, 59962306a36Sopenharmony_ci data->blksz, 200); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (host->initial_mode) 60262306a36Sopenharmony_ci sd_enable_initial_mode(host); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); 60562306a36Sopenharmony_ci } else { 60662306a36Sopenharmony_ci sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, 60962306a36Sopenharmony_ci data->blksz, 200); 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci kfree(buf); 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic int sd_change_phase(struct realtek_pci_sdmmc *host, 61662306a36Sopenharmony_ci u8 sample_point, bool rx) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 61962306a36Sopenharmony_ci u16 SD_VP_CTL = 0; 62062306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", 62162306a36Sopenharmony_ci __func__, rx ? "RX" : "TX", sample_point); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, CHANGE_CLK); 62462306a36Sopenharmony_ci if (rx) { 62562306a36Sopenharmony_ci SD_VP_CTL = SD_VPRX_CTL; 62662306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_VPRX_CTL, 62762306a36Sopenharmony_ci PHASE_SELECT_MASK, sample_point); 62862306a36Sopenharmony_ci } else { 62962306a36Sopenharmony_ci SD_VP_CTL = SD_VPTX_CTL; 63062306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_VPTX_CTL, 63162306a36Sopenharmony_ci PHASE_SELECT_MASK, sample_point); 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, 0); 63462306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, 63562306a36Sopenharmony_ci PHASE_NOT_RESET); 63662306a36Sopenharmony_ci rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, 0); 63762306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return 0; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic inline u32 test_phase_bit(u32 phase_map, unsigned int bit) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci bit %= RTSX_PHASE_MAX; 64562306a36Sopenharmony_ci return phase_map & (1 << bit); 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_cistatic int sd_get_phase_len(u32 phase_map, unsigned int start_bit) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci int i; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci for (i = 0; i < RTSX_PHASE_MAX; i++) { 65362306a36Sopenharmony_ci if (test_phase_bit(phase_map, start_bit + i) == 0) 65462306a36Sopenharmony_ci return i; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci return RTSX_PHASE_MAX; 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci int start = 0, len = 0; 66262306a36Sopenharmony_ci int start_final = 0, len_final = 0; 66362306a36Sopenharmony_ci u8 final_phase = 0xFF; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (phase_map == 0) { 66662306a36Sopenharmony_ci dev_err(sdmmc_dev(host), "phase error: [map:%x]\n", phase_map); 66762306a36Sopenharmony_ci return final_phase; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci while (start < RTSX_PHASE_MAX) { 67162306a36Sopenharmony_ci len = sd_get_phase_len(phase_map, start); 67262306a36Sopenharmony_ci if (len_final < len) { 67362306a36Sopenharmony_ci start_final = start; 67462306a36Sopenharmony_ci len_final = len; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci start += len ? len : 1; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci final_phase = (start_final + len_final / 2) % RTSX_PHASE_MAX; 68062306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "phase: [map:%x] [maxlen:%d] [final:%d]\n", 68162306a36Sopenharmony_ci phase_map, len_final, final_phase); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return final_phase; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic void sd_wait_data_idle(struct realtek_pci_sdmmc *host) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci int i; 68962306a36Sopenharmony_ci u8 val = 0; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci for (i = 0; i < 100; i++) { 69262306a36Sopenharmony_ci rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val); 69362306a36Sopenharmony_ci if (val & SD_DATA_IDLE) 69462306a36Sopenharmony_ci return; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci udelay(100); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host, 70162306a36Sopenharmony_ci u8 opcode, u8 sample_point) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci int err; 70462306a36Sopenharmony_ci struct mmc_command cmd = {}; 70562306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci sd_change_phase(host, sample_point, true); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 71062306a36Sopenharmony_ci SD_RSP_80CLK_TIMEOUT_EN); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci cmd.opcode = opcode; 71362306a36Sopenharmony_ci err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); 71462306a36Sopenharmony_ci if (err < 0) { 71562306a36Sopenharmony_ci /* Wait till SD DATA IDLE */ 71662306a36Sopenharmony_ci sd_wait_data_idle(host); 71762306a36Sopenharmony_ci sd_clear_error(host); 71862306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_CFG3, 71962306a36Sopenharmony_ci SD_RSP_80CLK_TIMEOUT_EN, 0); 72062306a36Sopenharmony_ci return err; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); 72462306a36Sopenharmony_ci return 0; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic int sd_tuning_phase(struct realtek_pci_sdmmc *host, 72862306a36Sopenharmony_ci u8 opcode, u32 *phase_map) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci int err, i; 73162306a36Sopenharmony_ci u32 raw_phase_map = 0; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci for (i = 0; i < RTSX_PHASE_MAX; i++) { 73462306a36Sopenharmony_ci err = sd_tuning_rx_cmd(host, opcode, (u8)i); 73562306a36Sopenharmony_ci if (err == 0) 73662306a36Sopenharmony_ci raw_phase_map |= 1 << i; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (phase_map) 74062306a36Sopenharmony_ci *phase_map = raw_phase_map; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return 0; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci int err, i; 74862306a36Sopenharmony_ci u32 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; 74962306a36Sopenharmony_ci u8 final_phase; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci for (i = 0; i < RX_TUNING_CNT; i++) { 75262306a36Sopenharmony_ci err = sd_tuning_phase(host, opcode, &(raw_phase_map[i])); 75362306a36Sopenharmony_ci if (err < 0) 75462306a36Sopenharmony_ci return err; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (raw_phase_map[i] == 0) 75762306a36Sopenharmony_ci break; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci phase_map = 0xFFFFFFFF; 76162306a36Sopenharmony_ci for (i = 0; i < RX_TUNING_CNT; i++) { 76262306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%08x\n", 76362306a36Sopenharmony_ci i, raw_phase_map[i]); 76462306a36Sopenharmony_ci phase_map &= raw_phase_map[i]; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%08x\n", phase_map); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (phase_map) { 76962306a36Sopenharmony_ci final_phase = sd_search_final_phase(host, phase_map); 77062306a36Sopenharmony_ci if (final_phase == 0xFF) 77162306a36Sopenharmony_ci return -EINVAL; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci err = sd_change_phase(host, final_phase, true); 77462306a36Sopenharmony_ci if (err < 0) 77562306a36Sopenharmony_ci return err; 77662306a36Sopenharmony_ci } else { 77762306a36Sopenharmony_ci return -EINVAL; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci return 0; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic inline int sdio_extblock_cmd(struct mmc_command *cmd, 78462306a36Sopenharmony_ci struct mmc_data *data) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci return (cmd->opcode == SD_IO_RW_EXTENDED) && (data->blksz == 512); 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic inline int sd_rw_cmd(struct mmc_command *cmd) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci return mmc_op_multi(cmd->opcode) || 79262306a36Sopenharmony_ci (cmd->opcode == MMC_READ_SINGLE_BLOCK) || 79362306a36Sopenharmony_ci (cmd->opcode == MMC_WRITE_BLOCK); 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic void sd_request(struct work_struct *work) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = container_of(work, 79962306a36Sopenharmony_ci struct realtek_pci_sdmmc, work); 80062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 80362306a36Sopenharmony_ci struct mmc_request *mrq = host->mrq; 80462306a36Sopenharmony_ci struct mmc_command *cmd = mrq->cmd; 80562306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci unsigned int data_size = 0; 80862306a36Sopenharmony_ci int err; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci if (host->eject || !sd_get_cd_int(host)) { 81162306a36Sopenharmony_ci cmd->error = -ENOMEDIUM; 81262306a36Sopenharmony_ci goto finish; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); 81662306a36Sopenharmony_ci if (err) { 81762306a36Sopenharmony_ci cmd->error = err; 81862306a36Sopenharmony_ci goto finish; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, 82662306a36Sopenharmony_ci host->initial_mode, host->double_clk, host->vpclk); 82762306a36Sopenharmony_ci rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL); 82862306a36Sopenharmony_ci rtsx_pci_write_register(pcr, CARD_SHARE_MODE, 82962306a36Sopenharmony_ci CARD_SHARE_MASK, CARD_SHARE_48_SD); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci mutex_lock(&host->host_mutex); 83262306a36Sopenharmony_ci host->mrq = mrq; 83362306a36Sopenharmony_ci mutex_unlock(&host->host_mutex); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci if (mrq->data) 83662306a36Sopenharmony_ci data_size = data->blocks * data->blksz; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci if (!data_size) { 83962306a36Sopenharmony_ci sd_send_cmd_get_rsp(host, cmd); 84062306a36Sopenharmony_ci } else if (sd_rw_cmd(cmd) || sdio_extblock_cmd(cmd, data)) { 84162306a36Sopenharmony_ci cmd->error = sd_rw_multi(host, mrq); 84262306a36Sopenharmony_ci if (!host->using_cookie) 84362306a36Sopenharmony_ci sdmmc_post_req(host->mmc, host->mrq, 0); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (mmc_op_multi(cmd->opcode) && mrq->stop) 84662306a36Sopenharmony_ci sd_send_cmd_get_rsp(host, mrq->stop); 84762306a36Sopenharmony_ci } else { 84862306a36Sopenharmony_ci sd_normal_rw(host, mrq); 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci if (mrq->data) { 85262306a36Sopenharmony_ci if (cmd->error || data->error) 85362306a36Sopenharmony_ci data->bytes_xfered = 0; 85462306a36Sopenharmony_ci else 85562306a36Sopenharmony_ci data->bytes_xfered = data->blocks * data->blksz; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cifinish: 86162306a36Sopenharmony_ci if (cmd->error) { 86262306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "CMD %d 0x%08x error(%d)\n", 86362306a36Sopenharmony_ci cmd->opcode, cmd->arg, cmd->error); 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci mutex_lock(&host->host_mutex); 86762306a36Sopenharmony_ci host->mrq = NULL; 86862306a36Sopenharmony_ci mutex_unlock(&host->host_mutex); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci mmc_request_done(mmc, mrq); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 87662306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci mutex_lock(&host->host_mutex); 87962306a36Sopenharmony_ci host->mrq = mrq; 88062306a36Sopenharmony_ci mutex_unlock(&host->host_mutex); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (sd_rw_cmd(mrq->cmd) || sdio_extblock_cmd(mrq->cmd, data)) 88362306a36Sopenharmony_ci host->using_cookie = sd_pre_dma_transfer(host, data, false); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci schedule_work(&host->work); 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic int sd_set_bus_width(struct realtek_pci_sdmmc *host, 88962306a36Sopenharmony_ci unsigned char bus_width) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci int err = 0; 89262306a36Sopenharmony_ci u8 width[] = { 89362306a36Sopenharmony_ci [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, 89462306a36Sopenharmony_ci [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, 89562306a36Sopenharmony_ci [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, 89662306a36Sopenharmony_ci }; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci if (bus_width <= MMC_BUS_WIDTH_8) 89962306a36Sopenharmony_ci err = rtsx_pci_write_register(host->pcr, SD_CFG1, 90062306a36Sopenharmony_ci 0x03, width[bus_width]); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci return err; 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 90862306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 90962306a36Sopenharmony_ci int err; 91062306a36Sopenharmony_ci u32 val; 91162306a36Sopenharmony_ci u8 test_mode; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (host->prev_power_state == MMC_POWER_ON) 91462306a36Sopenharmony_ci return 0; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci if (host->prev_power_state == MMC_POWER_UP) { 91762306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0); 91862306a36Sopenharmony_ci goto finish; 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci msleep(100); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 92462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); 92562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, 92662306a36Sopenharmony_ci CARD_SHARE_MASK, CARD_SHARE_48_SD); 92762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 92862306a36Sopenharmony_ci SD_CLK_EN, SD_CLK_EN); 92962306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, 100); 93062306a36Sopenharmony_ci if (err < 0) 93162306a36Sopenharmony_ci return err; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_SD_CARD); 93462306a36Sopenharmony_ci if (err < 0) 93562306a36Sopenharmony_ci return err; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci err = rtsx_pci_card_power_on(pcr, RTSX_SD_CARD); 93862306a36Sopenharmony_ci if (err < 0) 93962306a36Sopenharmony_ci return err; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci mdelay(1); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); 94462306a36Sopenharmony_ci if (err < 0) 94562306a36Sopenharmony_ci return err; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci /* send at least 74 clocks */ 94862306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci if (PCI_PID(pcr) == PID_5261) { 95162306a36Sopenharmony_ci /* 95262306a36Sopenharmony_ci * If test mode is set switch to SD Express mandatorily, 95362306a36Sopenharmony_ci * this is only for factory testing. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci rtsx_pci_read_register(pcr, RTS5261_FW_CFG_INFO0, &test_mode); 95662306a36Sopenharmony_ci if (test_mode & RTS5261_FW_EXPRESS_TEST_MASK) { 95762306a36Sopenharmony_ci sdmmc_init_sd_express(mmc, NULL); 95862306a36Sopenharmony_ci return 0; 95962306a36Sopenharmony_ci } 96062306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS) 96162306a36Sopenharmony_ci mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; 96262306a36Sopenharmony_ci /* 96362306a36Sopenharmony_ci * HW read wp status when resuming from S3/S4, 96462306a36Sopenharmony_ci * and then picks SD legacy interface if it's set 96562306a36Sopenharmony_ci * in read-only mode. 96662306a36Sopenharmony_ci */ 96762306a36Sopenharmony_ci val = rtsx_pci_readl(pcr, RTSX_BIPR); 96862306a36Sopenharmony_ci if (val & SD_WRITE_PROTECT) { 96962306a36Sopenharmony_ci pcr->extra_caps &= ~EXTRA_CAPS_SD_EXPRESS; 97062306a36Sopenharmony_ci mmc->caps2 &= ~(MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V); 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cifinish: 97562306a36Sopenharmony_ci host->prev_power_state = power_mode; 97662306a36Sopenharmony_ci return 0; 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic int sd_power_off(struct realtek_pci_sdmmc *host) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 98262306a36Sopenharmony_ci int err; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci host->prev_power_state = MMC_POWER_OFF; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); 98962306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, 100); 99262306a36Sopenharmony_ci if (err < 0) 99362306a36Sopenharmony_ci return err; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci err = rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); 99662306a36Sopenharmony_ci if (err < 0) 99762306a36Sopenharmony_ci return err; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD); 100062306a36Sopenharmony_ci} 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_cistatic int sd_set_power_mode(struct realtek_pci_sdmmc *host, 100362306a36Sopenharmony_ci unsigned char power_mode) 100462306a36Sopenharmony_ci{ 100562306a36Sopenharmony_ci int err; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (power_mode == MMC_POWER_OFF) 100862306a36Sopenharmony_ci err = sd_power_off(host); 100962306a36Sopenharmony_ci else 101062306a36Sopenharmony_ci err = sd_power_on(host, power_mode); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci return err; 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_cistatic int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing) 101662306a36Sopenharmony_ci{ 101762306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 101862306a36Sopenharmony_ci int err = 0; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci rtsx_pci_init_cmd(pcr); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci switch (timing) { 102362306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR104: 102462306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR50: 102562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, 102662306a36Sopenharmony_ci 0x0C | SD_ASYNC_FIFO_NOT_RST, 102762306a36Sopenharmony_ci SD_30_MODE | SD_ASYNC_FIFO_NOT_RST); 102862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, 102962306a36Sopenharmony_ci CLK_LOW_FREQ, CLK_LOW_FREQ); 103062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 103162306a36Sopenharmony_ci CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 103262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); 103362306a36Sopenharmony_ci break; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci case MMC_TIMING_MMC_DDR52: 103662306a36Sopenharmony_ci case MMC_TIMING_UHS_DDR50: 103762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, 103862306a36Sopenharmony_ci 0x0C | SD_ASYNC_FIFO_NOT_RST, 103962306a36Sopenharmony_ci SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); 104062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, 104162306a36Sopenharmony_ci CLK_LOW_FREQ, CLK_LOW_FREQ); 104262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 104362306a36Sopenharmony_ci CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 104462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); 104562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 104662306a36Sopenharmony_ci DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); 104762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 104862306a36Sopenharmony_ci DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, 104962306a36Sopenharmony_ci DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); 105062306a36Sopenharmony_ci break; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci case MMC_TIMING_MMC_HS: 105362306a36Sopenharmony_ci case MMC_TIMING_SD_HS: 105462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, 105562306a36Sopenharmony_ci 0x0C, SD_20_MODE); 105662306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, 105762306a36Sopenharmony_ci CLK_LOW_FREQ, CLK_LOW_FREQ); 105862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 105962306a36Sopenharmony_ci CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 106062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); 106162306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 106262306a36Sopenharmony_ci SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); 106362306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 106462306a36Sopenharmony_ci SD20_RX_SEL_MASK, SD20_RX_14_DELAY); 106562306a36Sopenharmony_ci break; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci default: 106862306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 106962306a36Sopenharmony_ci SD_CFG1, 0x0C, SD_20_MODE); 107062306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, 107162306a36Sopenharmony_ci CLK_LOW_FREQ, CLK_LOW_FREQ); 107262306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 107362306a36Sopenharmony_ci CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 107462306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); 107562306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 107662306a36Sopenharmony_ci SD_PUSH_POINT_CTL, 0xFF, 0); 107762306a36Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 107862306a36Sopenharmony_ci SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); 107962306a36Sopenharmony_ci break; 108062306a36Sopenharmony_ci } 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, 100); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci return err; 108562306a36Sopenharmony_ci} 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_cistatic void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 108862306a36Sopenharmony_ci{ 108962306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 109062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (host->eject) 109362306a36Sopenharmony_ci return; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD)) 109662306a36Sopenharmony_ci return; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci sd_set_bus_width(host, ios->bus_width); 110362306a36Sopenharmony_ci sd_set_power_mode(host, ios->power_mode); 110462306a36Sopenharmony_ci sd_set_timing(host, ios->timing); 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci host->vpclk = false; 110762306a36Sopenharmony_ci host->double_clk = true; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci switch (ios->timing) { 111062306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR104: 111162306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR50: 111262306a36Sopenharmony_ci host->ssc_depth = RTSX_SSC_DEPTH_2M; 111362306a36Sopenharmony_ci host->vpclk = true; 111462306a36Sopenharmony_ci host->double_clk = false; 111562306a36Sopenharmony_ci break; 111662306a36Sopenharmony_ci case MMC_TIMING_MMC_DDR52: 111762306a36Sopenharmony_ci case MMC_TIMING_UHS_DDR50: 111862306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR25: 111962306a36Sopenharmony_ci host->ssc_depth = RTSX_SSC_DEPTH_1M; 112062306a36Sopenharmony_ci break; 112162306a36Sopenharmony_ci default: 112262306a36Sopenharmony_ci host->ssc_depth = RTSX_SSC_DEPTH_500K; 112362306a36Sopenharmony_ci break; 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci host->initial_mode = (ios->clock <= 1000000) ? true : false; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci host->clock = ios->clock; 112962306a36Sopenharmony_ci rtsx_pci_switch_clock(pcr, ios->clock, host->ssc_depth, 113062306a36Sopenharmony_ci host->initial_mode, host->double_clk, host->vpclk); 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 113362306a36Sopenharmony_ci} 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_cistatic int sdmmc_get_ro(struct mmc_host *mmc) 113662306a36Sopenharmony_ci{ 113762306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 113862306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 113962306a36Sopenharmony_ci int ro = 0; 114062306a36Sopenharmony_ci u32 val; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci if (host->eject) 114362306a36Sopenharmony_ci return -ENOMEDIUM; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /* Check SD mechanical write-protect switch */ 115062306a36Sopenharmony_ci val = rtsx_pci_readl(pcr, RTSX_BIPR); 115162306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val); 115262306a36Sopenharmony_ci if (val & SD_WRITE_PROTECT) 115362306a36Sopenharmony_ci ro = 1; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci return ro; 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_cistatic int sdmmc_get_cd(struct mmc_host *mmc) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 116362306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 116462306a36Sopenharmony_ci int cd = 0; 116562306a36Sopenharmony_ci u32 val; 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci if (host->eject) 116862306a36Sopenharmony_ci return cd; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci /* Check SD card detect */ 117562306a36Sopenharmony_ci val = rtsx_pci_card_exist(pcr); 117662306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val); 117762306a36Sopenharmony_ci if (val & SD_EXIST) 117862306a36Sopenharmony_ci cd = 1; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci return cd; 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_cistatic int sd_wait_voltage_stable_1(struct realtek_pci_sdmmc *host) 118662306a36Sopenharmony_ci{ 118762306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 118862306a36Sopenharmony_ci int err; 118962306a36Sopenharmony_ci u8 stat; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci /* Reference to Signal Voltage Switch Sequence in SD spec. 119262306a36Sopenharmony_ci * Wait for a period of time so that the card can drive SD_CMD and 119362306a36Sopenharmony_ci * SD_DAT[3:0] to low after sending back CMD11 response. 119462306a36Sopenharmony_ci */ 119562306a36Sopenharmony_ci mdelay(1); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci /* SD_CMD, SD_DAT[3:0] should be driven to low by card; 119862306a36Sopenharmony_ci * If either one of SD_CMD,SD_DAT[3:0] is not low, 119962306a36Sopenharmony_ci * abort the voltage switch sequence; 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_ci err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat); 120262306a36Sopenharmony_ci if (err < 0) 120362306a36Sopenharmony_ci return err; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | 120662306a36Sopenharmony_ci SD_DAT1_STATUS | SD_DAT0_STATUS)) 120762306a36Sopenharmony_ci return -EINVAL; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci /* Stop toggle SD clock */ 121062306a36Sopenharmony_ci err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 121162306a36Sopenharmony_ci 0xFF, SD_CLK_FORCE_STOP); 121262306a36Sopenharmony_ci if (err < 0) 121362306a36Sopenharmony_ci return err; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci return 0; 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistatic int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 122162306a36Sopenharmony_ci int err; 122262306a36Sopenharmony_ci u8 stat, mask, val; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci /* Wait 1.8V output of voltage regulator in card stable */ 122562306a36Sopenharmony_ci msleep(50); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci /* Toggle SD clock again */ 122862306a36Sopenharmony_ci err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); 122962306a36Sopenharmony_ci if (err < 0) 123062306a36Sopenharmony_ci return err; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci /* Wait for a period of time so that the card can drive 123362306a36Sopenharmony_ci * SD_DAT[3:0] to high at 1.8V 123462306a36Sopenharmony_ci */ 123562306a36Sopenharmony_ci msleep(20); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci /* SD_CMD, SD_DAT[3:0] should be pulled high by host */ 123862306a36Sopenharmony_ci err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat); 123962306a36Sopenharmony_ci if (err < 0) 124062306a36Sopenharmony_ci return err; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci mask = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | 124362306a36Sopenharmony_ci SD_DAT1_STATUS | SD_DAT0_STATUS; 124462306a36Sopenharmony_ci val = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | 124562306a36Sopenharmony_ci SD_DAT1_STATUS | SD_DAT0_STATUS; 124662306a36Sopenharmony_ci if ((stat & mask) != val) { 124762306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), 124862306a36Sopenharmony_ci "%s: SD_BUS_STAT = 0x%x\n", __func__, stat); 124962306a36Sopenharmony_ci rtsx_pci_write_register(pcr, SD_BUS_STAT, 125062306a36Sopenharmony_ci SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); 125162306a36Sopenharmony_ci rtsx_pci_write_register(pcr, CARD_CLK_EN, 0xFF, 0); 125262306a36Sopenharmony_ci return -EINVAL; 125362306a36Sopenharmony_ci } 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci return 0; 125662306a36Sopenharmony_ci} 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_cistatic int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) 125962306a36Sopenharmony_ci{ 126062306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 126162306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 126262306a36Sopenharmony_ci int err = 0; 126362306a36Sopenharmony_ci u8 voltage; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", 126662306a36Sopenharmony_ci __func__, ios->signal_voltage); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci if (host->eject) 126962306a36Sopenharmony_ci return -ENOMEDIUM; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); 127262306a36Sopenharmony_ci if (err) 127362306a36Sopenharmony_ci return err; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) 128062306a36Sopenharmony_ci voltage = OUTPUT_3V3; 128162306a36Sopenharmony_ci else 128262306a36Sopenharmony_ci voltage = OUTPUT_1V8; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (voltage == OUTPUT_1V8) { 128562306a36Sopenharmony_ci err = sd_wait_voltage_stable_1(host); 128662306a36Sopenharmony_ci if (err < 0) 128762306a36Sopenharmony_ci goto out; 128862306a36Sopenharmony_ci } 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci err = rtsx_pci_switch_output_voltage(pcr, voltage); 129162306a36Sopenharmony_ci if (err < 0) 129262306a36Sopenharmony_ci goto out; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci if (voltage == OUTPUT_1V8) { 129562306a36Sopenharmony_ci err = sd_wait_voltage_stable_2(host); 129662306a36Sopenharmony_ci if (err < 0) 129762306a36Sopenharmony_ci goto out; 129862306a36Sopenharmony_ci } 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ciout: 130162306a36Sopenharmony_ci /* Stop toggle SD clock in idle */ 130262306a36Sopenharmony_ci err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 130362306a36Sopenharmony_ci SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci return err; 130862306a36Sopenharmony_ci} 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_cistatic int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) 131162306a36Sopenharmony_ci{ 131262306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 131362306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 131462306a36Sopenharmony_ci int err = 0; 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci if (host->eject) 131762306a36Sopenharmony_ci return -ENOMEDIUM; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); 132062306a36Sopenharmony_ci if (err) 132162306a36Sopenharmony_ci return err; 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci mutex_lock(&pcr->pcr_mutex); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci rtsx_pci_start_run(pcr); 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci /* Set initial TX phase */ 132862306a36Sopenharmony_ci switch (mmc->ios.timing) { 132962306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR104: 133062306a36Sopenharmony_ci err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false); 133162306a36Sopenharmony_ci break; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci case MMC_TIMING_UHS_SDR50: 133462306a36Sopenharmony_ci err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false); 133562306a36Sopenharmony_ci break; 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci case MMC_TIMING_UHS_DDR50: 133862306a36Sopenharmony_ci err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false); 133962306a36Sopenharmony_ci break; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci default: 134262306a36Sopenharmony_ci err = 0; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci if (err) 134662306a36Sopenharmony_ci goto out; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci /* Tuning RX phase */ 134962306a36Sopenharmony_ci if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) || 135062306a36Sopenharmony_ci (mmc->ios.timing == MMC_TIMING_UHS_SDR50)) 135162306a36Sopenharmony_ci err = sd_tuning_rx(host, opcode); 135262306a36Sopenharmony_ci else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50) 135362306a36Sopenharmony_ci err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ciout: 135662306a36Sopenharmony_ci mutex_unlock(&pcr->pcr_mutex); 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci return err; 135962306a36Sopenharmony_ci} 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_cistatic int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) 136262306a36Sopenharmony_ci{ 136362306a36Sopenharmony_ci u32 relink_time; 136462306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = mmc_priv(mmc); 136562306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci /* Set relink_time for changing to PCIe card */ 136862306a36Sopenharmony_ci relink_time = 0x8FFF; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci rtsx_pci_write_register(pcr, 0xFF01, 0xFF, relink_time); 137162306a36Sopenharmony_ci rtsx_pci_write_register(pcr, 0xFF02, 0xFF, relink_time >> 8); 137262306a36Sopenharmony_ci rtsx_pci_write_register(pcr, 0xFF03, 0x01, relink_time >> 16); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci rtsx_pci_write_register(pcr, PETXCFG, 0x80, 0x80); 137562306a36Sopenharmony_ci rtsx_pci_write_register(pcr, LDO_VCC_CFG0, 137662306a36Sopenharmony_ci RTS5261_LDO1_OCP_THD_MASK, 137762306a36Sopenharmony_ci pcr->option.sd_800mA_ocp_thd); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci if (pcr->ops->disable_auto_blink) 138062306a36Sopenharmony_ci pcr->ops->disable_auto_blink(pcr); 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci /* For PCIe/NVMe mode can't enter delink issue */ 138362306a36Sopenharmony_ci pcr->hw_param.interrupt_en &= ~(SD_INT_EN); 138462306a36Sopenharmony_ci rtsx_pci_writel(pcr, RTSX_BIER, pcr->hw_param.interrupt_en); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci rtsx_pci_write_register(pcr, RTS5260_AUTOLOAD_CFG4, 138762306a36Sopenharmony_ci RTS5261_AUX_CLK_16M_EN, RTS5261_AUX_CLK_16M_EN); 138862306a36Sopenharmony_ci rtsx_pci_write_register(pcr, RTS5261_FW_CFG0, 138962306a36Sopenharmony_ci RTS5261_FW_ENTER_EXPRESS, RTS5261_FW_ENTER_EXPRESS); 139062306a36Sopenharmony_ci rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, 139162306a36Sopenharmony_ci RTS5261_MCU_CLOCK_GATING, RTS5261_MCU_CLOCK_GATING); 139262306a36Sopenharmony_ci rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, 139362306a36Sopenharmony_ci RTS5261_MCU_BUS_SEL_MASK | RTS5261_MCU_CLOCK_SEL_MASK 139462306a36Sopenharmony_ci | RTS5261_DRIVER_ENABLE_FW, 139562306a36Sopenharmony_ci RTS5261_MCU_CLOCK_SEL_16M | RTS5261_DRIVER_ENABLE_FW); 139662306a36Sopenharmony_ci host->eject = true; 139762306a36Sopenharmony_ci return 0; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_cistatic const struct mmc_host_ops realtek_pci_sdmmc_ops = { 140162306a36Sopenharmony_ci .pre_req = sdmmc_pre_req, 140262306a36Sopenharmony_ci .post_req = sdmmc_post_req, 140362306a36Sopenharmony_ci .request = sdmmc_request, 140462306a36Sopenharmony_ci .set_ios = sdmmc_set_ios, 140562306a36Sopenharmony_ci .get_ro = sdmmc_get_ro, 140662306a36Sopenharmony_ci .get_cd = sdmmc_get_cd, 140762306a36Sopenharmony_ci .start_signal_voltage_switch = sdmmc_switch_voltage, 140862306a36Sopenharmony_ci .execute_tuning = sdmmc_execute_tuning, 140962306a36Sopenharmony_ci .init_sd_express = sdmmc_init_sd_express, 141062306a36Sopenharmony_ci}; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_cistatic void init_extra_caps(struct realtek_pci_sdmmc *host) 141362306a36Sopenharmony_ci{ 141462306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 141562306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci dev_dbg(sdmmc_dev(host), "pcr->extra_caps = 0x%x\n", pcr->extra_caps); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50) 142062306a36Sopenharmony_ci mmc->caps |= MMC_CAP_UHS_SDR50; 142162306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_SD_SDR104) 142262306a36Sopenharmony_ci mmc->caps |= MMC_CAP_UHS_SDR104; 142362306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_SD_DDR50) 142462306a36Sopenharmony_ci mmc->caps |= MMC_CAP_UHS_DDR50; 142562306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_MMC_HSDDR) 142662306a36Sopenharmony_ci mmc->caps |= MMC_CAP_1_8V_DDR; 142762306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT) 142862306a36Sopenharmony_ci mmc->caps |= MMC_CAP_8_BIT_DATA; 142962306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_NO_MMC) 143062306a36Sopenharmony_ci mmc->caps2 |= MMC_CAP2_NO_MMC; 143162306a36Sopenharmony_ci if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS) 143262306a36Sopenharmony_ci mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; 143362306a36Sopenharmony_ci} 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_cistatic void realtek_init_host(struct realtek_pci_sdmmc *host) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 143862306a36Sopenharmony_ci struct rtsx_pcr *pcr = host->pcr; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci mmc->f_min = 250000; 144162306a36Sopenharmony_ci mmc->f_max = 208000000; 144262306a36Sopenharmony_ci mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 144362306a36Sopenharmony_ci mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | 144462306a36Sopenharmony_ci MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | 144562306a36Sopenharmony_ci MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 144662306a36Sopenharmony_ci if (pcr->rtd3_en) 144762306a36Sopenharmony_ci mmc->caps = mmc->caps | MMC_CAP_AGGRESSIVE_PM; 144862306a36Sopenharmony_ci mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE | 144962306a36Sopenharmony_ci MMC_CAP2_NO_SDIO; 145062306a36Sopenharmony_ci mmc->max_current_330 = 400; 145162306a36Sopenharmony_ci mmc->max_current_180 = 800; 145262306a36Sopenharmony_ci mmc->ops = &realtek_pci_sdmmc_ops; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci init_extra_caps(host); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci mmc->max_segs = 256; 145762306a36Sopenharmony_ci mmc->max_seg_size = 65536; 145862306a36Sopenharmony_ci mmc->max_blk_size = 512; 145962306a36Sopenharmony_ci mmc->max_blk_count = 65535; 146062306a36Sopenharmony_ci mmc->max_req_size = 524288; 146162306a36Sopenharmony_ci} 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_cistatic void rtsx_pci_sdmmc_card_event(struct platform_device *pdev) 146462306a36Sopenharmony_ci{ 146562306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci host->cookie = -1; 146862306a36Sopenharmony_ci mmc_detect_change(host->mmc, 0); 146962306a36Sopenharmony_ci} 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_cistatic int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) 147262306a36Sopenharmony_ci{ 147362306a36Sopenharmony_ci struct mmc_host *mmc; 147462306a36Sopenharmony_ci struct realtek_pci_sdmmc *host; 147562306a36Sopenharmony_ci struct rtsx_pcr *pcr; 147662306a36Sopenharmony_ci struct pcr_handle *handle = pdev->dev.platform_data; 147762306a36Sopenharmony_ci int ret; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci if (!handle) 148062306a36Sopenharmony_ci return -ENXIO; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci pcr = handle->pcr; 148362306a36Sopenharmony_ci if (!pcr) 148462306a36Sopenharmony_ci return -ENXIO; 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller found\n"); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); 148962306a36Sopenharmony_ci if (!mmc) 149062306a36Sopenharmony_ci return -ENOMEM; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci host = mmc_priv(mmc); 149362306a36Sopenharmony_ci host->pcr = pcr; 149462306a36Sopenharmony_ci mmc->ios.power_delay_ms = 5; 149562306a36Sopenharmony_ci host->mmc = mmc; 149662306a36Sopenharmony_ci host->pdev = pdev; 149762306a36Sopenharmony_ci host->cookie = -1; 149862306a36Sopenharmony_ci host->prev_power_state = MMC_POWER_OFF; 149962306a36Sopenharmony_ci INIT_WORK(&host->work, sd_request); 150062306a36Sopenharmony_ci platform_set_drvdata(pdev, host); 150162306a36Sopenharmony_ci pcr->slots[RTSX_SD_CARD].p_dev = pdev; 150262306a36Sopenharmony_ci pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci mutex_init(&host->host_mutex); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci realtek_init_host(host); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci pm_runtime_no_callbacks(&pdev->dev); 150962306a36Sopenharmony_ci pm_runtime_set_active(&pdev->dev); 151062306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 151162306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(&pdev->dev, 200); 151262306a36Sopenharmony_ci pm_runtime_mark_last_busy(&pdev->dev); 151362306a36Sopenharmony_ci pm_runtime_use_autosuspend(&pdev->dev); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci ret = mmc_add_host(mmc); 151662306a36Sopenharmony_ci if (ret) { 151762306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 151862306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 151962306a36Sopenharmony_ci mmc_free_host(mmc); 152062306a36Sopenharmony_ci return ret; 152162306a36Sopenharmony_ci } 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci return 0; 152462306a36Sopenharmony_ci} 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_cistatic void rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) 152762306a36Sopenharmony_ci{ 152862306a36Sopenharmony_ci struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); 152962306a36Sopenharmony_ci struct rtsx_pcr *pcr; 153062306a36Sopenharmony_ci struct mmc_host *mmc; 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci pcr = host->pcr; 153362306a36Sopenharmony_ci pcr->slots[RTSX_SD_CARD].p_dev = NULL; 153462306a36Sopenharmony_ci pcr->slots[RTSX_SD_CARD].card_event = NULL; 153562306a36Sopenharmony_ci mmc = host->mmc; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci cancel_work_sync(&host->work); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci mutex_lock(&host->host_mutex); 154062306a36Sopenharmony_ci if (host->mrq) { 154162306a36Sopenharmony_ci dev_dbg(&(pdev->dev), 154262306a36Sopenharmony_ci "%s: Controller removed during transfer\n", 154362306a36Sopenharmony_ci mmc_hostname(mmc)); 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci rtsx_pci_complete_unfinished_transfer(pcr); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci host->mrq->cmd->error = -ENOMEDIUM; 154862306a36Sopenharmony_ci if (host->mrq->stop) 154962306a36Sopenharmony_ci host->mrq->stop->error = -ENOMEDIUM; 155062306a36Sopenharmony_ci mmc_request_done(mmc, host->mrq); 155162306a36Sopenharmony_ci } 155262306a36Sopenharmony_ci mutex_unlock(&host->host_mutex); 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci mmc_remove_host(mmc); 155562306a36Sopenharmony_ci host->eject = true; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci flush_work(&host->work); 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 156062306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci mmc_free_host(mmc); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci dev_dbg(&(pdev->dev), 156562306a36Sopenharmony_ci ": Realtek PCI-E SDMMC controller has been removed\n"); 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_cistatic const struct platform_device_id rtsx_pci_sdmmc_ids[] = { 156962306a36Sopenharmony_ci { 157062306a36Sopenharmony_ci .name = DRV_NAME_RTSX_PCI_SDMMC, 157162306a36Sopenharmony_ci }, { 157262306a36Sopenharmony_ci /* sentinel */ 157362306a36Sopenharmony_ci } 157462306a36Sopenharmony_ci}; 157562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_cistatic struct platform_driver rtsx_pci_sdmmc_driver = { 157862306a36Sopenharmony_ci .probe = rtsx_pci_sdmmc_drv_probe, 157962306a36Sopenharmony_ci .remove_new = rtsx_pci_sdmmc_drv_remove, 158062306a36Sopenharmony_ci .id_table = rtsx_pci_sdmmc_ids, 158162306a36Sopenharmony_ci .driver = { 158262306a36Sopenharmony_ci .name = DRV_NAME_RTSX_PCI_SDMMC, 158362306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 158462306a36Sopenharmony_ci }, 158562306a36Sopenharmony_ci}; 158662306a36Sopenharmony_cimodule_platform_driver(rtsx_pci_sdmmc_driver); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 158962306a36Sopenharmony_ciMODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>"); 159062306a36Sopenharmony_ciMODULE_DESCRIPTION("Realtek PCI-E SD/MMC Card Host Driver"); 1591