| .. | .. |
|---|
| 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> |
|---|
| .. | .. |
|---|
| 34 | 22 | #include <asm/unaligned.h> |
|---|
| 35 | 23 | |
|---|
| 36 | 24 | #include "rtsx_pcr.h" |
|---|
| 25 | +#include "rts5261.h" |
|---|
| 26 | +#include "rts5228.h" |
|---|
| 37 | 27 | |
|---|
| 38 | 28 | static bool msi_en = true; |
|---|
| 39 | 29 | module_param(msi_en, bool, S_IRUGO | S_IWUSR); |
|---|
| .. | .. |
|---|
| 45 | 35 | static struct mfd_cell rtsx_pcr_cells[] = { |
|---|
| 46 | 36 | [RTSX_SD_CARD] = { |
|---|
| 47 | 37 | .name = DRV_NAME_RTSX_PCI_SDMMC, |
|---|
| 48 | | - }, |
|---|
| 49 | | - [RTSX_MS_CARD] = { |
|---|
| 50 | | - .name = DRV_NAME_RTSX_PCI_MS, |
|---|
| 51 | 38 | }, |
|---|
| 52 | 39 | }; |
|---|
| 53 | 40 | |
|---|
| .. | .. |
|---|
| 63 | 50 | { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
|---|
| 64 | 51 | { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
|---|
| 65 | 52 | { PCI_DEVICE(0x10EC, 0x5260), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
|---|
| 53 | + { PCI_DEVICE(0x10EC, 0x5261), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
|---|
| 54 | + { PCI_DEVICE(0x10EC, 0x5228), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
|---|
| 66 | 55 | { 0, } |
|---|
| 67 | 56 | }; |
|---|
| 68 | 57 | |
|---|
| 69 | 58 | MODULE_DEVICE_TABLE(pci, rtsx_pci_ids); |
|---|
| 70 | 59 | |
|---|
| 71 | | -static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr) |
|---|
| 72 | | -{ |
|---|
| 73 | | - rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL, |
|---|
| 74 | | - 0xFC, pcr->aspm_en); |
|---|
| 75 | | -} |
|---|
| 76 | | - |
|---|
| 77 | 60 | static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr) |
|---|
| 78 | 61 | { |
|---|
| 79 | | - rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL, |
|---|
| 80 | | - 0xFC, 0); |
|---|
| 62 | + pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, |
|---|
| 63 | + PCI_EXP_LNKCTL_ASPMC, 0); |
|---|
| 81 | 64 | } |
|---|
| 82 | 65 | |
|---|
| 83 | 66 | static int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency) |
|---|
| .. | .. |
|---|
| 98 | 81 | |
|---|
| 99 | 82 | int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency) |
|---|
| 100 | 83 | { |
|---|
| 101 | | - if (pcr->ops->set_ltr_latency) |
|---|
| 102 | | - return pcr->ops->set_ltr_latency(pcr, latency); |
|---|
| 103 | | - else |
|---|
| 104 | | - return rtsx_comm_set_ltr_latency(pcr, latency); |
|---|
| 84 | + return rtsx_comm_set_ltr_latency(pcr, latency); |
|---|
| 105 | 85 | } |
|---|
| 106 | 86 | |
|---|
| 107 | 87 | static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable) |
|---|
| 108 | 88 | { |
|---|
| 109 | | - struct rtsx_cr_option *option = &pcr->option; |
|---|
| 110 | | - |
|---|
| 111 | 89 | if (pcr->aspm_enabled == enable) |
|---|
| 112 | 90 | return; |
|---|
| 113 | 91 | |
|---|
| 114 | | - if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { |
|---|
| 115 | | - if (enable) |
|---|
| 116 | | - rtsx_pci_enable_aspm(pcr); |
|---|
| 117 | | - else |
|---|
| 118 | | - rtsx_pci_disable_aspm(pcr); |
|---|
| 119 | | - } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { |
|---|
| 120 | | - u8 mask = FORCE_ASPM_VAL_MASK; |
|---|
| 121 | | - u8 val = 0; |
|---|
| 122 | | - |
|---|
| 123 | | - if (enable) |
|---|
| 124 | | - val = pcr->aspm_en; |
|---|
| 125 | | - rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); |
|---|
| 126 | | - } |
|---|
| 92 | + pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, |
|---|
| 93 | + PCI_EXP_LNKCTL_ASPMC, |
|---|
| 94 | + enable ? pcr->aspm_en : 0); |
|---|
| 127 | 95 | |
|---|
| 128 | 96 | pcr->aspm_enabled = enable; |
|---|
| 129 | 97 | } |
|---|
| .. | .. |
|---|
| 167 | 135 | |
|---|
| 168 | 136 | static void rtsx_pm_full_on(struct rtsx_pcr *pcr) |
|---|
| 169 | 137 | { |
|---|
| 170 | | - if (pcr->ops->full_on) |
|---|
| 171 | | - pcr->ops->full_on(pcr); |
|---|
| 172 | | - else |
|---|
| 173 | | - rtsx_comm_pm_full_on(pcr); |
|---|
| 138 | + rtsx_comm_pm_full_on(pcr); |
|---|
| 174 | 139 | } |
|---|
| 175 | 140 | |
|---|
| 176 | 141 | void rtsx_pci_start_run(struct rtsx_pcr *pcr) |
|---|
| .. | .. |
|---|
| 243 | 208 | int err, i, finished = 0; |
|---|
| 244 | 209 | u8 tmp; |
|---|
| 245 | 210 | |
|---|
| 246 | | - rtsx_pci_init_cmd(pcr); |
|---|
| 247 | | - |
|---|
| 248 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val); |
|---|
| 249 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8)); |
|---|
| 250 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr); |
|---|
| 251 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81); |
|---|
| 252 | | - |
|---|
| 253 | | - err = rtsx_pci_send_cmd(pcr, 100); |
|---|
| 254 | | - if (err < 0) |
|---|
| 255 | | - return err; |
|---|
| 211 | + rtsx_pci_write_register(pcr, PHYDATA0, 0xFF, (u8)val); |
|---|
| 212 | + rtsx_pci_write_register(pcr, PHYDATA1, 0xFF, (u8)(val >> 8)); |
|---|
| 213 | + rtsx_pci_write_register(pcr, PHYADDR, 0xFF, addr); |
|---|
| 214 | + rtsx_pci_write_register(pcr, PHYRWCTL, 0xFF, 0x81); |
|---|
| 256 | 215 | |
|---|
| 257 | 216 | for (i = 0; i < 100000; i++) { |
|---|
| 258 | 217 | err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); |
|---|
| .. | .. |
|---|
| 284 | 243 | { |
|---|
| 285 | 244 | int err, i, finished = 0; |
|---|
| 286 | 245 | u16 data; |
|---|
| 287 | | - u8 *ptr, tmp; |
|---|
| 246 | + u8 tmp, val1, val2; |
|---|
| 288 | 247 | |
|---|
| 289 | | - rtsx_pci_init_cmd(pcr); |
|---|
| 290 | | - |
|---|
| 291 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr); |
|---|
| 292 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80); |
|---|
| 293 | | - |
|---|
| 294 | | - err = rtsx_pci_send_cmd(pcr, 100); |
|---|
| 295 | | - if (err < 0) |
|---|
| 296 | | - return err; |
|---|
| 248 | + rtsx_pci_write_register(pcr, PHYADDR, 0xFF, addr); |
|---|
| 249 | + rtsx_pci_write_register(pcr, PHYRWCTL, 0xFF, 0x80); |
|---|
| 297 | 250 | |
|---|
| 298 | 251 | for (i = 0; i < 100000; i++) { |
|---|
| 299 | 252 | err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); |
|---|
| .. | .. |
|---|
| 309 | 262 | if (!finished) |
|---|
| 310 | 263 | return -ETIMEDOUT; |
|---|
| 311 | 264 | |
|---|
| 312 | | - rtsx_pci_init_cmd(pcr); |
|---|
| 313 | | - |
|---|
| 314 | | - rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0); |
|---|
| 315 | | - rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0); |
|---|
| 316 | | - |
|---|
| 317 | | - err = rtsx_pci_send_cmd(pcr, 100); |
|---|
| 318 | | - if (err < 0) |
|---|
| 319 | | - return err; |
|---|
| 320 | | - |
|---|
| 321 | | - ptr = rtsx_pci_get_cmd_data(pcr); |
|---|
| 322 | | - data = ((u16)ptr[1] << 8) | ptr[0]; |
|---|
| 265 | + rtsx_pci_read_register(pcr, PHYDATA0, &val1); |
|---|
| 266 | + rtsx_pci_read_register(pcr, PHYDATA1, &val2); |
|---|
| 267 | + data = val1 | (val2 << 8); |
|---|
| 323 | 268 | |
|---|
| 324 | 269 | if (val) |
|---|
| 325 | 270 | *val = data; |
|---|
| .. | .. |
|---|
| 453 | 398 | |
|---|
| 454 | 399 | if (end) |
|---|
| 455 | 400 | option |= RTSX_SG_END; |
|---|
| 456 | | - val = ((u64)addr << 32) | ((u64)len << 12) | option; |
|---|
| 457 | 401 | |
|---|
| 402 | + if ((PCI_PID(pcr) == PID_5261) || (PCI_PID(pcr) == PID_5228)) { |
|---|
| 403 | + if (len > 0xFFFF) |
|---|
| 404 | + val = ((u64)addr << 32) | (((u64)len & 0xFFFF) << 16) |
|---|
| 405 | + | (((u64)len >> 16) << 6) | option; |
|---|
| 406 | + else |
|---|
| 407 | + val = ((u64)addr << 32) | ((u64)len << 16) | option; |
|---|
| 408 | + } else { |
|---|
| 409 | + val = ((u64)addr << 32) | ((u64)len << 12) | option; |
|---|
| 410 | + } |
|---|
| 458 | 411 | put_unaligned_le64(val, ptr); |
|---|
| 459 | 412 | pcr->sgi++; |
|---|
| 460 | 413 | } |
|---|
| .. | .. |
|---|
| 699 | 652 | else |
|---|
| 700 | 653 | return -EINVAL; |
|---|
| 701 | 654 | |
|---|
| 702 | | - |
|---|
| 703 | 655 | return rtsx_pci_set_pull_ctl(pcr, tbl); |
|---|
| 704 | 656 | } |
|---|
| 705 | 657 | EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable); |
|---|
| 706 | 658 | |
|---|
| 707 | 659 | static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr) |
|---|
| 708 | 660 | { |
|---|
| 709 | | - pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN; |
|---|
| 661 | + struct rtsx_hw_param *hw_param = &pcr->hw_param; |
|---|
| 662 | + |
|---|
| 663 | + pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN |
|---|
| 664 | + | hw_param->interrupt_en; |
|---|
| 710 | 665 | |
|---|
| 711 | 666 | if (pcr->num_slots > 1) |
|---|
| 712 | 667 | pcr->bier |= MS_INT_EN; |
|---|
| .. | .. |
|---|
| 746 | 701 | [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K, |
|---|
| 747 | 702 | [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K, |
|---|
| 748 | 703 | }; |
|---|
| 704 | + |
|---|
| 705 | + if (PCI_PID(pcr) == PID_5261) |
|---|
| 706 | + return rts5261_pci_switch_clock(pcr, card_clock, |
|---|
| 707 | + ssc_depth, initial_mode, double_clk, vpclk); |
|---|
| 708 | + if (PCI_PID(pcr) == PID_5228) |
|---|
| 709 | + return rts5228_pci_switch_clock(pcr, card_clock, |
|---|
| 710 | + ssc_depth, initial_mode, double_clk, vpclk); |
|---|
| 749 | 711 | |
|---|
| 750 | 712 | if (initial_mode) { |
|---|
| 751 | 713 | /* We use 250k(around) here, in initial stage */ |
|---|
| .. | .. |
|---|
| 972 | 934 | |
|---|
| 973 | 935 | static void rtsx_pci_process_ocp(struct rtsx_pcr *pcr) |
|---|
| 974 | 936 | { |
|---|
| 975 | | - if (pcr->ops->process_ocp) |
|---|
| 937 | + if (pcr->ops->process_ocp) { |
|---|
| 976 | 938 | pcr->ops->process_ocp(pcr); |
|---|
| 939 | + } else { |
|---|
| 940 | + if (!pcr->option.ocp_en) |
|---|
| 941 | + return; |
|---|
| 942 | + rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat); |
|---|
| 943 | + if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { |
|---|
| 944 | + rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); |
|---|
| 945 | + rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0); |
|---|
| 946 | + rtsx_pci_clear_ocpstat(pcr); |
|---|
| 947 | + pcr->ocp_stat = 0; |
|---|
| 948 | + } |
|---|
| 949 | + } |
|---|
| 977 | 950 | } |
|---|
| 978 | 951 | |
|---|
| 979 | 952 | static int rtsx_pci_process_ocp_interrupt(struct rtsx_pcr *pcr) |
|---|
| .. | .. |
|---|
| 1042 | 1015 | } |
|---|
| 1043 | 1016 | } |
|---|
| 1044 | 1017 | |
|---|
| 1045 | | - if (pcr->card_inserted || pcr->card_removed) |
|---|
| 1018 | + if ((pcr->card_inserted || pcr->card_removed) && !(int_reg & SD_OC_INT)) |
|---|
| 1046 | 1019 | schedule_delayed_work(&pcr->carddet_work, |
|---|
| 1047 | 1020 | msecs_to_jiffies(200)); |
|---|
| 1048 | 1021 | |
|---|
| .. | .. |
|---|
| 1099 | 1072 | |
|---|
| 1100 | 1073 | static void rtsx_pm_power_saving(struct rtsx_pcr *pcr) |
|---|
| 1101 | 1074 | { |
|---|
| 1102 | | - if (pcr->ops->power_saving) |
|---|
| 1103 | | - pcr->ops->power_saving(pcr); |
|---|
| 1104 | | - else |
|---|
| 1105 | | - rtsx_comm_pm_power_saving(pcr); |
|---|
| 1075 | + rtsx_comm_pm_power_saving(pcr); |
|---|
| 1106 | 1076 | } |
|---|
| 1107 | 1077 | |
|---|
| 1108 | 1078 | static void rtsx_pci_idle_work(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 1126 | 1096 | mutex_unlock(&pcr->pcr_mutex); |
|---|
| 1127 | 1097 | } |
|---|
| 1128 | 1098 | |
|---|
| 1129 | | -#ifdef CONFIG_PM |
|---|
| 1130 | | -static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) |
|---|
| 1099 | +static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) |
|---|
| 1100 | +{ |
|---|
| 1101 | + /* Set relink_time to 0 */ |
|---|
| 1102 | + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, MASK_8_BIT_DEF, 0); |
|---|
| 1103 | + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, MASK_8_BIT_DEF, 0); |
|---|
| 1104 | + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, |
|---|
| 1105 | + RELINK_TIME_MASK, 0); |
|---|
| 1106 | + |
|---|
| 1107 | + rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, |
|---|
| 1108 | + D3_DELINK_MODE_EN, D3_DELINK_MODE_EN); |
|---|
| 1109 | + |
|---|
| 1110 | + rtsx_pci_write_register(pcr, FPDCTL, ALL_POWER_DOWN, ALL_POWER_DOWN); |
|---|
| 1111 | +} |
|---|
| 1112 | + |
|---|
| 1113 | +static void __maybe_unused rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) |
|---|
| 1131 | 1114 | { |
|---|
| 1132 | 1115 | if (pcr->ops->turn_off_led) |
|---|
| 1133 | 1116 | pcr->ops->turn_off_led(pcr); |
|---|
| .. | .. |
|---|
| 1140 | 1123 | |
|---|
| 1141 | 1124 | if (pcr->ops->force_power_down) |
|---|
| 1142 | 1125 | pcr->ops->force_power_down(pcr, pm_state); |
|---|
| 1126 | + else |
|---|
| 1127 | + rtsx_base_force_power_down(pcr, pm_state); |
|---|
| 1143 | 1128 | } |
|---|
| 1144 | | -#endif |
|---|
| 1145 | 1129 | |
|---|
| 1146 | 1130 | void rtsx_pci_enable_ocp(struct rtsx_pcr *pcr) |
|---|
| 1147 | 1131 | { |
|---|
| 1148 | 1132 | u8 val = SD_OCP_INT_EN | SD_DETECT_EN; |
|---|
| 1149 | 1133 | |
|---|
| 1150 | | - if (pcr->ops->enable_ocp) |
|---|
| 1134 | + if (pcr->ops->enable_ocp) { |
|---|
| 1151 | 1135 | pcr->ops->enable_ocp(pcr); |
|---|
| 1152 | | - else |
|---|
| 1136 | + } else { |
|---|
| 1137 | + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0); |
|---|
| 1153 | 1138 | rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val); |
|---|
| 1139 | + } |
|---|
| 1154 | 1140 | |
|---|
| 1155 | 1141 | } |
|---|
| 1156 | 1142 | |
|---|
| .. | .. |
|---|
| 1158 | 1144 | { |
|---|
| 1159 | 1145 | u8 mask = SD_OCP_INT_EN | SD_DETECT_EN; |
|---|
| 1160 | 1146 | |
|---|
| 1161 | | - if (pcr->ops->disable_ocp) |
|---|
| 1147 | + if (pcr->ops->disable_ocp) { |
|---|
| 1162 | 1148 | pcr->ops->disable_ocp(pcr); |
|---|
| 1163 | | - else |
|---|
| 1149 | + } else { |
|---|
| 1164 | 1150 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); |
|---|
| 1151 | + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, |
|---|
| 1152 | + OC_POWER_DOWN); |
|---|
| 1153 | + } |
|---|
| 1165 | 1154 | } |
|---|
| 1166 | 1155 | |
|---|
| 1167 | 1156 | void rtsx_pci_init_ocp(struct rtsx_pcr *pcr) |
|---|
| .. | .. |
|---|
| 1172 | 1161 | struct rtsx_cr_option *option = &(pcr->option); |
|---|
| 1173 | 1162 | |
|---|
| 1174 | 1163 | if (option->ocp_en) { |
|---|
| 1175 | | - u8 val = option->sd_400mA_ocp_thd; |
|---|
| 1164 | + u8 val = option->sd_800mA_ocp_thd; |
|---|
| 1176 | 1165 | |
|---|
| 1177 | 1166 | rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0); |
|---|
| 1178 | 1167 | rtsx_pci_write_register(pcr, REG_OCPPARA1, |
|---|
| .. | .. |
|---|
| 1182 | 1171 | rtsx_pci_write_register(pcr, REG_OCPGLITCH, |
|---|
| 1183 | 1172 | SD_OCP_GLITCH_MASK, pcr->hw_param.ocp_glitch); |
|---|
| 1184 | 1173 | rtsx_pci_enable_ocp(pcr); |
|---|
| 1185 | | - } else { |
|---|
| 1186 | | - /* OC power down */ |
|---|
| 1187 | | - rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, |
|---|
| 1188 | | - OC_POWER_DOWN); |
|---|
| 1189 | 1174 | } |
|---|
| 1190 | 1175 | } |
|---|
| 1191 | 1176 | } |
|---|
| .. | .. |
|---|
| 1207 | 1192 | u8 val = SD_OCP_INT_CLR | SD_OC_CLR; |
|---|
| 1208 | 1193 | |
|---|
| 1209 | 1194 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val); |
|---|
| 1195 | + udelay(100); |
|---|
| 1210 | 1196 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); |
|---|
| 1211 | 1197 | } |
|---|
| 1198 | +} |
|---|
| 1199 | + |
|---|
| 1200 | +void rtsx_pci_enable_oobs_polling(struct rtsx_pcr *pcr) |
|---|
| 1201 | +{ |
|---|
| 1202 | + u16 val; |
|---|
| 1203 | + |
|---|
| 1204 | + if ((PCI_PID(pcr) != PID_525A) && (PCI_PID(pcr) != PID_5260)) { |
|---|
| 1205 | + rtsx_pci_read_phy_register(pcr, 0x01, &val); |
|---|
| 1206 | + val |= 1<<9; |
|---|
| 1207 | + rtsx_pci_write_phy_register(pcr, 0x01, val); |
|---|
| 1208 | + } |
|---|
| 1209 | + rtsx_pci_write_register(pcr, REG_CFG_OOBS_OFF_TIMER, 0xFF, 0x32); |
|---|
| 1210 | + rtsx_pci_write_register(pcr, REG_CFG_OOBS_ON_TIMER, 0xFF, 0x05); |
|---|
| 1211 | + rtsx_pci_write_register(pcr, REG_CFG_VCM_ON_TIMER, 0xFF, 0x83); |
|---|
| 1212 | + rtsx_pci_write_register(pcr, REG_CFG_OOBS_POLLING, 0xFF, 0xDE); |
|---|
| 1213 | + |
|---|
| 1214 | +} |
|---|
| 1215 | + |
|---|
| 1216 | +void rtsx_pci_disable_oobs_polling(struct rtsx_pcr *pcr) |
|---|
| 1217 | +{ |
|---|
| 1218 | + u16 val; |
|---|
| 1219 | + |
|---|
| 1220 | + if ((PCI_PID(pcr) != PID_525A) && (PCI_PID(pcr) != PID_5260)) { |
|---|
| 1221 | + rtsx_pci_read_phy_register(pcr, 0x01, &val); |
|---|
| 1222 | + val &= ~(1<<9); |
|---|
| 1223 | + rtsx_pci_write_phy_register(pcr, 0x01, val); |
|---|
| 1224 | + } |
|---|
| 1225 | + rtsx_pci_write_register(pcr, REG_CFG_VCM_ON_TIMER, 0xFF, 0x03); |
|---|
| 1226 | + rtsx_pci_write_register(pcr, REG_CFG_OOBS_POLLING, 0xFF, 0x00); |
|---|
| 1227 | + |
|---|
| 1212 | 1228 | } |
|---|
| 1213 | 1229 | |
|---|
| 1214 | 1230 | int rtsx_sd_power_off_card3v3(struct rtsx_pcr *pcr) |
|---|
| .. | .. |
|---|
| 1216 | 1232 | rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN | |
|---|
| 1217 | 1233 | MS_CLK_EN | SD40_CLK_EN, 0); |
|---|
| 1218 | 1234 | rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0); |
|---|
| 1219 | | - |
|---|
| 1220 | 1235 | rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); |
|---|
| 1221 | 1236 | |
|---|
| 1222 | 1237 | msleep(50); |
|---|
| .. | .. |
|---|
| 1241 | 1256 | |
|---|
| 1242 | 1257 | static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) |
|---|
| 1243 | 1258 | { |
|---|
| 1259 | + struct pci_dev *pdev = pcr->pci; |
|---|
| 1244 | 1260 | int err; |
|---|
| 1245 | 1261 | |
|---|
| 1246 | | - pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP); |
|---|
| 1262 | + if (PCI_PID(pcr) == PID_5228) |
|---|
| 1263 | + rtsx_pci_write_register(pcr, RTS5228_LDO1_CFG1, RTS5228_LDO1_SR_TIME_MASK, |
|---|
| 1264 | + RTS5228_LDO1_SR_0_5); |
|---|
| 1265 | + |
|---|
| 1247 | 1266 | rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr); |
|---|
| 1248 | 1267 | |
|---|
| 1249 | 1268 | rtsx_pci_enable_bus_int(pcr); |
|---|
| 1250 | 1269 | |
|---|
| 1251 | 1270 | /* Power on SSC */ |
|---|
| 1252 | | - err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0); |
|---|
| 1271 | + if (PCI_PID(pcr) == PID_5261) { |
|---|
| 1272 | + /* Gating real mcu clock */ |
|---|
| 1273 | + err = rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, |
|---|
| 1274 | + RTS5261_MCU_CLOCK_GATING, 0); |
|---|
| 1275 | + err = rtsx_pci_write_register(pcr, RTS5261_REG_FPDCTL, |
|---|
| 1276 | + SSC_POWER_DOWN, 0); |
|---|
| 1277 | + } else { |
|---|
| 1278 | + err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0); |
|---|
| 1279 | + } |
|---|
| 1253 | 1280 | if (err < 0) |
|---|
| 1254 | 1281 | return err; |
|---|
| 1255 | 1282 | |
|---|
| .. | .. |
|---|
| 1279 | 1306 | /* Enable SSC Clock */ |
|---|
| 1280 | 1307 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, |
|---|
| 1281 | 1308 | 0xFF, SSC_8X_EN | SSC_SEL_4M); |
|---|
| 1282 | | - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12); |
|---|
| 1309 | + if (PCI_PID(pcr) == PID_5261) |
|---|
| 1310 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, |
|---|
| 1311 | + RTS5261_SSC_DEPTH_2M); |
|---|
| 1312 | + else if (PCI_PID(pcr) == PID_5228) |
|---|
| 1313 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, |
|---|
| 1314 | + RTS5228_SSC_DEPTH_2M); |
|---|
| 1315 | + else |
|---|
| 1316 | + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12); |
|---|
| 1317 | + |
|---|
| 1283 | 1318 | /* Disable cd_pwr_save */ |
|---|
| 1284 | 1319 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10); |
|---|
| 1285 | 1320 | /* Clear Link Ready Interrupt */ |
|---|
| .. | .. |
|---|
| 1310 | 1345 | case PID_524A: |
|---|
| 1311 | 1346 | case PID_525A: |
|---|
| 1312 | 1347 | case PID_5260: |
|---|
| 1348 | + case PID_5261: |
|---|
| 1349 | + case PID_5228: |
|---|
| 1313 | 1350 | rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1); |
|---|
| 1314 | 1351 | break; |
|---|
| 1315 | 1352 | default: |
|---|
| 1316 | 1353 | break; |
|---|
| 1317 | 1354 | } |
|---|
| 1318 | 1355 | |
|---|
| 1356 | + /*init ocp*/ |
|---|
| 1357 | + rtsx_pci_init_ocp(pcr); |
|---|
| 1358 | + |
|---|
| 1319 | 1359 | /* Enable clk_request_n to enable clock power management */ |
|---|
| 1320 | | - rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1); |
|---|
| 1360 | + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, |
|---|
| 1361 | + PCI_EXP_LNKCTL_CLKREQ_EN); |
|---|
| 1321 | 1362 | /* Enter L1 when host tx idle */ |
|---|
| 1322 | | - rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B); |
|---|
| 1363 | + pci_write_config_byte(pdev, 0x70F, 0x5B); |
|---|
| 1323 | 1364 | |
|---|
| 1324 | 1365 | if (pcr->ops->extra_init_hw) { |
|---|
| 1325 | 1366 | err = pcr->ops->extra_init_hw(pcr); |
|---|
| .. | .. |
|---|
| 1386 | 1427 | case 0x5286: |
|---|
| 1387 | 1428 | rtl8402_init_params(pcr); |
|---|
| 1388 | 1429 | break; |
|---|
| 1430 | + |
|---|
| 1389 | 1431 | case 0x5260: |
|---|
| 1390 | 1432 | rts5260_init_params(pcr); |
|---|
| 1433 | + break; |
|---|
| 1434 | + |
|---|
| 1435 | + case 0x5261: |
|---|
| 1436 | + rts5261_init_params(pcr); |
|---|
| 1437 | + break; |
|---|
| 1438 | + |
|---|
| 1439 | + case 0x5228: |
|---|
| 1440 | + rts5228_init_params(pcr); |
|---|
| 1391 | 1441 | break; |
|---|
| 1392 | 1442 | } |
|---|
| 1393 | 1443 | |
|---|
| .. | .. |
|---|
| 1476 | 1526 | bar = 1; |
|---|
| 1477 | 1527 | len = pci_resource_len(pcidev, bar); |
|---|
| 1478 | 1528 | base = pci_resource_start(pcidev, bar); |
|---|
| 1479 | | - pcr->remap_addr = ioremap_nocache(base, len); |
|---|
| 1529 | + pcr->remap_addr = ioremap(base, len); |
|---|
| 1480 | 1530 | if (!pcr->remap_addr) { |
|---|
| 1481 | 1531 | ret = -ENOMEM; |
|---|
| 1482 | | - goto free_handle; |
|---|
| 1532 | + goto free_idr; |
|---|
| 1483 | 1533 | } |
|---|
| 1484 | 1534 | |
|---|
| 1485 | 1535 | pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev), |
|---|
| .. | .. |
|---|
| 1541 | 1591 | pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr); |
|---|
| 1542 | 1592 | unmap: |
|---|
| 1543 | 1593 | iounmap(pcr->remap_addr); |
|---|
| 1594 | +free_idr: |
|---|
| 1595 | + spin_lock(&rtsx_pci_lock); |
|---|
| 1596 | + idr_remove(&rtsx_pci_idr, pcr->id); |
|---|
| 1597 | + spin_unlock(&rtsx_pci_lock); |
|---|
| 1544 | 1598 | free_handle: |
|---|
| 1545 | 1599 | kfree(handle); |
|---|
| 1546 | 1600 | free_pcr: |
|---|
| .. | .. |
|---|
| 1594 | 1648 | pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device); |
|---|
| 1595 | 1649 | } |
|---|
| 1596 | 1650 | |
|---|
| 1597 | | -#ifdef CONFIG_PM |
|---|
| 1598 | | - |
|---|
| 1599 | | -static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state) |
|---|
| 1651 | +static int __maybe_unused rtsx_pci_suspend(struct device *dev_d) |
|---|
| 1600 | 1652 | { |
|---|
| 1653 | + struct pci_dev *pcidev = to_pci_dev(dev_d); |
|---|
| 1601 | 1654 | struct pcr_handle *handle; |
|---|
| 1602 | 1655 | struct rtsx_pcr *pcr; |
|---|
| 1603 | 1656 | |
|---|
| .. | .. |
|---|
| 1613 | 1666 | |
|---|
| 1614 | 1667 | rtsx_pci_power_off(pcr, HOST_ENTER_S3); |
|---|
| 1615 | 1668 | |
|---|
| 1616 | | - pci_save_state(pcidev); |
|---|
| 1617 | | - pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); |
|---|
| 1618 | | - pci_disable_device(pcidev); |
|---|
| 1619 | | - pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); |
|---|
| 1669 | + device_wakeup_disable(dev_d); |
|---|
| 1620 | 1670 | |
|---|
| 1621 | 1671 | mutex_unlock(&pcr->pcr_mutex); |
|---|
| 1622 | 1672 | return 0; |
|---|
| 1623 | 1673 | } |
|---|
| 1624 | 1674 | |
|---|
| 1625 | | -static int rtsx_pci_resume(struct pci_dev *pcidev) |
|---|
| 1675 | +static int __maybe_unused rtsx_pci_resume(struct device *dev_d) |
|---|
| 1626 | 1676 | { |
|---|
| 1677 | + struct pci_dev *pcidev = to_pci_dev(dev_d); |
|---|
| 1627 | 1678 | struct pcr_handle *handle; |
|---|
| 1628 | 1679 | struct rtsx_pcr *pcr; |
|---|
| 1629 | 1680 | int ret = 0; |
|---|
| .. | .. |
|---|
| 1634 | 1685 | pcr = handle->pcr; |
|---|
| 1635 | 1686 | |
|---|
| 1636 | 1687 | mutex_lock(&pcr->pcr_mutex); |
|---|
| 1637 | | - |
|---|
| 1638 | | - pci_set_power_state(pcidev, PCI_D0); |
|---|
| 1639 | | - pci_restore_state(pcidev); |
|---|
| 1640 | | - ret = pci_enable_device(pcidev); |
|---|
| 1641 | | - if (ret) |
|---|
| 1642 | | - goto out; |
|---|
| 1643 | | - pci_set_master(pcidev); |
|---|
| 1644 | 1688 | |
|---|
| 1645 | 1689 | ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00); |
|---|
| 1646 | 1690 | if (ret) |
|---|
| .. | .. |
|---|
| 1656 | 1700 | mutex_unlock(&pcr->pcr_mutex); |
|---|
| 1657 | 1701 | return ret; |
|---|
| 1658 | 1702 | } |
|---|
| 1703 | + |
|---|
| 1704 | +#ifdef CONFIG_PM |
|---|
| 1659 | 1705 | |
|---|
| 1660 | 1706 | static void rtsx_pci_shutdown(struct pci_dev *pcidev) |
|---|
| 1661 | 1707 | { |
|---|
| .. | .. |
|---|
| 1676 | 1722 | |
|---|
| 1677 | 1723 | #else /* CONFIG_PM */ |
|---|
| 1678 | 1724 | |
|---|
| 1679 | | -#define rtsx_pci_suspend NULL |
|---|
| 1680 | | -#define rtsx_pci_resume NULL |
|---|
| 1681 | 1725 | #define rtsx_pci_shutdown NULL |
|---|
| 1682 | 1726 | |
|---|
| 1683 | 1727 | #endif /* CONFIG_PM */ |
|---|
| 1728 | + |
|---|
| 1729 | +static SIMPLE_DEV_PM_OPS(rtsx_pci_pm_ops, rtsx_pci_suspend, rtsx_pci_resume); |
|---|
| 1684 | 1730 | |
|---|
| 1685 | 1731 | static struct pci_driver rtsx_pci_driver = { |
|---|
| 1686 | 1732 | .name = DRV_NAME_RTSX_PCI, |
|---|
| 1687 | 1733 | .id_table = rtsx_pci_ids, |
|---|
| 1688 | 1734 | .probe = rtsx_pci_probe, |
|---|
| 1689 | 1735 | .remove = rtsx_pci_remove, |
|---|
| 1690 | | - .suspend = rtsx_pci_suspend, |
|---|
| 1691 | | - .resume = rtsx_pci_resume, |
|---|
| 1736 | + .driver.pm = &rtsx_pci_pm_ops, |
|---|
| 1692 | 1737 | .shutdown = rtsx_pci_shutdown, |
|---|
| 1693 | 1738 | }; |
|---|
| 1694 | 1739 | module_pci_driver(rtsx_pci_driver); |
|---|