aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/rts5249.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/rts5249.c')
-rw-r--r--drivers/mfd/rts5249.c110
1 files changed, 89 insertions, 21 deletions
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
index 15dc848bc081..3b835f593e35 100644
--- a/drivers/mfd/rts5249.c
+++ b/drivers/mfd/rts5249.c
@@ -17,7 +17,6 @@
17 * 17 *
18 * Author: 18 * Author:
19 * Wei WANG <wei_wang@realsil.com.cn> 19 * Wei WANG <wei_wang@realsil.com.cn>
20 * No. 128, West Shenhu Road, Suzhou Industry Park, Suzhou, China
21 */ 20 */
22 21
23#include <linux/module.h> 22#include <linux/module.h>
@@ -34,24 +33,95 @@ static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
34 return val & 0x0F; 33 return val & 0x0F;
35} 34}
36 35
36static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
37{
38 u8 driving_3v3[4][3] = {
39 {0x11, 0x11, 0x11},
40 {0x55, 0x55, 0x5C},
41 {0x99, 0x99, 0x92},
42 {0x99, 0x99, 0x92},
43 };
44 u8 driving_1v8[4][3] = {
45 {0x3C, 0x3C, 0x3C},
46 {0xB3, 0xB3, 0xB3},
47 {0xFE, 0xFE, 0xFE},
48 {0xC4, 0xC4, 0xC4},
49 };
50 u8 (*driving)[3], drive_sel;
51
52 if (voltage == OUTPUT_3V3) {
53 driving = driving_3v3;
54 drive_sel = pcr->sd30_drive_sel_3v3;
55 } else {
56 driving = driving_1v8;
57 drive_sel = pcr->sd30_drive_sel_1v8;
58 }
59
60 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
61 0xFF, driving[drive_sel][0]);
62 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
63 0xFF, driving[drive_sel][1]);
64 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
65 0xFF, driving[drive_sel][2]);
66}
67
68static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
69{
70 u32 reg;
71
72 rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
73 dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
74
75 if (!rtsx_vendor_setting_valid(reg))
76 return;
77
78 pcr->aspm_en = rtsx_reg_to_aspm(reg);
79 pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
80 pcr->card_drive_sel &= 0x3F;
81 pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
82
83 rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
84 dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
85 pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
86 if (rtsx_reg_check_reverse_socket(reg))
87 pcr->flags |= PCR_REVERSE_SOCKET;
88}
89
90static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
91{
92 /* Set relink_time to 0 */
93 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
94 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
95 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
96
97 if (pm_state == HOST_ENTER_S3)
98 rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
99
100 rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
101}
102
37static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) 103static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
38{ 104{
39 rtsx_pci_init_cmd(pcr); 105 rtsx_pci_init_cmd(pcr);
40 106
41 /* Configure GPIO as output */ 107 /* Configure GPIO as output */
42 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); 108 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
109 /* Reset ASPM state to default value */
110 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
43 /* Switch LDO3318 source from DV33 to card_3v3 */ 111 /* Switch LDO3318 source from DV33 to card_3v3 */
44 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); 112 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
45 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); 113 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
46 /* LED shine disabled, set initial shine cycle period */ 114 /* LED shine disabled, set initial shine cycle period */
47 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); 115 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
48 /* Correct driving */ 116 /* Configure driving */
49 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 117 rts5249_fill_driving(pcr, OUTPUT_3V3);
50 SD30_CLK_DRIVE_SEL, 0xFF, 0x99); 118 if (pcr->flags & PCR_REVERSE_SOCKET)
51 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 119 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
52 SD30_CMD_DRIVE_SEL, 0xFF, 0x99); 120 AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
53 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 121 else
54 SD30_DAT_DRIVE_SEL, 0xFF, 0x92); 122 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
123 AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80);
124 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
55 125
56 return rtsx_pci_send_cmd(pcr, 100); 126 return rtsx_pci_send_cmd(pcr, 100);
57} 127}
@@ -129,15 +199,11 @@ static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
129static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 199static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
130{ 200{
131 int err; 201 int err;
132 u8 clk_drive, cmd_drive, dat_drive;
133 202
134 if (voltage == OUTPUT_3V3) { 203 if (voltage == OUTPUT_3V3) {
135 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24); 204 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
136 if (err < 0) 205 if (err < 0)
137 return err; 206 return err;
138 clk_drive = 0x99;
139 cmd_drive = 0x99;
140 dat_drive = 0x92;
141 } else if (voltage == OUTPUT_1V8) { 207 } else if (voltage == OUTPUT_1V8) {
142 err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02); 208 err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
143 if (err < 0) 209 if (err < 0)
@@ -145,25 +211,18 @@ static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
145 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24); 211 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
146 if (err < 0) 212 if (err < 0)
147 return err; 213 return err;
148 clk_drive = 0xb3;
149 cmd_drive = 0xb3;
150 dat_drive = 0xb3;
151 } else { 214 } else {
152 return -EINVAL; 215 return -EINVAL;
153 } 216 }
154 217
155 /* set pad drive */ 218 /* set pad drive */
156 rtsx_pci_init_cmd(pcr); 219 rtsx_pci_init_cmd(pcr);
157 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, 220 rts5249_fill_driving(pcr, voltage);
158 0xFF, clk_drive);
159 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
160 0xFF, cmd_drive);
161 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
162 0xFF, dat_drive);
163 return rtsx_pci_send_cmd(pcr, 100); 221 return rtsx_pci_send_cmd(pcr, 100);
164} 222}
165 223
166static const struct pcr_ops rts5249_pcr_ops = { 224static const struct pcr_ops rts5249_pcr_ops = {
225 .fetch_vendor_settings = rts5249_fetch_vendor_settings,
167 .extra_init_hw = rts5249_extra_init_hw, 226 .extra_init_hw = rts5249_extra_init_hw,
168 .optimize_phy = rts5249_optimize_phy, 227 .optimize_phy = rts5249_optimize_phy,
169 .turn_on_led = rts5249_turn_on_led, 228 .turn_on_led = rts5249_turn_on_led,
@@ -173,6 +232,7 @@ static const struct pcr_ops rts5249_pcr_ops = {
173 .card_power_on = rts5249_card_power_on, 232 .card_power_on = rts5249_card_power_on,
174 .card_power_off = rts5249_card_power_off, 233 .card_power_off = rts5249_card_power_off,
175 .switch_output_voltage = rts5249_switch_output_voltage, 234 .switch_output_voltage = rts5249_switch_output_voltage,
235 .force_power_down = rts5249_force_power_down,
176}; 236};
177 237
178/* SD Pull Control Enable: 238/* SD Pull Control Enable:
@@ -233,6 +293,14 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
233 pcr->num_slots = 2; 293 pcr->num_slots = 2;
234 pcr->ops = &rts5249_pcr_ops; 294 pcr->ops = &rts5249_pcr_ops;
235 295
296 pcr->flags = 0;
297 pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
298 pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
299 pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
300 pcr->aspm_en = ASPM_L1_EN;
301 pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
302 pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
303
236 pcr->ic_version = rts5249_get_ic_version(pcr); 304 pcr->ic_version = rts5249_get_ic_version(pcr);
237 pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl; 305 pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
238 pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl; 306 pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;