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