linux/drivers/serial/s5pv210.c
<<
>>
Prefs
   1/* linux/drivers/serial/s5pv210.c
   2 *
   3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   4 *              http://www.samsung.com/
   5 *
   6 * Based on drivers/serial/s3c6400.c
   7 *
   8 * Driver for Samsung S5PV210 SoC UARTs.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13*/
  14
  15#include <linux/module.h>
  16#include <linux/ioport.h>
  17#include <linux/io.h>
  18#include <linux/platform_device.h>
  19#include <linux/init.h>
  20#include <linux/serial_core.h>
  21#include <linux/serial.h>
  22
  23#include <asm/irq.h>
  24#include <mach/hardware.h>
  25#include <plat/regs-serial.h>
  26#include "samsung.h"
  27
  28static int s5pv210_serial_setsource(struct uart_port *port,
  29                                        struct s3c24xx_uart_clksrc *clk)
  30{
  31        struct s3c2410_uartcfg *cfg = port->dev->platform_data;
  32        unsigned long ucon = rd_regl(port, S3C2410_UCON);
  33
  34        if ((cfg->clocks_size) == 1)
  35                return 0;
  36
  37        if (strcmp(clk->name, "pclk") == 0)
  38                ucon &= ~S5PV210_UCON_CLKMASK;
  39        else if (strcmp(clk->name, "uclk1") == 0)
  40                ucon |= S5PV210_UCON_CLKMASK;
  41        else {
  42                printk(KERN_ERR "unknown clock source %s\n", clk->name);
  43                return -EINVAL;
  44        }
  45
  46        wr_regl(port, S3C2410_UCON, ucon);
  47        return 0;
  48}
  49
  50
  51static int s5pv210_serial_getsource(struct uart_port *port,
  52                                        struct s3c24xx_uart_clksrc *clk)
  53{
  54        struct s3c2410_uartcfg *cfg = port->dev->platform_data;
  55        u32 ucon = rd_regl(port, S3C2410_UCON);
  56
  57        clk->divisor = 1;
  58
  59        if ((cfg->clocks_size) == 1)
  60                return 0;
  61
  62        switch (ucon & S5PV210_UCON_CLKMASK) {
  63        case S5PV210_UCON_PCLK:
  64                clk->name = "pclk";
  65                break;
  66        case S5PV210_UCON_UCLK:
  67                clk->name = "uclk1";
  68                break;
  69        }
  70
  71        return 0;
  72}
  73
  74static int s5pv210_serial_resetport(struct uart_port *port,
  75                                        struct s3c2410_uartcfg *cfg)
  76{
  77        unsigned long ucon = rd_regl(port, S3C2410_UCON);
  78
  79        ucon &= S5PV210_UCON_CLKMASK;
  80        wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
  81        wr_regl(port, S3C2410_ULCON, cfg->ulcon);
  82
  83        /* reset both fifos */
  84        wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
  85        wr_regl(port, S3C2410_UFCON, cfg->ufcon);
  86
  87        return 0;
  88}
  89
  90#define S5PV210_UART_DEFAULT_INFO(fifo_size)                    \
  91                .name           = "Samsung S5PV210 UART0",      \
  92                .type           = PORT_S3C6400,                 \
  93                .fifosize       = fifo_size,                    \
  94                .has_divslot    = 1,                            \
  95                .rx_fifomask    = S5PV210_UFSTAT_RXMASK,        \
  96                .rx_fifoshift   = S5PV210_UFSTAT_RXSHIFT,       \
  97                .rx_fifofull    = S5PV210_UFSTAT_RXFULL,        \
  98                .tx_fifofull    = S5PV210_UFSTAT_TXFULL,        \
  99                .tx_fifomask    = S5PV210_UFSTAT_TXMASK,        \
 100                .tx_fifoshift   = S5PV210_UFSTAT_TXSHIFT,       \
 101                .get_clksrc     = s5pv210_serial_getsource,     \
 102                .set_clksrc     = s5pv210_serial_setsource,     \
 103                .reset_port     = s5pv210_serial_resetport
 104
 105static struct s3c24xx_uart_info s5p_port_fifo256 = {
 106        S5PV210_UART_DEFAULT_INFO(256),
 107};
 108
 109static struct s3c24xx_uart_info s5p_port_fifo64 = {
 110        S5PV210_UART_DEFAULT_INFO(64),
 111};
 112
 113static struct s3c24xx_uart_info s5p_port_fifo16 = {
 114        S5PV210_UART_DEFAULT_INFO(16),
 115};
 116
 117static struct s3c24xx_uart_info *s5p_uart_inf[] = {
 118        [0] = &s5p_port_fifo256,
 119        [1] = &s5p_port_fifo64,
 120        [2] = &s5p_port_fifo16,
 121        [3] = &s5p_port_fifo16,
 122};
 123
 124/* device management */
 125static int s5p_serial_probe(struct platform_device *pdev)
 126{
 127        return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
 128}
 129
 130static struct platform_driver s5p_serial_driver = {
 131        .probe          = s5p_serial_probe,
 132        .remove         = __devexit_p(s3c24xx_serial_remove),
 133        .driver         = {
 134                .name   = "s5pv210-uart",
 135                .owner  = THIS_MODULE,
 136        },
 137};
 138
 139static int __init s5pv210_serial_console_init(void)
 140{
 141        return s3c24xx_serial_initconsole(&s5p_serial_driver, s5p_uart_inf);
 142}
 143
 144console_initcall(s5pv210_serial_console_init);
 145
 146static int __init s5p_serial_init(void)
 147{
 148        return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf);
 149}
 150
 151static void __exit s5p_serial_exit(void)
 152{
 153        platform_driver_unregister(&s5p_serial_driver);
 154}
 155
 156module_init(s5p_serial_init);
 157module_exit(s5p_serial_exit);
 158
 159MODULE_LICENSE("GPL");
 160MODULE_ALIAS("platform:s5pv210-uart");
 161MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support");
 162MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
 163
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.