diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 490 |
2 files changed, 422 insertions, 72 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 697565137e8e..bedc4b9f2ac4 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -40,6 +40,10 @@ config USB_STORAGE_REALTEK | |||
40 | 40 | ||
41 | If this driver is compiled as a module, it will be named ums-realtek. | 41 | If this driver is compiled as a module, it will be named ums-realtek. |
42 | 42 | ||
43 | config REALTEK_AUTOPM | ||
44 | bool "Realtek Card Reader autosuspend support" | ||
45 | depends on USB_STORAGE_REALTEK && CONFIG_PM_RUNTIME | ||
46 | default y | ||
43 | 47 | ||
44 | config USB_STORAGE_DATAFAB | 48 | config USB_STORAGE_DATAFAB |
45 | tristate "Datafab Compact Flash Reader support" | 49 | tristate "Datafab Compact Flash Reader support" |
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index d509a4a7d74f..34adc4b42ceb 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
25 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/workqueue.h> | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
29 | #include <linux/version.h> | 28 | #include <linux/version.h> |
30 | 29 | ||
@@ -51,6 +50,35 @@ static int auto_delink_en = 1; | |||
51 | module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); | 50 | module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); |
52 | MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); | 51 | MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); |
53 | 52 | ||
53 | #ifdef CONFIG_REALTEK_AUTOPM | ||
54 | static int ss_en = 1; | ||
55 | module_param(ss_en, int, S_IRUGO | S_IWUSR); | ||
56 | MODULE_PARM_DESC(ss_en, "enable selective suspend"); | ||
57 | |||
58 | static int ss_delay = 50; | ||
59 | module_param(ss_delay, int, S_IRUGO | S_IWUSR); | ||
60 | MODULE_PARM_DESC(ss_delay, | ||
61 | "seconds to delay before entering selective suspend"); | ||
62 | |||
63 | enum RTS51X_STAT { | ||
64 | RTS51X_STAT_INIT, | ||
65 | RTS51X_STAT_IDLE, | ||
66 | RTS51X_STAT_RUN, | ||
67 | RTS51X_STAT_SS | ||
68 | }; | ||
69 | |||
70 | #define POLLING_INTERVAL 50 | ||
71 | |||
72 | #define rts51x_set_stat(chip, stat) \ | ||
73 | ((chip)->state = (enum RTS51X_STAT)(stat)) | ||
74 | #define rts51x_get_stat(chip) ((chip)->state) | ||
75 | |||
76 | #define SET_LUN_READY(chip, lun) ((chip)->lun_ready |= ((u8)1 << (lun))) | ||
77 | #define CLR_LUN_READY(chip, lun) ((chip)->lun_ready &= ~((u8)1 << (lun))) | ||
78 | #define TST_LUN_READY(chip, lun) ((chip)->lun_ready & ((u8)1 << (lun))) | ||
79 | |||
80 | #endif | ||
81 | |||
54 | struct rts51x_status { | 82 | struct rts51x_status { |
55 | u16 vid; | 83 | u16 vid; |
56 | u16 pid; | 84 | u16 pid; |
@@ -70,14 +98,25 @@ struct rts51x_status { | |||
70 | }; | 98 | }; |
71 | 99 | ||
72 | struct rts51x_chip { | 100 | struct rts51x_chip { |
73 | u16 vendor_id; | 101 | u16 vendor_id; |
74 | u16 product_id; | 102 | u16 product_id; |
75 | char max_lun; | 103 | char max_lun; |
76 | 104 | ||
77 | struct rts51x_status *status; | 105 | struct rts51x_status *status; |
78 | int status_len; | 106 | int status_len; |
79 | 107 | ||
80 | u32 flag; | 108 | u32 flag; |
109 | #ifdef CONFIG_REALTEK_AUTOPM | ||
110 | struct us_data *us; | ||
111 | struct timer_list rts51x_suspend_timer; | ||
112 | unsigned long timer_expires; | ||
113 | int pwr_state; | ||
114 | u8 lun_ready; | ||
115 | enum RTS51X_STAT state; | ||
116 | int support_auto_delink; | ||
117 | #endif | ||
118 | /* used to back up the protocal choosen in probe1 phase */ | ||
119 | proto_cmnd proto_handler_backup; | ||
81 | }; | 120 | }; |
82 | 121 | ||
83 | /* flag definition */ | 122 | /* flag definition */ |
@@ -97,9 +136,14 @@ struct rts51x_chip { | |||
97 | #define RTS51X_GET_VID(chip) ((chip)->vendor_id) | 136 | #define RTS51X_GET_VID(chip) ((chip)->vendor_id) |
98 | #define RTS51X_GET_PID(chip) ((chip)->product_id) | 137 | #define RTS51X_GET_PID(chip) ((chip)->product_id) |
99 | 138 | ||
139 | #define VENDOR_ID(chip) ((chip)->status[0].vid) | ||
140 | #define PRODUCT_ID(chip) ((chip)->status[0].pid) | ||
100 | #define FW_VERSION(chip) ((chip)->status[0].fw_ver) | 141 | #define FW_VERSION(chip) ((chip)->status[0].fw_ver) |
101 | #define STATUS_LEN(chip) ((chip)->status_len) | 142 | #define STATUS_LEN(chip) ((chip)->status_len) |
102 | 143 | ||
144 | #define STATUS_SUCCESS 0 | ||
145 | #define STATUS_FAIL 1 | ||
146 | |||
103 | /* Check card reader function */ | 147 | /* Check card reader function */ |
104 | #define SUPPORT_DETAILED_TYPE1(chip) \ | 148 | #define SUPPORT_DETAILED_TYPE1(chip) \ |
105 | CHK_BIT((chip)->status[0].function[0], 1) | 149 | CHK_BIT((chip)->status[0].function[0], 1) |
@@ -119,15 +163,6 @@ struct rts51x_chip { | |||
119 | #define CHECK_ID(chip, pid, fw_ver) \ | 163 | #define CHECK_ID(chip, pid, fw_ver) \ |
120 | (CHECK_PID((chip), (pid)) && CHECK_FW_VER((chip), (fw_ver))) | 164 | (CHECK_PID((chip), (pid)) && CHECK_FW_VER((chip), (fw_ver))) |
121 | 165 | ||
122 | #define wait_timeout_x(task_state, msecs) \ | ||
123 | do { \ | ||
124 | set_current_state((task_state)); \ | ||
125 | schedule_timeout((msecs) * HZ / 1000); \ | ||
126 | } while (0) | ||
127 | |||
128 | #define wait_timeout(msecs) \ | ||
129 | wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) | ||
130 | |||
131 | static int init_realtek_cr(struct us_data *us); | 166 | static int init_realtek_cr(struct us_data *us); |
132 | 167 | ||
133 | /* | 168 | /* |
@@ -143,8 +178,9 @@ static int init_realtek_cr(struct us_data *us); | |||
143 | 178 | ||
144 | static const struct usb_device_id realtek_cr_ids[] = { | 179 | static const struct usb_device_id realtek_cr_ids[] = { |
145 | # include "unusual_realtek.h" | 180 | # include "unusual_realtek.h" |
146 | { } /* Terminating entry */ | 181 | {} /* Terminating entry */ |
147 | }; | 182 | }; |
183 | |||
148 | MODULE_DEVICE_TABLE(usb, realtek_cr_ids); | 184 | MODULE_DEVICE_TABLE(usb, realtek_cr_ids); |
149 | 185 | ||
150 | #undef UNUSUAL_DEV | 186 | #undef UNUSUAL_DEV |
@@ -165,7 +201,7 @@ MODULE_DEVICE_TABLE(usb, realtek_cr_ids); | |||
165 | 201 | ||
166 | static struct us_unusual_dev realtek_cr_unusual_dev_list[] = { | 202 | static struct us_unusual_dev realtek_cr_unusual_dev_list[] = { |
167 | # include "unusual_realtek.h" | 203 | # include "unusual_realtek.h" |
168 | { } /* Terminating entry */ | 204 | {} /* Terminating entry */ |
169 | }; | 205 | }; |
170 | 206 | ||
171 | #undef UNUSUAL_DEV | 207 | #undef UNUSUAL_DEV |
@@ -174,8 +210,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
174 | u8 *cmd, int cmd_len, u8 *buf, int buf_len, | 210 | u8 *cmd, int cmd_len, u8 *buf, int buf_len, |
175 | enum dma_data_direction dir, int *act_len) | 211 | enum dma_data_direction dir, int *act_len) |
176 | { | 212 | { |
177 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | 213 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *)us->iobuf; |
178 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | 214 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *)us->iobuf; |
179 | int result; | 215 | int result; |
180 | unsigned int residue; | 216 | unsigned int residue; |
181 | unsigned int cswlen; | 217 | unsigned int cswlen; |
@@ -195,7 +231,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
195 | 231 | ||
196 | /* send it to out endpoint */ | 232 | /* send it to out endpoint */ |
197 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | 233 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, |
198 | bcb, cbwlen, NULL); | 234 | bcb, cbwlen, NULL); |
199 | if (result != USB_STOR_XFER_GOOD) | 235 | if (result != USB_STOR_XFER_GOOD) |
200 | return USB_STOR_TRANSPORT_ERROR; | 236 | return USB_STOR_TRANSPORT_ERROR; |
201 | 237 | ||
@@ -204,24 +240,23 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
204 | 240 | ||
205 | if (buf && buf_len) { | 241 | if (buf && buf_len) { |
206 | unsigned int pipe = (dir == DMA_FROM_DEVICE) ? | 242 | unsigned int pipe = (dir == DMA_FROM_DEVICE) ? |
207 | us->recv_bulk_pipe : us->send_bulk_pipe; | 243 | us->recv_bulk_pipe : us->send_bulk_pipe; |
208 | result = usb_stor_bulk_transfer_buf(us, pipe, | 244 | result = usb_stor_bulk_transfer_buf(us, pipe, |
209 | buf, buf_len, NULL); | 245 | buf, buf_len, NULL); |
210 | if (result == USB_STOR_XFER_ERROR) | 246 | if (result == USB_STOR_XFER_ERROR) |
211 | return USB_STOR_TRANSPORT_ERROR; | 247 | return USB_STOR_TRANSPORT_ERROR; |
212 | } | 248 | } |
213 | 249 | ||
214 | /* get CSW for device status */ | 250 | /* get CSW for device status */ |
215 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 251 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
216 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); | 252 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); |
217 | if (result != USB_STOR_XFER_GOOD) | 253 | if (result != USB_STOR_XFER_GOOD) |
218 | return USB_STOR_TRANSPORT_ERROR; | 254 | return USB_STOR_TRANSPORT_ERROR; |
219 | 255 | ||
220 | /* check bulk status */ | 256 | /* check bulk status */ |
221 | if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) { | 257 | if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) { |
222 | US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n", | 258 | US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n", |
223 | le32_to_cpu(bcs->Signature), | 259 | le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN); |
224 | US_BULK_CS_SIGN); | ||
225 | return USB_STOR_TRANSPORT_ERROR; | 260 | return USB_STOR_TRANSPORT_ERROR; |
226 | } | 261 | } |
227 | 262 | ||
@@ -249,8 +284,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
249 | 284 | ||
250 | case US_BULK_STAT_PHASE: | 285 | case US_BULK_STAT_PHASE: |
251 | /* phase error -- note that a transport reset will be | 286 | /* phase error -- note that a transport reset will be |
252 | * invoked by the invoke_transport() function | 287 | * invoked by the invoke_transport() function |
253 | */ | 288 | */ |
254 | return USB_STOR_TRANSPORT_ERROR; | 289 | return USB_STOR_TRANSPORT_ERROR; |
255 | } | 290 | } |
256 | 291 | ||
@@ -266,10 +301,10 @@ static int rts51x_get_max_lun(struct us_data *us) | |||
266 | /* issue the command */ | 301 | /* issue the command */ |
267 | us->iobuf[0] = 0; | 302 | us->iobuf[0] = 0; |
268 | result = usb_stor_control_msg(us, us->recv_ctrl_pipe, | 303 | result = usb_stor_control_msg(us, us->recv_ctrl_pipe, |
269 | US_BULK_GET_MAX_LUN, | 304 | US_BULK_GET_MAX_LUN, |
270 | USB_DIR_IN | USB_TYPE_CLASS | | 305 | USB_DIR_IN | USB_TYPE_CLASS | |
271 | USB_RECIP_INTERFACE, | 306 | USB_RECIP_INTERFACE, |
272 | 0, us->ifnum, us->iobuf, 1, 10*HZ); | 307 | 0, us->ifnum, us->iobuf, 1, 10 * HZ); |
273 | 308 | ||
274 | US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", | 309 | US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", |
275 | result, us->iobuf[0]); | 310 | result, us->iobuf[0]); |
@@ -284,16 +319,16 @@ static int rts51x_get_max_lun(struct us_data *us) | |||
284 | static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | 319 | static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) |
285 | { | 320 | { |
286 | int retval; | 321 | int retval; |
287 | u8 cmnd[12] = {0}; | 322 | u8 cmnd[12] = { 0 }; |
288 | 323 | ||
289 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 324 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
290 | 325 | ||
291 | cmnd[0] = 0xF0; | 326 | cmnd[0] = 0xF0; |
292 | cmnd[1] = 0x0D; | 327 | cmnd[1] = 0x0D; |
293 | cmnd[2] = (u8)(addr >> 8); | 328 | cmnd[2] = (u8) (addr >> 8); |
294 | cmnd[3] = (u8)addr; | 329 | cmnd[3] = (u8) addr; |
295 | cmnd[4] = (u8)(len >> 8); | 330 | cmnd[4] = (u8) (len >> 8); |
296 | cmnd[5] = (u8)len; | 331 | cmnd[5] = (u8) len; |
297 | 332 | ||
298 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 333 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
299 | data, len, DMA_FROM_DEVICE, NULL); | 334 | data, len, DMA_FROM_DEVICE, NULL); |
@@ -306,16 +341,16 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
306 | static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | 341 | static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) |
307 | { | 342 | { |
308 | int retval; | 343 | int retval; |
309 | u8 cmnd[12] = {0}; | 344 | u8 cmnd[12] = { 0 }; |
310 | 345 | ||
311 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 346 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
312 | 347 | ||
313 | cmnd[0] = 0xF0; | 348 | cmnd[0] = 0xF0; |
314 | cmnd[1] = 0x0E; | 349 | cmnd[1] = 0x0E; |
315 | cmnd[2] = (u8)(addr >> 8); | 350 | cmnd[2] = (u8) (addr >> 8); |
316 | cmnd[3] = (u8)addr; | 351 | cmnd[3] = (u8) addr; |
317 | cmnd[4] = (u8)(len >> 8); | 352 | cmnd[4] = (u8) (len >> 8); |
318 | cmnd[5] = (u8)len; | 353 | cmnd[5] = (u8) len; |
319 | 354 | ||
320 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 355 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
321 | data, len, DMA_TO_DEVICE, NULL); | 356 | data, len, DMA_TO_DEVICE, NULL); |
@@ -329,7 +364,7 @@ static int rts51x_read_status(struct us_data *us, | |||
329 | u8 lun, u8 *status, int len, int *actlen) | 364 | u8 lun, u8 *status, int len, int *actlen) |
330 | { | 365 | { |
331 | int retval; | 366 | int retval; |
332 | u8 cmnd[12] = {0}; | 367 | u8 cmnd[12] = { 0 }; |
333 | 368 | ||
334 | US_DEBUGP("%s, lun = %d\n", __func__, lun); | 369 | US_DEBUGP("%s, lun = %d\n", __func__, lun); |
335 | 370 | ||
@@ -356,12 +391,12 @@ static int rts51x_check_status(struct us_data *us, u8 lun) | |||
356 | 391 | ||
357 | US_DEBUGP("chip->status_len = %d\n", chip->status_len); | 392 | US_DEBUGP("chip->status_len = %d\n", chip->status_len); |
358 | 393 | ||
359 | chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1]; | 394 | chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1]; |
360 | chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3]; | 395 | chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3]; |
361 | chip->status[lun].cur_lun = buf[4]; | 396 | chip->status[lun].cur_lun = buf[4]; |
362 | chip->status[lun].card_type = buf[5]; | 397 | chip->status[lun].card_type = buf[5]; |
363 | chip->status[lun].total_lun = buf[6]; | 398 | chip->status[lun].total_lun = buf[6]; |
364 | chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8]; | 399 | chip->status[lun].fw_ver = ((u16) buf[7] << 8) | buf[8]; |
365 | chip->status[lun].phy_exist = buf[9]; | 400 | chip->status[lun].phy_exist = buf[9]; |
366 | chip->status[lun].multi_flag = buf[10]; | 401 | chip->status[lun].multi_flag = buf[10]; |
367 | chip->status[lun].multi_card = buf[11]; | 402 | chip->status[lun].multi_card = buf[11]; |
@@ -432,6 +467,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
432 | int retval; | 467 | int retval; |
433 | u8 value; | 468 | u8 value; |
434 | 469 | ||
470 | US_DEBUGP("%s: <---\n", __func__); | ||
471 | |||
435 | if (!CHK_AUTO_DELINK(chip)) | 472 | if (!CHK_AUTO_DELINK(chip)) |
436 | return 0; | 473 | return 0; |
437 | 474 | ||
@@ -465,7 +502,7 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
465 | CLR_BIT(value, 2); | 502 | CLR_BIT(value, 2); |
466 | 503 | ||
467 | if (CHECK_ID(chip, 0x0159, 0x5889) || | 504 | if (CHECK_ID(chip, 0x0159, 0x5889) || |
468 | CHECK_ID(chip, 0x0138, 0x3880)) { | 505 | CHECK_ID(chip, 0x0138, 0x3880)) { |
469 | CLR_BIT(value, 0); | 506 | CLR_BIT(value, 0); |
470 | CLR_BIT(value, 7); | 507 | CLR_BIT(value, 7); |
471 | } | 508 | } |
@@ -487,6 +524,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
487 | } | 524 | } |
488 | } | 525 | } |
489 | 526 | ||
527 | US_DEBUGP("%s: --->\n", __func__); | ||
528 | |||
490 | return 0; | 529 | return 0; |
491 | } | 530 | } |
492 | 531 | ||
@@ -496,6 +535,8 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
496 | int retval; | 535 | int retval; |
497 | u8 value; | 536 | u8 value; |
498 | 537 | ||
538 | US_DEBUGP("%s: <---\n", __func__); | ||
539 | |||
499 | if (!CHK_AUTO_DELINK(chip)) | 540 | if (!CHK_AUTO_DELINK(chip)) |
500 | return 0; | 541 | return 0; |
501 | 542 | ||
@@ -528,14 +569,14 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
528 | return -EIO; | 569 | return -EIO; |
529 | } else { | 570 | } else { |
530 | if (CHECK_ID(chip, 0x0159, 0x5889) || | 571 | if (CHECK_ID(chip, 0x0159, 0x5889) || |
531 | CHECK_ID(chip, 0x0138, 0x3880) || | 572 | CHECK_ID(chip, 0x0138, 0x3880) || |
532 | CHECK_ID(chip, 0x0138, 0x3882)) { | 573 | CHECK_ID(chip, 0x0138, 0x3882)) { |
533 | retval = rts51x_read_mem(us, 0xFE47, &value, 1); | 574 | retval = rts51x_read_mem(us, 0xFE47, &value, 1); |
534 | if (retval < 0) | 575 | if (retval < 0) |
535 | return -EIO; | 576 | return -EIO; |
536 | 577 | ||
537 | if (CHECK_ID(chip, 0x0159, 0x5889) || | 578 | if (CHECK_ID(chip, 0x0159, 0x5889) || |
538 | CHECK_ID(chip, 0x0138, 0x3880)) { | 579 | CHECK_ID(chip, 0x0138, 0x3880)) { |
539 | SET_BIT(value, 0); | 580 | SET_BIT(value, 0); |
540 | SET_BIT(value, 7); | 581 | SET_BIT(value, 7); |
541 | } | 582 | } |
@@ -556,25 +597,323 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
556 | } | 597 | } |
557 | } | 598 | } |
558 | 599 | ||
600 | US_DEBUGP("%s: --->\n", __func__); | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static void fw5895_init(struct us_data *us) | ||
606 | { | ||
607 | struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | ||
608 | int retval; | ||
609 | u8 val; | ||
610 | |||
611 | US_DEBUGP("%s: <---\n", __func__); | ||
612 | |||
613 | if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) { | ||
614 | US_DEBUGP("Not the specified device, return immediately!\n"); | ||
615 | } else { | ||
616 | retval = rts51x_read_mem(us, 0xFD6F, &val, 1); | ||
617 | if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) { | ||
618 | val = 0x1F; | ||
619 | retval = rts51x_write_mem(us, 0xFD70, &val, 1); | ||
620 | if (retval != STATUS_SUCCESS) | ||
621 | US_DEBUGP("Write memory fail\n"); | ||
622 | } else { | ||
623 | US_DEBUGP("Read memory fail, OR (val & 0x1F) != 0\n"); | ||
624 | } | ||
625 | } | ||
626 | |||
627 | US_DEBUGP("%s: --->\n", __func__); | ||
628 | } | ||
629 | |||
630 | #ifdef CONFIG_REALTEK_AUTOPM | ||
631 | static void fw5895_set_mmc_wp(struct us_data *us) | ||
632 | { | ||
633 | struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | ||
634 | int retval; | ||
635 | u8 buf[13]; | ||
636 | |||
637 | US_DEBUGP("%s: <---\n", __func__); | ||
638 | |||
639 | if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) { | ||
640 | US_DEBUGP("Not the specified device, return immediately!\n"); | ||
641 | } else { | ||
642 | retval = rts51x_read_mem(us, 0xFD6F, buf, 1); | ||
643 | if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) { | ||
644 | /* SD Exist and SD WP */ | ||
645 | retval = rts51x_read_mem(us, 0xD04E, buf, 1); | ||
646 | if (retval == STATUS_SUCCESS) { | ||
647 | buf[0] |= 0x04; | ||
648 | retval = rts51x_write_mem(us, 0xFD70, buf, 1); | ||
649 | if (retval != STATUS_SUCCESS) | ||
650 | US_DEBUGP("Write memory fail\n"); | ||
651 | } else { | ||
652 | US_DEBUGP("Read memory fail\n"); | ||
653 | } | ||
654 | } else { | ||
655 | US_DEBUGP("Read memory fail, OR (buf[0]&0x24)!=0x24\n"); | ||
656 | } | ||
657 | } | ||
658 | |||
659 | US_DEBUGP("%s: --->\n", __func__); | ||
660 | } | ||
661 | |||
662 | static void rts51x_modi_suspend_timer(struct rts51x_chip *chip) | ||
663 | { | ||
664 | US_DEBUGP("%s: <---, state:%d\n", __func__, rts51x_get_stat(chip)); | ||
665 | |||
666 | chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay); | ||
667 | mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires); | ||
668 | |||
669 | US_DEBUGP("%s: --->\n", __func__); | ||
670 | } | ||
671 | |||
672 | static void rts51x_suspend_timer_fn(unsigned long data) | ||
673 | { | ||
674 | struct rts51x_chip *chip = (struct rts51x_chip *)data; | ||
675 | struct us_data *us = chip->us; | ||
676 | |||
677 | US_DEBUGP("%s: <---\n", __func__); | ||
678 | |||
679 | switch (rts51x_get_stat(chip)) { | ||
680 | case RTS51X_STAT_INIT: | ||
681 | case RTS51X_STAT_RUN: | ||
682 | rts51x_modi_suspend_timer(chip); | ||
683 | break; | ||
684 | case RTS51X_STAT_IDLE: | ||
685 | case RTS51X_STAT_SS: | ||
686 | US_DEBUGP("%s: RTS51X_STAT_SS, intf->pm_usage_cnt:%d," | ||
687 | "power.usage:%d\n", __func__, | ||
688 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
689 | atomic_read(&us->pusb_intf->dev.power.usage_count)); | ||
690 | |||
691 | if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) { | ||
692 | US_DEBUGP("%s: Ready to enter SS state.\n", | ||
693 | __func__); | ||
694 | rts51x_set_stat(chip, RTS51X_STAT_SS); | ||
695 | /* ignore mass storage interface's children */ | ||
696 | pm_suspend_ignore_children(&us->pusb_intf->dev, true); | ||
697 | usb_autopm_put_interface(us->pusb_intf); | ||
698 | US_DEBUGP("%s: RTS51X_STAT_SS 01," | ||
699 | "intf->pm_usage_cnt:%d, power.usage:%d\n", | ||
700 | __func__, | ||
701 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
702 | atomic_read( | ||
703 | &us->pusb_intf->dev.power.usage_count)); | ||
704 | } | ||
705 | break; | ||
706 | default: | ||
707 | US_DEBUGP("%s: Unknonwn state !!!\n", __func__); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | US_DEBUGP("%s: --->\n", __func__); | ||
712 | } | ||
713 | |||
714 | static inline int working_scsi(struct scsi_cmnd *srb) | ||
715 | { | ||
716 | if ((srb->cmnd[0] == TEST_UNIT_READY) || | ||
717 | (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL)) { | ||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
725 | { | ||
726 | struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | ||
727 | static int card_first_show = 1; | ||
728 | static u8 media_not_present[] = { 0x70, 0, 0x02, 0, 0, 0, 0, | ||
729 | 10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0 | ||
730 | }; | ||
731 | static u8 invalid_cmd_field[] = { 0x70, 0, 0x05, 0, 0, 0, 0, | ||
732 | 10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0 | ||
733 | }; | ||
734 | int ret; | ||
735 | |||
736 | US_DEBUGP("%s: <---\n", __func__); | ||
737 | |||
738 | if (working_scsi(srb)) { | ||
739 | US_DEBUGP("%s: working scsi, intf->pm_usage_cnt:%d," | ||
740 | "power.usage:%d\n", __func__, | ||
741 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
742 | atomic_read(&us->pusb_intf->dev.power.usage_count)); | ||
743 | |||
744 | if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) { | ||
745 | ret = usb_autopm_get_interface(us->pusb_intf); | ||
746 | US_DEBUGP("%s: working scsi, ret=%d\n", __func__, ret); | ||
747 | } | ||
748 | if (rts51x_get_stat(chip) != RTS51X_STAT_RUN) | ||
749 | rts51x_set_stat(chip, RTS51X_STAT_RUN); | ||
750 | chip->proto_handler_backup(srb, us); | ||
751 | } else { | ||
752 | if (rts51x_get_stat(chip) == RTS51X_STAT_SS) { | ||
753 | US_DEBUGP("%s: NOT working scsi\n", __func__); | ||
754 | if ((srb->cmnd[0] == TEST_UNIT_READY) && | ||
755 | (chip->pwr_state == US_SUSPEND)) { | ||
756 | if (TST_LUN_READY(chip, srb->device->lun)) { | ||
757 | srb->result = SAM_STAT_GOOD; | ||
758 | } else { | ||
759 | srb->result = SAM_STAT_CHECK_CONDITION; | ||
760 | memcpy(srb->sense_buffer, | ||
761 | media_not_present, | ||
762 | US_SENSE_SIZE); | ||
763 | } | ||
764 | US_DEBUGP("%s: TEST_UNIT_READY--->\n", | ||
765 | __func__); | ||
766 | goto out; | ||
767 | } | ||
768 | if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { | ||
769 | int prevent = srb->cmnd[4] & 0x1; | ||
770 | if (prevent) { | ||
771 | srb->result = SAM_STAT_CHECK_CONDITION; | ||
772 | memcpy(srb->sense_buffer, | ||
773 | invalid_cmd_field, | ||
774 | US_SENSE_SIZE); | ||
775 | } else { | ||
776 | srb->result = SAM_STAT_GOOD; | ||
777 | } | ||
778 | US_DEBUGP("%s: ALLOW_MEDIUM_REMOVAL--->\n", | ||
779 | __func__); | ||
780 | goto out; | ||
781 | } | ||
782 | } else { | ||
783 | US_DEBUGP("%s: NOT working scsi, not SS\n", __func__); | ||
784 | chip->proto_handler_backup(srb, us); | ||
785 | /* Check wether card is plugged in */ | ||
786 | if (srb->cmnd[0] == TEST_UNIT_READY) { | ||
787 | if (srb->result == SAM_STAT_GOOD) { | ||
788 | SET_LUN_READY(chip, srb->device->lun); | ||
789 | if (card_first_show) { | ||
790 | card_first_show = 0; | ||
791 | fw5895_set_mmc_wp(us); | ||
792 | } | ||
793 | } else { | ||
794 | CLR_LUN_READY(chip, srb->device->lun); | ||
795 | card_first_show = 1; | ||
796 | } | ||
797 | } | ||
798 | if (rts51x_get_stat(chip) != RTS51X_STAT_IDLE) | ||
799 | rts51x_set_stat(chip, RTS51X_STAT_IDLE); | ||
800 | } | ||
801 | } | ||
802 | out: | ||
803 | US_DEBUGP("%s: state:%d\n", __func__, rts51x_get_stat(chip)); | ||
804 | if (rts51x_get_stat(chip) == RTS51X_STAT_RUN) | ||
805 | rts51x_modi_suspend_timer(chip); | ||
806 | |||
807 | US_DEBUGP("%s: --->\n", __func__); | ||
808 | } | ||
809 | |||
810 | static int realtek_cr_autosuspend_setup(struct us_data *us) | ||
811 | { | ||
812 | struct rts51x_chip *chip; | ||
813 | struct rts51x_status *status = NULL; | ||
814 | u8 buf[16]; | ||
815 | int retval; | ||
816 | |||
817 | chip = (struct rts51x_chip *)us->extra; | ||
818 | chip->support_auto_delink = 0; | ||
819 | chip->pwr_state = US_RESUME; | ||
820 | chip->lun_ready = 0; | ||
821 | rts51x_set_stat(chip, RTS51X_STAT_INIT); | ||
822 | |||
823 | retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len)); | ||
824 | if (retval != STATUS_SUCCESS) { | ||
825 | US_DEBUGP("Read status fail\n"); | ||
826 | return -EIO; | ||
827 | } | ||
828 | status = chip->status; | ||
829 | status->vid = ((u16) buf[0] << 8) | buf[1]; | ||
830 | status->pid = ((u16) buf[2] << 8) | buf[3]; | ||
831 | status->cur_lun = buf[4]; | ||
832 | status->card_type = buf[5]; | ||
833 | status->total_lun = buf[6]; | ||
834 | status->fw_ver = ((u16) buf[7] << 8) | buf[8]; | ||
835 | status->phy_exist = buf[9]; | ||
836 | status->multi_flag = buf[10]; | ||
837 | status->multi_card = buf[11]; | ||
838 | status->log_exist = buf[12]; | ||
839 | if (chip->status_len == 16) { | ||
840 | status->detailed_type.detailed_type1 = buf[13]; | ||
841 | status->function[0] = buf[14]; | ||
842 | status->function[1] = buf[15]; | ||
843 | } | ||
844 | |||
845 | /* back up the proto_handler in us->extra */ | ||
846 | chip = (struct rts51x_chip *)(us->extra); | ||
847 | chip->proto_handler_backup = us->proto_handler; | ||
848 | /* Set the autosuspend_delay to 0 */ | ||
849 | pm_runtime_set_autosuspend_delay(&us->pusb_dev->dev, 0); | ||
850 | /* override us->proto_handler setted in get_protocol() */ | ||
851 | us->proto_handler = rts51x_invoke_transport; | ||
852 | |||
853 | chip->timer_expires = 0; | ||
854 | setup_timer(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, | ||
855 | (unsigned long)chip); | ||
856 | fw5895_init(us); | ||
857 | |||
858 | /* enable autosuspend funciton of the usb device */ | ||
859 | usb_enable_autosuspend(us->pusb_dev); | ||
860 | |||
559 | return 0; | 861 | return 0; |
560 | } | 862 | } |
863 | #endif | ||
561 | 864 | ||
562 | static void realtek_cr_destructor(void *extra) | 865 | static void realtek_cr_destructor(void *extra) |
563 | { | 866 | { |
564 | struct rts51x_chip *chip = (struct rts51x_chip *)extra; | 867 | struct rts51x_chip *chip = (struct rts51x_chip *)extra; |
565 | 868 | ||
869 | US_DEBUGP("%s: <---\n", __func__); | ||
870 | |||
566 | if (!chip) | 871 | if (!chip) |
567 | return; | 872 | return; |
568 | 873 | #ifdef CONFIG_REALTEK_AUTOPM | |
874 | if (ss_en) { | ||
875 | del_timer(&chip->rts51x_suspend_timer); | ||
876 | chip->timer_expires = 0; | ||
877 | } | ||
878 | #endif | ||
569 | kfree(chip->status); | 879 | kfree(chip->status); |
570 | } | 880 | } |
571 | 881 | ||
572 | #ifdef CONFIG_PM | 882 | #ifdef CONFIG_PM |
573 | static void realtek_pm_hook(struct us_data *us, int pm_state) | 883 | int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message) |
884 | { | ||
885 | struct us_data *us = usb_get_intfdata(iface); | ||
886 | |||
887 | US_DEBUGP("%s: <---\n", __func__); | ||
888 | |||
889 | /* wait until no command is running */ | ||
890 | mutex_lock(&us->dev_mutex); | ||
891 | |||
892 | config_autodelink_before_power_down(us); | ||
893 | |||
894 | mutex_unlock(&us->dev_mutex); | ||
895 | |||
896 | US_DEBUGP("%s: --->\n", __func__); | ||
897 | |||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static int realtek_cr_resume(struct usb_interface *iface) | ||
574 | { | 902 | { |
575 | if (pm_state == US_SUSPEND) | 903 | struct us_data *us = usb_get_intfdata(iface); |
576 | (void)config_autodelink_before_power_down(us); | 904 | |
905 | US_DEBUGP("%s: <---\n", __func__); | ||
906 | |||
907 | fw5895_init(us); | ||
908 | config_autodelink_after_power_on(us); | ||
909 | |||
910 | US_DEBUGP("%s: --->\n", __func__); | ||
911 | |||
912 | return 0; | ||
577 | } | 913 | } |
914 | #else | ||
915 | #define realtek_cr_suspend NULL | ||
916 | #define realtek_cr_resume NULL | ||
578 | #endif | 917 | #endif |
579 | 918 | ||
580 | static int init_realtek_cr(struct us_data *us) | 919 | static int init_realtek_cr(struct us_data *us) |
@@ -588,10 +927,6 @@ static int init_realtek_cr(struct us_data *us) | |||
588 | 927 | ||
589 | us->extra = chip; | 928 | us->extra = chip; |
590 | us->extra_destructor = realtek_cr_destructor; | 929 | us->extra_destructor = realtek_cr_destructor; |
591 | #ifdef CONFIG_PM | ||
592 | us->suspend_resume_hook = realtek_pm_hook; | ||
593 | #endif | ||
594 | |||
595 | us->max_lun = chip->max_lun = rts51x_get_max_lun(us); | 930 | us->max_lun = chip->max_lun = rts51x_get_max_lun(us); |
596 | 931 | ||
597 | US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); | 932 | US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); |
@@ -602,18 +937,24 @@ static int init_realtek_cr(struct us_data *us) | |||
602 | goto INIT_FAIL; | 937 | goto INIT_FAIL; |
603 | 938 | ||
604 | for (i = 0; i <= (int)(chip->max_lun); i++) { | 939 | for (i = 0; i <= (int)(chip->max_lun); i++) { |
605 | retval = rts51x_check_status(us, (u8)i); | 940 | retval = rts51x_check_status(us, (u8) i); |
606 | if (retval < 0) | 941 | if (retval < 0) |
607 | goto INIT_FAIL; | 942 | goto INIT_FAIL; |
608 | } | 943 | } |
609 | 944 | ||
610 | if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || | 945 | if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || |
611 | CHECK_FW_VER(chip, 0x5901)) | 946 | CHECK_FW_VER(chip, 0x5901)) |
612 | SET_AUTO_DELINK(chip); | 947 | SET_AUTO_DELINK(chip); |
613 | if (STATUS_LEN(chip) == 16) { | 948 | if (STATUS_LEN(chip) == 16) { |
614 | if (SUPPORT_AUTO_DELINK(chip)) | 949 | if (SUPPORT_AUTO_DELINK(chip)) |
615 | SET_AUTO_DELINK(chip); | 950 | SET_AUTO_DELINK(chip); |
616 | } | 951 | } |
952 | #ifdef CONFIG_REALTEK_AUTOPM | ||
953 | if (ss_en) { | ||
954 | chip->us = us; | ||
955 | realtek_cr_autosuspend_setup(us); | ||
956 | } | ||
957 | #endif | ||
617 | 958 | ||
618 | US_DEBUGP("chip->flag = 0x%x\n", chip->flag); | 959 | US_DEBUGP("chip->flag = 0x%x\n", chip->flag); |
619 | 960 | ||
@@ -632,7 +973,7 @@ INIT_FAIL: | |||
632 | } | 973 | } |
633 | 974 | ||
634 | static int realtek_cr_probe(struct usb_interface *intf, | 975 | static int realtek_cr_probe(struct usb_interface *intf, |
635 | const struct usb_device_id *id) | 976 | const struct usb_device_id *id) |
636 | { | 977 | { |
637 | struct us_data *us; | 978 | struct us_data *us; |
638 | int result; | 979 | int result; |
@@ -640,25 +981,30 @@ static int realtek_cr_probe(struct usb_interface *intf, | |||
640 | US_DEBUGP("Probe Realtek Card Reader!\n"); | 981 | US_DEBUGP("Probe Realtek Card Reader!\n"); |
641 | 982 | ||
642 | result = usb_stor_probe1(&us, intf, id, | 983 | result = usb_stor_probe1(&us, intf, id, |
643 | (id - realtek_cr_ids) + realtek_cr_unusual_dev_list); | 984 | (id - realtek_cr_ids) + |
985 | realtek_cr_unusual_dev_list); | ||
644 | if (result) | 986 | if (result) |
645 | return result; | 987 | return result; |
646 | 988 | ||
647 | result = usb_stor_probe2(us); | 989 | result = usb_stor_probe2(us); |
990 | |||
648 | return result; | 991 | return result; |
649 | } | 992 | } |
650 | 993 | ||
651 | static struct usb_driver realtek_cr_driver = { | 994 | static struct usb_driver realtek_cr_driver = { |
652 | .name = "ums-realtek", | 995 | .name = "ums-realtek", |
653 | .probe = realtek_cr_probe, | 996 | .probe = realtek_cr_probe, |
654 | .disconnect = usb_stor_disconnect, | 997 | .disconnect = usb_stor_disconnect, |
655 | .suspend = usb_stor_suspend, | 998 | /* .suspend = usb_stor_suspend, */ |
656 | .resume = usb_stor_resume, | 999 | /* .resume = usb_stor_resume, */ |
657 | .reset_resume = usb_stor_reset_resume, | 1000 | .reset_resume = usb_stor_reset_resume, |
658 | .pre_reset = usb_stor_pre_reset, | 1001 | .suspend = realtek_cr_suspend, |
659 | .post_reset = usb_stor_post_reset, | 1002 | .resume = realtek_cr_resume, |
660 | .id_table = realtek_cr_ids, | 1003 | .pre_reset = usb_stor_pre_reset, |
661 | .soft_unbind = 1, | 1004 | .post_reset = usb_stor_post_reset, |
1005 | .id_table = realtek_cr_ids, | ||
1006 | .soft_unbind = 1, | ||
1007 | .supports_autosuspend = 1, | ||
662 | }; | 1008 | }; |
663 | 1009 | ||
664 | static int __init realtek_cr_init(void) | 1010 | static int __init realtek_cr_init(void) |