mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
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:
commit
14a3c4ab0e
819 changed files with 34925 additions and 10317 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
118
drivers/serial/s3c24a0.c
Normal 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
151
drivers/serial/s3c6400.c
Normal 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");
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue