source: trunk/target/linux/lantiq/patches-2.6.39/0009-SERIAL-Lantiq-Add-driver-for-MIPS-Lantiq-SOCs.patch @ 27026

Last change on this file since 27026 was 27026, checked in by blogic, 6 years ago

[lantiq]

  • backport 2.6.8 patches to .39 / .32.33
  • remove lqtapi
  • bump tapi/dsl to .39
  • migrate to new ltq_ style api
  • add amazon_se support
File size: 19.9 KB
  • new file drivers/tty/serial/lantiq.c

    From 1d2b44b1afa3ef081cd817dbf947d48eb8f5d21a Mon Sep 17 00:00:00 2001
    From: John Crispin <blogic@openwrt.org>
    Date: Tue, 5 Apr 2011 14:10:57 +0200
    Subject: [PATCH 09/13] SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.
    
    Signed-off-by: John Crispin <blogic@openwrt.org>
    Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
    Cc: alan@lxorguk.ukuu.org.uk
    Cc: linux-mips@linux-mips.org
    Cc: linux-serial@vger.kernel.org
    Patchwork: https://patchwork.linux-mips.org/patch/2269/
    Acked-by: Alan Cox <alan@linux.intel.com>
    Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
    ---
     drivers/tty/serial/Kconfig  |    8 +
     drivers/tty/serial/Makefile |    1 +
     drivers/tty/serial/lantiq.c |  756 +++++++++++++++++++++++++++++++++++++++++++
     3 files changed, 765 insertions(+), 0 deletions(-)
     create mode 100644 drivers/tty/serial/lantiq.c
    
    - +  
     1/* 
     2 *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 
     3 * 
     4 * This program is free software; you can redistribute it and/or modify it 
     5 * under the terms of the GNU General Public License version 2 as published 
     6 * by the Free Software Foundation. 
     7 * 
     8 * This program is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     11 * GNU General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU General Public License 
     14 * along with this program; if not, write to the Free Software 
     15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     16 * 
     17 * Copyright (C) 2004 Infineon IFAP DC COM CPE 
     18 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> 
     19 * Copyright (C) 2007 John Crispin <blogic@openwrt.org> 
     20 * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com> 
     21 */ 
     22 
     23#include <linux/slab.h> 
     24#include <linux/module.h> 
     25#include <linux/ioport.h> 
     26#include <linux/init.h> 
     27#include <linux/console.h> 
     28#include <linux/sysrq.h> 
     29#include <linux/device.h> 
     30#include <linux/tty.h> 
     31#include <linux/tty_flip.h> 
     32#include <linux/serial_core.h> 
     33#include <linux/serial.h> 
     34#include <linux/platform_device.h> 
     35#include <linux/io.h> 
     36#include <linux/clk.h> 
     37 
     38#include <lantiq_soc.h> 
     39 
     40#define PORT_LTQ_ASC            111 
     41#define MAXPORTS                2 
     42#define UART_DUMMY_UER_RX       1 
     43#define DRVNAME                 "ltq_asc" 
     44#ifdef __BIG_ENDIAN 
     45#define LTQ_ASC_TBUF            (0x0020 + 3) 
     46#define LTQ_ASC_RBUF            (0x0024 + 3) 
     47#else 
     48#define LTQ_ASC_TBUF            0x0020 
     49#define LTQ_ASC_RBUF            0x0024 
     50#endif 
     51#define LTQ_ASC_FSTAT           0x0048 
     52#define LTQ_ASC_WHBSTATE        0x0018 
     53#define LTQ_ASC_STATE           0x0014 
     54#define LTQ_ASC_IRNCR           0x00F8 
     55#define LTQ_ASC_CLC             0x0000 
     56#define LTQ_ASC_ID              0x0008 
     57#define LTQ_ASC_PISEL           0x0004 
     58#define LTQ_ASC_TXFCON          0x0044 
     59#define LTQ_ASC_RXFCON          0x0040 
     60#define LTQ_ASC_CON             0x0010 
     61#define LTQ_ASC_BG              0x0050 
     62#define LTQ_ASC_IRNREN          0x00F4 
     63 
     64#define ASC_IRNREN_TX           0x1 
     65#define ASC_IRNREN_RX           0x2 
     66#define ASC_IRNREN_ERR          0x4 
     67#define ASC_IRNREN_TX_BUF       0x8 
     68#define ASC_IRNCR_TIR           0x1 
     69#define ASC_IRNCR_RIR           0x2 
     70#define ASC_IRNCR_EIR           0x4 
     71 
     72#define ASCOPT_CSIZE            0x3 
     73#define TXFIFO_FL               1 
     74#define RXFIFO_FL               1 
     75#define ASCCLC_DISS             0x2 
     76#define ASCCLC_RMCMASK          0x0000FF00 
     77#define ASCCLC_RMCOFFSET        8 
     78#define ASCCON_M_8ASYNC         0x0 
     79#define ASCCON_M_7ASYNC         0x2 
     80#define ASCCON_ODD              0x00000020 
     81#define ASCCON_STP              0x00000080 
     82#define ASCCON_BRS              0x00000100 
     83#define ASCCON_FDE              0x00000200 
     84#define ASCCON_R                0x00008000 
     85#define ASCCON_FEN              0x00020000 
     86#define ASCCON_ROEN             0x00080000 
     87#define ASCCON_TOEN             0x00100000 
     88#define ASCSTATE_PE             0x00010000 
     89#define ASCSTATE_FE             0x00020000 
     90#define ASCSTATE_ROE            0x00080000 
     91#define ASCSTATE_ANY            (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE) 
     92#define ASCWHBSTATE_CLRREN      0x00000001 
     93#define ASCWHBSTATE_SETREN      0x00000002 
     94#define ASCWHBSTATE_CLRPE       0x00000004 
     95#define ASCWHBSTATE_CLRFE       0x00000008 
     96#define ASCWHBSTATE_CLRROE      0x00000020 
     97#define ASCTXFCON_TXFEN         0x0001 
     98#define ASCTXFCON_TXFFLU        0x0002 
     99#define ASCTXFCON_TXFITLMASK    0x3F00 
     100#define ASCTXFCON_TXFITLOFF     8 
     101#define ASCRXFCON_RXFEN         0x0001 
     102#define ASCRXFCON_RXFFLU        0x0002 
     103#define ASCRXFCON_RXFITLMASK    0x3F00 
     104#define ASCRXFCON_RXFITLOFF     8 
     105#define ASCFSTAT_RXFFLMASK      0x003F 
     106#define ASCFSTAT_TXFFLMASK      0x3F00 
     107#define ASCFSTAT_TXFREEMASK     0x3F000000 
     108#define ASCFSTAT_TXFREEOFF      24 
     109 
     110static void lqasc_tx_chars(struct uart_port *port); 
     111static struct ltq_uart_port *lqasc_port[MAXPORTS]; 
     112static struct uart_driver lqasc_reg; 
     113static DEFINE_SPINLOCK(ltq_asc_lock); 
     114 
     115struct ltq_uart_port { 
     116        struct uart_port        port; 
     117        struct clk              *clk; 
     118        unsigned int            tx_irq; 
     119        unsigned int            rx_irq; 
     120        unsigned int            err_irq; 
     121}; 
     122 
     123static inline struct 
     124ltq_uart_port *to_ltq_uart_port(struct uart_port *port) 
     125{ 
     126        return container_of(port, struct ltq_uart_port, port); 
     127} 
     128 
     129static void 
     130lqasc_stop_tx(struct uart_port *port) 
     131{ 
     132        return; 
     133} 
     134 
     135static void 
     136lqasc_start_tx(struct uart_port *port) 
     137{ 
     138        unsigned long flags; 
     139        spin_lock_irqsave(&ltq_asc_lock, flags); 
     140        lqasc_tx_chars(port); 
     141        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     142        return; 
     143} 
     144 
     145static void 
     146lqasc_stop_rx(struct uart_port *port) 
     147{ 
     148        ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); 
     149} 
     150 
     151static void 
     152lqasc_enable_ms(struct uart_port *port) 
     153{ 
     154} 
     155 
     156static int 
     157lqasc_rx_chars(struct uart_port *port) 
     158{ 
     159        struct tty_struct *tty = tty_port_tty_get(&port->state->port); 
     160        unsigned int ch = 0, rsr = 0, fifocnt; 
     161 
     162        if (!tty) { 
     163                dev_dbg(port->dev, "%s:tty is busy now", __func__); 
     164                return -EBUSY; 
     165        } 
     166        fifocnt = 
     167                ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; 
     168        while (fifocnt--) { 
     169                u8 flag = TTY_NORMAL; 
     170                ch = ltq_r8(port->membase + LTQ_ASC_RBUF); 
     171                rsr = (ltq_r32(port->membase + LTQ_ASC_STATE) 
     172                        & ASCSTATE_ANY) | UART_DUMMY_UER_RX; 
     173                tty_flip_buffer_push(tty); 
     174                port->icount.rx++; 
     175 
     176                /* 
     177                 * Note that the error handling code is 
     178                 * out of the main execution path 
     179                 */ 
     180                if (rsr & ASCSTATE_ANY) { 
     181                        if (rsr & ASCSTATE_PE) { 
     182                                port->icount.parity++; 
     183                                ltq_w32_mask(0, ASCWHBSTATE_CLRPE, 
     184                                        port->membase + LTQ_ASC_WHBSTATE); 
     185                        } else if (rsr & ASCSTATE_FE) { 
     186                                port->icount.frame++; 
     187                                ltq_w32_mask(0, ASCWHBSTATE_CLRFE, 
     188                                        port->membase + LTQ_ASC_WHBSTATE); 
     189                        } 
     190                        if (rsr & ASCSTATE_ROE) { 
     191                                port->icount.overrun++; 
     192                                ltq_w32_mask(0, ASCWHBSTATE_CLRROE, 
     193                                        port->membase + LTQ_ASC_WHBSTATE); 
     194                        } 
     195 
     196                        rsr &= port->read_status_mask; 
     197 
     198                        if (rsr & ASCSTATE_PE) 
     199                                flag = TTY_PARITY; 
     200                        else if (rsr & ASCSTATE_FE) 
     201                                flag = TTY_FRAME; 
     202                } 
     203 
     204                if ((rsr & port->ignore_status_mask) == 0) 
     205                        tty_insert_flip_char(tty, ch, flag); 
     206 
     207                if (rsr & ASCSTATE_ROE) 
     208                        /* 
     209                         * Overrun is special, since it's reported 
     210                         * immediately, and doesn't affect the current 
     211                         * character 
     212                         */ 
     213                        tty_insert_flip_char(tty, 0, TTY_OVERRUN); 
     214        } 
     215        if (ch != 0) 
     216                tty_flip_buffer_push(tty); 
     217        tty_kref_put(tty); 
     218        return 0; 
     219} 
     220 
     221static void 
     222lqasc_tx_chars(struct uart_port *port) 
     223{ 
     224        struct circ_buf *xmit = &port->state->xmit; 
     225        if (uart_tx_stopped(port)) { 
     226                lqasc_stop_tx(port); 
     227                return; 
     228        } 
     229 
     230        while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) & 
     231                ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { 
     232                if (port->x_char) { 
     233                        ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF); 
     234                        port->icount.tx++; 
     235                        port->x_char = 0; 
     236                        continue; 
     237                } 
     238 
     239                if (uart_circ_empty(xmit)) 
     240                        break; 
     241 
     242                ltq_w8(port->state->xmit.buf[port->state->xmit.tail], 
     243                        port->membase + LTQ_ASC_TBUF); 
     244                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 
     245                port->icount.tx++; 
     246        } 
     247 
     248        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 
     249                uart_write_wakeup(port); 
     250} 
     251 
     252static irqreturn_t 
     253lqasc_tx_int(int irq, void *_port) 
     254{ 
     255        unsigned long flags; 
     256        struct uart_port *port = (struct uart_port *)_port; 
     257        spin_lock_irqsave(&ltq_asc_lock, flags); 
     258        ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); 
     259        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     260        lqasc_start_tx(port); 
     261        return IRQ_HANDLED; 
     262} 
     263 
     264static irqreturn_t 
     265lqasc_err_int(int irq, void *_port) 
     266{ 
     267        unsigned long flags; 
     268        struct uart_port *port = (struct uart_port *)_port; 
     269        spin_lock_irqsave(&ltq_asc_lock, flags); 
     270        /* clear any pending interrupts */ 
     271        ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | 
     272                ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE); 
     273        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     274        return IRQ_HANDLED; 
     275} 
     276 
     277static irqreturn_t 
     278lqasc_rx_int(int irq, void *_port) 
     279{ 
     280        unsigned long flags; 
     281        struct uart_port *port = (struct uart_port *)_port; 
     282        spin_lock_irqsave(&ltq_asc_lock, flags); 
     283        ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); 
     284        lqasc_rx_chars(port); 
     285        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     286        return IRQ_HANDLED; 
     287} 
     288 
     289static unsigned int 
     290lqasc_tx_empty(struct uart_port *port) 
     291{ 
     292        int status; 
     293        status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; 
     294        return status ? 0 : TIOCSER_TEMT; 
     295} 
     296 
     297static unsigned int 
     298lqasc_get_mctrl(struct uart_port *port) 
     299{ 
     300        return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR; 
     301} 
     302 
     303static void 
     304lqasc_set_mctrl(struct uart_port *port, u_int mctrl) 
     305{ 
     306} 
     307 
     308static void 
     309lqasc_break_ctl(struct uart_port *port, int break_state) 
     310{ 
     311} 
     312 
     313static int 
     314lqasc_startup(struct uart_port *port) 
     315{ 
     316        struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); 
     317        int retval; 
     318 
     319        port->uartclk = clk_get_rate(ltq_port->clk); 
     320 
     321        ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), 
     322                port->membase + LTQ_ASC_CLC); 
     323 
     324        ltq_w32(0, port->membase + LTQ_ASC_PISEL); 
     325        ltq_w32( 
     326                ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | 
     327                ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, 
     328                port->membase + LTQ_ASC_TXFCON); 
     329        ltq_w32( 
     330                ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) 
     331                | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, 
     332                port->membase + LTQ_ASC_RXFCON); 
     333        /* make sure other settings are written to hardware before 
     334         * setting enable bits 
     335         */ 
     336        wmb(); 
     337        ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | 
     338                ASCCON_ROEN, port->membase + LTQ_ASC_CON); 
     339 
     340        retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, 
     341                IRQF_DISABLED, "asc_tx", port); 
     342        if (retval) { 
     343                pr_err("failed to request lqasc_tx_int\n"); 
     344                return retval; 
     345        } 
     346 
     347        retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, 
     348                IRQF_DISABLED, "asc_rx", port); 
     349        if (retval) { 
     350                pr_err("failed to request lqasc_rx_int\n"); 
     351                goto err1; 
     352        } 
     353 
     354        retval = request_irq(ltq_port->err_irq, lqasc_err_int, 
     355                IRQF_DISABLED, "asc_err", port); 
     356        if (retval) { 
     357                pr_err("failed to request lqasc_err_int\n"); 
     358                goto err2; 
     359        } 
     360 
     361        ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, 
     362                port->membase + LTQ_ASC_IRNREN); 
     363        return 0; 
     364 
     365err2: 
     366        free_irq(ltq_port->rx_irq, port); 
     367err1: 
     368        free_irq(ltq_port->tx_irq, port); 
     369        return retval; 
     370} 
     371 
     372static void 
     373lqasc_shutdown(struct uart_port *port) 
     374{ 
     375        struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); 
     376        free_irq(ltq_port->tx_irq, port); 
     377        free_irq(ltq_port->rx_irq, port); 
     378        free_irq(ltq_port->err_irq, port); 
     379 
     380        ltq_w32(0, port->membase + LTQ_ASC_CON); 
     381        ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, 
     382                port->membase + LTQ_ASC_RXFCON); 
     383        ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, 
     384                port->membase + LTQ_ASC_TXFCON); 
     385} 
     386 
     387static void 
     388lqasc_set_termios(struct uart_port *port, 
     389        struct ktermios *new, struct ktermios *old) 
     390{ 
     391        unsigned int cflag; 
     392        unsigned int iflag; 
     393        unsigned int divisor; 
     394        unsigned int baud; 
     395        unsigned int con = 0; 
     396        unsigned long flags; 
     397 
     398        cflag = new->c_cflag; 
     399        iflag = new->c_iflag; 
     400 
     401        switch (cflag & CSIZE) { 
     402        case CS7: 
     403                con = ASCCON_M_7ASYNC; 
     404                break; 
     405 
     406        case CS5: 
     407        case CS6: 
     408        default: 
     409                new->c_cflag &= ~ CSIZE; 
     410                new->c_cflag |= CS8; 
     411                con = ASCCON_M_8ASYNC; 
     412                break; 
     413        } 
     414 
     415        cflag &= ~CMSPAR; /* Mark/Space parity is not supported */ 
     416 
     417        if (cflag & CSTOPB) 
     418                con |= ASCCON_STP; 
     419 
     420        if (cflag & PARENB) { 
     421                if (!(cflag & PARODD)) 
     422                        con &= ~ASCCON_ODD; 
     423                else 
     424                        con |= ASCCON_ODD; 
     425        } 
     426 
     427        port->read_status_mask = ASCSTATE_ROE; 
     428        if (iflag & INPCK) 
     429                port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 
     430 
     431        port->ignore_status_mask = 0; 
     432        if (iflag & IGNPAR) 
     433                port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 
     434 
     435        if (iflag & IGNBRK) { 
     436                /* 
     437                 * If we're ignoring parity and break indicators, 
     438                 * ignore overruns too (for real raw support). 
     439                 */ 
     440                if (iflag & IGNPAR) 
     441                        port->ignore_status_mask |= ASCSTATE_ROE; 
     442        } 
     443 
     444        if ((cflag & CREAD) == 0) 
     445                port->ignore_status_mask |= UART_DUMMY_UER_RX; 
     446 
     447        /* set error signals  - framing, parity  and overrun, enable receiver */ 
     448        con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; 
     449 
     450        spin_lock_irqsave(&ltq_asc_lock, flags); 
     451 
     452        /* set up CON */ 
     453        ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON); 
     454 
     455        /* Set baud rate - take a divider of 2 into account */ 
     456        baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); 
     457        divisor = uart_get_divisor(port, baud); 
     458        divisor = divisor / 2 - 1; 
     459 
     460        /* disable the baudrate generator */ 
     461        ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON); 
     462 
     463        /* make sure the fractional divider is off */ 
     464        ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON); 
     465 
     466        /* set up to use divisor of 2 */ 
     467        ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); 
     468 
     469        /* now we can write the new baudrate into the register */ 
     470        ltq_w32(divisor, port->membase + LTQ_ASC_BG); 
     471 
     472        /* turn the baudrate generator back on */ 
     473        ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON); 
     474 
     475        /* enable rx */ 
     476        ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); 
     477 
     478        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     479 
     480        /* Don't rewrite B0 */ 
     481        if (tty_termios_baud_rate(new)) 
     482                tty_termios_encode_baud_rate(new, baud, baud); 
     483} 
     484 
     485static const char* 
     486lqasc_type(struct uart_port *port) 
     487{ 
     488        if (port->type == PORT_LTQ_ASC) 
     489                return DRVNAME; 
     490        else 
     491                return NULL; 
     492} 
     493 
     494static void 
     495lqasc_release_port(struct uart_port *port) 
     496{ 
     497        if (port->flags & UPF_IOREMAP) { 
     498                iounmap(port->membase); 
     499                port->membase = NULL; 
     500        } 
     501} 
     502 
     503static int 
     504lqasc_request_port(struct uart_port *port) 
     505{ 
     506        struct platform_device *pdev = to_platform_device(port->dev); 
     507        struct resource *res; 
     508        int size; 
     509 
     510        res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     511        if (!res) { 
     512                dev_err(&pdev->dev, "cannot obtain I/O memory region"); 
     513                return -ENODEV; 
     514        } 
     515        size = resource_size(res); 
     516 
     517        res = devm_request_mem_region(&pdev->dev, res->start, 
     518                size, dev_name(&pdev->dev)); 
     519        if (!res) { 
     520                dev_err(&pdev->dev, "cannot request I/O memory region"); 
     521                return -EBUSY; 
     522        } 
     523 
     524        if (port->flags & UPF_IOREMAP) { 
     525                port->membase = devm_ioremap_nocache(&pdev->dev, 
     526                        port->mapbase, size); 
     527                if (port->membase == NULL) 
     528                        return -ENOMEM; 
     529        } 
     530        return 0; 
     531} 
     532 
     533static void 
     534lqasc_config_port(struct uart_port *port, int flags) 
     535{ 
     536        if (flags & UART_CONFIG_TYPE) { 
     537                port->type = PORT_LTQ_ASC; 
     538                lqasc_request_port(port); 
     539        } 
     540} 
     541 
     542static int 
     543lqasc_verify_port(struct uart_port *port, 
     544        struct serial_struct *ser) 
     545{ 
     546        int ret = 0; 
     547        if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC) 
     548                ret = -EINVAL; 
     549        if (ser->irq < 0 || ser->irq >= NR_IRQS) 
     550                ret = -EINVAL; 
     551        if (ser->baud_base < 9600) 
     552                ret = -EINVAL; 
     553        return ret; 
     554} 
     555 
     556static struct uart_ops lqasc_pops = { 
     557        .tx_empty =     lqasc_tx_empty, 
     558        .set_mctrl =    lqasc_set_mctrl, 
     559        .get_mctrl =    lqasc_get_mctrl, 
     560        .stop_tx =      lqasc_stop_tx, 
     561        .start_tx =     lqasc_start_tx, 
     562        .stop_rx =      lqasc_stop_rx, 
     563        .enable_ms =    lqasc_enable_ms, 
     564        .break_ctl =    lqasc_break_ctl, 
     565        .startup =      lqasc_startup, 
     566        .shutdown =     lqasc_shutdown, 
     567        .set_termios =  lqasc_set_termios, 
     568        .type =         lqasc_type, 
     569        .release_port = lqasc_release_port, 
     570        .request_port = lqasc_request_port, 
     571        .config_port =  lqasc_config_port, 
     572        .verify_port =  lqasc_verify_port, 
     573}; 
     574 
     575static void 
     576lqasc_console_putchar(struct uart_port *port, int ch) 
     577{ 
     578        int fifofree; 
     579 
     580        if (!port->membase) 
     581                return; 
     582 
     583        do { 
     584                fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT) 
     585                        & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; 
     586        } while (fifofree == 0); 
     587        ltq_w8(ch, port->membase + LTQ_ASC_TBUF); 
     588} 
     589 
     590 
     591static void 
     592lqasc_console_write(struct console *co, const char *s, u_int count) 
     593{ 
     594        struct ltq_uart_port *ltq_port; 
     595        struct uart_port *port; 
     596        unsigned long flags; 
     597 
     598        if (co->index >= MAXPORTS) 
     599                return; 
     600 
     601        ltq_port = lqasc_port[co->index]; 
     602        if (!ltq_port) 
     603                return; 
     604 
     605        port = &ltq_port->port; 
     606 
     607        spin_lock_irqsave(&ltq_asc_lock, flags); 
     608        uart_console_write(port, s, count, lqasc_console_putchar); 
     609        spin_unlock_irqrestore(&ltq_asc_lock, flags); 
     610} 
     611 
     612static int __init 
     613lqasc_console_setup(struct console *co, char *options) 
     614{ 
     615        struct ltq_uart_port *ltq_port; 
     616        struct uart_port *port; 
     617        int baud = 115200; 
     618        int bits = 8; 
     619        int parity = 'n'; 
     620        int flow = 'n'; 
     621 
     622        if (co->index >= MAXPORTS) 
     623                return -ENODEV; 
     624 
     625        ltq_port = lqasc_port[co->index]; 
     626        if (!ltq_port) 
     627                return -ENODEV; 
     628 
     629        port = &ltq_port->port; 
     630 
     631        port->uartclk = clk_get_rate(ltq_port->clk); 
     632 
     633        if (options) 
     634                uart_parse_options(options, &baud, &parity, &bits, &flow); 
     635        return uart_set_options(port, co, baud, parity, bits, flow); 
     636} 
     637 
     638static struct console lqasc_console = { 
     639        .name =         "ttyLTQ", 
     640        .write =        lqasc_console_write, 
     641        .device =       uart_console_device, 
     642        .setup =        lqasc_console_setup, 
     643        .flags =        CON_PRINTBUFFER, 
     644        .index =        -1, 
     645        .data =         &lqasc_reg, 
     646}; 
     647 
     648static int __init 
     649lqasc_console_init(void) 
     650{ 
     651        register_console(&lqasc_console); 
     652        return 0; 
     653} 
     654console_initcall(lqasc_console_init); 
     655 
     656static struct uart_driver lqasc_reg = { 
     657        .owner =        THIS_MODULE, 
     658        .driver_name =  DRVNAME, 
     659        .dev_name =     "ttyLTQ", 
     660        .major =        0, 
     661        .minor =        0, 
     662        .nr =           MAXPORTS, 
     663        .cons =         &lqasc_console, 
     664}; 
     665 
     666static int __init 
     667lqasc_probe(struct platform_device *pdev) 
     668{ 
     669        struct ltq_uart_port *ltq_port; 
     670        struct uart_port *port; 
     671        struct resource *mmres, *irqres; 
     672        int tx_irq, rx_irq, err_irq; 
     673        struct clk *clk; 
     674        int ret; 
     675 
     676        mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     677        irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 
     678        if (!mmres || !irqres) 
     679                return -ENODEV; 
     680 
     681        if (pdev->id >= MAXPORTS) 
     682                return -EBUSY; 
     683 
     684        if (lqasc_port[pdev->id] != NULL) 
     685                return -EBUSY; 
     686 
     687        clk = clk_get(&pdev->dev, "fpi"); 
     688        if (IS_ERR(clk)) { 
     689                pr_err("failed to get fpi clk\n"); 
     690                return -ENOENT; 
     691        } 
     692 
     693        tx_irq = platform_get_irq_byname(pdev, "tx"); 
     694        rx_irq = platform_get_irq_byname(pdev, "rx"); 
     695        err_irq = platform_get_irq_byname(pdev, "err"); 
     696        if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0)) 
     697                return -ENODEV; 
     698 
     699        ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL); 
     700        if (!ltq_port) 
     701                return -ENOMEM; 
     702 
     703        port = &ltq_port->port; 
     704 
     705        port->iotype    = SERIAL_IO_MEM; 
     706        port->flags     = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP; 
     707        port->ops       = &lqasc_pops; 
     708        port->fifosize  = 16; 
     709        port->type      = PORT_LTQ_ASC, 
     710        port->line      = pdev->id; 
     711        port->dev       = &pdev->dev; 
     712 
     713        port->irq       = tx_irq; /* unused, just to be backward-compatibe */ 
     714        port->mapbase   = mmres->start; 
     715 
     716        ltq_port->clk   = clk; 
     717 
     718        ltq_port->tx_irq = tx_irq; 
     719        ltq_port->rx_irq = rx_irq; 
     720        ltq_port->err_irq = err_irq; 
     721 
     722        lqasc_port[pdev->id] = ltq_port; 
     723        platform_set_drvdata(pdev, ltq_port); 
     724 
     725        ret = uart_add_one_port(&lqasc_reg, port); 
     726 
     727        return ret; 
     728} 
     729 
     730static struct platform_driver lqasc_driver = { 
     731        .driver         = { 
     732                .name   = DRVNAME, 
     733                .owner  = THIS_MODULE, 
     734        }, 
     735}; 
     736 
     737int __init 
     738init_lqasc(void) 
     739{ 
     740        int ret; 
     741 
     742        ret = uart_register_driver(&lqasc_reg); 
     743        if (ret != 0) 
     744                return ret; 
     745 
     746        ret = platform_driver_probe(&lqasc_driver, lqasc_probe); 
     747        if (ret != 0) 
     748                uart_unregister_driver(&lqasc_reg); 
     749 
     750        return ret; 
     751} 
     752 
     753module_init(init_lqasc); 
     754 
     755MODULE_DESCRIPTION("Lantiq serial port driver"); 
     756MODULE_LICENSE("GPL"); 
  • drivers/tty/serial/Kconfig

    a b  
    13911391        help 
    13921392          Support for Console on the NWP serial ports. 
    13931393 
     1394config SERIAL_LANTIQ 
     1395        bool "Lantiq serial driver" 
     1396        depends on LANTIQ 
     1397        select SERIAL_CORE 
     1398        select SERIAL_CORE_CONSOLE 
     1399        help 
     1400          Support for console and UART on Lantiq SoCs. 
     1401 
    13941402config SERIAL_QE 
    13951403        tristate "Freescale QUICC Engine serial port support" 
    13961404        depends on QUICC_ENGINE 
  • drivers/tty/serial/Makefile

    a b  
    9494obj-$(CONFIG_SERIAL_PCH_UART)   += pch_uart.o 
    9595obj-$(CONFIG_SERIAL_MSM_SMD)    += msm_smd_tty.o 
    9696obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o 
     97obj-$(CONFIG_SERIAL_LANTIQ)     += lantiq.o 
Note: See TracBrowser for help on using the repository browser.