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, &reg1);
86fa590c22SMicky Ching 	rtsx_read_register(chip, 0xFF38, &reg2);
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, &reg);
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