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