Commit | Line | Data |
---|---|---|
1dac4186 | 1 | /* Driver for Realtek RTS51xx USB 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 | * wwang (wei_wang@realsil.com.cn) | |
20 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | |
21 | * Maintainer: | |
22 | * Edwin Rong (edwin_rong@realsil.com.cn) | |
23 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | |
24 | */ | |
25 | ||
26 | #include <linux/blkdev.h> | |
27 | #include <linux/kthread.h> | |
28 | #include <linux/sched.h> | |
29 | #include <linux/workqueue.h> | |
30 | ||
31 | #include "debug.h" | |
32 | #include "trace.h" | |
33 | #include "rts51x.h" | |
34 | #include "rts51x_chip.h" | |
35 | #include "rts51x_card.h" | |
36 | #include "rts51x_transport.h" | |
1dac4186 | 37 | #include "xd.h" |
38 | #include "ms.h" | |
39 | #include "sd.h" | |
40 | ||
41 | static int check_sd_speed_prior(u32 sd_speed_prior) | |
42 | { | |
43 | int i, fake_para = 0; | |
44 | ||
45 | /* Check the legality of sd_speed_prior */ | |
46 | for (i = 0; i < 4; i++) { | |
47 | u8 tmp = (u8) (sd_speed_prior >> (i * 8)); | |
48 | if ((tmp < 0x01) || (tmp > 0x04)) { | |
49 | fake_para = 1; | |
50 | break; | |
51 | } | |
52 | } | |
53 | ||
54 | return !fake_para; | |
55 | } | |
56 | ||
57 | int rts51x_reset_chip(struct rts51x_chip *chip) | |
58 | { | |
59 | int retval; | |
60 | ||
61 | if (CHECK_PKG(chip, LQFP48)) { | |
62 | RTS51X_WRITE_REG(chip, CARD_PWR_CTL, LDO3318_PWR_MASK, | |
63 | LDO_SUSPEND); | |
64 | RTS51X_WRITE_REG(chip, CARD_PWR_CTL, FORCE_LDO_POWERB, | |
65 | FORCE_LDO_POWERB); | |
66 | RTS51X_WRITE_REG(chip, CARD_PULL_CTL1, 0x30, 0x10); | |
67 | RTS51X_WRITE_REG(chip, CARD_PULL_CTL5, 0x03, 0x01); | |
68 | RTS51X_WRITE_REG(chip, CARD_PULL_CTL6, 0x0C, 0x04); | |
69 | } | |
70 | if (chip->asic_code) { | |
71 | RTS51X_WRITE_REG(chip, SYS_DUMMY0, NYET_MSAK, NYET_EN); | |
72 | RTS51X_WRITE_REG(chip, CD_DEGLITCH_WIDTH, 0xFF, 0x08); | |
73 | rts51x_write_register(chip, CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, | |
74 | 0x00); | |
75 | rts51x_write_register(chip, SD30_DRIVE_SEL, SD30_DRIVE_MASK, | |
76 | chip->option.sd30_pad_drive); | |
77 | rts51x_write_register(chip, CARD_DRIVE_SEL, SD20_DRIVE_MASK, | |
78 | chip->option.sd20_pad_drive); | |
79 | if (chip->rts5179) | |
80 | rts51x_write_register(chip, CARD_PULL_CTL5, 0x03, 0x01); | |
0e545f6d OR |
81 | if (CHECK_PKG(chip, LQFP48)) { |
82 | rts51x_write_register(chip, CARD_PULL_CTL3, | |
83 | 0x80, 0x80); | |
84 | rts51x_write_register(chip, CARD_PULL_CTL6, | |
85 | 0xf0, 0xA0); | |
86 | } else { | |
87 | rts51x_write_register(chip, CARD_PULL_CTL1, | |
88 | 0x30, 0x20); | |
89 | rts51x_write_register(chip, CARD_PULL_CTL3, | |
90 | 0x80, 0x80); | |
91 | rts51x_write_register(chip, CARD_PULL_CTL6, | |
92 | 0x0c, 0x08); | |
1dac4186 | 93 | } |
94 | } | |
95 | if (chip->option.sd_ctl & SUPPORT_UHS50_MMC44) { | |
96 | SET_UHS50(chip); | |
97 | RTS51X_DEBUGP("option enable UHS50&MMC44,sd_ctl:0x%x\n", | |
98 | chip->option.sd_ctl); | |
99 | } else { | |
100 | /* if(CHECK_PID(chip, 0x0139)&&CHECK_PKG(chip, LQFP48)) */ | |
101 | if ((CHECK_PID(chip, 0x0139) && CHECK_PKG(chip, LQFP48)) | |
102 | || chip->rts5179) { | |
103 | SET_UHS50(chip); | |
104 | RTS51X_DEBUGP("PID enable UHS50&MMC44\n"); | |
105 | } else { | |
106 | CLEAR_UHS50(chip); | |
107 | RTS51X_DEBUGP("PID disable UHS50&MMC44\n"); | |
108 | } | |
109 | } | |
110 | ||
111 | if (chip->option.ms_errreg_fix && (chip->ic_version > 1)) | |
112 | rts51x_write_register(chip, 0xFD4D, 0x01, 0x01); | |
113 | retval = rts51x_write_phy_register(chip, 0xC2, 0x7C); | |
114 | if (retval != STATUS_SUCCESS) | |
115 | TRACE_RET(chip, retval); | |
116 | ||
117 | rts51x_init_cmd(chip); | |
118 | ||
119 | /* GPIO OE */ | |
120 | rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO, GPIO_OE, GPIO_OE); | |
1dac4186 | 121 | rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DMA1_CTL, |
122 | EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL); | |
123 | ||
124 | retval = rts51x_send_cmd(chip, MODE_C, 100); | |
125 | if (retval != STATUS_SUCCESS) | |
126 | TRACE_RET(chip, retval); | |
127 | #ifdef SUPPORT_OCP | |
128 | if (chip->asic_code) { | |
129 | rts51x_write_register(chip, OCPCTL, MS_OCP_DETECT_EN, | |
130 | MS_OCP_DETECT_EN); | |
131 | RTS51X_DEBUGP("Enable OCP detect!\n"); | |
132 | } | |
133 | #endif | |
134 | if (chip->option.FT2_fast_mode) { | |
355d8ae5 | 135 | rts51x_card_power_on(chip, SD_CARD | MS_CARD | XD_CARD); |
1dac4186 | 136 | wait_timeout(10); |
137 | } | |
1dac4186 | 138 | |
139 | return STATUS_SUCCESS; | |
140 | } | |
141 | ||
142 | int rts51x_init_chip(struct rts51x_chip *chip) | |
143 | { | |
144 | int retval; | |
145 | u8 val; | |
146 | ||
147 | chip->max_lun = 0; | |
148 | chip->cur_clk = 0; | |
149 | chip->cur_card = 0; | |
150 | ||
151 | chip->card2lun[XD_CARD] = 0; | |
152 | chip->card2lun[SD_CARD] = 0; | |
153 | chip->card2lun[MS_CARD] = 0; | |
154 | chip->card_ejected = 0; | |
155 | ||
156 | chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD; | |
1dac4186 | 157 | #ifdef CLOSE_SSC_POWER |
158 | rts51x_write_register(chip, FPDCTL, SSC_POWER_MASK, SSC_POWER_ON); | |
159 | udelay(100); | |
160 | rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, 0x00); | |
161 | #endif | |
162 | RTS51X_SET_STAT(chip, STAT_RUN); | |
163 | ||
164 | RTS51X_READ_REG(chip, HW_VERSION, &val); | |
1dac4186 | 165 | RTS51X_DEBUGP("HW_VERSION: 0x%x\n", val); |
166 | if (val & FPGA_VER) { | |
167 | chip->asic_code = 0; | |
168 | RTS51X_DEBUGP("FPGA!\n"); | |
169 | } else { | |
170 | chip->asic_code = 1; | |
171 | RTS51X_DEBUGP("ASIC!\n"); | |
172 | } | |
173 | chip->ic_version = val & HW_VER_MASK; | |
174 | ||
175 | if (!check_sd_speed_prior(chip->option.sd_speed_prior)) | |
176 | chip->option.sd_speed_prior = 0x01020403; | |
177 | RTS51X_DEBUGP("sd_speed_prior = 0x%08x\n", | |
178 | chip->option.sd_speed_prior); | |
179 | ||
180 | RTS51X_READ_REG(chip, CARD_SHARE_MODE, &val); | |
181 | if (val & CARD_SHARE_LQFP_SEL) { | |
182 | chip->package = LQFP48; | |
183 | RTS51X_DEBUGP("Package: LQFP48\n"); | |
184 | } else { | |
185 | chip->package = QFN24; | |
186 | RTS51X_DEBUGP("Package: QFN24\n"); | |
187 | } | |
188 | ||
189 | RTS51X_READ_REG(chip, HS_USB_STAT, &val); | |
190 | if (val & USB_HI_SPEED) { | |
191 | chip->usb_speed = USB_20; | |
192 | RTS51X_DEBUGP("USB High Speed\n"); | |
193 | } else { | |
194 | chip->usb_speed = USB_11; | |
195 | RTS51X_DEBUGP("USB Full Speed\n"); | |
196 | } | |
197 | ||
198 | RTS51X_READ_REG(chip, CFG_MODE_1, &val); | |
199 | if (val & RTS5179) { | |
200 | chip->rts5179 = 1; | |
201 | RTS51X_DEBUGP("device is rts5179\n"); | |
202 | } else { | |
203 | chip->rts5179 = 0; | |
204 | } | |
205 | ||
206 | retval = rts51x_reset_chip(chip); | |
207 | if (retval != STATUS_SUCCESS) | |
208 | TRACE_RET(chip, STATUS_FAIL); | |
209 | ||
210 | return STATUS_SUCCESS; | |
211 | } | |
212 | ||
213 | int rts51x_release_chip(struct rts51x_chip *chip) | |
214 | { | |
355d8ae5 RT |
215 | rts51x_xd_free_l2p_tbl(chip); |
216 | rts51x_ms_free_l2p_tbl(chip); | |
1dac4186 | 217 | chip->card_ready = 0; |
218 | return STATUS_SUCCESS; | |
219 | } | |
220 | ||
1dac4186 | 221 | static inline void rts51x_blink_led(struct rts51x_chip *chip) |
222 | { | |
223 | /* Read/Write */ | |
224 | if (chip->card_ready) { | |
225 | if (chip->led_toggle_counter < | |
226 | chip->option.led_toggle_interval) { | |
227 | chip->led_toggle_counter++; | |
228 | } else { | |
229 | chip->led_toggle_counter = 0; | |
355d8ae5 | 230 | rts51x_toggle_gpio(chip, LED_GPIO); |
1dac4186 | 231 | } |
232 | } | |
233 | } | |
1dac4186 | 234 | |
1dac4186 | 235 | static void rts51x_auto_delink_cmd(struct rts51x_chip *chip) |
236 | { | |
237 | rts51x_write_register(chip, AUTO_DELINK_EN, | |
238 | AUTO_DELINK, AUTO_DELINK); | |
239 | } | |
240 | ||
241 | static void rts51x_auto_delink_force_cmd(struct rts51x_chip *chip) | |
242 | { | |
243 | rts51x_write_register(chip, AUTO_DELINK_EN, | |
244 | AUTO_DELINK | FORCE_DELINK, | |
245 | AUTO_DELINK | FORCE_DELINK); | |
246 | } | |
247 | ||
248 | #ifdef USING_POLLING_CYCLE_DELINK | |
249 | /* using polling cycle as delink time */ | |
250 | static void rts51x_auto_delink_polling_cycle(struct rts51x_chip *chip) | |
251 | { | |
252 | if (chip->auto_delink_counter <= | |
253 | chip->option.delink_delay * 2) { | |
254 | if (chip->auto_delink_counter == | |
255 | chip->option.delink_delay) { | |
1dac4186 | 256 | if (chip->card_exist) { |
257 | /* False card */ | |
258 | if (!chip->card_ejected) { | |
259 | /* if card is not ejected or safely | |
260 | * remove,then do force delink */ | |
261 | RTS51X_DEBUGP("False card inserted," | |
262 | "do force delink\n"); | |
263 | rts51x_auto_delink_force_cmd(chip); | |
264 | chip->auto_delink_counter = | |
265 | chip->option.delink_delay * 2 + 1; | |
266 | } | |
267 | } else { | |
268 | RTS51X_DEBUGP("No card inserted, do delink\n"); | |
269 | /* rts51x_write_register(chip, CARD_PWR_CTL, | |
270 | DV3318_AUTO_PWR_OFF, 0); */ | |
271 | rts51x_auto_delink_cmd(chip); | |
272 | } | |
273 | } | |
274 | if (chip->auto_delink_counter == | |
275 | chip->option.delink_delay * 2) { | |
276 | RTS51X_DEBUGP("Try to do force delink\n"); | |
277 | rts51x_auto_delink_force_cmd(chip); | |
278 | } | |
279 | chip->auto_delink_counter++; | |
280 | } | |
281 | } | |
282 | ||
283 | static void rts51x_auto_delink(struct rts51x_chip *chip) | |
284 | { | |
285 | rts51x_auto_delink_polling_cycle(chip); | |
286 | } | |
287 | #else | |
288 | /* some of called funcs are not implemented, so comment it out */ | |
1dac4186 | 289 | static void rts51x_auto_delink(struct rts51x_chip *chip) |
290 | { | |
1dac4186 | 291 | } |
292 | #endif | |
293 | ||
294 | void rts51x_polling_func(struct rts51x_chip *chip) | |
295 | { | |
1dac4186 | 296 | |
297 | rts51x_init_cards(chip); | |
298 | ||
299 | #ifdef SUPPORT_OCP | |
300 | /* if OCP happen and card exist, then close card OE */ | |
301 | if ((chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) && | |
302 | (chip->card_exist)) { | |
303 | ||
304 | rts51x_prepare_run(chip); | |
305 | ||
306 | if (chip->card_exist & SD_CARD) | |
307 | rts51x_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); | |
308 | else if (chip->card_exist & MS_CARD) | |
309 | rts51x_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); | |
310 | else if (chip->card_exist & XD_CARD) | |
311 | rts51x_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); | |
312 | } | |
313 | #endif | |
314 | ||
315 | if (chip->idle_counter < IDLE_MAX_COUNT) { | |
316 | chip->idle_counter++; | |
317 | } else { | |
318 | if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) { | |
319 | RTS51X_DEBUGP("Idle state!\n"); | |
320 | RTS51X_SET_STAT(chip, STAT_IDLE); | |
1dac4186 | 321 | chip->led_toggle_counter = 0; |
1dac4186 | 322 | /* Idle state, turn off LED |
323 | * to reduce power consumption */ | |
324 | if (chip->option.led_always_on | |
325 | && (chip->card_exist & | |
326 | (SD_CARD | MS_CARD | XD_CARD)) | |
327 | && (!chip->card_ejected)) { | |
355d8ae5 | 328 | rts51x_turn_on_led(chip, LED_GPIO); |
1dac4186 | 329 | } else { |
330 | if (chip->rts5179) { | |
331 | rts51x_ep0_write_register(chip, | |
332 | CARD_GPIO, | |
333 | 0x03, 0x00); | |
334 | } else { | |
355d8ae5 | 335 | rts51x_turn_off_led(chip, LED_GPIO); |
1dac4186 | 336 | } |
337 | ||
338 | } | |
339 | ||
340 | #ifdef CLOSE_SSC_POWER | |
341 | if (!chip->card_ready) { | |
342 | rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, | |
343 | CLK_CHANGE); | |
344 | rts51x_write_register(chip, FPDCTL, | |
345 | SSC_POWER_MASK, | |
346 | SSC_POWER_DOWN); | |
347 | RTS51X_DEBUGP("Close SSC clock power!\n"); | |
348 | } | |
349 | #endif | |
350 | } | |
351 | } | |
352 | ||
353 | switch (RTS51X_GET_STAT(chip)) { | |
354 | case STAT_RUN: | |
1dac4186 | 355 | rts51x_blink_led(chip); |
355d8ae5 | 356 | rts51x_do_remaining_work(chip); |
1dac4186 | 357 | break; |
358 | ||
359 | case STAT_IDLE: | |
360 | break; | |
361 | ||
362 | default: | |
363 | break; | |
364 | } | |
365 | ||
3852587a | 366 | if (chip->option.auto_delink_en && !chip->card_ready) |
1dac4186 | 367 | rts51x_auto_delink(chip); |
3852587a | 368 | else |
1dac4186 | 369 | chip->auto_delink_counter = 0; |
1dac4186 | 370 | } |
371 | ||
372 | void rts51x_add_cmd(struct rts51x_chip *chip, | |
373 | u8 cmd_type, u16 reg_addr, u8 mask, u8 data) | |
374 | { | |
375 | int i; | |
376 | ||
377 | if (chip->cmd_idx < ((CMD_BUF_LEN - CMD_OFFSET) / 4)) { | |
378 | i = CMD_OFFSET + chip->cmd_idx * 4; | |
379 | chip->cmd_buf[i++] = | |
380 | ((cmd_type & 0x03) << 6) | (u8) ((reg_addr >> 8) & 0x3F); | |
381 | chip->cmd_buf[i++] = (u8) reg_addr; | |
382 | chip->cmd_buf[i++] = mask; | |
383 | chip->cmd_buf[i++] = data; | |
384 | chip->cmd_idx++; | |
385 | } | |
386 | } | |
387 | ||
388 | int rts51x_send_cmd(struct rts51x_chip *chip, u8 flag, int timeout) | |
389 | { | |
390 | int result; | |
391 | ||
392 | chip->cmd_buf[CNT_H] = (u8) (chip->cmd_idx >> 8); | |
393 | chip->cmd_buf[CNT_L] = (u8) (chip->cmd_idx); | |
394 | chip->cmd_buf[STAGE_FLAG] = flag; | |
395 | ||
396 | result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), | |
397 | (void *)(chip->cmd_buf), | |
398 | chip->cmd_idx * 4 + CMD_OFFSET, | |
399 | 0, NULL, timeout, MODE_C); | |
400 | if (result != STATUS_SUCCESS) | |
401 | TRACE_RET(chip, result); | |
402 | ||
403 | return STATUS_SUCCESS; | |
404 | } | |
405 | ||
406 | int rts51x_get_rsp(struct rts51x_chip *chip, int rsp_len, int timeout) | |
407 | { | |
408 | int result; | |
409 | ||
410 | if (rsp_len <= 0) | |
411 | TRACE_RET(chip, STATUS_ERROR); | |
412 | /* rsp_len must aligned to dword */ | |
413 | if (rsp_len % 4) | |
414 | rsp_len += (4 - rsp_len % 4); | |
415 | ||
416 | result = rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), | |
417 | (void *)chip->rsp_buf, rsp_len, | |
418 | 0, NULL, timeout, STAGE_R); | |
419 | if (result != STATUS_SUCCESS) | |
420 | TRACE_RET(chip, result); | |
421 | ||
422 | return STATUS_SUCCESS; | |
423 | } | |
424 | ||
aa2f92ae | 425 | int rts51x_get_card_status(struct rts51x_chip *chip, u16 *status) |
1dac4186 | 426 | { |
427 | int retval; | |
428 | u16 val; | |
429 | ||
430 | #ifdef GET_CARD_STATUS_USING_EPC | |
431 | retval = rts51x_get_epc_status(chip, &val); | |
432 | ||
433 | if (retval != STATUS_SUCCESS) | |
434 | TRACE_RET(chip, retval); | |
435 | #else | |
436 | retval = rts51x_ctrl_transfer(chip, RCV_CTRL_PIPE(chip), 0x02, 0xC0, | |
437 | 0, 0, &val, 2, 100); | |
438 | if (retval != STATUS_SUCCESS) | |
439 | TRACE_RET(chip, retval); | |
440 | #endif | |
441 | ||
442 | if (status) | |
443 | *status = val; | |
444 | ||
445 | return STATUS_SUCCESS; | |
446 | } | |
447 | ||
448 | int rts51x_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data) | |
449 | { | |
450 | int retval; | |
451 | ||
452 | rts51x_init_cmd(chip); | |
453 | rts51x_add_cmd(chip, WRITE_REG_CMD, addr, mask, data); | |
454 | retval = rts51x_send_cmd(chip, MODE_C, 100); | |
455 | if (retval != STATUS_SUCCESS) | |
456 | TRACE_RET(chip, STATUS_FAIL); | |
457 | ||
458 | return STATUS_SUCCESS; | |
459 | } | |
460 | ||
aa2f92ae | 461 | int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 *data) |
1dac4186 | 462 | { |
463 | int retval; | |
464 | ||
465 | if (data) | |
466 | *data = 0; | |
467 | rts51x_init_cmd(chip); | |
468 | rts51x_add_cmd(chip, READ_REG_CMD, addr, 0, 0); | |
469 | retval = rts51x_send_cmd(chip, MODE_CR, 100); | |
470 | if (retval != STATUS_SUCCESS) | |
471 | TRACE_RET(chip, STATUS_FAIL); | |
472 | ||
473 | retval = rts51x_get_rsp(chip, 1, 100); | |
474 | ||
475 | if (retval != STATUS_SUCCESS) | |
476 | TRACE_RET(chip, STATUS_FAIL); | |
477 | ||
478 | if (data) | |
479 | *data = chip->rsp_buf[0]; | |
480 | ||
481 | return STATUS_SUCCESS; | |
482 | } | |
483 | ||
484 | int rts51x_ep0_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, | |
485 | u8 data) | |
486 | { | |
487 | int retval; | |
488 | u16 value = 0, index = 0; | |
489 | ||
490 | value |= (u16) (3 & 0x03) << 14; | |
491 | value |= (u16) (addr & 0x3FFF); | |
492 | index |= (u16) mask << 8; | |
493 | index |= (u16) data; | |
494 | ||
495 | retval = rts51x_ctrl_transfer(chip, SND_CTRL_PIPE(chip), 0x00, 0x40, | |
496 | cpu_to_be16(value), cpu_to_be16(index), | |
497 | NULL, 0, 100); | |
498 | if (retval != STATUS_SUCCESS) | |
499 | TRACE_RET(chip, retval); | |
500 | ||
501 | return STATUS_SUCCESS; | |
502 | } | |
503 | ||
aa2f92ae | 504 | int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 *data) |
1dac4186 | 505 | { |
506 | int retval; | |
507 | u16 value = 0; | |
508 | u8 val; | |
509 | ||
510 | if (data) | |
511 | *data = 0; | |
512 | ||
513 | value |= (u16) (2 & 0x03) << 14; | |
514 | value |= (u16) (addr & 0x3FFF); | |
515 | ||
516 | retval = rts51x_ctrl_transfer(chip, RCV_CTRL_PIPE(chip), 0x00, 0xC0, | |
517 | cpu_to_be16(value), 0, &val, 1, 100); | |
518 | if (retval != STATUS_SUCCESS) | |
519 | TRACE_RET(chip, retval); | |
520 | ||
521 | if (data) | |
522 | *data = val; | |
523 | ||
524 | return STATUS_SUCCESS; | |
525 | } | |
526 | ||
527 | int rts51x_seq_write_register(struct rts51x_chip *chip, u16 addr, u16 len, | |
528 | u8 *data) | |
529 | { | |
530 | int result; | |
531 | u16 cmd_len = len + 12; | |
532 | ||
533 | if (!data) | |
534 | TRACE_RET(chip, STATUS_ERROR); | |
535 | ||
536 | cmd_len = (cmd_len <= CMD_BUF_LEN) ? cmd_len : CMD_BUF_LEN; | |
537 | ||
538 | /* cmd_len must aligned to dword */ | |
539 | if (cmd_len % 4) | |
540 | cmd_len += (4 - cmd_len % 4); | |
541 | ||
542 | chip->cmd_buf[0] = 'R'; | |
543 | chip->cmd_buf[1] = 'T'; | |
544 | chip->cmd_buf[2] = 'C'; | |
545 | chip->cmd_buf[3] = 'R'; | |
546 | chip->cmd_buf[PACKET_TYPE] = SEQ_WRITE; | |
547 | chip->cmd_buf[5] = (u8) (len >> 8); | |
548 | chip->cmd_buf[6] = (u8) len; | |
549 | chip->cmd_buf[STAGE_FLAG] = 0; | |
550 | chip->cmd_buf[8] = (u8) (addr >> 8); | |
551 | chip->cmd_buf[9] = (u8) addr; | |
552 | ||
553 | memcpy(chip->cmd_buf + 12, data, len); | |
554 | ||
555 | result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), | |
556 | (void *)(chip->cmd_buf), cmd_len, 0, | |
557 | NULL, 100, MODE_C); | |
558 | if (result != STATUS_SUCCESS) | |
559 | TRACE_RET(chip, result); | |
560 | ||
561 | return STATUS_SUCCESS; | |
562 | } | |
563 | ||
564 | int rts51x_seq_read_register(struct rts51x_chip *chip, u16 addr, u16 len, | |
565 | u8 *data) | |
566 | { | |
567 | int result; | |
568 | u16 rsp_len; | |
569 | ||
570 | if (!data) | |
571 | TRACE_RET(chip, STATUS_ERROR); | |
572 | /* rsp_len must aligned to dword */ | |
573 | if (len % 4) | |
574 | rsp_len = len + (4 - len % 4); | |
575 | else | |
576 | rsp_len = len; | |
577 | ||
578 | chip->cmd_buf[0] = 'R'; | |
579 | chip->cmd_buf[1] = 'T'; | |
580 | chip->cmd_buf[2] = 'C'; | |
581 | chip->cmd_buf[3] = 'R'; | |
582 | chip->cmd_buf[PACKET_TYPE] = SEQ_READ; | |
583 | chip->cmd_buf[5] = (u8) (rsp_len >> 8); | |
584 | chip->cmd_buf[6] = (u8) rsp_len; | |
585 | chip->cmd_buf[STAGE_FLAG] = STAGE_R; | |
586 | chip->cmd_buf[8] = (u8) (addr >> 8); | |
587 | chip->cmd_buf[9] = (u8) addr; | |
588 | ||
589 | result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), | |
590 | (void *)(chip->cmd_buf), 12, 0, NULL, | |
591 | 100, MODE_C); | |
592 | if (result != STATUS_SUCCESS) | |
593 | TRACE_RET(chip, result); | |
594 | ||
595 | result = rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), | |
596 | (void *)data, rsp_len, 0, NULL, 100, | |
597 | STAGE_DI); | |
598 | if (result != STATUS_SUCCESS) | |
599 | TRACE_RET(chip, result); | |
600 | ||
601 | return STATUS_SUCCESS; | |
602 | } | |
603 | ||
aa2f92ae | 604 | int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len) |
1dac4186 | 605 | { |
606 | int retval; | |
607 | ||
608 | if (!buf) | |
609 | TRACE_RET(chip, STATUS_ERROR); | |
610 | ||
611 | retval = | |
612 | rts51x_seq_read_register(chip, PPBUF_BASE2, (u16) buf_len, buf); | |
613 | if (retval != STATUS_SUCCESS) | |
614 | TRACE_RET(chip, retval); | |
615 | ||
616 | return STATUS_SUCCESS; | |
617 | } | |
618 | ||
aa2f92ae | 619 | int rts51x_write_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len) |
1dac4186 | 620 | { |
621 | int retval; | |
622 | ||
623 | if (!buf) | |
624 | TRACE_RET(chip, STATUS_ERROR); | |
625 | ||
626 | retval = | |
627 | rts51x_seq_write_register(chip, PPBUF_BASE2, (u16) buf_len, buf); | |
628 | if (retval != STATUS_SUCCESS) | |
629 | TRACE_RET(chip, retval); | |
630 | ||
631 | return STATUS_SUCCESS; | |
632 | } | |
633 | ||
634 | int rts51x_write_phy_register(struct rts51x_chip *chip, u8 addr, u8 val) | |
635 | { | |
636 | int retval; | |
637 | ||
638 | RTS51X_DEBUGP("Write 0x%x to phy register 0x%x\n", val, addr); | |
639 | ||
640 | rts51x_init_cmd(chip); | |
641 | ||
642 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val); | |
643 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F); | |
644 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
645 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
646 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | |
647 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, | |
648 | (addr >> 4) & 0x0F); | |
649 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
650 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
651 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | |
652 | ||
653 | retval = rts51x_send_cmd(chip, MODE_C, 100); | |
654 | if (retval != STATUS_SUCCESS) | |
655 | TRACE_RET(chip, retval); | |
656 | ||
657 | return STATUS_SUCCESS; | |
658 | } | |
659 | ||
aa2f92ae | 660 | int rts51x_read_phy_register(struct rts51x_chip *chip, u8 addr, u8 *val) |
1dac4186 | 661 | { |
662 | int retval; | |
663 | ||
664 | RTS51X_DEBUGP("Read from phy register 0x%x\n", addr); | |
665 | ||
666 | rts51x_init_cmd(chip); | |
667 | ||
668 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, 0x07); | |
669 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
670 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
671 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | |
672 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, | |
673 | (addr >> 4) & 0x0F); | |
674 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
675 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
676 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | |
677 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F); | |
678 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
679 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | |
680 | rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | |
681 | rts51x_add_cmd(chip, READ_REG_CMD, HS_VSTAOUT, 0, 0); | |
682 | ||
683 | retval = rts51x_send_cmd(chip, MODE_CR, 100); | |
684 | if (retval != STATUS_SUCCESS) | |
685 | TRACE_RET(chip, retval); | |
686 | ||
687 | retval = rts51x_get_rsp(chip, 1, 100); | |
688 | ||
689 | if (retval != STATUS_SUCCESS) | |
690 | TRACE_RET(chip, retval); | |
691 | ||
692 | if (val) | |
693 | *val = chip->rsp_buf[0]; | |
694 | ||
695 | RTS51X_DEBUGP("Return value: 0x%x\n", chip->rsp_buf[0]); | |
696 | ||
697 | return STATUS_SUCCESS; | |
698 | } | |
699 | ||
700 | void rts51x_do_before_power_down(struct rts51x_chip *chip) | |
701 | { | |
702 | RTS51X_DEBUGP("rts51x_do_before_power_down\n"); | |
703 | ||
704 | rts51x_prepare_run(chip); | |
705 | ||
706 | rts51x_release_cards(chip); | |
707 | if (chip->rts5179) | |
708 | rts51x_ep0_write_register(chip, CARD_GPIO, 0x03, 0x00); | |
709 | else | |
355d8ae5 | 710 | rts51x_turn_off_led(chip, LED_GPIO); |
1dac4186 | 711 | |
712 | chip->cur_clk = 0; | |
713 | chip->card_exist = 0; | |
714 | chip->cur_card = 0; | |
0e545f6d | 715 | if (chip->asic_code) { |
1dac4186 | 716 | if (CHECK_PKG(chip, LQFP48)) { |
717 | rts51x_write_register(chip, CARD_PULL_CTL3, 0x80, 0x00); | |
718 | rts51x_write_register(chip, CARD_PULL_CTL6, 0xf0, 0x50); | |
719 | } else { | |
720 | rts51x_write_register(chip, CARD_PULL_CTL1, 0x30, 0x10); | |
721 | rts51x_write_register(chip, CARD_PULL_CTL3, 0x80, 0x00); | |
722 | rts51x_write_register(chip, CARD_PULL_CTL6, 0x0c, 0x04); | |
723 | } | |
724 | } | |
725 | if (CHECK_PKG(chip, LQFP48)) | |
726 | rts51x_write_register(chip, CARD_PWR_CTL, LDO3318_PWR_MASK, | |
727 | LDO_OFF); | |
728 | } | |
729 | ||
730 | void rts51x_clear_hw_error(struct rts51x_chip *chip) | |
731 | { | |
732 | rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); | |
733 | } | |
734 | ||
735 | void rts51x_prepare_run(struct rts51x_chip *chip) | |
736 | { | |
737 | #ifdef CLOSE_SSC_POWER | |
738 | if (RTS51X_CHK_STAT(chip, STAT_IDLE) && (!chip->card_ready)) { | |
739 | rts51x_write_register(chip, FPDCTL, SSC_POWER_MASK, | |
740 | SSC_POWER_ON); | |
741 | udelay(100); | |
742 | RTS51X_DEBUGP("Open SSC clock power.\n"); | |
743 | ||
744 | rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, 0x00); | |
745 | } | |
746 | #endif | |
1dac4186 | 747 | } |
748 | ||
749 | #ifdef _MSG_TRACE | |
750 | void rts51x_trace_msg(struct rts51x_chip *chip, unsigned char *buf, int clear) | |
751 | { | |
752 | unsigned char *ptr; | |
753 | int i, msg_cnt; | |
754 | ||
755 | if (!buf) | |
756 | return; | |
757 | ||
758 | ptr = buf; | |
759 | ||
760 | if (chip->trace_msg[chip->msg_idx].valid) | |
761 | msg_cnt = TRACE_ITEM_CNT; | |
762 | else | |
763 | msg_cnt = chip->msg_idx; | |
764 | *(ptr++) = (u8) (msg_cnt >> 24); | |
765 | *(ptr++) = (u8) (msg_cnt >> 16); | |
766 | *(ptr++) = (u8) (msg_cnt >> 8); | |
767 | *(ptr++) = (u8) msg_cnt; | |
768 | RTS51X_DEBUGP("Trace message count is %d\n", msg_cnt); | |
769 | ||
770 | for (i = 1; i <= msg_cnt; i++) { | |
771 | int j, idx; | |
772 | ||
773 | idx = chip->msg_idx - i; | |
774 | if (idx < 0) | |
775 | idx += TRACE_ITEM_CNT; | |
776 | ||
777 | *(ptr++) = (u8) (chip->trace_msg[idx].line >> 8); | |
778 | *(ptr++) = (u8) (chip->trace_msg[idx].line); | |
779 | for (j = 0; j < MSG_FUNC_LEN; j++) | |
780 | *(ptr++) = chip->trace_msg[idx].func[j]; | |
781 | for (j = 0; j < MSG_FILE_LEN; j++) | |
782 | *(ptr++) = chip->trace_msg[idx].file[j]; | |
783 | for (j = 0; j < TIME_VAL_LEN; j++) | |
784 | *(ptr++) = chip->trace_msg[idx].timeval_buf[j]; | |
785 | } | |
786 | ||
787 | if (clear) { | |
788 | chip->msg_idx = 0; | |
789 | for (i = 0; i < TRACE_ITEM_CNT; i++) | |
790 | chip->trace_msg[i].valid = 0; | |
791 | } | |
792 | } | |
793 | #endif | |
794 | ||
aa2f92ae | 795 | void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status, |
1dac4186 | 796 | u8 status_len) |
797 | { | |
798 | struct sd_info *sd_card = &(chip->sd_card); | |
799 | struct ms_info *ms_card = &(chip->ms_card); | |
355d8ae5 | 800 | u8 card = rts51x_get_lun_card(chip, lun); |
1dac4186 | 801 | #ifdef SUPPORT_OC |
802 | u8 oc_now_mask = 0, oc_ever_mask = 0; | |
803 | #endif | |
804 | ||
805 | if (!status || (status_len < 32)) | |
806 | return; | |
807 | /* IC Version */ | |
808 | status[0] = (u8) RTS51X_GET_PID(chip); | |
809 | status[1] = (u8) (chip->ic_version); | |
810 | ||
811 | /* Auto delink mode */ | |
812 | if (chip->option.auto_delink_en) | |
813 | status[2] = 0x10; | |
814 | else | |
815 | status[2] = 0x00; | |
816 | ||
817 | /* Spec version */ | |
818 | status[3] = 20; | |
819 | status[4] = 10; | |
820 | status[5] = 05; | |
821 | status[6] = 21; | |
822 | ||
823 | /* Card WP */ | |
824 | if (chip->card_wp) | |
825 | status[7] = 0x20; | |
826 | else | |
827 | status[7] = 0x00; | |
828 | ||
829 | #ifdef SUPPORT_OC | |
830 | /* Over current status */ | |
831 | status[8] = 0; | |
832 | oc_now_mask = MS_OCP_NOW; | |
833 | oc_ever_mask = MS_OCP_EVER; | |
834 | ||
835 | if (chip->ocp_stat & oc_now_mask) | |
836 | status[8] |= 0x02; | |
837 | if (chip->ocp_stat & oc_ever_mask) | |
838 | status[8] |= 0x01; | |
839 | #endif | |
840 | ||
841 | if (card == SD_CARD) { | |
842 | if (CHK_SD(sd_card)) { | |
843 | if (CHK_SD_HCXC(sd_card)) { | |
844 | if (sd_card->capacity > 0x4000000) | |
845 | /* SDXC */ | |
846 | status[0x0E] = 0x02; | |
847 | else /* SDHC */ | |
848 | status[0x0E] = 0x01; | |
849 | } else { /* SDSC */ | |
850 | status[0x0E] = 0x00; | |
851 | } | |
852 | ||
853 | if (CHK_SD_SDR104(sd_card)) | |
854 | status[0x0F] = 0x03; | |
855 | else if (CHK_SD_DDR50(sd_card)) | |
856 | status[0x0F] = 0x04; | |
857 | else if (CHK_SD_SDR50(sd_card)) | |
858 | status[0x0F] = 0x02; | |
859 | else if (CHK_SD_HS(sd_card)) | |
860 | status[0x0F] = 0x01; | |
861 | else | |
862 | status[0x0F] = 0x00; /* Normal speed */ | |
863 | } else { | |
864 | if (CHK_MMC_SECTOR_MODE(sd_card)) | |
865 | status[0x0E] = 0x01; /* High capacity */ | |
866 | else | |
867 | status[0x0E] = 0x00; /* Normal capacity */ | |
868 | ||
869 | if (CHK_MMC_DDR52(sd_card)) | |
870 | status[0x0F] = 0x03; /* DDR 52M */ | |
871 | else if (CHK_MMC_52M(sd_card)) | |
872 | status[0x0F] = 0x02; /* SDR 52M */ | |
873 | else if (CHK_MMC_26M(sd_card)) | |
874 | status[0x0F] = 0x01; /* SDR 26M */ | |
875 | else | |
876 | status[0x0F] = 0x00; /* Normal speed */ | |
877 | } | |
878 | } else if (card == MS_CARD) { | |
879 | if (CHK_MSPRO(ms_card)) { | |
880 | if (CHK_MSXC(ms_card)) | |
881 | status[0x0E] = 0x01; /* XC */ | |
882 | else | |
883 | status[0x0E] = 0x00; | |
884 | ||
885 | if (CHK_HG8BIT(ms_card)) | |
886 | status[0x0F] = 0x01; | |
887 | else | |
888 | status[0x0F] = 0x00; | |
889 | } | |
890 | } | |
1dac4186 | 891 | |
892 | /* Function 0 | |
893 | * Support Magic Gate, CPRM and PhyRegister R/W */ | |
894 | status[0x18] = 0x8A; | |
895 | ||
896 | /* Function 2 | |
897 | * Support OC LUN status & WP LUN status */ | |
898 | status[0x1A] = 0x28; | |
899 | ||
1dac4186 | 900 | /* Function 2 |
901 | * Support OC LUN status & WP LUN status */ | |
902 | status[0x1A] = 0x28; | |
903 | } | |
904 | ||
905 | void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun, | |
906 | u8 *rts51x_status, u8 status_len) | |
907 | { | |
908 | if (!rts51x_status || (status_len < 16)) | |
909 | return; | |
910 | /* VID */ | |
911 | rts51x_status[0] = (u8) (RTS51X_GET_VID(chip) >> 8); | |
912 | rts51x_status[1] = (u8) RTS51X_GET_VID(chip); | |
913 | ||
914 | /* PID */ | |
915 | rts51x_status[2] = (u8) (RTS51X_GET_PID(chip) >> 8); | |
916 | rts51x_status[3] = (u8) RTS51X_GET_PID(chip); | |
917 | ||
918 | /* gbLUN */ | |
919 | rts51x_status[4] = (u8) lun; | |
920 | ||
921 | /* Lun Card Number */ | |
922 | if (chip->card_exist) { | |
923 | if (chip->card_exist & XD_CARD) | |
924 | rts51x_status[5] = 4; /* xD Card */ | |
925 | else if (chip->card_exist & SD_CARD) | |
926 | rts51x_status[5] = 2; /* SD Card */ | |
927 | else if (chip->card_exist & MS_CARD) | |
928 | rts51x_status[5] = 3; /* MS Card */ | |
929 | else | |
930 | rts51x_status[5] = 7; /* Multi */ | |
931 | } else { | |
932 | rts51x_status[5] = 7; /* Multi */ | |
933 | } | |
934 | ||
935 | /* Total LUNs */ | |
936 | rts51x_status[6] = 1; | |
937 | ||
938 | /* IC Version */ | |
939 | rts51x_status[7] = (u8) RTS51X_GET_PID(chip); | |
940 | rts51x_status[8] = chip->ic_version; | |
941 | ||
942 | /* Physical Exist */ | |
943 | if (check_card_exist(chip, lun)) | |
944 | rts51x_status[9] = 1; | |
945 | else | |
946 | rts51x_status[9] = 0; | |
947 | ||
948 | /* Multi Flag */ | |
949 | rts51x_status[10] = 1; | |
950 | ||
951 | /* LUN Valid Map */ | |
952 | rts51x_status[11] = XD_CARD | SD_CARD | MS_CARD; | |
953 | ||
954 | /* Logical Exist */ | |
955 | if (check_card_ready(chip, lun)) | |
956 | rts51x_status[12] = 1; | |
957 | else | |
958 | rts51x_status[12] = 0; | |
959 | ||
960 | /* Detailed Type */ | |
355d8ae5 | 961 | if (rts51x_get_lun_card(chip, lun) == XD_CARD) { |
1dac4186 | 962 | rts51x_status[13] = 0x40; |
355d8ae5 | 963 | } else if (rts51x_get_lun_card(chip, lun) == SD_CARD) { |
1dac4186 | 964 | struct sd_info *sd_card = &(chip->sd_card); |
965 | ||
966 | rts51x_status[13] = 0x20; | |
967 | if (CHK_SD(sd_card)) { | |
968 | if (CHK_SD_HCXC(sd_card)) | |
969 | rts51x_status[13] |= 0x04; /* Hi capacity SD */ | |
970 | if (CHK_SD_HS(sd_card)) | |
971 | rts51x_status[13] |= 0x02; /* Hi speed SD */ | |
972 | } else { | |
973 | rts51x_status[13] |= 0x08; /* MMC card */ | |
974 | if (CHK_MMC_52M(sd_card)) | |
975 | rts51x_status[13] |= 0x02; /* Hi speed */ | |
976 | if (CHK_MMC_SECTOR_MODE(sd_card)) | |
977 | rts51x_status[13] |= 0x04; /* Hi capacity */ | |
978 | } | |
355d8ae5 | 979 | } else if (rts51x_get_lun_card(chip, lun) == MS_CARD) { |
1dac4186 | 980 | struct ms_info *ms_card = &(chip->ms_card); |
981 | ||
982 | if (CHK_MSPRO(ms_card)) { | |
983 | rts51x_status[13] = 0x38; /* MS Pro */ | |
984 | if (CHK_HG8BIT(ms_card)) | |
985 | rts51x_status[13] |= 0x04; /* HG */ | |
986 | #ifdef SUPPORT_MSXC | |
987 | if (CHK_MSXC(ms_card)) | |
988 | rts51x_status[13] |= 0x01; /* MSXC */ | |
989 | #endif | |
990 | } else { | |
991 | rts51x_status[13] = 0x30; | |
992 | } | |
993 | } else { | |
994 | rts51x_status[13] = 0x70; | |
995 | } | |
996 | /* Support OC, auto delink, vendor r/w, get bus width */ | |
997 | rts51x_status[14] = 0x78; | |
998 | ||
999 | rts51x_status[15] = 0x82; | |
1000 | } | |
1001 | ||
1002 | int rts51x_transfer_data_rcc(struct rts51x_chip *chip, unsigned int pipe, | |
1003 | void *buf, unsigned int len, int use_sg, | |
1004 | unsigned int *act_len, int timeout, u8 stage_flag) | |
1005 | { | |
1006 | int retval; | |
1007 | ||
1008 | retval = | |
1009 | rts51x_transfer_data(chip, pipe, buf, len, use_sg, act_len, | |
1010 | timeout); | |
1011 | ||
1012 | return retval; | |
1013 | ||
1014 | } |