18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Driver for Realtek PCI-Express card reader 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: 78c2ecf20Sopenharmony_ci * Wei WANG <wei_wang@realsil.com.cn> 88c2ecf20Sopenharmony_ci * Roger Tseng <rogerable@realtek.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/bitops.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/rtsx_pci.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "rtsx_pcr.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci u8 val; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci rtsx_pci_read_register(pcr, SYS_VER, &val); 238c2ecf20Sopenharmony_ci return val & 0x0F; 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci u8 val = 0; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (val & 0x2) 338c2ecf20Sopenharmony_ci return 1; 348c2ecf20Sopenharmony_ci else 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct pci_dev *pdev = pcr->pci; 418c2ecf20Sopenharmony_ci u32 reg1 = 0; 428c2ecf20Sopenharmony_ci u8 reg3 = 0; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, PCR_SETTING_REG1, ®1); 458c2ecf20Sopenharmony_ci pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (!rtsx_vendor_setting_valid(reg1)) 488c2ecf20Sopenharmony_ci return; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci pcr->aspm_en = rtsx_reg_to_aspm(reg1); 518c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_1v8 = 528c2ecf20Sopenharmony_ci map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1)); 538c2ecf20Sopenharmony_ci pcr->card_drive_sel &= 0x3F; 548c2ecf20Sopenharmony_ci pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, PCR_SETTING_REG3, ®3); 578c2ecf20Sopenharmony_ci pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3); 588c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct pci_dev *pdev = pcr->pci; 648c2ecf20Sopenharmony_ci u32 reg = 0; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, PCR_SETTING_REG1, ®); 678c2ecf20Sopenharmony_ci pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (!rtsx_vendor_setting_valid(reg)) 708c2ecf20Sopenharmony_ci return; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci pcr->aspm_en = rtsx_reg_to_aspm(reg); 738c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_1v8 = 748c2ecf20Sopenharmony_ci map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg)); 758c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_3v3 = 768c2ecf20Sopenharmony_ci map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci rtsx_pci_init_cmd(pcr); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 898c2ecf20Sopenharmony_ci 0xFF, pcr->sd30_drive_sel_3v3); 908c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, 918c2ecf20Sopenharmony_ci CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return rtsx_pci_send_cmd(pcr, 100); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci rtsx_pci_init_cmd(pcr); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (rtl8411b_is_qfn48(pcr)) 1018c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 1028c2ecf20Sopenharmony_ci CARD_PULL_CTL3, 0xFF, 0xF5); 1038c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 1048c2ecf20Sopenharmony_ci 0xFF, pcr->sd30_drive_sel_3v3); 1058c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, 1068c2ecf20Sopenharmony_ci CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 1078c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL, 1088c2ecf20Sopenharmony_ci 0x06, 0x00); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return rtsx_pci_send_cmd(pcr, 100); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int rtl8411_turn_on_led(struct rtsx_pcr *pcr) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic int rtl8411_turn_off_led(struct rtsx_pcr *pcr) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci int err; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci rtsx_pci_init_cmd(pcr); 1388c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 1398c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 1408c2ecf20Sopenharmony_ci rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL, 1418c2ecf20Sopenharmony_ci BPP_LDO_POWB, BPP_LDO_SUSPEND); 1428c2ecf20Sopenharmony_ci err = rtsx_pci_send_cmd(pcr, 100); 1438c2ecf20Sopenharmony_ci if (err < 0) 1448c2ecf20Sopenharmony_ci return err; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* To avoid too large in-rush current */ 1478c2ecf20Sopenharmony_ci udelay(150); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 1508c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON); 1518c2ecf20Sopenharmony_ci if (err < 0) 1528c2ecf20Sopenharmony_ci return err; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci udelay(150); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 1578c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON); 1588c2ecf20Sopenharmony_ci if (err < 0) 1598c2ecf20Sopenharmony_ci return err; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci udelay(150); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 1648c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_ON); 1658c2ecf20Sopenharmony_ci if (err < 0) 1668c2ecf20Sopenharmony_ci return err; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci int err; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 1768c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_OFF); 1778c2ecf20Sopenharmony_ci if (err < 0) 1788c2ecf20Sopenharmony_ci return err; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, LDO_CTL, 1818c2ecf20Sopenharmony_ci BPP_LDO_POWB, BPP_LDO_SUSPEND); 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage, 1858c2ecf20Sopenharmony_ci int bpp_tuned18_shift, int bpp_asic_1v8) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci u8 mask, val; 1888c2ecf20Sopenharmony_ci int err; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK; 1918c2ecf20Sopenharmony_ci if (voltage == OUTPUT_3V3) { 1928c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, 1938c2ecf20Sopenharmony_ci SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); 1948c2ecf20Sopenharmony_ci if (err < 0) 1958c2ecf20Sopenharmony_ci return err; 1968c2ecf20Sopenharmony_ci val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3; 1978c2ecf20Sopenharmony_ci } else if (voltage == OUTPUT_1V8) { 1988c2ecf20Sopenharmony_ci err = rtsx_pci_write_register(pcr, 1998c2ecf20Sopenharmony_ci SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); 2008c2ecf20Sopenharmony_ci if (err < 0) 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8; 2038c2ecf20Sopenharmony_ci } else { 2048c2ecf20Sopenharmony_ci return -EINVAL; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci return rtl8411_do_switch_output_voltage(pcr, voltage, 2138c2ecf20Sopenharmony_ci BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci return rtl8411_do_switch_output_voltage(pcr, voltage, 2198c2ecf20Sopenharmony_ci BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0); 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci unsigned int card_exist; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 2278c2ecf20Sopenharmony_ci card_exist &= CARD_EXIST; 2288c2ecf20Sopenharmony_ci if (!card_exist) { 2298c2ecf20Sopenharmony_ci /* Enable card CD */ 2308c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, CD_PAD_CTL, 2318c2ecf20Sopenharmony_ci CD_DISABLE_MASK, CD_ENABLE); 2328c2ecf20Sopenharmony_ci /* Enable card interrupt */ 2338c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00); 2348c2ecf20Sopenharmony_ci return 0; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (hweight32(card_exist) > 1) { 2388c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, CARD_PWR_CTL, 2398c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 2408c2ecf20Sopenharmony_ci msleep(100); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 2438c2ecf20Sopenharmony_ci if (card_exist & MS_EXIST) 2448c2ecf20Sopenharmony_ci card_exist = MS_EXIST; 2458c2ecf20Sopenharmony_ci else if (card_exist & SD_EXIST) 2468c2ecf20Sopenharmony_ci card_exist = SD_EXIST; 2478c2ecf20Sopenharmony_ci else 2488c2ecf20Sopenharmony_ci card_exist = 0; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, CARD_PWR_CTL, 2518c2ecf20Sopenharmony_ci BPP_POWER_MASK, BPP_POWER_OFF); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n", 2548c2ecf20Sopenharmony_ci card_exist); 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (card_exist & MS_EXIST) { 2588c2ecf20Sopenharmony_ci /* Disable SD interrupt */ 2598c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40); 2608c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, CD_PAD_CTL, 2618c2ecf20Sopenharmony_ci CD_DISABLE_MASK, MS_CD_EN_ONLY); 2628c2ecf20Sopenharmony_ci } else if (card_exist & SD_EXIST) { 2638c2ecf20Sopenharmony_ci /* Disable MS interrupt */ 2648c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80); 2658c2ecf20Sopenharmony_ci rtsx_pci_write_register(pcr, CD_PAD_CTL, 2668c2ecf20Sopenharmony_ci CD_DISABLE_MASK, SD_CD_EN_ONLY); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return card_exist; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic int rtl8411_conv_clk_and_div_n(int input, int dir) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci int output; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (dir == CLK_TO_DIV_N) 2778c2ecf20Sopenharmony_ci output = input * 4 / 5 - 2; 2788c2ecf20Sopenharmony_ci else 2798c2ecf20Sopenharmony_ci output = (input + 2) * 5 / 4; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return output; 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic const struct pcr_ops rtl8411_pcr_ops = { 2858c2ecf20Sopenharmony_ci .fetch_vendor_settings = rtl8411_fetch_vendor_settings, 2868c2ecf20Sopenharmony_ci .extra_init_hw = rtl8411_extra_init_hw, 2878c2ecf20Sopenharmony_ci .optimize_phy = NULL, 2888c2ecf20Sopenharmony_ci .turn_on_led = rtl8411_turn_on_led, 2898c2ecf20Sopenharmony_ci .turn_off_led = rtl8411_turn_off_led, 2908c2ecf20Sopenharmony_ci .enable_auto_blink = rtl8411_enable_auto_blink, 2918c2ecf20Sopenharmony_ci .disable_auto_blink = rtl8411_disable_auto_blink, 2928c2ecf20Sopenharmony_ci .card_power_on = rtl8411_card_power_on, 2938c2ecf20Sopenharmony_ci .card_power_off = rtl8411_card_power_off, 2948c2ecf20Sopenharmony_ci .switch_output_voltage = rtl8411_switch_output_voltage, 2958c2ecf20Sopenharmony_ci .cd_deglitch = rtl8411_cd_deglitch, 2968c2ecf20Sopenharmony_ci .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 2978c2ecf20Sopenharmony_ci .force_power_down = rtl8411_force_power_down, 2988c2ecf20Sopenharmony_ci}; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic const struct pcr_ops rtl8402_pcr_ops = { 3018c2ecf20Sopenharmony_ci .fetch_vendor_settings = rtl8411_fetch_vendor_settings, 3028c2ecf20Sopenharmony_ci .extra_init_hw = rtl8411_extra_init_hw, 3038c2ecf20Sopenharmony_ci .optimize_phy = NULL, 3048c2ecf20Sopenharmony_ci .turn_on_led = rtl8411_turn_on_led, 3058c2ecf20Sopenharmony_ci .turn_off_led = rtl8411_turn_off_led, 3068c2ecf20Sopenharmony_ci .enable_auto_blink = rtl8411_enable_auto_blink, 3078c2ecf20Sopenharmony_ci .disable_auto_blink = rtl8411_disable_auto_blink, 3088c2ecf20Sopenharmony_ci .card_power_on = rtl8411_card_power_on, 3098c2ecf20Sopenharmony_ci .card_power_off = rtl8411_card_power_off, 3108c2ecf20Sopenharmony_ci .switch_output_voltage = rtl8402_switch_output_voltage, 3118c2ecf20Sopenharmony_ci .cd_deglitch = rtl8411_cd_deglitch, 3128c2ecf20Sopenharmony_ci .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 3138c2ecf20Sopenharmony_ci .force_power_down = rtl8411_force_power_down, 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic const struct pcr_ops rtl8411b_pcr_ops = { 3178c2ecf20Sopenharmony_ci .fetch_vendor_settings = rtl8411b_fetch_vendor_settings, 3188c2ecf20Sopenharmony_ci .extra_init_hw = rtl8411b_extra_init_hw, 3198c2ecf20Sopenharmony_ci .optimize_phy = NULL, 3208c2ecf20Sopenharmony_ci .turn_on_led = rtl8411_turn_on_led, 3218c2ecf20Sopenharmony_ci .turn_off_led = rtl8411_turn_off_led, 3228c2ecf20Sopenharmony_ci .enable_auto_blink = rtl8411_enable_auto_blink, 3238c2ecf20Sopenharmony_ci .disable_auto_blink = rtl8411_disable_auto_blink, 3248c2ecf20Sopenharmony_ci .card_power_on = rtl8411_card_power_on, 3258c2ecf20Sopenharmony_ci .card_power_off = rtl8411_card_power_off, 3268c2ecf20Sopenharmony_ci .switch_output_voltage = rtl8411_switch_output_voltage, 3278c2ecf20Sopenharmony_ci .cd_deglitch = rtl8411_cd_deglitch, 3288c2ecf20Sopenharmony_ci .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 3298c2ecf20Sopenharmony_ci .force_power_down = rtl8411_force_power_down, 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/* SD Pull Control Enable: 3338c2ecf20Sopenharmony_ci * SD_DAT[3:0] ==> pull up 3348c2ecf20Sopenharmony_ci * SD_CD ==> pull up 3358c2ecf20Sopenharmony_ci * SD_WP ==> pull up 3368c2ecf20Sopenharmony_ci * SD_CMD ==> pull up 3378c2ecf20Sopenharmony_ci * SD_CLK ==> pull down 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_cistatic const u32 rtl8411_sd_pull_ctl_enable_tbl[] = { 3408c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 3418c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 3428c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9), 3438c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 3448c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09), 3458c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 3468c2ecf20Sopenharmony_ci 0, 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/* SD Pull Control Disable: 3508c2ecf20Sopenharmony_ci * SD_DAT[3:0] ==> pull down 3518c2ecf20Sopenharmony_ci * SD_CD ==> pull up 3528c2ecf20Sopenharmony_ci * SD_WP ==> pull down 3538c2ecf20Sopenharmony_ci * SD_CMD ==> pull down 3548c2ecf20Sopenharmony_ci * SD_CLK ==> pull down 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_cistatic const u32 rtl8411_sd_pull_ctl_disable_tbl[] = { 3578c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 3588c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 3598c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 3608c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 3618c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 3628c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 3638c2ecf20Sopenharmony_ci 0, 3648c2ecf20Sopenharmony_ci}; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci/* MS Pull Control Enable: 3678c2ecf20Sopenharmony_ci * MS CD ==> pull up 3688c2ecf20Sopenharmony_ci * others ==> pull down 3698c2ecf20Sopenharmony_ci */ 3708c2ecf20Sopenharmony_cistatic const u32 rtl8411_ms_pull_ctl_enable_tbl[] = { 3718c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 3728c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 3738c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 3748c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05), 3758c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 3768c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 3778c2ecf20Sopenharmony_ci 0, 3788c2ecf20Sopenharmony_ci}; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* MS Pull Control Disable: 3818c2ecf20Sopenharmony_ci * MS CD ==> pull up 3828c2ecf20Sopenharmony_ci * others ==> pull down 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_cistatic const u32 rtl8411_ms_pull_ctl_disable_tbl[] = { 3858c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 3868c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 3878c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 3888c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 3898c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 3908c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 3918c2ecf20Sopenharmony_ci 0, 3928c2ecf20Sopenharmony_ci}; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = { 3958c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 3968c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 3978c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0), 3988c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 3998c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 4008c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4018c2ecf20Sopenharmony_ci 0, 4028c2ecf20Sopenharmony_ci}; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = { 4058c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 4068c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90), 4078c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11), 4088c2ecf20Sopenharmony_ci 0, 4098c2ecf20Sopenharmony_ci}; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = { 4128c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 4138c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4148c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 4158c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 4168c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 4178c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4188c2ecf20Sopenharmony_ci 0, 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = { 4228c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4238c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 4248c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4258c2ecf20Sopenharmony_ci 0, 4268c2ecf20Sopenharmony_ci}; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = { 4298c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 4308c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4318c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 4328c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50), 4338c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 4348c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4358c2ecf20Sopenharmony_ci 0, 4368c2ecf20Sopenharmony_ci}; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = { 4398c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4408c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 4418c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4428c2ecf20Sopenharmony_ci 0, 4438c2ecf20Sopenharmony_ci}; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = { 4468c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 4478c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4488c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 4498c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 4508c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 4518c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4528c2ecf20Sopenharmony_ci 0, 4538c2ecf20Sopenharmony_ci}; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = { 4568c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 4578c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 4588c2ecf20Sopenharmony_ci RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 4598c2ecf20Sopenharmony_ci 0, 4608c2ecf20Sopenharmony_ci}; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic void rtl8411_init_common_params(struct rtsx_pcr *pcr) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; 4658c2ecf20Sopenharmony_ci pcr->num_slots = 2; 4668c2ecf20Sopenharmony_ci pcr->flags = 0; 4678c2ecf20Sopenharmony_ci pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; 4688c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; 4698c2ecf20Sopenharmony_ci pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; 4708c2ecf20Sopenharmony_ci pcr->aspm_en = ASPM_L1_EN; 4718c2ecf20Sopenharmony_ci pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); 4728c2ecf20Sopenharmony_ci pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); 4738c2ecf20Sopenharmony_ci pcr->ic_version = rtl8411_get_ic_version(pcr); 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_civoid rtl8411_init_params(struct rtsx_pcr *pcr) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci rtl8411_init_common_params(pcr); 4798c2ecf20Sopenharmony_ci pcr->ops = &rtl8411_pcr_ops; 4808c2ecf20Sopenharmony_ci set_pull_ctrl_tables(pcr, rtl8411); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_civoid rtl8411b_init_params(struct rtsx_pcr *pcr) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci rtl8411_init_common_params(pcr); 4868c2ecf20Sopenharmony_ci pcr->ops = &rtl8411b_pcr_ops; 4878c2ecf20Sopenharmony_ci if (rtl8411b_is_qfn48(pcr)) 4888c2ecf20Sopenharmony_ci set_pull_ctrl_tables(pcr, rtl8411b_qfn48); 4898c2ecf20Sopenharmony_ci else 4908c2ecf20Sopenharmony_ci set_pull_ctrl_tables(pcr, rtl8411b_qfn64); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_civoid rtl8402_init_params(struct rtsx_pcr *pcr) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci rtl8411_init_common_params(pcr); 4968c2ecf20Sopenharmony_ci pcr->ops = &rtl8402_pcr_ops; 4978c2ecf20Sopenharmony_ci set_pull_ctrl_tables(pcr, rtl8411); 4988c2ecf20Sopenharmony_ci} 499