• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/serial/
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