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