aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--include/linux/mfd/rtsx_pci.h36
5 files changed, 284 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
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
index 26ea7f1b7caf..86bc635f8385 100644
--- a/include/linux/mfd/rtsx_pci.h
+++ b/include/linux/mfd/rtsx_pci.h
@@ -500,6 +500,8 @@
500#define BPP_POWER_15_PERCENT_ON 0x08 500#define BPP_POWER_15_PERCENT_ON 0x08
501#define BPP_POWER_ON 0x00 501#define BPP_POWER_ON 0x00
502#define BPP_POWER_MASK 0x0F 502#define BPP_POWER_MASK 0x0F
503#define SD_VCC_PARTIAL_POWER_ON 0x02
504#define SD_VCC_POWER_ON 0x00
503 505
504/* PWR_GATE_CTRL */ 506/* PWR_GATE_CTRL */
505#define PWR_GATE_EN 0x01 507#define PWR_GATE_EN 0x01
@@ -689,6 +691,40 @@
689#define IMAGE_FLAG_ADDR0 0xCE80 691#define IMAGE_FLAG_ADDR0 0xCE80
690#define IMAGE_FLAG_ADDR1 0xCE81 692#define IMAGE_FLAG_ADDR1 0xCE81
691 693
694/* Phy register */
695#define PHY_PCR 0x00
696#define PHY_RCR0 0x01
697#define PHY_RCR1 0x02
698#define PHY_RCR2 0x03
699#define PHY_RTCR 0x04
700#define PHY_RDR 0x05
701#define PHY_TCR0 0x06
702#define PHY_TCR1 0x07
703#define PHY_TUNE 0x08
704#define PHY_IMR 0x09
705#define PHY_BPCR 0x0A
706#define PHY_BIST 0x0B
707#define PHY_RAW_L 0x0C
708#define PHY_RAW_H 0x0D
709#define PHY_RAW_DATA 0x0E
710#define PHY_HOST_CLK_CTRL 0x0F
711#define PHY_DMR 0x10
712#define PHY_BACR 0x11
713#define PHY_IER 0x12
714#define PHY_BCSR 0x13
715#define PHY_BPR 0x14
716#define PHY_BPNR2 0x15
717#define PHY_BPNR 0x16
718#define PHY_BRNR2 0x17
719#define PHY_BENR 0x18
720#define PHY_REG_REV 0x19
721#define PHY_FLD0 0x1A
722#define PHY_FLD1 0x1B
723#define PHY_FLD2 0x1C
724#define PHY_FLD3 0x1D
725#define PHY_FLD4 0x1E
726#define PHY_DUM_REG 0x1F
727
692#define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0) 728#define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0)
693 729
694struct rtsx_pcr; 730struct rtsx_pcr;