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; 327*f7dd5462SWolfram Sang case MMC_RSP_R1_NO_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) { 4386f67cc6fSRoger Tseng /* 4396f67cc6fSRoger Tseng * The controller offloads the last byte {CRC-7, end bit 1'b1} 4406f67cc6fSRoger Tseng * of response type R2. Assign dummy CRC, 0, and end bit to the 4416f67cc6fSRoger Tseng * byte(ptr[16], goes into the LSB of resp[3] later). 4426f67cc6fSRoger Tseng */ 4436f67cc6fSRoger Tseng ptr[16] = 1; 4446f67cc6fSRoger Tseng 445c7f6558dSRoger Tseng for (i = 0; i < 4; i++) { 446c7f6558dSRoger Tseng cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); 447c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", 448c7f6558dSRoger Tseng i, cmd->resp[i]); 449c7f6558dSRoger Tseng } 450c7f6558dSRoger Tseng } else { 451c7f6558dSRoger Tseng cmd->resp[0] = get_unaligned_be32(ptr + 1); 452c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", 453c7f6558dSRoger Tseng cmd->resp[0]); 454c7f6558dSRoger Tseng } 455c7f6558dSRoger Tseng 456c7f6558dSRoger Tseng out: 457c7f6558dSRoger Tseng cmd->error = err; 458c7f6558dSRoger Tseng } 459c7f6558dSRoger Tseng 460c7f6558dSRoger Tseng static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq) 461c7f6558dSRoger Tseng { 462c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 463c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 464c7f6558dSRoger Tseng int read = (data->flags & MMC_DATA_READ) ? 1 : 0; 465c7f6558dSRoger Tseng u8 cfg2, trans_mode; 466c7f6558dSRoger Tseng int err; 467c7f6558dSRoger Tseng u8 flag; 468c7f6558dSRoger Tseng size_t data_len = data->blksz * data->blocks; 469c7f6558dSRoger Tseng unsigned int pipe; 470c7f6558dSRoger Tseng 471c7f6558dSRoger Tseng if (read) { 472c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: read %zu bytes\n", 473c7f6558dSRoger Tseng __func__, data_len); 474c7f6558dSRoger Tseng cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | 475c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; 476c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_READ_3; 477c7f6558dSRoger Tseng } else { 478c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: write %zu bytes\n", 479c7f6558dSRoger Tseng __func__, data_len); 480c7f6558dSRoger Tseng cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | 481c7f6558dSRoger Tseng SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; 482c7f6558dSRoger Tseng trans_mode = SD_TM_AUTO_WRITE_3; 483c7f6558dSRoger Tseng } 484c7f6558dSRoger Tseng 485c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 486c7f6558dSRoger Tseng 487c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); 488c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); 489c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 490c7f6558dSRoger Tseng 0xFF, (u8)data->blocks); 491c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 492c7f6558dSRoger Tseng 0xFF, (u8)(data->blocks >> 8)); 493c7f6558dSRoger Tseng 494c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, 495c7f6558dSRoger Tseng 0x01, RING_BUFFER); 496c7f6558dSRoger Tseng 497c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3, 498c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 24)); 499c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2, 500c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 16)); 501c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1, 502c7f6558dSRoger Tseng 0xFF, (u8)(data_len >> 8)); 503c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, 504c7f6558dSRoger Tseng 0xFF, (u8)data_len); 505c7f6558dSRoger Tseng if (read) { 506c7f6558dSRoger Tseng flag = MODE_CDIR; 507c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, 508c7f6558dSRoger Tseng 0x03 | DMA_PACK_SIZE_MASK, 509c7f6558dSRoger Tseng DMA_DIR_FROM_CARD | DMA_EN | DMA_512); 510c7f6558dSRoger Tseng } else { 511c7f6558dSRoger Tseng flag = MODE_CDOR; 512c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, 513c7f6558dSRoger Tseng 0x03 | DMA_PACK_SIZE_MASK, 514c7f6558dSRoger Tseng DMA_DIR_TO_CARD | DMA_EN | DMA_512); 515c7f6558dSRoger Tseng } 516c7f6558dSRoger Tseng 517c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); 518c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, 519c7f6558dSRoger Tseng trans_mode | SD_TRANSFER_START); 520c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, 521c7f6558dSRoger Tseng SD_TRANSFER_END, SD_TRANSFER_END); 522c7f6558dSRoger Tseng 523c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, flag, 100); 524c7f6558dSRoger Tseng if (err) 525c7f6558dSRoger Tseng return err; 526c7f6558dSRoger Tseng 527c7f6558dSRoger Tseng if (read) 528c7f6558dSRoger Tseng pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN); 529c7f6558dSRoger Tseng else 530c7f6558dSRoger Tseng pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT); 531c7f6558dSRoger Tseng 532c7f6558dSRoger Tseng err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len, 533c7f6558dSRoger Tseng data->sg_len, NULL, 10000); 534c7f6558dSRoger Tseng if (err) { 535c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n" 536c7f6558dSRoger Tseng , err); 537c7f6558dSRoger Tseng sd_clear_error(host); 538c7f6558dSRoger Tseng return err; 539c7f6558dSRoger Tseng } 540c7f6558dSRoger Tseng 541c7f6558dSRoger Tseng return rtsx_usb_get_rsp(ucr, 1, 2000); 542c7f6558dSRoger Tseng } 543c7f6558dSRoger Tseng 544c7f6558dSRoger Tseng static inline void sd_enable_initial_mode(struct rtsx_usb_sdmmc *host) 545c7f6558dSRoger Tseng { 546c7f6558dSRoger Tseng rtsx_usb_write_register(host->ucr, SD_CFG1, 547c7f6558dSRoger Tseng SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); 548c7f6558dSRoger Tseng } 549c7f6558dSRoger Tseng 550c7f6558dSRoger Tseng static inline void sd_disable_initial_mode(struct rtsx_usb_sdmmc *host) 551c7f6558dSRoger Tseng { 552c7f6558dSRoger Tseng rtsx_usb_write_register(host->ucr, SD_CFG1, 553c7f6558dSRoger Tseng SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); 554c7f6558dSRoger Tseng } 555c7f6558dSRoger Tseng 556c7f6558dSRoger Tseng static void sd_normal_rw(struct rtsx_usb_sdmmc *host, 557c7f6558dSRoger Tseng struct mmc_request *mrq) 558c7f6558dSRoger Tseng { 559c7f6558dSRoger Tseng struct mmc_command *cmd = mrq->cmd; 560c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 561c7f6558dSRoger Tseng u8 *buf; 562c7f6558dSRoger Tseng 563c7f6558dSRoger Tseng buf = kzalloc(data->blksz, GFP_NOIO); 564c7f6558dSRoger Tseng if (!buf) { 565c7f6558dSRoger Tseng cmd->error = -ENOMEM; 566c7f6558dSRoger Tseng return; 567c7f6558dSRoger Tseng } 568c7f6558dSRoger Tseng 569c7f6558dSRoger Tseng if (data->flags & MMC_DATA_READ) { 570c7f6558dSRoger Tseng if (host->initial_mode) 571c7f6558dSRoger Tseng sd_disable_initial_mode(host); 572c7f6558dSRoger Tseng 573c7f6558dSRoger Tseng cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, 574c7f6558dSRoger Tseng data->blksz, 200); 575c7f6558dSRoger Tseng 576c7f6558dSRoger Tseng if (host->initial_mode) 577c7f6558dSRoger Tseng sd_enable_initial_mode(host); 578c7f6558dSRoger Tseng 579c7f6558dSRoger Tseng sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); 580c7f6558dSRoger Tseng } else { 581c7f6558dSRoger Tseng sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); 582c7f6558dSRoger Tseng 583c7f6558dSRoger Tseng cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, 584c7f6558dSRoger Tseng data->blksz, 200); 585c7f6558dSRoger Tseng } 586c7f6558dSRoger Tseng 587c7f6558dSRoger Tseng kfree(buf); 588c7f6558dSRoger Tseng } 589c7f6558dSRoger Tseng 590c7f6558dSRoger Tseng static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) 591c7f6558dSRoger Tseng { 592c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 593c7f6558dSRoger Tseng int err; 594c7f6558dSRoger Tseng 595c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n", 596c7f6558dSRoger Tseng __func__, tx ? "TX" : "RX", sample_point); 597c7f6558dSRoger Tseng 598c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 599c7f6558dSRoger Tseng 600c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); 601c7f6558dSRoger Tseng 602c7f6558dSRoger Tseng if (tx) 603c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, 604c7f6558dSRoger Tseng 0x0F, sample_point); 605c7f6558dSRoger Tseng else 606c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK1_CTL, 607c7f6558dSRoger Tseng 0x0F, sample_point); 608c7f6558dSRoger Tseng 609c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); 610c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, 611c7f6558dSRoger Tseng PHASE_NOT_RESET, PHASE_NOT_RESET); 612c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); 613c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0); 614c7f6558dSRoger Tseng 615c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 616c7f6558dSRoger Tseng if (err) 617c7f6558dSRoger Tseng return err; 618c7f6558dSRoger Tseng 619c7f6558dSRoger Tseng return 0; 620c7f6558dSRoger Tseng } 621c7f6558dSRoger Tseng 622c7f6558dSRoger Tseng static inline u32 get_phase_point(u32 phase_map, unsigned int idx) 623c7f6558dSRoger Tseng { 624c7f6558dSRoger Tseng idx &= MAX_PHASE; 625c7f6558dSRoger Tseng return phase_map & (1 << idx); 626c7f6558dSRoger Tseng } 627c7f6558dSRoger Tseng 628c7f6558dSRoger Tseng static int get_phase_len(u32 phase_map, unsigned int idx) 629c7f6558dSRoger Tseng { 630c7f6558dSRoger Tseng int i; 631c7f6558dSRoger Tseng 632c7f6558dSRoger Tseng for (i = 0; i < MAX_PHASE + 1; i++) { 633c7f6558dSRoger Tseng if (get_phase_point(phase_map, idx + i) == 0) 634c7f6558dSRoger Tseng return i; 635c7f6558dSRoger Tseng } 636c7f6558dSRoger Tseng return MAX_PHASE + 1; 637c7f6558dSRoger Tseng } 638c7f6558dSRoger Tseng 639c7f6558dSRoger Tseng static u8 sd_search_final_phase(struct rtsx_usb_sdmmc *host, u32 phase_map) 640c7f6558dSRoger Tseng { 641c7f6558dSRoger Tseng int start = 0, len = 0; 642c7f6558dSRoger Tseng int start_final = 0, len_final = 0; 643c7f6558dSRoger Tseng u8 final_phase = 0xFF; 644c7f6558dSRoger Tseng 645c7f6558dSRoger Tseng if (phase_map == 0) { 646c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "Phase: [map:%x]\n", phase_map); 647c7f6558dSRoger Tseng return final_phase; 648c7f6558dSRoger Tseng } 649c7f6558dSRoger Tseng 650c7f6558dSRoger Tseng while (start < MAX_PHASE + 1) { 651c7f6558dSRoger Tseng len = get_phase_len(phase_map, start); 652c7f6558dSRoger Tseng if (len_final < len) { 653c7f6558dSRoger Tseng start_final = start; 654c7f6558dSRoger Tseng len_final = len; 655c7f6558dSRoger Tseng } 656c7f6558dSRoger Tseng start += len ? len : 1; 657c7f6558dSRoger Tseng } 658c7f6558dSRoger Tseng 659c7f6558dSRoger Tseng final_phase = (start_final + len_final / 2) & MAX_PHASE; 660c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "Phase: [map:%x] [maxlen:%d] [final:%d]\n", 661c7f6558dSRoger Tseng phase_map, len_final, final_phase); 662c7f6558dSRoger Tseng 663c7f6558dSRoger Tseng return final_phase; 664c7f6558dSRoger Tseng } 665c7f6558dSRoger Tseng 666c7f6558dSRoger Tseng static void sd_wait_data_idle(struct rtsx_usb_sdmmc *host) 667c7f6558dSRoger Tseng { 668c7f6558dSRoger Tseng int err, i; 669c7f6558dSRoger Tseng u8 val = 0; 670c7f6558dSRoger Tseng 671c7f6558dSRoger Tseng for (i = 0; i < 100; i++) { 672c7f6558dSRoger Tseng err = rtsx_usb_ep0_read_register(host->ucr, 673c7f6558dSRoger Tseng SD_DATA_STATE, &val); 674c7f6558dSRoger Tseng if (val & SD_DATA_IDLE) 675c7f6558dSRoger Tseng return; 676c7f6558dSRoger Tseng 677c7f6558dSRoger Tseng usleep_range(100, 1000); 678c7f6558dSRoger Tseng } 679c7f6558dSRoger Tseng } 680c7f6558dSRoger Tseng 681c7f6558dSRoger Tseng static int sd_tuning_rx_cmd(struct rtsx_usb_sdmmc *host, 682c7f6558dSRoger Tseng u8 opcode, u8 sample_point) 683c7f6558dSRoger Tseng { 684c7f6558dSRoger Tseng int err; 685c7f6558dSRoger Tseng struct mmc_command cmd = {0}; 686c7f6558dSRoger Tseng 687c7f6558dSRoger Tseng err = sd_change_phase(host, sample_point, 0); 688c7f6558dSRoger Tseng if (err) 689c7f6558dSRoger Tseng return err; 690c7f6558dSRoger Tseng 691c7f6558dSRoger Tseng cmd.opcode = MMC_SEND_TUNING_BLOCK; 692c7f6558dSRoger Tseng err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); 693c7f6558dSRoger Tseng if (err) { 694c7f6558dSRoger Tseng /* Wait till SD DATA IDLE */ 695c7f6558dSRoger Tseng sd_wait_data_idle(host); 696c7f6558dSRoger Tseng sd_clear_error(host); 697c7f6558dSRoger Tseng return err; 698c7f6558dSRoger Tseng } 699c7f6558dSRoger Tseng 700c7f6558dSRoger Tseng return 0; 701c7f6558dSRoger Tseng } 702c7f6558dSRoger Tseng 703c7f6558dSRoger Tseng static void sd_tuning_phase(struct rtsx_usb_sdmmc *host, 704c7f6558dSRoger Tseng u8 opcode, u16 *phase_map) 705c7f6558dSRoger Tseng { 706c7f6558dSRoger Tseng int err, i; 707c7f6558dSRoger Tseng u16 raw_phase_map = 0; 708c7f6558dSRoger Tseng 709c7f6558dSRoger Tseng for (i = MAX_PHASE; i >= 0; i--) { 710c7f6558dSRoger Tseng err = sd_tuning_rx_cmd(host, opcode, (u8)i); 711c7f6558dSRoger Tseng if (!err) 712c7f6558dSRoger Tseng raw_phase_map |= 1 << i; 713c7f6558dSRoger Tseng } 714c7f6558dSRoger Tseng 715c7f6558dSRoger Tseng if (phase_map) 716c7f6558dSRoger Tseng *phase_map = raw_phase_map; 717c7f6558dSRoger Tseng } 718c7f6558dSRoger Tseng 719c7f6558dSRoger Tseng static int sd_tuning_rx(struct rtsx_usb_sdmmc *host, u8 opcode) 720c7f6558dSRoger Tseng { 721c7f6558dSRoger Tseng int err, i; 722c7f6558dSRoger Tseng u16 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; 723c7f6558dSRoger Tseng u8 final_phase; 724c7f6558dSRoger Tseng 725c7f6558dSRoger Tseng /* setting fixed default TX phase */ 726c7f6558dSRoger Tseng err = sd_change_phase(host, 0x01, 1); 727c7f6558dSRoger Tseng if (err) { 728c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "TX phase setting failed\n"); 729c7f6558dSRoger Tseng return err; 730c7f6558dSRoger Tseng } 731c7f6558dSRoger Tseng 732c7f6558dSRoger Tseng /* tuning RX phase */ 733c7f6558dSRoger Tseng for (i = 0; i < RX_TUNING_CNT; i++) { 734c7f6558dSRoger Tseng sd_tuning_phase(host, opcode, &(raw_phase_map[i])); 735c7f6558dSRoger Tseng 736c7f6558dSRoger Tseng if (raw_phase_map[i] == 0) 737c7f6558dSRoger Tseng break; 738c7f6558dSRoger Tseng } 739c7f6558dSRoger Tseng 740c7f6558dSRoger Tseng phase_map = 0xFFFF; 741c7f6558dSRoger Tseng for (i = 0; i < RX_TUNING_CNT; i++) { 742c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%04x\n", 743c7f6558dSRoger Tseng i, raw_phase_map[i]); 744c7f6558dSRoger Tseng phase_map &= raw_phase_map[i]; 745c7f6558dSRoger Tseng } 746c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%04x\n", phase_map); 747c7f6558dSRoger Tseng 748c7f6558dSRoger Tseng if (phase_map) { 749c7f6558dSRoger Tseng final_phase = sd_search_final_phase(host, phase_map); 750c7f6558dSRoger Tseng if (final_phase == 0xFF) 751c7f6558dSRoger Tseng return -EINVAL; 752c7f6558dSRoger Tseng 753c7f6558dSRoger Tseng err = sd_change_phase(host, final_phase, 0); 754c7f6558dSRoger Tseng if (err) 755c7f6558dSRoger Tseng return err; 756c7f6558dSRoger Tseng } else { 757c7f6558dSRoger Tseng return -EINVAL; 758c7f6558dSRoger Tseng } 759c7f6558dSRoger Tseng 760c7f6558dSRoger Tseng return 0; 761c7f6558dSRoger Tseng } 762c7f6558dSRoger Tseng 763c7f6558dSRoger Tseng static int sdmmc_get_ro(struct mmc_host *mmc) 764c7f6558dSRoger Tseng { 765c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 766c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 767c7f6558dSRoger Tseng int err; 768c7f6558dSRoger Tseng u16 val; 769c7f6558dSRoger Tseng 770c7f6558dSRoger Tseng if (host->host_removal) 771c7f6558dSRoger Tseng return -ENOMEDIUM; 772c7f6558dSRoger Tseng 773c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 774c7f6558dSRoger Tseng 775c7f6558dSRoger Tseng /* Check SD card detect */ 776c7f6558dSRoger Tseng err = rtsx_usb_get_card_status(ucr, &val); 777c7f6558dSRoger Tseng 778c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 779c7f6558dSRoger Tseng 780c7f6558dSRoger Tseng 781c7f6558dSRoger Tseng /* Treat failed detection as non-ro */ 782c7f6558dSRoger Tseng if (err) 783c7f6558dSRoger Tseng return 0; 784c7f6558dSRoger Tseng 785c7f6558dSRoger Tseng if (val & SD_WP) 786c7f6558dSRoger Tseng return 1; 787c7f6558dSRoger Tseng 788c7f6558dSRoger Tseng return 0; 789c7f6558dSRoger Tseng } 790c7f6558dSRoger Tseng 791c7f6558dSRoger Tseng static int sdmmc_get_cd(struct mmc_host *mmc) 792c7f6558dSRoger Tseng { 793c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 794c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 795c7f6558dSRoger Tseng int err; 796c7f6558dSRoger Tseng u16 val; 797c7f6558dSRoger Tseng 798c7f6558dSRoger Tseng if (host->host_removal) 799c7f6558dSRoger Tseng return -ENOMEDIUM; 800c7f6558dSRoger Tseng 801c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 802c7f6558dSRoger Tseng 803c7f6558dSRoger Tseng /* Check SD card detect */ 804c7f6558dSRoger Tseng err = rtsx_usb_get_card_status(ucr, &val); 805c7f6558dSRoger Tseng 806c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 807c7f6558dSRoger Tseng 808c7f6558dSRoger Tseng /* Treat failed detection as non-exist */ 809c7f6558dSRoger Tseng if (err) 810c7f6558dSRoger Tseng goto no_card; 811c7f6558dSRoger Tseng 812c7f6558dSRoger Tseng if (val & SD_CD) { 813c7f6558dSRoger Tseng host->card_exist = true; 814c7f6558dSRoger Tseng return 1; 815c7f6558dSRoger Tseng } 816c7f6558dSRoger Tseng 817c7f6558dSRoger Tseng no_card: 818c7f6558dSRoger Tseng host->card_exist = false; 819c7f6558dSRoger Tseng return 0; 820c7f6558dSRoger Tseng } 821c7f6558dSRoger Tseng 822c7f6558dSRoger Tseng static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 823c7f6558dSRoger Tseng { 824c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 825c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 826c7f6558dSRoger Tseng struct mmc_command *cmd = mrq->cmd; 827c7f6558dSRoger Tseng struct mmc_data *data = mrq->data; 828c7f6558dSRoger Tseng unsigned int data_size = 0; 829c7f6558dSRoger Tseng 830c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 831c7f6558dSRoger Tseng 832c7f6558dSRoger Tseng if (host->host_removal) { 833c7f6558dSRoger Tseng cmd->error = -ENOMEDIUM; 834c7f6558dSRoger Tseng goto finish; 835c7f6558dSRoger Tseng } 836c7f6558dSRoger Tseng 837c7f6558dSRoger Tseng if ((!host->card_exist)) { 838c7f6558dSRoger Tseng cmd->error = -ENOMEDIUM; 839c7f6558dSRoger Tseng goto finish_detect_card; 840c7f6558dSRoger Tseng } 841c7f6558dSRoger Tseng 842c7f6558dSRoger Tseng /* 843c7f6558dSRoger Tseng * Reject SDIO CMDs to speed up card identification 844c7f6558dSRoger Tseng * since unsupported 845c7f6558dSRoger Tseng */ 846c7f6558dSRoger Tseng if (cmd->opcode == SD_IO_SEND_OP_COND || 847c7f6558dSRoger Tseng cmd->opcode == SD_IO_RW_DIRECT || 848c7f6558dSRoger Tseng cmd->opcode == SD_IO_RW_EXTENDED) { 849c7f6558dSRoger Tseng cmd->error = -EINVAL; 850c7f6558dSRoger Tseng goto finish; 851c7f6558dSRoger Tseng } 852c7f6558dSRoger Tseng 853c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 854c7f6558dSRoger Tseng 855c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 856c7f6558dSRoger Tseng host->mrq = mrq; 857c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 858c7f6558dSRoger Tseng 859c7f6558dSRoger Tseng if (mrq->data) 860c7f6558dSRoger Tseng data_size = data->blocks * data->blksz; 861c7f6558dSRoger Tseng 862c7f6558dSRoger Tseng if (!data_size) { 863c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, cmd); 864c7f6558dSRoger Tseng } else if ((!(data_size % 512) && cmd->opcode != MMC_SEND_EXT_CSD) || 865c7f6558dSRoger Tseng mmc_op_multi(cmd->opcode)) { 866c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, cmd); 867c7f6558dSRoger Tseng 868c7f6558dSRoger Tseng if (!cmd->error) { 869c7f6558dSRoger Tseng sd_rw_multi(host, mrq); 870c7f6558dSRoger Tseng 871c7f6558dSRoger Tseng if (mmc_op_multi(cmd->opcode) && mrq->stop) { 872c7f6558dSRoger Tseng sd_send_cmd_get_rsp(host, mrq->stop); 873c7f6558dSRoger Tseng rtsx_usb_write_register(ucr, MC_FIFO_CTL, 874c7f6558dSRoger Tseng FIFO_FLUSH, FIFO_FLUSH); 875c7f6558dSRoger Tseng } 876c7f6558dSRoger Tseng } 877c7f6558dSRoger Tseng } else { 878c7f6558dSRoger Tseng sd_normal_rw(host, mrq); 879c7f6558dSRoger Tseng } 880c7f6558dSRoger Tseng 881c7f6558dSRoger Tseng if (mrq->data) { 882c7f6558dSRoger Tseng if (cmd->error || data->error) 883c7f6558dSRoger Tseng data->bytes_xfered = 0; 884c7f6558dSRoger Tseng else 885c7f6558dSRoger Tseng data->bytes_xfered = data->blocks * data->blksz; 886c7f6558dSRoger Tseng } 887c7f6558dSRoger Tseng 888c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 889c7f6558dSRoger Tseng 890c7f6558dSRoger Tseng finish_detect_card: 891c7f6558dSRoger Tseng if (cmd->error) { 892c7f6558dSRoger Tseng /* 893c7f6558dSRoger Tseng * detect card when fail to update card existence state and 894c7f6558dSRoger Tseng * speed up card removal when retry 895c7f6558dSRoger Tseng */ 896c7f6558dSRoger Tseng sdmmc_get_cd(mmc); 897c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); 898c7f6558dSRoger Tseng } 899c7f6558dSRoger Tseng 900c7f6558dSRoger Tseng finish: 901c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 902c7f6558dSRoger Tseng host->mrq = NULL; 903c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 904c7f6558dSRoger Tseng 905c7f6558dSRoger Tseng mmc_request_done(mmc, mrq); 906c7f6558dSRoger Tseng } 907c7f6558dSRoger Tseng 908c7f6558dSRoger Tseng static int sd_set_bus_width(struct rtsx_usb_sdmmc *host, 909c7f6558dSRoger Tseng unsigned char bus_width) 910c7f6558dSRoger Tseng { 911c7f6558dSRoger Tseng int err = 0; 912c7f6558dSRoger Tseng u8 width[] = { 913c7f6558dSRoger Tseng [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, 914c7f6558dSRoger Tseng [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, 915c7f6558dSRoger Tseng [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, 916c7f6558dSRoger Tseng }; 917c7f6558dSRoger Tseng 918c7f6558dSRoger Tseng if (bus_width <= MMC_BUS_WIDTH_8) 919c7f6558dSRoger Tseng err = rtsx_usb_write_register(host->ucr, SD_CFG1, 920c7f6558dSRoger Tseng 0x03, width[bus_width]); 921c7f6558dSRoger Tseng 922c7f6558dSRoger Tseng return err; 923c7f6558dSRoger Tseng } 924c7f6558dSRoger Tseng 925c7f6558dSRoger Tseng static int sd_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr) 926c7f6558dSRoger Tseng { 927c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 928c7f6558dSRoger Tseng 929c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); 930c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 931c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 932c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 933c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 934c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 935c7f6558dSRoger Tseng 936c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 937c7f6558dSRoger Tseng } 938c7f6558dSRoger Tseng 939c7f6558dSRoger Tseng static int sd_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr) 940c7f6558dSRoger Tseng { 941c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 942c7f6558dSRoger Tseng 943c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); 944c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 945c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 946c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 947c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); 948c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); 949c7f6558dSRoger Tseng 950c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 951c7f6558dSRoger Tseng } 952c7f6558dSRoger Tseng 953c7f6558dSRoger Tseng static int sd_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr) 954c7f6558dSRoger Tseng { 955c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 956c7f6558dSRoger Tseng 957c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); 958c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); 959c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9); 960c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 961c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 962c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 963c7f6558dSRoger Tseng 964c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 965c7f6558dSRoger Tseng } 966c7f6558dSRoger Tseng 967c7f6558dSRoger Tseng static int sd_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr) 968c7f6558dSRoger Tseng { 969c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 970c7f6558dSRoger Tseng 971c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); 972c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A); 973c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5); 974c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A); 975c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65); 976c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A); 977c7f6558dSRoger Tseng 978c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 979c7f6558dSRoger Tseng } 980c7f6558dSRoger Tseng 981c7f6558dSRoger Tseng static int sd_power_on(struct rtsx_usb_sdmmc *host) 982c7f6558dSRoger Tseng { 983c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 984c7f6558dSRoger Tseng int err; 985c7f6558dSRoger Tseng 986c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 987c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 988c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); 989c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE, 990c7f6558dSRoger Tseng CARD_SHARE_MASK, CARD_SHARE_SD); 991c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, 992c7f6558dSRoger Tseng SD_CLK_EN, SD_CLK_EN); 993c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 994c7f6558dSRoger Tseng if (err) 995c7f6558dSRoger Tseng return err; 996c7f6558dSRoger Tseng 997c7f6558dSRoger Tseng if (CHECK_PKG(ucr, LQFP48)) 998c7f6558dSRoger Tseng err = sd_pull_ctl_enable_lqfp48(ucr); 999c7f6558dSRoger Tseng else 1000c7f6558dSRoger Tseng err = sd_pull_ctl_enable_qfn24(ucr); 1001c7f6558dSRoger Tseng if (err) 1002c7f6558dSRoger Tseng return err; 1003c7f6558dSRoger Tseng 1004c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, CARD_PWR_CTL, 1005c7f6558dSRoger Tseng POWER_MASK, PARTIAL_POWER_ON); 1006c7f6558dSRoger Tseng if (err) 1007c7f6558dSRoger Tseng return err; 1008c7f6558dSRoger Tseng 1009c7f6558dSRoger Tseng usleep_range(800, 1000); 1010c7f6558dSRoger Tseng 1011c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1012c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1013c7f6558dSRoger Tseng POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON); 1014c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, 1015c7f6558dSRoger Tseng SD_OUTPUT_EN, SD_OUTPUT_EN); 1016c7f6558dSRoger Tseng 1017c7f6558dSRoger Tseng return rtsx_usb_send_cmd(ucr, MODE_C, 100); 1018c7f6558dSRoger Tseng } 1019c7f6558dSRoger Tseng 1020c7f6558dSRoger Tseng static int sd_power_off(struct rtsx_usb_sdmmc *host) 1021c7f6558dSRoger Tseng { 1022c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1023c7f6558dSRoger Tseng int err; 1024c7f6558dSRoger Tseng 1025c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1026c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1027c7f6558dSRoger Tseng 1028c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); 1029c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); 1030c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1031c7f6558dSRoger Tseng POWER_MASK, POWER_OFF); 1032c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, 1033c7f6558dSRoger Tseng POWER_MASK|LDO3318_PWR_MASK, POWER_OFF|LDO_SUSPEND); 1034c7f6558dSRoger Tseng 1035c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1036c7f6558dSRoger Tseng if (err) 1037c7f6558dSRoger Tseng return err; 1038c7f6558dSRoger Tseng 1039c7f6558dSRoger Tseng if (CHECK_PKG(ucr, LQFP48)) 1040c7f6558dSRoger Tseng return sd_pull_ctl_disable_lqfp48(ucr); 1041c7f6558dSRoger Tseng return sd_pull_ctl_disable_qfn24(ucr); 1042c7f6558dSRoger Tseng } 1043c7f6558dSRoger Tseng 1044c7f6558dSRoger Tseng static int sd_set_power_mode(struct rtsx_usb_sdmmc *host, 1045c7f6558dSRoger Tseng unsigned char power_mode) 1046c7f6558dSRoger Tseng { 1047c7f6558dSRoger Tseng int err; 1048c7f6558dSRoger Tseng 1049c7f6558dSRoger Tseng if (power_mode != MMC_POWER_OFF) 1050c7f6558dSRoger Tseng power_mode = MMC_POWER_ON; 1051c7f6558dSRoger Tseng 1052c7f6558dSRoger Tseng if (power_mode == host->power_mode) 1053c7f6558dSRoger Tseng return 0; 1054c7f6558dSRoger Tseng 1055c7f6558dSRoger Tseng if (power_mode == MMC_POWER_OFF) { 1056c7f6558dSRoger Tseng err = sd_power_off(host); 1057c7f6558dSRoger Tseng pm_runtime_put(sdmmc_dev(host)); 1058c7f6558dSRoger Tseng } else { 1059c7f6558dSRoger Tseng pm_runtime_get_sync(sdmmc_dev(host)); 1060c7f6558dSRoger Tseng err = sd_power_on(host); 1061c7f6558dSRoger Tseng } 1062c7f6558dSRoger Tseng 1063c7f6558dSRoger Tseng if (!err) 1064c7f6558dSRoger Tseng host->power_mode = power_mode; 1065c7f6558dSRoger Tseng 1066c7f6558dSRoger Tseng return err; 1067c7f6558dSRoger Tseng } 1068c7f6558dSRoger Tseng 1069c7f6558dSRoger Tseng static int sd_set_timing(struct rtsx_usb_sdmmc *host, 1070c7f6558dSRoger Tseng unsigned char timing, bool *ddr_mode) 1071c7f6558dSRoger Tseng { 1072c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1073c7f6558dSRoger Tseng int err; 1074c7f6558dSRoger Tseng 1075c7f6558dSRoger Tseng *ddr_mode = false; 1076c7f6558dSRoger Tseng 1077c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1078c7f6558dSRoger Tseng 1079c7f6558dSRoger Tseng switch (timing) { 1080c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR104: 1081c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR50: 1082c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1083c7f6558dSRoger Tseng 0x0C | SD_ASYNC_FIFO_RST, 1084c7f6558dSRoger Tseng SD_30_MODE | SD_ASYNC_FIFO_RST); 1085c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1086c7f6558dSRoger Tseng CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 1087c7f6558dSRoger Tseng break; 1088c7f6558dSRoger Tseng 1089c7f6558dSRoger Tseng case MMC_TIMING_UHS_DDR50: 1090c7f6558dSRoger Tseng *ddr_mode = true; 1091c7f6558dSRoger Tseng 1092c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1093c7f6558dSRoger Tseng 0x0C | SD_ASYNC_FIFO_RST, 1094c7f6558dSRoger Tseng SD_DDR_MODE | SD_ASYNC_FIFO_RST); 1095c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1096c7f6558dSRoger Tseng CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); 1097c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 1098c7f6558dSRoger Tseng DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); 1099c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1100c7f6558dSRoger Tseng DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, 1101c7f6558dSRoger Tseng DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); 1102c7f6558dSRoger Tseng break; 1103c7f6558dSRoger Tseng 1104c7f6558dSRoger Tseng case MMC_TIMING_MMC_HS: 1105c7f6558dSRoger Tseng case MMC_TIMING_SD_HS: 1106c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, 1107c7f6558dSRoger Tseng 0x0C, SD_20_MODE); 1108c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1109c7f6558dSRoger Tseng CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 1110c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 1111c7f6558dSRoger Tseng SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); 1112c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1113c7f6558dSRoger Tseng SD20_RX_SEL_MASK, SD20_RX_14_DELAY); 1114c7f6558dSRoger Tseng break; 1115c7f6558dSRoger Tseng 1116c7f6558dSRoger Tseng default: 1117c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 1118c7f6558dSRoger Tseng SD_CFG1, 0x0C, SD_20_MODE); 1119c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, 1120c7f6558dSRoger Tseng CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); 1121c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, 1122c7f6558dSRoger Tseng SD_PUSH_POINT_CTL, 0xFF, 0); 1123c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 1124c7f6558dSRoger Tseng SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); 1125c7f6558dSRoger Tseng break; 1126c7f6558dSRoger Tseng } 1127c7f6558dSRoger Tseng 1128c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1129c7f6558dSRoger Tseng 1130c7f6558dSRoger Tseng return err; 1131c7f6558dSRoger Tseng } 1132c7f6558dSRoger Tseng 1133c7f6558dSRoger Tseng static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 1134c7f6558dSRoger Tseng { 1135c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1136c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1137c7f6558dSRoger Tseng 1138c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1139c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1140c7f6558dSRoger Tseng 1141c7f6558dSRoger Tseng if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { 1142c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1143c7f6558dSRoger Tseng return; 1144c7f6558dSRoger Tseng } 1145c7f6558dSRoger Tseng 1146c7f6558dSRoger Tseng sd_set_power_mode(host, ios->power_mode); 1147c7f6558dSRoger Tseng sd_set_bus_width(host, ios->bus_width); 1148c7f6558dSRoger Tseng sd_set_timing(host, ios->timing, &host->ddr_mode); 1149c7f6558dSRoger Tseng 1150c7f6558dSRoger Tseng host->vpclk = false; 1151c7f6558dSRoger Tseng host->double_clk = true; 1152c7f6558dSRoger Tseng 1153c7f6558dSRoger Tseng switch (ios->timing) { 1154c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR104: 1155c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR50: 1156c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_2M; 1157c7f6558dSRoger Tseng host->vpclk = true; 1158c7f6558dSRoger Tseng host->double_clk = false; 1159c7f6558dSRoger Tseng break; 1160c7f6558dSRoger Tseng case MMC_TIMING_UHS_DDR50: 1161c7f6558dSRoger Tseng case MMC_TIMING_UHS_SDR25: 1162c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_1M; 1163c7f6558dSRoger Tseng break; 1164c7f6558dSRoger Tseng default: 1165c7f6558dSRoger Tseng host->ssc_depth = SSC_DEPTH_512K; 1166c7f6558dSRoger Tseng break; 1167c7f6558dSRoger Tseng } 1168c7f6558dSRoger Tseng 1169c7f6558dSRoger Tseng host->initial_mode = (ios->clock <= 1000000) ? true : false; 1170c7f6558dSRoger Tseng host->clock = ios->clock; 1171c7f6558dSRoger Tseng 1172c7f6558dSRoger Tseng rtsx_usb_switch_clock(host->ucr, host->clock, host->ssc_depth, 1173c7f6558dSRoger Tseng host->initial_mode, host->double_clk, host->vpclk); 1174c7f6558dSRoger Tseng 1175c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1176c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s end\n", __func__); 1177c7f6558dSRoger Tseng } 1178c7f6558dSRoger Tseng 1179c7f6558dSRoger Tseng static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) 1180c7f6558dSRoger Tseng { 1181c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1182c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1183c7f6558dSRoger Tseng int err = 0; 1184c7f6558dSRoger Tseng 1185c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", 1186c7f6558dSRoger Tseng __func__, ios->signal_voltage); 1187c7f6558dSRoger Tseng 1188c7f6558dSRoger Tseng if (host->host_removal) 1189c7f6558dSRoger Tseng return -ENOMEDIUM; 1190c7f6558dSRoger Tseng 1191c7f6558dSRoger Tseng if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) 1192c7f6558dSRoger Tseng return -EPERM; 1193c7f6558dSRoger Tseng 1194c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1195c7f6558dSRoger Tseng 1196c7f6558dSRoger Tseng err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD); 1197c7f6558dSRoger Tseng if (err) { 1198c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1199c7f6558dSRoger Tseng return err; 1200c7f6558dSRoger Tseng } 1201c7f6558dSRoger Tseng 1202c7f6558dSRoger Tseng /* Let mmc core do the busy checking, simply stop the forced-toggle 1203c7f6558dSRoger Tseng * clock(while issuing CMD11) and switch voltage. 1204c7f6558dSRoger Tseng */ 1205c7f6558dSRoger Tseng rtsx_usb_init_cmd(ucr); 1206c7f6558dSRoger Tseng 1207c7f6558dSRoger Tseng if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 1208c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, 1209c7f6558dSRoger Tseng SD_IO_USING_1V8, SD_IO_USING_3V3); 1210c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 1211c7f6558dSRoger Tseng TUNE_SD18_MASK, TUNE_SD18_3V3); 1212c7f6558dSRoger Tseng } else { 1213c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BUS_STAT, 1214c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 1215c7f6558dSRoger Tseng SD_CLK_FORCE_STOP); 1216c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, 1217c7f6558dSRoger Tseng SD_IO_USING_1V8, SD_IO_USING_1V8); 1218c7f6558dSRoger Tseng rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 1219c7f6558dSRoger Tseng TUNE_SD18_MASK, TUNE_SD18_1V8); 1220c7f6558dSRoger Tseng } 1221c7f6558dSRoger Tseng 1222c7f6558dSRoger Tseng err = rtsx_usb_send_cmd(ucr, MODE_C, 100); 1223c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1224c7f6558dSRoger Tseng 1225c7f6558dSRoger Tseng return err; 1226c7f6558dSRoger Tseng } 1227c7f6558dSRoger Tseng 1228c7f6558dSRoger Tseng static int sdmmc_card_busy(struct mmc_host *mmc) 1229c7f6558dSRoger Tseng { 1230c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1231c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1232c7f6558dSRoger Tseng int err; 1233c7f6558dSRoger Tseng u8 stat; 1234c7f6558dSRoger Tseng u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS 1235c7f6558dSRoger Tseng | SD_DAT0_STATUS; 1236c7f6558dSRoger Tseng 1237c7f6558dSRoger Tseng dev_dbg(sdmmc_dev(host), "%s\n", __func__); 1238c7f6558dSRoger Tseng 1239c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1240c7f6558dSRoger Tseng 1241c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, SD_BUS_STAT, 1242c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 1243c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN); 1244c7f6558dSRoger Tseng if (err) 1245c7f6558dSRoger Tseng goto out; 1246c7f6558dSRoger Tseng 1247c7f6558dSRoger Tseng mdelay(1); 1248c7f6558dSRoger Tseng 1249c7f6558dSRoger Tseng err = rtsx_usb_read_register(ucr, SD_BUS_STAT, &stat); 1250c7f6558dSRoger Tseng if (err) 1251c7f6558dSRoger Tseng goto out; 1252c7f6558dSRoger Tseng 1253c7f6558dSRoger Tseng err = rtsx_usb_write_register(ucr, SD_BUS_STAT, 1254c7f6558dSRoger Tseng SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); 1255c7f6558dSRoger Tseng out: 1256c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1257c7f6558dSRoger Tseng 1258c7f6558dSRoger Tseng if (err) 1259c7f6558dSRoger Tseng return err; 1260c7f6558dSRoger Tseng 1261c7f6558dSRoger Tseng /* check if any pin between dat[0:3] is low */ 1262c7f6558dSRoger Tseng if ((stat & mask) != mask) 1263c7f6558dSRoger Tseng return 1; 1264c7f6558dSRoger Tseng else 1265c7f6558dSRoger Tseng return 0; 1266c7f6558dSRoger Tseng } 1267c7f6558dSRoger Tseng 1268c7f6558dSRoger Tseng static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) 1269c7f6558dSRoger Tseng { 1270c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = mmc_priv(mmc); 1271c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1272c7f6558dSRoger Tseng int err = 0; 1273c7f6558dSRoger Tseng 1274c7f6558dSRoger Tseng if (host->host_removal) 1275c7f6558dSRoger Tseng return -ENOMEDIUM; 1276c7f6558dSRoger Tseng 1277c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1278c7f6558dSRoger Tseng 1279c7f6558dSRoger Tseng if (!host->ddr_mode) 1280c7f6558dSRoger Tseng err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); 1281c7f6558dSRoger Tseng 1282c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1283c7f6558dSRoger Tseng 1284c7f6558dSRoger Tseng return err; 1285c7f6558dSRoger Tseng } 1286c7f6558dSRoger Tseng 1287c7f6558dSRoger Tseng static const struct mmc_host_ops rtsx_usb_sdmmc_ops = { 1288c7f6558dSRoger Tseng .request = sdmmc_request, 1289c7f6558dSRoger Tseng .set_ios = sdmmc_set_ios, 1290c7f6558dSRoger Tseng .get_ro = sdmmc_get_ro, 1291c7f6558dSRoger Tseng .get_cd = sdmmc_get_cd, 1292c7f6558dSRoger Tseng .start_signal_voltage_switch = sdmmc_switch_voltage, 1293c7f6558dSRoger Tseng .card_busy = sdmmc_card_busy, 1294c7f6558dSRoger Tseng .execute_tuning = sdmmc_execute_tuning, 1295c7f6558dSRoger Tseng }; 1296c7f6558dSRoger Tseng 1297c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1298c7f6558dSRoger Tseng static void rtsx_usb_led_control(struct led_classdev *led, 1299c7f6558dSRoger Tseng enum led_brightness brightness) 1300c7f6558dSRoger Tseng { 1301c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = container_of(led, 1302c7f6558dSRoger Tseng struct rtsx_usb_sdmmc, led); 1303c7f6558dSRoger Tseng 1304c7f6558dSRoger Tseng if (host->host_removal) 1305c7f6558dSRoger Tseng return; 1306c7f6558dSRoger Tseng 1307c7f6558dSRoger Tseng host->led.brightness = brightness; 1308c7f6558dSRoger Tseng schedule_work(&host->led_work); 1309c7f6558dSRoger Tseng } 1310c7f6558dSRoger Tseng 1311c7f6558dSRoger Tseng static void rtsx_usb_update_led(struct work_struct *work) 1312c7f6558dSRoger Tseng { 1313c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = 1314c7f6558dSRoger Tseng container_of(work, struct rtsx_usb_sdmmc, led_work); 1315c7f6558dSRoger Tseng struct rtsx_ucr *ucr = host->ucr; 1316c7f6558dSRoger Tseng 1317c7f6558dSRoger Tseng mutex_lock(&ucr->dev_mutex); 1318c7f6558dSRoger Tseng 1319c7f6558dSRoger Tseng if (host->led.brightness == LED_OFF) 1320c7f6558dSRoger Tseng rtsx_usb_turn_off_led(ucr); 1321c7f6558dSRoger Tseng else 1322c7f6558dSRoger Tseng rtsx_usb_turn_on_led(ucr); 1323c7f6558dSRoger Tseng 1324c7f6558dSRoger Tseng mutex_unlock(&ucr->dev_mutex); 1325c7f6558dSRoger Tseng } 1326c7f6558dSRoger Tseng #endif 1327c7f6558dSRoger Tseng 1328c7f6558dSRoger Tseng static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) 1329c7f6558dSRoger Tseng { 1330c7f6558dSRoger Tseng struct mmc_host *mmc = host->mmc; 1331c7f6558dSRoger Tseng 1332c7f6558dSRoger Tseng mmc->f_min = 250000; 1333c7f6558dSRoger Tseng mmc->f_max = 208000000; 1334c7f6558dSRoger Tseng mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 1335c7f6558dSRoger Tseng mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | 1336c7f6558dSRoger Tseng MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | 1337c7f6558dSRoger Tseng MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | 1338c7f6558dSRoger Tseng MMC_CAP_NEEDS_POLL; 1339517bf80fSRoger Tseng mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE; 1340c7f6558dSRoger Tseng 1341c7f6558dSRoger Tseng mmc->max_current_330 = 400; 1342c7f6558dSRoger Tseng mmc->max_current_180 = 800; 1343c7f6558dSRoger Tseng mmc->ops = &rtsx_usb_sdmmc_ops; 1344c7f6558dSRoger Tseng mmc->max_segs = 256; 1345c7f6558dSRoger Tseng mmc->max_seg_size = 65536; 1346c7f6558dSRoger Tseng mmc->max_blk_size = 512; 1347c7f6558dSRoger Tseng mmc->max_blk_count = 65535; 1348c7f6558dSRoger Tseng mmc->max_req_size = 524288; 1349c7f6558dSRoger Tseng 1350c7f6558dSRoger Tseng host->power_mode = MMC_POWER_OFF; 1351c7f6558dSRoger Tseng } 1352c7f6558dSRoger Tseng 1353c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) 1354c7f6558dSRoger Tseng { 1355c7f6558dSRoger Tseng struct mmc_host *mmc; 1356c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host; 1357c7f6558dSRoger Tseng struct rtsx_ucr *ucr; 1358c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1359c7f6558dSRoger Tseng int err; 1360c7f6558dSRoger Tseng #endif 1361c7f6558dSRoger Tseng 1362c7f6558dSRoger Tseng ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); 1363c7f6558dSRoger Tseng if (!ucr) 1364c7f6558dSRoger Tseng return -ENXIO; 1365c7f6558dSRoger Tseng 1366c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n"); 1367c7f6558dSRoger Tseng 1368c7f6558dSRoger Tseng mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); 1369c7f6558dSRoger Tseng if (!mmc) 1370c7f6558dSRoger Tseng return -ENOMEM; 1371c7f6558dSRoger Tseng 1372c7f6558dSRoger Tseng host = mmc_priv(mmc); 1373c7f6558dSRoger Tseng host->ucr = ucr; 1374c7f6558dSRoger Tseng host->mmc = mmc; 1375c7f6558dSRoger Tseng host->pdev = pdev; 1376c7f6558dSRoger Tseng platform_set_drvdata(pdev, host); 1377c7f6558dSRoger Tseng 1378c7f6558dSRoger Tseng mutex_init(&host->host_mutex); 1379c7f6558dSRoger Tseng rtsx_usb_init_host(host); 1380c7f6558dSRoger Tseng pm_runtime_enable(&pdev->dev); 1381c7f6558dSRoger Tseng 1382c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1383c7f6558dSRoger Tseng snprintf(host->led_name, sizeof(host->led_name), 1384c7f6558dSRoger Tseng "%s::", mmc_hostname(mmc)); 1385c7f6558dSRoger Tseng host->led.name = host->led_name; 1386c7f6558dSRoger Tseng host->led.brightness = LED_OFF; 1387c7f6558dSRoger Tseng host->led.default_trigger = mmc_hostname(mmc); 1388c7f6558dSRoger Tseng host->led.brightness_set = rtsx_usb_led_control; 1389c7f6558dSRoger Tseng 1390c7f6558dSRoger Tseng err = led_classdev_register(mmc_dev(mmc), &host->led); 1391c7f6558dSRoger Tseng if (err) 1392c7f6558dSRoger Tseng dev_err(&(pdev->dev), 1393c7f6558dSRoger Tseng "Failed to register LED device: %d\n", err); 1394c7f6558dSRoger Tseng INIT_WORK(&host->led_work, rtsx_usb_update_led); 1395c7f6558dSRoger Tseng 1396c7f6558dSRoger Tseng #endif 1397c7f6558dSRoger Tseng mmc_add_host(mmc); 1398c7f6558dSRoger Tseng 1399c7f6558dSRoger Tseng return 0; 1400c7f6558dSRoger Tseng } 1401c7f6558dSRoger Tseng 1402c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) 1403c7f6558dSRoger Tseng { 1404c7f6558dSRoger Tseng struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); 1405c7f6558dSRoger Tseng struct mmc_host *mmc; 1406c7f6558dSRoger Tseng 1407c7f6558dSRoger Tseng if (!host) 1408c7f6558dSRoger Tseng return 0; 1409c7f6558dSRoger Tseng 1410c7f6558dSRoger Tseng mmc = host->mmc; 1411c7f6558dSRoger Tseng host->host_removal = true; 1412c7f6558dSRoger Tseng 1413c7f6558dSRoger Tseng mutex_lock(&host->host_mutex); 1414c7f6558dSRoger Tseng if (host->mrq) { 1415c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), 1416c7f6558dSRoger Tseng "%s: Controller removed during transfer\n", 1417c7f6558dSRoger Tseng mmc_hostname(mmc)); 1418c7f6558dSRoger Tseng host->mrq->cmd->error = -ENOMEDIUM; 1419c7f6558dSRoger Tseng if (host->mrq->stop) 1420c7f6558dSRoger Tseng host->mrq->stop->error = -ENOMEDIUM; 1421c7f6558dSRoger Tseng mmc_request_done(mmc, host->mrq); 1422c7f6558dSRoger Tseng } 1423c7f6558dSRoger Tseng mutex_unlock(&host->host_mutex); 1424c7f6558dSRoger Tseng 1425c7f6558dSRoger Tseng mmc_remove_host(mmc); 1426c7f6558dSRoger Tseng 1427c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS 1428c7f6558dSRoger Tseng cancel_work_sync(&host->led_work); 1429c7f6558dSRoger Tseng led_classdev_unregister(&host->led); 1430c7f6558dSRoger Tseng #endif 1431c7f6558dSRoger Tseng 1432c7f6558dSRoger Tseng mmc_free_host(mmc); 1433c7f6558dSRoger Tseng pm_runtime_disable(&pdev->dev); 1434c7f6558dSRoger Tseng platform_set_drvdata(pdev, NULL); 1435c7f6558dSRoger Tseng 1436c7f6558dSRoger Tseng dev_dbg(&(pdev->dev), 1437c7f6558dSRoger Tseng ": Realtek USB SD/MMC module has been removed\n"); 1438c7f6558dSRoger Tseng 1439c7f6558dSRoger Tseng return 0; 1440c7f6558dSRoger Tseng } 1441c7f6558dSRoger Tseng 1442f2483b0dSKrzysztof Kozlowski static const struct platform_device_id rtsx_usb_sdmmc_ids[] = { 1443c7f6558dSRoger Tseng { 1444c7f6558dSRoger Tseng .name = "rtsx_usb_sdmmc", 1445c7f6558dSRoger Tseng }, { 1446c7f6558dSRoger Tseng /* sentinel */ 1447c7f6558dSRoger Tseng } 1448c7f6558dSRoger Tseng }; 1449c7f6558dSRoger Tseng MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); 1450c7f6558dSRoger Tseng 1451c7f6558dSRoger Tseng static struct platform_driver rtsx_usb_sdmmc_driver = { 1452c7f6558dSRoger Tseng .probe = rtsx_usb_sdmmc_drv_probe, 1453c7f6558dSRoger Tseng .remove = rtsx_usb_sdmmc_drv_remove, 1454c7f6558dSRoger Tseng .id_table = rtsx_usb_sdmmc_ids, 1455c7f6558dSRoger Tseng .driver = { 1456c7f6558dSRoger Tseng .name = "rtsx_usb_sdmmc", 1457c7f6558dSRoger Tseng }, 1458c7f6558dSRoger Tseng }; 1459c7f6558dSRoger Tseng module_platform_driver(rtsx_usb_sdmmc_driver); 1460c7f6558dSRoger Tseng 1461c7f6558dSRoger Tseng MODULE_LICENSE("GPL v2"); 1462c7f6558dSRoger Tseng MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>"); 1463c7f6558dSRoger Tseng MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver"); 1464