tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / memstick / host / rtsx_pci_ms.c
1 /* Realtek PCI-Express Memstick Card Interface driver
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
23 #include <linux/module.h>
24 #include <linux/highmem.h>
25 #include <linux/delay.h>
26 #include <linux/platform_device.h>
27 #include <linux/memstick.h>
28 #include <linux/mfd/rtsx_pci.h>
29 #include <asm/unaligned.h>
30
31 struct realtek_pci_ms {
32         struct platform_device  *pdev;
33         struct rtsx_pcr         *pcr;
34         struct memstick_host    *msh;
35         struct memstick_request *req;
36
37         struct mutex            host_mutex;
38         struct work_struct      handle_req;
39
40         u8                      ssc_depth;
41         unsigned int            clock;
42         unsigned char           ifmode;
43         bool                    eject;
44 };
45
46 static inline struct device *ms_dev(struct realtek_pci_ms *host)
47 {
48         return &(host->pdev->dev);
49 }
50
51 static inline void ms_clear_error(struct realtek_pci_ms *host)
52 {
53         rtsx_pci_write_register(host->pcr, CARD_STOP,
54                         MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
55 }
56
57 #ifdef DEBUG
58
59 static void ms_print_debug_regs(struct realtek_pci_ms *host)
60 {
61         struct rtsx_pcr *pcr = host->pcr;
62         u16 i;
63         u8 *ptr;
64
65         /* Print MS host internal registers */
66         rtsx_pci_init_cmd(pcr);
67         for (i = 0xFD40; i <= 0xFD44; i++)
68                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
69         for (i = 0xFD52; i <= 0xFD69; i++)
70                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
71         rtsx_pci_send_cmd(pcr, 100);
72
73         ptr = rtsx_pci_get_cmd_data(pcr);
74         for (i = 0xFD40; i <= 0xFD44; i++)
75                 dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
76         for (i = 0xFD52; i <= 0xFD69; i++)
77                 dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
78 }
79
80 #else
81
82 #define ms_print_debug_regs(host)
83
84 #endif
85
86 static int ms_power_on(struct realtek_pci_ms *host)
87 {
88         struct rtsx_pcr *pcr = host->pcr;
89         int err;
90
91         rtsx_pci_init_cmd(pcr);
92         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
93         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
94                         CARD_SHARE_MASK, CARD_SHARE_48_MS);
95         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
96                         MS_CLK_EN, MS_CLK_EN);
97         err = rtsx_pci_send_cmd(pcr, 100);
98         if (err < 0)
99                 return err;
100
101         err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
102         if (err < 0)
103                 return err;
104
105         err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
106         if (err < 0)
107                 return err;
108
109         /* Wait ms power stable */
110         msleep(150);
111
112         err = rtsx_pci_write_register(pcr, CARD_OE,
113                         MS_OUTPUT_EN, MS_OUTPUT_EN);
114         if (err < 0)
115                 return err;
116
117         return 0;
118 }
119
120 static int ms_power_off(struct realtek_pci_ms *host)
121 {
122         struct rtsx_pcr *pcr = host->pcr;
123         int err;
124
125         rtsx_pci_init_cmd(pcr);
126
127         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
128         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
129
130         err = rtsx_pci_send_cmd(pcr, 100);
131         if (err < 0)
132                 return err;
133
134         err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
135         if (err < 0)
136                 return err;
137
138         return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
139 }
140
141 static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
142                 u8 tpc, u8 cfg, struct scatterlist *sg)
143 {
144         struct rtsx_pcr *pcr = host->pcr;
145         int err;
146         unsigned int length = sg->length;
147         u16 sec_cnt = (u16)(length / 512);
148         u8 val, trans_mode, dma_dir;
149
150         dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
151                         __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
152                         length);
153
154         if (data_dir == READ) {
155                 dma_dir = DMA_DIR_FROM_CARD;
156                 trans_mode = MS_TM_AUTO_READ;
157         } else {
158                 dma_dir = DMA_DIR_TO_CARD;
159                 trans_mode = MS_TM_AUTO_WRITE;
160         }
161
162         rtsx_pci_init_cmd(pcr);
163
164         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
165         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
166                         0xFF, (u8)(sec_cnt >> 8));
167         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
168                         0xFF, (u8)sec_cnt);
169         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
170
171         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
172                         DMA_DONE_INT, DMA_DONE_INT);
173         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
174         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
175         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
176         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
177         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
178                         0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
179         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
180                         0x01, RING_BUFFER);
181
182         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
183                         0xFF, MS_TRANSFER_START | trans_mode);
184         rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
185                         MS_TRANSFER_END, MS_TRANSFER_END);
186
187         rtsx_pci_send_cmd_no_wait(pcr);
188
189         err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
190         if (err < 0) {
191                 ms_clear_error(host);
192                 return err;
193         }
194
195         rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
196         if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
197                 return -EIO;
198
199         return 0;
200 }
201
202 static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
203                 u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
204 {
205         struct rtsx_pcr *pcr = host->pcr;
206         int err, i;
207
208         dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
209
210         if (!data)
211                 return -EINVAL;
212
213         rtsx_pci_init_cmd(pcr);
214
215         for (i = 0; i < cnt; i++)
216                 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
217                                 PPBUF_BASE2 + i, 0xFF, data[i]);
218         if (cnt % 2)
219                 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
220                                 PPBUF_BASE2 + i, 0xFF, 0xFF);
221
222         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
223         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
224         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
225         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
226                         0x01, PINGPONG_BUFFER);
227
228         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
229                         0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
230         rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
231                         MS_TRANSFER_END, MS_TRANSFER_END);
232         if (int_reg)
233                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
234
235         err = rtsx_pci_send_cmd(pcr, 5000);
236         if (err < 0) {
237                 u8 val;
238
239                 rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
240                 dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
241
242                 if (int_reg)
243                         *int_reg = val & 0x0F;
244
245                 ms_print_debug_regs(host);
246
247                 ms_clear_error(host);
248
249                 if (!(tpc & 0x08)) {
250                         if (val & MS_CRC16_ERR)
251                                 return -EIO;
252                 } else {
253                         if (!(val & 0x80)) {
254                                 if (val & (MS_INT_ERR | MS_INT_CMDNK))
255                                         return -EIO;
256                         }
257                 }
258
259                 return -ETIMEDOUT;
260         }
261
262         if (int_reg) {
263                 u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
264                 *int_reg = *ptr & 0x0F;
265         }
266
267         return 0;
268 }
269
270 static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
271                 u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
272 {
273         struct rtsx_pcr *pcr = host->pcr;
274         int err, i;
275         u8 *ptr;
276
277         dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
278
279         if (!data)
280                 return -EINVAL;
281
282         rtsx_pci_init_cmd(pcr);
283
284         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
285         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
286         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
287         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
288                         0x01, PINGPONG_BUFFER);
289
290         rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
291                         0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
292         rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
293                         MS_TRANSFER_END, MS_TRANSFER_END);
294         for (i = 0; i < cnt - 1; i++)
295                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
296         if (cnt % 2)
297                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
298         else
299                 rtsx_pci_add_cmd(pcr, READ_REG_CMD,
300                                 PPBUF_BASE2 + cnt - 1, 0, 0);
301         if (int_reg)
302                 rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
303
304         err = rtsx_pci_send_cmd(pcr, 5000);
305         if (err < 0) {
306                 u8 val;
307
308                 rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
309                 dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
310
311                 if (int_reg)
312                         *int_reg = val & 0x0F;
313
314                 ms_print_debug_regs(host);
315
316                 ms_clear_error(host);
317
318                 if (!(tpc & 0x08)) {
319                         if (val & MS_CRC16_ERR)
320                                 return -EIO;
321                 } else {
322                         if (!(val & 0x80)) {
323                                 if (val & (MS_INT_ERR | MS_INT_CMDNK))
324                                         return -EIO;
325                         }
326                 }
327
328                 return -ETIMEDOUT;
329         }
330
331         ptr = rtsx_pci_get_cmd_data(pcr) + 1;
332         for (i = 0; i < cnt; i++)
333                 data[i] = *ptr++;
334
335         if (int_reg)
336                 *int_reg = *ptr & 0x0F;
337
338         return 0;
339 }
340
341 static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
342 {
343         struct memstick_request *req = host->req;
344         int err = 0;
345         u8 cfg = 0, int_reg;
346
347         dev_dbg(ms_dev(host), "%s\n", __func__);
348
349         if (req->need_card_int) {
350                 if (host->ifmode != MEMSTICK_SERIAL)
351                         cfg = WAIT_INT;
352         }
353
354         if (req->long_data) {
355                 err = ms_transfer_data(host, req->data_dir,
356                                 req->tpc, cfg, &(req->sg));
357         } else {
358                 if (req->data_dir == READ) {
359                         err = ms_read_bytes(host, req->tpc, cfg,
360                                         req->data_len, req->data, &int_reg);
361                 } else {
362                         err = ms_write_bytes(host, req->tpc, cfg,
363                                         req->data_len, req->data, &int_reg);
364                 }
365         }
366         if (err < 0)
367                 return err;
368
369         if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
370                 err = ms_read_bytes(host, MS_TPC_GET_INT,
371                                 NO_WAIT_INT, 1, &int_reg, NULL);
372                 if (err < 0)
373                         return err;
374         }
375
376         if (req->need_card_int) {
377                 dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
378
379                 if (int_reg & MS_INT_CMDNK)
380                         req->int_reg |= MEMSTICK_INT_CMDNAK;
381                 if (int_reg & MS_INT_BREQ)
382                         req->int_reg |= MEMSTICK_INT_BREQ;
383                 if (int_reg & MS_INT_ERR)
384                         req->int_reg |= MEMSTICK_INT_ERR;
385                 if (int_reg & MS_INT_CED)
386                         req->int_reg |= MEMSTICK_INT_CED;
387         }
388
389         return 0;
390 }
391
392 static void rtsx_pci_ms_handle_req(struct work_struct *work)
393 {
394         struct realtek_pci_ms *host = container_of(work,
395                         struct realtek_pci_ms, handle_req);
396         struct rtsx_pcr *pcr = host->pcr;
397         struct memstick_host *msh = host->msh;
398         int rc;
399
400         mutex_lock(&pcr->pcr_mutex);
401
402         rtsx_pci_start_run(pcr);
403
404         rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
405                         false, true, false);
406         rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
407         rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
408                         CARD_SHARE_MASK, CARD_SHARE_48_MS);
409
410         if (!host->req) {
411                 do {
412                         rc = memstick_next_req(msh, &host->req);
413                         dev_dbg(ms_dev(host), "next req %d\n", rc);
414
415                         if (!rc)
416                                 host->req->error = rtsx_pci_ms_issue_cmd(host);
417                 } while (!rc);
418         }
419
420         mutex_unlock(&pcr->pcr_mutex);
421 }
422
423 static void rtsx_pci_ms_request(struct memstick_host *msh)
424 {
425         struct realtek_pci_ms *host = memstick_priv(msh);
426
427         dev_dbg(ms_dev(host), "--> %s\n", __func__);
428
429         if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD))
430                 return;
431
432         schedule_work(&host->handle_req);
433 }
434
435 static int rtsx_pci_ms_set_param(struct memstick_host *msh,
436                 enum memstick_param param, int value)
437 {
438         struct realtek_pci_ms *host = memstick_priv(msh);
439         struct rtsx_pcr *pcr = host->pcr;
440         unsigned int clock = 0;
441         u8 ssc_depth = 0;
442         int err;
443
444         dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
445                         __func__, param, value);
446
447         err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD);
448         if (err)
449                 return err;
450
451         switch (param) {
452         case MEMSTICK_POWER:
453                 if (value == MEMSTICK_POWER_ON)
454                         err = ms_power_on(host);
455                 else if (value == MEMSTICK_POWER_OFF)
456                         err = ms_power_off(host);
457                 else
458                         return -EINVAL;
459                 break;
460
461         case MEMSTICK_INTERFACE:
462                 if (value == MEMSTICK_SERIAL) {
463                         clock = 19000000;
464                         ssc_depth = RTSX_SSC_DEPTH_500K;
465
466                         err = rtsx_pci_write_register(pcr, MS_CFG,
467                                         0x18, MS_BUS_WIDTH_1);
468                         if (err < 0)
469                                 return err;
470                 } else if (value == MEMSTICK_PAR4) {
471                         clock = 39000000;
472                         ssc_depth = RTSX_SSC_DEPTH_1M;
473
474                         err = rtsx_pci_write_register(pcr, MS_CFG,
475                                         0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
476                         if (err < 0)
477                                 return err;
478                 } else {
479                         return -EINVAL;
480                 }
481
482                 err = rtsx_pci_switch_clock(pcr, clock,
483                                 ssc_depth, false, true, false);
484                 if (err < 0)
485                         return err;
486
487                 host->ssc_depth = ssc_depth;
488                 host->clock = clock;
489                 host->ifmode = value;
490                 break;
491         }
492
493         return 0;
494 }
495
496 #ifdef CONFIG_PM
497
498 static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
499 {
500         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
501         struct memstick_host *msh = host->msh;
502
503         dev_dbg(ms_dev(host), "--> %s\n", __func__);
504
505         memstick_suspend_host(msh);
506         return 0;
507 }
508
509 static int rtsx_pci_ms_resume(struct platform_device *pdev)
510 {
511         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
512         struct memstick_host *msh = host->msh;
513
514         dev_dbg(ms_dev(host), "--> %s\n", __func__);
515
516         memstick_resume_host(msh);
517         return 0;
518 }
519
520 #else /* CONFIG_PM */
521
522 #define rtsx_pci_ms_suspend NULL
523 #define rtsx_pci_ms_resume NULL
524
525 #endif /* CONFIG_PM */
526
527 static void rtsx_pci_ms_card_event(struct platform_device *pdev)
528 {
529         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
530
531         memstick_detect_change(host->msh);
532 }
533
534 static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
535 {
536         struct memstick_host *msh;
537         struct realtek_pci_ms *host;
538         struct rtsx_pcr *pcr;
539         struct pcr_handle *handle = pdev->dev.platform_data;
540         int rc;
541
542         if (!handle)
543                 return -ENXIO;
544
545         pcr = handle->pcr;
546         if (!pcr)
547                 return -ENXIO;
548
549         dev_dbg(&(pdev->dev),
550                         ": Realtek PCI-E Memstick controller found\n");
551
552         msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
553         if (!msh)
554                 return -ENOMEM;
555
556         host = memstick_priv(msh);
557         host->pcr = pcr;
558         host->msh = msh;
559         host->pdev = pdev;
560         platform_set_drvdata(pdev, host);
561         pcr->slots[RTSX_MS_CARD].p_dev = pdev;
562         pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
563
564         mutex_init(&host->host_mutex);
565
566         INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
567         msh->request = rtsx_pci_ms_request;
568         msh->set_param = rtsx_pci_ms_set_param;
569         msh->caps = MEMSTICK_CAP_PAR4;
570
571         rc = memstick_add_host(msh);
572         if (rc) {
573                 memstick_free_host(msh);
574                 return rc;
575         }
576
577         return 0;
578 }
579
580 static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
581 {
582         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
583         struct rtsx_pcr *pcr;
584         struct memstick_host *msh;
585         int rc;
586
587         if (!host)
588                 return 0;
589
590         pcr = host->pcr;
591         pcr->slots[RTSX_MS_CARD].p_dev = NULL;
592         pcr->slots[RTSX_MS_CARD].card_event = NULL;
593         msh = host->msh;
594         host->eject = true;
595
596         mutex_lock(&host->host_mutex);
597         if (host->req) {
598                 dev_dbg(&(pdev->dev),
599                         "%s: Controller removed during transfer\n",
600                         dev_name(&msh->dev));
601
602                 rtsx_pci_complete_unfinished_transfer(pcr);
603
604                 host->req->error = -ENOMEDIUM;
605                 do {
606                         rc = memstick_next_req(msh, &host->req);
607                         if (!rc)
608                                 host->req->error = -ENOMEDIUM;
609                 } while (!rc);
610         }
611         mutex_unlock(&host->host_mutex);
612
613         memstick_remove_host(msh);
614         memstick_free_host(msh);
615
616         platform_set_drvdata(pdev, NULL);
617
618         dev_dbg(&(pdev->dev),
619                 ": Realtek PCI-E Memstick controller has been removed\n");
620
621         return 0;
622 }
623
624 static struct platform_device_id rtsx_pci_ms_ids[] = {
625         {
626                 .name = DRV_NAME_RTSX_PCI_MS,
627         }, {
628                 /* sentinel */
629         }
630 };
631 MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
632
633 static struct platform_driver rtsx_pci_ms_driver = {
634         .probe          = rtsx_pci_ms_drv_probe,
635         .remove         = rtsx_pci_ms_drv_remove,
636         .id_table       = rtsx_pci_ms_ids,
637         .suspend        = rtsx_pci_ms_suspend,
638         .resume         = rtsx_pci_ms_resume,
639         .driver         = {
640                 .owner  = THIS_MODULE,
641                 .name   = DRV_NAME_RTSX_PCI_MS,
642         },
643 };
644 module_platform_driver(rtsx_pci_ms_driver);
645
646 MODULE_LICENSE("GPL");
647 MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
648 MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");