diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/sdio_uart.c | 339 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/host/omap.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/pxamci.c | 14 | ||||
-rw-r--r-- | drivers/mmc/host/s3cmci.c | 2 |
8 files changed, 239 insertions, 143 deletions
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 36a8d53ad2a2..f53755533e7e 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/sched.h> | ||
32 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
34 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> |
@@ -73,11 +74,10 @@ struct uart_icount { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | struct sdio_uart_port { | 76 | struct sdio_uart_port { |
77 | struct tty_port port; | ||
76 | struct kref kref; | 78 | struct kref kref; |
77 | struct tty_struct *tty; | 79 | struct tty_struct *tty; |
78 | unsigned int index; | 80 | unsigned int index; |
79 | unsigned int opened; | ||
80 | struct mutex open_lock; | ||
81 | struct sdio_func *func; | 81 | struct sdio_func *func; |
82 | struct mutex func_lock; | 82 | struct mutex func_lock; |
83 | struct task_struct *in_sdio_uart_irq; | 83 | struct task_struct *in_sdio_uart_irq; |
@@ -87,6 +87,7 @@ struct sdio_uart_port { | |||
87 | struct uart_icount icount; | 87 | struct uart_icount icount; |
88 | unsigned int uartclk; | 88 | unsigned int uartclk; |
89 | unsigned int mctrl; | 89 | unsigned int mctrl; |
90 | unsigned int rx_mctrl; | ||
90 | unsigned int read_status_mask; | 91 | unsigned int read_status_mask; |
91 | unsigned int ignore_status_mask; | 92 | unsigned int ignore_status_mask; |
92 | unsigned char x_char; | 93 | unsigned char x_char; |
@@ -102,7 +103,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
102 | int index, ret = -EBUSY; | 103 | int index, ret = -EBUSY; |
103 | 104 | ||
104 | kref_init(&port->kref); | 105 | kref_init(&port->kref); |
105 | mutex_init(&port->open_lock); | ||
106 | mutex_init(&port->func_lock); | 106 | mutex_init(&port->func_lock); |
107 | spin_lock_init(&port->write_lock); | 107 | spin_lock_init(&port->write_lock); |
108 | 108 | ||
@@ -151,6 +151,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port) | |||
151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) | 151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) |
152 | { | 152 | { |
153 | struct sdio_func *func; | 153 | struct sdio_func *func; |
154 | struct tty_struct *tty; | ||
154 | 155 | ||
155 | BUG_ON(sdio_uart_table[port->index] != port); | 156 | BUG_ON(sdio_uart_table[port->index] != port); |
156 | 157 | ||
@@ -165,15 +166,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) | |||
165 | * give up on that port ASAP. | 166 | * give up on that port ASAP. |
166 | * Beware: the lock ordering is critical. | 167 | * Beware: the lock ordering is critical. |
167 | */ | 168 | */ |
168 | mutex_lock(&port->open_lock); | 169 | mutex_lock(&port->port.mutex); |
169 | mutex_lock(&port->func_lock); | 170 | mutex_lock(&port->func_lock); |
170 | func = port->func; | 171 | func = port->func; |
171 | sdio_claim_host(func); | 172 | sdio_claim_host(func); |
172 | port->func = NULL; | 173 | port->func = NULL; |
173 | mutex_unlock(&port->func_lock); | 174 | mutex_unlock(&port->func_lock); |
174 | if (port->opened) | 175 | tty = tty_port_tty_get(&port->port); |
175 | tty_hangup(port->tty); | 176 | /* tty_hangup is async so is this safe as is ?? */ |
176 | mutex_unlock(&port->open_lock); | 177 | if (tty) { |
178 | tty_hangup(tty); | ||
179 | tty_kref_put(tty); | ||
180 | } | ||
181 | mutex_unlock(&port->port.mutex); | ||
177 | sdio_release_irq(func); | 182 | sdio_release_irq(func); |
178 | sdio_disable_func(func); | 183 | sdio_disable_func(func); |
179 | sdio_release_host(func); | 184 | sdio_release_host(func); |
@@ -217,6 +222,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
217 | unsigned char status; | 222 | unsigned char status; |
218 | unsigned int ret; | 223 | unsigned int ret; |
219 | 224 | ||
225 | /* FIXME: What stops this losing the delta bits and breaking | ||
226 | sdio_uart_check_modem_status ? */ | ||
220 | status = sdio_in(port, UART_MSR); | 227 | status = sdio_in(port, UART_MSR); |
221 | 228 | ||
222 | ret = 0; | 229 | ret = 0; |
@@ -231,7 +238,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
231 | return ret; | 238 | return ret; |
232 | } | 239 | } |
233 | 240 | ||
234 | static void sdio_uart_write_mctrl(struct sdio_uart_port *port, unsigned int mctrl) | 241 | static void sdio_uart_write_mctrl(struct sdio_uart_port *port, |
242 | unsigned int mctrl) | ||
235 | { | 243 | { |
236 | unsigned char mcr = 0; | 244 | unsigned char mcr = 0; |
237 | 245 | ||
@@ -387,9 +395,10 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) | |||
387 | sdio_out(port, UART_IER, port->ier); | 395 | sdio_out(port, UART_IER, port->ier); |
388 | } | 396 | } |
389 | 397 | ||
390 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status) | 398 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, |
399 | unsigned int *status) | ||
391 | { | 400 | { |
392 | struct tty_struct *tty = port->tty; | 401 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
393 | unsigned int ch, flag; | 402 | unsigned int ch, flag; |
394 | int max_count = 256; | 403 | int max_count = 256; |
395 | 404 | ||
@@ -399,7 +408,7 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *s | |||
399 | port->icount.rx++; | 408 | port->icount.rx++; |
400 | 409 | ||
401 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | 410 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | |
402 | UART_LSR_FE | UART_LSR_OE))) { | 411 | UART_LSR_FE | UART_LSR_OE))) { |
403 | /* | 412 | /* |
404 | * For statistics only | 413 | * For statistics only |
405 | */ | 414 | */ |
@@ -417,33 +426,39 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *s | |||
417 | * Mask off conditions which should be ignored. | 426 | * Mask off conditions which should be ignored. |
418 | */ | 427 | */ |
419 | *status &= port->read_status_mask; | 428 | *status &= port->read_status_mask; |
420 | if (*status & UART_LSR_BI) { | 429 | if (*status & UART_LSR_BI) |
421 | flag = TTY_BREAK; | 430 | flag = TTY_BREAK; |
422 | } else if (*status & UART_LSR_PE) | 431 | else if (*status & UART_LSR_PE) |
423 | flag = TTY_PARITY; | 432 | flag = TTY_PARITY; |
424 | else if (*status & UART_LSR_FE) | 433 | else if (*status & UART_LSR_FE) |
425 | flag = TTY_FRAME; | 434 | flag = TTY_FRAME; |
426 | } | 435 | } |
427 | 436 | ||
428 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) | 437 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) |
429 | tty_insert_flip_char(tty, ch, flag); | 438 | if (tty) |
439 | tty_insert_flip_char(tty, ch, flag); | ||
430 | 440 | ||
431 | /* | 441 | /* |
432 | * Overrun is special. Since it's reported immediately, | 442 | * Overrun is special. Since it's reported immediately, |
433 | * it doesn't affect the current character. | 443 | * it doesn't affect the current character. |
434 | */ | 444 | */ |
435 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) | 445 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) |
436 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 446 | if (tty) |
447 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
437 | 448 | ||
438 | *status = sdio_in(port, UART_LSR); | 449 | *status = sdio_in(port, UART_LSR); |
439 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 450 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
440 | tty_flip_buffer_push(tty); | 451 | if (tty) { |
452 | tty_flip_buffer_push(tty); | ||
453 | tty_kref_put(tty); | ||
454 | } | ||
441 | } | 455 | } |
442 | 456 | ||
443 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 457 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) |
444 | { | 458 | { |
445 | struct circ_buf *xmit = &port->xmit; | 459 | struct circ_buf *xmit = &port->xmit; |
446 | int count; | 460 | int count; |
461 | struct tty_struct *tty; | ||
447 | 462 | ||
448 | if (port->x_char) { | 463 | if (port->x_char) { |
449 | sdio_out(port, UART_TX, port->x_char); | 464 | sdio_out(port, UART_TX, port->x_char); |
@@ -451,8 +466,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
451 | port->x_char = 0; | 466 | port->x_char = 0; |
452 | return; | 467 | return; |
453 | } | 468 | } |
454 | if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) { | 469 | |
470 | tty = tty_port_tty_get(&port->port); | ||
471 | |||
472 | if (tty == NULL || circ_empty(xmit) || | ||
473 | tty->stopped || tty->hw_stopped) { | ||
455 | sdio_uart_stop_tx(port); | 474 | sdio_uart_stop_tx(port); |
475 | tty_kref_put(tty); | ||
456 | return; | 476 | return; |
457 | } | 477 | } |
458 | 478 | ||
@@ -466,15 +486,17 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
466 | } while (--count > 0); | 486 | } while (--count > 0); |
467 | 487 | ||
468 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 488 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) |
469 | tty_wakeup(port->tty); | 489 | tty_wakeup(tty); |
470 | 490 | ||
471 | if (circ_empty(xmit)) | 491 | if (circ_empty(xmit)) |
472 | sdio_uart_stop_tx(port); | 492 | sdio_uart_stop_tx(port); |
493 | tty_kref_put(tty); | ||
473 | } | 494 | } |
474 | 495 | ||
475 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | 496 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) |
476 | { | 497 | { |
477 | int status; | 498 | int status; |
499 | struct tty_struct *tty; | ||
478 | 500 | ||
479 | status = sdio_in(port, UART_MSR); | 501 | status = sdio_in(port, UART_MSR); |
480 | 502 | ||
@@ -485,25 +507,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | |||
485 | port->icount.rng++; | 507 | port->icount.rng++; |
486 | if (status & UART_MSR_DDSR) | 508 | if (status & UART_MSR_DDSR) |
487 | port->icount.dsr++; | 509 | port->icount.dsr++; |
488 | if (status & UART_MSR_DDCD) | 510 | if (status & UART_MSR_DDCD) { |
489 | port->icount.dcd++; | 511 | port->icount.dcd++; |
512 | /* DCD raise - wake for open */ | ||
513 | if (status & UART_MSR_DCD) | ||
514 | wake_up_interruptible(&port->port.open_wait); | ||
515 | else { | ||
516 | /* DCD drop - hang up if tty attached */ | ||
517 | tty = tty_port_tty_get(&port->port); | ||
518 | if (tty) { | ||
519 | tty_hangup(tty); | ||
520 | tty_kref_put(tty); | ||
521 | } | ||
522 | } | ||
523 | } | ||
490 | if (status & UART_MSR_DCTS) { | 524 | if (status & UART_MSR_DCTS) { |
491 | port->icount.cts++; | 525 | port->icount.cts++; |
492 | if (port->tty->termios->c_cflag & CRTSCTS) { | 526 | tty = tty_port_tty_get(&port->port); |
527 | if (tty && (tty->termios->c_cflag & CRTSCTS)) { | ||
493 | int cts = (status & UART_MSR_CTS); | 528 | int cts = (status & UART_MSR_CTS); |
494 | if (port->tty->hw_stopped) { | 529 | if (tty->hw_stopped) { |
495 | if (cts) { | 530 | if (cts) { |
496 | port->tty->hw_stopped = 0; | 531 | tty->hw_stopped = 0; |
497 | sdio_uart_start_tx(port); | 532 | sdio_uart_start_tx(port); |
498 | tty_wakeup(port->tty); | 533 | tty_wakeup(tty); |
499 | } | 534 | } |
500 | } else { | 535 | } else { |
501 | if (!cts) { | 536 | if (!cts) { |
502 | port->tty->hw_stopped = 1; | 537 | tty->hw_stopped = 1; |
503 | sdio_uart_stop_tx(port); | 538 | sdio_uart_stop_tx(port); |
504 | } | 539 | } |
505 | } | 540 | } |
506 | } | 541 | } |
542 | tty_kref_put(tty); | ||
507 | } | 543 | } |
508 | } | 544 | } |
509 | 545 | ||
@@ -540,8 +576,62 @@ static void sdio_uart_irq(struct sdio_func *func) | |||
540 | port->in_sdio_uart_irq = NULL; | 576 | port->in_sdio_uart_irq = NULL; |
541 | } | 577 | } |
542 | 578 | ||
543 | static int sdio_uart_startup(struct sdio_uart_port *port) | 579 | static int uart_carrier_raised(struct tty_port *tport) |
580 | { | ||
581 | struct sdio_uart_port *port = | ||
582 | container_of(tport, struct sdio_uart_port, port); | ||
583 | unsigned int ret = sdio_uart_claim_func(port); | ||
584 | if (ret) /* Missing hardware shoudn't block for carrier */ | ||
585 | return 1; | ||
586 | ret = sdio_uart_get_mctrl(port); | ||
587 | sdio_uart_release_func(port); | ||
588 | if (ret & TIOCM_CAR) | ||
589 | return 1; | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * uart_dtr_rts - port helper to set uart signals | ||
595 | * @tport: tty port to be updated | ||
596 | * @onoff: set to turn on DTR/RTS | ||
597 | * | ||
598 | * Called by the tty port helpers when the modem signals need to be | ||
599 | * adjusted during an open, close and hangup. | ||
600 | */ | ||
601 | |||
602 | static void uart_dtr_rts(struct tty_port *tport, int onoff) | ||
544 | { | 603 | { |
604 | struct sdio_uart_port *port = | ||
605 | container_of(tport, struct sdio_uart_port, port); | ||
606 | int ret = sdio_uart_claim_func(port); | ||
607 | if (ret) | ||
608 | return; | ||
609 | if (onoff == 0) | ||
610 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
611 | else | ||
612 | sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
613 | sdio_uart_release_func(port); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * sdio_uart_activate - start up hardware | ||
618 | * @tport: tty port to activate | ||
619 | * @tty: tty bound to this port | ||
620 | * | ||
621 | * Activate a tty port. The port locking guarantees us this will be | ||
622 | * run exactly once per set of opens, and if successful will see the | ||
623 | * shutdown method run exactly once to match. Start up and shutdown are | ||
624 | * protected from each other by the internal locking and will not run | ||
625 | * at the same time even during a hangup event. | ||
626 | * | ||
627 | * If we successfully start up the port we take an extra kref as we | ||
628 | * will keep it around until shutdown when the kref is dropped. | ||
629 | */ | ||
630 | |||
631 | static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | ||
632 | { | ||
633 | struct sdio_uart_port *port = | ||
634 | container_of(tport, struct sdio_uart_port, port); | ||
545 | unsigned long page; | 635 | unsigned long page; |
546 | int ret; | 636 | int ret; |
547 | 637 | ||
@@ -549,7 +639,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
549 | * Set the TTY IO error marker - we will only clear this | 639 | * Set the TTY IO error marker - we will only clear this |
550 | * once we have successfully opened the port. | 640 | * once we have successfully opened the port. |
551 | */ | 641 | */ |
552 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 642 | set_bit(TTY_IO_ERROR, &tty->flags); |
553 | 643 | ||
554 | /* Initialise and allocate the transmit buffer. */ | 644 | /* Initialise and allocate the transmit buffer. */ |
555 | page = __get_free_page(GFP_KERNEL); | 645 | page = __get_free_page(GFP_KERNEL); |
@@ -574,7 +664,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
574 | */ | 664 | */ |
575 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); | 665 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); |
576 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO | | 666 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO | |
577 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | 667 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); |
578 | sdio_out(port, UART_FCR, 0); | 668 | sdio_out(port, UART_FCR, 0); |
579 | 669 | ||
580 | /* | 670 | /* |
@@ -590,19 +680,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
590 | */ | 680 | */ |
591 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); | 681 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); |
592 | 682 | ||
593 | port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; | 683 | port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; |
594 | port->mctrl = TIOCM_OUT2; | 684 | port->mctrl = TIOCM_OUT2; |
595 | 685 | ||
596 | sdio_uart_change_speed(port, port->tty->termios, NULL); | 686 | sdio_uart_change_speed(port, tty->termios, NULL); |
597 | 687 | ||
598 | if (port->tty->termios->c_cflag & CBAUD) | 688 | if (tty->termios->c_cflag & CBAUD) |
599 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 689 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); |
600 | 690 | ||
601 | if (port->tty->termios->c_cflag & CRTSCTS) | 691 | if (tty->termios->c_cflag & CRTSCTS) |
602 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) | 692 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) |
603 | port->tty->hw_stopped = 1; | 693 | tty->hw_stopped = 1; |
604 | 694 | ||
605 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 695 | clear_bit(TTY_IO_ERROR, &tty->flags); |
606 | 696 | ||
607 | /* Kick the IRQ handler once while we're still holding the host lock */ | 697 | /* Kick the IRQ handler once while we're still holding the host lock */ |
608 | sdio_uart_irq(port->func); | 698 | sdio_uart_irq(port->func); |
@@ -619,8 +709,20 @@ err1: | |||
619 | return ret; | 709 | return ret; |
620 | } | 710 | } |
621 | 711 | ||
622 | static void sdio_uart_shutdown(struct sdio_uart_port *port) | 712 | /** |
713 | * sdio_uart_shutdown - stop hardware | ||
714 | * @tport: tty port to shut down | ||
715 | * | ||
716 | * Deactivate a tty port. The port locking guarantees us this will be | ||
717 | * run only if a successful matching activate already ran. The two are | ||
718 | * protected from each other by the internal locking and will not run | ||
719 | * at the same time even during a hangup event. | ||
720 | */ | ||
721 | |||
722 | static void sdio_uart_shutdown(struct tty_port *tport) | ||
623 | { | 723 | { |
724 | struct sdio_uart_port *port = | ||
725 | container_of(tport, struct sdio_uart_port, port); | ||
624 | int ret; | 726 | int ret; |
625 | 727 | ||
626 | ret = sdio_uart_claim_func(port); | 728 | ret = sdio_uart_claim_func(port); |
@@ -629,13 +731,7 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port) | |||
629 | 731 | ||
630 | sdio_uart_stop_rx(port); | 732 | sdio_uart_stop_rx(port); |
631 | 733 | ||
632 | /* TODO: wait here for TX FIFO to drain */ | 734 | /* Disable interrupts from this port */ |
633 | |||
634 | /* Turn off DTR and RTS early. */ | ||
635 | if (port->tty->termios->c_cflag & HUPCL) | ||
636 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
637 | |||
638 | /* Disable interrupts from this port */ | ||
639 | sdio_release_irq(port->func); | 735 | sdio_release_irq(port->func); |
640 | port->ier = 0; | 736 | port->ier = 0; |
641 | sdio_out(port, UART_IER, 0); | 737 | sdio_out(port, UART_IER, 0); |
@@ -659,77 +755,70 @@ skip: | |||
659 | free_page((unsigned long)port->xmit.buf); | 755 | free_page((unsigned long)port->xmit.buf); |
660 | } | 756 | } |
661 | 757 | ||
662 | static int sdio_uart_open (struct tty_struct *tty, struct file * filp) | 758 | /** |
759 | * sdio_uart_install - install method | ||
760 | * @driver: the driver in use (sdio_uart in our case) | ||
761 | * @tty: the tty being bound | ||
762 | * | ||
763 | * Look up and bind the tty and the driver together. Initialize | ||
764 | * any needed private data (in our case the termios) | ||
765 | */ | ||
766 | |||
767 | static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) | ||
663 | { | 768 | { |
664 | struct sdio_uart_port *port; | 769 | int idx = tty->index; |
665 | int ret; | 770 | struct sdio_uart_port *port = sdio_uart_port_get(idx); |
771 | int ret = tty_init_termios(tty); | ||
772 | |||
773 | if (ret == 0) { | ||
774 | tty_driver_kref_get(driver); | ||
775 | tty->count++; | ||
776 | /* This is the ref sdio_uart_port get provided */ | ||
777 | tty->driver_data = port; | ||
778 | driver->ttys[idx] = tty; | ||
779 | } else | ||
780 | sdio_uart_port_put(port); | ||
781 | return ret; | ||
782 | } | ||
666 | 783 | ||
667 | port = sdio_uart_port_get(tty->index); | 784 | /** |
668 | if (!port) | 785 | * sdio_uart_cleanup - called on the last tty kref drop |
669 | return -ENODEV; | 786 | * @tty: the tty being destroyed |
787 | * | ||
788 | * Called asynchronously when the last reference to the tty is dropped. | ||
789 | * We cannot destroy the tty->driver_data port kref until this point | ||
790 | */ | ||
670 | 791 | ||
671 | mutex_lock(&port->open_lock); | 792 | static void sdio_uart_cleanup(struct tty_struct *tty) |
793 | { | ||
794 | struct sdio_uart_port *port = tty->driver_data; | ||
795 | tty->driver_data = NULL; /* Bug trap */ | ||
796 | sdio_uart_port_put(port); | ||
797 | } | ||
672 | 798 | ||
673 | /* | 799 | /* |
674 | * Make sure not to mess up with a dead port | 800 | * Open/close/hangup is now entirely boilerplate |
675 | * which has not been closed yet. | 801 | */ |
676 | */ | ||
677 | if (tty->driver_data && tty->driver_data != port) { | ||
678 | mutex_unlock(&port->open_lock); | ||
679 | sdio_uart_port_put(port); | ||
680 | return -EBUSY; | ||
681 | } | ||
682 | 802 | ||
683 | if (!port->opened) { | 803 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) |
684 | tty->driver_data = port; | 804 | { |
685 | port->tty = tty; | 805 | struct sdio_uart_port *port = tty->driver_data; |
686 | ret = sdio_uart_startup(port); | 806 | return tty_port_open(&port->port, tty, filp); |
687 | if (ret) { | ||
688 | tty->driver_data = NULL; | ||
689 | port->tty = NULL; | ||
690 | mutex_unlock(&port->open_lock); | ||
691 | sdio_uart_port_put(port); | ||
692 | return ret; | ||
693 | } | ||
694 | } | ||
695 | port->opened++; | ||
696 | mutex_unlock(&port->open_lock); | ||
697 | return 0; | ||
698 | } | 807 | } |
699 | 808 | ||
700 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) | 809 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) |
701 | { | 810 | { |
702 | struct sdio_uart_port *port = tty->driver_data; | 811 | struct sdio_uart_port *port = tty->driver_data; |
812 | tty_port_close(&port->port, tty, filp); | ||
813 | } | ||
703 | 814 | ||
704 | if (!port) | 815 | static void sdio_uart_hangup(struct tty_struct *tty) |
705 | return; | 816 | { |
706 | 817 | struct sdio_uart_port *port = tty->driver_data; | |
707 | mutex_lock(&port->open_lock); | 818 | tty_port_hangup(&port->port); |
708 | BUG_ON(!port->opened); | ||
709 | |||
710 | /* | ||
711 | * This is messy. The tty layer calls us even when open() | ||
712 | * returned an error. Ignore this close request if tty->count | ||
713 | * is larger than port->count. | ||
714 | */ | ||
715 | if (tty->count > port->opened) { | ||
716 | mutex_unlock(&port->open_lock); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | if (--port->opened == 0) { | ||
721 | tty->closing = 1; | ||
722 | sdio_uart_shutdown(port); | ||
723 | tty_ldisc_flush(tty); | ||
724 | port->tty = NULL; | ||
725 | tty->driver_data = NULL; | ||
726 | tty->closing = 0; | ||
727 | } | ||
728 | mutex_unlock(&port->open_lock); | ||
729 | sdio_uart_port_put(port); | ||
730 | } | 819 | } |
731 | 820 | ||
732 | static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | 821 | static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, |
733 | int count) | 822 | int count) |
734 | { | 823 | { |
735 | struct sdio_uart_port *port = tty->driver_data; | 824 | struct sdio_uart_port *port = tty->driver_data; |
@@ -754,7 +843,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | |||
754 | } | 843 | } |
755 | spin_unlock(&port->write_lock); | 844 | spin_unlock(&port->write_lock); |
756 | 845 | ||
757 | if ( !(port->ier & UART_IER_THRI)) { | 846 | if (!(port->ier & UART_IER_THRI)) { |
758 | int err = sdio_uart_claim_func(port); | 847 | int err = sdio_uart_claim_func(port); |
759 | if (!err) { | 848 | if (!err) { |
760 | sdio_uart_start_tx(port); | 849 | sdio_uart_start_tx(port); |
@@ -841,17 +930,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) | |||
841 | sdio_uart_release_func(port); | 930 | sdio_uart_release_func(port); |
842 | } | 931 | } |
843 | 932 | ||
844 | static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 933 | static void sdio_uart_set_termios(struct tty_struct *tty, |
934 | struct ktermios *old_termios) | ||
845 | { | 935 | { |
846 | struct sdio_uart_port *port = tty->driver_data; | 936 | struct sdio_uart_port *port = tty->driver_data; |
847 | unsigned int cflag = tty->termios->c_cflag; | 937 | unsigned int cflag = tty->termios->c_cflag; |
848 | 938 | ||
849 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
850 | |||
851 | if ((cflag ^ old_termios->c_cflag) == 0 && | ||
852 | RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) | ||
853 | return; | ||
854 | |||
855 | if (sdio_uart_claim_func(port) != 0) | 939 | if (sdio_uart_claim_func(port) != 0) |
856 | return; | 940 | return; |
857 | 941 | ||
@@ -925,8 +1009,8 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
925 | struct sdio_uart_port *port = tty->driver_data; | 1009 | struct sdio_uart_port *port = tty->driver_data; |
926 | int result; | 1010 | int result; |
927 | 1011 | ||
928 | result =sdio_uart_claim_func(port); | 1012 | result = sdio_uart_claim_func(port); |
929 | if(!result) { | 1013 | if (!result) { |
930 | sdio_uart_update_mctrl(port, set, clear); | 1014 | sdio_uart_update_mctrl(port, set, clear); |
931 | sdio_uart_release_func(port); | 1015 | sdio_uart_release_func(port); |
932 | } | 1016 | } |
@@ -944,33 +1028,33 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v) | |||
944 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 1028 | struct sdio_uart_port *port = sdio_uart_port_get(i); |
945 | if (port) { | 1029 | if (port) { |
946 | seq_printf(m, "%d: uart:SDIO", i); | 1030 | seq_printf(m, "%d: uart:SDIO", i); |
947 | if(capable(CAP_SYS_ADMIN)) { | 1031 | if (capable(CAP_SYS_ADMIN)) { |
948 | seq_printf(m, " tx:%d rx:%d", | 1032 | seq_printf(m, " tx:%d rx:%d", |
949 | port->icount.tx, port->icount.rx); | 1033 | port->icount.tx, port->icount.rx); |
950 | if (port->icount.frame) | 1034 | if (port->icount.frame) |
951 | seq_printf(m, " fe:%d", | 1035 | seq_printf(m, " fe:%d", |
952 | port->icount.frame); | 1036 | port->icount.frame); |
953 | if (port->icount.parity) | 1037 | if (port->icount.parity) |
954 | seq_printf(m, " pe:%d", | 1038 | seq_printf(m, " pe:%d", |
955 | port->icount.parity); | 1039 | port->icount.parity); |
956 | if (port->icount.brk) | 1040 | if (port->icount.brk) |
957 | seq_printf(m, " brk:%d", | 1041 | seq_printf(m, " brk:%d", |
958 | port->icount.brk); | 1042 | port->icount.brk); |
959 | if (port->icount.overrun) | 1043 | if (port->icount.overrun) |
960 | seq_printf(m, " oe:%d", | 1044 | seq_printf(m, " oe:%d", |
961 | port->icount.overrun); | 1045 | port->icount.overrun); |
962 | if (port->icount.cts) | 1046 | if (port->icount.cts) |
963 | seq_printf(m, " cts:%d", | 1047 | seq_printf(m, " cts:%d", |
964 | port->icount.cts); | 1048 | port->icount.cts); |
965 | if (port->icount.dsr) | 1049 | if (port->icount.dsr) |
966 | seq_printf(m, " dsr:%d", | 1050 | seq_printf(m, " dsr:%d", |
967 | port->icount.dsr); | 1051 | port->icount.dsr); |
968 | if (port->icount.rng) | 1052 | if (port->icount.rng) |
969 | seq_printf(m, " rng:%d", | 1053 | seq_printf(m, " rng:%d", |
970 | port->icount.rng); | 1054 | port->icount.rng); |
971 | if (port->icount.dcd) | 1055 | if (port->icount.dcd) |
972 | seq_printf(m, " dcd:%d", | 1056 | seq_printf(m, " dcd:%d", |
973 | port->icount.dcd); | 1057 | port->icount.dcd); |
974 | } | 1058 | } |
975 | sdio_uart_port_put(port); | 1059 | sdio_uart_port_put(port); |
976 | seq_putc(m, '\n'); | 1060 | seq_putc(m, '\n'); |
@@ -992,6 +1076,13 @@ static const struct file_operations sdio_uart_proc_fops = { | |||
992 | .release = single_release, | 1076 | .release = single_release, |
993 | }; | 1077 | }; |
994 | 1078 | ||
1079 | static const struct tty_port_operations sdio_uart_port_ops = { | ||
1080 | .dtr_rts = uart_dtr_rts, | ||
1081 | .carrier_raised = uart_carrier_raised, | ||
1082 | .shutdown = sdio_uart_shutdown, | ||
1083 | .activate = sdio_uart_activate, | ||
1084 | }; | ||
1085 | |||
995 | static const struct tty_operations sdio_uart_ops = { | 1086 | static const struct tty_operations sdio_uart_ops = { |
996 | .open = sdio_uart_open, | 1087 | .open = sdio_uart_open, |
997 | .close = sdio_uart_close, | 1088 | .close = sdio_uart_close, |
@@ -1002,9 +1093,12 @@ static const struct tty_operations sdio_uart_ops = { | |||
1002 | .throttle = sdio_uart_throttle, | 1093 | .throttle = sdio_uart_throttle, |
1003 | .unthrottle = sdio_uart_unthrottle, | 1094 | .unthrottle = sdio_uart_unthrottle, |
1004 | .set_termios = sdio_uart_set_termios, | 1095 | .set_termios = sdio_uart_set_termios, |
1096 | .hangup = sdio_uart_hangup, | ||
1005 | .break_ctl = sdio_uart_break_ctl, | 1097 | .break_ctl = sdio_uart_break_ctl, |
1006 | .tiocmget = sdio_uart_tiocmget, | 1098 | .tiocmget = sdio_uart_tiocmget, |
1007 | .tiocmset = sdio_uart_tiocmset, | 1099 | .tiocmset = sdio_uart_tiocmset, |
1100 | .install = sdio_uart_install, | ||
1101 | .cleanup = sdio_uart_cleanup, | ||
1008 | .proc_fops = &sdio_uart_proc_fops, | 1102 | .proc_fops = &sdio_uart_proc_fops, |
1009 | }; | 1103 | }; |
1010 | 1104 | ||
@@ -1041,7 +1135,7 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1041 | } | 1135 | } |
1042 | if (!tpl) { | 1136 | if (!tpl) { |
1043 | printk(KERN_WARNING | 1137 | printk(KERN_WARNING |
1044 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", | 1138 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", |
1045 | sdio_func_id(func)); | 1139 | sdio_func_id(func)); |
1046 | kfree(port); | 1140 | kfree(port); |
1047 | return -EINVAL; | 1141 | return -EINVAL; |
@@ -1066,13 +1160,16 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1066 | 1160 | ||
1067 | port->func = func; | 1161 | port->func = func; |
1068 | sdio_set_drvdata(func, port); | 1162 | sdio_set_drvdata(func, port); |
1163 | tty_port_init(&port->port); | ||
1164 | port->port.ops = &sdio_uart_port_ops; | ||
1069 | 1165 | ||
1070 | ret = sdio_uart_add_port(port); | 1166 | ret = sdio_uart_add_port(port); |
1071 | if (ret) { | 1167 | if (ret) { |
1072 | kfree(port); | 1168 | kfree(port); |
1073 | } else { | 1169 | } else { |
1074 | struct device *dev; | 1170 | struct device *dev; |
1075 | dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev); | 1171 | dev = tty_register_device(sdio_uart_tty_driver, |
1172 | port->index, &func->dev); | ||
1076 | if (IS_ERR(dev)) { | 1173 | if (IS_ERR(dev)) { |
1077 | sdio_uart_port_remove(port); | 1174 | sdio_uart_port_remove(port); |
1078 | ret = PTR_ERR(dev); | 1175 | ret = PTR_ERR(dev); |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 432ae8358c86..e04b751680d0 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -329,7 +329,7 @@ config MMC_SDRICOH_CS | |||
329 | 329 | ||
330 | config MMC_TMIO | 330 | config MMC_TMIO |
331 | tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" | 331 | tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" |
332 | depends on MFD_TMIO || MFD_ASIC3 | 332 | depends on MFD_TMIO || MFD_ASIC3 || SUPERH |
333 | help | 333 | help |
334 | This provides support for the SD/MMC cell found in TC6393XB, | 334 | This provides support for the SD/MMC cell found in TC6393XB, |
335 | T7L66XB and also HTC ASIC3 | 335 | T7L66XB and also HTC ASIC3 |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 705a5894a6bb..90d168ad03b6 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -56,7 +56,7 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
56 | clk = 255; | 56 | clk = 255; |
57 | host->cclk = host->mclk / (2 * (clk + 1)); | 57 | host->cclk = host->mclk / (2 * (clk + 1)); |
58 | } | 58 | } |
59 | if (host->hw_designer == 0x80) | 59 | if (host->hw_designer == AMBA_VENDOR_ST) |
60 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ | 60 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ |
61 | clk |= MCI_CLK_ENABLE; | 61 | clk |= MCI_CLK_ENABLE; |
62 | /* This hasn't proven to be worthwhile */ | 62 | /* This hasn't proven to be worthwhile */ |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index dba4600bcdb4..b31946e0b4ca 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -38,10 +38,9 @@ | |||
38 | #include <asm/div64.h> | 38 | #include <asm/div64.h> |
39 | #include <asm/sizes.h> | 39 | #include <asm/sizes.h> |
40 | 40 | ||
41 | #include <asm/mach/mmc.h> | 41 | #include <mach/mmc.h> |
42 | #include <mach/msm_iomap.h> | 42 | #include <mach/msm_iomap.h> |
43 | #include <mach/dma.h> | 43 | #include <mach/dma.h> |
44 | #include <mach/htc_pwrsink.h> | ||
45 | 44 | ||
46 | #include "msm_sdcc.h" | 45 | #include "msm_sdcc.h" |
47 | 46 | ||
@@ -775,13 +774,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
775 | 774 | ||
776 | switch (ios->power_mode) { | 775 | switch (ios->power_mode) { |
777 | case MMC_POWER_OFF: | 776 | case MMC_POWER_OFF: |
778 | htc_pwrsink_set(PWRSINK_SDCARD, 0); | ||
779 | break; | 777 | break; |
780 | case MMC_POWER_UP: | 778 | case MMC_POWER_UP: |
781 | pwr |= MCI_PWR_UP; | 779 | pwr |= MCI_PWR_UP; |
782 | break; | 780 | break; |
783 | case MMC_POWER_ON: | 781 | case MMC_POWER_ON: |
784 | htc_pwrsink_set(PWRSINK_SDCARD, 100); | ||
785 | pwr |= MCI_PWR_ON; | 782 | pwr |= MCI_PWR_ON; |
786 | break; | 783 | break; |
787 | } | 784 | } |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index b8fd7af1ceeb..5f970e253e50 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -30,12 +30,12 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
32 | 32 | ||
33 | #include <mach/board.h> | 33 | #include <plat/board.h> |
34 | #include <mach/mmc.h> | 34 | #include <plat/mmc.h> |
35 | #include <mach/gpio.h> | 35 | #include <mach/gpio.h> |
36 | #include <mach/dma.h> | 36 | #include <plat/dma.h> |
37 | #include <mach/mux.h> | 37 | #include <plat/mux.h> |
38 | #include <mach/fpga.h> | 38 | #include <plat/fpga.h> |
39 | 39 | ||
40 | #define OMAP_MMC_REG_CMD 0x00 | 40 | #define OMAP_MMC_REG_CMD 0x00 |
41 | #define OMAP_MMC_REG_ARGL 0x04 | 41 | #define OMAP_MMC_REG_ARGL 0x04 |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0aecaaebef3d..4b2322518909 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -30,11 +30,11 @@ | |||
30 | #include <linux/mmc/core.h> | 30 | #include <linux/mmc/core.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/semaphore.h> | 32 | #include <linux/semaphore.h> |
33 | #include <mach/dma.h> | 33 | #include <plat/dma.h> |
34 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
35 | #include <mach/board.h> | 35 | #include <plat/board.h> |
36 | #include <mach/mmc.h> | 36 | #include <plat/mmc.h> |
37 | #include <mach/cpu.h> | 37 | #include <plat/cpu.h> |
38 | 38 | ||
39 | /* OMAP HSMMC Host Controller Registers */ | 39 | /* OMAP HSMMC Host Controller Registers */ |
40 | #define OMAP_HSMMC_SYSCONFIG 0x0010 | 40 | #define OMAP_HSMMC_SYSCONFIG 0x0010 |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index b00d67319058..bb47ff465c04 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -43,6 +43,9 @@ | |||
43 | #define NR_SG 1 | 43 | #define NR_SG 1 |
44 | #define CLKRT_OFF (~0) | 44 | #define CLKRT_OFF (~0) |
45 | 45 | ||
46 | #define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310() \ | ||
47 | || cpu_is_pxa935()) | ||
48 | |||
46 | struct pxamci_host { | 49 | struct pxamci_host { |
47 | struct mmc_host *mmc; | 50 | struct mmc_host *mmc; |
48 | spinlock_t lock; | 51 | spinlock_t lock; |
@@ -457,7 +460,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
457 | clk_enable(host->clk); | 460 | clk_enable(host->clk); |
458 | 461 | ||
459 | if (ios->clock == 26000000) { | 462 | if (ios->clock == 26000000) { |
460 | /* to support 26MHz on pxa300/pxa310 */ | 463 | /* to support 26MHz */ |
461 | host->clkrt = 7; | 464 | host->clkrt = 7; |
462 | } else { | 465 | } else { |
463 | /* to handle (19.5MHz, 26MHz) */ | 466 | /* to handle (19.5MHz, 26MHz) */ |
@@ -608,8 +611,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
608 | * Calculate minimum clock rate, rounding up. | 611 | * Calculate minimum clock rate, rounding up. |
609 | */ | 612 | */ |
610 | mmc->f_min = (host->clkrate + 63) / 64; | 613 | mmc->f_min = (host->clkrate + 63) / 64; |
611 | mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000 | 614 | mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate; |
612 | : host->clkrate; | ||
613 | 615 | ||
614 | pxamci_init_ocr(host); | 616 | pxamci_init_ocr(host); |
615 | 617 | ||
@@ -618,7 +620,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
618 | if (!cpu_is_pxa25x()) { | 620 | if (!cpu_is_pxa25x()) { |
619 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 621 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
620 | host->cmdat |= CMDAT_SDIO_INT_EN; | 622 | host->cmdat |= CMDAT_SDIO_INT_EN; |
621 | if (cpu_is_pxa300() || cpu_is_pxa310()) | 623 | if (mmc_has_26MHz()) |
622 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | | 624 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | |
623 | MMC_CAP_SD_HIGHSPEED; | 625 | MMC_CAP_SD_HIGHSPEED; |
624 | } | 626 | } |
@@ -760,6 +762,8 @@ static int pxamci_remove(struct platform_device *pdev) | |||
760 | if (mmc) { | 762 | if (mmc) { |
761 | struct pxamci_host *host = mmc_priv(mmc); | 763 | struct pxamci_host *host = mmc_priv(mmc); |
762 | 764 | ||
765 | mmc_remove_host(mmc); | ||
766 | |||
763 | if (host->pdata) { | 767 | if (host->pdata) { |
764 | gpio_cd = host->pdata->gpio_card_detect; | 768 | gpio_cd = host->pdata->gpio_card_detect; |
765 | gpio_ro = host->pdata->gpio_card_ro; | 769 | gpio_ro = host->pdata->gpio_card_ro; |
@@ -779,8 +783,6 @@ static int pxamci_remove(struct platform_device *pdev) | |||
779 | if (host->pdata && host->pdata->exit) | 783 | if (host->pdata && host->pdata->exit) |
780 | host->pdata->exit(&pdev->dev, mmc); | 784 | host->pdata->exit(&pdev->dev, mmc); |
781 | 785 | ||
782 | mmc_remove_host(mmc); | ||
783 | |||
784 | pxamci_stop_clock(host); | 786 | pxamci_stop_clock(host); |
785 | writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| | 787 | writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| |
786 | END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, | 788 | END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 99b74a351020..941a4d35ef8d 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -1360,7 +1360,7 @@ static struct mmc_host_ops s3cmci_ops = { | |||
1360 | 1360 | ||
1361 | static struct s3c24xx_mci_pdata s3cmci_def_pdata = { | 1361 | static struct s3c24xx_mci_pdata s3cmci_def_pdata = { |
1362 | /* This is currently here to avoid a number of if (host->pdata) | 1362 | /* This is currently here to avoid a number of if (host->pdata) |
1363 | * checks. Any zero fields to ensure reaonable defaults are picked. */ | 1363 | * checks. Any zero fields to ensure reasonable defaults are picked. */ |
1364 | }; | 1364 | }; |
1365 | 1365 | ||
1366 | #ifdef CONFIG_CPU_FREQ | 1366 | #ifdef CONFIG_CPU_FREQ |