Root/
1 | /* Driver for Realtek PCI-Express card reader |
2 | * |
3 | * Copyright(c) 2009 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. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China |
21 | * |
22 | * Roger Tseng <rogerable@realtek.com> |
23 | * No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan |
24 | */ |
25 | |
26 | #include <linux/module.h> |
27 | #include <linux/delay.h> |
28 | #include <linux/mfd/rtsx_pci.h> |
29 | |
30 | #include "rtsx_pcr.h" |
31 | |
32 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) |
33 | { |
34 | u16 cap; |
35 | |
36 | rtsx_pci_init_cmd(pcr); |
37 | |
38 | /* Configure GPIO as output */ |
39 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); |
40 | /* Switch LDO3318 source from DV33 to card_3v3 */ |
41 | 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); |
43 | /* LED shine disabled, set initial shine cycle period */ |
44 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); |
45 | /* Configure LTR */ |
46 | pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap); |
47 | if (cap & PCI_EXP_LTR_EN) |
48 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); |
49 | /* Configure OBFF */ |
50 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); |
51 | /* Configure force_clock_req |
52 | * Maybe We should define 0xFF03 as some name |
53 | */ |
54 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08); |
55 | /* Correct driving */ |
56 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, |
57 | SD30_CLK_DRIVE_SEL, 0xFF, 0x96); |
58 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, |
59 | SD30_CMD_DRIVE_SEL, 0xFF, 0x96); |
60 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, |
61 | SD30_DAT_DRIVE_SEL, 0xFF, 0x96); |
62 | |
63 | return rtsx_pci_send_cmd(pcr, 100); |
64 | } |
65 | |
66 | static int rts5227_optimize_phy(struct rtsx_pcr *pcr) |
67 | { |
68 | /* Optimize RX sensitivity */ |
69 | return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42); |
70 | } |
71 | |
72 | static int rts5227_turn_on_led(struct rtsx_pcr *pcr) |
73 | { |
74 | return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02); |
75 | } |
76 | |
77 | static int rts5227_turn_off_led(struct rtsx_pcr *pcr) |
78 | { |
79 | return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00); |
80 | } |
81 | |
82 | static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr) |
83 | { |
84 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08); |
85 | } |
86 | |
87 | static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr) |
88 | { |
89 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00); |
90 | } |
91 | |
92 | static int rts5227_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_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 | /* To avoid too large in-rush current */ |
106 | udelay(150); |
107 | |
108 | rtsx_pci_init_cmd(pcr); |
109 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, |
110 | SD_POWER_MASK, SD_POWER_ON); |
111 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, |
112 | LDO3318_PWR_MASK, 0x06); |
113 | err = rtsx_pci_send_cmd(pcr, 100); |
114 | if (err < 0) |
115 | return err; |
116 | |
117 | return 0; |
118 | } |
119 | |
120 | static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) |
121 | { |
122 | rtsx_pci_init_cmd(pcr); |
123 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, |
124 | SD_POWER_MASK | PMOS_STRG_MASK, |
125 | SD_POWER_OFF | PMOS_STRG_400mA); |
126 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, |
127 | LDO3318_PWR_MASK, 0X00); |
128 | return rtsx_pci_send_cmd(pcr, 100); |
129 | } |
130 | |
131 | static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
132 | { |
133 | int err; |
134 | u8 drive_sel; |
135 | |
136 | if (voltage == OUTPUT_3V3) { |
137 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); |
138 | if (err < 0) |
139 | return err; |
140 | drive_sel = 0x96; |
141 | } else if (voltage == OUTPUT_1V8) { |
142 | err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); |
143 | if (err < 0) |
144 | return err; |
145 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24); |
146 | if (err < 0) |
147 | return err; |
148 | drive_sel = 0xB3; |
149 | } else { |
150 | return -EINVAL; |
151 | } |
152 | |
153 | /* set pad drive */ |
154 | rtsx_pci_init_cmd(pcr); |
155 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, |
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); |
162 | } |
163 | |
164 | static const struct pcr_ops rts5227_pcr_ops = { |
165 | .extra_init_hw = rts5227_extra_init_hw, |
166 | .optimize_phy = rts5227_optimize_phy, |
167 | .turn_on_led = rts5227_turn_on_led, |
168 | .turn_off_led = rts5227_turn_off_led, |
169 | .enable_auto_blink = rts5227_enable_auto_blink, |
170 | .disable_auto_blink = rts5227_disable_auto_blink, |
171 | .card_power_on = rts5227_card_power_on, |
172 | .card_power_off = rts5227_card_power_off, |
173 | .switch_output_voltage = rts5227_switch_output_voltage, |
174 | .cd_deglitch = NULL, |
175 | .conv_clk_and_div_n = NULL, |
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 | */ |
185 | static const u32 rts5227_sd_pull_ctl_enable_tbl[] = { |
186 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), |
187 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), |
188 | 0, |
189 | }; |
190 | |
191 | /* SD Pull Control Disable: |
192 | * SD_DAT[3:0] ==> pull down |
193 | * SD_CD ==> pull up |
194 | * SD_WP ==> pull down |
195 | * SD_CMD ==> pull down |
196 | * SD_CLK ==> pull down |
197 | */ |
198 | static const u32 rts5227_sd_pull_ctl_disable_tbl[] = { |
199 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), |
200 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), |
201 | 0, |
202 | }; |
203 | |
204 | /* MS Pull Control Enable: |
205 | * MS CD ==> pull up |
206 | * others ==> pull down |
207 | */ |
208 | static const u32 rts5227_ms_pull_ctl_enable_tbl[] = { |
209 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), |
210 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), |
211 | 0, |
212 | }; |
213 | |
214 | /* MS Pull Control Disable: |
215 | * MS CD ==> pull up |
216 | * others ==> pull down |
217 | */ |
218 | static const u32 rts5227_ms_pull_ctl_disable_tbl[] = { |
219 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), |
220 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), |
221 | 0, |
222 | }; |
223 | |
224 | void rts5227_init_params(struct rtsx_pcr *pcr) |
225 | { |
226 | pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; |
227 | pcr->num_slots = 2; |
228 | pcr->ops = &rts5227_pcr_ops; |
229 | |
230 | 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; |
232 | pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; |
233 | pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl; |
234 | } |
235 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9