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