blob: c0ce659a5aa6716c937bd2e17688e27c33c41293 [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
Punit Vara60d6a212015-09-21 21:59:41 +0530524 /*
525 * Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
526 * 0xFE5B
527 * bit[1] u_cd_rst_core_en rst_value = 0
528 * bit[2] u_force_rst_core_en rst_value = 0
529 * bit[5] u_mac_phy_rst_n_dbg rst_value = 1
530 * bit[4] u_non_sticky_rst_n_dbg rst_value = 0
531 */
Joe Perches8ee775f2015-03-25 12:54:26 -0700532 retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10);
533 if (retval) {
534 rtsx_trace(chip);
535 return retval;
536 }
Micky Chingfa590c22013-11-12 17:16:08 +0800537
538 /* Enable ASPM */
539 if (chip->aspm_l0s_l1_en) {
Fabio Falzoi5d069c82014-10-19 21:30:02 +0200540 retval = rtsx_reset_aspm(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700541 if (retval != STATUS_SUCCESS) {
542 rtsx_trace(chip);
543 return STATUS_FAIL;
544 }
Micky Chingfa590c22013-11-12 17:16:08 +0800545 } else {
546 if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
547 retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
Joe Perches031366e2015-03-25 12:54:25 -0700548 if (retval != STATUS_SUCCESS) {
549 rtsx_trace(chip);
550 return STATUS_FAIL;
551 }
Micky Chingfa590c22013-11-12 17:16:08 +0800552 }
553 retval = rtsx_write_config_byte(chip, LCTLR,
554 chip->aspm_l0s_l1_en);
Joe Perches031366e2015-03-25 12:54:25 -0700555 if (retval != STATUS_SUCCESS) {
556 rtsx_trace(chip);
557 return STATUS_FAIL;
558 }
Micky Chingfa590c22013-11-12 17:16:08 +0800559 }
560
561 retval = rtsx_write_config_byte(chip, 0x81, 1);
Joe Perches031366e2015-03-25 12:54:25 -0700562 if (retval != STATUS_SUCCESS) {
563 rtsx_trace(chip);
564 return STATUS_FAIL;
565 }
Micky Chingfa590c22013-11-12 17:16:08 +0800566
567 if (CHK_SDIO_EXIST(chip)) {
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300568 retval = rtsx_write_cfg_dw(chip,
569 CHECK_PID(chip, 0x5288) ? 2 : 1,
570 0xC0, 0xFF00, 0x0100);
Micky Chingfa590c22013-11-12 17:16:08 +0800571
Joe Perches031366e2015-03-25 12:54:25 -0700572 if (retval != STATUS_SUCCESS) {
573 rtsx_trace(chip);
574 return STATUS_FAIL;
575 }
Micky Chingfa590c22013-11-12 17:16:08 +0800576 }
577
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +0300578 if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) {
579 retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
Joe Perches031366e2015-03-25 12:54:25 -0700580 if (retval != STATUS_SUCCESS) {
581 rtsx_trace(chip);
582 return STATUS_FAIL;
583 }
Micky Chingfa590c22013-11-12 17:16:08 +0800584
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +0300585 retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
Joe Perches031366e2015-03-25 12:54:25 -0700586 if (retval != STATUS_SUCCESS) {
587 rtsx_trace(chip);
588 return STATUS_FAIL;
589 }
Micky Chingfa590c22013-11-12 17:16:08 +0800590 }
591
Joe Perches8ee775f2015-03-25 12:54:26 -0700592 retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT,
593 LINK_RDY_INT);
594 if (retval) {
595 rtsx_trace(chip);
596 return retval;
597 }
Micky Chingfa590c22013-11-12 17:16:08 +0800598
Joe Perches8ee775f2015-03-25 12:54:26 -0700599 retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
600 if (retval) {
601 rtsx_trace(chip);
602 return retval;
603 }
Micky Chingfa590c22013-11-12 17:16:08 +0800604
Fabio Falzoi506fe172014-10-19 21:30:03 +0200605 retval = rtsx_enable_pcie_intr(chip);
Joe Perches031366e2015-03-25 12:54:25 -0700606 if (retval != STATUS_SUCCESS) {
607 rtsx_trace(chip);
608 return STATUS_FAIL;
609 }
Micky Chingfa590c22013-11-12 17:16:08 +0800610
611 chip->need_reset = 0;
612
613 chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
614
615 if (chip->hw_bypass_sd)
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300616 goto nextcard;
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200617 dev_dbg(rtsx_dev(chip), "In %s, chip->int_reg = 0x%x\n", __func__,
Micky Chingfa590c22013-11-12 17:16:08 +0800618 chip->int_reg);
619 if (chip->int_reg & SD_EXIST) {
620#ifdef HW_AUTO_SWITCH_SD_BUS
621 if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C))
622 retval = rtsx_pre_handle_sdio_old(chip);
623 else
624 retval = rtsx_pre_handle_sdio_new(chip);
625
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200626 dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x (rtsx_reset_chip)\n",
Micky Chingfa590c22013-11-12 17:16:08 +0800627 (unsigned int)(chip->need_reset));
628#else /* HW_AUTO_SWITCH_SD_BUS */
629 retval = rtsx_pre_handle_sdio_old(chip);
630#endif /* HW_AUTO_SWITCH_SD_BUS */
Joe Perches031366e2015-03-25 12:54:25 -0700631 if (retval != STATUS_SUCCESS) {
632 rtsx_trace(chip);
633 return STATUS_FAIL;
634 }
Micky Chingfa590c22013-11-12 17:16:08 +0800635
636 } else {
637 chip->sd_io = 0;
Joe Perches8ee775f2015-03-25 12:54:26 -0700638 retval = rtsx_write_register(chip, SDIO_CTRL,
639 SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
640 if (retval) {
641 rtsx_trace(chip);
642 return retval;
643 }
Micky Chingfa590c22013-11-12 17:16:08 +0800644 }
645
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300646nextcard:
Micky Chingfa590c22013-11-12 17:16:08 +0800647 if (chip->int_reg & XD_EXIST)
648 chip->need_reset |= XD_CARD;
649 if (chip->int_reg & MS_EXIST)
650 chip->need_reset |= MS_CARD;
Joe Perches8ee775f2015-03-25 12:54:26 -0700651 if (chip->int_reg & CARD_EXIST) {
652 retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB,
653 SSC_RSTB);
654 if (retval) {
655 rtsx_trace(chip);
656 return retval;
657 }
658 }
Micky Chingfa590c22013-11-12 17:16:08 +0800659
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200660 dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__,
Micky Chingfa590c22013-11-12 17:16:08 +0800661 (unsigned int)(chip->need_reset));
662
Joe Perches8ee775f2015-03-25 12:54:26 -0700663 retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00);
664 if (retval) {
665 rtsx_trace(chip);
666 return retval;
667 }
Micky Chingfa590c22013-11-12 17:16:08 +0800668
669 if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
670 /* Turn off main power when entering S3/S4 state */
Joe Perches8ee775f2015-03-25 12:54:26 -0700671 retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03,
672 0x03);
673 if (retval) {
674 rtsx_trace(chip);
675 return retval;
676 }
Micky Chingfa590c22013-11-12 17:16:08 +0800677 }
678
679 if (chip->remote_wakeup_en && !chip->auto_delink_en) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700680 retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07);
681 if (retval) {
682 rtsx_trace(chip);
683 return retval;
684 }
685 if (chip->aux_pwr_exist) {
686 retval = rtsx_write_register(chip, PME_FORCE_CTL,
687 0xFF, 0x33);
688 if (retval) {
689 rtsx_trace(chip);
690 return retval;
691 }
692 }
Micky Chingfa590c22013-11-12 17:16:08 +0800693 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700694 retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04);
695 if (retval) {
696 rtsx_trace(chip);
697 return retval;
698 }
699 retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30);
700 if (retval) {
701 rtsx_trace(chip);
702 return retval;
703 }
Micky Chingfa590c22013-11-12 17:16:08 +0800704 }
705
Joe Perches8ee775f2015-03-25 12:54:26 -0700706 if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
707 retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14);
708 if (retval) {
709 rtsx_trace(chip);
710 return retval;
711 }
712 }
Micky Chingfa590c22013-11-12 17:16:08 +0800713
714 if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
715 retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
Joe Perches031366e2015-03-25 12:54:25 -0700716 if (retval != STATUS_SUCCESS) {
717 rtsx_trace(chip);
718 return STATUS_FAIL;
719 }
Micky Chingfa590c22013-11-12 17:16:08 +0800720 }
721
722 if (chip->ft2_fast_mode) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700723 retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
724 MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
725 if (retval) {
726 rtsx_trace(chip);
727 return retval;
728 }
Micky Chingfa590c22013-11-12 17:16:08 +0800729 udelay(chip->pmos_pwr_on_interval);
Joe Perches8ee775f2015-03-25 12:54:26 -0700730 retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
731 MS_POWER_ON | SD_POWER_ON);
732 if (retval) {
733 rtsx_trace(chip);
734 return retval;
735 }
Micky Chingfa590c22013-11-12 17:16:08 +0800736
737 wait_timeout(200);
738 }
739
740 /* Reset card */
741 rtsx_reset_detected_cards(chip, 0);
742
743 chip->driver_first_load = 0;
744
745 return STATUS_SUCCESS;
746}
747
748static inline int check_sd_speed_prior(u32 sd_speed_prior)
749{
Quentin Lambertde904bf2015-03-04 11:31:01 +0100750 bool fake_para = false;
751 int i;
Micky Chingfa590c22013-11-12 17:16:08 +0800752
753 for (i = 0; i < 4; i++) {
754 u8 tmp = (u8)(sd_speed_prior >> (i*8));
Mahati Chamarthy0be0b272014-09-25 02:53:54 +0530755
Micky Chingfa590c22013-11-12 17:16:08 +0800756 if ((tmp < 0x01) || (tmp > 0x04)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +0100757 fake_para = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800758 break;
759 }
760 }
761
762 return !fake_para;
763}
764
765static inline int check_sd_current_prior(u32 sd_current_prior)
766{
Quentin Lambertde904bf2015-03-04 11:31:01 +0100767 bool fake_para = false;
768 int i;
Micky Chingfa590c22013-11-12 17:16:08 +0800769
770 for (i = 0; i < 4; i++) {
771 u8 tmp = (u8)(sd_current_prior >> (i*8));
Mahati Chamarthy0be0b272014-09-25 02:53:54 +0530772
Micky Chingfa590c22013-11-12 17:16:08 +0800773 if (tmp > 0x03) {
Quentin Lambertde904bf2015-03-04 11:31:01 +0100774 fake_para = true;
Micky Chingfa590c22013-11-12 17:16:08 +0800775 break;
776 }
777 }
778
779 return !fake_para;
780}
781
782static int rts5208_init(struct rtsx_chip *chip)
783{
784 int retval;
785 u16 reg = 0;
786 u8 val = 0;
787
Joe Perches8ee775f2015-03-25 12:54:26 -0700788 retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
789 if (retval) {
790 rtsx_trace(chip);
791 return retval;
792 }
793 retval = rtsx_read_register(chip, CLK_SEL, &val);
794 if (retval) {
795 rtsx_trace(chip);
796 return retval;
797 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300798 chip->asic_code = val == 0 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800799
800 if (chip->asic_code) {
801 retval = rtsx_read_phy_register(chip, 0x1C, &reg);
Joe Perches031366e2015-03-25 12:54:25 -0700802 if (retval != STATUS_SUCCESS) {
803 rtsx_trace(chip);
804 return STATUS_FAIL;
805 }
Micky Chingfa590c22013-11-12 17:16:08 +0800806
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200807 dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n",
808 reg);
Micky Chingfa590c22013-11-12 17:16:08 +0800809 chip->ic_version = (reg >> 4) & 0x07;
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300810 chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800811
812 } else {
Joe Perches8ee775f2015-03-25 12:54:26 -0700813 retval = rtsx_read_register(chip, 0xFE80, &val);
814 if (retval) {
815 rtsx_trace(chip);
816 return retval;
817 }
Micky Chingfa590c22013-11-12 17:16:08 +0800818 chip->ic_version = val;
819 chip->phy_debug_mode = 0;
820 }
821
Joe Perches8ee775f2015-03-25 12:54:26 -0700822 retval = rtsx_read_register(chip, PDINFO, &val);
823 if (retval) {
824 rtsx_trace(chip);
825 return retval;
826 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200827 dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300828 chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800829
Joe Perches8ee775f2015-03-25 12:54:26 -0700830 retval = rtsx_read_register(chip, 0xFE50, &val);
831 if (retval) {
832 rtsx_trace(chip);
833 return retval;
834 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300835 chip->hw_bypass_sd = val & 0x01 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800836
837 rtsx_read_config_byte(chip, 0x0E, &val);
838 if (val & 0x80)
839 SET_SDIO_EXIST(chip);
840 else
841 CLR_SDIO_EXIST(chip);
842
843 if (chip->use_hw_setting) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700844 retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
845 if (retval) {
846 rtsx_trace(chip);
847 return retval;
848 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300849 chip->auto_delink_en = val & 0x80 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800850 }
851
852 return STATUS_SUCCESS;
853}
854
855static int rts5288_init(struct rtsx_chip *chip)
856{
857 int retval;
858 u8 val = 0, max_func;
859 u32 lval = 0;
860
Joe Perches8ee775f2015-03-25 12:54:26 -0700861 retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
862 if (retval) {
863 rtsx_trace(chip);
864 return retval;
865 }
866 retval = rtsx_read_register(chip, CLK_SEL, &val);
867 if (retval) {
868 rtsx_trace(chip);
869 return retval;
870 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300871 chip->asic_code = val == 0 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800872
873 chip->ic_version = 0;
874 chip->phy_debug_mode = 0;
875
Joe Perches8ee775f2015-03-25 12:54:26 -0700876 retval = rtsx_read_register(chip, PDINFO, &val);
877 if (retval) {
878 rtsx_trace(chip);
879 return retval;
880 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200881 dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300882 chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800883
Joe Perches8ee775f2015-03-25 12:54:26 -0700884 retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val);
885 if (retval) {
886 rtsx_trace(chip);
887 return retval;
888 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200889 dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val);
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300890 chip->baro_pkg = val & 0x04 ? QFN : LQFP;
Micky Chingfa590c22013-11-12 17:16:08 +0800891
Joe Perches8ee775f2015-03-25 12:54:26 -0700892 retval = rtsx_read_register(chip, 0xFE5A, &val);
893 if (retval) {
894 rtsx_trace(chip);
895 return retval;
896 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300897 chip->hw_bypass_sd = val & 0x10 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800898
899 retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
Joe Perches031366e2015-03-25 12:54:25 -0700900 if (retval != STATUS_SUCCESS) {
901 rtsx_trace(chip);
902 return STATUS_FAIL;
903 }
Micky Chingfa590c22013-11-12 17:16:08 +0800904
905 max_func = (u8)((lval >> 29) & 0x07);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200906 dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func);
Micky Chingfa590c22013-11-12 17:16:08 +0800907 if (max_func == 0x02)
908 SET_SDIO_EXIST(chip);
909 else
910 CLR_SDIO_EXIST(chip);
911
912 if (chip->use_hw_setting) {
Joe Perches8ee775f2015-03-25 12:54:26 -0700913 retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
914 if (retval) {
915 rtsx_trace(chip);
916 return retval;
917 }
Giedrius Statkevičius609fc152014-10-04 00:31:21 +0300918 chip->auto_delink_en = val & 0x80 ? 1 : 0;
Micky Chingfa590c22013-11-12 17:16:08 +0800919
920 if (CHECK_BARO_PKG(chip, LQFP))
921 chip->lun_mode = SD_MS_1LUN;
922 else
923 chip->lun_mode = DEFAULT_SINGLE;
Micky Chingfa590c22013-11-12 17:16:08 +0800924 }
925
926 return STATUS_SUCCESS;
927}
928
929int rtsx_init_chip(struct rtsx_chip *chip)
930{
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +0300931 struct sd_info *sd_card = &chip->sd_card;
932 struct xd_info *xd_card = &chip->xd_card;
933 struct ms_info *ms_card = &chip->ms_card;
Micky Chingfa590c22013-11-12 17:16:08 +0800934 int retval;
935 unsigned int i;
936
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200937 dev_dbg(rtsx_dev(chip), "Vendor ID: 0x%04x, Product ID: 0x%04x\n",
938 chip->vendor_id, chip->product_id);
Micky Chingfa590c22013-11-12 17:16:08 +0800939
940 chip->ic_version = 0;
941
942#ifdef _MSG_TRACE
943 chip->msg_idx = 0;
944#endif
945
946 memset(xd_card, 0, sizeof(struct xd_info));
947 memset(sd_card, 0, sizeof(struct sd_info));
948 memset(ms_card, 0, sizeof(struct ms_info));
949
950 chip->xd_reset_counter = 0;
951 chip->sd_reset_counter = 0;
952 chip->ms_reset_counter = 0;
953
954 chip->xd_show_cnt = MAX_SHOW_CNT;
955 chip->sd_show_cnt = MAX_SHOW_CNT;
956 chip->ms_show_cnt = MAX_SHOW_CNT;
957
958 chip->sd_io = 0;
959 chip->auto_delink_cnt = 0;
960 chip->auto_delink_allowed = 1;
961 rtsx_set_stat(chip, RTSX_STAT_INIT);
962
963 chip->aspm_enabled = 0;
964 chip->chip_insert_with_sdio = 0;
965 chip->sdio_aspm = 0;
966 chip->sdio_idle = 0;
967 chip->sdio_counter = 0;
968 chip->cur_card = 0;
969 chip->phy_debug_mode = 0;
970 chip->sdio_func_exist = 0;
971 memset(chip->sdio_raw_data, 0, 12);
972
973 for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
974 set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
975 chip->rw_fail_cnt[i] = 0;
976 }
977
978 if (!check_sd_speed_prior(chip->sd_speed_prior))
979 chip->sd_speed_prior = 0x01040203;
980
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200981 dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n",
982 chip->sd_speed_prior);
Micky Chingfa590c22013-11-12 17:16:08 +0800983
984 if (!check_sd_current_prior(chip->sd_current_prior))
985 chip->sd_current_prior = 0x00010203;
986
Fabio Falzoibf6c0d12014-07-30 00:15:53 +0200987 dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n",
988 chip->sd_current_prior);
Micky Chingfa590c22013-11-12 17:16:08 +0800989
990 if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0))
991 chip->sd_ddr_tx_phase = 0;
992
993 if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0))
994 chip->mmc_ddr_tx_phase = 0;
995
Joe Perches8ee775f2015-03-25 12:54:26 -0700996 retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0);
997 if (retval) {
998 rtsx_trace(chip);
999 return retval;
1000 }
Micky Chingfa590c22013-11-12 17:16:08 +08001001 wait_timeout(200);
Joe Perches8ee775f2015-03-25 12:54:26 -07001002 retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07);
1003 if (retval) {
1004 rtsx_trace(chip);
1005 return retval;
1006 }
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001007 dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n",
1008 chip->use_hw_setting);
Micky Chingfa590c22013-11-12 17:16:08 +08001009
1010 if (CHECK_PID(chip, 0x5208)) {
1011 retval = rts5208_init(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001012 if (retval != STATUS_SUCCESS) {
1013 rtsx_trace(chip);
1014 return STATUS_FAIL;
1015 }
Micky Chingfa590c22013-11-12 17:16:08 +08001016
1017 } else if (CHECK_PID(chip, 0x5288)) {
1018 retval = rts5288_init(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001019 if (retval != STATUS_SUCCESS) {
1020 rtsx_trace(chip);
1021 return STATUS_FAIL;
1022 }
Micky Chingfa590c22013-11-12 17:16:08 +08001023 }
1024
1025 if (chip->ss_en == 2)
1026 chip->ss_en = 0;
1027
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001028 dev_dbg(rtsx_dev(chip), "chip->asic_code = %d\n", chip->asic_code);
1029 dev_dbg(rtsx_dev(chip), "chip->ic_version = 0x%x\n", chip->ic_version);
1030 dev_dbg(rtsx_dev(chip), "chip->phy_debug_mode = %d\n",
1031 chip->phy_debug_mode);
1032 dev_dbg(rtsx_dev(chip), "chip->aux_pwr_exist = %d\n",
1033 chip->aux_pwr_exist);
1034 dev_dbg(rtsx_dev(chip), "chip->sdio_func_exist = %d\n",
1035 chip->sdio_func_exist);
1036 dev_dbg(rtsx_dev(chip), "chip->hw_bypass_sd = %d\n",
1037 chip->hw_bypass_sd);
1038 dev_dbg(rtsx_dev(chip), "chip->aspm_l0s_l1_en = %d\n",
1039 chip->aspm_l0s_l1_en);
1040 dev_dbg(rtsx_dev(chip), "chip->lun_mode = %d\n", chip->lun_mode);
1041 dev_dbg(rtsx_dev(chip), "chip->auto_delink_en = %d\n",
1042 chip->auto_delink_en);
1043 dev_dbg(rtsx_dev(chip), "chip->ss_en = %d\n", chip->ss_en);
1044 dev_dbg(rtsx_dev(chip), "chip->baro_pkg = %d\n", chip->baro_pkg);
Micky Chingfa590c22013-11-12 17:16:08 +08001045
1046 if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
1047 chip->card2lun[SD_CARD] = 0;
1048 chip->card2lun[MS_CARD] = 1;
1049 chip->card2lun[XD_CARD] = 0xFF;
1050 chip->lun2card[0] = SD_CARD;
1051 chip->lun2card[1] = MS_CARD;
1052 chip->max_lun = 1;
1053 SET_SDIO_IGNORED(chip);
1054 } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
1055 chip->card2lun[SD_CARD] = 0;
1056 chip->card2lun[MS_CARD] = 0;
1057 chip->card2lun[XD_CARD] = 0xFF;
1058 chip->lun2card[0] = SD_CARD | MS_CARD;
1059 chip->max_lun = 0;
1060 } else {
1061 chip->card2lun[XD_CARD] = 0;
1062 chip->card2lun[SD_CARD] = 0;
1063 chip->card2lun[MS_CARD] = 0;
1064 chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
1065 chip->max_lun = 0;
1066 }
1067
1068 retval = rtsx_reset_chip(chip);
Joe Perches031366e2015-03-25 12:54:25 -07001069 if (retval != STATUS_SUCCESS) {
1070 rtsx_trace(chip);
1071 return STATUS_FAIL;
1072 }
Micky Chingfa590c22013-11-12 17:16:08 +08001073
1074 return STATUS_SUCCESS;
1075}
1076
1077void rtsx_release_chip(struct rtsx_chip *chip)
1078{
1079 xd_free_l2p_tbl(chip);
1080 ms_free_l2p_tbl(chip);
1081 chip->card_exist = 0;
1082 chip->card_ready = 0;
1083}
1084
1085#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1086static inline void rtsx_blink_led(struct rtsx_chip *chip)
1087{
1088 if (chip->card_exist && chip->blink_led) {
1089 if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
1090 chip->led_toggle_counter++;
1091 } else {
1092 chip->led_toggle_counter = 0;
1093 toggle_gpio(chip, LED_GPIO);
1094 }
1095 }
1096}
1097#endif
1098
1099static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
1100{
Quentin Lambertde904bf2015-03-04 11:31:01 +01001101 bool reg_changed, maybe_support_aspm;
Micky Chingfa590c22013-11-12 17:16:08 +08001102 u32 tmp = 0;
1103 u8 reg0 = 0, reg1 = 0;
1104
Quentin Lambertde904bf2015-03-04 11:31:01 +01001105 maybe_support_aspm = false;
1106 reg_changed = false;
Micky Chingfa590c22013-11-12 17:16:08 +08001107 rtsx_read_config_byte(chip, LCTLR, &reg0);
1108 if (chip->aspm_level[0] != reg0) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001109 reg_changed = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001110 chip->aspm_level[0] = reg0;
1111 }
1112 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
1113 rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
1114 reg1 = (u8)tmp;
1115 if (chip->aspm_level[1] != reg1) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001116 reg_changed = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001117 chip->aspm_level[1] = reg1;
1118 }
1119
1120 if ((reg0 & 0x03) && (reg1 & 0x03))
Quentin Lambertde904bf2015-03-04 11:31:01 +01001121 maybe_support_aspm = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001122
1123 } else {
1124 if (reg0 & 0x03)
Quentin Lambertde904bf2015-03-04 11:31:01 +01001125 maybe_support_aspm = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001126 }
1127
1128 if (reg_changed) {
1129 if (maybe_support_aspm)
1130 chip->aspm_l0s_l1_en = 0x03;
1131
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001132 dev_dbg(rtsx_dev(chip), "aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
1133 chip->aspm_level[0], chip->aspm_level[1]);
Micky Chingfa590c22013-11-12 17:16:08 +08001134
1135 if (chip->aspm_l0s_l1_en) {
1136 chip->aspm_enabled = 1;
1137 } else {
1138 chip->aspm_enabled = 0;
1139 chip->sdio_aspm = 0;
1140 }
1141 rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001142 0x30 | chip->aspm_level[0] |
1143 (chip->aspm_level[1] << 2));
Micky Chingfa590c22013-11-12 17:16:08 +08001144 }
1145}
1146
Fabio Falzoi50763572015-06-14 15:48:48 +02001147static void rtsx_manage_ocp(struct rtsx_chip *chip)
1148{
1149#ifdef SUPPORT_OCP
1150 if (!chip->ocp_int)
1151 return;
1152
1153 rtsx_read_register(chip, OCPSTAT, &chip->ocp_stat);
1154
1155 if (chip->card_exist & SD_CARD)
1156 sd_power_off_card3v3(chip);
1157 else if (chip->card_exist & MS_CARD)
1158 ms_power_off_card3v3(chip);
1159 else if (chip->card_exist & XD_CARD)
1160 xd_power_off_card3v3(chip);
1161
1162 chip->ocp_int = 0;
1163#endif
1164}
1165
Fabio Falzoicb547642015-06-14 15:48:47 +02001166static void rtsx_manage_sd_lock(struct rtsx_chip *chip)
Micky Chingfa590c22013-11-12 17:16:08 +08001167{
1168#ifdef SUPPORT_SD_LOCK
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001169 struct sd_info *sd_card = &chip->sd_card;
Fabio Falzoicb547642015-06-14 15:48:47 +02001170 u8 val;
1171
1172 if (!sd_card->sd_erase_status)
1173 return;
1174
1175 if (chip->card_exist & SD_CARD) {
1176 rtsx_read_register(chip, 0xFD30, &val);
1177 if (val & 0x02) {
1178 sd_card->sd_erase_status = SD_NOT_ERASE;
1179 sd_card->sd_lock_notify = 1;
1180 chip->need_reinit |= SD_CARD;
1181 }
1182 } else {
1183 sd_card->sd_erase_status = SD_NOT_ERASE;
1184 }
Micky Chingfa590c22013-11-12 17:16:08 +08001185#endif
Fabio Falzoicb547642015-06-14 15:48:47 +02001186}
1187
Fabio Falzoi31949932015-06-14 15:48:49 +02001188static bool rtsx_is_ss_allowed(struct rtsx_chip *chip)
1189{
1190 u32 val;
1191
1192 if (!chip->ss_en || CHECK_PID(chip, 0x5288))
1193 return false;
1194
1195 if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
1196 rtsx_read_cfg_dw(chip, 1, 0x04, &val);
1197 if (val & 0x07)
1198 return false;
1199 }
1200
1201 return true;
1202}
1203
1204static void rtsx_manage_ss(struct rtsx_chip *chip)
1205{
1206 if (!rtsx_is_ss_allowed(chip) || chip->sd_io)
1207 return;
1208
1209 if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
1210 chip->ss_counter = 0;
1211 return;
1212 }
1213
1214 if (chip->ss_counter < (chip->ss_idle_period / POLLING_INTERVAL))
1215 chip->ss_counter++;
1216 else
1217 rtsx_exclusive_enter_ss(chip);
1218}
1219
Fabio Falzoi884a27e2015-06-14 15:48:50 +02001220static void rtsx_manage_aspm(struct rtsx_chip *chip)
1221{
1222 u8 data;
1223
1224 if (!CHECK_PID(chip, 0x5208))
1225 return;
1226
1227 rtsx_monitor_aspm_config(chip);
1228
1229#ifdef SUPPORT_SDIO_ASPM
1230 if (!CHK_SDIO_EXIST(chip) || CHK_SDIO_IGNORED(chip) ||
1231 !chip->aspm_l0s_l1_en || !chip->dynamic_aspm)
1232 return;
1233
1234 if (chip->sd_io) {
1235 dynamic_configure_sdio_aspm(chip);
1236 return;
1237 }
1238
1239 if (chip->sdio_aspm)
1240 return;
1241
1242 dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
1243 data = 0x30 | (chip->aspm_level[1] << 2);
1244 rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, data);
1245 chip->sdio_aspm = 1;
1246#endif
1247}
1248
Fabio Falzoi76d833a2015-06-14 15:48:51 +02001249static void rtsx_manage_idle(struct rtsx_chip *chip)
1250{
1251 if (chip->idle_counter < IDLE_MAX_COUNT) {
1252 chip->idle_counter++;
1253 return;
1254 }
1255
1256 if (rtsx_get_stat(chip) == RTSX_STAT_IDLE)
1257 return;
1258
1259 dev_dbg(rtsx_dev(chip), "Idle state!\n");
1260 rtsx_set_stat(chip, RTSX_STAT_IDLE);
1261
1262#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1263 chip->led_toggle_counter = 0;
1264#endif
1265 rtsx_force_power_on(chip, SSC_PDCTL);
1266
1267 turn_off_led(chip, LED_GPIO);
1268
1269 if (chip->auto_power_down && !chip->card_ready && !chip->sd_io)
1270 rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
1271}
1272
Fabio Falzoi00aa7162015-06-14 15:48:52 +02001273static void rtsx_manage_2lun_mode(struct rtsx_chip *chip)
1274{
1275#ifdef SUPPORT_OCP
1276 u8 sd_oc, ms_oc;
1277
1278 sd_oc = chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER);
1279 ms_oc = chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER);
1280
1281 if (sd_oc || ms_oc)
1282 dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
1283 chip->ocp_stat);
1284
1285 if (sd_oc && (chip->card_exist & SD_CARD)) {
1286 rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
1287 card_power_off(chip, SD_CARD);
1288 chip->card_fail |= SD_CARD;
1289 }
1290
1291 if (ms_oc && (chip->card_exist & MS_CARD)) {
1292 rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
1293 card_power_off(chip, MS_CARD);
1294 chip->card_fail |= MS_CARD;
1295 }
1296#endif
1297}
1298
1299static void rtsx_manage_1lun_mode(struct rtsx_chip *chip)
1300{
1301#ifdef SUPPORT_OCP
1302 if (!(chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)))
1303 return;
1304
1305 dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
1306 chip->ocp_stat);
1307
1308 if (chip->card_exist & SD_CARD) {
1309 rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
1310 chip->card_fail |= SD_CARD;
1311 } else if (chip->card_exist & MS_CARD) {
1312 rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
1313 chip->card_fail |= MS_CARD;
1314 } else if (chip->card_exist & XD_CARD) {
1315 rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
1316 chip->card_fail |= XD_CARD;
1317 }
1318 card_power_off(chip, SD_CARD);
1319#endif
1320}
1321
Fabio Falzoia9b693c2015-06-14 15:48:53 +02001322static void rtsx_delink_stage1(struct rtsx_chip *chip, int enter_L1,
1323 int stage3_cnt)
1324{
1325 u8 val;
1326
1327 rtsx_set_stat(chip, RTSX_STAT_DELINK);
1328
1329 if (chip->asic_code && CHECK_PID(chip, 0x5208))
1330 rtsx_set_phy_reg_bit(chip, 0x1C, 2);
1331
1332 if (chip->card_exist)
1333 dev_dbg(rtsx_dev(chip), "False card inserted, do force delink\n");
1334 else
1335 dev_dbg(rtsx_dev(chip), "No card inserted, do delink\n");
1336
1337 if (enter_L1)
1338 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
1339
1340 if (chip->card_exist)
Fabio Falzoi6c6f95a92015-06-19 17:44:33 +02001341 val = 0x02;
Fabio Falzoia9b693c2015-06-14 15:48:53 +02001342 else
1343 val = 0x0A;
1344
1345 rtsx_write_register(chip, CHANGE_LINK_STATE, val, val);
1346
1347 if (enter_L1)
1348 rtsx_enter_L1(chip);
1349
1350 if (chip->card_exist)
1351 chip->auto_delink_cnt = stage3_cnt + 1;
1352}
1353
1354static void rtsx_delink_stage(struct rtsx_chip *chip)
1355{
1356 int delink_stage1_cnt, delink_stage2_cnt, delink_stage3_cnt;
1357 int enter_L1;
1358
1359 if (!chip->auto_delink_en || !chip->auto_delink_allowed ||
1360 chip->card_ready || chip->card_ejected || chip->sd_io) {
1361 chip->auto_delink_cnt = 0;
1362 return;
1363 }
1364
1365 enter_L1 = chip->auto_delink_in_L1 &&
1366 (chip->aspm_l0s_l1_en || chip->ss_en);
1367
1368 delink_stage1_cnt = chip->delink_stage1_step;
1369 delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step;
1370 delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step;
1371
1372 if (chip->auto_delink_cnt > delink_stage3_cnt)
1373 return;
1374
1375 if (chip->auto_delink_cnt == delink_stage1_cnt)
1376 rtsx_delink_stage1(chip, enter_L1, delink_stage3_cnt);
1377
1378 if (chip->auto_delink_cnt == delink_stage2_cnt) {
1379 dev_dbg(rtsx_dev(chip), "Try to do force delink\n");
1380
1381 if (enter_L1)
1382 rtsx_exit_L1(chip);
1383
1384 if (chip->asic_code && CHECK_PID(chip, 0x5208))
1385 rtsx_set_phy_reg_bit(chip, 0x1C, 2);
1386
1387 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
1388 }
1389
1390 chip->auto_delink_cnt++;
1391}
1392
Fabio Falzoicb547642015-06-14 15:48:47 +02001393void rtsx_polling_func(struct rtsx_chip *chip)
1394{
Micky Chingfa590c22013-11-12 17:16:08 +08001395 if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
1396 return;
1397
1398 if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001399 goto delink_stage;
Micky Chingfa590c22013-11-12 17:16:08 +08001400
1401 if (chip->polling_config) {
1402 u8 val;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301403
Micky Chingfa590c22013-11-12 17:16:08 +08001404 rtsx_read_config_byte(chip, 0, &val);
1405 }
1406
1407 if (rtsx_chk_stat(chip, RTSX_STAT_SS))
1408 return;
1409
Fabio Falzoi50763572015-06-14 15:48:48 +02001410 rtsx_manage_ocp(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001411
Fabio Falzoicb547642015-06-14 15:48:47 +02001412 rtsx_manage_sd_lock(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001413
1414 rtsx_init_cards(chip);
1415
Fabio Falzoi31949932015-06-14 15:48:49 +02001416 rtsx_manage_ss(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001417
Fabio Falzoi884a27e2015-06-14 15:48:50 +02001418 rtsx_manage_aspm(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001419
Fabio Falzoi76d833a2015-06-14 15:48:51 +02001420 rtsx_manage_idle(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001421
1422 switch (rtsx_get_stat(chip)) {
1423 case RTSX_STAT_RUN:
1424#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
1425 rtsx_blink_led(chip);
1426#endif
1427 do_remaining_work(chip);
1428 break;
1429
1430 case RTSX_STAT_IDLE:
1431 if (chip->sd_io && !chip->sd_int)
1432 try_to_switch_sdio_ctrl(chip);
1433
1434 rtsx_enable_aspm(chip);
1435 break;
1436
1437 default:
1438 break;
1439 }
1440
Fabio Falzoi00aa7162015-06-14 15:48:52 +02001441 if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
1442 rtsx_manage_2lun_mode(chip);
1443 else
1444 rtsx_manage_1lun_mode(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001445
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03001446delink_stage:
Fabio Falzoia9b693c2015-06-14 15:48:53 +02001447 rtsx_delink_stage(chip);
Micky Chingfa590c22013-11-12 17:16:08 +08001448}
1449
1450void rtsx_undo_delink(struct rtsx_chip *chip)
1451{
1452 chip->auto_delink_allowed = 0;
1453 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00);
1454}
1455
1456/**
1457 * rtsx_stop_cmd - stop command transfer and DMA transfer
1458 * @chip: Realtek's card reader chip
1459 * @card: flash card type
1460 *
1461 * Stop command transfer and DMA transfer.
1462 * This function is called in error handler.
1463 */
1464void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
1465{
1466 int i;
1467
1468 for (i = 0; i <= 8; i++) {
1469 int addr = RTSX_HCBAR + i * 4;
1470 u32 reg;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301471
Micky Chingfa590c22013-11-12 17:16:08 +08001472 reg = rtsx_readl(chip, addr);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001473 dev_dbg(rtsx_dev(chip), "BAR (0x%02x): 0x%08x\n", addr, reg);
Micky Chingfa590c22013-11-12 17:16:08 +08001474 }
1475 rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
1476 rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
1477
1478 for (i = 0; i < 16; i++) {
1479 u16 addr = 0xFE20 + (u16)i;
1480 u8 val;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05301481
Micky Chingfa590c22013-11-12 17:16:08 +08001482 rtsx_read_register(chip, addr, &val);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001483 dev_dbg(rtsx_dev(chip), "0x%04X: 0x%02x\n", addr, val);
Micky Chingfa590c22013-11-12 17:16:08 +08001484 }
1485
1486 rtsx_write_register(chip, DMACTL, 0x80, 0x80);
1487 rtsx_write_register(chip, RBCTL, 0x80, 0x80);
1488}
1489
1490#define MAX_RW_REG_CNT 1024
1491
1492int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
1493{
1494 int i;
1495 u32 val = 3 << 30;
1496
1497 val |= (u32)(addr & 0x3FFF) << 16;
1498 val |= (u32)mask << 8;
1499 val |= (u32)data;
1500
1501 rtsx_writel(chip, RTSX_HAIMR, val);
1502
1503 for (i = 0; i < MAX_RW_REG_CNT; i++) {
1504 val = rtsx_readl(chip, RTSX_HAIMR);
1505 if ((val & (1 << 31)) == 0) {
Joe Perches031366e2015-03-25 12:54:25 -07001506 if (data != (u8)val) {
1507 rtsx_trace(chip);
1508 return STATUS_FAIL;
1509 }
Micky Chingfa590c22013-11-12 17:16:08 +08001510
1511 return STATUS_SUCCESS;
1512 }
1513 }
1514
Joe Perches031366e2015-03-25 12:54:25 -07001515 rtsx_trace(chip);
1516 return STATUS_TIMEDOUT;
Micky Chingfa590c22013-11-12 17:16:08 +08001517}
1518
1519int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
1520{
1521 u32 val = 2 << 30;
1522 int i;
1523
1524 if (data)
1525 *data = 0;
1526
1527 val |= (u32)(addr & 0x3FFF) << 16;
1528
1529 rtsx_writel(chip, RTSX_HAIMR, val);
1530
1531 for (i = 0; i < MAX_RW_REG_CNT; i++) {
1532 val = rtsx_readl(chip, RTSX_HAIMR);
1533 if ((val & (1 << 31)) == 0)
1534 break;
1535 }
1536
Joe Perches031366e2015-03-25 12:54:25 -07001537 if (i >= MAX_RW_REG_CNT) {
1538 rtsx_trace(chip);
1539 return STATUS_TIMEDOUT;
1540 }
Micky Chingfa590c22013-11-12 17:16:08 +08001541
1542 if (data)
1543 *data = (u8)(val & 0xFF);
1544
1545 return STATUS_SUCCESS;
1546}
1547
1548int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001549 u32 val)
Micky Chingfa590c22013-11-12 17:16:08 +08001550{
Joe Perches8ee775f2015-03-25 12:54:26 -07001551 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001552 u8 mode = 0, tmp;
1553 int i;
1554
1555 for (i = 0; i < 4; i++) {
1556 if (mask & 0xFF) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001557 retval = rtsx_write_register(chip, CFGDATA0 + i,
1558 0xFF,
1559 (u8)(val & mask & 0xFF));
1560 if (retval) {
1561 rtsx_trace(chip);
1562 return retval;
1563 }
Micky Chingfa590c22013-11-12 17:16:08 +08001564 mode |= (1 << i);
1565 }
1566 mask >>= 8;
1567 val >>= 8;
1568 }
1569
1570 if (mode) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001571 retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
1572 if (retval) {
1573 rtsx_trace(chip);
1574 return retval;
1575 }
1576 retval = rtsx_write_register(chip, CFGADDR1, 0xFF,
1577 (u8)(addr >> 8));
1578 if (retval) {
1579 rtsx_trace(chip);
1580 return retval;
1581 }
Micky Chingfa590c22013-11-12 17:16:08 +08001582
Joe Perches8ee775f2015-03-25 12:54:26 -07001583 retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
1584 0x80 | mode | ((func_no & 0x03) << 4));
1585 if (retval) {
1586 rtsx_trace(chip);
1587 return retval;
1588 }
Micky Chingfa590c22013-11-12 17:16:08 +08001589
1590 for (i = 0; i < MAX_RW_REG_CNT; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001591 retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
1592 if (retval) {
1593 rtsx_trace(chip);
1594 return retval;
1595 }
Micky Chingfa590c22013-11-12 17:16:08 +08001596 if ((tmp & 0x80) == 0)
1597 break;
1598 }
1599 }
1600
1601 return STATUS_SUCCESS;
1602}
1603
1604int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
1605{
Joe Perches8ee775f2015-03-25 12:54:26 -07001606 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001607 int i;
1608 u8 tmp;
1609 u32 data = 0;
1610
Joe Perches8ee775f2015-03-25 12:54:26 -07001611 retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
1612 if (retval) {
1613 rtsx_trace(chip);
1614 return retval;
1615 }
1616 retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
1617 if (retval) {
1618 rtsx_trace(chip);
1619 return retval;
1620 }
1621 retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
1622 0x80 | ((func_no & 0x03) << 4));
1623 if (retval) {
1624 rtsx_trace(chip);
1625 return retval;
1626 }
Micky Chingfa590c22013-11-12 17:16:08 +08001627
1628 for (i = 0; i < MAX_RW_REG_CNT; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001629 retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
1630 if (retval) {
1631 rtsx_trace(chip);
1632 return retval;
1633 }
Micky Chingfa590c22013-11-12 17:16:08 +08001634 if ((tmp & 0x80) == 0)
1635 break;
1636 }
1637
1638 for (i = 0; i < 4; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001639 retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp);
1640 if (retval) {
1641 rtsx_trace(chip);
1642 return retval;
1643 }
Micky Chingfa590c22013-11-12 17:16:08 +08001644 data |= (u32)tmp << (i * 8);
1645 }
1646
1647 if (val)
1648 *val = data;
1649
1650 return STATUS_SUCCESS;
1651}
1652
1653int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001654 int len)
Micky Chingfa590c22013-11-12 17:16:08 +08001655{
1656 u32 *data, *mask;
1657 u16 offset = addr % 4;
1658 u16 aligned_addr = addr - offset;
1659 int dw_len, i, j;
1660 int retval;
1661
Joe Perches031366e2015-03-25 12:54:25 -07001662 if (!buf) {
1663 rtsx_trace(chip);
1664 return STATUS_NOMEM;
1665 }
Micky Chingfa590c22013-11-12 17:16:08 +08001666
1667 if ((len + offset) % 4)
1668 dw_len = (len + offset) / 4 + 1;
1669 else
1670 dw_len = (len + offset) / 4;
1671
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001672 dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
Micky Chingfa590c22013-11-12 17:16:08 +08001673
1674 data = vzalloc(dw_len * 4);
Joe Perches031366e2015-03-25 12:54:25 -07001675 if (!data) {
1676 rtsx_trace(chip);
1677 return STATUS_NOMEM;
1678 }
Micky Chingfa590c22013-11-12 17:16:08 +08001679
1680 mask = vzalloc(dw_len * 4);
1681 if (!mask) {
1682 vfree(data);
Joe Perches031366e2015-03-25 12:54:25 -07001683 rtsx_trace(chip);
1684 return STATUS_NOMEM;
Micky Chingfa590c22013-11-12 17:16:08 +08001685 }
1686
1687 j = 0;
1688 for (i = 0; i < len; i++) {
1689 mask[j] |= 0xFF << (offset * 8);
1690 data[j] |= buf[i] << (offset * 8);
1691 if (++offset == 4) {
1692 j++;
1693 offset = 0;
1694 }
1695 }
1696
Fabio Falzoi69b8b222014-08-05 23:24:17 +02001697 print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask,
1698 dw_len * 4);
1699 print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data,
1700 dw_len * 4);
Micky Chingfa590c22013-11-12 17:16:08 +08001701
1702 for (i = 0; i < dw_len; i++) {
1703 retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001704 mask[i], data[i]);
Micky Chingfa590c22013-11-12 17:16:08 +08001705 if (retval != STATUS_SUCCESS) {
1706 vfree(data);
1707 vfree(mask);
Joe Perches031366e2015-03-25 12:54:25 -07001708 rtsx_trace(chip);
1709 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001710 }
1711 }
1712
1713 vfree(data);
1714 vfree(mask);
1715
1716 return STATUS_SUCCESS;
1717}
1718
1719int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001720 int len)
Micky Chingfa590c22013-11-12 17:16:08 +08001721{
1722 u32 *data;
1723 u16 offset = addr % 4;
1724 u16 aligned_addr = addr - offset;
1725 int dw_len, i, j;
1726 int retval;
1727
Micky Chingfa590c22013-11-12 17:16:08 +08001728 if ((len + offset) % 4)
1729 dw_len = (len + offset) / 4 + 1;
1730 else
1731 dw_len = (len + offset) / 4;
1732
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001733 dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
Micky Chingfa590c22013-11-12 17:16:08 +08001734
1735 data = vmalloc(dw_len * 4);
Joe Perches031366e2015-03-25 12:54:25 -07001736 if (!data) {
1737 rtsx_trace(chip);
1738 return STATUS_NOMEM;
1739 }
Micky Chingfa590c22013-11-12 17:16:08 +08001740
1741 for (i = 0; i < dw_len; i++) {
1742 retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03001743 data + i);
Micky Chingfa590c22013-11-12 17:16:08 +08001744 if (retval != STATUS_SUCCESS) {
1745 vfree(data);
Joe Perches031366e2015-03-25 12:54:25 -07001746 rtsx_trace(chip);
1747 return STATUS_FAIL;
Micky Chingfa590c22013-11-12 17:16:08 +08001748 }
1749 }
1750
1751 if (buf) {
1752 j = 0;
1753
1754 for (i = 0; i < len; i++) {
1755 buf[i] = (u8)(data[j] >> (offset * 8));
1756 if (++offset == 4) {
1757 j++;
1758 offset = 0;
1759 }
1760 }
1761 }
1762
1763 vfree(data);
1764
1765 return STATUS_SUCCESS;
1766}
1767
1768int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
1769{
Joe Perches8ee775f2015-03-25 12:54:26 -07001770 int retval;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001771 bool finished = false;
1772 int i;
Micky Chingfa590c22013-11-12 17:16:08 +08001773 u8 tmp;
1774
Joe Perches8ee775f2015-03-25 12:54:26 -07001775 retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val);
1776 if (retval) {
1777 rtsx_trace(chip);
1778 return retval;
1779 }
1780 retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
1781 if (retval) {
1782 rtsx_trace(chip);
1783 return retval;
1784 }
1785 retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
1786 if (retval) {
1787 rtsx_trace(chip);
1788 return retval;
1789 }
1790 retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81);
1791 if (retval) {
1792 rtsx_trace(chip);
1793 return retval;
1794 }
Micky Chingfa590c22013-11-12 17:16:08 +08001795
1796 for (i = 0; i < 100000; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001797 retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
1798 if (retval) {
1799 rtsx_trace(chip);
1800 return retval;
1801 }
Micky Chingfa590c22013-11-12 17:16:08 +08001802 if (!(tmp & 0x80)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001803 finished = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001804 break;
1805 }
1806 }
1807
Joe Perches031366e2015-03-25 12:54:25 -07001808 if (!finished) {
1809 rtsx_trace(chip);
1810 return STATUS_FAIL;
1811 }
Micky Chingfa590c22013-11-12 17:16:08 +08001812
1813 return STATUS_SUCCESS;
1814}
1815
1816int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
1817{
Joe Perches8ee775f2015-03-25 12:54:26 -07001818 int retval;
Quentin Lambertde904bf2015-03-04 11:31:01 +01001819 bool finished = false;
1820 int i;
Micky Chingfa590c22013-11-12 17:16:08 +08001821 u16 data = 0;
1822 u8 tmp;
1823
Joe Perches8ee775f2015-03-25 12:54:26 -07001824 retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
1825 if (retval) {
1826 rtsx_trace(chip);
1827 return retval;
1828 }
1829 retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80);
1830 if (retval) {
1831 rtsx_trace(chip);
1832 return retval;
1833 }
Micky Chingfa590c22013-11-12 17:16:08 +08001834
1835 for (i = 0; i < 100000; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001836 retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
1837 if (retval) {
1838 rtsx_trace(chip);
1839 return retval;
1840 }
Micky Chingfa590c22013-11-12 17:16:08 +08001841 if (!(tmp & 0x80)) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01001842 finished = true;
Micky Chingfa590c22013-11-12 17:16:08 +08001843 break;
1844 }
1845 }
1846
Joe Perches031366e2015-03-25 12:54:25 -07001847 if (!finished) {
1848 rtsx_trace(chip);
1849 return STATUS_FAIL;
1850 }
Micky Chingfa590c22013-11-12 17:16:08 +08001851
Joe Perches8ee775f2015-03-25 12:54:26 -07001852 retval = rtsx_read_register(chip, PHYDATA0, &tmp);
1853 if (retval) {
1854 rtsx_trace(chip);
1855 return retval;
1856 }
Micky Chingfa590c22013-11-12 17:16:08 +08001857 data = tmp;
Joe Perches8ee775f2015-03-25 12:54:26 -07001858 retval = rtsx_read_register(chip, PHYDATA1, &tmp);
1859 if (retval) {
1860 rtsx_trace(chip);
1861 return retval;
1862 }
Micky Chingfa590c22013-11-12 17:16:08 +08001863 data |= (u16)tmp << 8;
1864
1865 if (val)
1866 *val = data;
1867
1868 return STATUS_SUCCESS;
1869}
1870
1871int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
1872{
Joe Perches8ee775f2015-03-25 12:54:26 -07001873 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001874 int i;
1875 u8 data = 0;
1876
Joe Perches8ee775f2015-03-25 12:54:26 -07001877 retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr);
1878 if (retval) {
1879 rtsx_trace(chip);
1880 return retval;
1881 }
Micky Chingfa590c22013-11-12 17:16:08 +08001882
1883 for (i = 0; i < 100; i++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001884 retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
1885 if (retval) {
1886 rtsx_trace(chip);
1887 return retval;
1888 }
Micky Chingfa590c22013-11-12 17:16:08 +08001889 if (!(data & 0x80))
1890 break;
1891 udelay(1);
1892 }
1893
Joe Perches031366e2015-03-25 12:54:25 -07001894 if (data & 0x80) {
1895 rtsx_trace(chip);
1896 return STATUS_TIMEDOUT;
1897 }
Micky Chingfa590c22013-11-12 17:16:08 +08001898
Joe Perches8ee775f2015-03-25 12:54:26 -07001899 retval = rtsx_read_register(chip, EFUSE_DATA, &data);
1900 if (retval) {
1901 rtsx_trace(chip);
1902 return retval;
1903 }
Micky Chingfa590c22013-11-12 17:16:08 +08001904 if (val)
1905 *val = data;
1906
1907 return STATUS_SUCCESS;
1908}
1909
1910int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
1911{
Joe Perches8ee775f2015-03-25 12:54:26 -07001912 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08001913 int i, j;
1914 u8 data = 0, tmp = 0xFF;
1915
1916 for (i = 0; i < 8; i++) {
1917 if (val & (u8)(1 << i))
1918 continue;
1919
1920 tmp &= (~(u8)(1 << i));
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02001921 dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr);
Micky Chingfa590c22013-11-12 17:16:08 +08001922
Joe Perches8ee775f2015-03-25 12:54:26 -07001923 retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp);
1924 if (retval) {
1925 rtsx_trace(chip);
1926 return retval;
1927 }
1928 retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF,
1929 0xA0 | addr);
1930 if (retval) {
1931 rtsx_trace(chip);
1932 return retval;
1933 }
Micky Chingfa590c22013-11-12 17:16:08 +08001934
1935 for (j = 0; j < 100; j++) {
Joe Perches8ee775f2015-03-25 12:54:26 -07001936 retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
1937 if (retval) {
1938 rtsx_trace(chip);
1939 return retval;
1940 }
Micky Chingfa590c22013-11-12 17:16:08 +08001941 if (!(data & 0x80))
1942 break;
1943 wait_timeout(3);
1944 }
1945
Joe Perches031366e2015-03-25 12:54:25 -07001946 if (data & 0x80) {
1947 rtsx_trace(chip);
1948 return STATUS_TIMEDOUT;
1949 }
Micky Chingfa590c22013-11-12 17:16:08 +08001950
1951 wait_timeout(5);
1952 }
1953
1954 return STATUS_SUCCESS;
1955}
1956
1957int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
1958{
1959 int retval;
1960 u16 value;
1961
1962 retval = rtsx_read_phy_register(chip, reg, &value);
Joe Perches031366e2015-03-25 12:54:25 -07001963 if (retval != STATUS_SUCCESS) {
1964 rtsx_trace(chip);
1965 return STATUS_FAIL;
1966 }
Micky Chingfa590c22013-11-12 17:16:08 +08001967
1968 if (value & (1 << bit)) {
1969 value &= ~(1 << bit);
1970 retval = rtsx_write_phy_register(chip, reg, value);
Joe Perches031366e2015-03-25 12:54:25 -07001971 if (retval != STATUS_SUCCESS) {
1972 rtsx_trace(chip);
1973 return STATUS_FAIL;
1974 }
Micky Chingfa590c22013-11-12 17:16:08 +08001975 }
1976
1977 return STATUS_SUCCESS;
1978}
1979
1980int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
1981{
1982 int retval;
1983 u16 value;
1984
1985 retval = rtsx_read_phy_register(chip, reg, &value);
Joe Perches031366e2015-03-25 12:54:25 -07001986 if (retval != STATUS_SUCCESS) {
1987 rtsx_trace(chip);
1988 return STATUS_FAIL;
1989 }
Micky Chingfa590c22013-11-12 17:16:08 +08001990
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03001991 if ((value & (1 << bit)) == 0) {
Micky Chingfa590c22013-11-12 17:16:08 +08001992 value |= (1 << bit);
1993 retval = rtsx_write_phy_register(chip, reg, value);
Joe Perches031366e2015-03-25 12:54:25 -07001994 if (retval != STATUS_SUCCESS) {
1995 rtsx_trace(chip);
1996 return STATUS_FAIL;
1997 }
Micky Chingfa590c22013-11-12 17:16:08 +08001998 }
1999
2000 return STATUS_SUCCESS;
2001}
2002
2003int rtsx_check_link_ready(struct rtsx_chip *chip)
2004{
Joe Perches8ee775f2015-03-25 12:54:26 -07002005 int retval;
Micky Chingfa590c22013-11-12 17:16:08 +08002006 u8 val;
2007
Joe Perches8ee775f2015-03-25 12:54:26 -07002008 retval = rtsx_read_register(chip, IRQSTAT0, &val);
2009 if (retval) {
2010 rtsx_trace(chip);
2011 return retval;
2012 }
Micky Chingfa590c22013-11-12 17:16:08 +08002013
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002014 dev_dbg(rtsx_dev(chip), "IRQSTAT0: 0x%x\n", val);
Micky Chingfa590c22013-11-12 17:16:08 +08002015 if (val & LINK_RDY_INT) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002016 dev_dbg(rtsx_dev(chip), "Delinked!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002017 rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
2018 return STATUS_FAIL;
2019 }
2020
2021 return STATUS_SUCCESS;
2022}
2023
2024static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
2025{
2026 u32 ultmp;
2027
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002028 dev_dbg(rtsx_dev(chip), "%04x set pm_dstate to %d\n",
2029 chip->product_id, dstate);
Micky Chingfa590c22013-11-12 17:16:08 +08002030
2031 if (CHK_SDIO_EXIST(chip)) {
2032 u8 func_no;
2033
2034 if (CHECK_PID(chip, 0x5288))
2035 func_no = 2;
2036 else
2037 func_no = 1;
2038
2039 rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002040 dev_dbg(rtsx_dev(chip), "pm_dstate of function %d: 0x%x\n",
2041 (int)func_no, ultmp);
Micky Chingfa590c22013-11-12 17:16:08 +08002042 rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
2043 }
2044
2045 rtsx_write_config_byte(chip, 0x44, dstate);
2046 rtsx_write_config_byte(chip, 0x45, 0);
2047}
2048
2049void rtsx_enter_L1(struct rtsx_chip *chip)
2050{
2051 rtsx_handle_pm_dstate(chip, 2);
2052}
2053
2054void rtsx_exit_L1(struct rtsx_chip *chip)
2055{
2056 rtsx_write_config_byte(chip, 0x44, 0);
2057 rtsx_write_config_byte(chip, 0x45, 0);
2058}
2059
2060void rtsx_enter_ss(struct rtsx_chip *chip)
2061{
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002062 dev_dbg(rtsx_dev(chip), "Enter Selective Suspend State!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002063
2064 rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
2065
2066 if (chip->power_down_in_ss) {
2067 rtsx_power_off_card(chip);
2068 rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
2069 }
2070
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03002071 if (CHK_SDIO_EXIST(chip))
2072 rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
2073 0xC0, 0xFF00, 0x0100);
Micky Chingfa590c22013-11-12 17:16:08 +08002074
2075 if (chip->auto_delink_en) {
2076 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
2077 } else {
2078 if (!chip->phy_debug_mode) {
2079 u32 tmp;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05302080
Micky Chingfa590c22013-11-12 17:16:08 +08002081 tmp = rtsx_readl(chip, RTSX_BIER);
2082 tmp |= CARD_INT;
2083 rtsx_writel(chip, RTSX_BIER, tmp);
2084 }
2085
2086 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
2087 }
2088
2089 rtsx_enter_L1(chip);
2090
2091 RTSX_CLR_DELINK(chip);
2092 rtsx_set_stat(chip, RTSX_STAT_SS);
2093}
2094
2095void rtsx_exit_ss(struct rtsx_chip *chip)
2096{
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002097 dev_dbg(rtsx_dev(chip), "Exit Selective Suspend State!\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002098
2099 rtsx_exit_L1(chip);
2100
2101 if (chip->power_down_in_ss) {
2102 rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
2103 udelay(1000);
2104 }
2105
2106 if (RTSX_TST_DELINK(chip)) {
2107 chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
2108 rtsx_reinit_cards(chip, 1);
2109 RTSX_CLR_DELINK(chip);
2110 } else if (chip->power_down_in_ss) {
2111 chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
2112 rtsx_reinit_cards(chip, 0);
2113 }
2114}
2115
2116int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
2117{
2118 u32 status, int_enable;
Quentin Lambertde904bf2015-03-04 11:31:01 +01002119 bool exit_ss = false;
Micky Chingfa590c22013-11-12 17:16:08 +08002120#ifdef SUPPORT_OCP
2121 u32 ocp_int = 0;
2122
2123 ocp_int = OC_INT;
2124#endif
2125
2126 if (chip->ss_en) {
2127 chip->ss_counter = 0;
2128 if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
Quentin Lambertde904bf2015-03-04 11:31:01 +01002129 exit_ss = true;
Micky Chingfa590c22013-11-12 17:16:08 +08002130 rtsx_exit_L1(chip);
2131 rtsx_set_stat(chip, RTSX_STAT_RUN);
2132 }
2133 }
2134
2135 int_enable = rtsx_readl(chip, RTSX_BIER);
2136 chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
2137
2138 if (((chip->int_reg & int_enable) == 0) ||
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002139 (chip->int_reg == 0xFFFFFFFF))
Micky Chingfa590c22013-11-12 17:16:08 +08002140 return STATUS_FAIL;
2141
2142 status = chip->int_reg &= (int_enable | 0x7FFFFF);
2143
2144 if (status & CARD_INT) {
2145 chip->auto_delink_cnt = 0;
2146
2147 if (status & SD_INT) {
2148 if (status & SD_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002149 set_bit(SD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002150 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002151 set_bit(SD_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002152 chip->sd_reset_counter = 0;
2153 chip->sd_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002154 clear_bit(SD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002155 }
2156 } else {
Punit Vara60d6a212015-09-21 21:59:41 +05302157 /*
2158 * If multi-luns, it's possible that
2159 * when plugging/unplugging one card
2160 * there is another card which still
2161 * exists in the slot. In this case,
2162 * all existed cards should be reset.
2163 */
Micky Chingfa590c22013-11-12 17:16:08 +08002164 if (exit_ss && (status & SD_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002165 set_bit(SD_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002166 }
2167 if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
2168 if (status & XD_INT) {
2169 if (status & XD_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002170 set_bit(XD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002171 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002172 set_bit(XD_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002173 chip->xd_reset_counter = 0;
2174 chip->xd_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002175 clear_bit(XD_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002176 }
2177 } else {
2178 if (exit_ss && (status & XD_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002179 set_bit(XD_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002180 }
2181 }
2182 if (status & MS_INT) {
2183 if (status & MS_EXIST) {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002184 set_bit(MS_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002185 } else {
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002186 set_bit(MS_NR, &chip->need_release);
Micky Chingfa590c22013-11-12 17:16:08 +08002187 chip->ms_reset_counter = 0;
2188 chip->ms_show_cnt = 0;
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002189 clear_bit(MS_NR, &chip->need_reset);
Micky Chingfa590c22013-11-12 17:16:08 +08002190 }
2191 } else {
2192 if (exit_ss && (status & MS_EXIST))
Giedrius Statkevičiuse050dda2014-10-04 00:31:18 +03002193 set_bit(MS_NR, &chip->need_reinit);
Micky Chingfa590c22013-11-12 17:16:08 +08002194 }
2195 }
2196
2197#ifdef SUPPORT_OCP
2198 chip->ocp_int = ocp_int & status;
2199#endif
2200
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002201 if (chip->sd_io && (chip->int_reg & DATA_DONE_INT))
2202 chip->int_reg &= ~(u32)DATA_DONE_INT;
Micky Chingfa590c22013-11-12 17:16:08 +08002203
2204 return STATUS_SUCCESS;
2205}
2206
2207void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
2208{
2209 int retval;
2210
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002211 dev_dbg(rtsx_dev(chip), "%s, pm_stat = %d\n", __func__, pm_stat);
Micky Chingfa590c22013-11-12 17:16:08 +08002212
2213 rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
2214
2215 retval = rtsx_force_power_on(chip, SSC_PDCTL);
2216 if (retval != STATUS_SUCCESS)
2217 return;
2218
2219 rtsx_release_cards(chip);
2220 rtsx_disable_bus_int(chip);
2221 turn_off_led(chip, LED_GPIO);
2222
2223#ifdef HW_AUTO_SWITCH_SD_BUS
2224 if (chip->sd_io) {
2225 chip->sdio_in_charge = 1;
2226 if (CHECK_PID(chip, 0x5208)) {
2227 rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
2228 /* Enable sdio_bus_auto_switch */
2229 rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
2230 } else if (CHECK_PID(chip, 0x5288)) {
2231 rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
2232 /* Enable sdio_bus_auto_switch */
2233 rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
2234 }
2235 }
2236#endif
2237
2238 if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
2239 /* u_force_clkreq_0 */
2240 rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
2241 }
2242
2243 if (pm_stat == PM_S1) {
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002244 dev_dbg(rtsx_dev(chip), "Host enter S1\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002245 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002246 HOST_ENTER_S1);
Micky Chingfa590c22013-11-12 17:16:08 +08002247 } else if (pm_stat == PM_S3) {
2248 if (chip->s3_pwr_off_delay > 0)
2249 wait_timeout(chip->s3_pwr_off_delay);
2250
Fabio Falzoibf6c0d12014-07-30 00:15:53 +02002251 dev_dbg(rtsx_dev(chip), "Host enter S3\n");
Micky Chingfa590c22013-11-12 17:16:08 +08002252 rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002253 HOST_ENTER_S3);
Micky Chingfa590c22013-11-12 17:16:08 +08002254 }
2255
2256 if (chip->do_delink_before_power_down && chip->auto_delink_en)
2257 rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
2258
2259 rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
2260
2261 chip->cur_clk = 0;
2262 chip->cur_card = 0;
2263 chip->card_exist = 0;
2264}
2265
2266void rtsx_enable_aspm(struct rtsx_chip *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 enable ASPM\n");
2270 chip->aspm_enabled = 1;
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, 0);
2274 if (CHECK_PID(chip, 0x5208)) {
2275 rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002276 0x30 | chip->aspm_level[0]);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002277 } else {
2278 rtsx_write_config_byte(chip, LCTLR,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002279 chip->aspm_l0s_l1_en);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002280 }
Micky Chingfa590c22013-11-12 17:16:08 +08002281
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002282 if (CHK_SDIO_EXIST(chip)) {
2283 u16 val = chip->aspm_l0s_l1_en | 0x0100;
Mahati Chamarthy0be0b272014-09-25 02:53:54 +05302284
Giedrius Statkevičius609fc152014-10-04 00:31:21 +03002285 rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
2286 0xC0, 0xFFF, val);
Micky Chingfa590c22013-11-12 17:16:08 +08002287 }
2288 }
Micky Chingfa590c22013-11-12 17:16:08 +08002289}
2290
2291void rtsx_disable_aspm(struct rtsx_chip *chip)
2292{
2293 if (CHECK_PID(chip, 0x5208))
2294 rtsx_monitor_aspm_config(chip);
2295
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002296 if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && chip->aspm_enabled) {
2297 dev_dbg(rtsx_dev(chip), "Try to disable ASPM\n");
2298 chip->aspm_enabled = 0;
Micky Chingfa590c22013-11-12 17:16:08 +08002299
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002300 if (chip->asic_code && CHECK_PID(chip, 0x5208))
2301 rtsx_write_phy_register(chip, 0x07, 0x0129);
2302 if (CHECK_PID(chip, 0x5208))
2303 rtsx_write_register(chip, ASPM_FORCE_CTL,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002304 0xF3, 0x30);
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002305 else
2306 rtsx_write_config_byte(chip, LCTLR, 0x00);
Micky Chingfa590c22013-11-12 17:16:08 +08002307
Giedrius Statkevičius175dbfa2014-10-04 00:31:17 +03002308 wait_timeout(1);
Micky Chingfa590c22013-11-12 17:16:08 +08002309 }
Micky Chingfa590c22013-11-12 17:16:08 +08002310}
2311
2312int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
2313{
2314 int retval;
2315 int i, j;
2316 u16 reg_addr;
2317 u8 *ptr;
2318
Joe Perches031366e2015-03-25 12:54:25 -07002319 if (!buf) {
2320 rtsx_trace(chip);
2321 return STATUS_ERROR;
2322 }
Micky Chingfa590c22013-11-12 17:16:08 +08002323
2324 ptr = buf;
2325 reg_addr = PPBUF_BASE2;
2326 for (i = 0; i < buf_len/256; i++) {
2327 rtsx_init_cmd(chip);
2328
2329 for (j = 0; j < 256; j++)
2330 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
2331
2332 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002333 if (retval < 0) {
2334 rtsx_trace(chip);
2335 return STATUS_FAIL;
2336 }
Micky Chingfa590c22013-11-12 17:16:08 +08002337
2338 memcpy(ptr, rtsx_get_cmd_data(chip), 256);
2339 ptr += 256;
2340 }
2341
2342 if (buf_len%256) {
2343 rtsx_init_cmd(chip);
2344
2345 for (j = 0; j < buf_len%256; j++)
2346 rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
2347
2348 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002349 if (retval < 0) {
2350 rtsx_trace(chip);
2351 return STATUS_FAIL;
2352 }
Micky Chingfa590c22013-11-12 17:16:08 +08002353 }
2354
2355 memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256);
2356
2357 return STATUS_SUCCESS;
2358}
2359
2360int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
2361{
2362 int retval;
2363 int i, j;
2364 u16 reg_addr;
2365 u8 *ptr;
2366
Joe Perches031366e2015-03-25 12:54:25 -07002367 if (!buf) {
2368 rtsx_trace(chip);
2369 return STATUS_ERROR;
2370 }
Micky Chingfa590c22013-11-12 17:16:08 +08002371
2372 ptr = buf;
2373 reg_addr = PPBUF_BASE2;
2374 for (i = 0; i < buf_len/256; i++) {
2375 rtsx_init_cmd(chip);
2376
2377 for (j = 0; j < 256; j++) {
2378 rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002379 *ptr);
Micky Chingfa590c22013-11-12 17:16:08 +08002380 ptr++;
2381 }
2382
2383 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002384 if (retval < 0) {
2385 rtsx_trace(chip);
2386 return STATUS_FAIL;
2387 }
Micky Chingfa590c22013-11-12 17:16:08 +08002388 }
2389
2390 if (buf_len%256) {
2391 rtsx_init_cmd(chip);
2392
2393 for (j = 0; j < buf_len%256; j++) {
2394 rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
Giedrius Statkevičius21e69b72014-10-04 00:31:19 +03002395 *ptr);
Micky Chingfa590c22013-11-12 17:16:08 +08002396 ptr++;
2397 }
2398
2399 retval = rtsx_send_cmd(chip, 0, 250);
Joe Perches031366e2015-03-25 12:54:25 -07002400 if (retval < 0) {
2401 rtsx_trace(chip);
2402 return STATUS_FAIL;
2403 }
Micky Chingfa590c22013-11-12 17:16:08 +08002404 }
2405
2406 return STATUS_SUCCESS;
2407}
2408
2409int rtsx_check_chip_exist(struct rtsx_chip *chip)
2410{
Joe Perches031366e2015-03-25 12:54:25 -07002411 if (rtsx_readl(chip, 0) == 0xFFFFFFFF) {
2412 rtsx_trace(chip);
2413 return STATUS_FAIL;
2414 }
Micky Chingfa590c22013-11-12 17:16:08 +08002415
2416 return STATUS_SUCCESS;
2417}
2418
2419int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
2420{
2421 int retval;
2422 u8 mask = 0;
2423
2424 if (ctl & SSC_PDCTL)
2425 mask |= SSC_POWER_DOWN;
2426
2427#ifdef SUPPORT_OCP
2428 if (ctl & OC_PDCTL) {
2429 mask |= SD_OC_POWER_DOWN;
2430 if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
2431 mask |= MS_OC_POWER_DOWN;
2432 }
2433#endif
2434
2435 if (mask) {
2436 retval = rtsx_write_register(chip, FPDCTL, mask, 0);
Joe Perches031366e2015-03-25 12:54:25 -07002437 if (retval != STATUS_SUCCESS) {
2438 rtsx_trace(chip);
2439 return STATUS_FAIL;
2440 }
Micky Chingfa590c22013-11-12 17:16:08 +08002441
2442 if (CHECK_PID(chip, 0x5288))
2443 wait_timeout(200);
2444 }
2445
2446 return STATUS_SUCCESS;
2447}
2448
2449int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
2450{
2451 int retval;
2452 u8 mask = 0, val = 0;
2453
2454 if (ctl & SSC_PDCTL)
2455 mask |= SSC_POWER_DOWN;
2456
2457#ifdef SUPPORT_OCP
2458 if (ctl & OC_PDCTL) {
2459 mask |= SD_OC_POWER_DOWN;
2460 if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
2461 mask |= MS_OC_POWER_DOWN;
2462 }
2463#endif
2464
2465 if (mask) {
2466 val = mask;
2467 retval = rtsx_write_register(chip, FPDCTL, mask, val);
Joe Perches031366e2015-03-25 12:54:25 -07002468 if (retval != STATUS_SUCCESS) {
2469 rtsx_trace(chip);
2470 return STATUS_FAIL;
2471 }
Micky Chingfa590c22013-11-12 17:16:08 +08002472 }
2473
2474 return STATUS_SUCCESS;
2475}