rts5209.c (7329B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* Driver for Realtek PCI-Express card reader 3 * 4 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 5 * 6 * Author: 7 * Wei WANG <wei_wang@realsil.com.cn> 8 */ 9 10#include <linux/module.h> 11#include <linux/delay.h> 12#include <linux/rtsx_pci.h> 13 14#include "rtsx_pcr.h" 15 16static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr) 17{ 18 u8 val; 19 20 val = rtsx_pci_readb(pcr, 0x1C); 21 return val & 0x0F; 22} 23 24static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr) 25{ 26 struct pci_dev *pdev = pcr->pci; 27 u32 reg; 28 29 pci_read_config_dword(pdev, PCR_SETTING_REG1, ®); 30 pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); 31 32 if (rts5209_vendor_setting1_valid(reg)) { 33 if (rts5209_reg_check_ms_pmos(reg)) 34 pcr->flags |= PCR_MS_PMOS; 35 pcr->aspm_en = rts5209_reg_to_aspm(reg); 36 } 37 38 pci_read_config_dword(pdev, PCR_SETTING_REG2, ®); 39 pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); 40 41 if (rts5209_vendor_setting2_valid(reg)) { 42 pcr->sd30_drive_sel_1v8 = 43 rts5209_reg_to_sd30_drive_sel_1v8(reg); 44 pcr->sd30_drive_sel_3v3 = 45 rts5209_reg_to_sd30_drive_sel_3v3(reg); 46 pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg); 47 } 48} 49 50static void rts5209_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool runtime) 51{ 52 rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); 53} 54 55static int rts5209_extra_init_hw(struct rtsx_pcr *pcr) 56{ 57 rtsx_pci_init_cmd(pcr); 58 59 /* Turn off LED */ 60 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03); 61 /* Reset ASPM state to default value */ 62 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); 63 /* Force CLKREQ# PIN to drive 0 to request clock */ 64 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08); 65 /* Configure GPIO as output */ 66 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03); 67 /* Configure driving */ 68 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 69 0xFF, pcr->sd30_drive_sel_3v3); 70 71 return rtsx_pci_send_cmd(pcr, 100); 72} 73 74static int rts5209_optimize_phy(struct rtsx_pcr *pcr) 75{ 76 return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966); 77} 78 79static int rts5209_turn_on_led(struct rtsx_pcr *pcr) 80{ 81 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); 82} 83 84static int rts5209_turn_off_led(struct rtsx_pcr *pcr) 85{ 86 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01); 87} 88 89static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr) 90{ 91 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D); 92} 93 94static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr) 95{ 96 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00); 97} 98 99static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) 100{ 101 int err; 102 u8 pwr_mask, partial_pwr_on, pwr_on; 103 104 pwr_mask = SD_POWER_MASK; 105 partial_pwr_on = SD_PARTIAL_POWER_ON; 106 pwr_on = SD_POWER_ON; 107 108 if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) { 109 pwr_mask = MS_POWER_MASK; 110 partial_pwr_on = MS_PARTIAL_POWER_ON; 111 pwr_on = MS_POWER_ON; 112 } 113 114 rtsx_pci_init_cmd(pcr); 115 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 116 pwr_mask, partial_pwr_on); 117 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 118 LDO3318_PWR_MASK, 0x04); 119 err = rtsx_pci_send_cmd(pcr, 100); 120 if (err < 0) 121 return err; 122 123 /* To avoid too large in-rush current */ 124 udelay(150); 125 126 rtsx_pci_init_cmd(pcr); 127 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on); 128 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 129 LDO3318_PWR_MASK, 0x00); 130 return rtsx_pci_send_cmd(pcr, 100); 131} 132 133static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) 134{ 135 u8 pwr_mask, pwr_off; 136 137 pwr_mask = SD_POWER_MASK; 138 pwr_off = SD_POWER_OFF; 139 140 if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) { 141 pwr_mask = MS_POWER_MASK; 142 pwr_off = MS_POWER_OFF; 143 } 144 145 rtsx_pci_init_cmd(pcr); 146 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 147 pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA); 148 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 149 LDO3318_PWR_MASK, 0x06); 150 return rtsx_pci_send_cmd(pcr, 100); 151} 152 153static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 154{ 155 int err; 156 157 if (voltage == OUTPUT_3V3) { 158 err = rtsx_pci_write_register(pcr, 159 SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); 160 if (err < 0) 161 return err; 162 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); 163 if (err < 0) 164 return err; 165 } else if (voltage == OUTPUT_1V8) { 166 err = rtsx_pci_write_register(pcr, 167 SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); 168 if (err < 0) 169 return err; 170 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); 171 if (err < 0) 172 return err; 173 } else { 174 return -EINVAL; 175 } 176 177 return 0; 178} 179 180static const struct pcr_ops rts5209_pcr_ops = { 181 .fetch_vendor_settings = rts5209_fetch_vendor_settings, 182 .extra_init_hw = rts5209_extra_init_hw, 183 .optimize_phy = rts5209_optimize_phy, 184 .turn_on_led = rts5209_turn_on_led, 185 .turn_off_led = rts5209_turn_off_led, 186 .enable_auto_blink = rts5209_enable_auto_blink, 187 .disable_auto_blink = rts5209_disable_auto_blink, 188 .card_power_on = rts5209_card_power_on, 189 .card_power_off = rts5209_card_power_off, 190 .switch_output_voltage = rts5209_switch_output_voltage, 191 .cd_deglitch = NULL, 192 .conv_clk_and_div_n = NULL, 193 .force_power_down = rts5209_force_power_down, 194}; 195 196/* SD Pull Control Enable: 197 * SD_DAT[3:0] ==> pull up 198 * SD_CD ==> pull up 199 * SD_WP ==> pull up 200 * SD_CMD ==> pull up 201 * SD_CLK ==> pull down 202 */ 203static const u32 rts5209_sd_pull_ctl_enable_tbl[] = { 204 RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 205 RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 206 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), 207 0, 208}; 209 210/* SD Pull Control Disable: 211 * SD_DAT[3:0] ==> pull down 212 * SD_CD ==> pull up 213 * SD_WP ==> pull down 214 * SD_CMD ==> pull down 215 * SD_CLK ==> pull down 216 */ 217static const u32 rts5209_sd_pull_ctl_disable_tbl[] = { 218 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55), 219 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 220 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), 221 0, 222}; 223 224/* MS Pull Control Enable: 225 * MS CD ==> pull up 226 * others ==> pull down 227 */ 228static const u32 rts5209_ms_pull_ctl_enable_tbl[] = { 229 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 230 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 231 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 232 0, 233}; 234 235/* MS Pull Control Disable: 236 * MS CD ==> pull up 237 * others ==> pull down 238 */ 239static const u32 rts5209_ms_pull_ctl_disable_tbl[] = { 240 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 241 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 242 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 243 0, 244}; 245 246void rts5209_init_params(struct rtsx_pcr *pcr) 247{ 248 pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | 249 EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT; 250 pcr->num_slots = 2; 251 pcr->ops = &rts5209_pcr_ops; 252 253 pcr->flags = 0; 254 pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT; 255 pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; 256 pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; 257 pcr->aspm_en = ASPM_L1_EN; 258 pcr->aspm_mode = ASPM_MODE_CFG; 259 pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16); 260 pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); 261 262 pcr->ic_version = rts5209_get_ic_version(pcr); 263 pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl; 264 pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl; 265 pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl; 266 pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl; 267}