2019-05-19 15:51:47 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2017-11-29 17:09:56 +08:00
/* Driver for Realtek PCI-Express card reader
*
* Copyright ( c ) 2016 - 2017 Realtek Semiconductor Corp . All rights reserved .
*
* Author :
* Steven FENG < steven_feng @ realsil . com . cn >
* Rui FENG < rui_feng @ realsil . com . cn >
* Wei WANG < wei_wang @ realsil . com . cn >
*/
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/rtsx_pci.h>
# include "rts5260.h"
# include "rtsx_pcr.h"
static u8 rts5260_get_ic_version ( struct rtsx_pcr * pcr )
{
u8 val ;
rtsx_pci_read_register ( pcr , DUMMY_REG_RESET_0 , & val ) ;
return val & IC_VERSION_MASK ;
}
static void rts5260_fill_driving ( struct rtsx_pcr * pcr , u8 voltage )
{
2020-09-07 18:07:31 +08:00
u8 driving_3v3 [ 4 ] [ 3 ] = {
{ 0x11 , 0x11 , 0x11 } ,
{ 0x22 , 0x22 , 0x22 } ,
{ 0x55 , 0x55 , 0x55 } ,
{ 0x33 , 0x33 , 0x33 } ,
2017-11-29 17:09:56 +08:00
} ;
2020-09-07 18:07:31 +08:00
u8 driving_1v8 [ 4 ] [ 3 ] = {
{ 0x35 , 0x33 , 0x33 } ,
{ 0x8A , 0x88 , 0x88 } ,
{ 0xBD , 0xBB , 0xBB } ,
2017-11-29 17:09:56 +08:00
{ 0x9B , 0x99 , 0x99 } ,
} ;
u8 ( * driving ) [ 3 ] , drive_sel ;
if ( voltage = = OUTPUT_3V3 ) {
driving = driving_3v3 ;
drive_sel = pcr - > sd30_drive_sel_3v3 ;
} else {
driving = driving_1v8 ;
drive_sel = pcr - > sd30_drive_sel_1v8 ;
}
2019-02-19 20:49:58 +08:00
rtsx_pci_write_register ( pcr , SD30_CLK_DRIVE_SEL ,
2017-11-29 17:09:56 +08:00
0xFF , driving [ drive_sel ] [ 0 ] ) ;
2019-02-19 20:49:58 +08:00
rtsx_pci_write_register ( pcr , SD30_CMD_DRIVE_SEL ,
2017-11-29 17:09:56 +08:00
0xFF , driving [ drive_sel ] [ 1 ] ) ;
2019-02-19 20:49:58 +08:00
2020-09-07 18:07:31 +08:00
rtsx_pci_write_register ( pcr , SD30_DAT_DRIVE_SEL ,
2017-11-29 17:09:56 +08:00
0xFF , driving [ drive_sel ] [ 2 ] ) ;
}
static void rtsx_base_fetch_vendor_settings ( struct rtsx_pcr * pcr )
{
2020-07-21 16:23:34 -05:00
struct pci_dev * pdev = pcr - > pci ;
2017-11-29 17:09:56 +08:00
u32 reg ;
2020-07-21 16:23:34 -05:00
pci_read_config_dword ( pdev , PCR_SETTING_REG1 , & reg ) ;
2017-11-29 17:09:56 +08:00
pcr_dbg ( pcr , " Cfg 0x%x: 0x%x \n " , PCR_SETTING_REG1 , reg ) ;
if ( ! rtsx_vendor_setting_valid ( reg ) ) {
pcr_dbg ( pcr , " skip fetch vendor setting \n " ) ;
return ;
}
pcr - > aspm_en = rtsx_reg_to_aspm ( reg ) ;
pcr - > sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8 ( reg ) ;
pcr - > card_drive_sel & = 0x3F ;
pcr - > card_drive_sel | = rtsx_reg_to_card_drive_sel ( reg ) ;
2020-07-21 16:23:34 -05:00
pci_read_config_dword ( pdev , PCR_SETTING_REG2 , & reg ) ;
2017-11-29 17:09:56 +08:00
pcr_dbg ( pcr , " Cfg 0x%x: 0x%x \n " , PCR_SETTING_REG2 , reg ) ;
2020-09-07 18:07:31 +08:00
if ( rtsx_check_mmc_support ( reg ) )
pcr - > extra_caps | = EXTRA_CAPS_NO_MMC ;
2017-11-29 17:09:56 +08:00
pcr - > sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3 ( reg ) ;
if ( rtsx_reg_check_reverse_socket ( reg ) )
pcr - > flags | = PCR_REVERSE_SOCKET ;
}
static int rtsx_base_enable_auto_blink ( struct rtsx_pcr * pcr )
{
return rtsx_pci_write_register ( pcr , OLT_LED_CTL ,
LED_SHINE_MASK , LED_SHINE_EN ) ;
}
static int rtsx_base_disable_auto_blink ( struct rtsx_pcr * pcr )
{
return rtsx_pci_write_register ( pcr , OLT_LED_CTL ,
LED_SHINE_MASK , LED_SHINE_DISABLE ) ;
}
static int rts5260_turn_on_led ( struct rtsx_pcr * pcr )
{
return rtsx_pci_write_register ( pcr , RTS5260_REG_GPIO_CTL0 ,
RTS5260_REG_GPIO_MASK , RTS5260_REG_GPIO_ON ) ;
}
static int rts5260_turn_off_led ( struct rtsx_pcr * pcr )
{
return rtsx_pci_write_register ( pcr , RTS5260_REG_GPIO_CTL0 ,
RTS5260_REG_GPIO_MASK , RTS5260_REG_GPIO_OFF ) ;
}
/* SD Pull Control Enable:
* SD_DAT [ 3 : 0 ] = = > pull up
* SD_CD = = > pull up
* SD_WP = = > pull up
* SD_CMD = = > pull up
* SD_CLK = = > pull down
*/
static const u32 rts5260_sd_pull_ctl_enable_tbl [ ] = {
RTSX_REG_PAIR ( CARD_PULL_CTL1 , 0x66 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL2 , 0xAA ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL3 , 0xE9 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL4 , 0xAA ) ,
0 ,
} ;
/* SD Pull Control Disable:
* SD_DAT [ 3 : 0 ] = = > pull down
* SD_CD = = > pull up
* SD_WP = = > pull down
* SD_CMD = = > pull down
* SD_CLK = = > pull down
*/
static const u32 rts5260_sd_pull_ctl_disable_tbl [ ] = {
RTSX_REG_PAIR ( CARD_PULL_CTL1 , 0x66 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL2 , 0x55 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL3 , 0xD5 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL4 , 0x55 ) ,
0 ,
} ;
/* MS Pull Control Enable:
* MS CD = = > pull up
* others = = > pull down
*/
static const u32 rts5260_ms_pull_ctl_enable_tbl [ ] = {
RTSX_REG_PAIR ( CARD_PULL_CTL4 , 0x55 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL5 , 0x55 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL6 , 0x15 ) ,
0 ,
} ;
/* MS Pull Control Disable:
* MS CD = = > pull up
* others = = > pull down
*/
static const u32 rts5260_ms_pull_ctl_disable_tbl [ ] = {
RTSX_REG_PAIR ( CARD_PULL_CTL4 , 0x55 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL5 , 0x55 ) ,
RTSX_REG_PAIR ( CARD_PULL_CTL6 , 0x15 ) ,
0 ,
} ;
static int sd_set_sample_push_timing_sd30 ( struct rtsx_pcr * pcr )
{
rtsx_pci_write_register ( pcr , SD_CFG1 , SD_MODE_SELECT_MASK
| SD_ASYNC_FIFO_NOT_RST , SD_30_MODE | SD_ASYNC_FIFO_NOT_RST ) ;
rtsx_pci_write_register ( pcr , CLK_CTL , CLK_LOW_FREQ , CLK_LOW_FREQ ) ;
rtsx_pci_write_register ( pcr , CARD_CLK_SOURCE , 0xFF ,
2019-02-19 20:49:58 +08:00
CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1 ) ;
2017-11-29 17:09:56 +08:00
rtsx_pci_write_register ( pcr , CLK_CTL , CLK_LOW_FREQ , 0 ) ;
return 0 ;
}
static int rts5260_card_power_on ( struct rtsx_pcr * pcr , int card )
{
struct rtsx_cr_option * option = & pcr - > option ;
if ( option - > ocp_en )
rtsx_pci_enable_ocp ( pcr ) ;
2019-02-19 20:49:58 +08:00
rtsx_pci_write_register ( pcr , LDO_CONFIG2 , DV331812_VDD1 , DV331812_VDD1 ) ;
rtsx_pci_write_register ( pcr , LDO_VCC_CFG0 ,
2017-11-29 17:09:56 +08:00
RTS5260_DVCC_TUNE_MASK , RTS5260_DVCC_33 ) ;
2019-02-19 20:49:58 +08:00
rtsx_pci_write_register ( pcr , LDO_VCC_CFG1 , LDO_POW_SDVDD1_MASK ,
LDO_POW_SDVDD1_ON ) ;
rtsx_pci_write_register ( pcr , LDO_CONFIG2 ,
DV331812_POWERON , DV331812_POWERON ) ;
2017-11-29 17:09:56 +08:00
msleep ( 20 ) ;
if ( pcr - > extra_caps & EXTRA_CAPS_SD_SDR50 | |
pcr - > extra_caps & EXTRA_CAPS_SD_SDR104 )
sd_set_sample_push_timing_sd30 ( pcr ) ;
/* Initialize SD_CFG1 register */
rtsx_pci_write_register ( pcr , SD_CFG1 , 0xFF ,
SD_CLK_DIVIDE_128 | SD_20_MODE ) ;
rtsx_pci_write_register ( pcr , SD_SAMPLE_POINT_CTL ,
0xFF , SD20_RX_POS_EDGE ) ;
rtsx_pci_write_register ( pcr , SD_PUSH_POINT_CTL , 0xFF , 0 ) ;
rtsx_pci_write_register ( pcr , CARD_STOP , SD_STOP | SD_CLR_ERR ,
SD_STOP | SD_CLR_ERR ) ;
/* Reset SD_CFG3 register */
rtsx_pci_write_register ( pcr , SD_CFG3 , SD30_CLK_END_EN , 0 ) ;
rtsx_pci_write_register ( pcr , REG_SD_STOP_SDCLK_CFG ,
2019-02-19 20:49:58 +08:00
SD30_CLK_STOP_CFG_EN | SD30_CLK_STOP_CFG1 |
SD30_CLK_STOP_CFG0 , 0 ) ;
2017-11-29 17:09:56 +08:00
rtsx_pci_write_register ( pcr , REG_PRE_RW_MODE , EN_INFINITE_MODE , 0 ) ;
2019-09-13 01:04:01 +08:00
return 0 ;
2017-11-29 17:09:56 +08:00
}
static int rts5260_switch_output_voltage ( struct rtsx_pcr * pcr , u8 voltage )
{
switch ( voltage ) {
case OUTPUT_3V3 :
rtsx_pci_write_register ( pcr , LDO_CONFIG2 ,
DV331812_VDD1 , DV331812_VDD1 ) ;
rtsx_pci_write_register ( pcr , LDO_DV18_CFG ,
DV331812_MASK , DV331812_33 ) ;
rtsx_pci_write_register ( pcr , SD_PAD_CTL , SD_IO_USING_1V8 , 0 ) ;
break ;
case OUTPUT_1V8 :
rtsx_pci_write_register ( pcr , LDO_CONFIG2 ,
DV331812_VDD1 , DV331812_VDD1 ) ;
rtsx_pci_write_register ( pcr , LDO_DV18_CFG ,
DV331812_MASK , DV331812_17 ) ;
rtsx_pci_write_register ( pcr , SD_PAD_CTL , SD_IO_USING_1V8 ,
SD_IO_USING_1V8 ) ;
break ;
default :
return - EINVAL ;
}
/* set pad drive */
rts5260_fill_driving ( pcr , voltage ) ;
2019-02-19 20:49:58 +08:00
return 0 ;
2017-11-29 17:09:56 +08:00
}
static void rts5260_stop_cmd ( struct rtsx_pcr * pcr )
{
rtsx_pci_writel ( pcr , RTSX_HCBCTLR , STOP_CMD ) ;
rtsx_pci_writel ( pcr , RTSX_HDBCTLR , STOP_DMA ) ;
rtsx_pci_write_register ( pcr , RTS5260_DMA_RST_CTL_0 ,
RTS5260_DMA_RST | RTS5260_ADMA3_RST ,
RTS5260_DMA_RST | RTS5260_ADMA3_RST ) ;
rtsx_pci_write_register ( pcr , RBCTL , RB_FLUSH , RB_FLUSH ) ;
}
static void rts5260_card_before_power_off ( struct rtsx_pcr * pcr )
{
rts5260_stop_cmd ( pcr ) ;
rts5260_switch_output_voltage ( pcr , OUTPUT_3V3 ) ;
}
static int rts5260_card_power_off ( struct rtsx_pcr * pcr , int card )
{
int err = 0 ;
rts5260_card_before_power_off ( pcr ) ;
2019-02-19 20:49:58 +08:00
err = rtsx_pci_write_register ( pcr , LDO_VCC_CFG1 ,
2017-11-29 17:09:56 +08:00
LDO_POW_SDVDD1_MASK , LDO_POW_SDVDD1_OFF ) ;
2019-02-19 20:49:58 +08:00
err = rtsx_pci_write_register ( pcr , LDO_CONFIG2 ,
2017-11-29 17:09:56 +08:00
DV331812_POWERON , DV331812_POWEROFF ) ;
2019-02-19 20:49:58 +08:00
if ( pcr - > option . ocp_en )
rtsx_pci_disable_ocp ( pcr ) ;
2017-11-29 17:09:56 +08:00
return err ;
}
static void rts5260_init_ocp ( struct rtsx_pcr * pcr )
{
struct rtsx_cr_option * option = & pcr - > option ;
if ( option - > ocp_en ) {
u8 mask , val ;
rtsx_pci_write_register ( pcr , RTS5260_DVCC_CTRL ,
2019-02-19 20:49:58 +08:00
RTS5260_DVCC_OCP_THD_MASK ,
option - > sd_800mA_ocp_thd ) ;
2017-11-29 17:09:56 +08:00
rtsx_pci_write_register ( pcr , RTS5260_DV331812_CFG ,
2019-02-19 20:49:58 +08:00
RTS5260_DV331812_OCP_THD_MASK ,
RTS5260_DV331812_OCP_THD_270 ) ;
2017-11-29 17:09:56 +08:00
2019-02-19 20:49:58 +08:00
mask = SD_OCP_GLITCH_MASK ;
2017-11-29 17:09:56 +08:00
val = pcr - > hw_param . ocp_glitch ;
rtsx_pci_write_register ( pcr , REG_OCPGLITCH , mask , val ) ;
2019-02-19 20:49:58 +08:00
rtsx_pci_write_register ( pcr , RTS5260_DVCC_CTRL ,
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN ,
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN ) ;
2017-11-29 17:09:56 +08:00
rtsx_pci_enable_ocp ( pcr ) ;
} else {
rtsx_pci_write_register ( pcr , RTS5260_DVCC_CTRL ,
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN , 0 ) ;
}
}
static void rts5260_enable_ocp ( struct rtsx_pcr * pcr )
{
u8 val = 0 ;
val = SD_OCP_INT_EN | SD_DETECT_EN ;
rtsx_pci_write_register ( pcr , REG_OCPCTL , 0xFF , val ) ;
2019-02-19 20:49:58 +08:00
2017-11-29 17:09:56 +08:00
}
static void rts5260_disable_ocp ( struct rtsx_pcr * pcr )
{
u8 mask = 0 ;
mask = SD_OCP_INT_EN | SD_DETECT_EN ;
rtsx_pci_write_register ( pcr , REG_OCPCTL , mask , 0 ) ;
}
2019-02-19 20:49:58 +08:00
2018-02-07 13:23:27 +00:00
static int rts5260_get_ocpstat ( struct rtsx_pcr * pcr , u8 * val )
2017-11-29 17:09:56 +08:00
{
return rtsx_pci_read_register ( pcr , REG_OCPSTAT , val ) ;
}
2018-02-07 13:23:27 +00:00
static int rts5260_get_ocpstat2 ( struct rtsx_pcr * pcr , u8 * val )
2017-11-29 17:09:56 +08:00
{
return rtsx_pci_read_register ( pcr , REG_DV3318_OCPSTAT , val ) ;
}
2018-02-07 13:23:27 +00:00
static void rts5260_clear_ocpstat ( struct rtsx_pcr * pcr )
2017-11-29 17:09:56 +08:00
{
u8 mask = 0 ;
u8 val = 0 ;
mask = SD_OCP_INT_CLR | SD_OC_CLR ;
val = SD_OCP_INT_CLR | SD_OC_CLR ;
rtsx_pci_write_register ( pcr , REG_OCPCTL , mask , val ) ;
rtsx_pci_write_register ( pcr , REG_DV3318_OCPCTL ,
DV3318_OCP_INT_CLR | DV3318_OCP_CLR ,
DV3318_OCP_INT_CLR | DV3318_OCP_CLR ) ;
udelay ( 10 ) ;
rtsx_pci_write_register ( pcr , REG_OCPCTL , mask , 0 ) ;
rtsx_pci_write_register ( pcr , REG_DV3318_OCPCTL ,
DV3318_OCP_INT_CLR | DV3318_OCP_CLR , 0 ) ;
}
2018-02-07 13:23:27 +00:00
static void rts5260_process_ocp ( struct rtsx_pcr * pcr )
2017-11-29 17:09:56 +08:00
{
if ( ! pcr - > option . ocp_en )
return ;
rtsx_pci_get_ocpstat ( pcr , & pcr - > ocp_stat ) ;
rts5260_get_ocpstat2 ( pcr , & pcr - > ocp_stat2 ) ;
2019-02-19 20:49:58 +08:00
if ( ( pcr - > ocp_stat & ( SD_OC_NOW | SD_OC_EVER ) ) | |
( pcr - > ocp_stat2 & ( DV3318_OCP_NOW | DV3318_OCP_EVER ) ) ) {
rtsx_pci_card_power_off ( pcr , RTSX_SD_CARD ) ;
rtsx_pci_write_register ( pcr , CARD_OE , SD_OUTPUT_EN , 0 ) ;
rtsx_pci_clear_ocpstat ( pcr ) ;
2017-11-29 17:09:56 +08:00
pcr - > ocp_stat = 0 ;
pcr - > ocp_stat2 = 0 ;
}
}
2018-02-07 13:23:27 +00:00
static int rts5260_init_hw ( struct rtsx_pcr * pcr )
2017-11-29 17:09:56 +08:00
{
int err ;
rtsx_pci_init_cmd ( pcr ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , L1SUB_CONFIG1 ,
AUX_CLK_ACTIVE_SEL_MASK , MAC_CKSW_DONE ) ;
/* Rest L1SUB Config */
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , L1SUB_CONFIG3 , 0xFF , 0x00 ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , PM_CLK_FORCE_CTL ,
CLK_PM_EN , CLK_PM_EN ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , PWD_SUSPEND_EN , 0xFF , 0xFF ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , PWR_GATE_CTRL ,
PWR_GATE_EN , PWR_GATE_EN ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , REG_VREF ,
PWD_SUSPND_EN , PWD_SUSPND_EN ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , RBCTL ,
U_AUTO_DMA_EN_MASK , U_AUTO_DMA_DISABLE ) ;
if ( pcr - > flags & PCR_REVERSE_SOCKET )
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , PETXCFG , 0xB0 , 0xB0 ) ;
else
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , PETXCFG , 0xB0 , 0x80 ) ;
rtsx_pci_add_cmd ( pcr , WRITE_REG_CMD , OBFF_CFG ,
OBFF_EN_MASK , OBFF_DISABLE ) ;
err = rtsx_pci_send_cmd ( pcr , CMD_TIMEOUT_DEF ) ;
if ( err < 0 )
return err ;
2019-02-19 20:49:58 +08:00
rtsx_pci_init_ocp ( pcr ) ;
2017-11-29 17:09:56 +08:00
return 0 ;
}
static void rts5260_pwr_saving_setting ( struct rtsx_pcr * pcr )
{
int lss_l1_1 , lss_l1_2 ;
lss_l1_1 = rtsx_check_dev_flag ( pcr , ASPM_L1_1_EN )
| rtsx_check_dev_flag ( pcr , PM_L1_1_EN ) ;
lss_l1_2 = rtsx_check_dev_flag ( pcr , ASPM_L1_2_EN )
| rtsx_check_dev_flag ( pcr , PM_L1_2_EN ) ;
2019-04-17 15:35:08 +08:00
rtsx_pci_write_register ( pcr , ASPM_FORCE_CTL , 0xFF , 0 ) ;
2017-11-29 17:09:56 +08:00
if ( lss_l1_2 ) {
pcr_dbg ( pcr , " Set parameters for L1.2. " ) ;
rtsx_pci_write_register ( pcr , PWR_GLOBAL_CTRL ,
0xFF , PCIE_L1_2_EN ) ;
2019-03-05 14:47:46 +03:00
rtsx_pci_write_register ( pcr , RTS5260_DVCC_CTRL ,
2019-02-19 20:49:58 +08:00
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN ,
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN ) ;
2019-03-05 14:47:46 +03:00
rtsx_pci_write_register ( pcr , PWR_FE_CTL ,
2017-11-29 17:09:56 +08:00
0xFF , PCIE_L1_2_PD_FE_EN ) ;
} else if ( lss_l1_1 ) {
pcr_dbg ( pcr , " Set parameters for L1.1. " ) ;
rtsx_pci_write_register ( pcr , PWR_GLOBAL_CTRL ,
0xFF , PCIE_L1_1_EN ) ;
rtsx_pci_write_register ( pcr , PWR_FE_CTL ,
0xFF , PCIE_L1_1_PD_FE_EN ) ;
} else {
pcr_dbg ( pcr , " Set parameters for L1. " ) ;
rtsx_pci_write_register ( pcr , PWR_GLOBAL_CTRL ,
0xFF , PCIE_L1_0_EN ) ;
rtsx_pci_write_register ( pcr , PWR_FE_CTL ,
0xFF , PCIE_L1_0_PD_FE_EN ) ;
}
rtsx_pci_write_register ( pcr , CFG_L1_0_PCIE_DPHY_RET_VALUE ,
0xFF , CFG_L1_0_RET_VALUE_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_L1_0_PCIE_MAC_RET_VALUE ,
0xFF , CFG_L1_0_RET_VALUE_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_L1_0_CRC_SD30_RET_VALUE ,
0xFF , CFG_L1_0_RET_VALUE_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_L1_0_CRC_SD40_RET_VALUE ,
0xFF , CFG_L1_0_RET_VALUE_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_L1_0_SYS_RET_VALUE ,
0xFF , CFG_L1_0_RET_VALUE_DEFAULT ) ;
/*Option cut APHY*/
rtsx_pci_write_register ( pcr , CFG_PCIE_APHY_OFF_0 ,
0xFF , CFG_PCIE_APHY_OFF_0_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_PCIE_APHY_OFF_1 ,
0xFF , CFG_PCIE_APHY_OFF_1_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_PCIE_APHY_OFF_2 ,
0xFF , CFG_PCIE_APHY_OFF_2_DEFAULT ) ;
rtsx_pci_write_register ( pcr , CFG_PCIE_APHY_OFF_3 ,
0xFF , CFG_PCIE_APHY_OFF_3_DEFAULT ) ;
/*CDR DEC*/
rtsx_pci_write_register ( pcr , PWC_CDR , 0xFF , PWC_CDR_DEFAULT ) ;
/*PWMPFM*/
rtsx_pci_write_register ( pcr , CFG_LP_FPWM_VALUE ,
0xFF , CFG_LP_FPWM_VALUE_DEFAULT ) ;
/*No Power Saving WA*/
rtsx_pci_write_register ( pcr , CFG_L1_0_CRC_MISC_RET_VALUE ,
0xFF , CFG_L1_0_CRC_MISC_RET_VALUE_DEFAULT ) ;
}
static void rts5260_init_from_cfg ( struct rtsx_pcr * pcr )
{
2020-07-21 16:23:34 -05:00
struct pci_dev * pdev = pcr - > pci ;
2020-07-21 16:23:35 -05:00
int l1ss ;
2017-11-29 17:09:56 +08:00
struct rtsx_cr_option * option = & pcr - > option ;
u32 lval ;
2020-07-21 16:23:35 -05:00
l1ss = pci_find_ext_capability ( pdev , PCI_EXT_CAP_ID_L1SS ) ;
if ( ! l1ss )
return ;
pci_read_config_dword ( pdev , l1ss + PCI_L1SS_CTL1 , & lval ) ;
2017-11-29 17:09:56 +08:00
2020-07-21 16:23:36 -05:00
if ( lval & PCI_L1SS_CTL1_ASPM_L1_1 )
2017-11-29 17:09:56 +08:00
rtsx_set_dev_flag ( pcr , ASPM_L1_1_EN ) ;
2020-07-21 16:23:36 -05:00
if ( lval & PCI_L1SS_CTL1_ASPM_L1_2 )
2017-11-29 17:09:56 +08:00
rtsx_set_dev_flag ( pcr , ASPM_L1_2_EN ) ;
2020-07-21 16:23:36 -05:00
if ( lval & PCI_L1SS_CTL1_PCIPM_L1_1 )
2017-11-29 17:09:56 +08:00
rtsx_set_dev_flag ( pcr , PM_L1_1_EN ) ;
2020-07-21 16:23:36 -05:00
if ( lval & PCI_L1SS_CTL1_PCIPM_L1_2 )
2017-11-29 17:09:56 +08:00
rtsx_set_dev_flag ( pcr , PM_L1_2_EN ) ;
rts5260_pwr_saving_setting ( pcr ) ;
if ( option - > ltr_en ) {
u16 val ;
2020-07-21 16:23:34 -05:00
pcie_capability_read_word ( pdev , PCI_EXP_DEVCTL2 , & val ) ;
2017-11-29 17:09:56 +08:00
if ( val & PCI_EXP_DEVCTL2_LTR_EN ) {
option - > ltr_enabled = true ;
option - > ltr_active = true ;
rtsx_set_ltr_latency ( pcr , option - > ltr_active_latency ) ;
} else {
option - > ltr_enabled = false ;
}
}
if ( rtsx_check_dev_flag ( pcr , ASPM_L1_1_EN | ASPM_L1_2_EN
| PM_L1_1_EN | PM_L1_2_EN ) )
option - > force_clkreq_0 = false ;
else
option - > force_clkreq_0 = true ;
}
static int rts5260_extra_init_hw ( struct rtsx_pcr * pcr )
{
struct rtsx_cr_option * option = & pcr - > option ;
/* Set mcu_cnt to 7 to ensure data can be sampled properly */
rtsx_pci_write_register ( pcr , 0xFC03 , 0x7F , 0x07 ) ;
rtsx_pci_write_register ( pcr , SSC_DIV_N_0 , 0xFF , 0x5D ) ;
rts5260_init_from_cfg ( pcr ) ;
/* force no MDIO*/
rtsx_pci_write_register ( pcr , RTS5260_AUTOLOAD_CFG4 ,
0xFF , RTS5260_MIMO_DISABLE ) ;
/*Modify SDVCC Tune Default Parameters!*/
rtsx_pci_write_register ( pcr , LDO_VCC_CFG0 ,
RTS5260_DVCC_TUNE_MASK , RTS5260_DVCC_33 ) ;
rtsx_pci_write_register ( pcr , PCLK_CTL , PCLK_MODE_SEL , PCLK_MODE_SEL ) ;
rts5260_init_hw ( pcr ) ;
/*
* If u_force_clkreq_0 is enabled , CLKREQ # PIN will be forced
* to drive low , and we forcibly request clock .
*/
if ( option - > force_clkreq_0 )
2019-04-17 15:35:08 +08:00
rtsx_pci_write_register ( pcr , PETXCFG ,
2017-11-29 17:09:56 +08:00
FORCE_CLKREQ_DELINK_MASK , FORCE_CLKREQ_LOW ) ;
else
2019-04-17 15:35:08 +08:00
rtsx_pci_write_register ( pcr , PETXCFG ,
2017-11-29 17:09:56 +08:00
FORCE_CLKREQ_DELINK_MASK , FORCE_CLKREQ_HIGH ) ;
2020-09-07 18:07:31 +08:00
rtsx_pci_write_register ( pcr , pcr - > reg_pm_ctrl3 , 0x10 , 0x00 ) ;
2017-11-29 17:09:56 +08:00
return 0 ;
}
static void rts5260_set_l1off_cfg_sub_d0 ( struct rtsx_pcr * pcr , int active )
{
struct rtsx_cr_option * option = & pcr - > option ;
u32 interrupt = rtsx_pci_readl ( pcr , RTSX_BIPR ) ;
int card_exist = ( interrupt & SD_EXIST ) | ( interrupt & MS_EXIST ) ;
int aspm_L1_1 , aspm_L1_2 ;
u8 val = 0 ;
aspm_L1_1 = rtsx_check_dev_flag ( pcr , ASPM_L1_1_EN ) ;
aspm_L1_2 = rtsx_check_dev_flag ( pcr , ASPM_L1_2_EN ) ;
if ( active ) {
/* run, latency: 60us */
if ( aspm_L1_1 )
val = option - > ltr_l1off_snooze_sspwrgate ;
} else {
/* l1off, latency: 300us */
if ( aspm_L1_2 )
val = option - > ltr_l1off_sspwrgate ;
}
if ( aspm_L1_1 | | aspm_L1_2 ) {
if ( rtsx_check_dev_flag ( pcr ,
LTR_L1SS_PWR_GATE_CHECK_CARD_EN ) ) {
if ( card_exist )
val & = ~ L1OFF_MBIAS2_EN_5250 ;
else
val | = L1OFF_MBIAS2_EN_5250 ;
}
}
rtsx_set_l1off_sub ( pcr , val ) ;
}
static const struct pcr_ops rts5260_pcr_ops = {
. fetch_vendor_settings = rtsx_base_fetch_vendor_settings ,
. turn_on_led = rts5260_turn_on_led ,
. turn_off_led = rts5260_turn_off_led ,
. extra_init_hw = rts5260_extra_init_hw ,
. enable_auto_blink = rtsx_base_enable_auto_blink ,
. disable_auto_blink = rtsx_base_disable_auto_blink ,
. card_power_on = rts5260_card_power_on ,
. card_power_off = rts5260_card_power_off ,
. switch_output_voltage = rts5260_switch_output_voltage ,
. stop_cmd = rts5260_stop_cmd ,
. set_l1off_cfg_sub_d0 = rts5260_set_l1off_cfg_sub_d0 ,
. enable_ocp = rts5260_enable_ocp ,
. disable_ocp = rts5260_disable_ocp ,
. init_ocp = rts5260_init_ocp ,
. process_ocp = rts5260_process_ocp ,
. get_ocpstat = rts5260_get_ocpstat ,
. clear_ocpstat = rts5260_clear_ocpstat ,
} ;
void rts5260_init_params ( struct rtsx_pcr * pcr )
{
struct rtsx_cr_option * option = & pcr - > option ;
struct rtsx_hw_param * hw_param = & pcr - > hw_param ;
pcr - > extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104 ;
pcr - > num_slots = 2 ;
pcr - > flags = 0 ;
pcr - > card_drive_sel = RTSX_CARD_DRIVE_DEFAULT ;
pcr - > sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B ;
pcr - > sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B ;
pcr - > aspm_en = ASPM_L1_EN ;
2020-03-16 10:52:32 +08:00
pcr - > tx_initial_phase = SET_CLOCK_PHASE ( 27 , 29 , 11 ) ;
2017-11-29 17:09:56 +08:00
pcr - > rx_initial_phase = SET_CLOCK_PHASE ( 24 , 6 , 5 ) ;
pcr - > ic_version = rts5260_get_ic_version ( pcr ) ;
pcr - > sd_pull_ctl_enable_tbl = rts5260_sd_pull_ctl_enable_tbl ;
pcr - > sd_pull_ctl_disable_tbl = rts5260_sd_pull_ctl_disable_tbl ;
pcr - > ms_pull_ctl_enable_tbl = rts5260_ms_pull_ctl_enable_tbl ;
pcr - > ms_pull_ctl_disable_tbl = rts5260_ms_pull_ctl_disable_tbl ;
pcr - > reg_pm_ctrl3 = RTS524A_PM_CTRL3 ;
pcr - > ops = & rts5260_pcr_ops ;
option - > dev_flags = ( LTR_L1SS_PWR_GATE_CHECK_CARD_EN
| LTR_L1SS_PWR_GATE_EN ) ;
option - > ltr_en = true ;
/* init latency of active, idle, L1OFF to 60us, 300us, 3ms */
option - > ltr_active_latency = LTR_ACTIVE_LATENCY_DEF ;
option - > ltr_idle_latency = LTR_IDLE_LATENCY_DEF ;
option - > ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF ;
option - > l1_snooze_delay = L1_SNOOZE_DELAY_DEF ;
option - > ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF ;
option - > ltr_l1off_snooze_sspwrgate =
LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF ;
option - > ocp_en = 1 ;
if ( option - > ocp_en )
hw_param - > interrupt_en | = SD_OC_INT_EN ;
2019-04-17 15:35:08 +08:00
hw_param - > ocp_glitch = SD_OCP_GLITCH_100U | SDVIO_OCP_GLITCH_800U ;
2017-11-29 17:09:56 +08:00
option - > sd_400mA_ocp_thd = RTS5260_DVCC_OCP_THD_550 ;
option - > sd_800mA_ocp_thd = RTS5260_DVCC_OCP_THD_970 ;
}