root/drivers/tty/serial/milbeaut_usio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlb_usio_stop_tx
  2. mlb_usio_tx_chars
  3. mlb_usio_start_tx
  4. mlb_usio_stop_rx
  5. mlb_usio_enable_ms
  6. mlb_usio_rx_chars
  7. mlb_usio_rx_irq
  8. mlb_usio_tx_irq
  9. mlb_usio_tx_empty
  10. mlb_usio_set_mctrl
  11. mlb_usio_get_mctrl
  12. mlb_usio_break_ctl
  13. mlb_usio_startup
  14. mlb_usio_shutdown
  15. mlb_usio_set_termios
  16. mlb_usio_type
  17. mlb_usio_config_port
  18. mlb_usio_console_putchar
  19. mlb_usio_console_write
  20. mlb_usio_console_setup
  21. mlb_usio_console_init
  22. mlb_usio_early_console_write
  23. mlb_usio_early_console_setup
  24. mlb_usio_probe
  25. mlb_usio_remove
  26. mlb_usio_init
  27. mlb_usio_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2018 Socionext Inc.
   4  */
   5 
   6 #if defined(CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
   7 #define SUPPORT_SYSRQ
   8 #endif
   9 
  10 #include <linux/clk.h>
  11 #include <linux/console.h>
  12 #include <linux/module.h>
  13 #include <linux/of_irq.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/serial_core.h>
  16 #include <linux/tty.h>
  17 #include <linux/tty_flip.h>
  18 
  19 #define USIO_NAME               "mlb-usio-uart"
  20 #define USIO_UART_DEV_NAME      "ttyUSI"
  21 
  22 static struct uart_port mlb_usio_ports[CONFIG_SERIAL_MILBEAUT_USIO_PORTS];
  23 
  24 #define RX      0
  25 #define TX      1
  26 static int mlb_usio_irq[CONFIG_SERIAL_MILBEAUT_USIO_PORTS][2];
  27 
  28 #define MLB_USIO_REG_SMR                0
  29 #define MLB_USIO_REG_SCR                1
  30 #define MLB_USIO_REG_ESCR               2
  31 #define MLB_USIO_REG_SSR                3
  32 #define MLB_USIO_REG_DR                 4
  33 #define MLB_USIO_REG_BGR                6
  34 #define MLB_USIO_REG_FCR                12
  35 #define MLB_USIO_REG_FBYTE              14
  36 
  37 #define MLB_USIO_SMR_SOE                BIT(0)
  38 #define MLB_USIO_SMR_SBL                BIT(3)
  39 #define MLB_USIO_SCR_TXE                BIT(0)
  40 #define MLB_USIO_SCR_RXE                BIT(1)
  41 #define MLB_USIO_SCR_TBIE               BIT(2)
  42 #define MLB_USIO_SCR_TIE                BIT(3)
  43 #define MLB_USIO_SCR_RIE                BIT(4)
  44 #define MLB_USIO_SCR_UPCL               BIT(7)
  45 #define MLB_USIO_ESCR_L_8BIT            0
  46 #define MLB_USIO_ESCR_L_5BIT            1
  47 #define MLB_USIO_ESCR_L_6BIT            2
  48 #define MLB_USIO_ESCR_L_7BIT            3
  49 #define MLB_USIO_ESCR_P                 BIT(3)
  50 #define MLB_USIO_ESCR_PEN               BIT(4)
  51 #define MLB_USIO_ESCR_FLWEN             BIT(7)
  52 #define MLB_USIO_SSR_TBI                BIT(0)
  53 #define MLB_USIO_SSR_TDRE               BIT(1)
  54 #define MLB_USIO_SSR_RDRF               BIT(2)
  55 #define MLB_USIO_SSR_ORE                BIT(3)
  56 #define MLB_USIO_SSR_FRE                BIT(4)
  57 #define MLB_USIO_SSR_PE                 BIT(5)
  58 #define MLB_USIO_SSR_REC                BIT(7)
  59 #define MLB_USIO_SSR_BRK                BIT(8)
  60 #define MLB_USIO_FCR_FE1                BIT(0)
  61 #define MLB_USIO_FCR_FE2                BIT(1)
  62 #define MLB_USIO_FCR_FCL1               BIT(2)
  63 #define MLB_USIO_FCR_FCL2               BIT(3)
  64 #define MLB_USIO_FCR_FSET               BIT(4)
  65 #define MLB_USIO_FCR_FTIE               BIT(9)
  66 #define MLB_USIO_FCR_FDRQ               BIT(10)
  67 #define MLB_USIO_FCR_FRIIE              BIT(11)
  68 
  69 static void mlb_usio_stop_tx(struct uart_port *port)
  70 {
  71         writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE,
  72                port->membase + MLB_USIO_REG_FCR);
  73         writeb(readb(port->membase + MLB_USIO_REG_SCR) & ~MLB_USIO_SCR_TBIE,
  74                port->membase + MLB_USIO_REG_SCR);
  75 }
  76 
  77 static void mlb_usio_tx_chars(struct uart_port *port)
  78 {
  79         struct circ_buf *xmit = &port->state->xmit;
  80         int count;
  81 
  82         writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE,
  83                port->membase + MLB_USIO_REG_FCR);
  84         writeb(readb(port->membase + MLB_USIO_REG_SCR) &
  85                ~(MLB_USIO_SCR_TIE | MLB_USIO_SCR_TBIE),
  86                port->membase + MLB_USIO_REG_SCR);
  87 
  88         if (port->x_char) {
  89                 writew(port->x_char, port->membase + MLB_USIO_REG_DR);
  90                 port->icount.tx++;
  91                 port->x_char = 0;
  92                 return;
  93         }
  94         if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  95                 mlb_usio_stop_tx(port);
  96                 return;
  97         }
  98 
  99         count = port->fifosize -
 100                 (readw(port->membase + MLB_USIO_REG_FBYTE) & 0xff);
 101 
 102         do {
 103                 writew(xmit->buf[xmit->tail], port->membase + MLB_USIO_REG_DR);
 104 
 105                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 106                 port->icount.tx++;
 107                 if (uart_circ_empty(xmit))
 108                         break;
 109 
 110         } while (--count > 0);
 111 
 112         writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FDRQ,
 113                port->membase + MLB_USIO_REG_FCR);
 114 
 115         writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE,
 116                port->membase + MLB_USIO_REG_SCR);
 117 
 118         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 119                 uart_write_wakeup(port);
 120 
 121         if (uart_circ_empty(xmit))
 122                 mlb_usio_stop_tx(port);
 123 }
 124 
 125 static void mlb_usio_start_tx(struct uart_port *port)
 126 {
 127         u16 fcr = readw(port->membase + MLB_USIO_REG_FCR);
 128 
 129         writew(fcr | MLB_USIO_FCR_FTIE, port->membase + MLB_USIO_REG_FCR);
 130         if (!(fcr & MLB_USIO_FCR_FDRQ))
 131                 return;
 132 
 133         writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE,
 134                port->membase + MLB_USIO_REG_SCR);
 135 
 136         if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI)
 137                 mlb_usio_tx_chars(port);
 138 }
 139 
 140 static void mlb_usio_stop_rx(struct uart_port *port)
 141 {
 142         writeb(readb(port->membase + MLB_USIO_REG_SCR) & ~MLB_USIO_SCR_RIE,
 143                port->membase + MLB_USIO_REG_SCR);
 144 }
 145 
 146 static void mlb_usio_enable_ms(struct uart_port *port)
 147 {
 148         writeb(readb(port->membase + MLB_USIO_REG_SCR) |
 149                MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE,
 150                port->membase + MLB_USIO_REG_SCR);
 151 }
 152 
 153 static void mlb_usio_rx_chars(struct uart_port *port)
 154 {
 155         struct tty_port *ttyport = &port->state->port;
 156         unsigned long flag = 0;
 157         char ch = 0;
 158         u8 status;
 159         int max_count = 2;
 160 
 161         while (max_count--) {
 162                 status = readb(port->membase + MLB_USIO_REG_SSR);
 163 
 164                 if (!(status & MLB_USIO_SSR_RDRF))
 165                         break;
 166 
 167                 if (!(status & (MLB_USIO_SSR_ORE | MLB_USIO_SSR_FRE |
 168                                 MLB_USIO_SSR_PE))) {
 169                         ch = readw(port->membase + MLB_USIO_REG_DR);
 170                         flag = TTY_NORMAL;
 171                         port->icount.rx++;
 172                         if (uart_handle_sysrq_char(port, ch))
 173                                 continue;
 174                         uart_insert_char(port, status, MLB_USIO_SSR_ORE,
 175                                          ch, flag);
 176                         continue;
 177                 }
 178                 if (status & MLB_USIO_SSR_PE)
 179                         port->icount.parity++;
 180                 if (status & MLB_USIO_SSR_ORE)
 181                         port->icount.overrun++;
 182                 status &= port->read_status_mask;
 183                 if (status & MLB_USIO_SSR_BRK) {
 184                         flag = TTY_BREAK;
 185                         ch = 0;
 186                 } else
 187                         if (status & MLB_USIO_SSR_PE) {
 188                                 flag = TTY_PARITY;
 189                                 ch = 0;
 190                         } else
 191                                 if (status & MLB_USIO_SSR_FRE) {
 192                                         flag = TTY_FRAME;
 193                                         ch = 0;
 194                                 }
 195                 if (flag)
 196                         uart_insert_char(port, status, MLB_USIO_SSR_ORE,
 197                                          ch, flag);
 198 
 199                 writeb(readb(port->membase + MLB_USIO_REG_SSR) |
 200                                 MLB_USIO_SSR_REC,
 201                                 port->membase + MLB_USIO_REG_SSR);
 202 
 203                 max_count = readw(port->membase + MLB_USIO_REG_FBYTE) >> 8;
 204                 writew(readw(port->membase + MLB_USIO_REG_FCR) |
 205                        MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
 206                 port->membase + MLB_USIO_REG_FCR);
 207         }
 208 
 209         tty_flip_buffer_push(ttyport);
 210 }
 211 
 212 static irqreturn_t mlb_usio_rx_irq(int irq, void *dev_id)
 213 {
 214         struct uart_port *port = dev_id;
 215 
 216         spin_lock(&port->lock);
 217         mlb_usio_rx_chars(port);
 218         spin_unlock(&port->lock);
 219 
 220         return IRQ_HANDLED;
 221 }
 222 
 223 static irqreturn_t mlb_usio_tx_irq(int irq, void *dev_id)
 224 {
 225         struct uart_port *port = dev_id;
 226 
 227         spin_lock(&port->lock);
 228         if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI)
 229                 mlb_usio_tx_chars(port);
 230         spin_unlock(&port->lock);
 231 
 232         return IRQ_HANDLED;
 233 }
 234 
 235 static unsigned int mlb_usio_tx_empty(struct uart_port *port)
 236 {
 237         return (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI) ?
 238                 TIOCSER_TEMT : 0;
 239 }
 240 
 241 static void mlb_usio_set_mctrl(struct uart_port *port, unsigned int mctrl)
 242 {
 243 }
 244 
 245 static unsigned int mlb_usio_get_mctrl(struct uart_port *port)
 246 {
 247         return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
 248 
 249 }
 250 
 251 static void mlb_usio_break_ctl(struct uart_port *port, int break_state)
 252 {
 253 }
 254 
 255 static int mlb_usio_startup(struct uart_port *port)
 256 {
 257         const char *portname = to_platform_device(port->dev)->name;
 258         unsigned long flags;
 259         int ret, index = port->line;
 260         unsigned char  escr;
 261 
 262         ret = request_irq(mlb_usio_irq[index][RX], mlb_usio_rx_irq,
 263                                 0, portname, port);
 264         if (ret)
 265                 return ret;
 266         ret = request_irq(mlb_usio_irq[index][TX], mlb_usio_tx_irq,
 267                                 0, portname, port);
 268         if (ret) {
 269                 free_irq(mlb_usio_irq[index][RX], port);
 270                 return ret;
 271         }
 272 
 273         escr = readb(port->membase + MLB_USIO_REG_ESCR);
 274         if (of_property_read_bool(port->dev->of_node, "auto-flow-control"))
 275                 escr |= MLB_USIO_ESCR_FLWEN;
 276         spin_lock_irqsave(&port->lock, flags);
 277         writeb(0, port->membase + MLB_USIO_REG_SCR);
 278         writeb(escr, port->membase + MLB_USIO_REG_ESCR);
 279         writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR);
 280         writeb(MLB_USIO_SSR_REC, port->membase + MLB_USIO_REG_SSR);
 281         writew(0, port->membase + MLB_USIO_REG_FCR);
 282         writew(MLB_USIO_FCR_FCL1 | MLB_USIO_FCR_FCL2,
 283                port->membase + MLB_USIO_REG_FCR);
 284         writew(MLB_USIO_FCR_FE1 | MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
 285                port->membase + MLB_USIO_REG_FCR);
 286         writew(0, port->membase + MLB_USIO_REG_FBYTE);
 287         writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE);
 288 
 289         writeb(MLB_USIO_SCR_TXE  | MLB_USIO_SCR_RIE | MLB_USIO_SCR_TBIE |
 290                MLB_USIO_SCR_RXE, port->membase + MLB_USIO_REG_SCR);
 291         spin_unlock_irqrestore(&port->lock, flags);
 292 
 293         return 0;
 294 }
 295 
 296 static void mlb_usio_shutdown(struct uart_port *port)
 297 {
 298         int index = port->line;
 299 
 300         free_irq(mlb_usio_irq[index][RX], port);
 301         free_irq(mlb_usio_irq[index][TX], port);
 302 }
 303 
 304 static void mlb_usio_set_termios(struct uart_port *port,
 305                         struct ktermios *termios, struct ktermios *old)
 306 {
 307         unsigned int escr, smr = MLB_USIO_SMR_SOE;
 308         unsigned long flags, baud, quot;
 309 
 310         switch (termios->c_cflag & CSIZE) {
 311         case CS5:
 312                 escr = MLB_USIO_ESCR_L_5BIT;
 313                 break;
 314         case CS6:
 315                 escr = MLB_USIO_ESCR_L_6BIT;
 316                 break;
 317         case CS7:
 318                 escr = MLB_USIO_ESCR_L_7BIT;
 319                 break;
 320         case CS8:
 321         default:
 322                 escr = MLB_USIO_ESCR_L_8BIT;
 323                 break;
 324         }
 325 
 326         if (termios->c_cflag & CSTOPB)
 327                 smr |= MLB_USIO_SMR_SBL;
 328 
 329         if (termios->c_cflag & PARENB) {
 330                 escr |= MLB_USIO_ESCR_PEN;
 331                 if (termios->c_cflag & PARODD)
 332                         escr |= MLB_USIO_ESCR_P;
 333         }
 334         /* Set hard flow control */
 335         if (of_property_read_bool(port->dev->of_node, "auto-flow-control") ||
 336                         (termios->c_cflag & CRTSCTS))
 337                 escr |= MLB_USIO_ESCR_FLWEN;
 338 
 339         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk);
 340         if (baud > 1)
 341                 quot = port->uartclk / baud - 1;
 342         else
 343                 quot = 0;
 344 
 345         spin_lock_irqsave(&port->lock, flags);
 346         uart_update_timeout(port, termios->c_cflag, baud);
 347         port->read_status_mask = MLB_USIO_SSR_ORE | MLB_USIO_SSR_RDRF |
 348                                  MLB_USIO_SSR_TDRE;
 349         if (termios->c_iflag & INPCK)
 350                 port->read_status_mask |= MLB_USIO_SSR_FRE | MLB_USIO_SSR_PE;
 351 
 352         port->ignore_status_mask = 0;
 353         if (termios->c_iflag & IGNPAR)
 354                 port->ignore_status_mask |= MLB_USIO_SSR_FRE | MLB_USIO_SSR_PE;
 355         if ((termios->c_iflag & IGNBRK) && (termios->c_iflag & IGNPAR))
 356                 port->ignore_status_mask |= MLB_USIO_SSR_ORE;
 357         if ((termios->c_cflag & CREAD) == 0)
 358                 port->ignore_status_mask |= MLB_USIO_SSR_RDRF;
 359 
 360         writeb(0, port->membase + MLB_USIO_REG_SCR);
 361         writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR);
 362         writeb(MLB_USIO_SSR_REC, port->membase + MLB_USIO_REG_SSR);
 363         writew(0, port->membase + MLB_USIO_REG_FCR);
 364         writeb(smr, port->membase + MLB_USIO_REG_SMR);
 365         writeb(escr, port->membase + MLB_USIO_REG_ESCR);
 366         writew(quot, port->membase + MLB_USIO_REG_BGR);
 367         writew(0, port->membase + MLB_USIO_REG_FCR);
 368         writew(MLB_USIO_FCR_FCL1 | MLB_USIO_FCR_FCL2 | MLB_USIO_FCR_FE1 |
 369                MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
 370                port->membase + MLB_USIO_REG_FCR);
 371         writew(0, port->membase + MLB_USIO_REG_FBYTE);
 372         writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE);
 373         writeb(MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE | MLB_USIO_SCR_TBIE |
 374                MLB_USIO_SCR_TXE, port->membase + MLB_USIO_REG_SCR);
 375         spin_unlock_irqrestore(&port->lock, flags);
 376 }
 377 
 378 static const char *mlb_usio_type(struct uart_port *port)
 379 {
 380         return ((port->type == PORT_MLB_USIO) ? USIO_NAME : NULL);
 381 }
 382 
 383 static void mlb_usio_config_port(struct uart_port *port, int flags)
 384 {
 385         if (flags & UART_CONFIG_TYPE)
 386                 port->type = PORT_MLB_USIO;
 387 }
 388 
 389 static const struct uart_ops mlb_usio_ops = {
 390         .tx_empty       = mlb_usio_tx_empty,
 391         .set_mctrl      = mlb_usio_set_mctrl,
 392         .get_mctrl      = mlb_usio_get_mctrl,
 393         .stop_tx        = mlb_usio_stop_tx,
 394         .start_tx       = mlb_usio_start_tx,
 395         .stop_rx        = mlb_usio_stop_rx,
 396         .enable_ms      = mlb_usio_enable_ms,
 397         .break_ctl      = mlb_usio_break_ctl,
 398         .startup        = mlb_usio_startup,
 399         .shutdown       = mlb_usio_shutdown,
 400         .set_termios    = mlb_usio_set_termios,
 401         .type           = mlb_usio_type,
 402         .config_port    = mlb_usio_config_port,
 403 };
 404 
 405 #ifdef CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE
 406 
 407 static void mlb_usio_console_putchar(struct uart_port *port, int c)
 408 {
 409         while (!(readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TDRE))
 410                 cpu_relax();
 411 
 412         writew(c, port->membase + MLB_USIO_REG_DR);
 413 }
 414 
 415 static void mlb_usio_console_write(struct console *co, const char *s,
 416                                unsigned int count)
 417 {
 418         struct uart_port *port = &mlb_usio_ports[co->index];
 419 
 420         uart_console_write(port, s, count, mlb_usio_console_putchar);
 421 }
 422 
 423 static int __init mlb_usio_console_setup(struct console *co, char *options)
 424 {
 425         struct uart_port *port;
 426         int baud = 115200;
 427         int parity = 'n';
 428         int flow = 'n';
 429         int bits = 8;
 430 
 431         if (co->index >= CONFIG_SERIAL_MILBEAUT_USIO_PORTS)
 432                 return -ENODEV;
 433 
 434         port = &mlb_usio_ports[co->index];
 435         if (!port->membase)
 436                 return -ENODEV;
 437 
 438 
 439         if (options)
 440                 uart_parse_options(options, &baud, &parity, &bits, &flow);
 441 
 442         if (of_property_read_bool(port->dev->of_node, "auto-flow-control"))
 443                 flow = 'r';
 444 
 445         return uart_set_options(port, co, baud, parity, bits, flow);
 446 }
 447 
 448 
 449 static struct uart_driver mlb_usio_uart_driver;
 450 static struct console mlb_usio_console = {
 451         .name   = USIO_UART_DEV_NAME,
 452         .write  = mlb_usio_console_write,
 453         .device = uart_console_device,
 454         .setup  = mlb_usio_console_setup,
 455         .flags  = CON_PRINTBUFFER,
 456         .index  = -1,
 457         .data   = &mlb_usio_uart_driver,
 458 };
 459 
 460 static int __init mlb_usio_console_init(void)
 461 {
 462         register_console(&mlb_usio_console);
 463         return 0;
 464 }
 465 console_initcall(mlb_usio_console_init);
 466 
 467 
 468 static void mlb_usio_early_console_write(struct console *co, const char *s,
 469                                         u_int count)
 470 {
 471         struct earlycon_device *dev = co->data;
 472 
 473         uart_console_write(&dev->port, s, count, mlb_usio_console_putchar);
 474 }
 475 
 476 static int __init mlb_usio_early_console_setup(struct earlycon_device *device,
 477                                                 const char *opt)
 478 {
 479         if (!device->port.membase)
 480                 return -ENODEV;
 481         device->con->write = mlb_usio_early_console_write;
 482         return 0;
 483 }
 484 
 485 OF_EARLYCON_DECLARE(mlb_usio, "socionext,milbeaut-usio-uart",
 486                         mlb_usio_early_console_setup);
 487 
 488 #define USIO_CONSOLE    (&mlb_usio_console)
 489 #else
 490 #define USIO_CONSOLE    NULL
 491 #endif
 492 
 493 static struct  uart_driver mlb_usio_uart_driver = {
 494         .owner          = THIS_MODULE,
 495         .driver_name    = USIO_NAME,
 496         .dev_name       = USIO_UART_DEV_NAME,
 497         .cons           = USIO_CONSOLE,
 498         .nr             = CONFIG_SERIAL_MILBEAUT_USIO_PORTS,
 499 };
 500 
 501 static int mlb_usio_probe(struct platform_device *pdev)
 502 {
 503         struct clk *clk = devm_clk_get(&pdev->dev, NULL);
 504         struct uart_port *port;
 505         struct resource *res;
 506         int index = 0;
 507         int ret;
 508 
 509         if (IS_ERR(clk)) {
 510                 dev_err(&pdev->dev, "Missing clock\n");
 511                 return PTR_ERR(clk);
 512         }
 513         ret = clk_prepare_enable(clk);
 514         if (ret) {
 515                 dev_err(&pdev->dev, "Clock enable failed: %d\n", ret);
 516                 return ret;
 517         }
 518         of_property_read_u32(pdev->dev.of_node, "index", &index);
 519         port = &mlb_usio_ports[index];
 520 
 521         port->private_data = (void *)clk;
 522         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 523         if (res == NULL) {
 524                 dev_err(&pdev->dev, "Missing regs\n");
 525                 ret = -ENODEV;
 526                 goto failed;
 527         }
 528         port->membase = devm_ioremap(&pdev->dev, res->start,
 529                                 resource_size(res));
 530 
 531         ret = platform_get_irq_byname(pdev, "rx");
 532         mlb_usio_irq[index][RX] = ret;
 533 
 534         ret = platform_get_irq_byname(pdev, "tx");
 535         mlb_usio_irq[index][TX] = ret;
 536 
 537         port->irq = mlb_usio_irq[index][RX];
 538         port->uartclk = clk_get_rate(clk);
 539         port->fifosize = 128;
 540         port->iotype = UPIO_MEM32;
 541         port->flags = UPF_BOOT_AUTOCONF | UPF_SPD_VHI;
 542         port->line = index;
 543         port->ops = &mlb_usio_ops;
 544         port->dev = &pdev->dev;
 545 
 546         ret = uart_add_one_port(&mlb_usio_uart_driver, port);
 547         if (ret) {
 548                 dev_err(&pdev->dev, "Adding port failed: %d\n", ret);
 549                 goto failed;
 550         }
 551         return 0;
 552 
 553 failed:
 554         clk_disable_unprepare(clk);
 555 
 556         return ret;
 557 }
 558 
 559 static int mlb_usio_remove(struct platform_device *pdev)
 560 {
 561         struct uart_port *port = &mlb_usio_ports[pdev->id];
 562         struct clk *clk = port->private_data;
 563 
 564         uart_remove_one_port(&mlb_usio_uart_driver, port);
 565         clk_disable_unprepare(clk);
 566 
 567         return 0;
 568 }
 569 
 570 static const struct of_device_id mlb_usio_dt_ids[] = {
 571         { .compatible = "socionext,milbeaut-usio-uart" },
 572         { /* sentinel */ }
 573 };
 574 MODULE_DEVICE_TABLE(of, mlb_usio_dt_ids);
 575 
 576 static struct platform_driver mlb_usio_driver = {
 577         .probe          = mlb_usio_probe,
 578         .remove         = mlb_usio_remove,
 579         .driver         = {
 580                 .name   = USIO_NAME,
 581                 .of_match_table = mlb_usio_dt_ids,
 582         },
 583 };
 584 
 585 static int __init mlb_usio_init(void)
 586 {
 587         int ret = uart_register_driver(&mlb_usio_uart_driver);
 588 
 589         if (ret) {
 590                 pr_err("%s: uart registration failed: %d\n", __func__, ret);
 591                 return ret;
 592         }
 593         ret = platform_driver_register(&mlb_usio_driver);
 594         if (ret) {
 595                 uart_unregister_driver(&mlb_usio_uart_driver);
 596                 pr_err("%s: drv registration failed: %d\n", __func__, ret);
 597                 return ret;
 598         }
 599 
 600         return 0;
 601 }
 602 
 603 static void __exit mlb_usio_exit(void)
 604 {
 605         platform_driver_unregister(&mlb_usio_driver);
 606         uart_unregister_driver(&mlb_usio_uart_driver);
 607 }
 608 
 609 module_init(mlb_usio_init);
 610 module_exit(mlb_usio_exit);
 611 
 612 MODULE_AUTHOR("SOCIONEXT");
 613 MODULE_DESCRIPTION("MILBEAUT_USIO/UART Driver");
 614 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */