memstick: automatically retrieve "INT" value from command response
[sfrench/cifs-2.6.git] / drivers / memstick / host / tifm_ms.c
1 /*
2  *  TI FlashMedia driver
3  *
4  *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Special thanks to Carlos Corbacho for providing various MemoryStick cards
11  * that made this driver possible.
12  *
13  */
14
15 #include <linux/tifm.h>
16 #include <linux/memstick.h>
17 #include <linux/highmem.h>
18 #include <linux/scatterlist.h>
19 #include <linux/log2.h>
20 #include <asm/io.h>
21
22 #define DRIVER_NAME "tifm_ms"
23
24 static int no_dma;
25 module_param(no_dma, bool, 0644);
26
27 /*
28  * Some control bits of TIFM appear to conform to Sony's reference design,
29  * so I'm just assuming they all are.
30  */
31
32 #define TIFM_MS_STAT_DRQ     0x04000
33 #define TIFM_MS_STAT_MSINT   0x02000
34 #define TIFM_MS_STAT_RDY     0x01000
35 #define TIFM_MS_STAT_CRC     0x00200
36 #define TIFM_MS_STAT_TOE     0x00100
37 #define TIFM_MS_STAT_EMP     0x00020
38 #define TIFM_MS_STAT_FUL     0x00010
39 #define TIFM_MS_STAT_CED     0x00008
40 #define TIFM_MS_STAT_ERR     0x00004
41 #define TIFM_MS_STAT_BRQ     0x00002
42 #define TIFM_MS_STAT_CNK     0x00001
43
44 #define TIFM_MS_SYS_DMA      0x10000
45 #define TIFM_MS_SYS_RESET    0x08000
46 #define TIFM_MS_SYS_SRAC     0x04000
47 #define TIFM_MS_SYS_INTEN    0x02000
48 #define TIFM_MS_SYS_NOCRC    0x01000
49 #define TIFM_MS_SYS_INTCLR   0x00800
50 #define TIFM_MS_SYS_MSIEN    0x00400
51 #define TIFM_MS_SYS_FCLR     0x00200
52 #define TIFM_MS_SYS_FDIR     0x00100
53 #define TIFM_MS_SYS_DAM      0x00080
54 #define TIFM_MS_SYS_DRM      0x00040
55 #define TIFM_MS_SYS_DRQSL    0x00020
56 #define TIFM_MS_SYS_REI      0x00010
57 #define TIFM_MS_SYS_REO      0x00008
58 #define TIFM_MS_SYS_BSY_MASK 0x00007
59
60 #define TIFM_MS_SYS_FIFO     (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \
61                               | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK)
62
63 /* Hardware flags */
64 enum {
65         CMD_READY  = 0x01,
66         FIFO_READY = 0x02,
67         CARD_INT   = 0x04
68 };
69
70 struct tifm_ms {
71         struct tifm_dev         *dev;
72         struct timer_list       timer;
73         struct memstick_request *req;
74         unsigned int            mode_mask;
75         unsigned int            block_pos;
76         unsigned long           timeout_jiffies;
77         unsigned char           eject:1,
78                                 use_dma:1;
79         unsigned char           cmd_flags;
80         unsigned char           io_pos;
81         unsigned int            io_word;
82 };
83
84 static unsigned int tifm_ms_read_data(struct tifm_ms *host,
85                                       unsigned char *buf, unsigned int length)
86 {
87         struct tifm_dev *sock = host->dev;
88         unsigned int off = 0;
89
90         while (host->io_pos && length) {
91                 buf[off++] = host->io_word & 0xff;
92                 host->io_word >>= 8;
93                 length--;
94                 host->io_pos--;
95         }
96
97         if (!length)
98                 return off;
99
100         while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
101                 if (length < 4)
102                         break;
103                 *(unsigned int *)(buf + off) = __raw_readl(sock->addr
104                                                            + SOCK_MS_DATA);
105                 length -= 4;
106                 off += 4;
107         }
108
109         if (length
110             && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
111                 host->io_word = readl(sock->addr + SOCK_MS_DATA);
112                 for (host->io_pos = 4; host->io_pos; --host->io_pos) {
113                         buf[off++] = host->io_word & 0xff;
114                         host->io_word >>= 8;
115                         length--;
116                         if (!length)
117                                 break;
118                 }
119         }
120
121         return off;
122 }
123
124 static unsigned int tifm_ms_write_data(struct tifm_ms *host,
125                                        unsigned char *buf, unsigned int length)
126 {
127         struct tifm_dev *sock = host->dev;
128         unsigned int off = 0;
129
130         if (host->io_pos) {
131                 while (host->io_pos < 4 && length) {
132                         host->io_word |=  buf[off++] << (host->io_pos * 8);
133                         host->io_pos++;
134                         length--;
135                 }
136         }
137
138         if (host->io_pos == 4
139             && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
140                 writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
141                        sock->addr + SOCK_MS_SYSTEM);
142                 writel(host->io_word, sock->addr + SOCK_MS_DATA);
143                 host->io_pos = 0;
144                 host->io_word = 0;
145         } else if (host->io_pos) {
146                 return off;
147         }
148
149         if (!length)
150                 return off;
151
152         while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
153                 if (length < 4)
154                         break;
155                 writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
156                        sock->addr + SOCK_MS_SYSTEM);
157                 __raw_writel(*(unsigned int *)(buf + off),
158                              sock->addr + SOCK_MS_DATA);
159                 length -= 4;
160                 off += 4;
161         }
162
163         switch (length) {
164         case 3:
165                 host->io_word |= buf[off + 2] << 16;
166                 host->io_pos++;
167         case 2:
168                 host->io_word |= buf[off + 1] << 8;
169                 host->io_pos++;
170         case 1:
171                 host->io_word |= buf[off];
172                 host->io_pos++;
173         }
174
175         off += host->io_pos;
176
177         return off;
178 }
179
180 static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
181 {
182         struct tifm_dev *sock = host->dev;
183         unsigned int length;
184         unsigned int off;
185         unsigned int t_size, p_off, p_cnt;
186         unsigned char *buf;
187         struct page *pg;
188         unsigned long flags = 0;
189
190         if (host->req->long_data) {
191                 length = host->req->sg.length - host->block_pos;
192                 off = host->req->sg.offset + host->block_pos;
193         } else {
194                 length = host->req->data_len - host->block_pos;
195                 off = 0;
196         }
197         dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length,
198                 host->block_pos);
199
200         while (length) {
201                 if (host->req->long_data) {
202                         pg = nth_page(sg_page(&host->req->sg),
203                                       off >> PAGE_SHIFT);
204                         p_off = offset_in_page(off);
205                         p_cnt = PAGE_SIZE - p_off;
206                         p_cnt = min(p_cnt, length);
207
208                         local_irq_save(flags);
209                         buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
210                 } else {
211                         buf = host->req->data + host->block_pos;
212                         p_cnt = host->req->data_len - host->block_pos;
213                 }
214
215                 t_size = host->req->data_dir == WRITE
216                          ? tifm_ms_write_data(host, buf, p_cnt)
217                          : tifm_ms_read_data(host, buf, p_cnt);
218
219                 if (host->req->long_data) {
220                         kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
221                         local_irq_restore(flags);
222                 }
223
224                 if (!t_size)
225                         break;
226                 host->block_pos += t_size;
227                 length -= t_size;
228                 off += t_size;
229         }
230
231         dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length);
232         if (!length && (host->req->data_dir == WRITE)) {
233                 if (host->io_pos) {
234                         writel(TIFM_MS_SYS_FDIR
235                                | readl(sock->addr + SOCK_MS_SYSTEM),
236                                sock->addr + SOCK_MS_SYSTEM);
237                         writel(host->io_word, sock->addr + SOCK_MS_DATA);
238                 }
239                 writel(TIFM_MS_SYS_FDIR
240                        | readl(sock->addr + SOCK_MS_SYSTEM),
241                        sock->addr + SOCK_MS_SYSTEM);
242                 writel(0, sock->addr + SOCK_MS_DATA);
243         } else {
244                 readl(sock->addr + SOCK_MS_DATA);
245         }
246
247         return length;
248 }
249
250 static int tifm_ms_issue_cmd(struct tifm_ms *host)
251 {
252         struct tifm_dev *sock = host->dev;
253         unsigned char *data;
254         unsigned int data_len, cmd, sys_param;
255
256         host->cmd_flags = 0;
257         host->block_pos = 0;
258         host->io_pos = 0;
259         host->io_word = 0;
260         host->cmd_flags = 0;
261
262         data = host->req->data;
263
264         host->use_dma = !no_dma;
265
266         if (host->req->long_data) {
267                 data_len = host->req->sg.length;
268                 if (!is_power_of_2(data_len))
269                         host->use_dma = 0;
270         } else {
271                 data_len = host->req->data_len;
272                 host->use_dma = 0;
273         }
274
275         writel(TIFM_FIFO_INT_SETALL,
276                sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
277         writel(TIFM_FIFO_ENABLE,
278                sock->addr + SOCK_FIFO_CONTROL);
279
280         if (host->use_dma) {
281                 if (1 != tifm_map_sg(sock, &host->req->sg, 1,
282                                      host->req->data_dir == READ
283                                      ? PCI_DMA_FROMDEVICE
284                                      : PCI_DMA_TODEVICE)) {
285                         host->req->error = -ENOMEM;
286                         return host->req->error;
287                 }
288                 data_len = sg_dma_len(&host->req->sg);
289
290                 writel(ilog2(data_len) - 2,
291                        sock->addr + SOCK_FIFO_PAGE_SIZE);
292                 writel(TIFM_FIFO_INTMASK,
293                        sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
294                 sys_param = TIFM_DMA_EN | (1 << 8);
295                 if (host->req->data_dir == WRITE)
296                         sys_param |= TIFM_DMA_TX;
297
298                 writel(TIFM_FIFO_INTMASK,
299                        sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
300
301                 writel(sg_dma_address(&host->req->sg),
302                        sock->addr + SOCK_DMA_ADDRESS);
303                 writel(sys_param, sock->addr + SOCK_DMA_CONTROL);
304         } else {
305                 writel(host->mode_mask | TIFM_MS_SYS_FIFO,
306                        sock->addr + SOCK_MS_SYSTEM);
307
308                 writel(TIFM_FIFO_MORE,
309                        sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
310         }
311
312         mod_timer(&host->timer, jiffies + host->timeout_jiffies);
313         writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
314                sock->addr + SOCK_CONTROL);
315         host->req->error = 0;
316
317         sys_param = readl(sock->addr + SOCK_MS_SYSTEM);
318         sys_param |= TIFM_MS_SYS_INTCLR;
319
320         if (host->use_dma)
321                 sys_param |= TIFM_MS_SYS_DMA;
322         else
323                 sys_param &= ~TIFM_MS_SYS_DMA;
324
325         writel(sys_param, sock->addr + SOCK_MS_SYSTEM);
326
327         cmd = (host->req->tpc & 0xf) << 12;
328         cmd |= data_len;
329         writel(cmd, sock->addr + SOCK_MS_COMMAND);
330
331         dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param);
332         return 0;
333 }
334
335 static void tifm_ms_complete_cmd(struct tifm_ms *host)
336 {
337         struct tifm_dev *sock = host->dev;
338         struct memstick_host *msh = tifm_get_drvdata(sock);
339         int rc;
340
341         del_timer(&host->timer);
342
343         host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff;
344         host->req->int_reg = (host->req->int_reg & 1)
345                              | ((host->req->int_reg << 4) & 0xe0);
346
347         writel(TIFM_FIFO_INT_SETALL,
348                sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
349         writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
350
351         if (host->use_dma) {
352                 tifm_unmap_sg(sock, &host->req->sg, 1,
353                               host->req->data_dir == READ
354                               ? PCI_DMA_FROMDEVICE
355                               : PCI_DMA_TODEVICE);
356         }
357
358         writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
359                sock->addr + SOCK_CONTROL);
360
361         dev_dbg(&sock->dev, "TPC complete\n");
362         do {
363                 rc = memstick_next_req(msh, &host->req);
364         } while (!rc && tifm_ms_issue_cmd(host));
365 }
366
367 static int tifm_ms_check_status(struct tifm_ms *host)
368 {
369         if (!host->req->error) {
370                 if (!(host->cmd_flags & CMD_READY))
371                         return 1;
372                 if (!(host->cmd_flags & FIFO_READY))
373                         return 1;
374                 if (host->req->need_card_int
375                     && !(host->cmd_flags & CARD_INT))
376                         return 1;
377         }
378         return 0;
379 }
380
381 /* Called from interrupt handler */
382 static void tifm_ms_data_event(struct tifm_dev *sock)
383 {
384         struct tifm_ms *host;
385         unsigned int fifo_status = 0, host_status = 0;
386         int rc = 1;
387
388         spin_lock(&sock->lock);
389         host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
390         fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
391         host_status = readl(sock->addr + SOCK_MS_STATUS);
392         dev_dbg(&sock->dev,
393                 "data event: fifo_status %x, host_status %x, flags %x\n",
394                 fifo_status, host_status, host->cmd_flags);
395
396         if (host->req) {
397                 if (host->use_dma && (fifo_status & 1)) {
398                         host->cmd_flags |= FIFO_READY;
399                         rc = tifm_ms_check_status(host);
400                 }
401                 if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) {
402                         if (!tifm_ms_transfer_data(host)) {
403                                 host->cmd_flags |= FIFO_READY;
404                                 rc = tifm_ms_check_status(host);
405                         }
406                 }
407         }
408
409         writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
410         if (!rc)
411                 tifm_ms_complete_cmd(host);
412
413         spin_unlock(&sock->lock);
414 }
415
416
417 /* Called from interrupt handler */
418 static void tifm_ms_card_event(struct tifm_dev *sock)
419 {
420         struct tifm_ms *host;
421         unsigned int host_status = 0;
422         int rc = 1;
423
424         spin_lock(&sock->lock);
425         host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
426         host_status = readl(sock->addr + SOCK_MS_STATUS);
427         dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
428                 host_status, host->cmd_flags);
429
430         if (host->req) {
431                 if (host_status & TIFM_MS_STAT_TOE)
432                         host->req->error = -ETIME;
433                 else if (host_status & TIFM_MS_STAT_CRC)
434                         host->req->error = -EILSEQ;
435
436                 if (host_status & TIFM_MS_STAT_RDY)
437                         host->cmd_flags |= CMD_READY;
438
439                 if (host_status & TIFM_MS_STAT_MSINT)
440                         host->cmd_flags |= CARD_INT;
441
442                 rc = tifm_ms_check_status(host);
443
444         }
445
446         writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM),
447                sock->addr + SOCK_MS_SYSTEM);
448
449         if (!rc)
450                 tifm_ms_complete_cmd(host);
451
452         spin_unlock(&sock->lock);
453         return;
454 }
455
456 static void tifm_ms_request(struct memstick_host *msh)
457 {
458         struct tifm_ms *host = memstick_priv(msh);
459         struct tifm_dev *sock = host->dev;
460         unsigned long flags;
461         int rc;
462
463         spin_lock_irqsave(&sock->lock, flags);
464         if (host->req) {
465                 printk(KERN_ERR "%s : unfinished request detected\n",
466                        sock->dev.bus_id);
467                 spin_unlock_irqrestore(&sock->lock, flags);
468                 tifm_eject(host->dev);
469                 return;
470         }
471
472         if (host->eject) {
473                 do {
474                         rc = memstick_next_req(msh, &host->req);
475                         if (!rc)
476                                 host->req->error = -ETIME;
477                 } while (!rc);
478                 spin_unlock_irqrestore(&sock->lock, flags);
479                 return;
480         }
481
482         do {
483                 rc = memstick_next_req(msh, &host->req);
484         } while (!rc && tifm_ms_issue_cmd(host));
485
486         spin_unlock_irqrestore(&sock->lock, flags);
487         return;
488 }
489
490 static void tifm_ms_set_param(struct memstick_host *msh,
491                               enum memstick_param param,
492                               int value)
493 {
494         struct tifm_ms *host = memstick_priv(msh);
495         struct tifm_dev *sock = host->dev;
496         unsigned long flags;
497
498         spin_lock_irqsave(&sock->lock, flags);
499
500         switch (param) {
501         case MEMSTICK_POWER:
502                 /* also affected by media detection mechanism */
503                 if (value == MEMSTICK_POWER_ON) {
504                         host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
505                         writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM);
506                         writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
507                                sock->addr + SOCK_MS_SYSTEM);
508                         writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
509                 } else if (value == MEMSTICK_POWER_OFF) {
510                         writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
511                                sock->addr + SOCK_MS_SYSTEM);
512                         writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
513                 }
514                 break;
515         case MEMSTICK_INTERFACE:
516                 if (value == MEMSTICK_SERIAL) {
517                         host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
518                         writel((~TIFM_CTRL_FAST_CLK)
519                                & readl(sock->addr + SOCK_CONTROL),
520                                sock->addr + SOCK_CONTROL);
521                 } else if (value == MEMSTICK_PAR4) {
522                         host->mode_mask = 0;
523                         writel(TIFM_CTRL_FAST_CLK
524                                | readl(sock->addr + SOCK_CONTROL),
525                                sock->addr + SOCK_CONTROL);
526                 }
527                 break;
528         };
529
530         spin_unlock_irqrestore(&sock->lock, flags);
531 }
532
533 static void tifm_ms_abort(unsigned long data)
534 {
535         struct tifm_ms *host = (struct tifm_ms *)data;
536
537         dev_dbg(&host->dev->dev, "status %x\n",
538                 readl(host->dev->addr + SOCK_MS_STATUS));
539         printk(KERN_ERR
540                "%s : card failed to respond for a long period of time "
541                "(%x, %x)\n",
542                host->dev->dev.bus_id, host->req ? host->req->tpc : 0,
543                host->cmd_flags);
544
545         tifm_eject(host->dev);
546 }
547
548 static int tifm_ms_probe(struct tifm_dev *sock)
549 {
550         struct memstick_host *msh;
551         struct tifm_ms *host;
552         int rc = -EIO;
553
554         if (!(TIFM_SOCK_STATE_OCCUPIED
555               & readl(sock->addr + SOCK_PRESENT_STATE))) {
556                 printk(KERN_WARNING "%s : card gone, unexpectedly\n",
557                        sock->dev.bus_id);
558                 return rc;
559         }
560
561         msh = memstick_alloc_host(sizeof(struct tifm_ms), &sock->dev);
562         if (!msh)
563                 return -ENOMEM;
564
565         host = memstick_priv(msh);
566         tifm_set_drvdata(sock, msh);
567         host->dev = sock;
568         host->timeout_jiffies = msecs_to_jiffies(1000);
569
570         setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
571
572         msh->request = tifm_ms_request;
573         msh->set_param = tifm_ms_set_param;
574         sock->card_event = tifm_ms_card_event;
575         sock->data_event = tifm_ms_data_event;
576         if (tifm_has_ms_pif(sock))
577                 msh->caps |= MEMSTICK_CAP_PAR4;
578
579         rc = memstick_add_host(msh);
580         if (!rc)
581                 return 0;
582
583         memstick_free_host(msh);
584         return rc;
585 }
586
587 static void tifm_ms_remove(struct tifm_dev *sock)
588 {
589         struct memstick_host *msh = tifm_get_drvdata(sock);
590         struct tifm_ms *host = memstick_priv(msh);
591         int rc = 0;
592         unsigned long flags;
593
594         spin_lock_irqsave(&sock->lock, flags);
595         host->eject = 1;
596         if (host->req) {
597                 del_timer(&host->timer);
598                 writel(TIFM_FIFO_INT_SETALL,
599                        sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
600                 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
601                 if (host->use_dma)
602                         tifm_unmap_sg(sock, &host->req->sg, 1,
603                                       host->req->data_dir == READ
604                                       ? PCI_DMA_TODEVICE
605                                       : PCI_DMA_FROMDEVICE);
606                 host->req->error = -ETIME;
607
608                 do {
609                         rc = memstick_next_req(msh, &host->req);
610                         if (!rc)
611                                 host->req->error = -ETIME;
612                 } while (!rc);
613         }
614         spin_unlock_irqrestore(&sock->lock, flags);
615
616         memstick_remove_host(msh);
617         memstick_free_host(msh);
618 }
619
620 #ifdef CONFIG_PM
621
622 static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
623 {
624         struct memstick_host *msh = tifm_get_drvdata(sock);
625
626         memstick_suspend_host(msh);
627         return 0;
628 }
629
630 static int tifm_ms_resume(struct tifm_dev *sock)
631 {
632         struct memstick_host *msh = tifm_get_drvdata(sock);
633
634         memstick_resume_host(msh);
635         return 0;
636 }
637
638 #else
639
640 #define tifm_ms_suspend NULL
641 #define tifm_ms_resume NULL
642
643 #endif /* CONFIG_PM */
644
645 static struct tifm_device_id tifm_ms_id_tbl[] = {
646         { TIFM_TYPE_MS }, { 0 }
647 };
648
649 static struct tifm_driver tifm_ms_driver = {
650         .driver = {
651                 .name  = DRIVER_NAME,
652                 .owner = THIS_MODULE
653         },
654         .id_table = tifm_ms_id_tbl,
655         .probe    = tifm_ms_probe,
656         .remove   = tifm_ms_remove,
657         .suspend  = tifm_ms_suspend,
658         .resume   = tifm_ms_resume
659 };
660
661 static int __init tifm_ms_init(void)
662 {
663         return tifm_register_driver(&tifm_ms_driver);
664 }
665
666 static void __exit tifm_ms_exit(void)
667 {
668         tifm_unregister_driver(&tifm_ms_driver);
669 }
670
671 MODULE_AUTHOR("Alex Dubov");
672 MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
673 MODULE_LICENSE("GPL");
674 MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
675
676 module_init(tifm_ms_init);
677 module_exit(tifm_ms_exit);