1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
42 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
43
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
47 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
48
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
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
179
180
181
182
183
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
194
195
196
197
198
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
209
210
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
220
221
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}
242