aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorWei WANG <wei_wang@realsil.com.cn>2013-04-10 22:43:40 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-04-19 12:29:18 -0400
commit4c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbb (patch)
tree15e8cadfa536dccd2a73652c1f5e5a678db3f0f9 /drivers/mfd
parent95e50f6a2fe9ece6503e355400c171e0f5de61be (diff)
mfd: rtsx: Support RTS5249
RTS5249 supports SD UHS-II interface. In order to support SD UHS-II,the definitions of some internal registers of RTS5249 have to be modified and are different from its predecessors. So we need this patch to ensure RTS5249 can work, even SD/MMC stack doesn't support UHS-II interface. Signed-off-by: Wei WANG <wei_wang@realsil.com.cn> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/rts5249.c241
-rw-r--r--drivers/mfd/rtsx_pcr.c5
-rw-r--r--drivers/mfd/rtsx_pcr.h1
4 files changed, 248 insertions, 1 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f62a583b5c85..067656651b02 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
12obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o 12obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
13obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o 13obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
14 14
15rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o 15rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
16obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o 16obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
17 17
18obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 18obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
new file mode 100644
index 000000000000..15dc848bc081
--- /dev/null
+++ b/drivers/mfd/rts5249.c
@@ -0,0 +1,241 @@
1/* Driver for Realtek PCI-Express card reader
2 *
3 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
4 *
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
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author:
19 * Wei WANG <wei_wang@realsil.com.cn>
20 * No. 128, West Shenhu Road, Suzhou Industry Park, Suzhou, China
21 */
22
23#include <linux/module.h>
24#include <linux/delay.h>
25#include <linux/mfd/rtsx_pci.h>
26
27#include "rtsx_pcr.h"
28
29static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
30{
31 u8 val;
32
33 rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
34 return val & 0x0F;
35}
36
37static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
38{
39 rtsx_pci_init_cmd(pcr);
40
41 /* Configure GPIO as output */
42 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
43 /* Switch LDO3318 source from DV33 to card_3v3 */
44 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);
46 /* LED shine disabled, set initial shine cycle period */
47 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
48 /* Correct driving */
49 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
50 SD30_CLK_DRIVE_SEL, 0xFF, 0x99);
51 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
52 SD30_CMD_DRIVE_SEL, 0xFF, 0x99);
53 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
54 SD30_DAT_DRIVE_SEL, 0xFF, 0x92);
55
56 return rtsx_pci_send_cmd(pcr, 100);
57}
58
59static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
60{
61 int err;
62
63 err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, 0xFE46);
64 if (err < 0)
65 return err;
66
67 msleep(1);
68
69 return rtsx_pci_write_phy_register(pcr, PHY_BPCR, 0x05C0);
70}
71
72static int rts5249_turn_on_led(struct rtsx_pcr *pcr)
73{
74 return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
75}
76
77static int rts5249_turn_off_led(struct rtsx_pcr *pcr)
78{
79 return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
80}
81
82static int rts5249_enable_auto_blink(struct rtsx_pcr *pcr)
83{
84 return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
85}
86
87static int rts5249_disable_auto_blink(struct rtsx_pcr *pcr)
88{
89 return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
90}
91
92static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card)
93{
94 int err;
95
96 rtsx_pci_init_cmd(pcr);
97 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
98 SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
99 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
100 LDO3318_PWR_MASK, 0x02);
101 err = rtsx_pci_send_cmd(pcr, 100);
102 if (err < 0)
103 return err;
104
105 msleep(5);
106
107 rtsx_pci_init_cmd(pcr);
108 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
109 SD_POWER_MASK, SD_VCC_POWER_ON);
110 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
111 LDO3318_PWR_MASK, 0x06);
112 err = rtsx_pci_send_cmd(pcr, 100);
113 if (err < 0)
114 return err;
115
116 return 0;
117}
118
119static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
120{
121 rtsx_pci_init_cmd(pcr);
122 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
123 SD_POWER_MASK, SD_POWER_OFF);
124 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
125 LDO3318_PWR_MASK, 0x00);
126 return rtsx_pci_send_cmd(pcr, 100);
127}
128
129static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
130{
131 int err;
132 u8 clk_drive, cmd_drive, dat_drive;
133
134 if (voltage == OUTPUT_3V3) {
135 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
136 if (err < 0)
137 return err;
138 clk_drive = 0x99;
139 cmd_drive = 0x99;
140 dat_drive = 0x92;
141 } else if (voltage == OUTPUT_1V8) {
142 err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
143 if (err < 0)
144 return err;
145 err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
146 if (err < 0)
147 return err;
148 clk_drive = 0xb3;
149 cmd_drive = 0xb3;
150 dat_drive = 0xb3;
151 } else {
152 return -EINVAL;
153 }
154
155 /* set pad drive */
156 rtsx_pci_init_cmd(pcr);
157 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
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);
164}
165
166static const struct pcr_ops rts5249_pcr_ops = {
167 .extra_init_hw = rts5249_extra_init_hw,
168 .optimize_phy = rts5249_optimize_phy,
169 .turn_on_led = rts5249_turn_on_led,
170 .turn_off_led = rts5249_turn_off_led,
171 .enable_auto_blink = rts5249_enable_auto_blink,
172 .disable_auto_blink = rts5249_disable_auto_blink,
173 .card_power_on = rts5249_card_power_on,
174 .card_power_off = rts5249_card_power_off,
175 .switch_output_voltage = rts5249_switch_output_voltage,
176};
177
178/* SD Pull Control Enable:
179 * SD_DAT[3:0] ==> pull up
180 * SD_CD ==> pull up
181 * SD_WP ==> pull up
182 * SD_CMD ==> pull up
183 * SD_CLK ==> pull down
184 */
185static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
186 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
187 RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
188 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
189 RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
190 0,
191};
192
193/* SD Pull Control Disable:
194 * SD_DAT[3:0] ==> pull down
195 * SD_CD ==> pull up
196 * SD_WP ==> pull down
197 * SD_CMD ==> pull down
198 * SD_CLK ==> pull down
199 */
200static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
201 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
202 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
203 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
204 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
205 0,
206};
207
208/* MS Pull Control Enable:
209 * MS CD ==> pull up
210 * others ==> pull down
211 */
212static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
213 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
214 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
215 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
216 0,
217};
218
219/* MS Pull Control Disable:
220 * MS CD ==> pull up
221 * others ==> pull down
222 */
223static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
224 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
225 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
226 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
227 0,
228};
229
230void rts5249_init_params(struct rtsx_pcr *pcr)
231{
232 pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
233 pcr->num_slots = 2;
234 pcr->ops = &rts5249_pcr_ops;
235
236 pcr->ic_version = rts5249_get_ic_version(pcr);
237 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;
239 pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
240 pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
241}
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 578a1136b6dc..e968c01ca2ac 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -56,6 +56,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
56 { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, 56 { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
57 { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, 57 { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
58 { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, 58 { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
59 { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
59 { 0, } 60 { 0, }
60}; 61};
61 62
@@ -1033,6 +1034,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
1033 case 0x5227: 1034 case 0x5227:
1034 rts5227_init_params(pcr); 1035 rts5227_init_params(pcr);
1035 break; 1036 break;
1037
1038 case 0x5249:
1039 rts5249_init_params(pcr);
1040 break;
1036 } 1041 }
1037 1042
1038 dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", 1043 dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
index 2b3ab8a04823..55fcfc25c4e4 100644
--- a/drivers/mfd/rtsx_pcr.h
+++ b/drivers/mfd/rtsx_pcr.h
@@ -32,5 +32,6 @@ void rts5209_init_params(struct rtsx_pcr *pcr);
32void rts5229_init_params(struct rtsx_pcr *pcr); 32void rts5229_init_params(struct rtsx_pcr *pcr);
33void rtl8411_init_params(struct rtsx_pcr *pcr); 33void rtl8411_init_params(struct rtsx_pcr *pcr);
34void rts5227_init_params(struct rtsx_pcr *pcr); 34void rts5227_init_params(struct rtsx_pcr *pcr);
35void rts5249_init_params(struct rtsx_pcr *pcr);
35 36
36#endif 37#endif