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