1bb1e6779SKim Bradley // SPDX-License-Identifier: GPL-2.0+
2bb1e6779SKim Bradley /*
3bb1e6779SKim Bradley * Driver for Realtek PCI-Express card reader
4fa590c22SMicky Ching *
5fa590c22SMicky Ching * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
6fa590c22SMicky Ching *
7fa590c22SMicky Ching * Author:
8fa590c22SMicky Ching * Wei WANG (wei_wang@realsil.com.cn)
9fa590c22SMicky Ching * Micky Ching (micky_ching@realsil.com.cn)
10fa590c22SMicky Ching */
11fa590c22SMicky Ching
12fa590c22SMicky Ching #include <linux/blkdev.h>
13fa590c22SMicky Ching #include <linux/kthread.h>
14fa590c22SMicky Ching #include <linux/sched.h>
15fa590c22SMicky Ching #include <linux/workqueue.h>
16fa590c22SMicky Ching #include <linux/kernel.h>
17fa590c22SMicky Ching
18fa590c22SMicky Ching #include "rtsx.h"
19fa590c22SMicky Ching #include "sd.h"
20fa590c22SMicky Ching #include "xd.h"
21fa590c22SMicky Ching #include "ms.h"
22fa590c22SMicky Ching
do_remaining_work(struct rtsx_chip * chip)23fa590c22SMicky Ching void do_remaining_work(struct rtsx_chip *chip)
24fa590c22SMicky Ching {
25117b6038SWayne Porter struct sd_info *sd_card = &chip->sd_card;
26fa590c22SMicky Ching #ifdef XD_DELAY_WRITE
27117b6038SWayne Porter struct xd_info *xd_card = &chip->xd_card;
28fa590c22SMicky Ching #endif
29117b6038SWayne Porter struct ms_info *ms_card = &chip->ms_card;
30fa590c22SMicky Ching
31fa590c22SMicky Ching if (chip->card_ready & SD_CARD) {
32fa590c22SMicky Ching if (sd_card->seq_mode) {
33fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
34fa590c22SMicky Ching sd_card->cleanup_counter++;
35fa590c22SMicky Ching } else {
36fa590c22SMicky Ching sd_card->cleanup_counter = 0;
37fa590c22SMicky Ching }
38fa590c22SMicky Ching }
39fa590c22SMicky Ching
40fa590c22SMicky Ching #ifdef XD_DELAY_WRITE
41fa590c22SMicky Ching if (chip->card_ready & XD_CARD) {
42fa590c22SMicky Ching if (xd_card->delay_write.delay_write_flag) {
43fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
44fa590c22SMicky Ching xd_card->cleanup_counter++;
45fa590c22SMicky Ching } else {
46fa590c22SMicky Ching xd_card->cleanup_counter = 0;
47fa590c22SMicky Ching }
48fa590c22SMicky Ching }
49fa590c22SMicky Ching #endif
50fa590c22SMicky Ching
51fa590c22SMicky Ching if (chip->card_ready & MS_CARD) {
52fa590c22SMicky Ching if (CHK_MSPRO(ms_card)) {
53fa590c22SMicky Ching if (ms_card->seq_mode) {
54fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
55fa590c22SMicky Ching ms_card->cleanup_counter++;
56fa590c22SMicky Ching } else {
57fa590c22SMicky Ching ms_card->cleanup_counter = 0;
58fa590c22SMicky Ching }
59fa590c22SMicky Ching } else {
60fa590c22SMicky Ching #ifdef MS_DELAY_WRITE
61fa590c22SMicky Ching if (ms_card->delay_write.delay_write_flag) {
62fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
63fa590c22SMicky Ching ms_card->cleanup_counter++;
64fa590c22SMicky Ching } else {
65fa590c22SMicky Ching ms_card->cleanup_counter = 0;
66fa590c22SMicky Ching }
67fa590c22SMicky Ching #endif
68fa590c22SMicky Ching }
69fa590c22SMicky Ching }
70fa590c22SMicky Ching
71fa590c22SMicky Ching if (sd_card->cleanup_counter > POLLING_WAIT_CNT)
72fa590c22SMicky Ching sd_cleanup_work(chip);
73fa590c22SMicky Ching
74fa590c22SMicky Ching if (xd_card->cleanup_counter > POLLING_WAIT_CNT)
75fa590c22SMicky Ching xd_cleanup_work(chip);
76fa590c22SMicky Ching
77fa590c22SMicky Ching if (ms_card->cleanup_counter > POLLING_WAIT_CNT)
78fa590c22SMicky Ching ms_cleanup_work(chip);
79fa590c22SMicky Ching }
80fa590c22SMicky Ching
try_to_switch_sdio_ctrl(struct rtsx_chip * chip)81fa590c22SMicky Ching void try_to_switch_sdio_ctrl(struct rtsx_chip *chip)
82fa590c22SMicky Ching {
83fa590c22SMicky Ching u8 reg1 = 0, reg2 = 0;
84fa590c22SMicky Ching
85fa590c22SMicky Ching rtsx_read_register(chip, 0xFF34, ®1);
86fa590c22SMicky Ching rtsx_read_register(chip, 0xFF38, ®2);
87bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n",
88bf6c0d11SFabio Falzoi reg1, reg2);
89fa590c22SMicky Ching if ((reg1 & 0xC0) && (reg2 & 0xC0)) {
90fa590c22SMicky Ching chip->sd_int = 1;
918470e791SGulsah Kose rtsx_write_register(chip, SDIO_CTRL, 0xFF,
928470e791SGulsah Kose SDIO_BUS_CTRL | SDIO_CD_CTRL);
938470e791SGulsah Kose rtsx_write_register(chip, PWR_GATE_CTRL,
948470e791SGulsah Kose LDO3318_PWR_MASK, LDO_ON);
95fa590c22SMicky Ching }
96fa590c22SMicky Ching }
97fa590c22SMicky Ching
98fa590c22SMicky Ching #ifdef SUPPORT_SDIO_ASPM
dynamic_configure_sdio_aspm(struct rtsx_chip * chip)99fa590c22SMicky Ching void dynamic_configure_sdio_aspm(struct rtsx_chip *chip)
100fa590c22SMicky Ching {
101fa590c22SMicky Ching u8 buf[12], reg;
102fa590c22SMicky Ching int i;
103fa590c22SMicky Ching
104fa590c22SMicky Ching for (i = 0; i < 12; i++)
105fa590c22SMicky Ching rtsx_read_register(chip, 0xFF08 + i, &buf[i]);
106fa590c22SMicky Ching rtsx_read_register(chip, 0xFF25, ®);
107fa590c22SMicky Ching if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) {
108fa590c22SMicky Ching chip->sdio_counter = 0;
109fa590c22SMicky Ching chip->sdio_idle = 0;
110fa590c22SMicky Ching } else {
111fa590c22SMicky Ching if (!chip->sdio_idle) {
112fa590c22SMicky Ching chip->sdio_counter++;
113fa590c22SMicky Ching if (chip->sdio_counter >= SDIO_IDLE_COUNT) {
114fa590c22SMicky Ching chip->sdio_counter = 0;
115fa590c22SMicky Ching chip->sdio_idle = 1;
116fa590c22SMicky Ching }
117fa590c22SMicky Ching }
118fa590c22SMicky Ching }
119fa590c22SMicky Ching memcpy(chip->sdio_raw_data, buf, 12);
120fa590c22SMicky Ching
121fa590c22SMicky Ching if (chip->sdio_idle) {
122fa590c22SMicky Ching if (!chip->sdio_aspm) {
123bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
124fa590c22SMicky Ching rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC,
125fa590c22SMicky Ching 0x30 | (chip->aspm_level[1] << 2));
126fa590c22SMicky Ching chip->sdio_aspm = 1;
127fa590c22SMicky Ching }
128fa590c22SMicky Ching } else {
129fa590c22SMicky Ching if (chip->sdio_aspm) {
130bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "SDIO exit ASPM!\n");
131fa590c22SMicky Ching rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30);
132fa590c22SMicky Ching chip->sdio_aspm = 0;
133fa590c22SMicky Ching }
134fa590c22SMicky Ching }
135fa590c22SMicky Ching }
136fa590c22SMicky Ching #endif
137fa590c22SMicky Ching
do_reset_sd_card(struct rtsx_chip * chip)138fa590c22SMicky Ching void do_reset_sd_card(struct rtsx_chip *chip)
139fa590c22SMicky Ching {
140fa590c22SMicky Ching int retval;
141fa590c22SMicky Ching
142bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
143fa590c22SMicky Ching chip->sd_reset_counter, chip->card2lun[SD_CARD]);
144fa590c22SMicky Ching
145fa590c22SMicky Ching if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) {
146117b6038SWayne Porter clear_bit(SD_NR, &chip->need_reset);
147fa590c22SMicky Ching chip->sd_reset_counter = 0;
148fa590c22SMicky Ching chip->sd_show_cnt = 0;
149fa590c22SMicky Ching return;
150fa590c22SMicky Ching }
151fa590c22SMicky Ching
152fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
153fa590c22SMicky Ching
154fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
155fa590c22SMicky Ching rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
156fa590c22SMicky Ching
157fa590c22SMicky Ching retval = reset_sd_card(chip);
158fa590c22SMicky Ching if (chip->need_release & SD_CARD)
159fa590c22SMicky Ching return;
160fa590c22SMicky Ching if (retval == STATUS_SUCCESS) {
161117b6038SWayne Porter clear_bit(SD_NR, &chip->need_reset);
162fa590c22SMicky Ching chip->sd_reset_counter = 0;
163fa590c22SMicky Ching chip->sd_show_cnt = 0;
164fa590c22SMicky Ching chip->card_ready |= SD_CARD;
165fa590c22SMicky Ching chip->card_fail &= ~SD_CARD;
166fa590c22SMicky Ching chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
167fa590c22SMicky Ching } else {
168*a815e131SBenjamin Philip if (chip->sd_io || chip->sd_reset_counter >= MAX_RESET_CNT) {
169117b6038SWayne Porter clear_bit(SD_NR, &chip->need_reset);
170fa590c22SMicky Ching chip->sd_reset_counter = 0;
171fa590c22SMicky Ching chip->sd_show_cnt = 0;
172fa590c22SMicky Ching } else {
173fa590c22SMicky Ching chip->sd_reset_counter++;
174fa590c22SMicky Ching }
175fa590c22SMicky Ching chip->card_ready &= ~SD_CARD;
176fa590c22SMicky Ching chip->card_fail |= SD_CARD;
177fa590c22SMicky Ching chip->capacity[chip->card2lun[SD_CARD]] = 0;
178fa590c22SMicky Ching chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
179fa590c22SMicky Ching
180fa590c22SMicky Ching rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
181fa590c22SMicky Ching if (!chip->ft2_fast_mode)
182fa590c22SMicky Ching card_power_off(chip, SD_CARD);
183fa590c22SMicky Ching if (chip->sd_io) {
184fa590c22SMicky Ching chip->sd_int = 0;
185fa590c22SMicky Ching try_to_switch_sdio_ctrl(chip);
186fa590c22SMicky Ching } else {
187fa590c22SMicky Ching disable_card_clock(chip, SD_CARD);
188fa590c22SMicky Ching }
189fa590c22SMicky Ching }
190fa590c22SMicky Ching }
191fa590c22SMicky Ching
do_reset_xd_card(struct rtsx_chip * chip)192fa590c22SMicky Ching void do_reset_xd_card(struct rtsx_chip *chip)
193fa590c22SMicky Ching {
194fa590c22SMicky Ching int retval;
195fa590c22SMicky Ching
196bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
197fa590c22SMicky Ching chip->xd_reset_counter, chip->card2lun[XD_CARD]);
198fa590c22SMicky Ching
199fa590c22SMicky Ching if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) {
200117b6038SWayne Porter clear_bit(XD_NR, &chip->need_reset);
201fa590c22SMicky Ching chip->xd_reset_counter = 0;
202fa590c22SMicky Ching chip->xd_show_cnt = 0;
203fa590c22SMicky Ching return;
204fa590c22SMicky Ching }
205fa590c22SMicky Ching
206fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
207fa590c22SMicky Ching
208fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
209fa590c22SMicky Ching rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
210fa590c22SMicky Ching
211fa590c22SMicky Ching retval = reset_xd_card(chip);
212fa590c22SMicky Ching if (chip->need_release & XD_CARD)
213fa590c22SMicky Ching return;
214fa590c22SMicky Ching if (retval == STATUS_SUCCESS) {
215117b6038SWayne Porter clear_bit(XD_NR, &chip->need_reset);
216fa590c22SMicky Ching chip->xd_reset_counter = 0;
217fa590c22SMicky Ching chip->card_ready |= XD_CARD;
218fa590c22SMicky Ching chip->card_fail &= ~XD_CARD;
219fa590c22SMicky Ching chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
220fa590c22SMicky Ching } else {
221fa590c22SMicky Ching if (chip->xd_reset_counter >= MAX_RESET_CNT) {
222117b6038SWayne Porter clear_bit(XD_NR, &chip->need_reset);
223fa590c22SMicky Ching chip->xd_reset_counter = 0;
224fa590c22SMicky Ching chip->xd_show_cnt = 0;
225fa590c22SMicky Ching } else {
226fa590c22SMicky Ching chip->xd_reset_counter++;
227fa590c22SMicky Ching }
228fa590c22SMicky Ching chip->card_ready &= ~XD_CARD;
229fa590c22SMicky Ching chip->card_fail |= XD_CARD;
230fa590c22SMicky Ching chip->capacity[chip->card2lun[XD_CARD]] = 0;
231fa590c22SMicky Ching chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
232fa590c22SMicky Ching
233fa590c22SMicky Ching rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
234fa590c22SMicky Ching if (!chip->ft2_fast_mode)
235fa590c22SMicky Ching card_power_off(chip, XD_CARD);
236fa590c22SMicky Ching disable_card_clock(chip, XD_CARD);
237fa590c22SMicky Ching }
238fa590c22SMicky Ching }
239fa590c22SMicky Ching
do_reset_ms_card(struct rtsx_chip * chip)240fa590c22SMicky Ching void do_reset_ms_card(struct rtsx_chip *chip)
241fa590c22SMicky Ching {
242fa590c22SMicky Ching int retval;
243fa590c22SMicky Ching
244bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
245fa590c22SMicky Ching chip->ms_reset_counter, chip->card2lun[MS_CARD]);
246fa590c22SMicky Ching
247fa590c22SMicky Ching if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) {
248117b6038SWayne Porter clear_bit(MS_NR, &chip->need_reset);
249fa590c22SMicky Ching chip->ms_reset_counter = 0;
250fa590c22SMicky Ching chip->ms_show_cnt = 0;
251fa590c22SMicky Ching return;
252fa590c22SMicky Ching }
253fa590c22SMicky Ching
254fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
255fa590c22SMicky Ching
256fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
257fa590c22SMicky Ching rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
258fa590c22SMicky Ching
259fa590c22SMicky Ching retval = reset_ms_card(chip);
260fa590c22SMicky Ching if (chip->need_release & MS_CARD)
261fa590c22SMicky Ching return;
262fa590c22SMicky Ching if (retval == STATUS_SUCCESS) {
263117b6038SWayne Porter clear_bit(MS_NR, &chip->need_reset);
264fa590c22SMicky Ching chip->ms_reset_counter = 0;
265fa590c22SMicky Ching chip->card_ready |= MS_CARD;
266fa590c22SMicky Ching chip->card_fail &= ~MS_CARD;
267fa590c22SMicky Ching chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
268fa590c22SMicky Ching } else {
269fa590c22SMicky Ching if (chip->ms_reset_counter >= MAX_RESET_CNT) {
270117b6038SWayne Porter clear_bit(MS_NR, &chip->need_reset);
271fa590c22SMicky Ching chip->ms_reset_counter = 0;
272fa590c22SMicky Ching chip->ms_show_cnt = 0;
273fa590c22SMicky Ching } else {
274fa590c22SMicky Ching chip->ms_reset_counter++;
275fa590c22SMicky Ching }
276fa590c22SMicky Ching chip->card_ready &= ~MS_CARD;
277fa590c22SMicky Ching chip->card_fail |= MS_CARD;
278fa590c22SMicky Ching chip->capacity[chip->card2lun[MS_CARD]] = 0;
279fa590c22SMicky Ching chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
280fa590c22SMicky Ching
281fa590c22SMicky Ching rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
282fa590c22SMicky Ching if (!chip->ft2_fast_mode)
283fa590c22SMicky Ching card_power_off(chip, MS_CARD);
284fa590c22SMicky Ching disable_card_clock(chip, MS_CARD);
285fa590c22SMicky Ching }
286fa590c22SMicky Ching }
287fa590c22SMicky Ching
release_sdio(struct rtsx_chip * chip)288fa590c22SMicky Ching static void release_sdio(struct rtsx_chip *chip)
289fa590c22SMicky Ching {
290fa590c22SMicky Ching if (chip->sd_io) {
291fa590c22SMicky Ching rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
292fa590c22SMicky Ching SD_STOP | SD_CLR_ERR);
293fa590c22SMicky Ching
294fa590c22SMicky Ching if (chip->chip_insert_with_sdio) {
295fa590c22SMicky Ching chip->chip_insert_with_sdio = 0;
296fa590c22SMicky Ching
297fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288))
298fa590c22SMicky Ching rtsx_write_register(chip, 0xFE5A, 0x08, 0x00);
299fa590c22SMicky Ching else
300fa590c22SMicky Ching rtsx_write_register(chip, 0xFE70, 0x80, 0x00);
301fa590c22SMicky Ching }
302fa590c22SMicky Ching
303fa590c22SMicky Ching rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0);
304fa590c22SMicky Ching chip->sd_io = 0;
305fa590c22SMicky Ching }
306fa590c22SMicky Ching }
307fa590c22SMicky Ching
rtsx_power_off_card(struct rtsx_chip * chip)308fa590c22SMicky Ching void rtsx_power_off_card(struct rtsx_chip *chip)
309fa590c22SMicky Ching {
310fa590c22SMicky Ching if ((chip->card_ready & SD_CARD) || chip->sd_io) {
311fa590c22SMicky Ching sd_cleanup_work(chip);
312fa590c22SMicky Ching sd_power_off_card3v3(chip);
313fa590c22SMicky Ching }
314fa590c22SMicky Ching
315fa590c22SMicky Ching if (chip->card_ready & XD_CARD) {
316fa590c22SMicky Ching xd_cleanup_work(chip);
317fa590c22SMicky Ching xd_power_off_card3v3(chip);
318fa590c22SMicky Ching }
319fa590c22SMicky Ching
320fa590c22SMicky Ching if (chip->card_ready & MS_CARD) {
321fa590c22SMicky Ching ms_cleanup_work(chip);
322fa590c22SMicky Ching ms_power_off_card3v3(chip);
323fa590c22SMicky Ching }
324fa590c22SMicky Ching }
325fa590c22SMicky Ching
rtsx_release_cards(struct rtsx_chip * chip)326fa590c22SMicky Ching void rtsx_release_cards(struct rtsx_chip *chip)
327fa590c22SMicky Ching {
328fa590c22SMicky Ching chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
329fa590c22SMicky Ching
330fa590c22SMicky Ching if ((chip->card_ready & SD_CARD) || chip->sd_io) {
331fa590c22SMicky Ching if (chip->int_reg & SD_EXIST)
332fa590c22SMicky Ching sd_cleanup_work(chip);
333fa590c22SMicky Ching release_sd_card(chip);
334fa590c22SMicky Ching }
335fa590c22SMicky Ching
336fa590c22SMicky Ching if (chip->card_ready & XD_CARD) {
337fa590c22SMicky Ching if (chip->int_reg & XD_EXIST)
338fa590c22SMicky Ching xd_cleanup_work(chip);
339fa590c22SMicky Ching release_xd_card(chip);
340fa590c22SMicky Ching }
341fa590c22SMicky Ching
342fa590c22SMicky Ching if (chip->card_ready & MS_CARD) {
343fa590c22SMicky Ching if (chip->int_reg & MS_EXIST)
344fa590c22SMicky Ching ms_cleanup_work(chip);
345fa590c22SMicky Ching release_ms_card(chip);
346fa590c22SMicky Ching }
347fa590c22SMicky Ching }
348fa590c22SMicky Ching
rtsx_reset_cards(struct rtsx_chip * chip)349fa590c22SMicky Ching void rtsx_reset_cards(struct rtsx_chip *chip)
350fa590c22SMicky Ching {
351fa590c22SMicky Ching if (!chip->need_reset)
352fa590c22SMicky Ching return;
353fa590c22SMicky Ching
354fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
355fa590c22SMicky Ching
356fa590c22SMicky Ching rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
357fa590c22SMicky Ching
358fa590c22SMicky Ching rtsx_disable_aspm(chip);
359fa590c22SMicky Ching
360fa590c22SMicky Ching if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio)
361117b6038SWayne Porter clear_bit(SD_NR, &chip->need_reset);
362fa590c22SMicky Ching
363fa590c22SMicky Ching if (chip->need_reset & XD_CARD) {
364fa590c22SMicky Ching chip->card_exist |= XD_CARD;
365fa590c22SMicky Ching
366fa590c22SMicky Ching if (chip->xd_show_cnt >= MAX_SHOW_CNT)
367fa590c22SMicky Ching do_reset_xd_card(chip);
368fa590c22SMicky Ching else
369fa590c22SMicky Ching chip->xd_show_cnt++;
370fa590c22SMicky Ching }
371fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
372fa590c22SMicky Ching if (chip->card_exist & XD_CARD) {
373117b6038SWayne Porter clear_bit(SD_NR, &chip->need_reset);
374117b6038SWayne Porter clear_bit(MS_NR, &chip->need_reset);
375fa590c22SMicky Ching }
376fa590c22SMicky Ching }
377fa590c22SMicky Ching if (chip->need_reset & SD_CARD) {
378fa590c22SMicky Ching chip->card_exist |= SD_CARD;
379fa590c22SMicky Ching
380fa590c22SMicky Ching if (chip->sd_show_cnt >= MAX_SHOW_CNT) {
381fa590c22SMicky Ching rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
382fa590c22SMicky Ching do_reset_sd_card(chip);
383fa590c22SMicky Ching } else {
384fa590c22SMicky Ching chip->sd_show_cnt++;
385fa590c22SMicky Ching }
386fa590c22SMicky Ching }
387fa590c22SMicky Ching if (chip->need_reset & MS_CARD) {
388fa590c22SMicky Ching chip->card_exist |= MS_CARD;
389fa590c22SMicky Ching
390fa590c22SMicky Ching if (chip->ms_show_cnt >= MAX_SHOW_CNT)
391fa590c22SMicky Ching do_reset_ms_card(chip);
392fa590c22SMicky Ching else
393fa590c22SMicky Ching chip->ms_show_cnt++;
394fa590c22SMicky Ching }
395fa590c22SMicky Ching }
396fa590c22SMicky Ching
rtsx_reinit_cards(struct rtsx_chip * chip,int reset_chip)397fa590c22SMicky Ching void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip)
398fa590c22SMicky Ching {
399fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
400fa590c22SMicky Ching
401fa590c22SMicky Ching rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
402fa590c22SMicky Ching
403fa590c22SMicky Ching if (reset_chip)
404fa590c22SMicky Ching rtsx_reset_chip(chip);
405fa590c22SMicky Ching
406fa590c22SMicky Ching chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
407fa590c22SMicky Ching
408fa590c22SMicky Ching if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) {
409fa590c22SMicky Ching release_sdio(chip);
410fa590c22SMicky Ching release_sd_card(chip);
411fa590c22SMicky Ching
412fa590c22SMicky Ching wait_timeout(100);
413fa590c22SMicky Ching
414fa590c22SMicky Ching chip->card_exist |= SD_CARD;
415fa590c22SMicky Ching do_reset_sd_card(chip);
416fa590c22SMicky Ching }
417fa590c22SMicky Ching
418fa590c22SMicky Ching if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) {
419fa590c22SMicky Ching release_xd_card(chip);
420fa590c22SMicky Ching
421fa590c22SMicky Ching wait_timeout(100);
422fa590c22SMicky Ching
423fa590c22SMicky Ching chip->card_exist |= XD_CARD;
424fa590c22SMicky Ching do_reset_xd_card(chip);
425fa590c22SMicky Ching }
426fa590c22SMicky Ching
427fa590c22SMicky Ching if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) {
428fa590c22SMicky Ching release_ms_card(chip);
429fa590c22SMicky Ching
430fa590c22SMicky Ching wait_timeout(100);
431fa590c22SMicky Ching
432fa590c22SMicky Ching chip->card_exist |= MS_CARD;
433fa590c22SMicky Ching do_reset_ms_card(chip);
434fa590c22SMicky Ching }
435fa590c22SMicky Ching
436fa590c22SMicky Ching chip->need_reinit = 0;
437fa590c22SMicky Ching }
438fa590c22SMicky Ching
439fa590c22SMicky Ching #ifdef DISABLE_CARD_INT
card_cd_debounce(struct rtsx_chip * chip,unsigned long * need_reset,unsigned long * need_release)4408470e791SGulsah Kose void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset,
4418470e791SGulsah Kose unsigned long *need_release)
442fa590c22SMicky Ching {
443fa590c22SMicky Ching u8 release_map = 0, reset_map = 0;
444fa590c22SMicky Ching
445fa590c22SMicky Ching chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
446fa590c22SMicky Ching
447fa590c22SMicky Ching if (chip->card_exist) {
448fa590c22SMicky Ching if (chip->card_exist & XD_CARD) {
449fa590c22SMicky Ching if (!(chip->int_reg & XD_EXIST))
450fa590c22SMicky Ching release_map |= XD_CARD;
451fa590c22SMicky Ching } else if (chip->card_exist & SD_CARD) {
452fa590c22SMicky Ching if (!(chip->int_reg & SD_EXIST))
453fa590c22SMicky Ching release_map |= SD_CARD;
454fa590c22SMicky Ching } else if (chip->card_exist & MS_CARD) {
455fa590c22SMicky Ching if (!(chip->int_reg & MS_EXIST))
456fa590c22SMicky Ching release_map |= MS_CARD;
457fa590c22SMicky Ching }
458fa590c22SMicky Ching } else {
459fa590c22SMicky Ching if (chip->int_reg & XD_EXIST)
460fa590c22SMicky Ching reset_map |= XD_CARD;
461fa590c22SMicky Ching else if (chip->int_reg & SD_EXIST)
462fa590c22SMicky Ching reset_map |= SD_CARD;
463fa590c22SMicky Ching else if (chip->int_reg & MS_EXIST)
464fa590c22SMicky Ching reset_map |= MS_CARD;
465fa590c22SMicky Ching }
466fa590c22SMicky Ching
467fa590c22SMicky Ching if (reset_map) {
468fa590c22SMicky Ching int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0;
469fa590c22SMicky Ching int i;
470fa590c22SMicky Ching
471fa590c22SMicky Ching for (i = 0; i < (DEBOUNCE_CNT); i++) {
472fa590c22SMicky Ching chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
473fa590c22SMicky Ching
474fa590c22SMicky Ching if (chip->int_reg & XD_EXIST)
475fa590c22SMicky Ching xd_cnt++;
476fa590c22SMicky Ching else
477fa590c22SMicky Ching xd_cnt = 0;
478fa590c22SMicky Ching
479fa590c22SMicky Ching if (chip->int_reg & SD_EXIST)
480fa590c22SMicky Ching sd_cnt++;
481fa590c22SMicky Ching else
482fa590c22SMicky Ching sd_cnt = 0;
483fa590c22SMicky Ching
484fa590c22SMicky Ching if (chip->int_reg & MS_EXIST)
485fa590c22SMicky Ching ms_cnt++;
486fa590c22SMicky Ching else
487fa590c22SMicky Ching ms_cnt = 0;
488fa590c22SMicky Ching
489fa590c22SMicky Ching wait_timeout(30);
490fa590c22SMicky Ching }
491fa590c22SMicky Ching
492fa590c22SMicky Ching reset_map = 0;
4938470e791SGulsah Kose if (!(chip->card_exist & XD_CARD) &&
4948470e791SGulsah Kose (xd_cnt > (DEBOUNCE_CNT - 1)))
495fa590c22SMicky Ching reset_map |= XD_CARD;
4968470e791SGulsah Kose if (!(chip->card_exist & SD_CARD) &&
4978470e791SGulsah Kose (sd_cnt > (DEBOUNCE_CNT - 1)))
498fa590c22SMicky Ching reset_map |= SD_CARD;
4998470e791SGulsah Kose if (!(chip->card_exist & MS_CARD) &&
5008470e791SGulsah Kose (ms_cnt > (DEBOUNCE_CNT - 1)))
501fa590c22SMicky Ching reset_map |= MS_CARD;
502fa590c22SMicky Ching }
503fa590c22SMicky Ching
504fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
505fa590c22SMicky Ching rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00);
506fa590c22SMicky Ching
507fa590c22SMicky Ching if (need_reset)
508fa590c22SMicky Ching *need_reset = reset_map;
509fa590c22SMicky Ching if (need_release)
510fa590c22SMicky Ching *need_release = release_map;
511fa590c22SMicky Ching }
512fa590c22SMicky Ching #endif
513fa590c22SMicky Ching
rtsx_init_cards(struct rtsx_chip * chip)514fa590c22SMicky Ching void rtsx_init_cards(struct rtsx_chip *chip)
515fa590c22SMicky Ching {
516fa590c22SMicky Ching if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
517bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Reset chip in polling thread!\n");
518fa590c22SMicky Ching rtsx_reset_chip(chip);
519fa590c22SMicky Ching RTSX_CLR_DELINK(chip);
520fa590c22SMicky Ching }
521fa590c22SMicky Ching
522fa590c22SMicky Ching #ifdef DISABLE_CARD_INT
523117b6038SWayne Porter card_cd_debounce(chip, &chip->need_reset, &chip->need_release);
524fa590c22SMicky Ching #endif
525fa590c22SMicky Ching
526fa590c22SMicky Ching if (chip->need_release) {
527fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
528fa590c22SMicky Ching if (chip->int_reg & XD_EXIST) {
529117b6038SWayne Porter clear_bit(SD_NR, &chip->need_release);
530117b6038SWayne Porter clear_bit(MS_NR, &chip->need_release);
531fa590c22SMicky Ching }
532fa590c22SMicky Ching }
533fa590c22SMicky Ching
534fa590c22SMicky Ching if (!(chip->card_exist & SD_CARD) && !chip->sd_io)
535117b6038SWayne Porter clear_bit(SD_NR, &chip->need_release);
536fa590c22SMicky Ching if (!(chip->card_exist & XD_CARD))
537117b6038SWayne Porter clear_bit(XD_NR, &chip->need_release);
538fa590c22SMicky Ching if (!(chip->card_exist & MS_CARD))
539117b6038SWayne Porter clear_bit(MS_NR, &chip->need_release);
540fa590c22SMicky Ching
541bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "chip->need_release = 0x%x\n",
5428470e791SGulsah Kose (unsigned int)(chip->need_release));
543fa590c22SMicky Ching
544fa590c22SMicky Ching #ifdef SUPPORT_OCP
545fa590c22SMicky Ching if (chip->need_release) {
546fa590c22SMicky Ching if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER))
547fa590c22SMicky Ching rtsx_write_register(chip, OCPCLR,
548e379c79bSWayne Porter CARD_OC_INT_CLR |
549e379c79bSWayne Porter CARD_OC_CLR,
550e379c79bSWayne Porter CARD_OC_INT_CLR |
551e379c79bSWayne Porter CARD_OC_CLR);
552fa590c22SMicky Ching chip->ocp_stat = 0;
553fa590c22SMicky Ching }
554fa590c22SMicky Ching #endif
555fa590c22SMicky Ching if (chip->need_release) {
556fa590c22SMicky Ching rtsx_set_stat(chip, RTSX_STAT_RUN);
557fa590c22SMicky Ching rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
558fa590c22SMicky Ching }
559fa590c22SMicky Ching
560fa590c22SMicky Ching if (chip->need_release & SD_CARD) {
561117b6038SWayne Porter clear_bit(SD_NR, &chip->need_release);
562fa590c22SMicky Ching chip->card_exist &= ~SD_CARD;
563fa590c22SMicky Ching chip->card_ejected &= ~SD_CARD;
564fa590c22SMicky Ching chip->card_fail &= ~SD_CARD;
565fa590c22SMicky Ching CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]);
566fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
567fa590c22SMicky Ching rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
568fa590c22SMicky Ching
569fa590c22SMicky Ching release_sdio(chip);
570fa590c22SMicky Ching release_sd_card(chip);
571fa590c22SMicky Ching }
572fa590c22SMicky Ching
573fa590c22SMicky Ching if (chip->need_release & XD_CARD) {
574117b6038SWayne Porter clear_bit(XD_NR, &chip->need_release);
575fa590c22SMicky Ching chip->card_exist &= ~XD_CARD;
576fa590c22SMicky Ching chip->card_ejected &= ~XD_CARD;
577fa590c22SMicky Ching chip->card_fail &= ~XD_CARD;
578fa590c22SMicky Ching CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]);
579fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
580fa590c22SMicky Ching
581fa590c22SMicky Ching release_xd_card(chip);
582fa590c22SMicky Ching
5838470e791SGulsah Kose if (CHECK_PID(chip, 0x5288) &&
5848470e791SGulsah Kose CHECK_BARO_PKG(chip, QFN))
5858470e791SGulsah Kose rtsx_write_register(chip, HOST_SLEEP_STATE,
5868470e791SGulsah Kose 0xC0, 0xC0);
587fa590c22SMicky Ching }
588fa590c22SMicky Ching
589fa590c22SMicky Ching if (chip->need_release & MS_CARD) {
590117b6038SWayne Porter clear_bit(MS_NR, &chip->need_release);
591fa590c22SMicky Ching chip->card_exist &= ~MS_CARD;
592fa590c22SMicky Ching chip->card_ejected &= ~MS_CARD;
593fa590c22SMicky Ching chip->card_fail &= ~MS_CARD;
594fa590c22SMicky Ching CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]);
595fa590c22SMicky Ching chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
596fa590c22SMicky Ching
597fa590c22SMicky Ching release_ms_card(chip);
598fa590c22SMicky Ching }
599fa590c22SMicky Ching
600bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "chip->card_exist = 0x%x\n",
601bf6c0d11SFabio Falzoi chip->card_exist);
602fa590c22SMicky Ching
603fa590c22SMicky Ching if (!chip->card_exist)
604fa590c22SMicky Ching turn_off_led(chip, LED_GPIO);
605fa590c22SMicky Ching }
606fa590c22SMicky Ching
607fa590c22SMicky Ching if (chip->need_reset) {
608bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x\n",
6098470e791SGulsah Kose (unsigned int)(chip->need_reset));
610fa590c22SMicky Ching
611fa590c22SMicky Ching rtsx_reset_cards(chip);
612fa590c22SMicky Ching }
613fa590c22SMicky Ching
614fa590c22SMicky Ching if (chip->need_reinit) {
615bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "chip->need_reinit = 0x%x\n",
6168470e791SGulsah Kose (unsigned int)(chip->need_reinit));
617fa590c22SMicky Ching
618fa590c22SMicky Ching rtsx_reinit_cards(chip, 0);
619fa590c22SMicky Ching }
620fa590c22SMicky Ching }
621fa590c22SMicky Ching
switch_ssc_clock(struct rtsx_chip * chip,int clk)622fa590c22SMicky Ching int switch_ssc_clock(struct rtsx_chip *chip, int clk)
623fa590c22SMicky Ching {
624fa590c22SMicky Ching int retval;
625132aba09SSergio Paracuellos u8 n = (u8)(clk - 2), min_n, max_n;
626fa590c22SMicky Ching u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask;
627fa590c22SMicky Ching int sd_vpclk_phase_reset = 0;
628fa590c22SMicky Ching
629fa590c22SMicky Ching if (chip->cur_clk == clk)
630fa590c22SMicky Ching return STATUS_SUCCESS;
631fa590c22SMicky Ching
632132aba09SSergio Paracuellos min_n = 60;
633132aba09SSergio Paracuellos max_n = 120;
634fa590c22SMicky Ching max_div = CLK_DIV_4;
635fa590c22SMicky Ching
636bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n",
6378470e791SGulsah Kose clk, chip->cur_clk);
638fa590c22SMicky Ching
639*a815e131SBenjamin Philip if (clk <= 2 || n > max_n)
640031366eaSJoe Perches return STATUS_FAIL;
641fa590c22SMicky Ching
642fa590c22SMicky Ching mcu_cnt = (u8)(125 / clk + 3);
643fa590c22SMicky Ching if (mcu_cnt > 7)
644fa590c22SMicky Ching mcu_cnt = 7;
645fa590c22SMicky Ching
646fa590c22SMicky Ching div = CLK_DIV_1;
647132aba09SSergio Paracuellos while ((n < min_n) && (div < max_div)) {
648132aba09SSergio Paracuellos n = (n + 2) * 2 - 2;
649fa590c22SMicky Ching div++;
650fa590c22SMicky Ching }
651132aba09SSergio Paracuellos dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div);
652fa590c22SMicky Ching
653fa590c22SMicky Ching if (chip->ssc_en) {
654fa590c22SMicky Ching ssc_depth = 0x01;
655132aba09SSergio Paracuellos n -= 2;
656fa590c22SMicky Ching } else {
657fa590c22SMicky Ching ssc_depth = 0;
658fa590c22SMicky Ching }
659fa590c22SMicky Ching
660fa590c22SMicky Ching ssc_depth_mask = 0x03;
661fa590c22SMicky Ching
662bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "ssc_depth = %d\n", ssc_depth);
663fa590c22SMicky Ching
664fa590c22SMicky Ching rtsx_init_cmd(chip);
665fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
666fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
667fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
668fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth);
669132aba09SSergio Paracuellos rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
670fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
671fa590c22SMicky Ching if (sd_vpclk_phase_reset) {
6728470e791SGulsah Kose rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
6738470e791SGulsah Kose PHASE_NOT_RESET, 0);
6748470e791SGulsah Kose rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
6758470e791SGulsah Kose PHASE_NOT_RESET, PHASE_NOT_RESET);
676fa590c22SMicky Ching }
677fa590c22SMicky Ching
678fa590c22SMicky Ching retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
6799f902b49SAymen Qader if (retval < 0)
680031366eaSJoe Perches return STATUS_ERROR;
681fa590c22SMicky Ching
682fa590c22SMicky Ching udelay(10);
6838ee775f9SJoe Perches retval = rtsx_write_register(chip, CLK_CTL, CLK_LOW_FREQ, 0);
6849f902b49SAymen Qader if (retval)
6858ee775f9SJoe Perches return retval;
686fa590c22SMicky Ching
687fa590c22SMicky Ching chip->cur_clk = clk;
688fa590c22SMicky Ching
689fa590c22SMicky Ching return STATUS_SUCCESS;
690fa590c22SMicky Ching }
691fa590c22SMicky Ching
switch_normal_clock(struct rtsx_chip * chip,int clk)692fa590c22SMicky Ching int switch_normal_clock(struct rtsx_chip *chip, int clk)
693fa590c22SMicky Ching {
6948ee775f9SJoe Perches int retval;
695fa590c22SMicky Ching u8 sel, div, mcu_cnt;
696fa590c22SMicky Ching int sd_vpclk_phase_reset = 0;
697fa590c22SMicky Ching
698fa590c22SMicky Ching if (chip->cur_clk == clk)
699fa590c22SMicky Ching return STATUS_SUCCESS;
700fa590c22SMicky Ching
701fa590c22SMicky Ching switch (clk) {
702fa590c22SMicky Ching case CLK_20:
703bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 20MHz\n");
704fa590c22SMicky Ching sel = SSC_80;
705fa590c22SMicky Ching div = CLK_DIV_4;
706fa590c22SMicky Ching mcu_cnt = 7;
707fa590c22SMicky Ching break;
708fa590c22SMicky Ching
709fa590c22SMicky Ching case CLK_30:
710bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 30MHz\n");
711fa590c22SMicky Ching sel = SSC_120;
712fa590c22SMicky Ching div = CLK_DIV_4;
713fa590c22SMicky Ching mcu_cnt = 7;
714fa590c22SMicky Ching break;
715fa590c22SMicky Ching
716fa590c22SMicky Ching case CLK_40:
717bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 40MHz\n");
718fa590c22SMicky Ching sel = SSC_80;
719fa590c22SMicky Ching div = CLK_DIV_2;
720fa590c22SMicky Ching mcu_cnt = 7;
721fa590c22SMicky Ching break;
722fa590c22SMicky Ching
723fa590c22SMicky Ching case CLK_50:
724bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 50MHz\n");
725fa590c22SMicky Ching sel = SSC_100;
726fa590c22SMicky Ching div = CLK_DIV_2;
727fa590c22SMicky Ching mcu_cnt = 6;
728fa590c22SMicky Ching break;
729fa590c22SMicky Ching
730fa590c22SMicky Ching case CLK_60:
731bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 60MHz\n");
732fa590c22SMicky Ching sel = SSC_120;
733fa590c22SMicky Ching div = CLK_DIV_2;
734fa590c22SMicky Ching mcu_cnt = 6;
735fa590c22SMicky Ching break;
736fa590c22SMicky Ching
737fa590c22SMicky Ching case CLK_80:
738bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 80MHz\n");
739fa590c22SMicky Ching sel = SSC_80;
740fa590c22SMicky Ching div = CLK_DIV_1;
741fa590c22SMicky Ching mcu_cnt = 5;
742fa590c22SMicky Ching break;
743fa590c22SMicky Ching
744fa590c22SMicky Ching case CLK_100:
745bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 100MHz\n");
746fa590c22SMicky Ching sel = SSC_100;
747fa590c22SMicky Ching div = CLK_DIV_1;
748fa590c22SMicky Ching mcu_cnt = 5;
749fa590c22SMicky Ching break;
750fa590c22SMicky Ching
751fa590c22SMicky Ching case CLK_120:
752bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 120MHz\n");
753fa590c22SMicky Ching sel = SSC_120;
754fa590c22SMicky Ching div = CLK_DIV_1;
755fa590c22SMicky Ching mcu_cnt = 5;
756fa590c22SMicky Ching break;
757fa590c22SMicky Ching
758fa590c22SMicky Ching case CLK_150:
759bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 150MHz\n");
760fa590c22SMicky Ching sel = SSC_150;
761fa590c22SMicky Ching div = CLK_DIV_1;
762fa590c22SMicky Ching mcu_cnt = 4;
763fa590c22SMicky Ching break;
764fa590c22SMicky Ching
765fa590c22SMicky Ching case CLK_200:
766bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Switch clock to 200MHz\n");
767fa590c22SMicky Ching sel = SSC_200;
768fa590c22SMicky Ching div = CLK_DIV_1;
769fa590c22SMicky Ching mcu_cnt = 4;
770fa590c22SMicky Ching break;
771fa590c22SMicky Ching
772fa590c22SMicky Ching default:
773bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Try to switch to an illegal clock (%d)\n",
774bf6c0d11SFabio Falzoi clk);
775031366eaSJoe Perches return STATUS_FAIL;
776fa590c22SMicky Ching }
777fa590c22SMicky Ching
7788ee775f9SJoe Perches retval = rtsx_write_register(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
7799f902b49SAymen Qader if (retval)
7808ee775f9SJoe Perches return retval;
7818ee775f9SJoe Perches if (sd_vpclk_phase_reset) {
7828ee775f9SJoe Perches retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
7838ee775f9SJoe Perches PHASE_NOT_RESET, 0);
7849f902b49SAymen Qader if (retval)
7858ee775f9SJoe Perches return retval;
7868ee775f9SJoe Perches retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
7878ee775f9SJoe Perches PHASE_NOT_RESET, 0);
7889f902b49SAymen Qader if (retval)
7898ee775f9SJoe Perches return retval;
7908ee775f9SJoe Perches }
7918ee775f9SJoe Perches retval = rtsx_write_register(chip, CLK_DIV, 0xFF,
7928ee775f9SJoe Perches (div << 4) | mcu_cnt);
7939f902b49SAymen Qader if (retval)
7948ee775f9SJoe Perches return retval;
7958ee775f9SJoe Perches retval = rtsx_write_register(chip, CLK_SEL, 0xFF, sel);
7969f902b49SAymen Qader if (retval)
7978ee775f9SJoe Perches return retval;
798fa590c22SMicky Ching
799fa590c22SMicky Ching if (sd_vpclk_phase_reset) {
800fa590c22SMicky Ching udelay(200);
8018ee775f9SJoe Perches retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
8028ee775f9SJoe Perches PHASE_NOT_RESET, PHASE_NOT_RESET);
8039f902b49SAymen Qader if (retval)
8048ee775f9SJoe Perches return retval;
8058ee775f9SJoe Perches retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
8068ee775f9SJoe Perches PHASE_NOT_RESET, PHASE_NOT_RESET);
8079f902b49SAymen Qader if (retval)
8088ee775f9SJoe Perches return retval;
809fa590c22SMicky Ching udelay(200);
810fa590c22SMicky Ching }
8118ee775f9SJoe Perches retval = rtsx_write_register(chip, CLK_CTL, 0xFF, 0);
8129f902b49SAymen Qader if (retval)
8138ee775f9SJoe Perches return retval;
814fa590c22SMicky Ching
815fa590c22SMicky Ching chip->cur_clk = clk;
816fa590c22SMicky Ching
817fa590c22SMicky Ching return STATUS_SUCCESS;
818fa590c22SMicky Ching }
819fa590c22SMicky Ching
trans_dma_enable(enum dma_data_direction dir,struct rtsx_chip * chip,u32 byte_cnt,u8 pack_size)8208470e791SGulsah Kose void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip,
8218470e791SGulsah Kose u32 byte_cnt, u8 pack_size)
822fa590c22SMicky Ching {
823fa590c22SMicky Ching if (pack_size > DMA_1024)
824fa590c22SMicky Ching pack_size = DMA_512;
825fa590c22SMicky Ching
826fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT);
827fa590c22SMicky Ching
828fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24));
829fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16));
830fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8));
831fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt);
832fa590c22SMicky Ching
833fa590c22SMicky Ching if (dir == DMA_FROM_DEVICE) {
8348470e791SGulsah Kose rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
8358470e791SGulsah Kose 0x03 | DMA_PACK_SIZE_MASK,
836fa590c22SMicky Ching DMA_DIR_FROM_CARD | DMA_EN | pack_size);
837fa590c22SMicky Ching } else {
8388470e791SGulsah Kose rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
8398470e791SGulsah Kose 0x03 | DMA_PACK_SIZE_MASK,
840fa590c22SMicky Ching DMA_DIR_TO_CARD | DMA_EN | pack_size);
841fa590c22SMicky Ching }
842fa590c22SMicky Ching
843fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
844fa590c22SMicky Ching }
845fa590c22SMicky Ching
enable_card_clock(struct rtsx_chip * chip,u8 card)846fa590c22SMicky Ching int enable_card_clock(struct rtsx_chip *chip, u8 card)
847fa590c22SMicky Ching {
8488ee775f9SJoe Perches int retval;
849fa590c22SMicky Ching u8 clk_en = 0;
850fa590c22SMicky Ching
851fa590c22SMicky Ching if (card & XD_CARD)
852fa590c22SMicky Ching clk_en |= XD_CLK_EN;
853fa590c22SMicky Ching if (card & SD_CARD)
854fa590c22SMicky Ching clk_en |= SD_CLK_EN;
855fa590c22SMicky Ching if (card & MS_CARD)
856fa590c22SMicky Ching clk_en |= MS_CLK_EN;
857fa590c22SMicky Ching
8588ee775f9SJoe Perches retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, clk_en);
8599f902b49SAymen Qader if (retval)
8608ee775f9SJoe Perches return retval;
861fa590c22SMicky Ching
862fa590c22SMicky Ching return STATUS_SUCCESS;
863fa590c22SMicky Ching }
864fa590c22SMicky Ching
disable_card_clock(struct rtsx_chip * chip,u8 card)865fa590c22SMicky Ching int disable_card_clock(struct rtsx_chip *chip, u8 card)
866fa590c22SMicky Ching {
8678ee775f9SJoe Perches int retval;
868fa590c22SMicky Ching u8 clk_en = 0;
869fa590c22SMicky Ching
870fa590c22SMicky Ching if (card & XD_CARD)
871fa590c22SMicky Ching clk_en |= XD_CLK_EN;
872fa590c22SMicky Ching if (card & SD_CARD)
873fa590c22SMicky Ching clk_en |= SD_CLK_EN;
874fa590c22SMicky Ching if (card & MS_CARD)
875fa590c22SMicky Ching clk_en |= MS_CLK_EN;
876fa590c22SMicky Ching
8778ee775f9SJoe Perches retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, 0);
8789f902b49SAymen Qader if (retval)
8798ee775f9SJoe Perches return retval;
880fa590c22SMicky Ching
881fa590c22SMicky Ching return STATUS_SUCCESS;
882fa590c22SMicky Ching }
883fa590c22SMicky Ching
card_power_on(struct rtsx_chip * chip,u8 card)884fa590c22SMicky Ching int card_power_on(struct rtsx_chip *chip, u8 card)
885fa590c22SMicky Ching {
886fa590c22SMicky Ching int retval;
887fa590c22SMicky Ching u8 mask, val1, val2;
888fa590c22SMicky Ching
889*a815e131SBenjamin Philip if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
890fa590c22SMicky Ching mask = MS_POWER_MASK;
891fa590c22SMicky Ching val1 = MS_PARTIAL_POWER_ON;
892fa590c22SMicky Ching val2 = MS_POWER_ON;
893fa590c22SMicky Ching } else {
894fa590c22SMicky Ching mask = SD_POWER_MASK;
895fa590c22SMicky Ching val1 = SD_PARTIAL_POWER_ON;
896fa590c22SMicky Ching val2 = SD_POWER_ON;
897fa590c22SMicky Ching }
898fa590c22SMicky Ching
899fa590c22SMicky Ching rtsx_init_cmd(chip);
900fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
901fa590c22SMicky Ching
902fa590c22SMicky Ching retval = rtsx_send_cmd(chip, 0, 100);
9039f902b49SAymen Qader if (retval != STATUS_SUCCESS)
904031366eaSJoe Perches return STATUS_FAIL;
905fa590c22SMicky Ching
906fa590c22SMicky Ching udelay(chip->pmos_pwr_on_interval);
907fa590c22SMicky Ching
908fa590c22SMicky Ching rtsx_init_cmd(chip);
909fa590c22SMicky Ching rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
910fa590c22SMicky Ching
911fa590c22SMicky Ching retval = rtsx_send_cmd(chip, 0, 100);
9129f902b49SAymen Qader if (retval != STATUS_SUCCESS)
913031366eaSJoe Perches return STATUS_FAIL;
914fa590c22SMicky Ching
915fa590c22SMicky Ching return STATUS_SUCCESS;
916fa590c22SMicky Ching }
917fa590c22SMicky Ching
card_power_off(struct rtsx_chip * chip,u8 card)918fa590c22SMicky Ching int card_power_off(struct rtsx_chip *chip, u8 card)
919fa590c22SMicky Ching {
9208ee775f9SJoe Perches int retval;
921fa590c22SMicky Ching u8 mask, val;
922fa590c22SMicky Ching
923*a815e131SBenjamin Philip if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
924fa590c22SMicky Ching mask = MS_POWER_MASK;
925fa590c22SMicky Ching val = MS_POWER_OFF;
926fa590c22SMicky Ching } else {
927fa590c22SMicky Ching mask = SD_POWER_MASK;
928fa590c22SMicky Ching val = SD_POWER_OFF;
929fa590c22SMicky Ching }
930fa590c22SMicky Ching
9318ee775f9SJoe Perches retval = rtsx_write_register(chip, CARD_PWR_CTL, mask, val);
9329f902b49SAymen Qader if (retval)
9338ee775f9SJoe Perches return retval;
934fa590c22SMicky Ching
935fa590c22SMicky Ching return STATUS_SUCCESS;
936fa590c22SMicky Ching }
937fa590c22SMicky Ching
card_rw(struct scsi_cmnd * srb,struct rtsx_chip * chip,u32 sec_addr,u16 sec_cnt)9388470e791SGulsah Kose int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
9398470e791SGulsah Kose u32 sec_addr, u16 sec_cnt)
940fa590c22SMicky Ching {
941fa590c22SMicky Ching int retval;
942fa590c22SMicky Ching unsigned int lun = SCSI_LUN(srb);
943fa590c22SMicky Ching int i;
944fa590c22SMicky Ching
9459f902b49SAymen Qader if (!chip->rw_card[lun])
946031366eaSJoe Perches return STATUS_FAIL;
947fa590c22SMicky Ching
948fa590c22SMicky Ching for (i = 0; i < 3; i++) {
949fa590c22SMicky Ching chip->rw_need_retry = 0;
950fa590c22SMicky Ching
951fa590c22SMicky Ching retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt);
952fa590c22SMicky Ching if (retval != STATUS_SUCCESS) {
953fa590c22SMicky Ching if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
954fa590c22SMicky Ching rtsx_release_chip(chip);
955031366eaSJoe Perches return STATUS_FAIL;
956fa590c22SMicky Ching }
9578470e791SGulsah Kose if (detect_card_cd(chip, chip->cur_card) !=
958031366eaSJoe Perches STATUS_SUCCESS) {
959031366eaSJoe Perches return STATUS_FAIL;
960031366eaSJoe Perches }
961fa590c22SMicky Ching
962fa590c22SMicky Ching if (!chip->rw_need_retry) {
963bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "RW fail, but no need to retry\n");
964fa590c22SMicky Ching break;
965fa590c22SMicky Ching }
966fa590c22SMicky Ching } else {
967fa590c22SMicky Ching chip->rw_need_retry = 0;
968fa590c22SMicky Ching break;
969fa590c22SMicky Ching }
970fa590c22SMicky Ching
971bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Retry RW, (i = %d)\n", i);
972fa590c22SMicky Ching }
973fa590c22SMicky Ching
974fa590c22SMicky Ching return retval;
975fa590c22SMicky Ching }
976fa590c22SMicky Ching
card_share_mode(struct rtsx_chip * chip,int card)977fa590c22SMicky Ching int card_share_mode(struct rtsx_chip *chip, int card)
978fa590c22SMicky Ching {
9798ee775f9SJoe Perches int retval;
980fa590c22SMicky Ching u8 mask, value;
981fa590c22SMicky Ching
982fa590c22SMicky Ching if (CHECK_PID(chip, 0x5208)) {
983fa590c22SMicky Ching mask = CARD_SHARE_MASK;
9849f902b49SAymen Qader if (card == SD_CARD)
985fa590c22SMicky Ching value = CARD_SHARE_48_SD;
9869f902b49SAymen Qader else if (card == MS_CARD)
987fa590c22SMicky Ching value = CARD_SHARE_48_MS;
9889f902b49SAymen Qader else if (card == XD_CARD)
989fa590c22SMicky Ching value = CARD_SHARE_48_XD;
9909f902b49SAymen Qader else
991031366eaSJoe Perches return STATUS_FAIL;
992fa590c22SMicky Ching
993fa590c22SMicky Ching } else if (CHECK_PID(chip, 0x5288)) {
994fa590c22SMicky Ching mask = 0x03;
9959f902b49SAymen Qader if (card == SD_CARD)
996fa590c22SMicky Ching value = CARD_SHARE_BAROSSA_SD;
9979f902b49SAymen Qader else if (card == MS_CARD)
998fa590c22SMicky Ching value = CARD_SHARE_BAROSSA_MS;
9999f902b49SAymen Qader else if (card == XD_CARD)
1000fa590c22SMicky Ching value = CARD_SHARE_BAROSSA_XD;
10019f902b49SAymen Qader else
1002031366eaSJoe Perches return STATUS_FAIL;
1003fa590c22SMicky Ching
1004fa590c22SMicky Ching } else {
1005031366eaSJoe Perches return STATUS_FAIL;
1006fa590c22SMicky Ching }
1007fa590c22SMicky Ching
10088ee775f9SJoe Perches retval = rtsx_write_register(chip, CARD_SHARE_MODE, mask, value);
10099f902b49SAymen Qader if (retval)
10108ee775f9SJoe Perches return retval;
1011fa590c22SMicky Ching
1012fa590c22SMicky Ching return STATUS_SUCCESS;
1013fa590c22SMicky Ching }
1014fa590c22SMicky Ching
select_card(struct rtsx_chip * chip,int card)1015fa590c22SMicky Ching int select_card(struct rtsx_chip *chip, int card)
1016fa590c22SMicky Ching {
1017fa590c22SMicky Ching int retval;
1018fa590c22SMicky Ching
1019fa590c22SMicky Ching if (chip->cur_card != card) {
1020fa590c22SMicky Ching u8 mod;
1021fa590c22SMicky Ching
10229f902b49SAymen Qader if (card == SD_CARD)
1023fa590c22SMicky Ching mod = SD_MOD_SEL;
10249f902b49SAymen Qader else if (card == MS_CARD)
1025fa590c22SMicky Ching mod = MS_MOD_SEL;
10269f902b49SAymen Qader else if (card == XD_CARD)
1027fa590c22SMicky Ching mod = XD_MOD_SEL;
10289f902b49SAymen Qader else if (card == SPI_CARD)
1029fa590c22SMicky Ching mod = SPI_MOD_SEL;
10309f902b49SAymen Qader else
1031031366eaSJoe Perches return STATUS_FAIL;
1032fa590c22SMicky Ching
10338ee775f9SJoe Perches retval = rtsx_write_register(chip, CARD_SELECT, 0x07, mod);
10349f902b49SAymen Qader if (retval)
10358ee775f9SJoe Perches return retval;
1036fa590c22SMicky Ching chip->cur_card = card;
1037fa590c22SMicky Ching
1038fa590c22SMicky Ching retval = card_share_mode(chip, card);
10399f902b49SAymen Qader if (retval != STATUS_SUCCESS)
1040031366eaSJoe Perches return STATUS_FAIL;
1041031366eaSJoe Perches }
1042fa590c22SMicky Ching
1043fa590c22SMicky Ching return STATUS_SUCCESS;
1044fa590c22SMicky Ching }
1045fa590c22SMicky Ching
toggle_gpio(struct rtsx_chip * chip,u8 gpio)1046fa590c22SMicky Ching void toggle_gpio(struct rtsx_chip *chip, u8 gpio)
1047fa590c22SMicky Ching {
1048fa590c22SMicky Ching u8 temp_reg;
1049fa590c22SMicky Ching
1050fa590c22SMicky Ching rtsx_read_register(chip, CARD_GPIO, &temp_reg);
1051fa590c22SMicky Ching temp_reg ^= (0x01 << gpio);
1052fa590c22SMicky Ching rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg);
1053fa590c22SMicky Ching }
1054fa590c22SMicky Ching
turn_on_led(struct rtsx_chip * chip,u8 gpio)1055fa590c22SMicky Ching void turn_on_led(struct rtsx_chip *chip, u8 gpio)
1056fa590c22SMicky Ching {
1057fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288))
10588470e791SGulsah Kose rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
10598470e791SGulsah Kose (u8)(1 << gpio));
1060fa590c22SMicky Ching else
1061fa590c22SMicky Ching rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
1062fa590c22SMicky Ching }
1063fa590c22SMicky Ching
turn_off_led(struct rtsx_chip * chip,u8 gpio)1064fa590c22SMicky Ching void turn_off_led(struct rtsx_chip *chip, u8 gpio)
1065fa590c22SMicky Ching {
1066fa590c22SMicky Ching if (CHECK_PID(chip, 0x5288))
1067fa590c22SMicky Ching rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
1068fa590c22SMicky Ching else
10698470e791SGulsah Kose rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
10708470e791SGulsah Kose (u8)(1 << gpio));
1071fa590c22SMicky Ching }
1072fa590c22SMicky Ching
detect_card_cd(struct rtsx_chip * chip,int card)1073fa590c22SMicky Ching int detect_card_cd(struct rtsx_chip *chip, int card)
1074fa590c22SMicky Ching {
1075fa590c22SMicky Ching u32 card_cd, status;
1076fa590c22SMicky Ching
1077fa590c22SMicky Ching if (card == SD_CARD) {
1078fa590c22SMicky Ching card_cd = SD_EXIST;
1079fa590c22SMicky Ching } else if (card == MS_CARD) {
1080fa590c22SMicky Ching card_cd = MS_EXIST;
1081fa590c22SMicky Ching } else if (card == XD_CARD) {
1082fa590c22SMicky Ching card_cd = XD_EXIST;
1083fa590c22SMicky Ching } else {
1084bf6c0d11SFabio Falzoi dev_dbg(rtsx_dev(chip), "Wrong card type: 0x%x\n", card);
1085031366eaSJoe Perches return STATUS_FAIL;
1086fa590c22SMicky Ching }
1087fa590c22SMicky Ching
1088fa590c22SMicky Ching status = rtsx_readl(chip, RTSX_BIPR);
10899f902b49SAymen Qader if (!(status & card_cd))
1090031366eaSJoe Perches return STATUS_FAIL;
1091fa590c22SMicky Ching
1092fa590c22SMicky Ching return STATUS_SUCCESS;
1093fa590c22SMicky Ching }
1094fa590c22SMicky Ching
check_card_exist(struct rtsx_chip * chip,unsigned int lun)1095fa590c22SMicky Ching int check_card_exist(struct rtsx_chip *chip, unsigned int lun)
1096fa590c22SMicky Ching {
1097fa590c22SMicky Ching if (chip->card_exist & chip->lun2card[lun])
1098fa590c22SMicky Ching return 1;
1099fa590c22SMicky Ching
1100fa590c22SMicky Ching return 0;
1101fa590c22SMicky Ching }
1102fa590c22SMicky Ching
check_card_ready(struct rtsx_chip * chip,unsigned int lun)1103fa590c22SMicky Ching int check_card_ready(struct rtsx_chip *chip, unsigned int lun)
1104fa590c22SMicky Ching {
1105fa590c22SMicky Ching if (chip->card_ready & chip->lun2card[lun])
1106fa590c22SMicky Ching return 1;
1107fa590c22SMicky Ching
1108fa590c22SMicky Ching return 0;
1109fa590c22SMicky Ching }
1110fa590c22SMicky Ching
check_card_wp(struct rtsx_chip * chip,unsigned int lun)1111fa590c22SMicky Ching int check_card_wp(struct rtsx_chip *chip, unsigned int lun)
1112fa590c22SMicky Ching {
1113fa590c22SMicky Ching if (chip->card_wp & chip->lun2card[lun])
1114fa590c22SMicky Ching return 1;
1115fa590c22SMicky Ching
1116fa590c22SMicky Ching return 0;
1117fa590c22SMicky Ching }
1118fa590c22SMicky Ching
get_lun_card(struct rtsx_chip * chip,unsigned int lun)1119fa590c22SMicky Ching u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun)
1120fa590c22SMicky Ching {
1121fa590c22SMicky Ching if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
1122fa590c22SMicky Ching return (u8)XD_CARD;
1123fa590c22SMicky Ching else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD)
1124fa590c22SMicky Ching return (u8)SD_CARD;
1125fa590c22SMicky Ching else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD)
1126fa590c22SMicky Ching return (u8)MS_CARD;
1127fa590c22SMicky Ching
1128fa590c22SMicky Ching return 0;
1129fa590c22SMicky Ching }
1130fa590c22SMicky Ching
eject_card(struct rtsx_chip * chip,unsigned int lun)1131fa590c22SMicky Ching void eject_card(struct rtsx_chip *chip, unsigned int lun)
1132fa590c22SMicky Ching {
1133fa590c22SMicky Ching do_remaining_work(chip);
1134fa590c22SMicky Ching
1135fa590c22SMicky Ching if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
1136fa590c22SMicky Ching release_sd_card(chip);
1137fa590c22SMicky Ching chip->card_ejected |= SD_CARD;
1138fa590c22SMicky Ching chip->card_ready &= ~SD_CARD;
1139fa590c22SMicky Ching chip->capacity[lun] = 0;
1140fa590c22SMicky Ching } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
1141fa590c22SMicky Ching release_xd_card(chip);
1142fa590c22SMicky Ching chip->card_ejected |= XD_CARD;
1143fa590c22SMicky Ching chip->card_ready &= ~XD_CARD;
1144fa590c22SMicky Ching chip->capacity[lun] = 0;
1145fa590c22SMicky Ching } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
1146fa590c22SMicky Ching release_ms_card(chip);
1147fa590c22SMicky Ching chip->card_ejected |= MS_CARD;
1148fa590c22SMicky Ching chip->card_ready &= ~MS_CARD;
1149fa590c22SMicky Ching chip->capacity[lun] = 0;
1150fa590c22SMicky Ching }
1151fa590c22SMicky Ching }
1152