aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memstick/host
diff options
context:
space:
mode:
authorAlex Dubov <oakad@yahoo.com>2008-02-09 13:20:54 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-09 14:08:34 -0500
commitbaf8532a147d5b76681ce040e2c8f25a3f0e718d (patch)
tree69c228046709295c1152f2063321327789c3b9f4 /drivers/memstick/host
parent941edd030b9725f9f85bd62dfdb68cde3a50fb66 (diff)
memstick: initial commit for Sony MemoryStick support
Sony MemoryStick cards are used in many products manufactured by Sony. They are available both as storage and as IO expansion cards. Currently, only MemoryStick Pro storage cards are supported via TI FlashMedia MemoryStick interface. [mboton@gmail.com: biuld fix] [akpm@linux-foundation.org: build fix] Signed-off-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Miguel Boton <mboton@gmail.co> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick/host')
-rw-r--r--drivers/memstick/host/Kconfig22
-rw-r--r--drivers/memstick/host/Makefile10
-rw-r--r--drivers/memstick/host/tifm_ms.c685
3 files changed, 717 insertions, 0 deletions
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
new file mode 100644
index 000000000000..c002fcc3c879
--- /dev/null
+++ b/drivers/memstick/host/Kconfig
@@ -0,0 +1,22 @@
1#
2# MemoryStick host controller drivers
3#
4
5comment "MemoryStick Host Controller Drivers"
6
7config MEMSTICK_TIFM_MS
8 tristate "TI Flash Media MemoryStick Interface support (EXPERIMENTAL)"
9 depends on EXPERIMENTAL && PCI
10 select TIFM_CORE
11 help
12 Say Y here if you want to be able to access MemoryStick cards with
13 the Texas Instruments(R) Flash Media card reader, found in many
14 laptops.
15 This option 'selects' (turns on, enables) 'TIFM_CORE', but you
16 probably also need appropriate card reader host adapter, such as
17 'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
18 (TIFM_7XX1)'.
19
20 To compile this driver as a module, choose M here: the
21 module will be called tifm_ms.
22
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
new file mode 100644
index 000000000000..ee666380efa1
--- /dev/null
+++ b/drivers/memstick/host/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for MemoryStick host controller drivers
3#
4
5ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
6 EXTRA_CFLAGS += -DDEBUG
7endif
8
9obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
10
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
new file mode 100644
index 000000000000..f55b71a4337d
--- /dev/null
+++ b/drivers/memstick/host/tifm_ms.c
@@ -0,0 +1,685 @@
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#define DRIVER_VERSION "0.1"
24
25static int no_dma;
26module_param(no_dma, bool, 0644);
27
28#define TIFM_MS_TIMEOUT 0x00100
29#define TIFM_MS_BADCRC 0x00200
30#define TIFM_MS_EOTPC 0x01000
31#define TIFM_MS_INT 0x02000
32
33/* The meaning of the bit majority in this constant is unknown. */
34#define TIFM_MS_SERIAL 0x04010
35
36#define TIFM_MS_SYS_LATCH 0x00100
37#define TIFM_MS_SYS_NOT_RDY 0x00800
38#define TIFM_MS_SYS_DATA 0x10000
39
40/* Hardware flags */
41enum {
42 CMD_READY = 0x0001,
43 FIFO_READY = 0x0002,
44 CARD_READY = 0x0004,
45 DATA_CARRY = 0x0008
46};
47
48struct tifm_ms {
49 struct tifm_dev *dev;
50 unsigned short eject:1,
51 no_dma:1;
52 unsigned short cmd_flags;
53 unsigned int mode_mask;
54 unsigned int block_pos;
55 unsigned long timeout_jiffies;
56
57 struct timer_list timer;
58 struct memstick_request *req;
59 unsigned int io_word;
60};
61
62static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset,
63 struct page *pg, unsigned int page_off,
64 unsigned int length)
65{
66 struct tifm_dev *sock = host->dev;
67 unsigned int cnt = 0, off = 0;
68 unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off;
69
70 if (host->cmd_flags & DATA_CARRY) {
71 while ((fifo_offset & 3) && length) {
72 buf[off++] = host->io_word & 0xff;
73 host->io_word >>= 8;
74 length--;
75 fifo_offset++;
76 }
77 if (!(fifo_offset & 3))
78 host->cmd_flags &= ~DATA_CARRY;
79 if (!length)
80 return;
81 }
82
83 do {
84 host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
85 + fifo_offset);
86 cnt = 4;
87 while (length && cnt) {
88 buf[off++] = (host->io_word >> 8) & 0xff;
89 cnt--;
90 length--;
91 }
92 fifo_offset += 4 - cnt;
93 } while (length);
94
95 if (cnt)
96 host->cmd_flags |= DATA_CARRY;
97
98 kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
99}
100
101static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset,
102 struct page *pg, unsigned int page_off,
103 unsigned int length)
104{
105 struct tifm_dev *sock = host->dev;
106 unsigned int cnt = 0, off = 0;
107 unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off;
108
109 if (host->cmd_flags & DATA_CARRY) {
110 while (fifo_offset & 3) {
111 host->io_word |= buf[off++] << (8 * (fifo_offset & 3));
112 length--;
113 fifo_offset++;
114 }
115 if (!(fifo_offset & 3)) {
116 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
117 + fifo_offset - 4);
118
119 host->cmd_flags &= ~DATA_CARRY;
120 }
121 if (!length)
122 return;
123 }
124
125 do {
126 cnt = 4;
127 host->io_word = 0;
128 while (length && cnt) {
129 host->io_word |= buf[off++] << (4 - cnt);
130 cnt--;
131 length--;
132 }
133 fifo_offset += 4 - cnt;
134 if (!cnt)
135 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
136 + fifo_offset - 4);
137
138 } while (length);
139
140 if (cnt)
141 host->cmd_flags |= DATA_CARRY;
142
143 kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ);
144}
145
146static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length)
147{
148 unsigned int t_size;
149 unsigned int off = host->req->sg.offset + host->block_pos;
150 unsigned int p_off, p_cnt;
151 struct page *pg;
152 unsigned long flags;
153
154 dev_dbg(&host->dev->dev, "moving block\n");
155 local_irq_save(flags);
156 t_size = length;
157 while (t_size) {
158 pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT);
159 p_off = offset_in_page(off);
160 p_cnt = PAGE_SIZE - p_off;
161 p_cnt = min(p_cnt, t_size);
162
163 if (host->req->data_dir == WRITE)
164 tifm_ms_write_fifo(host, length - t_size,
165 pg, p_off, p_cnt);
166 else
167 tifm_ms_read_fifo(host, length - t_size,
168 pg, p_off, p_cnt);
169
170 t_size -= p_cnt;
171 }
172 local_irq_restore(flags);
173}
174
175static int tifm_ms_transfer_data(struct tifm_ms *host, int skip)
176{
177 struct tifm_dev *sock = host->dev;
178 unsigned int length = host->req->sg.length - host->block_pos;
179
180 if (!length)
181 return 1;
182
183 if (length > TIFM_FIFO_SIZE)
184 length = TIFM_FIFO_SIZE;
185
186 if (!skip) {
187 tifm_ms_move_block(host, length);
188 host->block_pos += length;
189 }
190
191 if ((host->req->data_dir == READ)
192 && (host->block_pos == host->req->sg.length))
193 return 1;
194
195 writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE);
196 if (host->req->data_dir == WRITE)
197 writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL);
198 else
199 writel((1 << 8), sock->addr + SOCK_DMA_CONTROL);
200
201 return 0;
202}
203
204static int tifm_ms_issue_cmd(struct tifm_ms *host)
205{
206 struct tifm_dev *sock = host->dev;
207 unsigned char *data;
208 unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0;
209
210 host->cmd_flags = 0;
211
212 if (host->req->io_type == MEMSTICK_IO_SG) {
213 if (!host->no_dma) {
214 if (1 != tifm_map_sg(sock, &host->req->sg, 1,
215 host->req->data_dir == READ
216 ? PCI_DMA_FROMDEVICE
217 : PCI_DMA_TODEVICE)) {
218 host->req->error = -ENOMEM;
219 return host->req->error;
220 }
221 data_len = sg_dma_len(&host->req->sg);
222 } else
223 data_len = host->req->sg.length;
224
225 writel(TIFM_FIFO_INT_SETALL,
226 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
227 writel(TIFM_FIFO_ENABLE,
228 sock->addr + SOCK_FIFO_CONTROL);
229 writel(TIFM_FIFO_INTMASK,
230 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
231
232 if (!host->no_dma) {
233 writel(ilog2(data_len) - 2,
234 sock->addr + SOCK_FIFO_PAGE_SIZE);
235 writel(sg_dma_address(&host->req->sg),
236 sock->addr + SOCK_DMA_ADDRESS);
237 if (host->req->data_dir == WRITE)
238 writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
239 sock->addr + SOCK_DMA_CONTROL);
240 else
241 writel((1 << 8) | TIFM_DMA_EN,
242 sock->addr + SOCK_DMA_CONTROL);
243 } else {
244 tifm_ms_transfer_data(host,
245 host->req->data_dir == READ);
246 }
247
248 cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
249 cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY;
250 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
251 } else if (host->req->io_type == MEMSTICK_IO_VAL) {
252 data = host->req->data;
253 data_len = host->req->data_len;
254
255 cmd_mask = host->mode_mask | 0x2607; /* unknown constant */
256
257 if (host->req->data_dir == WRITE) {
258 cmd_mask |= TIFM_MS_SYS_LATCH;
259 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
260 for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) {
261 writel(TIFM_MS_SYS_LATCH
262 | readl(sock->addr + SOCK_MS_SYSTEM),
263 sock->addr + SOCK_MS_SYSTEM);
264 __raw_writel(*(unsigned int *)(data + cnt),
265 sock->addr + SOCK_MS_DATA);
266 dev_dbg(&sock->dev, "writing %x\n",
267 *(int *)(data + cnt));
268 }
269 switch (data_len - cnt) {
270 case 3:
271 tval |= data[cnt + 2] << 16;
272 case 2:
273 tval |= data[cnt + 1] << 8;
274 case 1:
275 tval |= data[cnt];
276 writel(TIFM_MS_SYS_LATCH
277 | readl(sock->addr + SOCK_MS_SYSTEM),
278 sock->addr + SOCK_MS_SYSTEM);
279 writel(tval, sock->addr + SOCK_MS_DATA);
280 dev_dbg(&sock->dev, "writing %x\n", tval);
281 }
282
283 writel(TIFM_MS_SYS_LATCH
284 | readl(sock->addr + SOCK_MS_SYSTEM),
285 sock + SOCK_MS_SYSTEM);
286 writel(0, sock->addr + SOCK_MS_DATA);
287 dev_dbg(&sock->dev, "writing %x\n", 0);
288
289 } else
290 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
291
292 cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
293 cmd_mask &= ~TIFM_MS_SYS_DATA;
294 cmd_mask |= TIFM_MS_SYS_NOT_RDY;
295 dev_dbg(&sock->dev, "mask %x\n", cmd_mask);
296 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
297 } else
298 BUG();
299
300 mod_timer(&host->timer, jiffies + host->timeout_jiffies);
301 writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
302 sock->addr + SOCK_CONTROL);
303 host->req->error = 0;
304
305 cmd = (host->req->tpc & 0xf) << 12;
306 cmd |= data_len;
307 writel(cmd, sock->addr + SOCK_MS_COMMAND);
308
309 dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask);
310 return 0;
311}
312
313static void tifm_ms_complete_cmd(struct tifm_ms *host)
314{
315 struct tifm_dev *sock = host->dev;
316 struct memstick_host *msh = tifm_get_drvdata(sock);
317 unsigned int tval = 0, data_len;
318 unsigned char *data;
319 int rc;
320
321 del_timer(&host->timer);
322 if (host->req->io_type == MEMSTICK_IO_SG) {
323 if (!host->no_dma)
324 tifm_unmap_sg(sock, &host->req->sg, 1,
325 host->req->data_dir == READ
326 ? PCI_DMA_FROMDEVICE
327 : PCI_DMA_TODEVICE);
328 } else if (host->req->io_type == MEMSTICK_IO_VAL) {
329 writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM),
330 sock->addr + SOCK_MS_SYSTEM);
331
332 data = host->req->data;
333 data_len = host->req->data_len;
334
335 if (host->req->data_dir == READ) {
336 for (rc = 0; (data_len - rc) >= 4; rc += 4)
337 *(int *)(data + rc)
338 = __raw_readl(sock->addr
339 + SOCK_MS_DATA);
340
341 if (data_len - rc)
342 tval = readl(sock->addr + SOCK_MS_DATA);
343 switch (data_len - rc) {
344 case 3:
345 data[rc + 2] = (tval >> 16) & 0xff;
346 case 2:
347 data[rc + 1] = (tval >> 8) & 0xff;
348 case 1:
349 data[rc] = tval & 0xff;
350 }
351 readl(sock->addr + SOCK_MS_DATA);
352 }
353 }
354
355 writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
356 sock->addr + SOCK_CONTROL);
357
358 do {
359 rc = memstick_next_req(msh, &host->req);
360 } while (!rc && tifm_ms_issue_cmd(host));
361}
362
363static int tifm_ms_check_status(struct tifm_ms *host)
364{
365 if (!host->req->error) {
366 if (!(host->cmd_flags & CMD_READY))
367 return 1;
368 if ((host->req->io_type == MEMSTICK_IO_SG)
369 && !(host->cmd_flags & FIFO_READY))
370 return 1;
371 if (host->req->need_card_int
372 && !(host->cmd_flags & CARD_READY))
373 return 1;
374 }
375 return 0;
376}
377
378/* Called from interrupt handler */
379static void tifm_ms_data_event(struct tifm_dev *sock)
380{
381 struct tifm_ms *host;
382 unsigned int fifo_status = 0;
383 int rc = 1;
384
385 spin_lock(&sock->lock);
386 host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
387 fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
388 dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
389 fifo_status, host->cmd_flags);
390
391 if (host->req) {
392 if (fifo_status & TIFM_FIFO_READY) {
393 if (!host->no_dma || tifm_ms_transfer_data(host, 0)) {
394 host->cmd_flags |= FIFO_READY;
395 rc = tifm_ms_check_status(host);
396 }
397 }
398 }
399
400 writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
401 if (!rc)
402 tifm_ms_complete_cmd(host);
403
404 spin_unlock(&sock->lock);
405}
406
407
408/* Called from interrupt handler */
409static void tifm_ms_card_event(struct tifm_dev *sock)
410{
411 struct tifm_ms *host;
412 unsigned int host_status = 0;
413 int rc = 1;
414
415 spin_lock(&sock->lock);
416 host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
417 host_status = readl(sock->addr + SOCK_MS_STATUS);
418 dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
419 host_status, host->cmd_flags);
420
421 if (host->req) {
422 if (host_status & TIFM_MS_TIMEOUT)
423 host->req->error = -ETIME;
424 else if (host_status & TIFM_MS_BADCRC)
425 host->req->error = -EILSEQ;
426
427 if (host->req->error) {
428 writel(TIFM_FIFO_INT_SETALL,
429 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
430 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
431 }
432
433 if (host_status & TIFM_MS_EOTPC)
434 host->cmd_flags |= CMD_READY;
435 if (host_status & TIFM_MS_INT)
436 host->cmd_flags |= CARD_READY;
437
438 rc = tifm_ms_check_status(host);
439
440 }
441
442 writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM),
443 sock->addr + SOCK_MS_SYSTEM);
444 writel((~TIFM_MS_SYS_DATA) & 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
454static void tifm_ms_request(struct memstick_host *msh)
455{
456 struct tifm_ms *host = memstick_priv(msh);
457 struct tifm_dev *sock = host->dev;
458 unsigned long flags;
459 int rc;
460
461 spin_lock_irqsave(&sock->lock, flags);
462 if (host->req) {
463 printk(KERN_ERR "%s : unfinished request detected\n",
464 sock->dev.bus_id);
465 spin_unlock_irqrestore(&sock->lock, flags);
466 tifm_eject(host->dev);
467 return;
468 }
469
470 if (host->eject) {
471 do {
472 rc = memstick_next_req(msh, &host->req);
473 if (!rc)
474 host->req->error = -ETIME;
475 } while (!rc);
476 spin_unlock_irqrestore(&sock->lock, flags);
477 return;
478 }
479
480 do {
481 rc = memstick_next_req(msh, &host->req);
482 } while (!rc && tifm_ms_issue_cmd(host));
483
484 spin_unlock_irqrestore(&sock->lock, flags);
485 return;
486}
487
488static void tifm_ms_set_param(struct memstick_host *msh,
489 enum memstick_param param,
490 int value)
491{
492 struct tifm_ms *host = memstick_priv(msh);
493 struct tifm_dev *sock = host->dev;
494 unsigned long flags;
495
496 spin_lock_irqsave(&sock->lock, flags);
497
498 switch (param) {
499 case MEMSTICK_POWER:
500 /* this is set by card detection mechanism */
501 break;
502 case MEMSTICK_INTERFACE:
503 if (value == MEMSTICK_SERIAL) {
504 host->mode_mask = TIFM_MS_SERIAL;
505 writel((~TIFM_CTRL_FAST_CLK)
506 & readl(sock->addr + SOCK_CONTROL),
507 sock->addr + SOCK_CONTROL);
508 } else if (value == MEMSTICK_PARALLEL) {
509 host->mode_mask = 0;
510 writel(TIFM_CTRL_FAST_CLK
511 | readl(sock->addr + SOCK_CONTROL),
512 sock->addr + SOCK_CONTROL);
513 }
514 break;
515 };
516
517 spin_unlock_irqrestore(&sock->lock, flags);
518}
519
520static void tifm_ms_abort(unsigned long data)
521{
522 struct tifm_ms *host = (struct tifm_ms *)data;
523
524 dev_dbg(&host->dev->dev, "status %x\n",
525 readl(host->dev->addr + SOCK_MS_STATUS));
526 printk(KERN_ERR
527 "%s : card failed to respond for a long period of time "
528 "(%x, %x)\n",
529 host->dev->dev.bus_id, host->req ? host->req->tpc : 0,
530 host->cmd_flags);
531
532 tifm_eject(host->dev);
533}
534
535static int tifm_ms_initialize_host(struct tifm_ms *host)
536{
537 struct tifm_dev *sock = host->dev;
538 struct memstick_host *msh = tifm_get_drvdata(sock);
539
540 host->mode_mask = TIFM_MS_SERIAL;
541 writel(0x8000, sock->addr + SOCK_MS_SYSTEM);
542 writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
543 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
544 if (tifm_has_ms_pif(sock))
545 msh->caps |= MEMSTICK_CAP_PARALLEL;
546
547 return 0;
548}
549
550static 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 sock->dev.bus_id);
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 host->no_dma = no_dma;
572
573 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
574
575 msh->request = tifm_ms_request;
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 rc = tifm_ms_initialize_host(host);
580
581 if (!rc)
582 rc = memstick_add_host(msh);
583 if (!rc)
584 return 0;
585
586 memstick_free_host(msh);
587 return rc;
588}
589
590static 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 spin_lock_irqsave(&sock->lock, flags);
598 host->eject = 1;
599 if (host->req) {
600 del_timer(&host->timer);
601 writel(TIFM_FIFO_INT_SETALL,
602 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
603 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
604 if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma)
605 tifm_unmap_sg(sock, &host->req->sg, 1,
606 host->req->data_dir == READ
607 ? PCI_DMA_TODEVICE
608 : PCI_DMA_FROMDEVICE);
609 host->req->error = -ETIME;
610
611 do {
612 rc = memstick_next_req(msh, &host->req);
613 if (!rc)
614 host->req->error = -ETIME;
615 } while (!rc);
616 }
617 spin_unlock_irqrestore(&sock->lock, flags);
618
619 memstick_remove_host(msh);
620
621 writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
622 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
623
624 memstick_free_host(msh);
625}
626
627#ifdef CONFIG_PM
628
629static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
630{
631 return 0;
632}
633
634static int tifm_ms_resume(struct tifm_dev *sock)
635{
636 struct memstick_host *msh = tifm_get_drvdata(sock);
637 struct tifm_ms *host = memstick_priv(msh);
638
639 tifm_ms_initialize_host(host);
640 memstick_detect_change(msh);
641
642 return 0;
643}
644
645#else
646
647#define tifm_ms_suspend NULL
648#define tifm_ms_resume NULL
649
650#endif /* CONFIG_PM */
651
652static struct tifm_device_id tifm_ms_id_tbl[] = {
653 { TIFM_TYPE_MS }, { 0 }
654};
655
656static struct tifm_driver tifm_ms_driver = {
657 .driver = {
658 .name = DRIVER_NAME,
659 .owner = THIS_MODULE
660 },
661 .id_table = tifm_ms_id_tbl,
662 .probe = tifm_ms_probe,
663 .remove = tifm_ms_remove,
664 .suspend = tifm_ms_suspend,
665 .resume = tifm_ms_resume
666};
667
668static int __init tifm_ms_init(void)
669{
670 return tifm_register_driver(&tifm_ms_driver);
671}
672
673static void __exit tifm_ms_exit(void)
674{
675 tifm_unregister_driver(&tifm_ms_driver);
676}
677
678MODULE_AUTHOR("Alex Dubov");
679MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
680MODULE_LICENSE("GPL");
681MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
682MODULE_VERSION(DRIVER_VERSION);
683
684module_init(tifm_ms_init);
685module_exit(tifm_ms_exit);