blob: 5946cc47e86bec2da9e207cbd0dcf5b5b606a9a9 [file] [log] [blame]
Micky Chingfa590c22013-11-12 17:16:08 +08001/* Driver for Realtek PCI-Express card reader
2 *
3 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author:
19 * Wei WANG (wei_wang@realsil.com.cn)
20 * Micky Ching (micky_ching@realsil.com.cn)
21 */
22
23#include <linux/blkdev.h>
24#include <linux/kthread.h>
25#include <linux/sched.h>
26#include <linux/workqueue.h>
27#include <linux/vmalloc.h>
28
29#include "rtsx.h"
Micky Chingfa590c22013-11-12 17:16:08 +080030#include "sd.h"
31#include "xd.h"
32#include "ms.h"
33
34static void rtsx_calibration(struct rtsx_chip *chip)
35{
36 rtsx_write_phy_register(chip, 0x1B, 0x135E);
37 wait_timeout(10);
38 rtsx_write_phy_register(chip, 0x00, 0x0280);
39 rtsx_write_phy_register(chip, 0x01, 0x7112);
40 rtsx_write_phy_register(chip, 0x01, 0x7110);
41 rtsx_write_phy_register(chip, 0x01, 0x7112);
42 rtsx_write_phy_register(chip, 0x01, 0x7113);
43 rtsx_write_phy_register(chip, 0x00, 0x0288);
44}
45
46void rtsx_disable_card_int(struct rtsx_chip *chip)
47{
48 u32 reg = rtsx_readl(chip, RTSX_BIER);
49
50 reg &= ~(XD_INT_EN | SD_INT_EN | MS_INT_EN);
51 rtsx_writel(chip, RTSX_BIER, reg);
52}
53
54void rtsx_enable_card_int(struct rtsx_chip *chip)
55{
56 u32 reg = rtsx_readl(chip, RTSX_BIER);
57 int i;
58
59 for (i = 0; i <= chip->max_lun; i++) {
60 if (chip->lun2card[i] & XD_CARD)
61 reg |= XD_INT_EN;
62 if (chip->lun2card[i] & SD_CARD)
63 reg |= SD_INT_EN;
64 if (chip->lun2card[i] & MS_CARD)
65 reg |= MS_INT_EN;
66 }
67 if (chip->hw_bypass_sd)
68 reg &= ~((u32)SD_INT_EN);
69
70 rtsx_writel(chip, RTSX_BIER, reg);
71}
72
73void rtsx_enable_bus_int(struct rtsx_chip *chip)
74{
75 u32 reg = 0;
76#ifndef DISABLE_CARD_INT
77 int i;
78#endif
79
80 reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN;
81
82#ifndef DISABLE_CARD_INT
83 for (i = 0; i <= chip->max_lun; i++) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +020084 dev_dbg(rtsx_dev(chip), "lun2card[%d] = 0x%02x\n",
85 i, chip->lun2card[i]);
Micky Chingfa590c22013-11-12 17:16:08 +080086
87 if (chip->lun2card[i] & XD_CARD)
88 reg |= XD_INT_EN;
89 if (chip->lun2card[i] & SD_CARD)
90 reg |= SD_INT_EN;
91 if (chip->lun2card[i] & MS_CARD)
92 reg |= MS_INT_EN;
93 }
94 if (chip->hw_bypass_sd)
95 reg &= ~((u32)SD_INT_EN);
96#endif
97
98 if (chip->ic_version >= IC_VER_C)
99 reg |= DELINK_INT_EN;
100#ifdef SUPPORT_OCP
Micky Chingbf2ec0f2014-04-02 17:58:52 +0800101 reg |= OC_INT_EN;
Micky Chingfa590c22013-11-12 17:16:08 +0800102#endif
103 if (!chip->adma_mode)
104 reg |= DATA_DONE_INT_EN;
105
106 /* Enable Bus Interrupt */
107 rtsx_writel(chip, RTSX_BIER, reg);
108
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200109 dev_dbg(rtsx_dev(chip), "RTSX_BIER: 0x%08x\n", reg);
Micky Chingfa590c22013-11-12 17:16:08 +0800110}
111
112void rtsx_disable_bus_int(struct rtsx_chip *chip)
113{
114 rtsx_writel(chip, RTSX_BIER, 0);
115}
116
117static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
118{
Joe Perches8ee775f2015-03-25 12:54:26 -0700119 int retval;
120
Micky Chingfa590c22013-11-12 17:16:08 +0800121 if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
122 if (chip->asic_code) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700123 retval = rtsx_write_register(chip, CARD_PULL_CTL5,
124 0xFF,
125 MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
126 if (retval) {
127 rtsx_trace(chip);
128 return retval;
129 }
Micky Chingfa590c22013-11-12 17:16:08 +0800130 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700131 retval = rtsx_write_register(chip, FPGA_PULL_CTL,
132 0xFF,
133 FPGA_SD_PULL_CTL_EN);
134 if (retval) {
135 rtsx_trace(chip);
136 return retval;
137 }
Micky Chingfa590c22013-11-12 17:16:08 +0800138 }
Joe Perches8ee775f2015-03-25 12:54:26 -0700139 retval = rtsx_write_register(chip, CARD_SHARE_MODE, 0xFF,
140 CARD_SHARE_48_SD);
141 if (retval) {
142 rtsx_trace(chip);
143 return retval;
144 }
Micky Chingfa590c22013-11-12 17:16:08 +0800145
146 /* Enable SDIO internal clock */
Joe Perches8ee775f2015-03-25 12:54:26 -0700147 retval = rtsx_write_register(chip, 0xFF2C, 0x01, 0x01);
148 if (retval) {
149 rtsx_trace(chip);
150 return retval;
151 }
Micky Chingfa590c22013-11-12 17:16:08 +0800152
Joe Perches8ee775f2015-03-25 12:54:26 -0700153 retval = rtsx_write_register(chip, SDIO_CTRL, 0xFF,
154 SDIO_BUS_CTRL | SDIO_CD_CTRL);
155 if (retval) {
156 rtsx_trace(chip);
157 return retval;
158 }
Micky Chingfa590c22013-11-12 17:16:08 +0800159
160 chip->sd_int = 1;
161 chip->sd_io = 1;
162 } else {
163 chip->need_reset |= SD_CARD;
164 }
165
166 return STATUS_SUCCESS;
167}
168
169#ifdef HW_AUTO_SWITCH_SD_BUS
170static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
171{
172 u8 tmp;
Quentin Lambertde904bf2015-03-04 11:31:01 +0100173 bool sw_bypass_sd = false;
Micky Chingfa590c22013-11-12 17:16:08 +0800174 int retval;
175
176 if (chip->driver_first_load) {
177 if (CHECK_PID(chip, 0x5288)) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700178 retval = rtsx_read_register(chip, 0xFE5A, &tmp);
179 if (retval) {
180 rtsx_trace(chip);
181 return retval;
182 }
Micky Chingfa590c22013-11-12 17:16:08 +0800183 if (tmp & 0x08)
Quentin Lambertde904bf2015-03-04 11:31:01 +0100184 sw_bypass_sd = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800185 } else if (CHECK_PID(chip, 0x5208)) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700186 retval = rtsx_read_register(chip, 0xFE70, &tmp);
187 if (retval) {
188 rtsx_trace(chip);
189 return retval;
190 }
Micky Chingfa590c22013-11-12 17:16:08 +0800191 if (tmp & 0x80)
Quentin Lambertde904bf2015-03-04 11:31:01 +0100192 sw_bypass_sd = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800193 }
194 } else {
195 if (chip->sdio_in_charge)
Quentin Lambertde904bf2015-03-04 11:31:01 +0100196 sw_bypass_sd = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800197 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200198 dev_dbg(rtsx_dev(chip), "chip->sdio_in_charge = %d\n",
199 chip->sdio_in_charge);
200 dev_dbg(rtsx_dev(chip), "chip->driver_first_load = %d\n",
201 chip->driver_first_load);
202 dev_dbg(rtsx_dev(chip), "sw_bypass_sd = %d\n",
203 sw_bypass_sd);
Micky Chingfa590c22013-11-12 17:16:08 +0800204
205 if (sw_bypass_sd) {
206 u8 cd_toggle_mask = 0;
207
Joe Perches8ee775f2015-03-25 12:54:26 -0700208 retval = rtsx_read_register(chip, TLPTISTAT, &tmp);
209 if (retval) {
210 rtsx_trace(chip);
211 return retval;
212 }
Micky Chingfa590c22013-11-12 17:16:08 +0800213 cd_toggle_mask = 0x08;
214
215 if (tmp & cd_toggle_mask) {
216 /* Disable sdio_bus_auto_switch */
Joe Perches8ee775f2015-03-25 12:54:26 -0700217 if (CHECK_PID(chip, 0x5288)) {
218 retval = rtsx_write_register(chip, 0xFE5A,
219 0x08, 0x00);
220 if (retval) {
221 rtsx_trace(chip);
222 return retval;
223 }
224 } else if (CHECK_PID(chip, 0x5208)) {
225 retval = rtsx_write_register(chip, 0xFE70,
226 0x80, 0x00);
227 if (retval) {
228 rtsx_trace(chip);
229 return retval;
230 }
231 }
Micky Chingfa590c22013-11-12 17:16:08 +0800232
Joe Perches8ee775f2015-03-25 12:54:26 -0700233 retval = rtsx_write_register(chip, TLPTISTAT, 0xFF,
234 tmp);
235 if (retval) {
236 rtsx_trace(chip);
237 return retval;
238 }
Micky Chingfa590c22013-11-12 17:16:08 +0800239
240 chip->need_reset |= SD_CARD;
241 } else {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200242 dev_dbg(rtsx_dev(chip), "Chip inserted with SDIO!\n");
Micky Chingfa590c22013-11-12 17:16:08 +0800243
244 if (chip->asic_code) {
245 retval = sd_pull_ctl_enable(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700246 if (retval != STATUS_SUCCESS) {
247 rtsx_trace(chip);
248 return STATUS_FAIL;
249 }
Micky Chingfa590c22013-11-12 17:16:08 +0800250 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700251 retval = rtsx_write_register(chip,
252 FPGA_PULL_CTL,
253 FPGA_SD_PULL_CTL_BIT | 0x20,
254 0);
255 if (retval) {
256 rtsx_trace(chip);
257 return retval;
258 }
Micky Chingfa590c22013-11-12 17:16:08 +0800259 }
260 retval = card_share_mode(chip, SD_CARD);
Joe Perches031366e2015-03-25 12:54:25 -0700261 if (retval != STATUS_SUCCESS) {
262 rtsx_trace(chip);
263 return STATUS_FAIL;
264 }
Micky Chingfa590c22013-11-12 17:16:08 +0800265
266 /* Enable sdio_bus_auto_switch */
Joe Perches8ee775f2015-03-25 12:54:26 -0700267 if (CHECK_PID(chip, 0x5288)) {
268 retval = rtsx_write_register(chip, 0xFE5A,
269 0x08, 0x08);
270 if (retval) {
271 rtsx_trace(chip);
272 return retval;
273 }
274 } else if (CHECK_PID(chip, 0x5208)) {
275 retval = rtsx_write_register(chip, 0xFE70,
276 0x80, 0x80);
277 if (retval) {
278 rtsx_trace(chip);
279 return retval;
280 }
281 }
Micky Chingfa590c22013-11-12 17:16:08 +0800282
283 chip->chip_insert_with_sdio = 1;
284 chip->sd_io = 1;
285 }
286 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700287 retval = rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
288 if (retval) {
289 rtsx_trace(chip);
290 return retval;
291 }
Micky Chingfa590c22013-11-12 17:16:08 +0800292
293 chip->need_reset |= SD_CARD;
294 }
295
296 return STATUS_SUCCESS;
297}
298#endif
299
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200300static int rtsx_reset_aspm(struct rtsx_chip *chip)
301{
302 int ret;
303
304 if (chip->dynamic_aspm) {
305 if (!CHK_SDIO_EXIST(chip) || !CHECK_PID(chip, 0x5288))
306 return STATUS_SUCCESS;
307
308 ret = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF,
309 chip->aspm_l0s_l1_en);
Joe Perches031366e2015-03-25 12:54:25 -0700310 if (ret != STATUS_SUCCESS) {
311 rtsx_trace(chip);
312 return STATUS_FAIL;
313 }
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200314
315 return STATUS_SUCCESS;
316 }
317
Joe Perches8ee775f2015-03-25 12:54:26 -0700318 if (CHECK_PID(chip, 0x5208)) {
319 ret = rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
320 if (ret) {
321 rtsx_trace(chip);
322 return ret;
323 }
324 }
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200325 ret = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
Joe Perches031366e2015-03-25 12:54:25 -0700326 if (ret != STATUS_SUCCESS) {
327 rtsx_trace(chip);
328 return STATUS_FAIL;
329 }
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200330
331 chip->aspm_level[0] = chip->aspm_l0s_l1_en;
332 if (CHK_SDIO_EXIST(chip)) {
333 chip->aspm_level[1] = chip->aspm_l0s_l1_en;
334 ret = rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
335 0xC0, 0xFF, chip->aspm_l0s_l1_en);
Joe Perches031366e2015-03-25 12:54:25 -0700336 if (ret != STATUS_SUCCESS) {
337 rtsx_trace(chip);
338 return STATUS_FAIL;
339 }
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200340 }
341
342 chip->aspm_enabled = 1;
343
344 return STATUS_SUCCESS;
345}
346
Fabio Falzoi506fe172014-10-19 21:30:03 +0200347static int rtsx_enable_pcie_intr(struct rtsx_chip *chip)
348{
349 int ret;
350
351 if (!chip->asic_code || !CHECK_PID(chip, 0x5208)) {
352 rtsx_enable_bus_int(chip);
353 return STATUS_SUCCESS;
354 }
355
356 if (chip->phy_debug_mode) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700357 ret = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
358 if (ret) {
359 rtsx_trace(chip);
360 return ret;
361 }
Fabio Falzoi506fe172014-10-19 21:30:03 +0200362 rtsx_disable_bus_int(chip);
363 } else {
364 rtsx_enable_bus_int(chip);
365 }
366
367 if (chip->ic_version >= IC_VER_D) {
368 u16 reg;
369
370 ret = rtsx_read_phy_register(chip, 0x00, &reg);
Joe Perches031366e2015-03-25 12:54:25 -0700371 if (ret != STATUS_SUCCESS) {
372 rtsx_trace(chip);
373 return STATUS_FAIL;
374 }
Fabio Falzoi506fe172014-10-19 21:30:03 +0200375
376 reg &= 0xFE7F;
377 reg |= 0x80;
378 ret = rtsx_write_phy_register(chip, 0x00, reg);
Joe Perches031366e2015-03-25 12:54:25 -0700379 if (ret != STATUS_SUCCESS) {
380 rtsx_trace(chip);
381 return STATUS_FAIL;
382 }
Fabio Falzoi506fe172014-10-19 21:30:03 +0200383
384 ret = rtsx_read_phy_register(chip, 0x1C, &reg);
Joe Perches031366e2015-03-25 12:54:25 -0700385 if (ret != STATUS_SUCCESS) {
386 rtsx_trace(chip);
387 return STATUS_FAIL;
388 }
Fabio Falzoi506fe172014-10-19 21:30:03 +0200389
390 reg &= 0xFFF7;
391 ret = rtsx_write_phy_register(chip, 0x1C, reg);
Joe Perches031366e2015-03-25 12:54:25 -0700392 if (ret != STATUS_SUCCESS) {
393 rtsx_trace(chip);
394 return STATUS_FAIL;
395 }
Fabio Falzoi506fe172014-10-19 21:30:03 +0200396 }
397
398 if (chip->driver_first_load && (chip->ic_version < IC_VER_C))
399 rtsx_calibration(chip);
400
401 return STATUS_SUCCESS;
402}
403
Micky Chingfa590c22013-11-12 17:16:08 +0800404int rtsx_reset_chip(struct rtsx_chip *chip)
405{
406 int retval;
407
408 rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
409
410 rtsx_disable_aspm(chip);
411
Joe Perches8ee775f2015-03-25 12:54:26 -0700412 retval = rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
413 if (retval) {
414 rtsx_trace(chip);
415 return retval;
416 }
Micky Chingfa590c22013-11-12 17:16:08 +0800417
418 /* Disable card clock */
Joe Perches8ee775f2015-03-25 12:54:26 -0700419 retval = rtsx_write_register(chip, CARD_CLK_EN, 0x1E, 0);
420 if (retval) {
421 rtsx_trace(chip);
422 return retval;
423 }
Micky Chingfa590c22013-11-12 17:16:08 +0800424
425#ifdef SUPPORT_OCP
426 /* SSC power on, OCD power on */
Joe Perches8ee775f2015-03-25 12:54:26 -0700427 if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
428 retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, 0);
429 if (retval) {
430 rtsx_trace(chip);
431 return retval;
432 }
433 } else {
434 retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
435 MS_OC_POWER_DOWN);
436 if (retval) {
437 rtsx_trace(chip);
438 return retval;
439 }
440 }
Micky Chingfa590c22013-11-12 17:16:08 +0800441
Joe Perches8ee775f2015-03-25 12:54:26 -0700442 retval = rtsx_write_register(chip, OCPPARA1, OCP_TIME_MASK,
443 OCP_TIME_800);
444 if (retval) {
445 rtsx_trace(chip);
446 return retval;
447 }
448 retval = rtsx_write_register(chip, OCPPARA2, OCP_THD_MASK,
449 OCP_THD_244_946);
450 if (retval) {
451 rtsx_trace(chip);
452 return retval;
453 }
454 retval = rtsx_write_register(chip, OCPCTL, 0xFF,
455 CARD_OC_INT_EN | CARD_DETECT_EN);
456 if (retval) {
457 rtsx_trace(chip);
458 return retval;
459 }
Micky Chingfa590c22013-11-12 17:16:08 +0800460#else
461 /* OC power down */
Joe Perches8ee775f2015-03-25 12:54:26 -0700462 retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
463 OC_POWER_DOWN);
464 if (retval) {
465 rtsx_trace(chip);
466 return retval;
467 }
Micky Chingfa590c22013-11-12 17:16:08 +0800468#endif
469
Joe Perches8ee775f2015-03-25 12:54:26 -0700470 if (!CHECK_PID(chip, 0x5288)) {
471 retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0xFF, 0x03);
472 if (retval) {
473 rtsx_trace(chip);
474 return retval;
475 }
476 }
Micky Chingfa590c22013-11-12 17:16:08 +0800477
478 /* Turn off LED */
Joe Perches8ee775f2015-03-25 12:54:26 -0700479 retval = rtsx_write_register(chip, CARD_GPIO, 0xFF, 0x03);
480 if (retval) {
481 rtsx_trace(chip);
482 return retval;
483 }
Micky Chingfa590c22013-11-12 17:16:08 +0800484
485 /* Reset delink mode */
Joe Perches8ee775f2015-03-25 12:54:26 -0700486 retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0);
487 if (retval) {
488 rtsx_trace(chip);
489 return retval;
490 }
Micky Chingfa590c22013-11-12 17:16:08 +0800491
492 /* Card driving select */
Joe Perches8ee775f2015-03-25 12:54:26 -0700493 retval = rtsx_write_register(chip, CARD_DRIVE_SEL, 0xFF,
494 chip->card_drive_sel);
495 if (retval) {
496 rtsx_trace(chip);
497 return retval;
498 }
Micky Chingfa590c22013-11-12 17:16:08 +0800499
500#ifdef LED_AUTO_BLINK
Joe Perches8ee775f2015-03-25 12:54:26 -0700501 retval = rtsx_write_register(chip, CARD_AUTO_BLINK, 0xFF,
502 LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
503 if (retval) {
504 rtsx_trace(chip);
505 return retval;
506 }
Micky Chingfa590c22013-11-12 17:16:08 +0800507#endif
508
509 if (chip->asic_code) {
510 /* Enable SSC Clock */
Joe Perches8ee775f2015-03-25 12:54:26 -0700511 retval = rtsx_write_register(chip, SSC_CTL1, 0xFF,
512 SSC_8X_EN | SSC_SEL_4M);
513 if (retval) {
514 rtsx_trace(chip);
515 return retval;
516 }
517 retval = rtsx_write_register(chip, SSC_CTL2, 0xFF, 0x12);
518 if (retval) {
519 rtsx_trace(chip);
520 return retval;
521 }
Micky Chingfa590c22013-11-12 17:16:08 +0800522 }
523
524 /* Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
525 0xFE5B
526 bit[1] u_cd_rst_core_en rst_value = 0
527 bit[2] u_force_rst_core_en rst_value = 0
528 bit[5] u_mac_phy_rst_n_dbg rst_value = 1
529 bit[4] u_non_sticky_rst_n_dbg rst_value = 0
530 */
Joe Perches8ee775f2015-03-25 12:54:26 -0700531 retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10);
532 if (retval) {
533 rtsx_trace(chip);
534 return retval;
535 }
Micky Chingfa590c22013-11-12 17:16:08 +0800536
537 /* Enable ASPM */
538 if (chip->aspm_l0s_l1_en) {
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200539 retval = rtsx_reset_aspm(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700540 if (retval != STATUS_SUCCESS) {
541 rtsx_trace(chip);
542 return STATUS_FAIL;
543 }
Micky Chingfa590c22013-11-12 17:16:08 +0800544 } else {
545 if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
546 retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
Joe Perches031366e2015-03-25 12:54:25 -0700547 if (retval != STATUS_SUCCESS) {
548 rtsx_trace(chip);
549 return STATUS_FAIL;
550 }
Micky Chingfa590c22013-11-12 17:16:08 +0800551 }
552 retval = rtsx_write_config_byte(chip, LCTLR,
553 chip->aspm_l0s_l1_en);
Joe Perches031366e2015-03-25 12:54:25 -0700554 if (retval != STATUS_SUCCESS) {
555 rtsx_trace(chip);
556 return STATUS_FAIL;
557 }
Micky Chingfa590c22013-11-12 17:16:08 +0800558 }
559
560 retval = rtsx_write_config_byte(chip, 0x81, 1);
Joe Perches031366e2015-03-25 12:54:25 -0700561 if (retval != STATUS_SUCCESS) {
562 rtsx_trace(chip);
563 return STATUS_FAIL;
564 }
Micky Chingfa590c22013-11-12 17:16:08 +0800565
566 if (CHK_SDIO_EXIST(chip)) {
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300567 retval = rtsx_write_cfg_dw(chip,
568 CHECK_PID(chip, 0x5288) ? 2 : 1,
569 0xC0, 0xFF00, 0x0100);
Micky Chingfa590c22013-11-12 17:16:08 +0800570
Joe Perches031366e2015-03-25 12:54:25 -0700571 if (retval != STATUS_SUCCESS) {
572 rtsx_trace(chip);
573 return STATUS_FAIL;
574 }
Micky Chingfa590c22013-11-12 17:16:08 +0800575 }
576
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +0300577 if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) {
578 retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
Joe Perches031366e2015-03-25 12:54:25 -0700579 if (retval != STATUS_SUCCESS) {
580 rtsx_trace(chip);
581 return STATUS_FAIL;
582 }
Micky Chingfa590c22013-11-12 17:16:08 +0800583
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +0300584 retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
Joe Perches031366e2015-03-25 12:54:25 -0700585 if (retval != STATUS_SUCCESS) {
586 rtsx_trace(chip);
587 return STATUS_FAIL;
588 }
Micky Chingfa590c22013-11-12 17:16:08 +0800589 }
590
Joe Perches8ee775f2015-03-25 12:54:26 -0700591 retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT,
592 LINK_RDY_INT);
593 if (retval) {
594 rtsx_trace(chip);
595 return retval;
596 }
Micky Chingfa590c22013-11-12 17:16:08 +0800597
Joe Perches8ee775f2015-03-25 12:54:26 -0700598 retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
599 if (retval) {
600 rtsx_trace(chip);
601 return retval;
602 }
Micky Chingfa590c22013-11-12 17:16:08 +0800603
Fabio Falzoi506fe172014-10-19 21:30:03 +0200604 retval = rtsx_enable_pcie_intr(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700605 if (retval != STATUS_SUCCESS) {
606 rtsx_trace(chip);
607 return STATUS_FAIL;
608 }
Micky Chingfa590c22013-11-12 17:16:08 +0800609
610 chip->need_reset = 0;
611
612 chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
613
614 if (chip->hw_bypass_sd)
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300615 goto nextcard;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200616 dev_dbg(rtsx_dev(chip), "In %s, chip->int_reg = 0x%x\n", __func__,
Micky Chingfa590c22013-11-12 17:16:08 +0800617 chip->int_reg);
618 if (chip->int_reg & SD_EXIST) {
619#ifdef HW_AUTO_SWITCH_SD_BUS
620 if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C))
621 retval = rtsx_pre_handle_sdio_old(chip);
622 else
623 retval = rtsx_pre_handle_sdio_new(chip);
624
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200625 dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x (rtsx_reset_chip)\n",
Micky Chingfa590c22013-11-12 17:16:08 +0800626 (unsigned int)(chip->need_reset));
627#else /* HW_AUTO_SWITCH_SD_BUS */
628 retval = rtsx_pre_handle_sdio_old(chip);
629#endif /* HW_AUTO_SWITCH_SD_BUS */
Joe Perches031366e2015-03-25 12:54:25 -0700630 if (retval != STATUS_SUCCESS) {
631 rtsx_trace(chip);
632 return STATUS_FAIL;
633 }
Micky Chingfa590c22013-11-12 17:16:08 +0800634
635 } else {
636 chip->sd_io = 0;
Joe Perches8ee775f2015-03-25 12:54:26 -0700637 retval = rtsx_write_register(chip, SDIO_CTRL,
638 SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
639 if (retval) {
640 rtsx_trace(chip);
641 return retval;
642 }
Micky Chingfa590c22013-11-12 17:16:08 +0800643 }
644
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300645nextcard:
Micky Chingfa590c22013-11-12 17:16:08 +0800646 if (chip->int_reg & XD_EXIST)
647 chip->need_reset |= XD_CARD;
648 if (chip->int_reg & MS_EXIST)
649 chip->need_reset |= MS_CARD;
Joe Perches8ee775f2015-03-25 12:54:26 -0700650 if (chip->int_reg & CARD_EXIST) {
651 retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB,
652 SSC_RSTB);
653 if (retval) {
654 rtsx_trace(chip);
655 return retval;
656 }
657 }
Micky Chingfa590c22013-11-12 17:16:08 +0800658
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200659 dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__,
Micky Chingfa590c22013-11-12 17:16:08 +0800660 (unsigned int)(chip->need_reset));
661
Joe Perches8ee775f2015-03-25 12:54:26 -0700662 retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00);
663 if (retval) {
664 rtsx_trace(chip);
665 return retval;
666 }
Micky Chingfa590c22013-11-12 17:16:08 +0800667
668 if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
669 /* Turn off main power when entering S3/S4 state */
Joe Perches8ee775f2015-03-25 12:54:26 -0700670 retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03,
671 0x03);
672 if (retval) {
673 rtsx_trace(chip);
674 return retval;
675 }
Micky Chingfa590c22013-11-12 17:16:08 +0800676 }
677
678 if (chip->remote_wakeup_en && !chip->auto_delink_en) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700679 retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07);
680 if (retval) {
681 rtsx_trace(chip);
682 return retval;
683 }
684 if (chip->aux_pwr_exist) {
685 retval = rtsx_write_register(chip, PME_FORCE_CTL,
686 0xFF, 0x33);
687 if (retval) {
688 rtsx_trace(chip);
689 return retval;
690 }
691 }
Micky Chingfa590c22013-11-12 17:16:08 +0800692 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700693 retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04);
694 if (retval) {
695 rtsx_trace(chip);
696 return retval;
697 }
698 retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30);
699 if (retval) {
700 rtsx_trace(chip);
701 return retval;
702 }
Micky Chingfa590c22013-11-12 17:16:08 +0800703 }
704
Joe Perches8ee775f2015-03-25 12:54:26 -0700705 if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
706 retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14);
707 if (retval) {
708 rtsx_trace(chip);
709 return retval;
710 }
711 }
Micky Chingfa590c22013-11-12 17:16:08 +0800712
713 if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
714 retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
Joe Perches031366e2015-03-25 12:54:25 -0700715 if (retval != STATUS_SUCCESS) {
716 rtsx_trace(chip);
717 return STATUS_FAIL;
718 }
Micky Chingfa590c22013-11-12 17:16:08 +0800719 }
720
721 if (chip->ft2_fast_mode) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700722 retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
723 MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
724 if (retval) {
725 rtsx_trace(chip);
726 return retval;
727 }
Micky Chingfa590c22013-11-12 17:16:08 +0800728 udelay(chip->pmos_pwr_on_interval);
Joe Perches8ee775f2015-03-25 12:54:26 -0700729 retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
730 MS_POWER_ON | SD_POWER_ON);
731 if (retval) {
732 rtsx_trace(chip);
733 return retval;
734 }
Micky Chingfa590c22013-11-12 17:16:08 +0800735
736 wait_timeout(200);
737 }
738
739 /* Reset card */
740 rtsx_reset_detected_cards(chip, 0);
741
742 chip->driver_first_load = 0;
743
744 return STATUS_SUCCESS;
745}
746
747static inline int check_sd_speed_prior(u32 sd_speed_prior)
748{
Quentin Lambertde904bf2015-03-04 11:31:01 +0100749 bool fake_para = false;
750 int i;
Micky Chingfa590c22013-11-12 17:16:08 +0800751
752 for (i = 0; i < 4; i++) {
753 u8 tmp = (u8)(sd_speed_prior >> (i*8));
Mahati Chamarthy0be0b272014-09-25 02:53:54 +0530754
Micky Chingfa590c22013-11-12 17:16:08 +0800755 if ((tmp < 0x01) || (tmp > 0x04)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +0100756 fake_para = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800757 break;
758 }
759 }
760
761 return !fake_para;
762}
763
764static inline int check_sd_current_prior(u32 sd_current_prior)
765{
Quentin Lambertde904bf2015-03-04 11:31:01 +0100766 bool fake_para = false;
767 int i;
Micky Chingfa590c22013-11-12 17:16:08 +0800768
769 for (i = 0; i < 4; i++) {
770 u8 tmp = (u8)(sd_current_prior >> (i*8));
Mahati Chamarthy0be0b272014-09-25 02:53:54 +0530771
Micky Chingfa590c22013-11-12 17:16:08 +0800772 if (tmp > 0x03) {
Quentin Lambertde904bf2015-03-04 11:31:01 +0100773 fake_para = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800774 break;
775 }
776 }
777
778 return !fake_para;
779}
780
781static int rts5208_init(struct rtsx_chip *chip)
782{
783 int retval;
784 u16 reg = 0;
785 u8 val = 0;
786
Joe Perches8ee775f2015-03-25 12:54:26 -0700787 retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
788 if (retval) {
789 rtsx_trace(chip);
790 return retval;
791 }
792 retval = rtsx_read_register(chip, CLK_SEL, &val);
793 if (retval) {
794 rtsx_trace(chip);
795 return retval;
796 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300797 chip->asic_code = val == 0 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800798
799 if (chip->asic_code) {
800 retval = rtsx_read_phy_register(chip, 0x1C, &reg);
Joe Perches031366e2015-03-25 12:54:25 -0700801 if (retval != STATUS_SUCCESS) {
802 rtsx_trace(chip);
803 return STATUS_FAIL;
804 }
Micky Chingfa590c22013-11-12 17:16:08 +0800805
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200806 dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n",
807 reg);
Micky Chingfa590c22013-11-12 17:16:08 +0800808 chip->ic_version = (reg >> 4) & 0x07;
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300809 chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800810
811 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700812 retval = rtsx_read_register(chip, 0xFE80, &val);
813 if (retval) {
814 rtsx_trace(chip);
815 return retval;
816 }
Micky Chingfa590c22013-11-12 17:16:08 +0800817 chip->ic_version = val;
818 chip->phy_debug_mode = 0;
819 }
820
Joe Perches8ee775f2015-03-25 12:54:26 -0700821 retval = rtsx_read_register(chip, PDINFO, &val);
822 if (retval) {
823 rtsx_trace(chip);
824 return retval;
825 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200826 dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300827 chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800828
Joe Perches8ee775f2015-03-25 12:54:26 -0700829 retval = rtsx_read_register(chip, 0xFE50, &val);
830 if (retval) {
831 rtsx_trace(chip);
832 return retval;
833 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300834 chip->hw_bypass_sd = val & 0x01 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800835
836 rtsx_read_config_byte(chip, 0x0E, &val);
837 if (val & 0x80)
838 SET_SDIO_EXIST(chip);
839 else
840 CLR_SDIO_EXIST(chip);
841
842 if (chip->use_hw_setting) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700843 retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
844 if (retval) {
845 rtsx_trace(chip);
846 return retval;
847 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300848 chip->auto_delink_en = val & 0x80 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800849 }
850
851 return STATUS_SUCCESS;
852}
853
854static int rts5288_init(struct rtsx_chip *chip)
855{
856 int retval;
857 u8 val = 0, max_func;
858 u32 lval = 0;
859
Joe Perches8ee775f2015-03-25 12:54:26 -0700860 retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
861 if (retval) {
862 rtsx_trace(chip);
863 return retval;
864 }
865 retval = rtsx_read_register(chip, CLK_SEL, &val);
866 if (retval) {
867 rtsx_trace(chip);
868 return retval;
869 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300870 chip->asic_code = val == 0 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800871
872 chip->ic_version = 0;
873 chip->phy_debug_mode = 0;
874
Joe Perches8ee775f2015-03-25 12:54:26 -0700875 retval = rtsx_read_register(chip, PDINFO, &val);
876 if (retval) {
877 rtsx_trace(chip);
878 return retval;
879 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200880 dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300881 chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800882
Joe Perches8ee775f2015-03-25 12:54:26 -0700883 retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val);
884 if (retval) {
885 rtsx_trace(chip);
886 return retval;
887 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200888 dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300889 chip->baro_pkg = val & 0x04 ? QFN : LQFP;
Micky Chingfa590c22013-11-12 17:16:08 +0800890
Joe Perches8ee775f2015-03-25 12:54:26 -0700891 retval = rtsx_read_register(chip, 0xFE5A, &val);
892 if (retval) {
893 rtsx_trace(chip);
894 return retval;
895 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300896 chip->hw_bypass_sd = val & 0x10 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800897
898 retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
Joe Perches031366e2015-03-25 12:54:25 -0700899 if (retval != STATUS_SUCCESS) {
900 rtsx_trace(chip);
901 return STATUS_FAIL;
902 }
Micky Chingfa590c22013-11-12 17:16:08 +0800903
904 max_func = (u8)((lval >> 29) & 0x07);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200905 dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func);
Micky Chingfa590c22013-11-12 17:16:08 +0800906 if (max_func == 0x02)
907 SET_SDIO_EXIST(chip);
908 else
909 CLR_SDIO_EXIST(chip);
910
911 if (chip->use_hw_setting) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700912 retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
913 if (retval) {
914 rtsx_trace(chip);
915 return retval;
916 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300917 chip->auto_delink_en = val & 0x80 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800918
919 if (CHECK_BARO_PKG(chip, LQFP))
920 chip->lun_mode = SD_MS_1LUN;
921 else
922 chip->lun_mode = DEFAULT_SINGLE;
Micky Chingfa590c22013-11-12 17:16:08 +0800923 }
924
925 return STATUS_SUCCESS;
926}
927
928int rtsx_init_chip(struct rtsx_chip *chip)
929{
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300930 struct sd_info *sd_card = &chip->sd_card;
931 struct xd_info *xd_card = &chip->xd_card;
932 struct ms_info *ms_card = &chip->ms_card;
Micky Chingfa590c22013-11-12 17:16:08 +0800933 int retval;
934 unsigned int i;
935
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200936 dev_dbg(rtsx_dev(chip), "Vendor ID: 0x%04x, Product ID: 0x%04x\n",
937 chip->vendor_id, chip->product_id);
Micky Chingfa590c22013-11-12 17:16:08 +0800938
939 chip->ic_version = 0;
940
941#ifdef _MSG_TRACE
942 chip->msg_idx = 0;
943#endif
944
945 memset(xd_card, 0, sizeof(struct xd_info));
946 memset(sd_card, 0, sizeof(struct sd_info));
947 memset(ms_card, 0, sizeof(struct ms_info));
948
949 chip->xd_reset_counter = 0;
950 chip->sd_reset_counter = 0;
951 chip->ms_reset_counter = 0;
952
953 chip->xd_show_cnt = MAX_SHOW_CNT;
954 chip->sd_show_cnt = MAX_SHOW_CNT;
955 chip->ms_show_cnt = MAX_SHOW_CNT;
956
957 chip->sd_io = 0;
958 chip->auto_delink_cnt = 0;
959 chip->auto_delink_allowed = 1;
960 rtsx_set_stat(chip, RTSX_STAT_INIT);
961
962 chip->aspm_enabled = 0;
963 chip->chip_insert_with_sdio = 0;
964 chip->sdio_aspm = 0;
965 chip->sdio_idle = 0;
966 chip->sdio_counter = 0;
967 chip->cur_card = 0;
968 chip->phy_debug_mode = 0;
969 chip->sdio_func_exist = 0;
970 memset(chip->sdio_raw_data, 0, 12);
971
972 for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
973 set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
974 chip->rw_fail_cnt[i] = 0;
975 }
976
977 if (!check_sd_speed_prior(chip->sd_speed_prior))
978 chip->sd_speed_prior = 0x01040203;
979
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200980 dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n",
981 chip->sd_speed_prior);
Micky Chingfa590c22013-11-12 17:16:08 +0800982
983 if (!check_sd_current_prior(chip->sd_current_prior))
984 chip->sd_current_prior = 0x00010203;
985
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200986 dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n",
987 chip->sd_current_prior);
Micky Chingfa590c22013-11-12 17:16:08 +0800988
989 if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0))
990 chip->sd_ddr_tx_phase = 0;
991
992 if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0))
993 chip->mmc_ddr_tx_phase = 0;
994
Joe Perches8ee775f2015-03-25 12:54:26 -0700995 retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0);
996 if (retval) {
997 rtsx_trace(chip);
998 return retval;
999 }
Micky Chingfa590c22013-11-12 17:16:08 +08001000 wait_timeout(200);
Joe Perches8ee775f2015-03-25 12:54:26 -07001001 retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07);
1002 if (retval) {
1003 rtsx_trace(chip);
1004 return retval;
1005 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001006 dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n",
1007 chip->use_hw_setting);
Micky Chingfa590c22013-11-12 17:16:08 +08001008
1009 if (CHECK_PID(chip, 0x5208)) {
1010 retval = rts5208_init(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001011 if (retval != STATUS_SUCCESS) {
1012 rtsx_trace(chip);
1013 return STATUS_FAIL;
1014 }
Micky Chingfa590c22013-11-12 17:16:08 +08001015
1016 } else if (CHECK_PID(chip, 0x5288)) {
1017 retval = rts5288_init(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001018 if (retval != STATUS_SUCCESS) {
1019 rtsx_trace(chip);
1020 return STATUS_FAIL;
1021 }
Micky Chingfa590c22013-11-12 17:16:08 +08001022 }
1023
1024 if (chip->ss_en == 2)
1025 chip->ss_en = 0;
1026
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001027 dev_dbg(rtsx_dev(chip), "chip->asic_code = %d\n", chip->asic_code);
1028 dev_dbg(rtsx_dev(chip), "chip->ic_version = 0x%x\n", chip->ic_version);
1029 dev_dbg(rtsx_dev(chip), "chip->phy_debug_mode = %d\n",
1030 chip->phy_debug_mode);
1031 dev_dbg(rtsx_dev(chip), "chip->aux_pwr_exist = %d\n",
1032 chip->aux_pwr_exist);
1033 dev_dbg(rtsx_dev(chip), "chip->sdio_func_exist = %d\n",
1034 chip->sdio_func_exist);
1035 dev_dbg(rtsx_dev(chip), "chip->hw_bypass_sd = %d\n",
1036 chip->hw_bypass_sd);
1037 dev_dbg(rtsx_dev(chip), "chip->aspm_l0s_l1_en = %d\n",
1038 chip->aspm_l0s_l1_en);
1039 dev_dbg(rtsx_dev(chip), "chip->lun_mode = %d\n", chip->lun_mode);
1040 dev_dbg(rtsx_dev(chip), "chip->auto_delink_en = %d\n",
1041 chip->auto_delink_en);
1042 dev_dbg(rtsx_dev(chip), "chip->ss_en = %d\n", chip->ss_en);
1043 dev_dbg(rtsx_dev(chip), "chip->baro_pkg = %d\n", chip->baro_pkg);
Micky Chingfa590c22013-11-12 17:16:08 +08001044
1045 if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
1046 chip->card2lun[SD_CARD] = 0;
1047 chip->card2lun[MS_CARD] = 1;
1048 chip->card2lun[XD_CARD] = 0xFF;
1049 chip->lun2card[0] = SD_CARD;
1050 chip->lun2card[1] = MS_CARD;
1051 chip->max_lun = 1;
1052 SET_SDIO_IGNORED(chip);
1053 } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
1054 chip->card2lun[SD_CARD] = 0;
1055 chip->card2lun[MS_CARD] = 0;
1056 chip->card2lun[XD_CARD] = 0xFF;
1057 chip->lun2card[0] = SD_CARD | MS_CARD;
1058 chip->max_lun = 0;
1059 } else {
1060 chip->card2lun[XD_CARD] = 0;
1061 chip->card2lun[SD_CARD] = 0;
1062 chip->card2lun[MS_CARD] = 0;
1063 chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
1064 chip->max_lun = 0;
1065 }
1066
1067 retval = rtsx_reset_chip(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001068 if (retval != STATUS_SUCCESS) {
1069 rtsx_trace(chip);
1070 return STATUS_FAIL;
1071 }
Micky Chingfa590c22013-11-12 17:16:08 +08001072
1073 return STATUS_SUCCESS;
1074}
1075
1076void rtsx_release_chip(struct rtsx_chip *chip)
1077{
1078 xd_free_l2p_tbl(chip);
1079 ms_free_l2p_tbl(chip);
1080 chip->card_exist = 0;
1081 chip->card_ready = 0;
1082}
1083
1084#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1085static inline void rtsx_blink_led(struct rtsx_chip *chip)
1086{
1087 if (chip->card_exist && chip->blink_led) {
1088 if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
1089 chip->led_toggle_counter++;
1090 } else {
1091 chip->led_toggle_counter = 0;
1092 toggle_gpio(chip, LED_GPIO);
1093 }
1094 }
1095}
1096#endif
1097
1098static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
1099{
Quentin Lambertde904bf2015-03-04 11:31:01 +01001100 bool reg_changed, maybe_support_aspm;
Micky Chingfa590c22013-11-12 17:16:08 +08001101 u32 tmp = 0;
1102 u8 reg0 = 0, reg1 = 0;
1103
Quentin Lambertde904bf2015-03-04 11:31:01 +01001104 maybe_support_aspm = false;
1105 reg_changed = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001106 rtsx_read_config_byte(chip, LCTLR, &reg0);
1107 if (chip->aspm_level[0] != reg0) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001108 reg_changed = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001109 chip->aspm_level[0] = reg0;
1110 }
1111 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
1112 rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
1113 reg1 = (u8)tmp;
1114 if (chip->aspm_level[1] != reg1) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001115 reg_changed = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001116 chip->aspm_level[1] = reg1;
1117 }
1118
1119 if ((reg0 & 0x03) && (reg1 & 0x03))
Quentin Lambertde904bf2015-03-04 11:31:01 +01001120 maybe_support_aspm = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001121
1122 } else {
1123 if (reg0 & 0x03)
Quentin Lambertde904bf2015-03-04 11:31:01 +01001124 maybe_support_aspm = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001125 }
1126
1127 if (reg_changed) {
1128 if (maybe_support_aspm)
1129 chip->aspm_l0s_l1_en = 0x03;
1130
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001131 dev_dbg(rtsx_dev(chip), "aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
1132 chip->aspm_level[0], chip->aspm_level[1]);
Micky Chingfa590c22013-11-12 17:16:08 +08001133
1134 if (chip->aspm_l0s_l1_en) {
1135 chip->aspm_enabled = 1;
1136 } else {
1137 chip->aspm_enabled = 0;
1138 chip->sdio_aspm = 0;
1139 }
1140 rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001141 0x30 | chip->aspm_level[0] |
1142 (chip->aspm_level[1] << 2));
Micky Chingfa590c22013-11-12 17:16:08 +08001143 }
1144}
1145
Fabio Falzoi50763572015-06-14 15:48:48 +02001146static void rtsx_manage_ocp(struct rtsx_chip *chip)
1147{
1148#ifdef SUPPORT_OCP
1149 if (!chip->ocp_int)
1150 return;
1151
1152 rtsx_read_register(chip, OCPSTAT, &chip->ocp_stat);
1153
1154 if (chip->card_exist & SD_CARD)
1155 sd_power_off_card3v3(chip);
1156 else if (chip->card_exist & MS_CARD)
1157 ms_power_off_card3v3(chip);
1158 else if (chip->card_exist & XD_CARD)
1159 xd_power_off_card3v3(chip);
1160
1161 chip->ocp_int = 0;
1162#endif
1163}
1164
Fabio Falzoicb547642015-06-14 15:48:47 +02001165static void rtsx_manage_sd_lock(struct rtsx_chip *chip)
Micky Chingfa590c22013-11-12 17:16:08 +08001166{
1167#ifdef SUPPORT_SD_LOCK
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001168 struct sd_info *sd_card = &chip->sd_card;
Fabio Falzoicb547642015-06-14 15:48:47 +02001169 u8 val;
1170
1171 if (!sd_card->sd_erase_status)
1172 return;
1173
1174 if (chip->card_exist & SD_CARD) {
1175 rtsx_read_register(chip, 0xFD30, &val);
1176 if (val & 0x02) {
1177 sd_card->sd_erase_status = SD_NOT_ERASE;
1178 sd_card->sd_lock_notify = 1;
1179 chip->need_reinit |= SD_CARD;
1180 }
1181 } else {
1182 sd_card->sd_erase_status = SD_NOT_ERASE;
1183 }
Micky Chingfa590c22013-11-12 17:16:08 +08001184#endif
Fabio Falzoicb547642015-06-14 15:48:47 +02001185}
1186
1187void rtsx_polling_func(struct rtsx_chip *chip)
1188{
Quentin Lambertde904bf2015-03-04 11:31:01 +01001189 bool ss_allowed;
Micky Chingfa590c22013-11-12 17:16:08 +08001190
1191 if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
1192 return;
1193
1194 if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001195 goto delink_stage;
Micky Chingfa590c22013-11-12 17:16:08 +08001196
1197 if (chip->polling_config) {
1198 u8 val;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301199
Micky Chingfa590c22013-11-12 17:16:08 +08001200 rtsx_read_config_byte(chip, 0, &val);
1201 }
1202
1203 if (rtsx_chk_stat(chip, RTSX_STAT_SS))
1204 return;
1205
Fabio Falzoi50763572015-06-14 15:48:48 +02001206 rtsx_manage_ocp(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001207
Fabio Falzoicb547642015-06-14 15:48:47 +02001208 rtsx_manage_sd_lock(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001209
1210 rtsx_init_cards(chip);
1211
1212 if (chip->ss_en) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001213 ss_allowed = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001214
1215 if (CHECK_PID(chip, 0x5288)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001216 ss_allowed = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001217 } else {
1218 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
1219 u32 val;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301220
Micky Chingfa590c22013-11-12 17:16:08 +08001221 rtsx_read_cfg_dw(chip, 1, 0x04, &val);
1222 if (val & 0x07)
Quentin Lambertde904bf2015-03-04 11:31:01 +01001223 ss_allowed = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001224 }
1225 }
1226 } else {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001227 ss_allowed = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001228 }
1229
1230 if (ss_allowed && !chip->sd_io) {
1231 if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
1232 chip->ss_counter = 0;
1233 } else {
1234 if (chip->ss_counter <
1235 (chip->ss_idle_period / POLLING_INTERVAL)) {
1236 chip->ss_counter++;
1237 } else {
1238 rtsx_exclusive_enter_ss(chip);
1239 return;
1240 }
1241 }
1242 }
1243
1244 if (CHECK_PID(chip, 0x5208)) {
1245 rtsx_monitor_aspm_config(chip);
1246
1247#ifdef SUPPORT_SDIO_ASPM
1248 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) &&
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001249 chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
Micky Chingfa590c22013-11-12 17:16:08 +08001250 if (chip->sd_io) {
1251 dynamic_configure_sdio_aspm(chip);
1252 } else {
1253 if (!chip->sdio_aspm) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001254 dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001255 rtsx_write_register(chip,
1256 ASPM_FORCE_CTL, 0xFC,
Giedrius Statkevičiusfbbf3592014-10-04 00:31:20 +03001257 0x30 |
1258 (chip->aspm_level[1] << 2));
Micky Chingfa590c22013-11-12 17:16:08 +08001259 chip->sdio_aspm = 1;
1260 }
1261 }
1262 }
1263#endif
1264 }
1265
1266 if (chip->idle_counter < IDLE_MAX_COUNT) {
1267 chip->idle_counter++;
1268 } else {
1269 if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001270 dev_dbg(rtsx_dev(chip), "Idle state!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001271 rtsx_set_stat(chip, RTSX_STAT_IDLE);
1272
1273#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1274 chip->led_toggle_counter = 0;
1275#endif
1276 rtsx_force_power_on(chip, SSC_PDCTL);
1277
1278 turn_off_led(chip, LED_GPIO);
1279
Giedrius Statkevičiusfbbf3592014-10-04 00:31:20 +03001280 if (chip->auto_power_down && !chip->card_ready &&
1281 !chip->sd_io)
1282 rtsx_force_power_down(chip,
1283 SSC_PDCTL | OC_PDCTL);
Micky Chingfa590c22013-11-12 17:16:08 +08001284 }
1285 }
1286
1287 switch (rtsx_get_stat(chip)) {
1288 case RTSX_STAT_RUN:
1289#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1290 rtsx_blink_led(chip);
1291#endif
1292 do_remaining_work(chip);
1293 break;
1294
1295 case RTSX_STAT_IDLE:
1296 if (chip->sd_io && !chip->sd_int)
1297 try_to_switch_sdio_ctrl(chip);
1298
1299 rtsx_enable_aspm(chip);
1300 break;
1301
1302 default:
1303 break;
1304 }
1305
Micky Chingfa590c22013-11-12 17:16:08 +08001306#ifdef SUPPORT_OCP
1307 if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
Micky Chingfa590c22013-11-12 17:16:08 +08001308 if (chip->ocp_stat &
1309 (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER))
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001310 dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08001311 chip->ocp_stat);
Micky Chingfa590c22013-11-12 17:16:08 +08001312
1313 if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
1314 if (chip->card_exist & SD_CARD) {
1315 rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001316 0);
Micky Chingfa590c22013-11-12 17:16:08 +08001317 card_power_off(chip, SD_CARD);
1318 chip->card_fail |= SD_CARD;
1319 }
1320 }
1321 if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) {
1322 if (chip->card_exist & MS_CARD) {
1323 rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001324 0);
Micky Chingfa590c22013-11-12 17:16:08 +08001325 card_power_off(chip, MS_CARD);
1326 chip->card_fail |= MS_CARD;
1327 }
1328 }
1329 } else {
1330 if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001331 dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
Micky Chingfa590c22013-11-12 17:16:08 +08001332 chip->ocp_stat);
1333 if (chip->card_exist & SD_CARD) {
1334 rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001335 0);
Micky Chingfa590c22013-11-12 17:16:08 +08001336 chip->card_fail |= SD_CARD;
1337 } else if (chip->card_exist & MS_CARD) {
1338 rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001339 0);
Micky Chingfa590c22013-11-12 17:16:08 +08001340 chip->card_fail |= MS_CARD;
1341 } else if (chip->card_exist & XD_CARD) {
1342 rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001343 0);
Micky Chingfa590c22013-11-12 17:16:08 +08001344 chip->card_fail |= XD_CARD;
1345 }
1346 card_power_off(chip, SD_CARD);
1347 }
1348 }
1349#endif
1350
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001351delink_stage:
Micky Chingfa590c22013-11-12 17:16:08 +08001352 if (chip->auto_delink_en && chip->auto_delink_allowed &&
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001353 !chip->card_ready && !chip->card_ejected && !chip->sd_io) {
Micky Chingfa590c22013-11-12 17:16:08 +08001354 int enter_L1 = chip->auto_delink_in_L1 && (
1355 chip->aspm_l0s_l1_en || chip->ss_en);
1356 int delink_stage1_cnt = chip->delink_stage1_step;
1357 int delink_stage2_cnt = delink_stage1_cnt +
1358 chip->delink_stage2_step;
1359 int delink_stage3_cnt = delink_stage2_cnt +
1360 chip->delink_stage3_step;
1361
1362 if (chip->auto_delink_cnt <= delink_stage3_cnt) {
1363 if (chip->auto_delink_cnt == delink_stage1_cnt) {
1364 rtsx_set_stat(chip, RTSX_STAT_DELINK);
1365
1366 if (chip->asic_code && CHECK_PID(chip, 0x5208))
1367 rtsx_set_phy_reg_bit(chip, 0x1C, 2);
1368
1369 if (chip->card_exist) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001370 dev_dbg(rtsx_dev(chip), "False card inserted, do force delink\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001371
1372 if (enter_L1)
Giedrius Statkevičiusfbbf3592014-10-04 00:31:20 +03001373 rtsx_write_register(chip,
1374 HOST_SLEEP_STATE,
1375 0x03, 1);
Micky Chingfa590c22013-11-12 17:16:08 +08001376
1377 rtsx_write_register(chip,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001378 CHANGE_LINK_STATE,
1379 0x0A, 0x0A);
Micky Chingfa590c22013-11-12 17:16:08 +08001380
1381 if (enter_L1)
1382 rtsx_enter_L1(chip);
1383
Giedrius Statkevičiusfbbf3592014-10-04 00:31:20 +03001384 chip->auto_delink_cnt =
1385 delink_stage3_cnt + 1;
Micky Chingfa590c22013-11-12 17:16:08 +08001386 } else {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001387 dev_dbg(rtsx_dev(chip), "No card inserted, do delink\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001388
1389 if (enter_L1)
Giedrius Statkevičiusfbbf3592014-10-04 00:31:20 +03001390 rtsx_write_register(chip,
1391 HOST_SLEEP_STATE,
1392 0x03, 1);
Micky Chingfa590c22013-11-12 17:16:08 +08001393
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001394 rtsx_write_register(chip,
1395 CHANGE_LINK_STATE,
1396 0x02, 0x02);
Micky Chingfa590c22013-11-12 17:16:08 +08001397
1398 if (enter_L1)
1399 rtsx_enter_L1(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001400 }
1401 }
1402
1403 if (chip->auto_delink_cnt == delink_stage2_cnt) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001404 dev_dbg(rtsx_dev(chip), "Try to do force delink\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001405
1406 if (enter_L1)
1407 rtsx_exit_L1(chip);
1408
1409 if (chip->asic_code && CHECK_PID(chip, 0x5208))
1410 rtsx_set_phy_reg_bit(chip, 0x1C, 2);
1411
1412 rtsx_write_register(chip, CHANGE_LINK_STATE,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001413 0x0A, 0x0A);
Micky Chingfa590c22013-11-12 17:16:08 +08001414 }
1415
1416 chip->auto_delink_cnt++;
1417 }
1418 } else {
1419 chip->auto_delink_cnt = 0;
1420 }
1421}
1422
1423void rtsx_undo_delink(struct rtsx_chip *chip)
1424{
1425 chip->auto_delink_allowed = 0;
1426 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00);
1427}
1428
1429/**
1430 * rtsx_stop_cmd - stop command transfer and DMA transfer
1431 * @chip: Realtek's card reader chip
1432 * @card: flash card type
1433 *
1434 * Stop command transfer and DMA transfer.
1435 * This function is called in error handler.
1436 */
1437void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
1438{
1439 int i;
1440
1441 for (i = 0; i <= 8; i++) {
1442 int addr = RTSX_HCBAR + i * 4;
1443 u32 reg;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301444
Micky Chingfa590c22013-11-12 17:16:08 +08001445 reg = rtsx_readl(chip, addr);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001446 dev_dbg(rtsx_dev(chip), "BAR (0x%02x): 0x%08x\n", addr, reg);
Micky Chingfa590c22013-11-12 17:16:08 +08001447 }
1448 rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
1449 rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
1450
1451 for (i = 0; i < 16; i++) {
1452 u16 addr = 0xFE20 + (u16)i;
1453 u8 val;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301454
Micky Chingfa590c22013-11-12 17:16:08 +08001455 rtsx_read_register(chip, addr, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001456 dev_dbg(rtsx_dev(chip), "0x%04X: 0x%02x\n", addr, val);
Micky Chingfa590c22013-11-12 17:16:08 +08001457 }
1458
1459 rtsx_write_register(chip, DMACTL, 0x80, 0x80);
1460 rtsx_write_register(chip, RBCTL, 0x80, 0x80);
1461}
1462
1463#define MAX_RW_REG_CNT 1024
1464
1465int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
1466{
1467 int i;
1468 u32 val = 3 << 30;
1469
1470 val |= (u32)(addr & 0x3FFF) << 16;
1471 val |= (u32)mask << 8;
1472 val |= (u32)data;
1473
1474 rtsx_writel(chip, RTSX_HAIMR, val);
1475
1476 for (i = 0; i < MAX_RW_REG_CNT; i++) {
1477 val = rtsx_readl(chip, RTSX_HAIMR);
1478 if ((val & (1 << 31)) == 0) {
Joe Perches031366e2015-03-25 12:54:25 -07001479 if (data != (u8)val) {
1480 rtsx_trace(chip);
1481 return STATUS_FAIL;
1482 }
Micky Chingfa590c22013-11-12 17:16:08 +08001483
1484 return STATUS_SUCCESS;
1485 }
1486 }
1487
Joe Perches031366e2015-03-25 12:54:25 -07001488 rtsx_trace(chip);
1489 return STATUS_TIMEDOUT;
Micky Chingfa590c22013-11-12 17:16:08 +08001490}
1491
1492int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
1493{
1494 u32 val = 2 << 30;
1495 int i;
1496
1497 if (data)
1498 *data = 0;
1499
1500 val |= (u32)(addr & 0x3FFF) << 16;
1501
1502 rtsx_writel(chip, RTSX_HAIMR, val);
1503
1504 for (i = 0; i < MAX_RW_REG_CNT; i++) {
1505 val = rtsx_readl(chip, RTSX_HAIMR);
1506 if ((val & (1 << 31)) == 0)
1507 break;
1508 }
1509
Joe Perches031366e2015-03-25 12:54:25 -07001510 if (i >= MAX_RW_REG_CNT) {
1511 rtsx_trace(chip);
1512 return STATUS_TIMEDOUT;
1513 }
Micky Chingfa590c22013-11-12 17:16:08 +08001514
1515 if (data)
1516 *data = (u8)(val & 0xFF);
1517
1518 return STATUS_SUCCESS;
1519}
1520
1521int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001522 u32 val)
Micky Chingfa590c22013-11-12 17:16:08 +08001523{
Joe Perches8ee775f2015-03-25 12:54:26 -07001524 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001525 u8 mode = 0, tmp;
1526 int i;
1527
1528 for (i = 0; i < 4; i++) {
1529 if (mask & 0xFF) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001530 retval = rtsx_write_register(chip, CFGDATA0 + i,
1531 0xFF,
1532 (u8)(val & mask & 0xFF));
1533 if (retval) {
1534 rtsx_trace(chip);
1535 return retval;
1536 }
Micky Chingfa590c22013-11-12 17:16:08 +08001537 mode |= (1 << i);
1538 }
1539 mask >>= 8;
1540 val >>= 8;
1541 }
1542
1543 if (mode) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001544 retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
1545 if (retval) {
1546 rtsx_trace(chip);
1547 return retval;
1548 }
1549 retval = rtsx_write_register(chip, CFGADDR1, 0xFF,
1550 (u8)(addr >> 8));
1551 if (retval) {
1552 rtsx_trace(chip);
1553 return retval;
1554 }
Micky Chingfa590c22013-11-12 17:16:08 +08001555
Joe Perches8ee775f2015-03-25 12:54:26 -07001556 retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
1557 0x80 | mode | ((func_no & 0x03) << 4));
1558 if (retval) {
1559 rtsx_trace(chip);
1560 return retval;
1561 }
Micky Chingfa590c22013-11-12 17:16:08 +08001562
1563 for (i = 0; i < MAX_RW_REG_CNT; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001564 retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
1565 if (retval) {
1566 rtsx_trace(chip);
1567 return retval;
1568 }
Micky Chingfa590c22013-11-12 17:16:08 +08001569 if ((tmp & 0x80) == 0)
1570 break;
1571 }
1572 }
1573
1574 return STATUS_SUCCESS;
1575}
1576
1577int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
1578{
Joe Perches8ee775f2015-03-25 12:54:26 -07001579 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001580 int i;
1581 u8 tmp;
1582 u32 data = 0;
1583
Joe Perches8ee775f2015-03-25 12:54:26 -07001584 retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
1585 if (retval) {
1586 rtsx_trace(chip);
1587 return retval;
1588 }
1589 retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
1590 if (retval) {
1591 rtsx_trace(chip);
1592 return retval;
1593 }
1594 retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
1595 0x80 | ((func_no & 0x03) << 4));
1596 if (retval) {
1597 rtsx_trace(chip);
1598 return retval;
1599 }
Micky Chingfa590c22013-11-12 17:16:08 +08001600
1601 for (i = 0; i < MAX_RW_REG_CNT; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001602 retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
1603 if (retval) {
1604 rtsx_trace(chip);
1605 return retval;
1606 }
Micky Chingfa590c22013-11-12 17:16:08 +08001607 if ((tmp & 0x80) == 0)
1608 break;
1609 }
1610
1611 for (i = 0; i < 4; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001612 retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp);
1613 if (retval) {
1614 rtsx_trace(chip);
1615 return retval;
1616 }
Micky Chingfa590c22013-11-12 17:16:08 +08001617 data |= (u32)tmp << (i * 8);
1618 }
1619
1620 if (val)
1621 *val = data;
1622
1623 return STATUS_SUCCESS;
1624}
1625
1626int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001627 int len)
Micky Chingfa590c22013-11-12 17:16:08 +08001628{
1629 u32 *data, *mask;
1630 u16 offset = addr % 4;
1631 u16 aligned_addr = addr - offset;
1632 int dw_len, i, j;
1633 int retval;
1634
Joe Perches031366e2015-03-25 12:54:25 -07001635 if (!buf) {
1636 rtsx_trace(chip);
1637 return STATUS_NOMEM;
1638 }
Micky Chingfa590c22013-11-12 17:16:08 +08001639
1640 if ((len + offset) % 4)
1641 dw_len = (len + offset) / 4 + 1;
1642 else
1643 dw_len = (len + offset) / 4;
1644
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001645 dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
Micky Chingfa590c22013-11-12 17:16:08 +08001646
1647 data = vzalloc(dw_len * 4);
Joe Perches031366e2015-03-25 12:54:25 -07001648 if (!data) {
1649 rtsx_trace(chip);
1650 return STATUS_NOMEM;
1651 }
Micky Chingfa590c22013-11-12 17:16:08 +08001652
1653 mask = vzalloc(dw_len * 4);
1654 if (!mask) {
1655 vfree(data);
Joe Perches031366e2015-03-25 12:54:25 -07001656 rtsx_trace(chip);
1657 return STATUS_NOMEM;
Micky Chingfa590c22013-11-12 17:16:08 +08001658 }
1659
1660 j = 0;
1661 for (i = 0; i < len; i++) {
1662 mask[j] |= 0xFF << (offset * 8);
1663 data[j] |= buf[i] << (offset * 8);
1664 if (++offset == 4) {
1665 j++;
1666 offset = 0;
1667 }
1668 }
1669
Fabio Falzoi69b8b222014-08-05 23:24:17 +02001670 print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask,
1671 dw_len * 4);
1672 print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data,
1673 dw_len * 4);
Micky Chingfa590c22013-11-12 17:16:08 +08001674
1675 for (i = 0; i < dw_len; i++) {
1676 retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001677 mask[i], data[i]);
Micky Chingfa590c22013-11-12 17:16:08 +08001678 if (retval != STATUS_SUCCESS) {
1679 vfree(data);
1680 vfree(mask);
Joe Perches031366e2015-03-25 12:54:25 -07001681 rtsx_trace(chip);
1682 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001683 }
1684 }
1685
1686 vfree(data);
1687 vfree(mask);
1688
1689 return STATUS_SUCCESS;
1690}
1691
1692int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001693 int len)
Micky Chingfa590c22013-11-12 17:16:08 +08001694{
1695 u32 *data;
1696 u16 offset = addr % 4;
1697 u16 aligned_addr = addr - offset;
1698 int dw_len, i, j;
1699 int retval;
1700
Micky Chingfa590c22013-11-12 17:16:08 +08001701 if ((len + offset) % 4)
1702 dw_len = (len + offset) / 4 + 1;
1703 else
1704 dw_len = (len + offset) / 4;
1705
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001706 dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
Micky Chingfa590c22013-11-12 17:16:08 +08001707
1708 data = vmalloc(dw_len * 4);
Joe Perches031366e2015-03-25 12:54:25 -07001709 if (!data) {
1710 rtsx_trace(chip);
1711 return STATUS_NOMEM;
1712 }
Micky Chingfa590c22013-11-12 17:16:08 +08001713
1714 for (i = 0; i < dw_len; i++) {
1715 retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001716 data + i);
Micky Chingfa590c22013-11-12 17:16:08 +08001717 if (retval != STATUS_SUCCESS) {
1718 vfree(data);
Joe Perches031366e2015-03-25 12:54:25 -07001719 rtsx_trace(chip);
1720 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001721 }
1722 }
1723
1724 if (buf) {
1725 j = 0;
1726
1727 for (i = 0; i < len; i++) {
1728 buf[i] = (u8)(data[j] >> (offset * 8));
1729 if (++offset == 4) {
1730 j++;
1731 offset = 0;
1732 }
1733 }
1734 }
1735
1736 vfree(data);
1737
1738 return STATUS_SUCCESS;
1739}
1740
1741int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
1742{
Joe Perches8ee775f2015-03-25 12:54:26 -07001743 int retval;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001744 bool finished = false;
1745 int i;
Micky Chingfa590c22013-11-12 17:16:08 +08001746 u8 tmp;
1747
Joe Perches8ee775f2015-03-25 12:54:26 -07001748 retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val);
1749 if (retval) {
1750 rtsx_trace(chip);
1751 return retval;
1752 }
1753 retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
1754 if (retval) {
1755 rtsx_trace(chip);
1756 return retval;
1757 }
1758 retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
1759 if (retval) {
1760 rtsx_trace(chip);
1761 return retval;
1762 }
1763 retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81);
1764 if (retval) {
1765 rtsx_trace(chip);
1766 return retval;
1767 }
Micky Chingfa590c22013-11-12 17:16:08 +08001768
1769 for (i = 0; i < 100000; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001770 retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
1771 if (retval) {
1772 rtsx_trace(chip);
1773 return retval;
1774 }
Micky Chingfa590c22013-11-12 17:16:08 +08001775 if (!(tmp & 0x80)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001776 finished = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001777 break;
1778 }
1779 }
1780
Joe Perches031366e2015-03-25 12:54:25 -07001781 if (!finished) {
1782 rtsx_trace(chip);
1783 return STATUS_FAIL;
1784 }
Micky Chingfa590c22013-11-12 17:16:08 +08001785
1786 return STATUS_SUCCESS;
1787}
1788
1789int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
1790{
Joe Perches8ee775f2015-03-25 12:54:26 -07001791 int retval;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001792 bool finished = false;
1793 int i;
Micky Chingfa590c22013-11-12 17:16:08 +08001794 u16 data = 0;
1795 u8 tmp;
1796
Joe Perches8ee775f2015-03-25 12:54:26 -07001797 retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
1798 if (retval) {
1799 rtsx_trace(chip);
1800 return retval;
1801 }
1802 retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80);
1803 if (retval) {
1804 rtsx_trace(chip);
1805 return retval;
1806 }
Micky Chingfa590c22013-11-12 17:16:08 +08001807
1808 for (i = 0; i < 100000; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001809 retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
1810 if (retval) {
1811 rtsx_trace(chip);
1812 return retval;
1813 }
Micky Chingfa590c22013-11-12 17:16:08 +08001814 if (!(tmp & 0x80)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001815 finished = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001816 break;
1817 }
1818 }
1819
Joe Perches031366e2015-03-25 12:54:25 -07001820 if (!finished) {
1821 rtsx_trace(chip);
1822 return STATUS_FAIL;
1823 }
Micky Chingfa590c22013-11-12 17:16:08 +08001824
Joe Perches8ee775f2015-03-25 12:54:26 -07001825 retval = rtsx_read_register(chip, PHYDATA0, &tmp);
1826 if (retval) {
1827 rtsx_trace(chip);
1828 return retval;
1829 }
Micky Chingfa590c22013-11-12 17:16:08 +08001830 data = tmp;
Joe Perches8ee775f2015-03-25 12:54:26 -07001831 retval = rtsx_read_register(chip, PHYDATA1, &tmp);
1832 if (retval) {
1833 rtsx_trace(chip);
1834 return retval;
1835 }
Micky Chingfa590c22013-11-12 17:16:08 +08001836 data |= (u16)tmp << 8;
1837
1838 if (val)
1839 *val = data;
1840
1841 return STATUS_SUCCESS;
1842}
1843
1844int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
1845{
Joe Perches8ee775f2015-03-25 12:54:26 -07001846 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001847 int i;
1848 u8 data = 0;
1849
Joe Perches8ee775f2015-03-25 12:54:26 -07001850 retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr);
1851 if (retval) {
1852 rtsx_trace(chip);
1853 return retval;
1854 }
Micky Chingfa590c22013-11-12 17:16:08 +08001855
1856 for (i = 0; i < 100; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001857 retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
1858 if (retval) {
1859 rtsx_trace(chip);
1860 return retval;
1861 }
Micky Chingfa590c22013-11-12 17:16:08 +08001862 if (!(data & 0x80))
1863 break;
1864 udelay(1);
1865 }
1866
Joe Perches031366e2015-03-25 12:54:25 -07001867 if (data & 0x80) {
1868 rtsx_trace(chip);
1869 return STATUS_TIMEDOUT;
1870 }
Micky Chingfa590c22013-11-12 17:16:08 +08001871
Joe Perches8ee775f2015-03-25 12:54:26 -07001872 retval = rtsx_read_register(chip, EFUSE_DATA, &data);
1873 if (retval) {
1874 rtsx_trace(chip);
1875 return retval;
1876 }
Micky Chingfa590c22013-11-12 17:16:08 +08001877 if (val)
1878 *val = data;
1879
1880 return STATUS_SUCCESS;
1881}
1882
1883int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
1884{
Joe Perches8ee775f2015-03-25 12:54:26 -07001885 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001886 int i, j;
1887 u8 data = 0, tmp = 0xFF;
1888
1889 for (i = 0; i < 8; i++) {
1890 if (val & (u8)(1 << i))
1891 continue;
1892
1893 tmp &= (~(u8)(1 << i));
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001894 dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr);
Micky Chingfa590c22013-11-12 17:16:08 +08001895
Joe Perches8ee775f2015-03-25 12:54:26 -07001896 retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp);
1897 if (retval) {
1898 rtsx_trace(chip);
1899 return retval;
1900 }
1901 retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF,
1902 0xA0 | addr);
1903 if (retval) {
1904 rtsx_trace(chip);
1905 return retval;
1906 }
Micky Chingfa590c22013-11-12 17:16:08 +08001907
1908 for (j = 0; j < 100; j++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001909 retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
1910 if (retval) {
1911 rtsx_trace(chip);
1912 return retval;
1913 }
Micky Chingfa590c22013-11-12 17:16:08 +08001914 if (!(data & 0x80))
1915 break;
1916 wait_timeout(3);
1917 }
1918
Joe Perches031366e2015-03-25 12:54:25 -07001919 if (data & 0x80) {
1920 rtsx_trace(chip);
1921 return STATUS_TIMEDOUT;
1922 }
Micky Chingfa590c22013-11-12 17:16:08 +08001923
1924 wait_timeout(5);
1925 }
1926
1927 return STATUS_SUCCESS;
1928}
1929
1930int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
1931{
1932 int retval;
1933 u16 value;
1934
1935 retval = rtsx_read_phy_register(chip, reg, &value);
Joe Perches031366e2015-03-25 12:54:25 -07001936 if (retval != STATUS_SUCCESS) {
1937 rtsx_trace(chip);
1938 return STATUS_FAIL;
1939 }
Micky Chingfa590c22013-11-12 17:16:08 +08001940
1941 if (value & (1 << bit)) {
1942 value &= ~(1 << bit);
1943 retval = rtsx_write_phy_register(chip, reg, value);
Joe Perches031366e2015-03-25 12:54:25 -07001944 if (retval != STATUS_SUCCESS) {
1945 rtsx_trace(chip);
1946 return STATUS_FAIL;
1947 }
Micky Chingfa590c22013-11-12 17:16:08 +08001948 }
1949
1950 return STATUS_SUCCESS;
1951}
1952
1953int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
1954{
1955 int retval;
1956 u16 value;
1957
1958 retval = rtsx_read_phy_register(chip, reg, &value);
Joe Perches031366e2015-03-25 12:54:25 -07001959 if (retval != STATUS_SUCCESS) {
1960 rtsx_trace(chip);
1961 return STATUS_FAIL;
1962 }
Micky Chingfa590c22013-11-12 17:16:08 +08001963
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03001964 if ((value & (1 << bit)) == 0) {
Micky Chingfa590c22013-11-12 17:16:08 +08001965 value |= (1 << bit);
1966 retval = rtsx_write_phy_register(chip, reg, value);
Joe Perches031366e2015-03-25 12:54:25 -07001967 if (retval != STATUS_SUCCESS) {
1968 rtsx_trace(chip);
1969 return STATUS_FAIL;
1970 }
Micky Chingfa590c22013-11-12 17:16:08 +08001971 }
1972
1973 return STATUS_SUCCESS;
1974}
1975
1976int rtsx_check_link_ready(struct rtsx_chip *chip)
1977{
Joe Perches8ee775f2015-03-25 12:54:26 -07001978 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001979 u8 val;
1980
Joe Perches8ee775f2015-03-25 12:54:26 -07001981 retval = rtsx_read_register(chip, IRQSTAT0, &val);
1982 if (retval) {
1983 rtsx_trace(chip);
1984 return retval;
1985 }
Micky Chingfa590c22013-11-12 17:16:08 +08001986
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001987 dev_dbg(rtsx_dev(chip), "IRQSTAT0: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +08001988 if (val & LINK_RDY_INT) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001989 dev_dbg(rtsx_dev(chip), "Delinked!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08001990 rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
1991 return STATUS_FAIL;
1992 }
1993
1994 return STATUS_SUCCESS;
1995}
1996
1997static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
1998{
1999 u32 ultmp;
2000
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002001 dev_dbg(rtsx_dev(chip), "%04x set pm_dstate to %d\n",
2002 chip->product_id, dstate);
Micky Chingfa590c22013-11-12 17:16:08 +08002003
2004 if (CHK_SDIO_EXIST(chip)) {
2005 u8 func_no;
2006
2007 if (CHECK_PID(chip, 0x5288))
2008 func_no = 2;
2009 else
2010 func_no = 1;
2011
2012 rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002013 dev_dbg(rtsx_dev(chip), "pm_dstate of function %d: 0x%x\n",
2014 (int)func_no, ultmp);
Micky Chingfa590c22013-11-12 17:16:08 +08002015 rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
2016 }
2017
2018 rtsx_write_config_byte(chip, 0x44, dstate);
2019 rtsx_write_config_byte(chip, 0x45, 0);
2020}
2021
2022void rtsx_enter_L1(struct rtsx_chip *chip)
2023{
2024 rtsx_handle_pm_dstate(chip, 2);
2025}
2026
2027void rtsx_exit_L1(struct rtsx_chip *chip)
2028{
2029 rtsx_write_config_byte(chip, 0x44, 0);
2030 rtsx_write_config_byte(chip, 0x45, 0);
2031}
2032
2033void rtsx_enter_ss(struct rtsx_chip *chip)
2034{
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002035 dev_dbg(rtsx_dev(chip), "Enter Selective Suspend State!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002036
2037 rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
2038
2039 if (chip->power_down_in_ss) {
2040 rtsx_power_off_card(chip);
2041 rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
2042 }
2043
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03002044 if (CHK_SDIO_EXIST(chip))
2045 rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
2046 0xC0, 0xFF00, 0x0100);
Micky Chingfa590c22013-11-12 17:16:08 +08002047
2048 if (chip->auto_delink_en) {
2049 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
2050 } else {
2051 if (!chip->phy_debug_mode) {
2052 u32 tmp;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05302053
Micky Chingfa590c22013-11-12 17:16:08 +08002054 tmp = rtsx_readl(chip, RTSX_BIER);
2055 tmp |= CARD_INT;
2056 rtsx_writel(chip, RTSX_BIER, tmp);
2057 }
2058
2059 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
2060 }
2061
2062 rtsx_enter_L1(chip);
2063
2064 RTSX_CLR_DELINK(chip);
2065 rtsx_set_stat(chip, RTSX_STAT_SS);
2066}
2067
2068void rtsx_exit_ss(struct rtsx_chip *chip)
2069{
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002070 dev_dbg(rtsx_dev(chip), "Exit Selective Suspend State!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002071
2072 rtsx_exit_L1(chip);
2073
2074 if (chip->power_down_in_ss) {
2075 rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
2076 udelay(1000);
2077 }
2078
2079 if (RTSX_TST_DELINK(chip)) {
2080 chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
2081 rtsx_reinit_cards(chip, 1);
2082 RTSX_CLR_DELINK(chip);
2083 } else if (chip->power_down_in_ss) {
2084 chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
2085 rtsx_reinit_cards(chip, 0);
2086 }
2087}
2088
2089int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
2090{
2091 u32 status, int_enable;
Quentin Lambertde904bf2015-03-04 11:31:01 +01002092 bool exit_ss = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002093#ifdef SUPPORT_OCP
2094 u32 ocp_int = 0;
2095
2096 ocp_int = OC_INT;
2097#endif
2098
2099 if (chip->ss_en) {
2100 chip->ss_counter = 0;
2101 if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01002102 exit_ss = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002103 rtsx_exit_L1(chip);
2104 rtsx_set_stat(chip, RTSX_STAT_RUN);
2105 }
2106 }
2107
2108 int_enable = rtsx_readl(chip, RTSX_BIER);
2109 chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
2110
2111 if (((chip->int_reg & int_enable) == 0) ||
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002112 (chip->int_reg == 0xFFFFFFFF))
Micky Chingfa590c22013-11-12 17:16:08 +08002113 return STATUS_FAIL;
2114
2115 status = chip->int_reg &= (int_enable | 0x7FFFFF);
2116
2117 if (status & CARD_INT) {
2118 chip->auto_delink_cnt = 0;
2119
2120 if (status & SD_INT) {
2121 if (status & SD_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002122 set_bit(SD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002123 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002124 set_bit(SD_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002125 chip->sd_reset_counter = 0;
2126 chip->sd_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002127 clear_bit(SD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002128 }
2129 } else {
2130 /* If multi-luns, it's possible that
2131 when plugging/unplugging one card
2132 there is another card which still
2133 exists in the slot. In this case,
2134 all existed cards should be reset.
2135 */
2136 if (exit_ss && (status & SD_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002137 set_bit(SD_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002138 }
2139 if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
2140 if (status & XD_INT) {
2141 if (status & XD_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002142 set_bit(XD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002143 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002144 set_bit(XD_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002145 chip->xd_reset_counter = 0;
2146 chip->xd_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002147 clear_bit(XD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002148 }
2149 } else {
2150 if (exit_ss && (status & XD_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002151 set_bit(XD_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002152 }
2153 }
2154 if (status & MS_INT) {
2155 if (status & MS_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002156 set_bit(MS_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002157 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002158 set_bit(MS_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002159 chip->ms_reset_counter = 0;
2160 chip->ms_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002161 clear_bit(MS_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002162 }
2163 } else {
2164 if (exit_ss && (status & MS_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002165 set_bit(MS_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002166 }
2167 }
2168
2169#ifdef SUPPORT_OCP
2170 chip->ocp_int = ocp_int & status;
2171#endif
2172
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002173 if (chip->sd_io && (chip->int_reg & DATA_DONE_INT))
2174 chip->int_reg &= ~(u32)DATA_DONE_INT;
Micky Chingfa590c22013-11-12 17:16:08 +08002175
2176 return STATUS_SUCCESS;
2177}
2178
2179void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
2180{
2181 int retval;
2182
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002183 dev_dbg(rtsx_dev(chip), "%s, pm_stat = %d\n", __func__, pm_stat);
Micky Chingfa590c22013-11-12 17:16:08 +08002184
2185 rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
2186
2187 retval = rtsx_force_power_on(chip, SSC_PDCTL);
2188 if (retval != STATUS_SUCCESS)
2189 return;
2190
2191 rtsx_release_cards(chip);
2192 rtsx_disable_bus_int(chip);
2193 turn_off_led(chip, LED_GPIO);
2194
2195#ifdef HW_AUTO_SWITCH_SD_BUS
2196 if (chip->sd_io) {
2197 chip->sdio_in_charge = 1;
2198 if (CHECK_PID(chip, 0x5208)) {
2199 rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
2200 /* Enable sdio_bus_auto_switch */
2201 rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
2202 } else if (CHECK_PID(chip, 0x5288)) {
2203 rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
2204 /* Enable sdio_bus_auto_switch */
2205 rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
2206 }
2207 }
2208#endif
2209
2210 if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
2211 /* u_force_clkreq_0 */
2212 rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
2213 }
2214
2215 if (pm_stat == PM_S1) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002216 dev_dbg(rtsx_dev(chip), "Host enter S1\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002217 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002218 HOST_ENTER_S1);
Micky Chingfa590c22013-11-12 17:16:08 +08002219 } else if (pm_stat == PM_S3) {
2220 if (chip->s3_pwr_off_delay > 0)
2221 wait_timeout(chip->s3_pwr_off_delay);
2222
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002223 dev_dbg(rtsx_dev(chip), "Host enter S3\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002224 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002225 HOST_ENTER_S3);
Micky Chingfa590c22013-11-12 17:16:08 +08002226 }
2227
2228 if (chip->do_delink_before_power_down && chip->auto_delink_en)
2229 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
2230
2231 rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
2232
2233 chip->cur_clk = 0;
2234 chip->cur_card = 0;
2235 chip->card_exist = 0;
2236}
2237
2238void rtsx_enable_aspm(struct rtsx_chip *chip)
2239{
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002240 if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && !chip->aspm_enabled) {
2241 dev_dbg(rtsx_dev(chip), "Try to enable ASPM\n");
2242 chip->aspm_enabled = 1;
Micky Chingfa590c22013-11-12 17:16:08 +08002243
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002244 if (chip->asic_code && CHECK_PID(chip, 0x5208))
2245 rtsx_write_phy_register(chip, 0x07, 0);
2246 if (CHECK_PID(chip, 0x5208)) {
2247 rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002248 0x30 | chip->aspm_level[0]);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002249 } else {
2250 rtsx_write_config_byte(chip, LCTLR,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002251 chip->aspm_l0s_l1_en);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002252 }
Micky Chingfa590c22013-11-12 17:16:08 +08002253
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002254 if (CHK_SDIO_EXIST(chip)) {
2255 u16 val = chip->aspm_l0s_l1_en | 0x0100;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05302256
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03002257 rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
2258 0xC0, 0xFFF, val);
Micky Chingfa590c22013-11-12 17:16:08 +08002259 }
2260 }
Micky Chingfa590c22013-11-12 17:16:08 +08002261}
2262
2263void rtsx_disable_aspm(struct rtsx_chip *chip)
2264{
2265 if (CHECK_PID(chip, 0x5208))
2266 rtsx_monitor_aspm_config(chip);
2267
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002268 if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && chip->aspm_enabled) {
2269 dev_dbg(rtsx_dev(chip), "Try to disable ASPM\n");
2270 chip->aspm_enabled = 0;
Micky Chingfa590c22013-11-12 17:16:08 +08002271
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002272 if (chip->asic_code && CHECK_PID(chip, 0x5208))
2273 rtsx_write_phy_register(chip, 0x07, 0x0129);
2274 if (CHECK_PID(chip, 0x5208))
2275 rtsx_write_register(chip, ASPM_FORCE_CTL,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002276 0xF3, 0x30);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002277 else
2278 rtsx_write_config_byte(chip, LCTLR, 0x00);
Micky Chingfa590c22013-11-12 17:16:08 +08002279
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002280 wait_timeout(1);
Micky Chingfa590c22013-11-12 17:16:08 +08002281 }
Micky Chingfa590c22013-11-12 17:16:08 +08002282}
2283
2284int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
2285{
2286 int retval;
2287 int i, j;
2288 u16 reg_addr;
2289 u8 *ptr;
2290
Joe Perches031366e2015-03-25 12:54:25 -07002291 if (!buf) {
2292 rtsx_trace(chip);
2293 return STATUS_ERROR;
2294 }
Micky Chingfa590c22013-11-12 17:16:08 +08002295
2296 ptr = buf;
2297 reg_addr = PPBUF_BASE2;
2298 for (i = 0; i < buf_len/256; i++) {
2299 rtsx_init_cmd(chip);
2300
2301 for (j = 0; j < 256; j++)
2302 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
2303
2304 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002305 if (retval < 0) {
2306 rtsx_trace(chip);
2307 return STATUS_FAIL;
2308 }
Micky Chingfa590c22013-11-12 17:16:08 +08002309
2310 memcpy(ptr, rtsx_get_cmd_data(chip), 256);
2311 ptr += 256;
2312 }
2313
2314 if (buf_len%256) {
2315 rtsx_init_cmd(chip);
2316
2317 for (j = 0; j < buf_len%256; j++)
2318 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
2319
2320 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002321 if (retval < 0) {
2322 rtsx_trace(chip);
2323 return STATUS_FAIL;
2324 }
Micky Chingfa590c22013-11-12 17:16:08 +08002325 }
2326
2327 memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256);
2328
2329 return STATUS_SUCCESS;
2330}
2331
2332int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
2333{
2334 int retval;
2335 int i, j;
2336 u16 reg_addr;
2337 u8 *ptr;
2338
Joe Perches031366e2015-03-25 12:54:25 -07002339 if (!buf) {
2340 rtsx_trace(chip);
2341 return STATUS_ERROR;
2342 }
Micky Chingfa590c22013-11-12 17:16:08 +08002343
2344 ptr = buf;
2345 reg_addr = PPBUF_BASE2;
2346 for (i = 0; i < buf_len/256; i++) {
2347 rtsx_init_cmd(chip);
2348
2349 for (j = 0; j < 256; j++) {
2350 rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002351 *ptr);
Micky Chingfa590c22013-11-12 17:16:08 +08002352 ptr++;
2353 }
2354
2355 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002356 if (retval < 0) {
2357 rtsx_trace(chip);
2358 return STATUS_FAIL;
2359 }
Micky Chingfa590c22013-11-12 17:16:08 +08002360 }
2361
2362 if (buf_len%256) {
2363 rtsx_init_cmd(chip);
2364
2365 for (j = 0; j < buf_len%256; j++) {
2366 rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002367 *ptr);
Micky Chingfa590c22013-11-12 17:16:08 +08002368 ptr++;
2369 }
2370
2371 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002372 if (retval < 0) {
2373 rtsx_trace(chip);
2374 return STATUS_FAIL;
2375 }
Micky Chingfa590c22013-11-12 17:16:08 +08002376 }
2377
2378 return STATUS_SUCCESS;
2379}
2380
2381int rtsx_check_chip_exist(struct rtsx_chip *chip)
2382{
Joe Perches031366e2015-03-25 12:54:25 -07002383 if (rtsx_readl(chip, 0) == 0xFFFFFFFF) {
2384 rtsx_trace(chip);
2385 return STATUS_FAIL;
2386 }
Micky Chingfa590c22013-11-12 17:16:08 +08002387
2388 return STATUS_SUCCESS;
2389}
2390
2391int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
2392{
2393 int retval;
2394 u8 mask = 0;
2395
2396 if (ctl & SSC_PDCTL)
2397 mask |= SSC_POWER_DOWN;
2398
2399#ifdef SUPPORT_OCP
2400 if (ctl & OC_PDCTL) {
2401 mask |= SD_OC_POWER_DOWN;
2402 if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
2403 mask |= MS_OC_POWER_DOWN;
2404 }
2405#endif
2406
2407 if (mask) {
2408 retval = rtsx_write_register(chip, FPDCTL, mask, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002409 if (retval != STATUS_SUCCESS) {
2410 rtsx_trace(chip);
2411 return STATUS_FAIL;
2412 }
Micky Chingfa590c22013-11-12 17:16:08 +08002413
2414 if (CHECK_PID(chip, 0x5288))
2415 wait_timeout(200);
2416 }
2417
2418 return STATUS_SUCCESS;
2419}
2420
2421int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
2422{
2423 int retval;
2424 u8 mask = 0, val = 0;
2425
2426 if (ctl & SSC_PDCTL)
2427 mask |= SSC_POWER_DOWN;
2428
2429#ifdef SUPPORT_OCP
2430 if (ctl & OC_PDCTL) {
2431 mask |= SD_OC_POWER_DOWN;
2432 if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
2433 mask |= MS_OC_POWER_DOWN;
2434 }
2435#endif
2436
2437 if (mask) {
2438 val = mask;
2439 retval = rtsx_write_register(chip, FPDCTL, mask, val);
Joe Perches031366e2015-03-25 12:54:25 -07002440 if (retval != STATUS_SUCCESS) {
2441 rtsx_trace(chip);
2442 return STATUS_FAIL;
2443 }
Micky Chingfa590c22013-11-12 17:16:08 +08002444 }
2445
2446 return STATUS_SUCCESS;
2447}