aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/rtl8411.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/rtl8411.c')
-rw-r--r--drivers/mfd/rtl8411.c94
1 files changed, 86 insertions, 8 deletions
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
index c436bf27e78d..52801351864d 100644
--- a/drivers/mfd/rtl8411.c
+++ b/drivers/mfd/rtl8411.c
@@ -1,6 +1,6 @@
1/* Driver for Realtek PCI-Express card reader 1/* Driver for Realtek PCI-Express card reader
2 * 2 *
3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. 3 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License as published by the
@@ -17,7 +17,7 @@
17 * 17 *
18 * Author: 18 * Author:
19 * Wei WANG <wei_wang@realsil.com.cn> 19 * Wei WANG <wei_wang@realsil.com.cn>
20 * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China 20 * Roger Tseng <rogerable@realtek.com>
21 */ 21 */
22 22
23#include <linux/module.h> 23#include <linux/module.h>
@@ -47,19 +47,77 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
47 return 0; 47 return 0;
48} 48}
49 49
50static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
51{
52 u32 reg1;
53 u8 reg3;
54
55 rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
56 dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
57
58 if (!rtsx_vendor_setting_valid(reg1))
59 return;
60
61 pcr->aspm_en = rtsx_reg_to_aspm(reg1);
62 pcr->sd30_drive_sel_1v8 =
63 map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1));
64 pcr->card_drive_sel &= 0x3F;
65 pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
66
67 rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
68 dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
69 pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
70}
71
72static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
73{
74 u32 reg;
75
76 rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
77 dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
78
79 if (!rtsx_vendor_setting_valid(reg))
80 return;
81
82 pcr->aspm_en = rtsx_reg_to_aspm(reg);
83 pcr->sd30_drive_sel_1v8 =
84 map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
85 pcr->sd30_drive_sel_3v3 =
86 map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg));
87}
88
89static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
90{
91 rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
92}
93
50static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) 94static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
51{ 95{
52 return rtsx_pci_write_register(pcr, CD_PAD_CTL, 96 rtsx_pci_init_cmd(pcr);
97
98 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
99 0xFF, pcr->sd30_drive_sel_3v3);
100 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
53 CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 101 CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
102
103 return rtsx_pci_send_cmd(pcr, 100);
54} 104}
55 105
56static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) 106static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
57{ 107{
58 if (rtl8411b_is_qfn48(pcr)) 108 rtsx_pci_init_cmd(pcr);
59 rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5);
60 109
61 return rtsx_pci_write_register(pcr, CD_PAD_CTL, 110 if (rtl8411b_is_qfn48(pcr))
111 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
112 CARD_PULL_CTL3, 0xFF, 0xF5);
113 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
114 0xFF, pcr->sd30_drive_sel_3v3);
115 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
62 CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 116 CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
117 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL,
118 0x06, 0x00);
119
120 return rtsx_pci_send_cmd(pcr, 100);
63} 121}
64 122
65static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) 123static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
@@ -141,13 +199,13 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
141 mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; 199 mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
142 if (voltage == OUTPUT_3V3) { 200 if (voltage == OUTPUT_3V3) {
143 err = rtsx_pci_write_register(pcr, 201 err = rtsx_pci_write_register(pcr,
144 SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); 202 SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
145 if (err < 0) 203 if (err < 0)
146 return err; 204 return err;
147 val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; 205 val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
148 } else if (voltage == OUTPUT_1V8) { 206 } else if (voltage == OUTPUT_1V8) {
149 err = rtsx_pci_write_register(pcr, 207 err = rtsx_pci_write_register(pcr,
150 SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); 208 SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
151 if (err < 0) 209 if (err < 0)
152 return err; 210 return err;
153 val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; 211 val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
@@ -222,6 +280,7 @@ static int rtl8411_conv_clk_and_div_n(int input, int dir)
222} 280}
223 281
224static const struct pcr_ops rtl8411_pcr_ops = { 282static const struct pcr_ops rtl8411_pcr_ops = {
283 .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
225 .extra_init_hw = rtl8411_extra_init_hw, 284 .extra_init_hw = rtl8411_extra_init_hw,
226 .optimize_phy = NULL, 285 .optimize_phy = NULL,
227 .turn_on_led = rtl8411_turn_on_led, 286 .turn_on_led = rtl8411_turn_on_led,
@@ -233,9 +292,11 @@ static const struct pcr_ops rtl8411_pcr_ops = {
233 .switch_output_voltage = rtl8411_switch_output_voltage, 292 .switch_output_voltage = rtl8411_switch_output_voltage,
234 .cd_deglitch = rtl8411_cd_deglitch, 293 .cd_deglitch = rtl8411_cd_deglitch,
235 .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 294 .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
295 .force_power_down = rtl8411_force_power_down,
236}; 296};
237 297
238static const struct pcr_ops rtl8411b_pcr_ops = { 298static const struct pcr_ops rtl8411b_pcr_ops = {
299 .fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
239 .extra_init_hw = rtl8411b_extra_init_hw, 300 .extra_init_hw = rtl8411b_extra_init_hw,
240 .optimize_phy = NULL, 301 .optimize_phy = NULL,
241 .turn_on_led = rtl8411_turn_on_led, 302 .turn_on_led = rtl8411_turn_on_led,
@@ -247,6 +308,7 @@ static const struct pcr_ops rtl8411b_pcr_ops = {
247 .switch_output_voltage = rtl8411_switch_output_voltage, 308 .switch_output_voltage = rtl8411_switch_output_voltage,
248 .cd_deglitch = rtl8411_cd_deglitch, 309 .cd_deglitch = rtl8411_cd_deglitch,
249 .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 310 .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
311 .force_power_down = rtl8411_force_power_down,
250}; 312};
251 313
252/* SD Pull Control Enable: 314/* SD Pull Control Enable:
@@ -385,6 +447,14 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
385 pcr->num_slots = 2; 447 pcr->num_slots = 2;
386 pcr->ops = &rtl8411_pcr_ops; 448 pcr->ops = &rtl8411_pcr_ops;
387 449
450 pcr->flags = 0;
451 pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
452 pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
453 pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
454 pcr->aspm_en = ASPM_L1_EN;
455 pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
456 pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
457
388 pcr->ic_version = rtl8411_get_ic_version(pcr); 458 pcr->ic_version = rtl8411_get_ic_version(pcr);
389 pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl; 459 pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
390 pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl; 460 pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
@@ -398,6 +468,14 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr)
398 pcr->num_slots = 2; 468 pcr->num_slots = 2;
399 pcr->ops = &rtl8411b_pcr_ops; 469 pcr->ops = &rtl8411b_pcr_ops;
400 470
471 pcr->flags = 0;
472 pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
473 pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
474 pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
475 pcr->aspm_en = ASPM_L1_EN;
476 pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
477 pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
478
401 pcr->ic_version = rtl8411_get_ic_version(pcr); 479 pcr->ic_version = rtl8411_get_ic_version(pcr);
402 480
403 if (rtl8411b_is_qfn48(pcr)) { 481 if (rtl8411b_is_qfn48(pcr)) {