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)
345ec30f11eSUlf 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 
13004bfdd76dSUlf Hansson 	pm_runtime_get_noresume(sdmmc_dev(host));
1301c7f6558dSRoger Tseng 	mutex_lock(&ucr->dev_mutex);
1302c7f6558dSRoger Tseng 
13034bfdd76dSUlf Hansson 	if (host->power_mode == MMC_POWER_OFF)
13044bfdd76dSUlf Hansson 		goto out;
13054bfdd76dSUlf Hansson 
1306c7f6558dSRoger Tseng 	if (host->led.brightness == LED_OFF)
1307c7f6558dSRoger Tseng 		rtsx_usb_turn_off_led(ucr);
1308c7f6558dSRoger Tseng 	else
1309c7f6558dSRoger Tseng 		rtsx_usb_turn_on_led(ucr);
1310c7f6558dSRoger Tseng 
13114bfdd76dSUlf Hansson out:
1312c7f6558dSRoger Tseng 	mutex_unlock(&ucr->dev_mutex);
13134f48aa7aSUlf Hansson 	pm_runtime_put(sdmmc_dev(host));
1314c7f6558dSRoger Tseng }
1315c7f6558dSRoger Tseng #endif
1316c7f6558dSRoger Tseng 
1317c7f6558dSRoger Tseng static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host)
1318c7f6558dSRoger Tseng {
1319c7f6558dSRoger Tseng 	struct mmc_host *mmc = host->mmc;
1320c7f6558dSRoger Tseng 
1321c7f6558dSRoger Tseng 	mmc->f_min = 250000;
1322c7f6558dSRoger Tseng 	mmc->f_max = 208000000;
1323c7f6558dSRoger Tseng 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
1324c7f6558dSRoger Tseng 	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED |
1325c7f6558dSRoger Tseng 		MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST |
1326c7f6558dSRoger Tseng 		MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
1327400fdb25SUlf Hansson 		MMC_CAP_NEEDS_POLL | MMC_CAP_ERASE;
13284b7d4545SUlf Hansson 	mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE |
13294b7d4545SUlf Hansson 		MMC_CAP2_NO_SDIO;
1330c7f6558dSRoger Tseng 
1331c7f6558dSRoger Tseng 	mmc->max_current_330 = 400;
1332c7f6558dSRoger Tseng 	mmc->max_current_180 = 800;
1333c7f6558dSRoger Tseng 	mmc->ops = &rtsx_usb_sdmmc_ops;
1334c7f6558dSRoger Tseng 	mmc->max_segs = 256;
1335c7f6558dSRoger Tseng 	mmc->max_seg_size = 65536;
1336c7f6558dSRoger Tseng 	mmc->max_blk_size = 512;
1337c7f6558dSRoger Tseng 	mmc->max_blk_count = 65535;
1338c7f6558dSRoger Tseng 	mmc->max_req_size = 524288;
1339c7f6558dSRoger Tseng 
1340c7f6558dSRoger Tseng 	host->power_mode = MMC_POWER_OFF;
1341c7f6558dSRoger Tseng }
1342c7f6558dSRoger Tseng 
1343c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
1344c7f6558dSRoger Tseng {
1345c7f6558dSRoger Tseng 	struct mmc_host *mmc;
1346c7f6558dSRoger Tseng 	struct rtsx_usb_sdmmc *host;
1347c7f6558dSRoger Tseng 	struct rtsx_ucr *ucr;
1348c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS
1349c7f6558dSRoger Tseng 	int err;
1350c7f6558dSRoger Tseng #endif
1351c7f6558dSRoger Tseng 
1352c7f6558dSRoger Tseng 	ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent));
1353c7f6558dSRoger Tseng 	if (!ucr)
1354c7f6558dSRoger Tseng 		return -ENXIO;
1355c7f6558dSRoger Tseng 
1356c7f6558dSRoger Tseng 	dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n");
1357c7f6558dSRoger Tseng 
1358c7f6558dSRoger Tseng 	mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
1359c7f6558dSRoger Tseng 	if (!mmc)
1360c7f6558dSRoger Tseng 		return -ENOMEM;
1361c7f6558dSRoger Tseng 
1362c7f6558dSRoger Tseng 	host = mmc_priv(mmc);
1363c7f6558dSRoger Tseng 	host->ucr = ucr;
1364c7f6558dSRoger Tseng 	host->mmc = mmc;
1365c7f6558dSRoger Tseng 	host->pdev = pdev;
1366c7f6558dSRoger Tseng 	platform_set_drvdata(pdev, host);
1367c7f6558dSRoger Tseng 
1368c7f6558dSRoger Tseng 	mutex_init(&host->host_mutex);
1369c7f6558dSRoger Tseng 	rtsx_usb_init_host(host);
1370089d6aa6SUlf Hansson 	pm_runtime_use_autosuspend(&pdev->dev);
1371089d6aa6SUlf Hansson 	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
1372c7f6558dSRoger Tseng 	pm_runtime_enable(&pdev->dev);
1373c7f6558dSRoger Tseng 
1374c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS
1375c7f6558dSRoger Tseng 	snprintf(host->led_name, sizeof(host->led_name),
1376c7f6558dSRoger Tseng 		"%s::", mmc_hostname(mmc));
1377c7f6558dSRoger Tseng 	host->led.name = host->led_name;
1378c7f6558dSRoger Tseng 	host->led.brightness = LED_OFF;
1379c7f6558dSRoger Tseng 	host->led.default_trigger = mmc_hostname(mmc);
1380c7f6558dSRoger Tseng 	host->led.brightness_set = rtsx_usb_led_control;
1381c7f6558dSRoger Tseng 
1382c7f6558dSRoger Tseng 	err = led_classdev_register(mmc_dev(mmc), &host->led);
1383c7f6558dSRoger Tseng 	if (err)
1384c7f6558dSRoger Tseng 		dev_err(&(pdev->dev),
1385c7f6558dSRoger Tseng 				"Failed to register LED device: %d\n", err);
1386c7f6558dSRoger Tseng 	INIT_WORK(&host->led_work, rtsx_usb_update_led);
1387c7f6558dSRoger Tseng 
1388c7f6558dSRoger Tseng #endif
1389c7f6558dSRoger Tseng 	mmc_add_host(mmc);
1390c7f6558dSRoger Tseng 
1391c7f6558dSRoger Tseng 	return 0;
1392c7f6558dSRoger Tseng }
1393c7f6558dSRoger Tseng 
1394c7f6558dSRoger Tseng static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
1395c7f6558dSRoger Tseng {
1396c7f6558dSRoger Tseng 	struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev);
1397c7f6558dSRoger Tseng 	struct mmc_host *mmc;
1398c7f6558dSRoger Tseng 
1399c7f6558dSRoger Tseng 	if (!host)
1400c7f6558dSRoger Tseng 		return 0;
1401c7f6558dSRoger Tseng 
1402c7f6558dSRoger Tseng 	mmc = host->mmc;
1403c7f6558dSRoger Tseng 	host->host_removal = true;
1404c7f6558dSRoger Tseng 
1405c7f6558dSRoger Tseng 	mutex_lock(&host->host_mutex);
1406c7f6558dSRoger Tseng 	if (host->mrq) {
1407c7f6558dSRoger Tseng 		dev_dbg(&(pdev->dev),
1408c7f6558dSRoger Tseng 			"%s: Controller removed during transfer\n",
1409c7f6558dSRoger Tseng 			mmc_hostname(mmc));
1410c7f6558dSRoger Tseng 		host->mrq->cmd->error = -ENOMEDIUM;
1411c7f6558dSRoger Tseng 		if (host->mrq->stop)
1412c7f6558dSRoger Tseng 			host->mrq->stop->error = -ENOMEDIUM;
1413c7f6558dSRoger Tseng 		mmc_request_done(mmc, host->mrq);
1414c7f6558dSRoger Tseng 	}
1415c7f6558dSRoger Tseng 	mutex_unlock(&host->host_mutex);
1416c7f6558dSRoger Tseng 
1417c7f6558dSRoger Tseng 	mmc_remove_host(mmc);
1418c7f6558dSRoger Tseng 
1419c7f6558dSRoger Tseng #ifdef RTSX_USB_USE_LEDS_CLASS
1420c7f6558dSRoger Tseng 	cancel_work_sync(&host->led_work);
1421c7f6558dSRoger Tseng 	led_classdev_unregister(&host->led);
1422c7f6558dSRoger Tseng #endif
1423c7f6558dSRoger Tseng 
1424c7f6558dSRoger Tseng 	mmc_free_host(mmc);
1425c7f6558dSRoger Tseng 	pm_runtime_disable(&pdev->dev);
1426089d6aa6SUlf Hansson 	pm_runtime_dont_use_autosuspend(&pdev->dev);
1427c7f6558dSRoger Tseng 	platform_set_drvdata(pdev, NULL);
1428c7f6558dSRoger Tseng 
1429c7f6558dSRoger Tseng 	dev_dbg(&(pdev->dev),
1430c7f6558dSRoger Tseng 		": Realtek USB SD/MMC module has been removed\n");
1431c7f6558dSRoger Tseng 
1432c7f6558dSRoger Tseng 	return 0;
1433c7f6558dSRoger Tseng }
1434c7f6558dSRoger Tseng 
1435f2483b0dSKrzysztof Kozlowski static const struct platform_device_id rtsx_usb_sdmmc_ids[] = {
1436c7f6558dSRoger Tseng 	{
1437c7f6558dSRoger Tseng 		.name = "rtsx_usb_sdmmc",
1438c7f6558dSRoger Tseng 	}, {
1439c7f6558dSRoger Tseng 		/* sentinel */
1440c7f6558dSRoger Tseng 	}
1441c7f6558dSRoger Tseng };
1442c7f6558dSRoger Tseng MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids);
1443c7f6558dSRoger Tseng 
1444c7f6558dSRoger Tseng static struct platform_driver rtsx_usb_sdmmc_driver = {
1445c7f6558dSRoger Tseng 	.probe		= rtsx_usb_sdmmc_drv_probe,
1446c7f6558dSRoger Tseng 	.remove		= rtsx_usb_sdmmc_drv_remove,
1447c7f6558dSRoger Tseng 	.id_table       = rtsx_usb_sdmmc_ids,
1448c7f6558dSRoger Tseng 	.driver		= {
1449c7f6558dSRoger Tseng 		.name	= "rtsx_usb_sdmmc",
1450c7f6558dSRoger Tseng 	},
1451c7f6558dSRoger Tseng };
1452c7f6558dSRoger Tseng module_platform_driver(rtsx_usb_sdmmc_driver);
1453c7f6558dSRoger Tseng 
1454c7f6558dSRoger Tseng MODULE_LICENSE("GPL v2");
1455c7f6558dSRoger Tseng MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
1456c7f6558dSRoger Tseng MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver");
1457