mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
[ARM] S3C24XX: Split serial driver into core and per-cpu drivers
The S3C2410 serial driver in drivers/serial/s3c2410.c has been growing bigger with the addition of more variants of this hardware with the growing Samsung SoCs range. As such, it would be easier to split this code up into a core and per-cpu drivers to make driver addition easier, and the core smaller. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
This commit is contained in:
parent
6fc601e37b
commit
b497549a03
9 changed files with 1929 additions and 1835 deletions
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.26-rc8
|
||||
# Wed Jun 25 13:39:12 2008
|
||||
# Thu Jul 3 11:48:41 2008
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
|
@ -12,6 +12,7 @@ CONFIG_MMU=y
|
|||
CONFIG_NO_IOPORT=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
|
@ -23,6 +24,7 @@ CONFIG_GENERIC_HWEIGHT=y
|
|||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_ARCH_SUPPORTS_AOUT=y
|
||||
CONFIG_ZONE_DMA=y
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
CONFIG_VECTORS_BASE=0xffff0000
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
|
@ -131,7 +133,6 @@ CONFIG_CLASSIC_RCU=y
|
|||
# CONFIG_ARCH_AT91 is not set
|
||||
# CONFIG_ARCH_CLPS7500 is not set
|
||||
# CONFIG_ARCH_CLPS711X is not set
|
||||
# CONFIG_ARCH_CO285 is not set
|
||||
# CONFIG_ARCH_EBSA110 is not set
|
||||
# CONFIG_ARCH_EP93XX is not set
|
||||
# CONFIG_ARCH_FOOTBRIDGE is not set
|
||||
|
@ -145,8 +146,11 @@ CONFIG_CLASSIC_RCU=y
|
|||
# CONFIG_ARCH_IXP2000 is not set
|
||||
# CONFIG_ARCH_IXP4XX is not set
|
||||
# CONFIG_ARCH_L7200 is not set
|
||||
# CONFIG_ARCH_KIRKWOOD is not set
|
||||
# CONFIG_ARCH_KS8695 is not set
|
||||
# CONFIG_ARCH_NS9XXX is not set
|
||||
# CONFIG_ARCH_LOKI is not set
|
||||
# CONFIG_ARCH_MV78XX0 is not set
|
||||
# CONFIG_ARCH_MXC is not set
|
||||
# CONFIG_ARCH_ORION5X is not set
|
||||
# CONFIG_ARCH_PNX4008 is not set
|
||||
|
@ -871,8 +875,12 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
|
|||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_SAMSUNG=y
|
||||
# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
|
||||
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
|
||||
CONFIG_SERIAL_S3C2410=y
|
||||
CONFIG_SERIAL_S3C2410_CONSOLE=y
|
||||
CONFIG_SERIAL_S3C2412=y
|
||||
CONFIG_SERIAL_S3C2440=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
|
@ -1544,6 +1552,7 @@ CONFIG_FRAME_POINTER=y
|
|||
# CONFIG_RCU_TORTURE_TEST is not set
|
||||
# CONFIG_BACKTRACE_SELF_TEST is not set
|
||||
# CONFIG_FAULT_INJECTION is not set
|
||||
# CONFIG_LATENCYTOP is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_DEBUG_ERRORS=y
|
||||
|
|
|
@ -448,22 +448,27 @@ config SERIAL_CLPS711X_CONSOLE
|
|||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_S3C2410
|
||||
tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
|
||||
depends on ARM && ARCH_S3C2410
|
||||
select SERIAL_CORE
|
||||
config SERIAL_SAMSUNG
|
||||
tristate "Samsung SoC serial support"
|
||||
depends on ARM && PLAT_S3C24XX
|
||||
help
|
||||
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
|
||||
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
|
||||
provide all of these ports, depending on how the serial port
|
||||
pins are configured.
|
||||
|
||||
Currently this driver supports the UARTS on the S3C2410, S3C2440,
|
||||
S3C2442, S3C2412 and S3C2413 CPUs.
|
||||
config SERIAL_SAMSUNG_DEBUG
|
||||
bool "Samsung SoC serial debug"
|
||||
depends on SERIAL_SAMSUNG
|
||||
help
|
||||
Add support for debugging the serial driver. Since this is
|
||||
generally being used as a console, we use our own output
|
||||
routines that go via the low-level debug printascii()
|
||||
function.
|
||||
|
||||
config SERIAL_S3C2410_CONSOLE
|
||||
bool "Support for console on S3C2410 serial port"
|
||||
depends on SERIAL_S3C2410=y
|
||||
config SERIAL_SAMSUNG_CONSOLE
|
||||
bool "Support for console on Samsung SoC serial port"
|
||||
depends on SERIAL_SAMSUNG=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Allow selection of the S3C24XX on-board serial ports for use as
|
||||
|
@ -476,6 +481,37 @@ config SERIAL_S3C2410_CONSOLE
|
|||
your boot loader about how to pass options to the kernel at
|
||||
boot time.)
|
||||
|
||||
config SERIAL_S3C2400
|
||||
tristate "Samsung S3C2410 Serial port support"
|
||||
depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400
|
||||
default y if CPU_S3C2400
|
||||
help
|
||||
Serial port support for the Samsung S3C2400 SoC
|
||||
|
||||
config SERIAL_S3C2410
|
||||
tristate "Samsung S3C2410 Serial port support"
|
||||
depends on SERIAL_SAMSUNG && CPU_S3C2410
|
||||
default y if CPU_S3C2410
|
||||
help
|
||||
Serial port support for the Samsung S3C2410 SoC
|
||||
|
||||
config SERIAL_S3C2412
|
||||
tristate "Samsung S3C2412/S3C2413 Serial port support"
|
||||
depends on SERIAL_SAMSUNG && CPU_S3C2412
|
||||
default y if CPU_S3C2412
|
||||
help
|
||||
Serial port support for the Samsung S3C2412 and S3C2413 SoC
|
||||
|
||||
config SERIAL_S3C2440
|
||||
tristate "Samsung S3C2440/S3C2442 Serial port support"
|
||||
depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442)
|
||||
default y if CPU_S3C2440
|
||||
default y if CPU_S3C2442
|
||||
help
|
||||
Serial port support for the Samsung S3C2440 and S3C2442 SoC
|
||||
|
||||
|
||||
|
||||
config SERIAL_DZ
|
||||
bool "DECstation DZ serial driver"
|
||||
depends on MACH_DECSTATION && 32BIT
|
||||
|
|
|
@ -28,7 +28,11 @@ obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
|
|||
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
|
||||
obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
|
||||
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
|
||||
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
|
||||
obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
|
||||
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
|
||||
obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
|
||||
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
|
||||
obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
|
||||
obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
|
||||
obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
|
||||
|
|
106
drivers/serial/s3c2400.c
Normal file
106
drivers/serial/s3c2400.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* linux/drivers/serial/s3c240.c
|
||||
*
|
||||
* Driver for Samsung SoC onboard UARTs.
|
||||
*
|
||||
* Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "samsung.h"
|
||||
|
||||
static int s3c2400_serial_getsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
clk->divisor = 1;
|
||||
clk->name = "pclk";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2400_serial_setsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2400_serial_resetport(struct uart_port *port,
|
||||
struct s3c2410_uartcfg *cfg)
|
||||
{
|
||||
dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
|
||||
port, port->mapbase, cfg);
|
||||
|
||||
wr_regl(port, S3C2410_UCON, cfg->ucon);
|
||||
wr_regl(port, S3C2410_ULCON, cfg->ulcon);
|
||||
|
||||
/* reset both fifos */
|
||||
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c24xx_uart_info s3c2400_uart_inf = {
|
||||
.name = "Samsung S3C2400 UART",
|
||||
.type = PORT_S3C2400,
|
||||
.fifosize = 16,
|
||||
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S3C2410_UFSTAT_RXFULL,
|
||||
.tx_fifofull = S3C2410_UFSTAT_TXFULL,
|
||||
.tx_fifomask = S3C2410_UFSTAT_TXMASK,
|
||||
.tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
|
||||
.get_clksrc = s3c2400_serial_getsource,
|
||||
.set_clksrc = s3c2400_serial_setsource,
|
||||
.reset_port = s3c2400_serial_resetport,
|
||||
};
|
||||
|
||||
static int s3c2400_serial_probe(struct platform_device *dev)
|
||||
{
|
||||
return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
|
||||
}
|
||||
|
||||
static struct platform_driver s3c2400_serial_drv = {
|
||||
.probe = s3c2400_serial_probe,
|
||||
.remove = s3c24xx_serial_remove,
|
||||
.driver = {
|
||||
.name = "s3c2400-uart",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
s3c24xx_console_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
|
||||
|
||||
static inline int s3c2400_serial_init(void)
|
||||
{
|
||||
return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
|
||||
}
|
||||
|
||||
static inline void s3c2400_serial_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c2400_serial_drv);
|
||||
}
|
||||
|
||||
module_init(s3c2400_serial_init);
|
||||
module_exit(s3c2400_serial_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
MODULE_DESCRIPTION("Samsung S3C2400 SoC Serial port driver");
|
||||
MODULE_ALIAS("platform:s3c2400-uart");
|
File diff suppressed because it is too large
Load diff
151
drivers/serial/s3c2412.c
Normal file
151
drivers/serial/s3c2412.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* linux/drivers/serial/s3c2412.c
|
||||
*
|
||||
* Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs.
|
||||
*
|
||||
* Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "samsung.h"
|
||||
|
||||
static int s3c2412_serial_setsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
ucon &= ~S3C2412_UCON_CLKMASK;
|
||||
|
||||
if (strcmp(clk->name, "uclk") == 0)
|
||||
ucon |= S3C2440_UCON_UCLK;
|
||||
else if (strcmp(clk->name, "pclk") == 0)
|
||||
ucon |= S3C2440_UCON_PCLK;
|
||||
else if (strcmp(clk->name, "usysclk") == 0)
|
||||
ucon |= S3C2412_UCON_USYSCLK;
|
||||
else {
|
||||
printk(KERN_ERR "unknown clock source %s\n", clk->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wr_regl(port, S3C2410_UCON, ucon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int s3c2412_serial_getsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
switch (ucon & S3C2412_UCON_CLKMASK) {
|
||||
case S3C2412_UCON_UCLK:
|
||||
clk->divisor = 1;
|
||||
clk->name = "uclk";
|
||||
break;
|
||||
|
||||
case S3C2412_UCON_PCLK:
|
||||
case S3C2412_UCON_PCLK2:
|
||||
clk->divisor = 1;
|
||||
clk->name = "pclk";
|
||||
break;
|
||||
|
||||
case S3C2412_UCON_USYSCLK:
|
||||
clk->divisor = 1;
|
||||
clk->name = "usysclk";
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2412_serial_resetport(struct uart_port *port,
|
||||
struct s3c2410_uartcfg *cfg)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
dbg("%s: port=%p (%08lx), cfg=%p\n",
|
||||
__func__, port, port->mapbase, cfg);
|
||||
|
||||
/* ensure we don't change the clock settings... */
|
||||
|
||||
ucon &= S3C2412_UCON_CLKMASK;
|
||||
|
||||
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
|
||||
wr_regl(port, S3C2410_ULCON, cfg->ulcon);
|
||||
|
||||
/* reset both fifos */
|
||||
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c24xx_uart_info s3c2412_uart_inf = {
|
||||
.name = "Samsung S3C2412 UART",
|
||||
.type = PORT_S3C2412,
|
||||
.fifosize = 64,
|
||||
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
|
||||
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
|
||||
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
|
||||
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
|
||||
.get_clksrc = s3c2412_serial_getsource,
|
||||
.set_clksrc = s3c2412_serial_setsource,
|
||||
.reset_port = s3c2412_serial_resetport,
|
||||
};
|
||||
|
||||
/* device management */
|
||||
|
||||
static int s3c2412_serial_probe(struct platform_device *dev)
|
||||
{
|
||||
dbg("s3c2440_serial_probe: dev=%p\n", dev);
|
||||
return s3c24xx_serial_probe(dev, &s3c2412_uart_inf);
|
||||
}
|
||||
|
||||
static struct platform_driver s3c2412_serial_drv = {
|
||||
.probe = s3c2412_serial_probe,
|
||||
.remove = s3c24xx_serial_remove,
|
||||
.driver = {
|
||||
.name = "s3c2412-uart",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
s3c24xx_console_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
|
||||
|
||||
static inline int s3c2412_serial_init(void)
|
||||
{
|
||||
return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
|
||||
}
|
||||
|
||||
static inline void s3c2412_serial_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c2412_serial_drv);
|
||||
}
|
||||
|
||||
module_init(s3c2412_serial_init);
|
||||
module_exit(s3c2412_serial_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver");
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:s3c2412-uart");
|
181
drivers/serial/s3c2440.c
Normal file
181
drivers/serial/s3c2440.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/* linux/drivers/serial/s3c2440.c
|
||||
*
|
||||
* Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs.
|
||||
*
|
||||
* Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include "samsung.h"
|
||||
|
||||
|
||||
static int s3c2440_serial_setsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
/* todo - proper fclk<>nonfclk switch. */
|
||||
|
||||
ucon &= ~S3C2440_UCON_CLKMASK;
|
||||
|
||||
if (strcmp(clk->name, "uclk") == 0)
|
||||
ucon |= S3C2440_UCON_UCLK;
|
||||
else if (strcmp(clk->name, "pclk") == 0)
|
||||
ucon |= S3C2440_UCON_PCLK;
|
||||
else if (strcmp(clk->name, "fclk") == 0)
|
||||
ucon |= S3C2440_UCON_FCLK;
|
||||
else {
|
||||
printk(KERN_ERR "unknown clock source %s\n", clk->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wr_regl(port, S3C2410_UCON, ucon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int s3c2440_serial_getsource(struct uart_port *port,
|
||||
struct s3c24xx_uart_clksrc *clk)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
unsigned long ucon0, ucon1, ucon2;
|
||||
|
||||
switch (ucon & S3C2440_UCON_CLKMASK) {
|
||||
case S3C2440_UCON_UCLK:
|
||||
clk->divisor = 1;
|
||||
clk->name = "uclk";
|
||||
break;
|
||||
|
||||
case S3C2440_UCON_PCLK:
|
||||
case S3C2440_UCON_PCLK2:
|
||||
clk->divisor = 1;
|
||||
clk->name = "pclk";
|
||||
break;
|
||||
|
||||
case S3C2440_UCON_FCLK:
|
||||
/* the fun of calculating the uart divisors on
|
||||
* the s3c2440 */
|
||||
|
||||
ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
|
||||
ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
|
||||
ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
|
||||
|
||||
printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
|
||||
|
||||
ucon0 &= S3C2440_UCON0_DIVMASK;
|
||||
ucon1 &= S3C2440_UCON1_DIVMASK;
|
||||
ucon2 &= S3C2440_UCON2_DIVMASK;
|
||||
|
||||
if (ucon0 != 0) {
|
||||
clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
|
||||
clk->divisor += 6;
|
||||
} else if (ucon1 != 0) {
|
||||
clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
|
||||
clk->divisor += 21;
|
||||
} else if (ucon2 != 0) {
|
||||
clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
|
||||
clk->divisor += 36;
|
||||
} else {
|
||||
/* manual calims 44, seems to be 9 */
|
||||
clk->divisor = 9;
|
||||
}
|
||||
|
||||
clk->name = "fclk";
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2440_serial_resetport(struct uart_port *port,
|
||||
struct s3c2410_uartcfg *cfg)
|
||||
{
|
||||
unsigned long ucon = rd_regl(port, S3C2410_UCON);
|
||||
|
||||
dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
|
||||
port, port->mapbase, cfg);
|
||||
|
||||
/* ensure we don't change the clock settings... */
|
||||
|
||||
ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
|
||||
|
||||
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
|
||||
wr_regl(port, S3C2410_ULCON, cfg->ulcon);
|
||||
|
||||
/* reset both fifos */
|
||||
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
|
||||
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c24xx_uart_info s3c2440_uart_inf = {
|
||||
.name = "Samsung S3C2440 UART",
|
||||
.type = PORT_S3C2440,
|
||||
.fifosize = 64,
|
||||
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
|
||||
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
|
||||
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
|
||||
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
|
||||
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
|
||||
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
|
||||
.get_clksrc = s3c2440_serial_getsource,
|
||||
.set_clksrc = s3c2440_serial_setsource,
|
||||
.reset_port = s3c2440_serial_resetport,
|
||||
};
|
||||
|
||||
/* device management */
|
||||
|
||||
static int s3c2440_serial_probe(struct platform_device *dev)
|
||||
{
|
||||
dbg("s3c2440_serial_probe: dev=%p\n", dev);
|
||||
return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
|
||||
}
|
||||
|
||||
static struct platform_driver s3c2440_serial_drv = {
|
||||
.probe = s3c2440_serial_probe,
|
||||
.remove = s3c24xx_serial_remove,
|
||||
.driver = {
|
||||
.name = "s3c2440-uart",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
s3c24xx_console_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
|
||||
|
||||
static int __init s3c2440_serial_init(void)
|
||||
{
|
||||
return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
|
||||
}
|
||||
|
||||
static void __exit s3c2440_serial_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c2440_serial_drv);
|
||||
}
|
||||
|
||||
module_init(s3c2440_serial_init);
|
||||
module_exit(s3c2440_serial_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver");
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
MODULE_LICENSE("GPLi v2");
|
||||
MODULE_ALIAS("platform:s3c2440-uart");
|
1317
drivers/serial/samsung.c
Normal file
1317
drivers/serial/samsung.c
Normal file
File diff suppressed because it is too large
Load diff
102
drivers/serial/samsung.h
Normal file
102
drivers/serial/samsung.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* linux/drivers/serial/samsung.h
|
||||
*
|
||||
* Driver for Samsung SoC onboard UARTs.
|
||||
*
|
||||
* Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
struct s3c24xx_uart_info {
|
||||
char *name;
|
||||
unsigned int type;
|
||||
unsigned int fifosize;
|
||||
unsigned long rx_fifomask;
|
||||
unsigned long rx_fifoshift;
|
||||
unsigned long rx_fifofull;
|
||||
unsigned long tx_fifomask;
|
||||
unsigned long tx_fifoshift;
|
||||
unsigned long tx_fifofull;
|
||||
|
||||
/* clock source control */
|
||||
|
||||
int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
|
||||
int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
|
||||
|
||||
/* uart controls */
|
||||
int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
|
||||
};
|
||||
|
||||
struct s3c24xx_uart_port {
|
||||
unsigned char rx_claimed;
|
||||
unsigned char tx_claimed;
|
||||
|
||||
struct s3c24xx_uart_info *info;
|
||||
struct s3c24xx_uart_clksrc *clksrc;
|
||||
struct clk *clk;
|
||||
struct clk *baudclk;
|
||||
struct uart_port port;
|
||||
};
|
||||
|
||||
/* conversion functions */
|
||||
|
||||
#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
|
||||
#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data)
|
||||
|
||||
/* register access controls */
|
||||
|
||||
#define portaddr(port, reg) ((port)->membase + (reg))
|
||||
|
||||
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
|
||||
#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
|
||||
|
||||
#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
|
||||
#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
|
||||
|
||||
extern int s3c24xx_serial_probe(struct platform_device *dev,
|
||||
struct s3c24xx_uart_info *uart);
|
||||
|
||||
extern int s3c24xx_serial_remove(struct platform_device *dev);
|
||||
|
||||
extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
|
||||
struct s3c24xx_uart_info *uart);
|
||||
|
||||
extern int s3c24xx_serial_init(struct platform_driver *drv,
|
||||
struct s3c24xx_uart_info *info);
|
||||
|
||||
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
|
||||
|
||||
#define s3c24xx_console_init(__drv, __inf) \
|
||||
static int __init s3c_serial_console_init(void) \
|
||||
{ \
|
||||
return s3c24xx_serial_initconsole(__drv, __inf); \
|
||||
} \
|
||||
\
|
||||
console_initcall(s3c_serial_console_init)
|
||||
|
||||
#else
|
||||
#define s3c24xx_console_init(drv, inf) extern void no_console(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
|
||||
|
||||
extern void printascii(const char *);
|
||||
|
||||
static void dbg(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
char buff[256];
|
||||
|
||||
va_start(va, fmt);
|
||||
vsprintf(buff, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
printascii(buff);
|
||||
}
|
||||
|
||||
#else
|
||||
#define dbg(x...) do { } while (0)
|
||||
#endif
|
Loading…
Reference in a new issue