diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-07 23:14:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-07 23:14:19 -0400 |
commit | 8de4651abe61c6b6a94a70a57ef163020fed05ee (patch) | |
tree | a2455b59b7df7239a5819b9cf2248e27eef483c4 /drivers/mfd/rts5227.c | |
parent | 327fff3e1391a27dcc89de6e0481689a865361c9 (diff) | |
parent | 9c31e8840836de447e1e508a6d756af419790ed6 (diff) |
Merge tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next
Pull MFD (multi-function device) updates from Samuel Ortiz:
"For the 3.12 merge window we have one new driver for the DA9063 PMIC
from Dialog Semiconductor.
Besides that driver we also have:
- Device tree support for the s2mps11 driver
- More devm_* conversion for the pm8921, max89xx, menelaus, tps65010,
wl1273 and pcf50633-adc drivers.
- A conversion to threaded IRQ and IRQ domain for the twl6030 driver.
- A fairly big update for the rtsx driver: Better power saving
support, better vendor settings handling, and a few fixes.
- Support for a couple more boards (COMe-bHL6 and COMe-cTH6) for the
Kontron driver.
- A conversion to the dev_get_platdata() API for all MFD drivers.
- A removal of non-DT (legacy) support for the twl6040 driver.
- A few fixes and additions (Mic detect level) to the wm5110 register
tables.
- Regmap support for the davinci_voicecodec driver.
- The usual bunch of minor cleanups and janitorial fixes"
* tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (81 commits)
mfd: ucb1x00-core: Rewrite ucb1x00_add_dev()
mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for event name
mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for sysfs
mfd: timberdale: Use module_pci_driver
mfd: timberdale: Remove redundant break
mfd: timberdale: Staticize local variables
mfd: ab8500-debugfs: Staticize local variables
mfd: db8500-prcmu: Staticize clk_mgt
mfd: db8500-prcmu: Use ANSI function declaration
mfd: omap-usb-host: Staticize usbhs_driver_name
mfd: 88pm805: Fix potential NULL pdata dereference
mfd: 88pm800: Fix potential NULL pdata dereference
mfd: twl6040: Use regmap for register cache
mfd: davinci_voicecodec: Provide a regmap for register I/O
mfd: davinci_voicecodec: Remove unused read and write functions
mmc: memstick: rtsx: Modify copyright comments
mmc: rtsx: Clear SD_CLK toggle enable bit if switching voltage fail
mfd: mmc: rtsx: Change default tx phase
mfd: pcf50633-adc: Use devm_*() functions
mfd: rtsx: Copyright modifications
...
Diffstat (limited to 'drivers/mfd/rts5227.c')
-rw-r--r-- | drivers/mfd/rts5227.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index 164b7faa70c9..9c8eec80ceed 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.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,10 +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 | ||
21 | * | ||
22 | * Roger Tseng <rogerable@realtek.com> | 20 | * Roger Tseng <rogerable@realtek.com> |
23 | * No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan | ||
24 | */ | 21 | */ |
25 | 22 | ||
26 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -29,6 +26,73 @@ | |||
29 | 26 | ||
30 | #include "rtsx_pcr.h" | 27 | #include "rtsx_pcr.h" |
31 | 28 | ||
29 | static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage) | ||
30 | { | ||
31 | u8 driving_3v3[4][3] = { | ||
32 | {0x13, 0x13, 0x13}, | ||
33 | {0x96, 0x96, 0x96}, | ||
34 | {0x7F, 0x7F, 0x7F}, | ||
35 | {0x96, 0x96, 0x96}, | ||
36 | }; | ||
37 | u8 driving_1v8[4][3] = { | ||
38 | {0x99, 0x99, 0x99}, | ||
39 | {0xAA, 0xAA, 0xAA}, | ||
40 | {0xFE, 0xFE, 0xFE}, | ||
41 | {0xB3, 0xB3, 0xB3}, | ||
42 | }; | ||
43 | u8 (*driving)[3], drive_sel; | ||
44 | |||
45 | if (voltage == OUTPUT_3V3) { | ||
46 | driving = driving_3v3; | ||
47 | drive_sel = pcr->sd30_drive_sel_3v3; | ||
48 | } else { | ||
49 | driving = driving_1v8; | ||
50 | drive_sel = pcr->sd30_drive_sel_1v8; | ||
51 | } | ||
52 | |||
53 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, | ||
54 | 0xFF, driving[drive_sel][0]); | ||
55 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, | ||
56 | 0xFF, driving[drive_sel][1]); | ||
57 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, | ||
58 | 0xFF, driving[drive_sel][2]); | ||
59 | } | ||
60 | |||
61 | static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) | ||
62 | { | ||
63 | u32 reg; | ||
64 | |||
65 | rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); | ||
66 | dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); | ||
67 | |||
68 | if (!rtsx_vendor_setting_valid(reg)) | ||
69 | return; | ||
70 | |||
71 | pcr->aspm_en = rtsx_reg_to_aspm(reg); | ||
72 | pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); | ||
73 | pcr->card_drive_sel &= 0x3F; | ||
74 | pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); | ||
75 | |||
76 | rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); | ||
77 | dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); | ||
78 | pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); | ||
79 | if (rtsx_reg_check_reverse_socket(reg)) | ||
80 | pcr->flags |= PCR_REVERSE_SOCKET; | ||
81 | } | ||
82 | |||
83 | static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) | ||
84 | { | ||
85 | /* Set relink_time to 0 */ | ||
86 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); | ||
87 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); | ||
88 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); | ||
89 | |||
90 | if (pm_state == HOST_ENTER_S3) | ||
91 | rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); | ||
92 | |||
93 | rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); | ||
94 | } | ||
95 | |||
32 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) | 96 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) |
33 | { | 97 | { |
34 | u16 cap; | 98 | u16 cap; |
@@ -37,6 +101,8 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) | |||
37 | 101 | ||
38 | /* Configure GPIO as output */ | 102 | /* Configure GPIO as output */ |
39 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); | 103 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); |
104 | /* Reset ASPM state to default value */ | ||
105 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); | ||
40 | /* Switch LDO3318 source from DV33 to card_3v3 */ | 106 | /* Switch LDO3318 source from DV33 to card_3v3 */ |
41 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); | 107 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); |
42 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); | 108 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); |
@@ -48,17 +114,16 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) | |||
48 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); | 114 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); |
49 | /* Configure OBFF */ | 115 | /* Configure OBFF */ |
50 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); | 116 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); |
51 | /* Configure force_clock_req | 117 | /* Configure driving */ |
52 | * Maybe We should define 0xFF03 as some name | 118 | rts5227_fill_driving(pcr, OUTPUT_3V3); |
53 | */ | 119 | /* Configure force_clock_req */ |
54 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08); | 120 | if (pcr->flags & PCR_REVERSE_SOCKET) |
55 | /* Correct driving */ | 121 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, |
56 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | 122 | AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8); |
57 | SD30_CLK_DRIVE_SEL, 0xFF, 0x96); | 123 | else |
58 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | 124 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, |
59 | SD30_CMD_DRIVE_SEL, 0xFF, 0x96); | 125 | AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88); |
60 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | 126 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); |
61 | SD30_DAT_DRIVE_SEL, 0xFF, 0x96); | ||
62 | 127 | ||
63 | return rtsx_pci_send_cmd(pcr, 100); | 128 | return rtsx_pci_send_cmd(pcr, 100); |
64 | } | 129 | } |
@@ -131,13 +196,11 @@ static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) | |||
131 | static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | 196 | static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
132 | { | 197 | { |
133 | int err; | 198 | int err; |
134 | u8 drive_sel; | ||
135 | 199 | ||
136 | if (voltage == OUTPUT_3V3) { | 200 | if (voltage == OUTPUT_3V3) { |
137 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | 201 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); |
138 | if (err < 0) | 202 | if (err < 0) |
139 | return err; | 203 | return err; |
140 | drive_sel = 0x96; | ||
141 | } else if (voltage == OUTPUT_1V8) { | 204 | } else if (voltage == OUTPUT_1V8) { |
142 | err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); | 205 | err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); |
143 | if (err < 0) | 206 | if (err < 0) |
@@ -145,23 +208,18 @@ static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | |||
145 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24); | 208 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24); |
146 | if (err < 0) | 209 | if (err < 0) |
147 | return err; | 210 | return err; |
148 | drive_sel = 0xB3; | ||
149 | } else { | 211 | } else { |
150 | return -EINVAL; | 212 | return -EINVAL; |
151 | } | 213 | } |
152 | 214 | ||
153 | /* set pad drive */ | 215 | /* set pad drive */ |
154 | rtsx_pci_init_cmd(pcr); | 216 | rtsx_pci_init_cmd(pcr); |
155 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, | 217 | rts5227_fill_driving(pcr, voltage); |
156 | 0xFF, drive_sel); | ||
157 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, | ||
158 | 0xFF, drive_sel); | ||
159 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, | ||
160 | 0xFF, drive_sel); | ||
161 | return rtsx_pci_send_cmd(pcr, 100); | 218 | return rtsx_pci_send_cmd(pcr, 100); |
162 | } | 219 | } |
163 | 220 | ||
164 | static const struct pcr_ops rts5227_pcr_ops = { | 221 | static const struct pcr_ops rts5227_pcr_ops = { |
222 | .fetch_vendor_settings = rts5227_fetch_vendor_settings, | ||
165 | .extra_init_hw = rts5227_extra_init_hw, | 223 | .extra_init_hw = rts5227_extra_init_hw, |
166 | .optimize_phy = rts5227_optimize_phy, | 224 | .optimize_phy = rts5227_optimize_phy, |
167 | .turn_on_led = rts5227_turn_on_led, | 225 | .turn_on_led = rts5227_turn_on_led, |
@@ -173,6 +231,7 @@ static const struct pcr_ops rts5227_pcr_ops = { | |||
173 | .switch_output_voltage = rts5227_switch_output_voltage, | 231 | .switch_output_voltage = rts5227_switch_output_voltage, |
174 | .cd_deglitch = NULL, | 232 | .cd_deglitch = NULL, |
175 | .conv_clk_and_div_n = NULL, | 233 | .conv_clk_and_div_n = NULL, |
234 | .force_power_down = rts5227_force_power_down, | ||
176 | }; | 235 | }; |
177 | 236 | ||
178 | /* SD Pull Control Enable: | 237 | /* SD Pull Control Enable: |
@@ -227,6 +286,14 @@ void rts5227_init_params(struct rtsx_pcr *pcr) | |||
227 | pcr->num_slots = 2; | 286 | pcr->num_slots = 2; |
228 | pcr->ops = &rts5227_pcr_ops; | 287 | pcr->ops = &rts5227_pcr_ops; |
229 | 288 | ||
289 | pcr->flags = 0; | ||
290 | pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; | ||
291 | pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; | ||
292 | pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; | ||
293 | pcr->aspm_en = ASPM_L1_EN; | ||
294 | pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15); | ||
295 | pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7); | ||
296 | |||
230 | pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; | 297 | pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; |
231 | pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; | 298 | pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; |
232 | pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; | 299 | pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; |