.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Driver for Realtek PCI-Express card reader |
---|
2 | 3 | * |
---|
3 | 4 | * 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 | 5 | * |
---|
18 | 6 | * Author: |
---|
19 | 7 | * Wei WANG <wei_wang@realsil.com.cn> |
---|
.. | .. |
---|
68 | 56 | |
---|
69 | 57 | static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) |
---|
70 | 58 | { |
---|
| 59 | + struct pci_dev *pdev = pcr->pci; |
---|
71 | 60 | u32 reg; |
---|
72 | 61 | |
---|
73 | | - rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); |
---|
| 62 | + pci_read_config_dword(pdev, PCR_SETTING_REG1, ®); |
---|
74 | 63 | pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); |
---|
75 | 64 | |
---|
76 | 65 | if (!rtsx_vendor_setting_valid(reg)) |
---|
.. | .. |
---|
81 | 70 | pcr->card_drive_sel &= 0x3F; |
---|
82 | 71 | pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); |
---|
83 | 72 | |
---|
84 | | - rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); |
---|
| 73 | + pci_read_config_dword(pdev, PCR_SETTING_REG2, ®); |
---|
85 | 74 | pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); |
---|
| 75 | + if (rtsx_check_mmc_support(reg)) |
---|
| 76 | + pcr->extra_caps |= EXTRA_CAPS_NO_MMC; |
---|
86 | 77 | pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); |
---|
87 | 78 | if (rtsx_reg_check_reverse_socket(reg)) |
---|
88 | 79 | pcr->flags |= PCR_REVERSE_SOCKET; |
---|
89 | 80 | } |
---|
90 | 81 | |
---|
91 | | -static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) |
---|
| 82 | +static void rts5227_init_from_cfg(struct rtsx_pcr *pcr) |
---|
92 | 83 | { |
---|
93 | | - /* Set relink_time to 0 */ |
---|
94 | | - rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); |
---|
95 | | - rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); |
---|
96 | | - rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); |
---|
| 84 | + struct pci_dev *pdev = pcr->pci; |
---|
| 85 | + int l1ss; |
---|
| 86 | + u32 lval; |
---|
| 87 | + struct rtsx_cr_option *option = &pcr->option; |
---|
97 | 88 | |
---|
98 | | - if (pm_state == HOST_ENTER_S3) |
---|
99 | | - rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10); |
---|
| 89 | + l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); |
---|
| 90 | + if (!l1ss) |
---|
| 91 | + return; |
---|
100 | 92 | |
---|
101 | | - rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); |
---|
| 93 | + pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); |
---|
| 94 | + |
---|
| 95 | + if (CHK_PCI_PID(pcr, 0x522A)) { |
---|
| 96 | + if (0 == (lval & 0x0F)) |
---|
| 97 | + rtsx_pci_enable_oobs_polling(pcr); |
---|
| 98 | + else |
---|
| 99 | + rtsx_pci_disable_oobs_polling(pcr); |
---|
| 100 | + } |
---|
| 101 | + |
---|
| 102 | + if (lval & PCI_L1SS_CTL1_ASPM_L1_1) |
---|
| 103 | + rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); |
---|
| 104 | + else |
---|
| 105 | + rtsx_clear_dev_flag(pcr, ASPM_L1_1_EN); |
---|
| 106 | + |
---|
| 107 | + if (lval & PCI_L1SS_CTL1_ASPM_L1_2) |
---|
| 108 | + rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); |
---|
| 109 | + else |
---|
| 110 | + rtsx_clear_dev_flag(pcr, ASPM_L1_2_EN); |
---|
| 111 | + |
---|
| 112 | + if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) |
---|
| 113 | + rtsx_set_dev_flag(pcr, PM_L1_1_EN); |
---|
| 114 | + else |
---|
| 115 | + rtsx_clear_dev_flag(pcr, PM_L1_1_EN); |
---|
| 116 | + |
---|
| 117 | + if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) |
---|
| 118 | + rtsx_set_dev_flag(pcr, PM_L1_2_EN); |
---|
| 119 | + else |
---|
| 120 | + rtsx_clear_dev_flag(pcr, PM_L1_2_EN); |
---|
| 121 | + |
---|
| 122 | + if (option->ltr_en) { |
---|
| 123 | + u16 val; |
---|
| 124 | + |
---|
| 125 | + pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val); |
---|
| 126 | + if (val & PCI_EXP_DEVCTL2_LTR_EN) { |
---|
| 127 | + option->ltr_enabled = true; |
---|
| 128 | + option->ltr_active = true; |
---|
| 129 | + rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
---|
| 130 | + } else { |
---|
| 131 | + option->ltr_enabled = false; |
---|
| 132 | + } |
---|
| 133 | + } |
---|
| 134 | + |
---|
| 135 | + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN |
---|
| 136 | + | PM_L1_1_EN | PM_L1_2_EN)) |
---|
| 137 | + option->force_clkreq_0 = false; |
---|
| 138 | + else |
---|
| 139 | + option->force_clkreq_0 = true; |
---|
| 140 | + |
---|
102 | 141 | } |
---|
103 | 142 | |
---|
104 | 143 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) |
---|
105 | 144 | { |
---|
106 | 145 | u16 cap; |
---|
| 146 | + struct rtsx_cr_option *option = &pcr->option; |
---|
107 | 147 | |
---|
| 148 | + rts5227_init_from_cfg(pcr); |
---|
108 | 149 | rtsx_pci_init_cmd(pcr); |
---|
109 | 150 | |
---|
110 | 151 | /* Configure GPIO as output */ |
---|
.. | .. |
---|
126 | 167 | rts5227_fill_driving(pcr, OUTPUT_3V3); |
---|
127 | 168 | /* Configure force_clock_req */ |
---|
128 | 169 | if (pcr->flags & PCR_REVERSE_SOCKET) |
---|
129 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8); |
---|
| 170 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x30); |
---|
130 | 171 | else |
---|
131 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88); |
---|
| 172 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x00); |
---|
| 173 | + |
---|
| 174 | + if (option->force_clkreq_0) |
---|
| 175 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, |
---|
| 176 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
---|
| 177 | + else |
---|
| 178 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, |
---|
| 179 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); |
---|
| 180 | + |
---|
132 | 181 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00); |
---|
133 | 182 | |
---|
134 | 183 | return rtsx_pci_send_cmd(pcr, 100); |
---|
.. | .. |
---|
170 | 219 | { |
---|
171 | 220 | int err; |
---|
172 | 221 | |
---|
| 222 | + if (pcr->option.ocp_en) |
---|
| 223 | + rtsx_pci_enable_ocp(pcr); |
---|
| 224 | + |
---|
173 | 225 | rtsx_pci_init_cmd(pcr); |
---|
174 | 226 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, |
---|
175 | 227 | SD_POWER_MASK, SD_PARTIAL_POWER_ON); |
---|
| 228 | + |
---|
176 | 229 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, |
---|
177 | 230 | LDO3318_PWR_MASK, 0x02); |
---|
| 231 | + |
---|
178 | 232 | err = rtsx_pci_send_cmd(pcr, 100); |
---|
179 | 233 | if (err < 0) |
---|
180 | 234 | return err; |
---|
181 | 235 | |
---|
182 | 236 | /* To avoid too large in-rush current */ |
---|
183 | | - udelay(150); |
---|
184 | | - |
---|
| 237 | + msleep(20); |
---|
185 | 238 | rtsx_pci_init_cmd(pcr); |
---|
186 | 239 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, |
---|
187 | 240 | SD_POWER_MASK, SD_POWER_ON); |
---|
| 241 | + |
---|
188 | 242 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, |
---|
189 | 243 | LDO3318_PWR_MASK, 0x06); |
---|
| 244 | + |
---|
| 245 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, |
---|
| 246 | + SD_OUTPUT_EN, SD_OUTPUT_EN); |
---|
| 247 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, |
---|
| 248 | + MS_OUTPUT_EN, MS_OUTPUT_EN); |
---|
190 | 249 | return rtsx_pci_send_cmd(pcr, 100); |
---|
191 | 250 | } |
---|
192 | 251 | |
---|
193 | 252 | static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) |
---|
194 | 253 | { |
---|
195 | | - rtsx_pci_init_cmd(pcr); |
---|
196 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, |
---|
197 | | - SD_POWER_MASK | PMOS_STRG_MASK, |
---|
198 | | - SD_POWER_OFF | PMOS_STRG_400mA); |
---|
199 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, |
---|
200 | | - LDO3318_PWR_MASK, 0X00); |
---|
201 | | - return rtsx_pci_send_cmd(pcr, 100); |
---|
| 254 | + if (pcr->option.ocp_en) |
---|
| 255 | + rtsx_pci_disable_ocp(pcr); |
---|
| 256 | + |
---|
| 257 | + rtsx_pci_write_register(pcr, CARD_PWR_CTL, SD_POWER_MASK | |
---|
| 258 | + PMOS_STRG_MASK, SD_POWER_OFF | PMOS_STRG_400mA); |
---|
| 259 | + rtsx_pci_write_register(pcr, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0X00); |
---|
| 260 | + |
---|
| 261 | + return 0; |
---|
202 | 262 | } |
---|
203 | 263 | |
---|
204 | 264 | static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
---|
.. | .. |
---|
239 | 299 | .switch_output_voltage = rts5227_switch_output_voltage, |
---|
240 | 300 | .cd_deglitch = NULL, |
---|
241 | 301 | .conv_clk_and_div_n = NULL, |
---|
242 | | - .force_power_down = rts5227_force_power_down, |
---|
243 | 302 | }; |
---|
244 | 303 | |
---|
245 | 304 | /* SD Pull Control Enable: |
---|
.. | .. |
---|
353 | 412 | return 0; |
---|
354 | 413 | } |
---|
355 | 414 | |
---|
| 415 | +static int rts522a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
---|
| 416 | +{ |
---|
| 417 | + int err; |
---|
| 418 | + |
---|
| 419 | + if (voltage == OUTPUT_3V3) { |
---|
| 420 | + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x57E4); |
---|
| 421 | + if (err < 0) |
---|
| 422 | + return err; |
---|
| 423 | + } else if (voltage == OUTPUT_1V8) { |
---|
| 424 | + err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); |
---|
| 425 | + if (err < 0) |
---|
| 426 | + return err; |
---|
| 427 | + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x54A4); |
---|
| 428 | + if (err < 0) |
---|
| 429 | + return err; |
---|
| 430 | + } else { |
---|
| 431 | + return -EINVAL; |
---|
| 432 | + } |
---|
| 433 | + |
---|
| 434 | + /* set pad drive */ |
---|
| 435 | + rtsx_pci_init_cmd(pcr); |
---|
| 436 | + rts5227_fill_driving(pcr, voltage); |
---|
| 437 | + return rtsx_pci_send_cmd(pcr, 100); |
---|
| 438 | +} |
---|
| 439 | + |
---|
| 440 | +static void rts522a_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active) |
---|
| 441 | +{ |
---|
| 442 | + struct rtsx_cr_option *option = &pcr->option; |
---|
| 443 | + int aspm_L1_1, aspm_L1_2; |
---|
| 444 | + u8 val = 0; |
---|
| 445 | + |
---|
| 446 | + aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN); |
---|
| 447 | + aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN); |
---|
| 448 | + |
---|
| 449 | + if (active) { |
---|
| 450 | + /* run, latency: 60us */ |
---|
| 451 | + if (aspm_L1_1) |
---|
| 452 | + val = option->ltr_l1off_snooze_sspwrgate; |
---|
| 453 | + } else { |
---|
| 454 | + /* l1off, latency: 300us */ |
---|
| 455 | + if (aspm_L1_2) |
---|
| 456 | + val = option->ltr_l1off_sspwrgate; |
---|
| 457 | + } |
---|
| 458 | + |
---|
| 459 | + rtsx_set_l1off_sub(pcr, val); |
---|
| 460 | +} |
---|
| 461 | + |
---|
356 | 462 | /* rts522a operations mainly derived from rts5227, except phy/hw init setting. |
---|
357 | 463 | */ |
---|
358 | 464 | static const struct pcr_ops rts522a_pcr_ops = { |
---|
.. | .. |
---|
365 | 471 | .disable_auto_blink = rts5227_disable_auto_blink, |
---|
366 | 472 | .card_power_on = rts5227_card_power_on, |
---|
367 | 473 | .card_power_off = rts5227_card_power_off, |
---|
368 | | - .switch_output_voltage = rts5227_switch_output_voltage, |
---|
| 474 | + .switch_output_voltage = rts522a_switch_output_voltage, |
---|
369 | 475 | .cd_deglitch = NULL, |
---|
370 | 476 | .conv_clk_and_div_n = NULL, |
---|
371 | | - .force_power_down = rts5227_force_power_down, |
---|
| 477 | + .set_l1off_cfg_sub_d0 = rts522a_set_l1off_cfg_sub_d0, |
---|
372 | 478 | }; |
---|
373 | 479 | |
---|
374 | 480 | void rts522a_init_params(struct rtsx_pcr *pcr) |
---|
375 | 481 | { |
---|
| 482 | + struct rtsx_cr_option *option = &pcr->option; |
---|
| 483 | + |
---|
376 | 484 | rts5227_init_params(pcr); |
---|
377 | 485 | pcr->ops = &rts522a_pcr_ops; |
---|
378 | 486 | pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11); |
---|
379 | 487 | pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3; |
---|
| 488 | + |
---|
| 489 | + option->dev_flags = LTR_L1SS_PWR_GATE_EN; |
---|
| 490 | + option->ltr_en = true; |
---|
| 491 | + |
---|
| 492 | + /* init latency of active, idle, L1OFF to 60us, 300us, 3ms */ |
---|
| 493 | + option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF; |
---|
| 494 | + option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF; |
---|
| 495 | + option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF; |
---|
| 496 | + option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF; |
---|
| 497 | + option->ltr_l1off_sspwrgate = 0x7F; |
---|
| 498 | + option->ltr_l1off_snooze_sspwrgate = 0x78; |
---|
| 499 | + |
---|
| 500 | + pcr->option.ocp_en = 1; |
---|
| 501 | + if (pcr->option.ocp_en) |
---|
| 502 | + pcr->hw_param.interrupt_en |= SD_OC_INT_EN; |
---|
| 503 | + pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M; |
---|
| 504 | + pcr->option.sd_800mA_ocp_thd = RTS522A_OCP_THD_800; |
---|
| 505 | + |
---|
380 | 506 | } |
---|