1167 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SDIO UART/GPS driver4 *5 * Based on drivers/serial/8250.c and drivers/serial/serial_core.c6 * by Russell King.7 *8 * Author: Nicolas Pitre9 * Created: June 15, 200710 * Copyright: MontaVista Software, Inc.11 */12 13/*14 * Note: Although this driver assumes a 16550A-like UART implementation,15 * it is not possible to leverage the common 8250/16550 driver, nor the16 * core UART infrastructure, as they assumes direct access to the hardware17 * registers, often under a spinlock. This is not possible in the SDIO18 * context as SDIO access functions must be able to sleep.19 *20 * Because we need to lock the SDIO host to ensure an exclusive access to21 * the card, we simply rely on that lock to also prevent and serialize22 * concurrent access to the same port.23 */24 25#include <linux/module.h>26#include <linux/init.h>27#include <linux/kernel.h>28#include <linux/sched.h>29#include <linux/mutex.h>30#include <linux/seq_file.h>31#include <linux/serial.h>32#include <linux/serial_reg.h>33#include <linux/circ_buf.h>34#include <linux/tty.h>35#include <linux/tty_flip.h>36#include <linux/kfifo.h>37#include <linux/slab.h>38 39#include <linux/mmc/core.h>40#include <linux/mmc/card.h>41#include <linux/mmc/sdio_func.h>42#include <linux/mmc/sdio_ids.h>43 44 45#define UART_NR 8 /* Number of UARTs this driver can handle */46 47 48#define FIFO_SIZE PAGE_SIZE49#define WAKEUP_CHARS 25650 51struct uart_icount {52 __u32 cts;53 __u32 dsr;54 __u32 rng;55 __u32 dcd;56 __u32 rx;57 __u32 tx;58 __u32 frame;59 __u32 overrun;60 __u32 parity;61 __u32 brk;62};63 64struct sdio_uart_port {65 struct tty_port port;66 unsigned int index;67 struct sdio_func *func;68 struct mutex func_lock;69 struct task_struct *in_sdio_uart_irq;70 unsigned int regs_offset;71 struct kfifo xmit_fifo;72 spinlock_t write_lock;73 struct uart_icount icount;74 unsigned int uartclk;75 unsigned int mctrl;76 unsigned int rx_mctrl;77 unsigned int read_status_mask;78 unsigned int ignore_status_mask;79 unsigned char x_char;80 unsigned char ier;81 unsigned char lcr;82};83 84static struct sdio_uart_port *sdio_uart_table[UART_NR];85static DEFINE_SPINLOCK(sdio_uart_table_lock);86 87static int sdio_uart_add_port(struct sdio_uart_port *port)88{89 int index, ret = -EBUSY;90 91 mutex_init(&port->func_lock);92 spin_lock_init(&port->write_lock);93 if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))94 return -ENOMEM;95 96 spin_lock(&sdio_uart_table_lock);97 for (index = 0; index < UART_NR; index++) {98 if (!sdio_uart_table[index]) {99 port->index = index;100 sdio_uart_table[index] = port;101 ret = 0;102 break;103 }104 }105 spin_unlock(&sdio_uart_table_lock);106 107 return ret;108}109 110static struct sdio_uart_port *sdio_uart_port_get(unsigned index)111{112 struct sdio_uart_port *port;113 114 if (index >= UART_NR)115 return NULL;116 117 spin_lock(&sdio_uart_table_lock);118 port = sdio_uart_table[index];119 if (port)120 tty_port_get(&port->port);121 spin_unlock(&sdio_uart_table_lock);122 123 return port;124}125 126static void sdio_uart_port_put(struct sdio_uart_port *port)127{128 tty_port_put(&port->port);129}130 131static void sdio_uart_port_remove(struct sdio_uart_port *port)132{133 struct sdio_func *func;134 135 spin_lock(&sdio_uart_table_lock);136 sdio_uart_table[port->index] = NULL;137 spin_unlock(&sdio_uart_table_lock);138 139 /*140 * We're killing a port that potentially still is in use by141 * the tty layer. Be careful to prevent any further access142 * to the SDIO function and arrange for the tty layer to143 * give up on that port ASAP.144 * Beware: the lock ordering is critical.145 */146 mutex_lock(&port->port.mutex);147 mutex_lock(&port->func_lock);148 func = port->func;149 sdio_claim_host(func);150 port->func = NULL;151 mutex_unlock(&port->func_lock);152 /* tty_hangup is async so is this safe as is ?? */153 tty_port_tty_hangup(&port->port, false);154 mutex_unlock(&port->port.mutex);155 sdio_release_irq(func);156 sdio_disable_func(func);157 sdio_release_host(func);158 159 sdio_uart_port_put(port);160}161 162static int sdio_uart_claim_func(struct sdio_uart_port *port)163{164 mutex_lock(&port->func_lock);165 if (unlikely(!port->func)) {166 mutex_unlock(&port->func_lock);167 return -ENODEV;168 }169 if (likely(port->in_sdio_uart_irq != current))170 sdio_claim_host(port->func);171 mutex_unlock(&port->func_lock);172 return 0;173}174 175static inline void sdio_uart_release_func(struct sdio_uart_port *port)176{177 if (likely(port->in_sdio_uart_irq != current))178 sdio_release_host(port->func);179}180 181static inline u8 sdio_in(struct sdio_uart_port *port, int offset)182{183 return sdio_readb(port->func, port->regs_offset + offset, NULL);184}185 186static inline void sdio_out(struct sdio_uart_port *port, int offset, int value)187{188 sdio_writeb(port->func, value, port->regs_offset + offset, NULL);189}190 191static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port)192{193 unsigned int ret;194 u8 status;195 196 /* FIXME: What stops this losing the delta bits and breaking197 sdio_uart_check_modem_status ? */198 status = sdio_in(port, UART_MSR);199 200 ret = 0;201 if (status & UART_MSR_DCD)202 ret |= TIOCM_CAR;203 if (status & UART_MSR_RI)204 ret |= TIOCM_RNG;205 if (status & UART_MSR_DSR)206 ret |= TIOCM_DSR;207 if (status & UART_MSR_CTS)208 ret |= TIOCM_CTS;209 return ret;210}211 212static void sdio_uart_write_mctrl(struct sdio_uart_port *port,213 unsigned int mctrl)214{215 unsigned char mcr = 0;216 217 if (mctrl & TIOCM_RTS)218 mcr |= UART_MCR_RTS;219 if (mctrl & TIOCM_DTR)220 mcr |= UART_MCR_DTR;221 if (mctrl & TIOCM_OUT1)222 mcr |= UART_MCR_OUT1;223 if (mctrl & TIOCM_OUT2)224 mcr |= UART_MCR_OUT2;225 if (mctrl & TIOCM_LOOP)226 mcr |= UART_MCR_LOOP;227 228 sdio_out(port, UART_MCR, mcr);229}230 231static inline void sdio_uart_update_mctrl(struct sdio_uart_port *port,232 unsigned int set, unsigned int clear)233{234 unsigned int old;235 236 old = port->mctrl;237 port->mctrl = (old & ~clear) | set;238 if (old != port->mctrl)239 sdio_uart_write_mctrl(port, port->mctrl);240}241 242#define sdio_uart_set_mctrl(port, x) sdio_uart_update_mctrl(port, x, 0)243#define sdio_uart_clear_mctrl(port, x) sdio_uart_update_mctrl(port, 0, x)244 245static void sdio_uart_change_speed(struct sdio_uart_port *port,246 struct ktermios *termios,247 const struct ktermios *old)248{249 unsigned char cval, fcr = 0;250 unsigned int baud, quot;251 252 cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));253 254 if (termios->c_cflag & CSTOPB)255 cval |= UART_LCR_STOP;256 if (termios->c_cflag & PARENB)257 cval |= UART_LCR_PARITY;258 if (!(termios->c_cflag & PARODD))259 cval |= UART_LCR_EPAR;260 261 for (;;) {262 baud = tty_termios_baud_rate(termios);263 if (baud == 0)264 baud = 9600; /* Special case: B0 rate. */265 if (baud <= port->uartclk)266 break;267 /*268 * Oops, the quotient was zero. Try again with the old269 * baud rate if possible, otherwise default to 9600.270 */271 termios->c_cflag &= ~CBAUD;272 if (old) {273 termios->c_cflag |= old->c_cflag & CBAUD;274 old = NULL;275 } else276 termios->c_cflag |= B9600;277 }278 quot = (2 * port->uartclk + baud) / (2 * baud);279 280 if (baud < 2400)281 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;282 else283 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;284 285 port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;286 if (termios->c_iflag & INPCK)287 port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;288 if (termios->c_iflag & (BRKINT | PARMRK))289 port->read_status_mask |= UART_LSR_BI;290 291 /*292 * Characters to ignore293 */294 port->ignore_status_mask = 0;295 if (termios->c_iflag & IGNPAR)296 port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;297 if (termios->c_iflag & IGNBRK) {298 port->ignore_status_mask |= UART_LSR_BI;299 /*300 * If we're ignoring parity and break indicators,301 * ignore overruns too (for real raw support).302 */303 if (termios->c_iflag & IGNPAR)304 port->ignore_status_mask |= UART_LSR_OE;305 }306 307 /*308 * ignore all characters if CREAD is not set309 */310 if ((termios->c_cflag & CREAD) == 0)311 port->ignore_status_mask |= UART_LSR_DR;312 313 /*314 * CTS flow control flag and modem status interrupts315 */316 port->ier &= ~UART_IER_MSI;317 if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))318 port->ier |= UART_IER_MSI;319 320 port->lcr = cval;321 322 sdio_out(port, UART_IER, port->ier);323 sdio_out(port, UART_LCR, cval | UART_LCR_DLAB);324 sdio_out(port, UART_DLL, quot & 0xff);325 sdio_out(port, UART_DLM, quot >> 8);326 sdio_out(port, UART_LCR, cval);327 sdio_out(port, UART_FCR, fcr);328 329 sdio_uart_write_mctrl(port, port->mctrl);330}331 332static void sdio_uart_start_tx(struct sdio_uart_port *port)333{334 if (!(port->ier & UART_IER_THRI)) {335 port->ier |= UART_IER_THRI;336 sdio_out(port, UART_IER, port->ier);337 }338}339 340static void sdio_uart_stop_tx(struct sdio_uart_port *port)341{342 if (port->ier & UART_IER_THRI) {343 port->ier &= ~UART_IER_THRI;344 sdio_out(port, UART_IER, port->ier);345 }346}347 348static void sdio_uart_stop_rx(struct sdio_uart_port *port)349{350 port->ier &= ~UART_IER_RLSI;351 port->read_status_mask &= ~UART_LSR_DR;352 sdio_out(port, UART_IER, port->ier);353}354 355static void sdio_uart_receive_chars(struct sdio_uart_port *port, u8 *status)356{357 int max_count = 256;358 359 do {360 u8 ch = sdio_in(port, UART_RX);361 u8 flag = TTY_NORMAL;362 port->icount.rx++;363 364 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |365 UART_LSR_FE | UART_LSR_OE))) {366 /*367 * For statistics only368 */369 if (*status & UART_LSR_BI) {370 *status &= ~(UART_LSR_FE | UART_LSR_PE);371 port->icount.brk++;372 } else if (*status & UART_LSR_PE)373 port->icount.parity++;374 else if (*status & UART_LSR_FE)375 port->icount.frame++;376 if (*status & UART_LSR_OE)377 port->icount.overrun++;378 379 /*380 * Mask off conditions which should be ignored.381 */382 *status &= port->read_status_mask;383 if (*status & UART_LSR_BI)384 flag = TTY_BREAK;385 else if (*status & UART_LSR_PE)386 flag = TTY_PARITY;387 else if (*status & UART_LSR_FE)388 flag = TTY_FRAME;389 }390 391 if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)392 tty_insert_flip_char(&port->port, ch, flag);393 394 /*395 * Overrun is special. Since it's reported immediately,396 * it doesn't affect the current character.397 */398 if (*status & ~port->ignore_status_mask & UART_LSR_OE)399 tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);400 401 *status = sdio_in(port, UART_LSR);402 } while ((*status & UART_LSR_DR) && (max_count-- > 0));403 404 tty_flip_buffer_push(&port->port);405}406 407static void sdio_uart_transmit_chars(struct sdio_uart_port *port)408{409 struct kfifo *xmit = &port->xmit_fifo;410 int count;411 struct tty_struct *tty;412 u8 iobuf[16];413 int len;414 415 if (port->x_char) {416 sdio_out(port, UART_TX, port->x_char);417 port->icount.tx++;418 port->x_char = 0;419 return;420 }421 422 tty = tty_port_tty_get(&port->port);423 424 if (tty == NULL || !kfifo_len(xmit) ||425 tty->flow.stopped || tty->hw_stopped) {426 sdio_uart_stop_tx(port);427 tty_kref_put(tty);428 return;429 }430 431 len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock);432 for (count = 0; count < len; count++) {433 sdio_out(port, UART_TX, iobuf[count]);434 port->icount.tx++;435 }436 437 len = kfifo_len(xmit);438 if (len < WAKEUP_CHARS) {439 tty_wakeup(tty);440 if (len == 0)441 sdio_uart_stop_tx(port);442 }443 tty_kref_put(tty);444}445 446static void sdio_uart_check_modem_status(struct sdio_uart_port *port)447{448 struct tty_struct *tty;449 u8 status;450 451 status = sdio_in(port, UART_MSR);452 453 if ((status & UART_MSR_ANY_DELTA) == 0)454 return;455 456 if (status & UART_MSR_TERI)457 port->icount.rng++;458 if (status & UART_MSR_DDSR)459 port->icount.dsr++;460 if (status & UART_MSR_DDCD) {461 port->icount.dcd++;462 /* DCD raise - wake for open */463 if (status & UART_MSR_DCD)464 wake_up_interruptible(&port->port.open_wait);465 else {466 /* DCD drop - hang up if tty attached */467 tty_port_tty_hangup(&port->port, false);468 }469 }470 if (status & UART_MSR_DCTS) {471 port->icount.cts++;472 tty = tty_port_tty_get(&port->port);473 if (tty && C_CRTSCTS(tty)) {474 int cts = (status & UART_MSR_CTS);475 if (tty->hw_stopped) {476 if (cts) {477 tty->hw_stopped = false;478 sdio_uart_start_tx(port);479 tty_wakeup(tty);480 }481 } else {482 if (!cts) {483 tty->hw_stopped = true;484 sdio_uart_stop_tx(port);485 }486 }487 }488 tty_kref_put(tty);489 }490}491 492/*493 * This handles the interrupt from one port.494 */495static void sdio_uart_irq(struct sdio_func *func)496{497 struct sdio_uart_port *port = sdio_get_drvdata(func);498 u8 iir, lsr;499 500 /*501 * In a few places sdio_uart_irq() is called directly instead of502 * waiting for the actual interrupt to be raised and the SDIO IRQ503 * thread scheduled in order to reduce latency. However, some504 * interaction with the tty core may end up calling us back505 * (serial echo, flow control, etc.) through those same places506 * causing undesirable effects. Let's stop the recursion here.507 */508 if (unlikely(port->in_sdio_uart_irq == current))509 return;510 511 iir = sdio_in(port, UART_IIR);512 if (iir & UART_IIR_NO_INT)513 return;514 515 port->in_sdio_uart_irq = current;516 lsr = sdio_in(port, UART_LSR);517 if (lsr & UART_LSR_DR)518 sdio_uart_receive_chars(port, &lsr);519 sdio_uart_check_modem_status(port);520 if (lsr & UART_LSR_THRE)521 sdio_uart_transmit_chars(port);522 port->in_sdio_uart_irq = NULL;523}524 525static bool uart_carrier_raised(struct tty_port *tport)526{527 struct sdio_uart_port *port =528 container_of(tport, struct sdio_uart_port, port);529 unsigned int ret = sdio_uart_claim_func(port);530 if (ret) /* Missing hardware shouldn't block for carrier */531 return 1;532 ret = sdio_uart_get_mctrl(port);533 sdio_uart_release_func(port);534 535 return ret & TIOCM_CAR;536}537 538/**539 * uart_dtr_rts - port helper to set uart signals540 * @tport: tty port to be updated541 * @active: set to turn on DTR/RTS542 *543 * Called by the tty port helpers when the modem signals need to be544 * adjusted during an open, close and hangup.545 */546 547static void uart_dtr_rts(struct tty_port *tport, bool active)548{549 struct sdio_uart_port *port =550 container_of(tport, struct sdio_uart_port, port);551 int ret = sdio_uart_claim_func(port);552 if (ret)553 return;554 if (!active)555 sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);556 else557 sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);558 sdio_uart_release_func(port);559}560 561/**562 * sdio_uart_activate - start up hardware563 * @tport: tty port to activate564 * @tty: tty bound to this port565 *566 * Activate a tty port. The port locking guarantees us this will be567 * run exactly once per set of opens, and if successful will see the568 * shutdown method run exactly once to match. Start up and shutdown are569 * protected from each other by the internal locking and will not run570 * at the same time even during a hangup event.571 *572 * If we successfully start up the port we take an extra kref as we573 * will keep it around until shutdown when the kref is dropped.574 */575 576static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)577{578 struct sdio_uart_port *port =579 container_of(tport, struct sdio_uart_port, port);580 int ret;581 582 /*583 * Set the TTY IO error marker - we will only clear this584 * once we have successfully opened the port.585 */586 set_bit(TTY_IO_ERROR, &tty->flags);587 588 kfifo_reset(&port->xmit_fifo);589 590 ret = sdio_uart_claim_func(port);591 if (ret)592 return ret;593 ret = sdio_enable_func(port->func);594 if (ret)595 goto err1;596 ret = sdio_claim_irq(port->func, sdio_uart_irq);597 if (ret)598 goto err2;599 600 /*601 * Clear the FIFO buffers and disable them.602 * (they will be reenabled in sdio_change_speed())603 */604 sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);605 sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |606 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);607 sdio_out(port, UART_FCR, 0);608 609 /*610 * Clear the interrupt registers.611 */612 (void) sdio_in(port, UART_LSR);613 (void) sdio_in(port, UART_RX);614 (void) sdio_in(port, UART_IIR);615 (void) sdio_in(port, UART_MSR);616 617 /*618 * Now, initialize the UART619 */620 sdio_out(port, UART_LCR, UART_LCR_WLEN8);621 622 port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;623 port->mctrl = TIOCM_OUT2;624 625 sdio_uart_change_speed(port, &tty->termios, NULL);626 627 if (C_BAUD(tty))628 sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);629 630 if (C_CRTSCTS(tty))631 if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))632 tty->hw_stopped = true;633 634 clear_bit(TTY_IO_ERROR, &tty->flags);635 636 /* Kick the IRQ handler once while we're still holding the host lock */637 sdio_uart_irq(port->func);638 639 sdio_uart_release_func(port);640 return 0;641 642err2:643 sdio_disable_func(port->func);644err1:645 sdio_uart_release_func(port);646 return ret;647}648 649/**650 * sdio_uart_shutdown - stop hardware651 * @tport: tty port to shut down652 *653 * Deactivate a tty port. The port locking guarantees us this will be654 * run only if a successful matching activate already ran. The two are655 * protected from each other by the internal locking and will not run656 * at the same time even during a hangup event.657 */658 659static void sdio_uart_shutdown(struct tty_port *tport)660{661 struct sdio_uart_port *port =662 container_of(tport, struct sdio_uart_port, port);663 int ret;664 665 ret = sdio_uart_claim_func(port);666 if (ret)667 return;668 669 sdio_uart_stop_rx(port);670 671 /* Disable interrupts from this port */672 sdio_release_irq(port->func);673 port->ier = 0;674 sdio_out(port, UART_IER, 0);675 676 sdio_uart_clear_mctrl(port, TIOCM_OUT2);677 678 /* Disable break condition and FIFOs. */679 port->lcr &= ~UART_LCR_SBC;680 sdio_out(port, UART_LCR, port->lcr);681 sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |682 UART_FCR_CLEAR_RCVR |683 UART_FCR_CLEAR_XMIT);684 sdio_out(port, UART_FCR, 0);685 686 sdio_disable_func(port->func);687 688 sdio_uart_release_func(port);689}690 691static void sdio_uart_port_destroy(struct tty_port *tport)692{693 struct sdio_uart_port *port =694 container_of(tport, struct sdio_uart_port, port);695 kfifo_free(&port->xmit_fifo);696 kfree(port);697}698 699/**700 * sdio_uart_install - install method701 * @driver: the driver in use (sdio_uart in our case)702 * @tty: the tty being bound703 *704 * Look up and bind the tty and the driver together. Initialize705 * any needed private data (in our case the termios)706 */707 708static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)709{710 int idx = tty->index;711 struct sdio_uart_port *port = sdio_uart_port_get(idx);712 int ret = tty_standard_install(driver, tty);713 714 if (ret == 0)715 /* This is the ref sdio_uart_port get provided */716 tty->driver_data = port;717 else718 sdio_uart_port_put(port);719 return ret;720}721 722/**723 * sdio_uart_cleanup - called on the last tty kref drop724 * @tty: the tty being destroyed725 *726 * Called asynchronously when the last reference to the tty is dropped.727 * We cannot destroy the tty->driver_data port kref until this point728 */729 730static void sdio_uart_cleanup(struct tty_struct *tty)731{732 struct sdio_uart_port *port = tty->driver_data;733 tty->driver_data = NULL; /* Bug trap */734 sdio_uart_port_put(port);735}736 737/*738 * Open/close/hangup is now entirely boilerplate739 */740 741static int sdio_uart_open(struct tty_struct *tty, struct file *filp)742{743 struct sdio_uart_port *port = tty->driver_data;744 return tty_port_open(&port->port, tty, filp);745}746 747static void sdio_uart_close(struct tty_struct *tty, struct file * filp)748{749 struct sdio_uart_port *port = tty->driver_data;750 tty_port_close(&port->port, tty, filp);751}752 753static void sdio_uart_hangup(struct tty_struct *tty)754{755 struct sdio_uart_port *port = tty->driver_data;756 tty_port_hangup(&port->port);757}758 759static ssize_t sdio_uart_write(struct tty_struct *tty, const u8 *buf,760 size_t count)761{762 struct sdio_uart_port *port = tty->driver_data;763 int ret;764 765 if (!port->func)766 return -ENODEV;767 768 ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock);769 if (!(port->ier & UART_IER_THRI)) {770 int err = sdio_uart_claim_func(port);771 if (!err) {772 sdio_uart_start_tx(port);773 sdio_uart_irq(port->func);774 sdio_uart_release_func(port);775 } else776 ret = err;777 }778 779 return ret;780}781 782static unsigned int sdio_uart_write_room(struct tty_struct *tty)783{784 struct sdio_uart_port *port = tty->driver_data;785 return FIFO_SIZE - kfifo_len(&port->xmit_fifo);786}787 788static unsigned int sdio_uart_chars_in_buffer(struct tty_struct *tty)789{790 struct sdio_uart_port *port = tty->driver_data;791 return kfifo_len(&port->xmit_fifo);792}793 794static void sdio_uart_send_xchar(struct tty_struct *tty, u8 ch)795{796 struct sdio_uart_port *port = tty->driver_data;797 798 port->x_char = ch;799 if (ch && !(port->ier & UART_IER_THRI)) {800 if (sdio_uart_claim_func(port) != 0)801 return;802 sdio_uart_start_tx(port);803 sdio_uart_irq(port->func);804 sdio_uart_release_func(port);805 }806}807 808static void sdio_uart_throttle(struct tty_struct *tty)809{810 struct sdio_uart_port *port = tty->driver_data;811 812 if (!I_IXOFF(tty) && !C_CRTSCTS(tty))813 return;814 815 if (sdio_uart_claim_func(port) != 0)816 return;817 818 if (I_IXOFF(tty)) {819 port->x_char = STOP_CHAR(tty);820 sdio_uart_start_tx(port);821 }822 823 if (C_CRTSCTS(tty))824 sdio_uart_clear_mctrl(port, TIOCM_RTS);825 826 sdio_uart_irq(port->func);827 sdio_uart_release_func(port);828}829 830static void sdio_uart_unthrottle(struct tty_struct *tty)831{832 struct sdio_uart_port *port = tty->driver_data;833 834 if (!I_IXOFF(tty) && !C_CRTSCTS(tty))835 return;836 837 if (sdio_uart_claim_func(port) != 0)838 return;839 840 if (I_IXOFF(tty)) {841 if (port->x_char) {842 port->x_char = 0;843 } else {844 port->x_char = START_CHAR(tty);845 sdio_uart_start_tx(port);846 }847 }848 849 if (C_CRTSCTS(tty))850 sdio_uart_set_mctrl(port, TIOCM_RTS);851 852 sdio_uart_irq(port->func);853 sdio_uart_release_func(port);854}855 856static void sdio_uart_set_termios(struct tty_struct *tty,857 const struct ktermios *old_termios)858{859 struct sdio_uart_port *port = tty->driver_data;860 unsigned int cflag = tty->termios.c_cflag;861 862 if (sdio_uart_claim_func(port) != 0)863 return;864 865 sdio_uart_change_speed(port, &tty->termios, old_termios);866 867 /* Handle transition to B0 status */868 if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))869 sdio_uart_clear_mctrl(port, TIOCM_RTS | TIOCM_DTR);870 871 /* Handle transition away from B0 status */872 if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {873 unsigned int mask = TIOCM_DTR;874 if (!(cflag & CRTSCTS) || !tty_throttled(tty))875 mask |= TIOCM_RTS;876 sdio_uart_set_mctrl(port, mask);877 }878 879 /* Handle turning off CRTSCTS */880 if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {881 tty->hw_stopped = false;882 sdio_uart_start_tx(port);883 }884 885 /* Handle turning on CRTSCTS */886 if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {887 if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) {888 tty->hw_stopped = true;889 sdio_uart_stop_tx(port);890 }891 }892 893 sdio_uart_release_func(port);894}895 896static int sdio_uart_break_ctl(struct tty_struct *tty, int break_state)897{898 struct sdio_uart_port *port = tty->driver_data;899 int result;900 901 result = sdio_uart_claim_func(port);902 if (result != 0)903 return result;904 905 if (break_state == -1)906 port->lcr |= UART_LCR_SBC;907 else908 port->lcr &= ~UART_LCR_SBC;909 sdio_out(port, UART_LCR, port->lcr);910 911 sdio_uart_release_func(port);912 return 0;913}914 915static int sdio_uart_tiocmget(struct tty_struct *tty)916{917 struct sdio_uart_port *port = tty->driver_data;918 int result;919 920 result = sdio_uart_claim_func(port);921 if (!result) {922 result = port->mctrl | sdio_uart_get_mctrl(port);923 sdio_uart_release_func(port);924 }925 926 return result;927}928 929static int sdio_uart_tiocmset(struct tty_struct *tty,930 unsigned int set, unsigned int clear)931{932 struct sdio_uart_port *port = tty->driver_data;933 int result;934 935 result = sdio_uart_claim_func(port);936 if (!result) {937 sdio_uart_update_mctrl(port, set, clear);938 sdio_uart_release_func(port);939 }940 941 return result;942}943 944static int sdio_uart_proc_show(struct seq_file *m, void *v)945{946 int i;947 948 seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n",949 "", "", "");950 for (i = 0; i < UART_NR; i++) {951 struct sdio_uart_port *port = sdio_uart_port_get(i);952 if (port) {953 seq_printf(m, "%d: uart:SDIO", i);954 if (capable(CAP_SYS_ADMIN)) {955 seq_printf(m, " tx:%d rx:%d",956 port->icount.tx, port->icount.rx);957 if (port->icount.frame)958 seq_printf(m, " fe:%d",959 port->icount.frame);960 if (port->icount.parity)961 seq_printf(m, " pe:%d",962 port->icount.parity);963 if (port->icount.brk)964 seq_printf(m, " brk:%d",965 port->icount.brk);966 if (port->icount.overrun)967 seq_printf(m, " oe:%d",968 port->icount.overrun);969 if (port->icount.cts)970 seq_printf(m, " cts:%d",971 port->icount.cts);972 if (port->icount.dsr)973 seq_printf(m, " dsr:%d",974 port->icount.dsr);975 if (port->icount.rng)976 seq_printf(m, " rng:%d",977 port->icount.rng);978 if (port->icount.dcd)979 seq_printf(m, " dcd:%d",980 port->icount.dcd);981 }982 sdio_uart_port_put(port);983 seq_putc(m, '\n');984 }985 }986 return 0;987}988 989static const struct tty_port_operations sdio_uart_port_ops = {990 .dtr_rts = uart_dtr_rts,991 .carrier_raised = uart_carrier_raised,992 .shutdown = sdio_uart_shutdown,993 .activate = sdio_uart_activate,994 .destruct = sdio_uart_port_destroy,995};996 997static const struct tty_operations sdio_uart_ops = {998 .open = sdio_uart_open,999 .close = sdio_uart_close,1000 .write = sdio_uart_write,1001 .write_room = sdio_uart_write_room,1002 .chars_in_buffer = sdio_uart_chars_in_buffer,1003 .send_xchar = sdio_uart_send_xchar,1004 .throttle = sdio_uart_throttle,1005 .unthrottle = sdio_uart_unthrottle,1006 .set_termios = sdio_uart_set_termios,1007 .hangup = sdio_uart_hangup,1008 .break_ctl = sdio_uart_break_ctl,1009 .tiocmget = sdio_uart_tiocmget,1010 .tiocmset = sdio_uart_tiocmset,1011 .install = sdio_uart_install,1012 .cleanup = sdio_uart_cleanup,1013 .proc_show = sdio_uart_proc_show,1014};1015 1016static struct tty_driver *sdio_uart_tty_driver;1017 1018static int sdio_uart_probe(struct sdio_func *func,1019 const struct sdio_device_id *id)1020{1021 struct sdio_uart_port *port;1022 int ret;1023 1024 port = kzalloc(sizeof(struct sdio_uart_port), GFP_KERNEL);1025 if (!port)1026 return -ENOMEM;1027 1028 if (func->class == SDIO_CLASS_UART) {1029 pr_warn("%s: need info on UART class basic setup\n",1030 sdio_func_id(func));1031 kfree(port);1032 return -ENOSYS;1033 } else if (func->class == SDIO_CLASS_GPS) {1034 /*1035 * We need tuple 0x91. It contains SUBTPL_SIOREG1036 * and SUBTPL_RCVCAPS.1037 */1038 struct sdio_func_tuple *tpl;1039 for (tpl = func->tuples; tpl; tpl = tpl->next) {1040 if (tpl->code != 0x91)1041 continue;1042 if (tpl->size < 10)1043 continue;1044 if (tpl->data[1] == 0) /* SUBTPL_SIOREG */1045 break;1046 }1047 if (!tpl) {1048 pr_warn("%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",1049 sdio_func_id(func));1050 kfree(port);1051 return -EINVAL;1052 }1053 pr_debug("%s: Register ID = 0x%02x, Exp ID = 0x%02x\n",1054 sdio_func_id(func), tpl->data[2], tpl->data[3]);1055 port->regs_offset = (tpl->data[4] << 0) |1056 (tpl->data[5] << 8) |1057 (tpl->data[6] << 16);1058 pr_debug("%s: regs offset = 0x%x\n",1059 sdio_func_id(func), port->regs_offset);1060 port->uartclk = tpl->data[7] * 115200;1061 if (port->uartclk == 0)1062 port->uartclk = 115200;1063 pr_debug("%s: clk %d baudcode %u 4800-div %u\n",1064 sdio_func_id(func), port->uartclk,1065 tpl->data[7], tpl->data[8] | (tpl->data[9] << 8));1066 } else {1067 kfree(port);1068 return -EINVAL;1069 }1070 1071 port->func = func;1072 sdio_set_drvdata(func, port);1073 tty_port_init(&port->port);1074 port->port.ops = &sdio_uart_port_ops;1075 1076 ret = sdio_uart_add_port(port);1077 if (ret) {1078 kfree(port);1079 } else {1080 struct device *dev;1081 dev = tty_port_register_device(&port->port,1082 sdio_uart_tty_driver, port->index, &func->dev);1083 if (IS_ERR(dev)) {1084 sdio_uart_port_remove(port);1085 ret = PTR_ERR(dev);1086 }1087 }1088 1089 return ret;1090}1091 1092static void sdio_uart_remove(struct sdio_func *func)1093{1094 struct sdio_uart_port *port = sdio_get_drvdata(func);1095 1096 tty_unregister_device(sdio_uart_tty_driver, port->index);1097 sdio_uart_port_remove(port);1098}1099 1100static const struct sdio_device_id sdio_uart_ids[] = {1101 { SDIO_DEVICE_CLASS(SDIO_CLASS_UART) },1102 { SDIO_DEVICE_CLASS(SDIO_CLASS_GPS) },1103 { /* end: all zeroes */ },1104};1105 1106MODULE_DEVICE_TABLE(sdio, sdio_uart_ids);1107 1108static struct sdio_driver sdio_uart_driver = {1109 .probe = sdio_uart_probe,1110 .remove = sdio_uart_remove,1111 .name = "sdio_uart",1112 .id_table = sdio_uart_ids,1113};1114 1115static int __init sdio_uart_init(void)1116{1117 int ret;1118 struct tty_driver *tty_drv;1119 1120 sdio_uart_tty_driver = tty_drv = tty_alloc_driver(UART_NR,1121 TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);1122 if (IS_ERR(tty_drv))1123 return PTR_ERR(tty_drv);1124 1125 tty_drv->driver_name = "sdio_uart";1126 tty_drv->name = "ttySDIO";1127 tty_drv->major = 0; /* dynamically allocated */1128 tty_drv->minor_start = 0;1129 tty_drv->type = TTY_DRIVER_TYPE_SERIAL;1130 tty_drv->subtype = SERIAL_TYPE_NORMAL;1131 tty_drv->init_termios = tty_std_termios;1132 tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;1133 tty_drv->init_termios.c_ispeed = 4800;1134 tty_drv->init_termios.c_ospeed = 4800;1135 tty_set_operations(tty_drv, &sdio_uart_ops);1136 1137 ret = tty_register_driver(tty_drv);1138 if (ret)1139 goto err1;1140 1141 ret = sdio_register_driver(&sdio_uart_driver);1142 if (ret)1143 goto err2;1144 1145 return 0;1146 1147err2:1148 tty_unregister_driver(tty_drv);1149err1:1150 tty_driver_kref_put(tty_drv);1151 return ret;1152}1153 1154static void __exit sdio_uart_exit(void)1155{1156 sdio_unregister_driver(&sdio_uart_driver);1157 tty_unregister_driver(sdio_uart_tty_driver);1158 tty_driver_kref_put(sdio_uart_tty_driver);1159}1160 1161module_init(sdio_uart_init);1162module_exit(sdio_uart_exit);1163 1164MODULE_AUTHOR("Nicolas Pitre");1165MODULE_DESCRIPTION("SDIO UART/GPS driver");1166MODULE_LICENSE("GPL");1167