4 * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
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.
10 * Special thanks to Carlos Corbacho for providing various MemoryStick cards
11 * that made this driver possible.
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>
22 #define DRIVER_NAME "tifm_ms"
23 #define DRIVER_VERSION "0.1"
26 module_param(no_dma, bool, 0644);
28 #define TIFM_MS_TIMEOUT 0x00100
29 #define TIFM_MS_BADCRC 0x00200
30 #define TIFM_MS_EOTPC 0x01000
31 #define TIFM_MS_INT 0x02000
33 /* The meaning of the bit majority in this constant is unknown. */
34 #define TIFM_MS_SERIAL 0x04010
36 #define TIFM_MS_SYS_LATCH 0x00100
37 #define TIFM_MS_SYS_NOT_RDY 0x00800
38 #define TIFM_MS_SYS_DATA 0x10000
50 unsigned short eject:1,
52 unsigned short cmd_flags;
53 unsigned int mode_mask;
54 unsigned int block_pos;
55 unsigned long timeout_jiffies;
57 struct timer_list timer;
58 struct memstick_request *req;
62 static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset,
63 struct page *pg, unsigned int page_off,
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;
70 if (host->cmd_flags & DATA_CARRY) {
71 while ((fifo_offset & 3) && length) {
72 buf[off++] = host->io_word & 0xff;
77 if (!(fifo_offset & 3))
78 host->cmd_flags &= ~DATA_CARRY;
84 host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
87 while (length && cnt) {
88 buf[off++] = (host->io_word >> 8) & 0xff;
92 fifo_offset += 4 - cnt;
96 host->cmd_flags |= DATA_CARRY;
98 kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
101 static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset,
102 struct page *pg, unsigned int page_off,
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;
109 if (host->cmd_flags & DATA_CARRY) {
110 while (fifo_offset & 3) {
111 host->io_word |= buf[off++] << (8 * (fifo_offset & 3));
115 if (!(fifo_offset & 3)) {
116 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
119 host->cmd_flags &= ~DATA_CARRY;
128 while (length && cnt) {
129 host->io_word |= buf[off++] << (4 - cnt);
133 fifo_offset += 4 - cnt;
135 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
141 host->cmd_flags |= DATA_CARRY;
143 kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ);
146 static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length)
149 unsigned int off = host->req->sg.offset + host->block_pos;
150 unsigned int p_off, p_cnt;
154 dev_dbg(&host->dev->dev, "moving block\n");
155 local_irq_save(flags);
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);
163 if (host->req->data_dir == WRITE)
164 tifm_ms_write_fifo(host, length - t_size,
167 tifm_ms_read_fifo(host, length - t_size,
172 local_irq_restore(flags);
175 static int tifm_ms_transfer_data(struct tifm_ms *host, int skip)
177 struct tifm_dev *sock = host->dev;
178 unsigned int length = host->req->sg.length - host->block_pos;
183 if (length > TIFM_FIFO_SIZE)
184 length = TIFM_FIFO_SIZE;
187 tifm_ms_move_block(host, length);
188 host->block_pos += length;
191 if ((host->req->data_dir == READ)
192 && (host->block_pos == host->req->sg.length))
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);
199 writel((1 << 8), sock->addr + SOCK_DMA_CONTROL);
204 static int tifm_ms_issue_cmd(struct tifm_ms *host)
206 struct tifm_dev *sock = host->dev;
208 unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0;
212 if (host->req->io_type == MEMSTICK_IO_SG) {
214 if (1 != tifm_map_sg(sock, &host->req->sg, 1,
215 host->req->data_dir == READ
217 : PCI_DMA_TODEVICE)) {
218 host->req->error = -ENOMEM;
219 return host->req->error;
221 data_len = sg_dma_len(&host->req->sg);
223 data_len = host->req->sg.length;
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);
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);
241 writel((1 << 8) | TIFM_DMA_EN,
242 sock->addr + SOCK_DMA_CONTROL);
244 tifm_ms_transfer_data(host,
245 host->req->data_dir == READ);
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;
255 cmd_mask = host->mode_mask | 0x2607; /* unknown constant */
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));
269 switch (data_len - cnt) {
271 tval |= data[cnt + 2] << 16;
273 tval |= data[cnt + 1] << 8;
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);
283 writel(TIFM_MS_SYS_LATCH
284 | readl(sock->addr + SOCK_MS_SYSTEM),
285 sock->addr + SOCK_MS_SYSTEM);
286 writel(0, sock->addr + SOCK_MS_DATA);
287 dev_dbg(&sock->dev, "writing %x\n", 0);
290 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
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);
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;
305 cmd = (host->req->tpc & 0xf) << 12;
307 writel(cmd, sock->addr + SOCK_MS_COMMAND);
309 dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask);
313 static void tifm_ms_complete_cmd(struct tifm_ms *host)
315 struct tifm_dev *sock = host->dev;
316 struct memstick_host *msh = tifm_get_drvdata(sock);
317 unsigned int tval = 0, data_len;
321 del_timer(&host->timer);
322 if (host->req->io_type == MEMSTICK_IO_SG) {
324 tifm_unmap_sg(sock, &host->req->sg, 1,
325 host->req->data_dir == READ
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);
332 data = host->req->data;
333 data_len = host->req->data_len;
335 if (host->req->data_dir == READ) {
336 for (rc = 0; (data_len - rc) >= 4; rc += 4)
338 = __raw_readl(sock->addr
342 tval = readl(sock->addr + SOCK_MS_DATA);
343 switch (data_len - rc) {
345 data[rc + 2] = (tval >> 16) & 0xff;
347 data[rc + 1] = (tval >> 8) & 0xff;
349 data[rc] = tval & 0xff;
351 readl(sock->addr + SOCK_MS_DATA);
355 writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
356 sock->addr + SOCK_CONTROL);
359 rc = memstick_next_req(msh, &host->req);
360 } while (!rc && tifm_ms_issue_cmd(host));
363 static int tifm_ms_check_status(struct tifm_ms *host)
365 if (!host->req->error) {
366 if (!(host->cmd_flags & CMD_READY))
368 if ((host->req->io_type == MEMSTICK_IO_SG)
369 && !(host->cmd_flags & FIFO_READY))
371 if (host->req->need_card_int
372 && !(host->cmd_flags & CARD_READY))
378 /* Called from interrupt handler */
379 static void tifm_ms_data_event(struct tifm_dev *sock)
381 struct tifm_ms *host;
382 unsigned int fifo_status = 0;
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);
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);
400 writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
402 tifm_ms_complete_cmd(host);
404 spin_unlock(&sock->lock);
408 /* Called from interrupt handler */
409 static void tifm_ms_card_event(struct tifm_dev *sock)
411 struct tifm_ms *host;
412 unsigned int host_status = 0;
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);
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;
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);
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;
438 rc = tifm_ms_check_status(host);
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);
448 tifm_ms_complete_cmd(host);
450 spin_unlock(&sock->lock);
454 static void tifm_ms_request(struct memstick_host *msh)
456 struct tifm_ms *host = memstick_priv(msh);
457 struct tifm_dev *sock = host->dev;
461 spin_lock_irqsave(&sock->lock, flags);
463 printk(KERN_ERR "%s : unfinished request detected\n",
465 spin_unlock_irqrestore(&sock->lock, flags);
466 tifm_eject(host->dev);
472 rc = memstick_next_req(msh, &host->req);
474 host->req->error = -ETIME;
476 spin_unlock_irqrestore(&sock->lock, flags);
481 rc = memstick_next_req(msh, &host->req);
482 } while (!rc && tifm_ms_issue_cmd(host));
484 spin_unlock_irqrestore(&sock->lock, flags);
488 static void tifm_ms_set_param(struct memstick_host *msh,
489 enum memstick_param param,
492 struct tifm_ms *host = memstick_priv(msh);
493 struct tifm_dev *sock = host->dev;
496 spin_lock_irqsave(&sock->lock, flags);
500 /* this is set by card detection mechanism */
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) {
510 writel(TIFM_CTRL_FAST_CLK
511 | readl(sock->addr + SOCK_CONTROL),
512 sock->addr + SOCK_CONTROL);
517 spin_unlock_irqrestore(&sock->lock, flags);
520 static void tifm_ms_abort(unsigned long data)
522 struct tifm_ms *host = (struct tifm_ms *)data;
524 dev_dbg(&host->dev->dev, "status %x\n",
525 readl(host->dev->addr + SOCK_MS_STATUS));
527 "%s : card failed to respond for a long period of time "
529 host->dev->dev.bus_id, host->req ? host->req->tpc : 0,
532 tifm_eject(host->dev);
535 static int tifm_ms_initialize_host(struct tifm_ms *host)
537 struct tifm_dev *sock = host->dev;
538 struct memstick_host *msh = tifm_get_drvdata(sock);
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;
550 static int tifm_ms_probe(struct tifm_dev *sock)
552 struct memstick_host *msh;
553 struct tifm_ms *host;
556 if (!(TIFM_SOCK_STATE_OCCUPIED
557 & readl(sock->addr + SOCK_PRESENT_STATE))) {
558 printk(KERN_WARNING "%s : card gone, unexpectedly\n",
563 msh = memstick_alloc_host(sizeof(struct tifm_ms), &sock->dev);
567 host = memstick_priv(msh);
568 tifm_set_drvdata(sock, msh);
570 host->timeout_jiffies = msecs_to_jiffies(1000);
571 host->no_dma = no_dma;
573 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
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);
582 rc = memstick_add_host(msh);
586 memstick_free_host(msh);
590 static void tifm_ms_remove(struct tifm_dev *sock)
592 struct memstick_host *msh = tifm_get_drvdata(sock);
593 struct tifm_ms *host = memstick_priv(msh);
597 spin_lock_irqsave(&sock->lock, flags);
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
608 : PCI_DMA_FROMDEVICE);
609 host->req->error = -ETIME;
612 rc = memstick_next_req(msh, &host->req);
614 host->req->error = -ETIME;
617 spin_unlock_irqrestore(&sock->lock, flags);
619 memstick_remove_host(msh);
621 writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
622 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
624 memstick_free_host(msh);
629 static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
634 static int tifm_ms_resume(struct tifm_dev *sock)
636 struct memstick_host *msh = tifm_get_drvdata(sock);
637 struct tifm_ms *host = memstick_priv(msh);
639 tifm_ms_initialize_host(host);
640 memstick_detect_change(msh);
647 #define tifm_ms_suspend NULL
648 #define tifm_ms_resume NULL
650 #endif /* CONFIG_PM */
652 static struct tifm_device_id tifm_ms_id_tbl[] = {
653 { TIFM_TYPE_MS }, { 0 }
656 static struct tifm_driver tifm_ms_driver = {
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
668 static int __init tifm_ms_init(void)
670 return tifm_register_driver(&tifm_ms_driver);
673 static void __exit tifm_ms_exit(void)
675 tifm_unregister_driver(&tifm_ms_driver);
678 MODULE_AUTHOR("Alex Dubov");
679 MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
680 MODULE_LICENSE("GPL");
681 MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
682 MODULE_VERSION(DRIVER_VERSION);
684 module_init(tifm_ms_init);
685 module_exit(tifm_ms_exit);