]> Pileus Git - ~andy/linux/blob - drivers/memstick/host/rtsx_pci_ms.c
[SCSI] Merge tag 'fcoe-02-19-13' into for-linus
[~andy/linux] / 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         schedule_work(&host->handle_req);
430 }
431
432 static int rtsx_pci_ms_set_param(struct memstick_host *msh,
433                 enum memstick_param param, int value)
434 {
435         struct realtek_pci_ms *host = memstick_priv(msh);
436         struct rtsx_pcr *pcr = host->pcr;
437         unsigned int clock = 0;
438         u8 ssc_depth = 0;
439         int err;
440
441         dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
442                         __func__, param, value);
443
444         switch (param) {
445         case MEMSTICK_POWER:
446                 if (value == MEMSTICK_POWER_ON)
447                         err = ms_power_on(host);
448                 else if (value == MEMSTICK_POWER_OFF)
449                         err = ms_power_off(host);
450                 else
451                         return -EINVAL;
452                 break;
453
454         case MEMSTICK_INTERFACE:
455                 if (value == MEMSTICK_SERIAL) {
456                         clock = 19000000;
457                         ssc_depth = RTSX_SSC_DEPTH_500K;
458
459                         err = rtsx_pci_write_register(pcr, MS_CFG,
460                                         0x18, MS_BUS_WIDTH_1);
461                         if (err < 0)
462                                 return err;
463                 } else if (value == MEMSTICK_PAR4) {
464                         clock = 39000000;
465                         ssc_depth = RTSX_SSC_DEPTH_1M;
466
467                         err = rtsx_pci_write_register(pcr, MS_CFG,
468                                         0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
469                         if (err < 0)
470                                 return err;
471                 } else {
472                         return -EINVAL;
473                 }
474
475                 err = rtsx_pci_switch_clock(pcr, clock,
476                                 ssc_depth, false, true, false);
477                 if (err < 0)
478                         return err;
479
480                 host->ssc_depth = ssc_depth;
481                 host->clock = clock;
482                 host->ifmode = value;
483                 break;
484         }
485
486         return 0;
487 }
488
489 #ifdef CONFIG_PM
490
491 static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
492 {
493         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
494         struct memstick_host *msh = host->msh;
495
496         dev_dbg(ms_dev(host), "--> %s\n", __func__);
497
498         memstick_suspend_host(msh);
499         return 0;
500 }
501
502 static int rtsx_pci_ms_resume(struct platform_device *pdev)
503 {
504         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
505         struct memstick_host *msh = host->msh;
506
507         dev_dbg(ms_dev(host), "--> %s\n", __func__);
508
509         memstick_resume_host(msh);
510         return 0;
511 }
512
513 #else /* CONFIG_PM */
514
515 #define rtsx_pci_ms_suspend NULL
516 #define rtsx_pci_ms_resume NULL
517
518 #endif /* CONFIG_PM */
519
520 static void rtsx_pci_ms_card_event(struct platform_device *pdev)
521 {
522         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
523
524         memstick_detect_change(host->msh);
525 }
526
527 static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
528 {
529         struct memstick_host *msh;
530         struct realtek_pci_ms *host;
531         struct rtsx_pcr *pcr;
532         struct pcr_handle *handle = pdev->dev.platform_data;
533         int rc;
534
535         if (!handle)
536                 return -ENXIO;
537
538         pcr = handle->pcr;
539         if (!pcr)
540                 return -ENXIO;
541
542         dev_dbg(&(pdev->dev),
543                         ": Realtek PCI-E Memstick controller found\n");
544
545         msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
546         if (!msh)
547                 return -ENOMEM;
548
549         host = memstick_priv(msh);
550         host->pcr = pcr;
551         host->msh = msh;
552         host->pdev = pdev;
553         platform_set_drvdata(pdev, host);
554         pcr->slots[RTSX_MS_CARD].p_dev = pdev;
555         pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
556
557         mutex_init(&host->host_mutex);
558
559         INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
560         msh->request = rtsx_pci_ms_request;
561         msh->set_param = rtsx_pci_ms_set_param;
562         msh->caps = MEMSTICK_CAP_PAR4;
563
564         rc = memstick_add_host(msh);
565         if (rc) {
566                 memstick_free_host(msh);
567                 return rc;
568         }
569
570         return 0;
571 }
572
573 static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
574 {
575         struct realtek_pci_ms *host = platform_get_drvdata(pdev);
576         struct rtsx_pcr *pcr;
577         struct memstick_host *msh;
578         int rc;
579
580         if (!host)
581                 return 0;
582
583         pcr = host->pcr;
584         pcr->slots[RTSX_MS_CARD].p_dev = NULL;
585         pcr->slots[RTSX_MS_CARD].card_event = NULL;
586         msh = host->msh;
587         host->eject = true;
588
589         mutex_lock(&host->host_mutex);
590         if (host->req) {
591                 dev_dbg(&(pdev->dev),
592                         "%s: Controller removed during transfer\n",
593                         dev_name(&msh->dev));
594
595                 rtsx_pci_complete_unfinished_transfer(pcr);
596
597                 host->req->error = -ENOMEDIUM;
598                 do {
599                         rc = memstick_next_req(msh, &host->req);
600                         if (!rc)
601                                 host->req->error = -ENOMEDIUM;
602                 } while (!rc);
603         }
604         mutex_unlock(&host->host_mutex);
605
606         memstick_remove_host(msh);
607         memstick_free_host(msh);
608
609         platform_set_drvdata(pdev, NULL);
610
611         dev_dbg(&(pdev->dev),
612                 ": Realtek PCI-E Memstick controller has been removed\n");
613
614         return 0;
615 }
616
617 static struct platform_device_id rtsx_pci_ms_ids[] = {
618         {
619                 .name = DRV_NAME_RTSX_PCI_MS,
620         }, {
621                 /* sentinel */
622         }
623 };
624 MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
625
626 static struct platform_driver rtsx_pci_ms_driver = {
627         .probe          = rtsx_pci_ms_drv_probe,
628         .remove         = rtsx_pci_ms_drv_remove,
629         .id_table       = rtsx_pci_ms_ids,
630         .suspend        = rtsx_pci_ms_suspend,
631         .resume         = rtsx_pci_ms_resume,
632         .driver         = {
633                 .owner  = THIS_MODULE,
634                 .name   = DRV_NAME_RTSX_PCI_MS,
635         },
636 };
637 module_platform_driver(rtsx_pci_ms_driver);
638
639 MODULE_LICENSE("GPL");
640 MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
641 MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");