Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm

* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (407 commits)
  [ARM] pxafb: add support for overlay1 and overlay2 as framebuffer devices
  [ARM] pxafb: cleanup of the timing checking code
  [ARM] pxafb: cleanup of the color format manipulation code
  [ARM] pxafb: add palette format support for LCCR4_PAL_FOR_3
  [ARM] pxafb: add support for FBIOPAN_DISPLAY by dma braching
  [ARM] pxafb: allow pxafb_set_par() to start from arbitrary yoffset
  [ARM] pxafb: allow video memory size to be configurable
  [ARM] pxa: add document on the MFP design and how to use it
  [ARM] sa1100_wdt: don't assume CLOCK_TICK_RATE to be a constant
  [ARM] rtc-sa1100: don't assume CLOCK_TICK_RATE to be a constant
  [ARM] pxa/tavorevb: update board support (smartpanel LCD + keypad)
  [ARM] pxa: Update eseries defconfig
  [ARM] 5352/1: add w90p910-plat config file
  [ARM] s3c: S3C options should depend on PLAT_S3C
  [ARM] mv78xx0: implement GPIO and GPIO interrupt support
  [ARM] Kirkwood: implement GPIO and GPIO interrupt support
  [ARM] Orion: share GPIO IRQ handling code
  [ARM] Orion: share GPIO handling code
  [ARM] s3c: define __io using the typesafe version
  [ARM] S3C64XX: Ensure CPU_V6 is selected
  ...
This commit is contained in:
Linus Torvalds 2008-12-30 17:36:49 -08:00
commit 14a3c4ab0e
819 changed files with 34925 additions and 10317 deletions

View file

@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
depends on ARM && PLAT_S3C24XX
depends on ARM && PLAT_S3C
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@ -455,6 +455,16 @@ config SERIAL_SAMSUNG
provide all of these ports, depending on how the serial port
pins are configured.
config SERIAL_SAMSUNG_UARTS
int
depends on SERIAL_SAMSUNG
default 2 if ARCH_S3C2400
default 4 if ARCH_S3C64XX || CPU_S3C2443
default 3
help
Select the number of available UART ports for the Samsung S3C
serial driver
config SERIAL_SAMSUNG_DEBUG
bool "Samsung SoC serial debug"
depends on SERIAL_SAMSUNG && DEBUG_LL
@ -508,7 +518,20 @@ config SERIAL_S3C2440
help
Serial port support for the Samsung S3C2440 and S3C2442 SoC
config SERIAL_S3C24A0
tristate "Samsung S3C24A0 Serial port support"
depends on SERIAL_SAMSUNG && CPU_S3C24A0
default y if CPU_S3C24A0
help
Serial port support for the Samsung S3C24A0 SoC
config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410)
default y
help
Serial port support for the Samsung S3C6400 and S3C6410
SoCs
config SERIAL_DZ
bool "DECstation DZ serial driver"

View file

@ -41,6 +41,8 @@ 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_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o

View file

@ -692,7 +692,7 @@ static int pl010_probe(struct amba_device *dev, void *id)
goto free;
}
uap->clk = clk_get(&dev->dev, "UARTCLK");
uap->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto unmap;

View file

@ -756,7 +756,7 @@ static int pl011_probe(struct amba_device *dev, void *id)
goto free;
}
uap->clk = clk_get(&dev->dev, "UARTCLK");
uap->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto unmap;

View file

@ -66,7 +66,7 @@
#define ONEMS 0xb0 /* One Millisecond register */
#define UTS 0xb4 /* UART Test Register */
#endif
#ifdef CONFIG_ARCH_IMX
#if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1)
#define BIPR1 0xb0 /* Incremental Preset Register 1 */
#define BIPR2 0xb4 /* Incremental Preset Register 2 */
#define BIPR3 0xb8 /* Incremental Preset Register 3 */
@ -96,7 +96,7 @@
#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
#define UCR1_SNDBRK (1<<4) /* Send break */
#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
#ifdef CONFIG_ARCH_IMX
#if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1)
#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
#endif
#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2
@ -187,11 +187,11 @@
#define MAX_INTERNAL_IRQ IMX_IRQS
#endif
#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2
#ifdef CONFIG_ARCH_MXC
#define SERIAL_IMX_MAJOR 207
#define MINOR_START 16
#define DEV_NAME "ttymxc"
#define MAX_INTERNAL_IRQ MXC_MAX_INT_LINES
#define MAX_INTERNAL_IRQ MXC_INTERNAL_IRQS
#endif
/*

View file

@ -48,6 +48,7 @@
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/pxa-regs.h>
#include <mach/regs-uart.h>
struct uart_pxa_port {
@ -766,7 +767,7 @@ static int serial_pxa_probe(struct platform_device *dev)
if (!sport)
return -ENOMEM;
sport->clk = clk_get(&dev->dev, "UARTCLK");
sport->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(sport->clk)) {
ret = PTR_ERR(sport->clk);
goto err_free;

118
drivers/serial/s3c24a0.c Normal file
View file

@ -0,0 +1,118 @@
/* linux/drivers/serial/s3c24a0.c
*
* Driver for Samsung S3C24A0 SoC onboard UARTs.
*
* Based on drivers/serial/s3c2410.c
*
* Author: Sandeep Patil <sandeep.patil@azingo.com>
*
* 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/platform_device.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <mach/hardware.h>
#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
static int s3c24a0_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
if (strcmp(clk->name, "uclk") == 0)
ucon |= S3C2410_UCON_UCLK;
else
ucon &= ~S3C2410_UCON_UCLK;
wr_regl(port, S3C2410_UCON, ucon);
return 0;
}
static int s3c24a0_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
clk->divisor = 1;
clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
return 0;
}
static int s3c24a0_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
{
dbg("s3c24a0_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 s3c24a0_uart_inf = {
.name = "Samsung S3C24A0 UART",
.type = PORT_S3C2410,
.fifosize = 16,
.rx_fifomask = S3C24A0_UFSTAT_RXMASK,
.rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT,
.rx_fifofull = S3C24A0_UFSTAT_RXFULL,
.tx_fifofull = S3C24A0_UFSTAT_TXFULL,
.tx_fifomask = S3C24A0_UFSTAT_TXMASK,
.tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT,
.get_clksrc = s3c24a0_serial_getsource,
.set_clksrc = s3c24a0_serial_setsource,
.reset_port = s3c24a0_serial_resetport,
};
static int s3c24a0_serial_probe(struct platform_device *dev)
{
return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
}
static struct platform_driver s3c24a0_serial_drv = {
.probe = s3c24a0_serial_probe,
.remove = s3c24xx_serial_remove,
.driver = {
.name = "s3c24a0-uart",
.owner = THIS_MODULE,
},
};
s3c24xx_console_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
static int __init s3c24a0_serial_init(void)
{
return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
}
static void __exit s3c24a0_serial_exit(void)
{
platform_driver_unregister(&s3c24a0_serial_drv);
}
module_init(s3c24a0_serial_init);
module_exit(s3c24a0_serial_exit);

151
drivers/serial/s3c6400.c Normal file
View file

@ -0,0 +1,151 @@
/* linux/drivers/serial/s3c6400.c
*
* Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* 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 <mach/hardware.h>
#include <plat/regs-serial.h>
#include "samsung.h"
static int s3c6400_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
if (strcmp(clk->name, "uclk0") == 0) {
ucon &= ~S3C6400_UCON_CLKMASK;
ucon |= S3C6400_UCON_UCLK0;
} else if (strcmp(clk->name, "uclk1") == 0)
ucon |= S3C6400_UCON_UCLK1;
else if (strcmp(clk->name, "pclk") == 0) {
/* See notes about transitioning from UCLK to PCLK */
ucon &= ~S3C6400_UCON_UCLK0;
} else {
printk(KERN_ERR "unknown clock source %s\n", clk->name);
return -EINVAL;
}
wr_regl(port, S3C2410_UCON, ucon);
return 0;
}
static int s3c6400_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
u32 ucon = rd_regl(port, S3C2410_UCON);
clk->divisor = 1;
switch (ucon & S3C6400_UCON_CLKMASK) {
case S3C6400_UCON_UCLK0:
clk->name = "uclk0";
break;
case S3C6400_UCON_UCLK1:
clk->name = "uclk1";
break;
case S3C6400_UCON_PCLK:
case S3C6400_UCON_PCLK2:
clk->name = "pclk";
break;
}
return 0;
}
static int s3c6400_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n",
port, port->mapbase, cfg);
/* ensure we don't change the clock settings... */
ucon &= S3C6400_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 s3c6400_uart_inf = {
.name = "Samsung S3C6400 UART",
.type = PORT_S3C6400,
.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 = s3c6400_serial_getsource,
.set_clksrc = s3c6400_serial_setsource,
.reset_port = s3c6400_serial_resetport,
};
/* device management */
static int s3c6400_serial_probe(struct platform_device *dev)
{
dbg("s3c6400_serial_probe: dev=%p\n", dev);
return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
}
static struct platform_driver s3c6400_serial_drv = {
.probe = s3c6400_serial_probe,
.remove = s3c24xx_serial_remove,
.driver = {
.name = "s3c6400-uart",
.owner = THIS_MODULE,
},
};
s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
static int __init s3c6400_serial_init(void)
{
return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
}
static void __exit s3c6400_serial_exit(void)
{
platform_driver_unregister(&s3c6400_serial_drv);
}
module_init(s3c6400_serial_init);
module_exit(s3c6400_serial_exit);
MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver");
MODULE_AUTHOR("Ben Dooks <[email protected]>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:s3c6400-uart");

View file

@ -42,13 +42,14 @@
#include <linux/serial.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
@ -58,19 +59,6 @@
#define S3C24XX_SERIAL_MAJOR 204
#define S3C24XX_SERIAL_MINOR 64
/* we can support 3 uarts, but not always use them */
#ifdef CONFIG_CPU_S3C2400
#define NR_PORTS (2)
#else
#define NR_PORTS (3)
#endif
/* port irq numbers */
#define TX_IRQ(port) ((port)->irq + 1)
#define RX_IRQ(port) ((port)->irq)
/* macros to change one thing to another */
#define tx_enabled(port) ((port)->unused[0])
@ -136,8 +124,10 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
static void s3c24xx_serial_stop_tx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
disable_irq(ourport->tx_irq);
tx_enabled(port) = 0;
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_enable(port);
@ -146,11 +136,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
static void s3c24xx_serial_start_tx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (!tx_enabled(port)) {
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_disable(port);
enable_irq(TX_IRQ(port));
enable_irq(ourport->tx_irq);
tx_enabled(port) = 1;
}
}
@ -158,9 +150,11 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (rx_enabled(port)) {
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
disable_irq(RX_IRQ(port));
disable_irq(ourport->rx_irq);
rx_enabled(port) = 0;
}
}
@ -384,13 +378,13 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (ourport->tx_claimed) {
free_irq(TX_IRQ(port), ourport);
free_irq(ourport->tx_irq, ourport);
tx_enabled(port) = 0;
ourport->tx_claimed = 0;
}
if (ourport->rx_claimed) {
free_irq(RX_IRQ(port), ourport);
free_irq(ourport->rx_irq, ourport);
ourport->rx_claimed = 0;
rx_enabled(port) = 0;
}
@ -407,12 +401,11 @@ static int s3c24xx_serial_startup(struct uart_port *port)
rx_enabled(port) = 1;
ret = request_irq(RX_IRQ(port),
s3c24xx_serial_rx_chars, 0,
ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
s3c24xx_serial_portname(port), ourport);
if (ret != 0) {
printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
return ret;
}
@ -422,12 +415,11 @@ static int s3c24xx_serial_startup(struct uart_port *port)
tx_enabled(port) = 1;
ret = request_irq(TX_IRQ(port),
s3c24xx_serial_tx_chars, 0,
ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
s3c24xx_serial_portname(port), ourport);
if (ret) {
printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
goto err;
}
@ -452,6 +444,8 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
ourport->pm_level = level;
switch (level) {
case 3:
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
@ -661,6 +655,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
ourport->clksrc = clksrc;
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}
switch (termios->c_cflag & CSIZE) {
@ -752,6 +747,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
return "S3C2440";
case PORT_S3C2412:
return "S3C2412";
case PORT_S3C6400:
return "S3C6400/10";
default:
return NULL;
}
@ -827,14 +824,14 @@ static struct uart_ops s3c24xx_serial_ops = {
static struct uart_driver s3c24xx_uart_drv = {
.owner = THIS_MODULE,
.dev_name = "s3c2410_serial",
.nr = 3,
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
[0] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
@ -859,7 +856,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
.line = 1,
}
},
#if NR_PORTS > 2
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = {
.port = {
@ -872,6 +869,20 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
.flags = UPF_BOOT_AUTOCONF,
.line = 2,
}
},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[3] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 3,
}
}
#endif
};
@ -890,6 +901,89 @@ static inline int s3c24xx_serial_resetport(struct uart_port *port,
return (info->reset_port)(port, cfg);
}
#ifdef CONFIG_CPU_FREQ
static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
unsigned long val, void *data)
{
struct s3c24xx_uart_port *port;
struct uart_port *uport;
port = container_of(nb, struct s3c24xx_uart_port, freq_transition);
uport = &port->port;
/* check to see if port is enabled */
if (port->pm_level != 0)
return 0;
/* try and work out if the baudrate is changing, we can detect
* a change in rate, but we do not have support for detecting
* a disturbance in the clock-rate over the change.
*/
if (IS_ERR(port->clk))
goto exit;
if (port->baudclk_rate == clk_get_rate(port->clk))
goto exit;
if (val == CPUFREQ_PRECHANGE) {
/* we should really shut the port down whilst the
* frequency change is in progress. */
} else if (val == CPUFREQ_POSTCHANGE) {
struct ktermios *termios;
struct tty_struct *tty;
if (uport->info == NULL)
goto exit;
tty = uport->info->port.tty;
if (tty == NULL)
goto exit;
termios = tty->termios;
if (termios == NULL) {
printk(KERN_WARNING "%s: no termios?\n", __func__);
goto exit;
}
s3c24xx_serial_set_termios(uport, termios, NULL);
}
exit:
return 0;
}
static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
{
port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
return cpufreq_register_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
}
static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
{
cpufreq_unregister_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
}
#else
static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
{
return 0;
}
static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
{
}
#endif
/* s3c24xx_serial_init_port
*
* initialise a single serial port from the platform device given
@ -914,8 +1008,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (port->mapbase != 0)
return 0;
if (cfg->hwport > 3)
return -EINVAL;
if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) {
printk(KERN_ERR "%s: port %d bigger than %d\n", __func__,
cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS);
return -ERANGE;
}
/* setup info for port */
port->dev = &platdev->dev;
@ -943,18 +1040,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
port->mapbase = res->start;
port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
port->mapbase = res->start;
port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000);
ret = platform_get_irq(platdev, 0);
if (ret < 0)
port->irq = 0;
else
else {
port->irq = ret;
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
ourport->clk = clk_get(&platdev->dev, "uart");
dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
port->mapbase, port->membase, port->irq, port->uartclk);
dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
port->mapbase, port->membase, port->irq,
ourport->rx_irq, ourport->tx_irq, port->uartclk);
/* reset the fifos (and setup the uart) */
s3c24xx_serial_resetport(port, cfg);
@ -1002,6 +1107,10 @@ int s3c24xx_serial_probe(struct platform_device *dev,
if (ret < 0)
printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__);
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
dev_err(&dev->dev, "failed to add cpufreq notifier\n");
return 0;
probe_err:
@ -1015,6 +1124,7 @@ int s3c24xx_serial_remove(struct platform_device *dev)
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
if (port) {
s3c24xx_serial_cpufreq_deregister(to_ourport(port));
device_remove_file(&dev->dev, &dev_attr_clock_source);
uart_remove_one_port(&s3c24xx_uart_drv, port);
}
@ -1219,7 +1329,7 @@ static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info)
platdev_ptr = s3c24xx_uart_devs;
for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) {
for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) {
s3c24xx_serial_init_port(ptr, info, *platdev_ptr);
}
@ -1240,7 +1350,7 @@ s3c24xx_serial_console_setup(struct console *co, char *options)
/* is this a valid port */
if (co->index == -1 || co->index >= NR_PORTS)
if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
co->index = 0;
port = &s3c24xx_serial_ports[co->index].port;

View file

@ -33,12 +33,21 @@ struct s3c24xx_uart_info {
struct s3c24xx_uart_port {
unsigned char rx_claimed;
unsigned char tx_claimed;
unsigned int pm_level;
unsigned long baudclk_rate;
unsigned int rx_irq;
unsigned int tx_irq;
struct s3c24xx_uart_info *info;
struct s3c24xx_uart_clksrc *clksrc;
struct clk *clk;
struct clk *baudclk;
struct uart_port port;
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
};
/* conversion functions */

View file

@ -41,9 +41,10 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/io.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#define DEV_MAJOR 204
#define DEV_MINOR 16