1c7f6558dSRoger Tseng /* Realtek USB SD/MMC Card Interface driver 2c7f6558dSRoger Tseng * 3c7f6558dSRoger Tseng * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 4c7f6558dSRoger Tseng * 5c7f6558dSRoger Tseng * This program is free software; you can redistribute it and/or modify it 6c7f6558dSRoger Tseng * under the terms of the GNU General Public License version 2 7c7f6558dSRoger Tseng * as published by the Free Software Foundation. 8c7f6558dSRoger Tseng * 9c7f6558dSRoger Tseng * This program is distributed in the hope that it will be useful, but 10c7f6558dSRoger Tseng * WITHOUT ANY WARRANTY; without even the implied warranty of 11c7f6558dSRoger Tseng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12c7f6558dSRoger Tseng * General Public License for more details. 13c7f6558dSRoger Tseng * 14c7f6558dSRoger Tseng * You should have received a copy of the GNU General Public License along 15c7f6558dSRoger Tseng * with this program; if not, see <http://www.gnu.org/licenses/>. 16c7f6558dSRoger Tseng * 17c7f6558dSRoger Tseng * Author: 18c7f6558dSRoger Tseng * Roger Tseng <rogerable@realtek.com> 19c7f6558dSRoger Tseng */ 20c7f6558dSRoger Tseng 21c7f6558dSRoger Tseng #include <linux/module.h> 22c7f6558dSRoger Tseng #include <linux/slab.h> 23c7f6558dSRoger Tseng #include <linux/delay.h> 24c7f6558dSRoger Tseng #include <linux/platform_device.h> 25c7f6558dSRoger Tseng #include <linux/usb.h> 26c7f6558dSRoger Tseng #include <linux/mmc/host.h> 27c7f6558dSRoger Tseng #include <linux/mmc/mmc.h> 28c7f6558dSRoger Tseng #include <linux/mmc/sd.h> 29c7f6558dSRoger Tseng #include <linux/mmc/sdio.h> 30c7f6558dSRoger Tseng #include <linux/mmc/card.h> 31c7f6558dSRoger Tseng #include <linux/scatterlist.h> 32c7f6558dSRoger Tseng #include <linux/pm_runtime.h> 33c7f6558dSRoger Tseng 34c7f6558dSRoger Tseng #include <linux/mfd/rtsx_usb.h> 35c7f6558dSRoger Tseng #include <asm/unaligned.h> 36c7f6558dSRoger Tseng 37b677b885SArnd Bergmann #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ 38b677b885SArnd Bergmann defined(CONFIG_MMC_REALTEK_USB_MODULE)) 39c7f6558dSRoger Tseng #include <linux/leds.h> 40c7f6558dSRoger Tseng #include <linux/workqueue.h> 41c7f6558dSRoger Tseng #define RTSX_USB_USE_LEDS_CLASS 42c7f6558dSRoger Tseng #endif 43c7f6558dSRoger Tseng 44c7f6558dSRoger Tseng struct rtsx_usb_sdmmc { 45c7f6558dSRoger Tseng struct platform_device *pdev; 46c7f6558dSRoger Tseng struct rtsx_ucr *ucr; 47c7f6558dSRoger Tseng struct mmc_host *mmc; 48c7f6558dSRoger Tseng struct mmc_request *mrq; 49c7f6558dSRoger Tseng 50c7f6558dSRoger Tseng struct mutex host_mutex; 51c7f6558dSRoger Tseng 52c7f6558dSRoger Tseng u8 ssc_depth; 53c7f6558dSRoger Tseng unsigned int clock; 54c7f6558dSRoger Tseng bool vpclk; 55c7f6558dSRoger Tseng bool double_clk; 56c7f6558dSRoger Tseng bool host_removal; 57c7f6558dSRoger Tseng bool card_exist; 58c7f6558dSRoger Tseng bool initial_mode; 59c7f6558dSRoger Tseng bool ddr_mode; 60c7f6558dSRoger Tseng 61c7f6558dSRoger Tseng unsigned char power_mode; 62c7f6558dSRoger Tseng 63b677b885SArnd Bergmann #ifdef RTSX_USB_USE_LEDS_CLASS 64c7f6558dSRoger Tseng struct led_classdev led; 65c7f6558dSRoger Tseng char led_name[32]; 66c7f6558dSRoger Tseng struct work_struct led_work; 67c7f6558dSRoger Tseng #endif 68c7f6558dSRoger Tseng }; 69c7f6558dSRoger Tseng 70c7f6558dSRoger Tseng static inline struct device *sdmmc_dev(struct rtsx_usb_sdmmc *host) 71c7f6558dSRoger Tseng { 72c7f6558dSRoger Tseng return &(host->pdev->dev); 73c7f6558dSRoger Tseng } 74c7f6558dSRoger Tseng 75c7f6558dSRoger Tseng static inline void sd_clear_error(struct rtsx_usb_sdmmc *host) 76c7f6558dSRoger Tseng { 77c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 78c7f6558dSRoger Tseng rtsx_usb_ep0_write_register(ucr, CARD_STOP, 79c7f6558dSRoger Tseng SD_STOP | SD_CLR_ERR, 80c7f6558dSRoger Tseng SD_STOP | SD_CLR_ERR); 81c7f6558dSRoger Tseng 82c7f6558dSRoger Tseng rtsx_usb_clear_dma_err(ucr); 83c7f6558dSRoger Tseng rtsx_usb_clear_fsm_err(ucr); 84c7f6558dSRoger Tseng } 85c7f6558dSRoger Tseng 86c7f6558dSRoger Tseng #ifdef DEBUG 87c7f6558dSRoger Tseng static void sd_print_debug_regs(struct rtsx_usb_sdmmc *host) 88c7f6558dSRoger Tseng { 89c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 90c7f6558dSRoger Tseng u8 val = 0; 91c7f6558dSRoger Tseng 92c7f6558dSRoger Tseng rtsx_usb_ep0_read_register(ucr, SD_STAT1, &val); 93c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "SD_STAT1: 0x%x\n", val); 94c7f6558dSRoger Tseng rtsx_usb_ep0_read_register(ucr, SD_STAT2, &val); 95c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "SD_STAT2: 0x%x\n", val); 96c7f6558dSRoger Tseng rtsx_usb_ep0_read_register(ucr, SD_BUS_STAT, &val); 97c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "SD_BUS_STAT: 0x%x\n", val); 98c7f6558dSRoger Tseng } 99c7f6558dSRoger Tseng #else 100c7f6558dSRoger Tseng #define sd_print_debug_regs(host) 101c7f6558dSRoger Tseng #endif /* DEBUG */ 102c7f6558dSRoger Tseng 103c7f6558dSRoger Tseng static int sd_read_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, 104c7f6558dSRoger Tseng u16 byte_cnt, u8 *buf, int buf_len, int timeout) 105c7f6558dSRoger Tseng { 106c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 107c7f6558dSRoger Tseng int err; 108c7f6558dSRoger Tseng u8 trans_mode; 109c7f6558dSRoger Tseng 110c7f6558dSRoger Tseng if (!buf) 111c7f6558dSRoger Tseng buf_len = 0; 112c7f6558dSRoger Tseng 113c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 114c7f6558dSRoger Tseng if (cmd != NULL) { 115c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__ 116c7f6558dSRoger Tseng , cmd->opcode); 117c7f6558dSRoger Tseng if (cmd->opcode == MMC_SEND_TUNING_BLOCK) 118c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_TUNING; 119c7f6558dSRoger Tseng else 120c7f6558dSRoger Tseng trans_mode = SD_TM_NORMAL_READ; 121c7f6558dSRoger Tseng 122c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 123c7f6558dSRoger Tseng SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); 124c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 125c7f6558dSRoger Tseng SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); 126c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 127c7f6558dSRoger Tseng SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); 128c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 129c7f6558dSRoger Tseng SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); 130c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 131c7f6558dSRoger Tseng SD_CMD4, 0xFF, (u8)cmd->arg); 132c7f6558dSRoger Tseng } else { 133c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_READ_3; 134c7f6558dSRoger Tseng } 135c7f6558dSRoger Tseng 136c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); 137c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 138c7f6558dSRoger Tseng 0xFF, (u8)(byte_cnt >> 8)); 139c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); 140c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); 141c7f6558dSRoger Tseng 142c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, 143c7f6558dSRoger Tseng SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 144c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); 145c7f6558dSRoger Tseng if (trans_mode != SD_TM_AUTO_TUNING) 146c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 147c7f6558dSRoger Tseng CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); 148c7f6558dSRoger Tseng 149c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 150c7f6558dSRoger Tseng 0xFF, trans_mode | SD_TRANSFER_START); 151c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, 152c7f6558dSRoger Tseng SD_TRANSFER_END, SD_TRANSFER_END); 153c7f6558dSRoger Tseng 154c7f6558dSRoger Tseng if (cmd != NULL) { 155c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); 156c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); 157c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); 158c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); 159c7f6558dSRoger Tseng } 160c7f6558dSRoger Tseng 161c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); 162c7f6558dSRoger Tseng if (err) { 163c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 164c7f6558dSRoger Tseng "rtsx_usb_send_cmd failed (err = %d)\n", err); 165c7f6558dSRoger Tseng return err; 166c7f6558dSRoger Tseng } 167c7f6558dSRoger Tseng 168c7f6558dSRoger Tseng err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); 169c7f6558dSRoger Tseng if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { 170c7f6558dSRoger Tseng sd_print_debug_regs(host); 171c7f6558dSRoger Tseng 172c7f6558dSRoger Tseng if (!err) { 173c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 174c7f6558dSRoger Tseng "Transfer failed (SD_TRANSFER = %02x)\n", 175c7f6558dSRoger Tseng ucr->rsp_buf[0]); 176c7f6558dSRoger Tseng err = -EIO; 177c7f6558dSRoger Tseng } else { 178c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 179c7f6558dSRoger Tseng "rtsx_usb_get_rsp failed (err = %d)\n", err); 180c7f6558dSRoger Tseng } 181c7f6558dSRoger Tseng 182c7f6558dSRoger Tseng return err; 183c7f6558dSRoger Tseng } 184c7f6558dSRoger Tseng 185c7f6558dSRoger Tseng if (cmd != NULL) { 186c7f6558dSRoger Tseng cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); 187c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", 188c7f6558dSRoger Tseng cmd->resp[0]); 189c7f6558dSRoger Tseng } 190c7f6558dSRoger Tseng 191c7f6558dSRoger Tseng if (buf && buf_len) { 192c7f6558dSRoger Tseng /* 2-byte aligned part */ 193c7f6558dSRoger Tseng err = rtsx_usb_read_ppbuf(ucr, buf, byte_cnt - (byte_cnt % 2)); 194c7f6558dSRoger Tseng if (err) { 195c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 196c7f6558dSRoger Tseng "rtsx_usb_read_ppbuf failed (err = %d)\n", err); 197c7f6558dSRoger Tseng return err; 198c7f6558dSRoger Tseng } 199c7f6558dSRoger Tseng 200c7f6558dSRoger Tseng /* unaligned byte */ 201c7f6558dSRoger Tseng if (byte_cnt % 2) 202c7f6558dSRoger Tseng return rtsx_usb_read_register(ucr, 203c7f6558dSRoger Tseng PPBUF_BASE2 + byte_cnt, 204c7f6558dSRoger Tseng buf + byte_cnt - 1); 205c7f6558dSRoger Tseng } 206c7f6558dSRoger Tseng 207c7f6558dSRoger Tseng return 0; 208c7f6558dSRoger Tseng } 209c7f6558dSRoger Tseng 210c7f6558dSRoger Tseng static int sd_write_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, 211c7f6558dSRoger Tseng u16 byte_cnt, u8 *buf, int buf_len, int timeout) 212c7f6558dSRoger Tseng { 213c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 214c7f6558dSRoger Tseng int err; 215c7f6558dSRoger Tseng u8 trans_mode; 216c7f6558dSRoger Tseng 217c7f6558dSRoger Tseng if (!buf) 218c7f6558dSRoger Tseng buf_len = 0; 219c7f6558dSRoger Tseng 220c7f6558dSRoger Tseng if (buf && buf_len) { 221c7f6558dSRoger Tseng err = rtsx_usb_write_ppbuf(ucr, buf, buf_len); 222c7f6558dSRoger Tseng if (err) { 223c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 224c7f6558dSRoger Tseng "rtsx_usb_write_ppbuf failed (err = %d)\n", 225c7f6558dSRoger Tseng err); 226c7f6558dSRoger Tseng return err; 227c7f6558dSRoger Tseng } 228c7f6558dSRoger Tseng } 229c7f6558dSRoger Tseng 230c7f6558dSRoger Tseng trans_mode = (cmd != NULL) ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; 231c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 232c7f6558dSRoger Tseng 233c7f6558dSRoger Tseng if (cmd != NULL) { 234c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, 235c7f6558dSRoger Tseng cmd->opcode); 236c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 237c7f6558dSRoger Tseng SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); 238c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 239c7f6558dSRoger Tseng SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); 240c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 241c7f6558dSRoger Tseng SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); 242c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 243c7f6558dSRoger Tseng SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); 244c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 245c7f6558dSRoger Tseng SD_CMD4, 0xFF, (u8)cmd->arg); 246c7f6558dSRoger Tseng } 247c7f6558dSRoger Tseng 248c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); 249c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 250c7f6558dSRoger Tseng 0xFF, (u8)(byte_cnt >> 8)); 251c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); 252c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); 253c7f6558dSRoger Tseng 254c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, 255c7f6558dSRoger Tseng SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 256c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); 257c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 258c7f6558dSRoger Tseng CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); 259c7f6558dSRoger Tseng 260c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 261c7f6558dSRoger Tseng trans_mode | SD_TRANSFER_START); 262c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, 263c7f6558dSRoger Tseng SD_TRANSFER_END, SD_TRANSFER_END); 264c7f6558dSRoger Tseng 265c7f6558dSRoger Tseng if (cmd != NULL) { 266c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); 267c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); 268c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); 269c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); 270c7f6558dSRoger Tseng } 271c7f6558dSRoger Tseng 272c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); 273c7f6558dSRoger Tseng if (err) { 274c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 275c7f6558dSRoger Tseng "rtsx_usb_send_cmd failed (err = %d)\n", err); 276c7f6558dSRoger Tseng return err; 277c7f6558dSRoger Tseng } 278c7f6558dSRoger Tseng 279c7f6558dSRoger Tseng err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); 280c7f6558dSRoger Tseng if (err) { 281c7f6558dSRoger Tseng sd_print_debug_regs(host); 282c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 283c7f6558dSRoger Tseng "rtsx_usb_get_rsp failed (err = %d)\n", err); 284c7f6558dSRoger Tseng return err; 285c7f6558dSRoger Tseng } 286c7f6558dSRoger Tseng 287c7f6558dSRoger Tseng if (cmd != NULL) { 288c7f6558dSRoger Tseng cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); 289c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", 290c7f6558dSRoger Tseng cmd->resp[0]); 291c7f6558dSRoger Tseng } 292c7f6558dSRoger Tseng 293c7f6558dSRoger Tseng return 0; 294c7f6558dSRoger Tseng } 295c7f6558dSRoger Tseng 296c7f6558dSRoger Tseng static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host, 297c7f6558dSRoger Tseng struct mmc_command *cmd) 298c7f6558dSRoger Tseng { 299c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 300c7f6558dSRoger Tseng u8 cmd_idx = (u8)cmd->opcode; 301c7f6558dSRoger Tseng u32 arg = cmd->arg; 302c7f6558dSRoger Tseng int err = 0; 303c7f6558dSRoger Tseng int timeout = 100; 304c7f6558dSRoger Tseng int i; 305c7f6558dSRoger Tseng u8 *ptr; 306c7f6558dSRoger Tseng int stat_idx = 0; 307c7f6558dSRoger Tseng int len = 2; 308c7f6558dSRoger Tseng u8 rsp_type; 309c7f6558dSRoger Tseng 310c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", 311c7f6558dSRoger Tseng __func__, cmd_idx, arg); 312c7f6558dSRoger Tseng 313c7f6558dSRoger Tseng /* Response type: 314c7f6558dSRoger Tseng * R0 315c7f6558dSRoger Tseng * R1, R5, R6, R7 316c7f6558dSRoger Tseng * R1b 317c7f6558dSRoger Tseng * R2 318c7f6558dSRoger Tseng * R3, R4 319c7f6558dSRoger Tseng */ 320c7f6558dSRoger Tseng switch (mmc_resp_type(cmd)) { 321c7f6558dSRoger Tseng case MMC_RSP_NONE: 322c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R0; 323c7f6558dSRoger Tseng break; 324c7f6558dSRoger Tseng case MMC_RSP_R1: 325c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R1; 326c7f6558dSRoger Tseng break; 327c7f6558dSRoger Tseng case MMC_RSP_R1 & ~MMC_RSP_CRC: 328c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; 329c7f6558dSRoger Tseng break; 330c7f6558dSRoger Tseng case MMC_RSP_R1B: 331c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R1b; 332c7f6558dSRoger Tseng break; 333c7f6558dSRoger Tseng case MMC_RSP_R2: 334c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R2; 335c7f6558dSRoger Tseng break; 336c7f6558dSRoger Tseng case MMC_RSP_R3: 337c7f6558dSRoger Tseng rsp_type = SD_RSP_TYPE_R3; 338c7f6558dSRoger Tseng break; 339c7f6558dSRoger Tseng default: 340c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); 341c7f6558dSRoger Tseng err = -EINVAL; 342c7f6558dSRoger Tseng goto out; 343c7f6558dSRoger Tseng } 344c7f6558dSRoger Tseng 345c7f6558dSRoger Tseng if (rsp_type == SD_RSP_TYPE_R1b) 346c7f6558dSRoger Tseng timeout = 3000; 347c7f6558dSRoger Tseng 348c7f6558dSRoger Tseng if (cmd->opcode == SD_SWITCH_VOLTAGE) { 349c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, SD_BUS_STAT, 350c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 351c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN); 352c7f6558dSRoger Tseng if (err) 353c7f6558dSRoger Tseng goto out; 354c7f6558dSRoger Tseng } 355c7f6558dSRoger Tseng 356c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 357c7f6558dSRoger Tseng 358c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); 359c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); 360c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); 361c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); 362c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); 363c7f6558dSRoger Tseng 364c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); 365c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, 366c7f6558dSRoger Tseng 0x01, PINGPONG_BUFFER); 367c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 368c7f6558dSRoger Tseng 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); 369c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, 370c7f6558dSRoger Tseng SD_TRANSFER_END | SD_STAT_IDLE, 371c7f6558dSRoger Tseng SD_TRANSFER_END | SD_STAT_IDLE); 372c7f6558dSRoger Tseng 373c7f6558dSRoger Tseng if (rsp_type == SD_RSP_TYPE_R2) { 374c7f6558dSRoger Tseng /* Read data from ping-pong buffer */ 375c7f6558dSRoger Tseng for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) 376c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); 377c7f6558dSRoger Tseng stat_idx = 16; 378c7f6558dSRoger Tseng } else if (rsp_type != SD_RSP_TYPE_R0) { 379c7f6558dSRoger Tseng /* Read data from SD_CMDx registers */ 380c7f6558dSRoger Tseng for (i = SD_CMD0; i <= SD_CMD4; i++) 381c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); 382c7f6558dSRoger Tseng stat_idx = 5; 383c7f6558dSRoger Tseng } 384c7f6558dSRoger Tseng len += stat_idx; 385c7f6558dSRoger Tseng 386c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_STAT1, 0, 0); 387c7f6558dSRoger Tseng 388c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_CR, 100); 389c7f6558dSRoger Tseng if (err) { 390c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 391c7f6558dSRoger Tseng "rtsx_usb_send_cmd error (err = %d)\n", err); 392c7f6558dSRoger Tseng goto out; 393c7f6558dSRoger Tseng } 394c7f6558dSRoger Tseng 395c7f6558dSRoger Tseng err = rtsx_usb_get_rsp(ucr, len, timeout); 396c7f6558dSRoger Tseng if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { 397c7f6558dSRoger Tseng sd_print_debug_regs(host); 398c7f6558dSRoger Tseng sd_clear_error(host); 399c7f6558dSRoger Tseng 400c7f6558dSRoger Tseng if (!err) { 401c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 402c7f6558dSRoger Tseng "Transfer failed (SD_TRANSFER = %02x)\n", 403c7f6558dSRoger Tseng ucr->rsp_buf[0]); 404c7f6558dSRoger Tseng err = -EIO; 405c7f6558dSRoger Tseng } else { 406c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), 407c7f6558dSRoger Tseng "rtsx_usb_get_rsp failed (err = %d)\n", err); 408c7f6558dSRoger Tseng } 409c7f6558dSRoger Tseng 410c7f6558dSRoger Tseng goto out; 411c7f6558dSRoger Tseng } 412c7f6558dSRoger Tseng 413c7f6558dSRoger Tseng if (rsp_type == SD_RSP_TYPE_R0) { 414c7f6558dSRoger Tseng err = 0; 415c7f6558dSRoger Tseng goto out; 416c7f6558dSRoger Tseng } 417c7f6558dSRoger Tseng 418c7f6558dSRoger Tseng /* Skip result of CHECK_REG_CMD */ 419c7f6558dSRoger Tseng ptr = ucr->rsp_buf + 1; 420c7f6558dSRoger Tseng 421c7f6558dSRoger Tseng /* Check (Start,Transmission) bit of Response */ 422c7f6558dSRoger Tseng if ((ptr[0] & 0xC0) != 0) { 423c7f6558dSRoger Tseng err = -EILSEQ; 424c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); 425c7f6558dSRoger Tseng goto out; 426c7f6558dSRoger Tseng } 427c7f6558dSRoger Tseng 428c7f6558dSRoger Tseng /* Check CRC7 */ 429c7f6558dSRoger Tseng if (!(rsp_type & SD_NO_CHECK_CRC7)) { 430c7f6558dSRoger Tseng if (ptr[stat_idx] & SD_CRC7_ERR) { 431c7f6558dSRoger Tseng err = -EILSEQ; 432c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "CRC7 error\n"); 433c7f6558dSRoger Tseng goto out; 434c7f6558dSRoger Tseng } 435c7f6558dSRoger Tseng } 436c7f6558dSRoger Tseng 437c7f6558dSRoger Tseng if (rsp_type == SD_RSP_TYPE_R2) { 438c7f6558dSRoger Tseng for (i = 0; i < 4; i++) { 439c7f6558dSRoger Tseng cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); 440c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", 441c7f6558dSRoger Tseng i, cmd->resp[i]); 442c7f6558dSRoger Tseng } 443c7f6558dSRoger Tseng } else { 444c7f6558dSRoger Tseng cmd->resp[0] = get_unaligned_be32(ptr + 1); 445c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", 446c7f6558dSRoger Tseng cmd->resp[0]); 447c7f6558dSRoger Tseng } 448c7f6558dSRoger Tseng 449c7f6558dSRoger Tseng out: 450c7f6558dSRoger Tseng cmd->error = err; 451c7f6558dSRoger Tseng } 452c7f6558dSRoger Tseng 453c7f6558dSRoger Tseng static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq) 454c7f6558dSRoger Tseng { 455c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 456c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 457c7f6558dSRoger Tseng int read = (data->flags & MMC_DATA_READ) ? 1 : 0; 458c7f6558dSRoger Tseng u8 cfg2, trans_mode; 459c7f6558dSRoger Tseng int err; 460c7f6558dSRoger Tseng u8 flag; 461c7f6558dSRoger Tseng size_t data_len = data->blksz * data->blocks; 462c7f6558dSRoger Tseng unsigned int pipe; 463c7f6558dSRoger Tseng 464c7f6558dSRoger Tseng if (read) { 465c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: read %zu bytes\n", 466c7f6558dSRoger Tseng __func__, data_len); 467c7f6558dSRoger Tseng cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 468c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; 469c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_READ_3; 470c7f6558dSRoger Tseng } else { 471c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: write %zu bytes\n", 472c7f6558dSRoger Tseng __func__, data_len); 473c7f6558dSRoger Tseng cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | 474c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; 475c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_WRITE_3; 476c7f6558dSRoger Tseng } 477c7f6558dSRoger Tseng 478c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 479c7f6558dSRoger Tseng 480c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); 481c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); 482c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 483c7f6558dSRoger Tseng 0xFF, (u8)data->blocks); 484c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 485c7f6558dSRoger Tseng 0xFF, (u8)(data->blocks >> 8)); 486c7f6558dSRoger Tseng 487c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, 488c7f6558dSRoger Tseng 0x01, RING_BUFFER); 489c7f6558dSRoger Tseng 490c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3, 491c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 24)); 492c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2, 493c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 16)); 494c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1, 495c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 8)); 496c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, 497c7f6558dSRoger Tseng 0xFF, (u8)data_len); 498c7f6558dSRoger Tseng if (read) { 499c7f6558dSRoger Tseng flag = MODE_CDIR; 500c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, 501c7f6558dSRoger Tseng 0x03 | DMA_PACK_SIZE_MASK, 502c7f6558dSRoger Tseng DMA_DIR_FROM_CARD | DMA_EN | DMA_512); 503c7f6558dSRoger Tseng } else { 504c7f6558dSRoger Tseng flag = MODE_CDOR; 505c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, 506c7f6558dSRoger Tseng 0x03 | DMA_PACK_SIZE_MASK, 507c7f6558dSRoger Tseng DMA_DIR_TO_CARD | DMA_EN | DMA_512); 508c7f6558dSRoger Tseng } 509c7f6558dSRoger Tseng 510c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); 511c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 512c7f6558dSRoger Tseng trans_mode | SD_TRANSFER_START); 513c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, 514c7f6558dSRoger Tseng SD_TRANSFER_END, SD_TRANSFER_END); 515c7f6558dSRoger Tseng 516c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, flag, 100); 517c7f6558dSRoger Tseng if (err) 518c7f6558dSRoger Tseng return err; 519c7f6558dSRoger Tseng 520c7f6558dSRoger Tseng if (read) 521c7f6558dSRoger Tseng pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN); 522c7f6558dSRoger Tseng else 523c7f6558dSRoger Tseng pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT); 524c7f6558dSRoger Tseng 525c7f6558dSRoger Tseng err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len, 526c7f6558dSRoger Tseng data->sg_len, NULL, 10000); 527c7f6558dSRoger Tseng if (err) { 528c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n" 529c7f6558dSRoger Tseng , err); 530c7f6558dSRoger Tseng sd_clear_error(host); 531c7f6558dSRoger Tseng return err; 532c7f6558dSRoger Tseng } 533c7f6558dSRoger Tseng 534c7f6558dSRoger Tseng return rtsx_usb_get_rsp(ucr, 1, 2000); 535c7f6558dSRoger Tseng } 536c7f6558dSRoger Tseng 537c7f6558dSRoger Tseng static inline void sd_enable_initial_mode(struct rtsx_usb_sdmmc *host) 538c7f6558dSRoger Tseng { 539c7f6558dSRoger Tseng rtsx_usb_write_register(host->ucr, SD_CFG1, 540c7f6558dSRoger Tseng SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); 541c7f6558dSRoger Tseng } 542c7f6558dSRoger Tseng 543c7f6558dSRoger Tseng static inline void sd_disable_initial_mode(struct rtsx_usb_sdmmc *host) 544c7f6558dSRoger Tseng { 545c7f6558dSRoger Tseng rtsx_usb_write_register(host->ucr, SD_CFG1, 546c7f6558dSRoger Tseng SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); 547c7f6558dSRoger Tseng } 548c7f6558dSRoger Tseng 549c7f6558dSRoger Tseng static void sd_normal_rw(struct rtsx_usb_sdmmc *host, 550c7f6558dSRoger Tseng struct mmc_request *mrq) 551c7f6558dSRoger Tseng { 552c7f6558dSRoger Tseng struct mmc_command *cmd = mrq->cmd; 553c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 554c7f6558dSRoger Tseng u8 *buf; 555c7f6558dSRoger Tseng 556c7f6558dSRoger Tseng buf = kzalloc(data->blksz, GFP_NOIO); 557c7f6558dSRoger Tseng if (!buf) { 558c7f6558dSRoger Tseng cmd->error = -ENOMEM; 559c7f6558dSRoger Tseng return; 560c7f6558dSRoger Tseng } 561c7f6558dSRoger Tseng 562c7f6558dSRoger Tseng if (data->flags & MMC_DATA_READ) { 563c7f6558dSRoger Tseng if (host->initial_mode) 564c7f6558dSRoger Tseng sd_disable_initial_mode(host); 565c7f6558dSRoger Tseng 566c7f6558dSRoger Tseng cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, 567c7f6558dSRoger Tseng data->blksz, 200); 568c7f6558dSRoger Tseng 569c7f6558dSRoger Tseng if (host->initial_mode) 570c7f6558dSRoger Tseng sd_enable_initial_mode(host); 571c7f6558dSRoger Tseng 572c7f6558dSRoger Tseng sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); 573c7f6558dSRoger Tseng } else { 574c7f6558dSRoger Tseng sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); 575c7f6558dSRoger Tseng 576c7f6558dSRoger Tseng cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, 577c7f6558dSRoger Tseng data->blksz, 200); 578c7f6558dSRoger Tseng } 579c7f6558dSRoger Tseng 580c7f6558dSRoger Tseng kfree(buf); 581c7f6558dSRoger Tseng } 582c7f6558dSRoger Tseng 583c7f6558dSRoger Tseng static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) 584c7f6558dSRoger Tseng { 585c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 586c7f6558dSRoger Tseng int err; 587c7f6558dSRoger Tseng 588c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n", 589c7f6558dSRoger Tseng __func__, tx ? "TX" : "RX", sample_point); 590c7f6558dSRoger Tseng 591c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 592c7f6558dSRoger Tseng 593c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); 594c7f6558dSRoger Tseng 595c7f6558dSRoger Tseng if (tx) 596c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, 597c7f6558dSRoger Tseng 0x0F, sample_point); 598c7f6558dSRoger Tseng else 599c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK1_CTL, 600c7f6558dSRoger Tseng 0x0F, sample_point); 601c7f6558dSRoger Tseng 602c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); 603c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, 604c7f6558dSRoger Tseng PHASE_NOT_RESET, PHASE_NOT_RESET); 605c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); 606c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0); 607c7f6558dSRoger Tseng 608c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 609c7f6558dSRoger Tseng if (err) 610c7f6558dSRoger Tseng return err; 611c7f6558dSRoger Tseng 612c7f6558dSRoger Tseng return 0; 613c7f6558dSRoger Tseng } 614c7f6558dSRoger Tseng 615c7f6558dSRoger Tseng static inline u32 get_phase_point(u32 phase_map, unsigned int idx) 616c7f6558dSRoger Tseng { 617c7f6558dSRoger Tseng idx &= MAX_PHASE; 618c7f6558dSRoger Tseng return phase_map & (1 << idx); 619c7f6558dSRoger Tseng } 620c7f6558dSRoger Tseng 621c7f6558dSRoger Tseng static int get_phase_len(u32 phase_map, unsigned int idx) 622c7f6558dSRoger Tseng { 623c7f6558dSRoger Tseng int i; 624c7f6558dSRoger Tseng 625c7f6558dSRoger Tseng for (i = 0; i < MAX_PHASE + 1; i++) { 626c7f6558dSRoger Tseng if (get_phase_point(phase_map, idx + i) == 0) 627c7f6558dSRoger Tseng return i; 628c7f6558dSRoger Tseng } 629c7f6558dSRoger Tseng return MAX_PHASE + 1; 630c7f6558dSRoger Tseng } 631c7f6558dSRoger Tseng 632c7f6558dSRoger Tseng static u8 sd_search_final_phase(struct rtsx_usb_sdmmc *host, u32 phase_map) 633c7f6558dSRoger Tseng { 634c7f6558dSRoger Tseng int start = 0, len = 0; 635c7f6558dSRoger Tseng int start_final = 0, len_final = 0; 636c7f6558dSRoger Tseng u8 final_phase = 0xFF; 637c7f6558dSRoger Tseng 638c7f6558dSRoger Tseng if (phase_map == 0) { 639c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "Phase: [map:%x]\n", phase_map); 640c7f6558dSRoger Tseng return final_phase; 641c7f6558dSRoger Tseng } 642c7f6558dSRoger Tseng 643c7f6558dSRoger Tseng while (start < MAX_PHASE + 1) { 644c7f6558dSRoger Tseng len = get_phase_len(phase_map, start); 645c7f6558dSRoger Tseng if (len_final < len) { 646c7f6558dSRoger Tseng start_final = start; 647c7f6558dSRoger Tseng len_final = len; 648c7f6558dSRoger Tseng } 649c7f6558dSRoger Tseng start += len ? len : 1; 650c7f6558dSRoger Tseng } 651c7f6558dSRoger Tseng 652c7f6558dSRoger Tseng final_phase = (start_final + len_final / 2) & MAX_PHASE; 653c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "Phase: [map:%x] [maxlen:%d] [final:%d]\n", 654c7f6558dSRoger Tseng phase_map, len_final, final_phase); 655c7f6558dSRoger Tseng 656c7f6558dSRoger Tseng return final_phase; 657c7f6558dSRoger Tseng } 658c7f6558dSRoger Tseng 659c7f6558dSRoger Tseng static void sd_wait_data_idle(struct rtsx_usb_sdmmc *host) 660c7f6558dSRoger Tseng { 661c7f6558dSRoger Tseng int err, i; 662c7f6558dSRoger Tseng u8 val = 0; 663c7f6558dSRoger Tseng 664c7f6558dSRoger Tseng for (i = 0; i < 100; i++) { 665c7f6558dSRoger Tseng err = rtsx_usb_ep0_read_register(host->ucr, 666c7f6558dSRoger Tseng SD_DATA_STATE, &val); 667c7f6558dSRoger Tseng if (val & SD_DATA_IDLE) 668c7f6558dSRoger Tseng return; 669c7f6558dSRoger Tseng 670c7f6558dSRoger Tseng usleep_range(100, 1000); 671c7f6558dSRoger Tseng } 672c7f6558dSRoger Tseng } 673c7f6558dSRoger Tseng 674c7f6558dSRoger Tseng static int sd_tuning_rx_cmd(struct rtsx_usb_sdmmc *host, 675c7f6558dSRoger Tseng u8 opcode, u8 sample_point) 676c7f6558dSRoger Tseng { 677c7f6558dSRoger Tseng int err; 678c7f6558dSRoger Tseng struct mmc_command cmd = {0}; 679c7f6558dSRoger Tseng 680c7f6558dSRoger Tseng err = sd_change_phase(host, sample_point, 0); 681c7f6558dSRoger Tseng if (err) 682c7f6558dSRoger Tseng return err; 683c7f6558dSRoger Tseng 684c7f6558dSRoger Tseng cmd.opcode = MMC_SEND_TUNING_BLOCK; 685c7f6558dSRoger Tseng err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); 686c7f6558dSRoger Tseng if (err) { 687c7f6558dSRoger Tseng /* Wait till SD DATA IDLE */ 688c7f6558dSRoger Tseng sd_wait_data_idle(host); 689c7f6558dSRoger Tseng sd_clear_error(host); 690c7f6558dSRoger Tseng return err; 691c7f6558dSRoger Tseng } 692c7f6558dSRoger Tseng 693c7f6558dSRoger Tseng return 0; 694c7f6558dSRoger Tseng } 695c7f6558dSRoger Tseng 696c7f6558dSRoger Tseng static void sd_tuning_phase(struct rtsx_usb_sdmmc *host, 697c7f6558dSRoger Tseng u8 opcode, u16 *phase_map) 698c7f6558dSRoger Tseng { 699c7f6558dSRoger Tseng int err, i; 700c7f6558dSRoger Tseng u16 raw_phase_map = 0; 701c7f6558dSRoger Tseng 702c7f6558dSRoger Tseng for (i = MAX_PHASE; i >= 0; i--) { 703c7f6558dSRoger Tseng err = sd_tuning_rx_cmd(host, opcode, (u8)i); 704c7f6558dSRoger Tseng if (!err) 705c7f6558dSRoger Tseng raw_phase_map |= 1 << i; 706c7f6558dSRoger Tseng } 707c7f6558dSRoger Tseng 708c7f6558dSRoger Tseng if (phase_map) 709c7f6558dSRoger Tseng *phase_map = raw_phase_map; 710c7f6558dSRoger Tseng } 711c7f6558dSRoger Tseng 712c7f6558dSRoger Tseng static int sd_tuning_rx(struct rtsx_usb_sdmmc *host, u8 opcode) 713c7f6558dSRoger Tseng { 714c7f6558dSRoger Tseng int err, i; 715c7f6558dSRoger Tseng u16 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; 716c7f6558dSRoger Tseng u8 final_phase; 717c7f6558dSRoger Tseng 718c7f6558dSRoger Tseng /* setting fixed default TX phase */ 719c7f6558dSRoger Tseng err = sd_change_phase(host, 0x01, 1); 720c7f6558dSRoger Tseng if (err) { 721c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "TX phase setting failed\n"); 722c7f6558dSRoger Tseng return err; 723c7f6558dSRoger Tseng } 724c7f6558dSRoger Tseng 725c7f6558dSRoger Tseng /* tuning RX phase */ 726c7f6558dSRoger Tseng for (i = 0; i < RX_TUNING_CNT; i++) { 727c7f6558dSRoger Tseng sd_tuning_phase(host, opcode, &(raw_phase_map[i])); 728c7f6558dSRoger Tseng 729c7f6558dSRoger Tseng if (raw_phase_map[i] == 0) 730c7f6558dSRoger Tseng break; 731c7f6558dSRoger Tseng } 732c7f6558dSRoger Tseng 733c7f6558dSRoger Tseng phase_map = 0xFFFF; 734c7f6558dSRoger Tseng for (i = 0; i < RX_TUNING_CNT; i++) { 735c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%04x\n", 736c7f6558dSRoger Tseng i, raw_phase_map[i]); 737c7f6558dSRoger Tseng phase_map &= raw_phase_map[i]; 738c7f6558dSRoger Tseng } 739c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%04x\n", phase_map); 740c7f6558dSRoger Tseng 741c7f6558dSRoger Tseng if (phase_map) { 742c7f6558dSRoger Tseng final_phase = sd_search_final_phase(host, phase_map); 743c7f6558dSRoger Tseng if (final_phase == 0xFF) 744c7f6558dSRoger Tseng return -EINVAL; 745c7f6558dSRoger Tseng 746c7f6558dSRoger Tseng err = sd_change_phase(host, final_phase, 0); 747c7f6558dSRoger Tseng if (err) 748c7f6558dSRoger Tseng return err; 749c7f6558dSRoger Tseng } else { 750c7f6558dSRoger Tseng return -EINVAL; 751c7f6558dSRoger Tseng } 752c7f6558dSRoger Tseng 753c7f6558dSRoger Tseng return 0; 754c7f6558dSRoger Tseng } 755c7f6558dSRoger Tseng 756c7f6558dSRoger Tseng static int sdmmc_get_ro(struct mmc_host *mmc) 757c7f6558dSRoger Tseng { 758c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 759c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 760c7f6558dSRoger Tseng int err; 761c7f6558dSRoger Tseng u16 val; 762c7f6558dSRoger Tseng 763c7f6558dSRoger Tseng if (host->host_removal) 764c7f6558dSRoger Tseng return -ENOMEDIUM; 765c7f6558dSRoger Tseng 766c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 767c7f6558dSRoger Tseng 768c7f6558dSRoger Tseng /* Check SD card detect */ 769c7f6558dSRoger Tseng err = rtsx_usb_get_card_status(ucr, &val); 770c7f6558dSRoger Tseng 771c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 772c7f6558dSRoger Tseng 773c7f6558dSRoger Tseng 774c7f6558dSRoger Tseng /* Treat failed detection as non-ro */ 775c7f6558dSRoger Tseng if (err) 776c7f6558dSRoger Tseng return 0; 777c7f6558dSRoger Tseng 778c7f6558dSRoger Tseng if (val & SD_WP) 779c7f6558dSRoger Tseng return 1; 780c7f6558dSRoger Tseng 781c7f6558dSRoger Tseng return 0; 782c7f6558dSRoger Tseng } 783c7f6558dSRoger Tseng 784c7f6558dSRoger Tseng static int sdmmc_get_cd(struct mmc_host *mmc) 785c7f6558dSRoger Tseng { 786c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 787c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 788c7f6558dSRoger Tseng int err; 789c7f6558dSRoger Tseng u16 val; 790c7f6558dSRoger Tseng 791c7f6558dSRoger Tseng if (host->host_removal) 792c7f6558dSRoger Tseng return -ENOMEDIUM; 793c7f6558dSRoger Tseng 794c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 795c7f6558dSRoger Tseng 796c7f6558dSRoger Tseng /* Check SD card detect */ 797c7f6558dSRoger Tseng err = rtsx_usb_get_card_status(ucr, &val); 798c7f6558dSRoger Tseng 799c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 800c7f6558dSRoger Tseng 801c7f6558dSRoger Tseng /* Treat failed detection as non-exist */ 802c7f6558dSRoger Tseng if (err) 803c7f6558dSRoger Tseng goto no_card; 804c7f6558dSRoger Tseng 805c7f6558dSRoger Tseng if (val & SD_CD) { 806c7f6558dSRoger Tseng host->card_exist = true; 807c7f6558dSRoger Tseng return 1; 808c7f6558dSRoger Tseng } 809c7f6558dSRoger Tseng 810c7f6558dSRoger Tseng no_card: 811c7f6558dSRoger Tseng host->card_exist = false; 812c7f6558dSRoger Tseng return 0; 813c7f6558dSRoger Tseng } 814c7f6558dSRoger Tseng 815c7f6558dSRoger Tseng static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 816c7f6558dSRoger Tseng { 817c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 818c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 819c7f6558dSRoger Tseng struct mmc_command *cmd = mrq->cmd; 820c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 821c7f6558dSRoger Tseng unsigned int data_size = 0; 822c7f6558dSRoger Tseng 823c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 824c7f6558dSRoger Tseng 825c7f6558dSRoger Tseng if (host->host_removal) { 826c7f6558dSRoger Tseng cmd->error = -ENOMEDIUM; 827c7f6558dSRoger Tseng goto finish; 828c7f6558dSRoger Tseng } 829c7f6558dSRoger Tseng 830c7f6558dSRoger Tseng if ((!host->card_exist)) { 831c7f6558dSRoger Tseng cmd->error = -ENOMEDIUM; 832c7f6558dSRoger Tseng goto finish_detect_card; 833c7f6558dSRoger Tseng } 834c7f6558dSRoger Tseng 835c7f6558dSRoger Tseng /* 836c7f6558dSRoger Tseng * Reject SDIO CMDs to speed up card identification 837c7f6558dSRoger Tseng * since unsupported 838c7f6558dSRoger Tseng */ 839c7f6558dSRoger Tseng if (cmd->opcode == SD_IO_SEND_OP_COND || 840c7f6558dSRoger Tseng cmd->opcode == SD_IO_RW_DIRECT || 841c7f6558dSRoger Tseng cmd->opcode == SD_IO_RW_EXTENDED) { 842c7f6558dSRoger Tseng cmd->error = -EINVAL; 843c7f6558dSRoger Tseng goto finish; 844c7f6558dSRoger Tseng } 845c7f6558dSRoger Tseng 846c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 847c7f6558dSRoger Tseng 848c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 849c7f6558dSRoger Tseng host->mrq = mrq; 850c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 851c7f6558dSRoger Tseng 852c7f6558dSRoger Tseng if (mrq->data) 853c7f6558dSRoger Tseng data_size = data->blocks * data->blksz; 854c7f6558dSRoger Tseng 855c7f6558dSRoger Tseng if (!data_size) { 856c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, cmd); 857c7f6558dSRoger Tseng } else if ((!(data_size % 512) && cmd->opcode != MMC_SEND_EXT_CSD) || 858c7f6558dSRoger Tseng mmc_op_multi(cmd->opcode)) { 859c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, cmd); 860c7f6558dSRoger Tseng 861c7f6558dSRoger Tseng if (!cmd->error) { 862c7f6558dSRoger Tseng sd_rw_multi(host, mrq); 863c7f6558dSRoger Tseng 864c7f6558dSRoger Tseng if (mmc_op_multi(cmd->opcode) && mrq->stop) { 865c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, mrq->stop); 866c7f6558dSRoger Tseng rtsx_usb_write_register(ucr, MC_FIFO_CTL, 867c7f6558dSRoger Tseng FIFO_FLUSH, FIFO_FLUSH); 868c7f6558dSRoger Tseng } 869c7f6558dSRoger Tseng } 870c7f6558dSRoger Tseng } else { 871c7f6558dSRoger Tseng sd_normal_rw(host, mrq); 872c7f6558dSRoger Tseng } 873c7f6558dSRoger Tseng 874c7f6558dSRoger Tseng if (mrq->data) { 875c7f6558dSRoger Tseng if (cmd->error || data->error) 876c7f6558dSRoger Tseng data->bytes_xfered = 0; 877c7f6558dSRoger Tseng else 878c7f6558dSRoger Tseng data->bytes_xfered = data->blocks * data->blksz; 879c7f6558dSRoger Tseng } 880c7f6558dSRoger Tseng 881c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 882c7f6558dSRoger Tseng 883c7f6558dSRoger Tseng finish_detect_card: 884c7f6558dSRoger Tseng if (cmd->error) { 885c7f6558dSRoger Tseng /* 886c7f6558dSRoger Tseng * detect card when fail to update card existence state and 887c7f6558dSRoger Tseng * speed up card removal when retry 888c7f6558dSRoger Tseng */ 889c7f6558dSRoger Tseng sdmmc_get_cd(mmc); 890c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); 891c7f6558dSRoger Tseng } 892c7f6558dSRoger Tseng 893c7f6558dSRoger Tseng finish: 894c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 895c7f6558dSRoger Tseng host->mrq = NULL; 896c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 897c7f6558dSRoger Tseng 898c7f6558dSRoger Tseng mmc_request_done(mmc, mrq); 899c7f6558dSRoger Tseng } 900c7f6558dSRoger Tseng 901c7f6558dSRoger Tseng static int sd_set_bus_width(struct rtsx_usb_sdmmc *host, 902c7f6558dSRoger Tseng unsigned char bus_width) 903c7f6558dSRoger Tseng { 904c7f6558dSRoger Tseng int err = 0; 905c7f6558dSRoger Tseng u8 width[] = { 906c7f6558dSRoger Tseng [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, 907c7f6558dSRoger Tseng [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, 908c7f6558dSRoger Tseng [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, 909c7f6558dSRoger Tseng }; 910c7f6558dSRoger Tseng 911c7f6558dSRoger Tseng if (bus_width <= MMC_BUS_WIDTH_8) 912c7f6558dSRoger Tseng err = rtsx_usb_write_register(host->ucr, SD_CFG1, 913c7f6558dSRoger Tseng 0x03, width[bus_width]); 914c7f6558dSRoger Tseng 915c7f6558dSRoger Tseng return err; 916c7f6558dSRoger Tseng } 917c7f6558dSRoger Tseng 918c7f6558dSRoger Tseng static int sd_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr) 919c7f6558dSRoger Tseng { 920c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 921c7f6558dSRoger Tseng 922c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); 923c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 924c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 925c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 926c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 927c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 928c7f6558dSRoger Tseng 929c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 930c7f6558dSRoger Tseng } 931c7f6558dSRoger Tseng 932c7f6558dSRoger Tseng static int sd_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr) 933c7f6558dSRoger Tseng { 934c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 935c7f6558dSRoger Tseng 936c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); 937c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 938c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 939c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 940c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); 941c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); 942c7f6558dSRoger Tseng 943c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 944c7f6558dSRoger Tseng } 945c7f6558dSRoger Tseng 946c7f6558dSRoger Tseng static int sd_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr) 947c7f6558dSRoger Tseng { 948c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 949c7f6558dSRoger Tseng 950c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); 951c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); 952c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9); 953c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 954c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 955c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 956c7f6558dSRoger Tseng 957c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 958c7f6558dSRoger Tseng } 959c7f6558dSRoger Tseng 960c7f6558dSRoger Tseng static int sd_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr) 961c7f6558dSRoger Tseng { 962c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 963c7f6558dSRoger Tseng 964c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); 965c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A); 966c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5); 967c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A); 968c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65); 969c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A); 970c7f6558dSRoger Tseng 971c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 972c7f6558dSRoger Tseng } 973c7f6558dSRoger Tseng 974c7f6558dSRoger Tseng static int sd_power_on(struct rtsx_usb_sdmmc *host) 975c7f6558dSRoger Tseng { 976c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 977c7f6558dSRoger Tseng int err; 978c7f6558dSRoger Tseng 979c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 980c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 981c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); 982c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE, 983c7f6558dSRoger Tseng CARD_SHARE_MASK, CARD_SHARE_SD); 984c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, 985c7f6558dSRoger Tseng SD_CLK_EN, SD_CLK_EN); 986c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 987c7f6558dSRoger Tseng if (err) 988c7f6558dSRoger Tseng return err; 989c7f6558dSRoger Tseng 990c7f6558dSRoger Tseng if (CHECK_PKG(ucr, LQFP48)) 991c7f6558dSRoger Tseng err = sd_pull_ctl_enable_lqfp48(ucr); 992c7f6558dSRoger Tseng else 993c7f6558dSRoger Tseng err = sd_pull_ctl_enable_qfn24(ucr); 994c7f6558dSRoger Tseng if (err) 995c7f6558dSRoger Tseng return err; 996c7f6558dSRoger Tseng 997c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, CARD_PWR_CTL, 998c7f6558dSRoger Tseng POWER_MASK, PARTIAL_POWER_ON); 999c7f6558dSRoger Tseng if (err) 1000c7f6558dSRoger Tseng return err; 1001c7f6558dSRoger Tseng 1002c7f6558dSRoger Tseng usleep_range(800, 1000); 1003c7f6558dSRoger Tseng 1004c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1005c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1006c7f6558dSRoger Tseng POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON); 1007c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, 1008c7f6558dSRoger Tseng SD_OUTPUT_EN, SD_OUTPUT_EN); 1009c7f6558dSRoger Tseng 1010c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 1011c7f6558dSRoger Tseng } 1012c7f6558dSRoger Tseng 1013c7f6558dSRoger Tseng static int sd_power_off(struct rtsx_usb_sdmmc *host) 1014c7f6558dSRoger Tseng { 1015c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1016c7f6558dSRoger Tseng int err; 1017c7f6558dSRoger Tseng 1018c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1019c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1020c7f6558dSRoger Tseng 1021c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); 1022c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); 1023c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1024c7f6558dSRoger Tseng POWER_MASK, POWER_OFF); 1025c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1026c7f6558dSRoger Tseng POWER_MASK|LDO3318_PWR_MASK, POWER_OFF|LDO_SUSPEND); 1027c7f6558dSRoger Tseng 1028c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1029c7f6558dSRoger Tseng if (err) 1030c7f6558dSRoger Tseng return err; 1031c7f6558dSRoger Tseng 1032c7f6558dSRoger Tseng if (CHECK_PKG(ucr, LQFP48)) 1033c7f6558dSRoger Tseng return sd_pull_ctl_disable_lqfp48(ucr); 1034c7f6558dSRoger Tseng return sd_pull_ctl_disable_qfn24(ucr); 1035c7f6558dSRoger Tseng } 1036c7f6558dSRoger Tseng 1037c7f6558dSRoger Tseng static int sd_set_power_mode(struct rtsx_usb_sdmmc *host, 1038c7f6558dSRoger Tseng unsigned char power_mode) 1039c7f6558dSRoger Tseng { 1040c7f6558dSRoger Tseng int err; 1041c7f6558dSRoger Tseng 1042c7f6558dSRoger Tseng if (power_mode != MMC_POWER_OFF) 1043c7f6558dSRoger Tseng power_mode = MMC_POWER_ON; 1044c7f6558dSRoger Tseng 1045c7f6558dSRoger Tseng if (power_mode == host->power_mode) 1046c7f6558dSRoger Tseng return 0; 1047c7f6558dSRoger Tseng 1048c7f6558dSRoger Tseng if (power_mode == MMC_POWER_OFF) { 1049c7f6558dSRoger Tseng err = sd_power_off(host); 1050c7f6558dSRoger Tseng pm_runtime_put(sdmmc_dev(host)); 1051c7f6558dSRoger Tseng } else { 1052c7f6558dSRoger Tseng pm_runtime_get_sync(sdmmc_dev(host)); 1053c7f6558dSRoger Tseng err = sd_power_on(host); 1054c7f6558dSRoger Tseng } 1055c7f6558dSRoger Tseng 1056c7f6558dSRoger Tseng if (!err) 1057c7f6558dSRoger Tseng host->power_mode = power_mode; 1058c7f6558dSRoger Tseng 1059c7f6558dSRoger Tseng return err; 1060c7f6558dSRoger Tseng } 1061c7f6558dSRoger Tseng 1062c7f6558dSRoger Tseng static int sd_set_timing(struct rtsx_usb_sdmmc *host, 1063c7f6558dSRoger Tseng unsigned char timing, bool *ddr_mode) 1064c7f6558dSRoger Tseng { 1065c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1066c7f6558dSRoger Tseng int err; 1067c7f6558dSRoger Tseng 1068c7f6558dSRoger Tseng *ddr_mode = false; 1069c7f6558dSRoger Tseng 1070c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1071c7f6558dSRoger Tseng 1072c7f6558dSRoger Tseng switch (timing) { 1073c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR104: 1074c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR50: 1075c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1076c7f6558dSRoger Tseng 0x0C | SD_ASYNC_FIFO_RST, 1077c7f6558dSRoger Tseng SD_30_MODE | SD_ASYNC_FIFO_RST); 1078c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1079c7f6558dSRoger Tseng CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 1080c7f6558dSRoger Tseng break; 1081c7f6558dSRoger Tseng 1082c7f6558dSRoger Tseng case MMC_TIMING_UHS_DDR50: 1083c7f6558dSRoger Tseng *ddr_mode = true; 1084c7f6558dSRoger Tseng 1085c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1086c7f6558dSRoger Tseng 0x0C | SD_ASYNC_FIFO_RST, 1087c7f6558dSRoger Tseng SD_DDR_MODE | SD_ASYNC_FIFO_RST); 1088c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1089c7f6558dSRoger Tseng CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 1090c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 1091c7f6558dSRoger Tseng DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); 1092c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1093c7f6558dSRoger Tseng DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, 1094c7f6558dSRoger Tseng DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); 1095c7f6558dSRoger Tseng break; 1096c7f6558dSRoger Tseng 1097c7f6558dSRoger Tseng case MMC_TIMING_MMC_HS: 1098c7f6558dSRoger Tseng case MMC_TIMING_SD_HS: 1099c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1100c7f6558dSRoger Tseng 0x0C, SD_20_MODE); 1101c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1102c7f6558dSRoger Tseng CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 1103c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 1104c7f6558dSRoger Tseng SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); 1105c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1106c7f6558dSRoger Tseng SD20_RX_SEL_MASK, SD20_RX_14_DELAY); 1107c7f6558dSRoger Tseng break; 1108c7f6558dSRoger Tseng 1109c7f6558dSRoger Tseng default: 1110c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 1111c7f6558dSRoger Tseng SD_CFG1, 0x0C, SD_20_MODE); 1112c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1113c7f6558dSRoger Tseng CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 1114c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 1115c7f6558dSRoger Tseng SD_PUSH_POINT_CTL, 0xFF, 0); 1116c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1117c7f6558dSRoger Tseng SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); 1118c7f6558dSRoger Tseng break; 1119c7f6558dSRoger Tseng } 1120c7f6558dSRoger Tseng 1121c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1122c7f6558dSRoger Tseng 1123c7f6558dSRoger Tseng return err; 1124c7f6558dSRoger Tseng } 1125c7f6558dSRoger Tseng 1126c7f6558dSRoger Tseng static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1127c7f6558dSRoger Tseng { 1128c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1129c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1130c7f6558dSRoger Tseng 1131c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1132c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1133c7f6558dSRoger Tseng 1134c7f6558dSRoger Tseng if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { 1135c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1136c7f6558dSRoger Tseng return; 1137c7f6558dSRoger Tseng } 1138c7f6558dSRoger Tseng 1139c7f6558dSRoger Tseng sd_set_power_mode(host, ios->power_mode); 1140c7f6558dSRoger Tseng sd_set_bus_width(host, ios->bus_width); 1141c7f6558dSRoger Tseng sd_set_timing(host, ios->timing, &host->ddr_mode); 1142c7f6558dSRoger Tseng 1143c7f6558dSRoger Tseng host->vpclk = false; 1144c7f6558dSRoger Tseng host->double_clk = true; 1145c7f6558dSRoger Tseng 1146c7f6558dSRoger Tseng switch (ios->timing) { 1147c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR104: 1148c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR50: 1149c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_2M; 1150c7f6558dSRoger Tseng host->vpclk = true; 1151c7f6558dSRoger Tseng host->double_clk = false; 1152c7f6558dSRoger Tseng break; 1153c7f6558dSRoger Tseng case MMC_TIMING_UHS_DDR50: 1154c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR25: 1155c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_1M; 1156c7f6558dSRoger Tseng break; 1157c7f6558dSRoger Tseng default: 1158c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_512K; 1159c7f6558dSRoger Tseng break; 1160c7f6558dSRoger Tseng } 1161c7f6558dSRoger Tseng 1162c7f6558dSRoger Tseng host->initial_mode = (ios->clock <= 1000000) ? true : false; 1163c7f6558dSRoger Tseng host->clock = ios->clock; 1164c7f6558dSRoger Tseng 1165c7f6558dSRoger Tseng rtsx_usb_switch_clock(host->ucr, host->clock, host->ssc_depth, 1166c7f6558dSRoger Tseng host->initial_mode, host->double_clk, host->vpclk); 1167c7f6558dSRoger Tseng 1168c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1169c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s end\n", __func__); 1170c7f6558dSRoger Tseng } 1171c7f6558dSRoger Tseng 1172c7f6558dSRoger Tseng static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) 1173c7f6558dSRoger Tseng { 1174c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1175c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1176c7f6558dSRoger Tseng int err = 0; 1177c7f6558dSRoger Tseng 1178c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", 1179c7f6558dSRoger Tseng __func__, ios->signal_voltage); 1180c7f6558dSRoger Tseng 1181c7f6558dSRoger Tseng if (host->host_removal) 1182c7f6558dSRoger Tseng return -ENOMEDIUM; 1183c7f6558dSRoger Tseng 1184c7f6558dSRoger Tseng if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) 1185c7f6558dSRoger Tseng return -EPERM; 1186c7f6558dSRoger Tseng 1187c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1188c7f6558dSRoger Tseng 1189c7f6558dSRoger Tseng err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD); 1190c7f6558dSRoger Tseng if (err) { 1191c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1192c7f6558dSRoger Tseng return err; 1193c7f6558dSRoger Tseng } 1194c7f6558dSRoger Tseng 1195c7f6558dSRoger Tseng /* Let mmc core do the busy checking, simply stop the forced-toggle 1196c7f6558dSRoger Tseng * clock(while issuing CMD11) and switch voltage. 1197c7f6558dSRoger Tseng */ 1198c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1199c7f6558dSRoger Tseng 1200c7f6558dSRoger Tseng if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 1201c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, 1202c7f6558dSRoger Tseng SD_IO_USING_1V8, SD_IO_USING_3V3); 1203c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 1204c7f6558dSRoger Tseng TUNE_SD18_MASK, TUNE_SD18_3V3); 1205c7f6558dSRoger Tseng } else { 1206c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BUS_STAT, 1207c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 1208c7f6558dSRoger Tseng SD_CLK_FORCE_STOP); 1209c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, 1210c7f6558dSRoger Tseng SD_IO_USING_1V8, SD_IO_USING_1V8); 1211c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 1212c7f6558dSRoger Tseng TUNE_SD18_MASK, TUNE_SD18_1V8); 1213c7f6558dSRoger Tseng } 1214c7f6558dSRoger Tseng 1215c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1216c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1217c7f6558dSRoger Tseng 1218c7f6558dSRoger Tseng return err; 1219c7f6558dSRoger Tseng } 1220c7f6558dSRoger Tseng 1221c7f6558dSRoger Tseng static int sdmmc_card_busy(struct mmc_host *mmc) 1222c7f6558dSRoger Tseng { 1223c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1224c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1225c7f6558dSRoger Tseng int err; 1226c7f6558dSRoger Tseng u8 stat; 1227c7f6558dSRoger Tseng u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS 1228c7f6558dSRoger Tseng | SD_DAT0_STATUS; 1229c7f6558dSRoger Tseng 1230c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1231c7f6558dSRoger Tseng 1232c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1233c7f6558dSRoger Tseng 1234c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, SD_BUS_STAT, 1235c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 1236c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN); 1237c7f6558dSRoger Tseng if (err) 1238c7f6558dSRoger Tseng goto out; 1239c7f6558dSRoger Tseng 1240c7f6558dSRoger Tseng mdelay(1); 1241c7f6558dSRoger Tseng 1242c7f6558dSRoger Tseng err = rtsx_usb_read_register(ucr, SD_BUS_STAT, &stat); 1243c7f6558dSRoger Tseng if (err) 1244c7f6558dSRoger Tseng goto out; 1245c7f6558dSRoger Tseng 1246c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, SD_BUS_STAT, 1247c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); 1248c7f6558dSRoger Tseng out: 1249c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1250c7f6558dSRoger Tseng 1251c7f6558dSRoger Tseng if (err) 1252c7f6558dSRoger Tseng return err; 1253c7f6558dSRoger Tseng 1254c7f6558dSRoger Tseng /* check if any pin between dat[0:3] is low */ 1255c7f6558dSRoger Tseng if ((stat & mask) != mask) 1256c7f6558dSRoger Tseng return 1; 1257c7f6558dSRoger Tseng else 1258c7f6558dSRoger Tseng return 0; 1259c7f6558dSRoger Tseng } 1260c7f6558dSRoger Tseng 1261c7f6558dSRoger Tseng static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) 1262c7f6558dSRoger Tseng { 1263c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1264c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1265c7f6558dSRoger Tseng int err = 0; 1266c7f6558dSRoger Tseng 1267c7f6558dSRoger Tseng if (host->host_removal) 1268c7f6558dSRoger Tseng return -ENOMEDIUM; 1269c7f6558dSRoger Tseng 1270c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1271c7f6558dSRoger Tseng 1272c7f6558dSRoger Tseng if (!host->ddr_mode) 1273c7f6558dSRoger Tseng err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); 1274c7f6558dSRoger Tseng 1275c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1276c7f6558dSRoger Tseng 1277c7f6558dSRoger Tseng return err; 1278c7f6558dSRoger Tseng } 1279c7f6558dSRoger Tseng 1280c7f6558dSRoger Tseng static const struct mmc_host_ops rtsx_usb_sdmmc_ops = { 1281c7f6558dSRoger Tseng .request = sdmmc_request, 1282c7f6558dSRoger Tseng .set_ios = sdmmc_set_ios, 1283c7f6558dSRoger Tseng .get_ro = sdmmc_get_ro, 1284c7f6558dSRoger Tseng .get_cd = sdmmc_get_cd, 1285c7f6558dSRoger Tseng .start_signal_voltage_switch = sdmmc_switch_voltage, 1286c7f6558dSRoger Tseng .card_busy = sdmmc_card_busy, 1287c7f6558dSRoger Tseng .execute_tuning = sdmmc_execute_tuning, 1288c7f6558dSRoger Tseng }; 1289c7f6558dSRoger Tseng 1290c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1291c7f6558dSRoger Tseng static void rtsx_usb_led_control(struct led_classdev *led, 1292c7f6558dSRoger Tseng enum led_brightness brightness) 1293c7f6558dSRoger Tseng { 1294c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = container_of(led, 1295c7f6558dSRoger Tseng struct rtsx_usb_sdmmc, led); 1296c7f6558dSRoger Tseng 1297c7f6558dSRoger Tseng if (host->host_removal) 1298c7f6558dSRoger Tseng return; 1299c7f6558dSRoger Tseng 1300c7f6558dSRoger Tseng host->led.brightness = brightness; 1301c7f6558dSRoger Tseng schedule_work(&host->led_work); 1302c7f6558dSRoger Tseng } 1303c7f6558dSRoger Tseng 1304c7f6558dSRoger Tseng static void rtsx_usb_update_led(struct work_struct *work) 1305c7f6558dSRoger Tseng { 1306c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = 1307c7f6558dSRoger Tseng container_of(work, struct rtsx_usb_sdmmc, led_work); 1308c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1309c7f6558dSRoger Tseng 1310c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1311c7f6558dSRoger Tseng 1312c7f6558dSRoger Tseng if (host->led.brightness == LED_OFF) 1313c7f6558dSRoger Tseng rtsx_usb_turn_off_led(ucr); 1314c7f6558dSRoger Tseng else 1315c7f6558dSRoger Tseng rtsx_usb_turn_on_led(ucr); 1316c7f6558dSRoger Tseng 1317c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1318c7f6558dSRoger Tseng } 1319c7f6558dSRoger Tseng #endif 1320c7f6558dSRoger Tseng 1321c7f6558dSRoger Tseng static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) 1322c7f6558dSRoger Tseng { 1323c7f6558dSRoger Tseng struct mmc_host *mmc = host->mmc; 1324c7f6558dSRoger Tseng 1325c7f6558dSRoger Tseng mmc->f_min = 250000; 1326c7f6558dSRoger Tseng mmc->f_max = 208000000; 1327c7f6558dSRoger Tseng mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 1328c7f6558dSRoger Tseng mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | 1329c7f6558dSRoger Tseng MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | 1330c7f6558dSRoger Tseng MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | 1331c7f6558dSRoger Tseng MMC_CAP_NEEDS_POLL; 1332c7f6558dSRoger Tseng 1333c7f6558dSRoger Tseng mmc->max_current_330 = 400; 1334c7f6558dSRoger Tseng mmc->max_current_180 = 800; 1335c7f6558dSRoger Tseng mmc->ops = &rtsx_usb_sdmmc_ops; 1336c7f6558dSRoger Tseng mmc->max_segs = 256; 1337c7f6558dSRoger Tseng mmc->max_seg_size = 65536; 1338c7f6558dSRoger Tseng mmc->max_blk_size = 512; 1339c7f6558dSRoger Tseng mmc->max_blk_count = 65535; 1340c7f6558dSRoger Tseng mmc->max_req_size = 524288; 1341c7f6558dSRoger Tseng 1342c7f6558dSRoger Tseng host->power_mode = MMC_POWER_OFF; 1343c7f6558dSRoger Tseng } 1344c7f6558dSRoger Tseng 1345c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) 1346c7f6558dSRoger Tseng { 1347c7f6558dSRoger Tseng struct mmc_host *mmc; 1348c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host; 1349c7f6558dSRoger Tseng struct rtsx_ucr *ucr; 1350c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1351c7f6558dSRoger Tseng int err; 1352c7f6558dSRoger Tseng #endif 1353c7f6558dSRoger Tseng 1354c7f6558dSRoger Tseng ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); 1355c7f6558dSRoger Tseng if (!ucr) 1356c7f6558dSRoger Tseng return -ENXIO; 1357c7f6558dSRoger Tseng 1358c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n"); 1359c7f6558dSRoger Tseng 1360c7f6558dSRoger Tseng mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); 1361c7f6558dSRoger Tseng if (!mmc) 1362c7f6558dSRoger Tseng return -ENOMEM; 1363c7f6558dSRoger Tseng 1364c7f6558dSRoger Tseng host = mmc_priv(mmc); 1365c7f6558dSRoger Tseng host->ucr = ucr; 1366c7f6558dSRoger Tseng host->mmc = mmc; 1367c7f6558dSRoger Tseng host->pdev = pdev; 1368c7f6558dSRoger Tseng platform_set_drvdata(pdev, host); 1369c7f6558dSRoger Tseng 1370c7f6558dSRoger Tseng mutex_init(&host->host_mutex); 1371c7f6558dSRoger Tseng rtsx_usb_init_host(host); 1372c7f6558dSRoger Tseng pm_runtime_enable(&pdev->dev); 1373c7f6558dSRoger Tseng 1374c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1375c7f6558dSRoger Tseng snprintf(host->led_name, sizeof(host->led_name), 1376c7f6558dSRoger Tseng "%s::", mmc_hostname(mmc)); 1377c7f6558dSRoger Tseng host->led.name = host->led_name; 1378c7f6558dSRoger Tseng host->led.brightness = LED_OFF; 1379c7f6558dSRoger Tseng host->led.default_trigger = mmc_hostname(mmc); 1380c7f6558dSRoger Tseng host->led.brightness_set = rtsx_usb_led_control; 1381c7f6558dSRoger Tseng 1382c7f6558dSRoger Tseng err = led_classdev_register(mmc_dev(mmc), &host->led); 1383c7f6558dSRoger Tseng if (err) 1384c7f6558dSRoger Tseng dev_err(&(pdev->dev), 1385c7f6558dSRoger Tseng "Failed to register LED device: %d\n", err); 1386c7f6558dSRoger Tseng INIT_WORK(&host->led_work, rtsx_usb_update_led); 1387c7f6558dSRoger Tseng 1388c7f6558dSRoger Tseng #endif 1389c7f6558dSRoger Tseng mmc_add_host(mmc); 1390c7f6558dSRoger Tseng 1391c7f6558dSRoger Tseng return 0; 1392c7f6558dSRoger Tseng } 1393c7f6558dSRoger Tseng 1394c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) 1395c7f6558dSRoger Tseng { 1396c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); 1397c7f6558dSRoger Tseng struct mmc_host *mmc; 1398c7f6558dSRoger Tseng 1399c7f6558dSRoger Tseng if (!host) 1400c7f6558dSRoger Tseng return 0; 1401c7f6558dSRoger Tseng 1402c7f6558dSRoger Tseng mmc = host->mmc; 1403c7f6558dSRoger Tseng host->host_removal = true; 1404c7f6558dSRoger Tseng 1405c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 1406c7f6558dSRoger Tseng if (host->mrq) { 1407c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), 1408c7f6558dSRoger Tseng "%s: Controller removed during transfer\n", 1409c7f6558dSRoger Tseng mmc_hostname(mmc)); 1410c7f6558dSRoger Tseng host->mrq->cmd->error = -ENOMEDIUM; 1411c7f6558dSRoger Tseng if (host->mrq->stop) 1412c7f6558dSRoger Tseng host->mrq->stop->error = -ENOMEDIUM; 1413c7f6558dSRoger Tseng mmc_request_done(mmc, host->mrq); 1414c7f6558dSRoger Tseng } 1415c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 1416c7f6558dSRoger Tseng 1417c7f6558dSRoger Tseng mmc_remove_host(mmc); 1418c7f6558dSRoger Tseng 1419c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1420c7f6558dSRoger Tseng cancel_work_sync(&host->led_work); 1421c7f6558dSRoger Tseng led_classdev_unregister(&host->led); 1422c7f6558dSRoger Tseng #endif 1423c7f6558dSRoger Tseng 1424c7f6558dSRoger Tseng mmc_free_host(mmc); 1425c7f6558dSRoger Tseng pm_runtime_disable(&pdev->dev); 1426c7f6558dSRoger Tseng platform_set_drvdata(pdev, NULL); 1427c7f6558dSRoger Tseng 1428c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), 1429c7f6558dSRoger Tseng ": Realtek USB SD/MMC module has been removed\n"); 1430c7f6558dSRoger Tseng 1431c7f6558dSRoger Tseng return 0; 1432c7f6558dSRoger Tseng } 1433c7f6558dSRoger Tseng 1434c7f6558dSRoger Tseng static struct platform_device_id rtsx_usb_sdmmc_ids[] = { 1435c7f6558dSRoger Tseng { 1436c7f6558dSRoger Tseng .name = "rtsx_usb_sdmmc", 1437c7f6558dSRoger Tseng }, { 1438c7f6558dSRoger Tseng /* sentinel */ 1439c7f6558dSRoger Tseng } 1440c7f6558dSRoger Tseng }; 1441c7f6558dSRoger Tseng MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); 1442c7f6558dSRoger Tseng 1443c7f6558dSRoger Tseng static struct platform_driver rtsx_usb_sdmmc_driver = { 1444c7f6558dSRoger Tseng .probe = rtsx_usb_sdmmc_drv_probe, 1445c7f6558dSRoger Tseng .remove = rtsx_usb_sdmmc_drv_remove, 1446c7f6558dSRoger Tseng .id_table = rtsx_usb_sdmmc_ids, 1447c7f6558dSRoger Tseng .driver = { 1448c7f6558dSRoger Tseng .owner = THIS_MODULE, 1449c7f6558dSRoger Tseng .name = "rtsx_usb_sdmmc", 1450c7f6558dSRoger Tseng }, 1451c7f6558dSRoger Tseng }; 1452c7f6558dSRoger Tseng module_platform_driver(rtsx_usb_sdmmc_driver); 1453c7f6558dSRoger Tseng 1454c7f6558dSRoger Tseng MODULE_LICENSE("GPL v2"); 1455c7f6558dSRoger Tseng MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>"); 1456c7f6558dSRoger Tseng MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver"); 1457