[Galaxy 3 Android Development] cdesai:
Difference in drivers/serial

diff -crB linux/drivers/serial/Kconfig g3/drivers/serial/Kconfig
*** linux/drivers/serial/Kconfig	2010-02-23 07:38:51.000000000 -0800
--- g3/drivers/serial/Kconfig	2011-02-26 04:41:49.000000000 -0800
***************
*** 535,545 ****

config SERIAL_S5PC100
tristate "Samsung S5PC100 Serial port support"
!	depends on SERIAL_SAMSUNG && CPU_S5PC100
default y
help
Serial port support for the Samsung S5PC100 SoCs

config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
--- 535,558 ----

config SERIAL_S5PC100
tristate "Samsung S5PC100 Serial port support"
!	depends on SERIAL_SAMSUNG && (CPU_S5PC100 || CPU_S5PC110 || CPU_S5P6442)
default y
help
Serial port support for the Samsung S5PC100 SoCs

+ config SERIAL_S5PC1XX_HSUART
+ bool "Support for High speed UART(3Mbps) on S5PC1XX serial port"
+ depends on SERIAL_S5PC100=y
+ select SERIAL_CORE
+ help
+ Allow High speed UART on the S5PC1XX on-board serial ports
+
+ config S5P_UART_DMA_EN
+ bool "Support for UART DMA Tx and Rx"
+ depends on SERIAL_S5PC100=y
+ help
+ Allow UART on S5PC1XX to use DMA. (instead of being interrupt driven.)
+
config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff -crB linux/drivers/serial/Makefile g3/drivers/serial/Makefile
*** linux/drivers/serial/Makefile	2010-02-23 07:38:51.000000000 -0800
--- g3/drivers/serial/Makefile	2011-02-26 04:41:49.000000000 -0800
***************
*** 44,50 ****
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
! obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
--- 44,50 ----
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
! obj-$(CONFIG_SERIAL_S5PC100) += s5pc100.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
Only in g3/drivers/serial: s5pc100.c
diff -crB linux/drivers/serial/samsung.c g3/drivers/serial/samsung.c
*** linux/drivers/serial/samsung.c	2010-02-23 07:38:51.000000000 -0800
--- g3/drivers/serial/samsung.c	2011-02-26 04:41:49.000000000 -0800
***************
*** 53,58 ****
--- 53,60 ----

#include "samsung.h"

+ #define HIGH_SPEED_UART
+
/* UART name and device definitions */

#define S3C24XX_SERIAL_NAME	"ttySAC"
***************
*** 67,72 ****
--- 69,77 ----
/* flag to ignore all characters comming in */
#define RXSTAT_DUMMY_READ (0x10000000)

+ const unsigned int nSlotTable[16] = {0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4a52, 0x54aa,
+ 0x5555, 0xd555, 0xd5d5, 0xddd5, 0xdddd, 0xdfdd, 0xdfdf, 0xffdf};
+
static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
{
return container_of(port, struct s3c24xx_uart_port, port);
***************
*** 388,393 ****
--- 392,402 ----
ourport->rx_claimed = 0;
rx_enabled(port) = 0;
}
+ if(ourport->tx_claimed && ourport->rx_claimed) {
+ printk("calling shutdown from startup \n");
+ s3c24xx_serial_shutdown(port);
+ }
+
}

***************
*** 446,451 ****
--- 455,467 ----

ourport->pm_level = level;

+	/* FIXME - Clock gates of sclk and pclk are not separated on s5p6442.
+	So we only need to control ip3 gate when we want to disable the clock related to UART.
+	It's not ourport->baudclk but ourport->clk which control ip3 gate.
+	Because ourport->baudclk has clk_null_enable fuction if source clock is pclk.
+	However getting ourport->clk failed on probe. For this reason, we cannot disable the clock.
+	If it affects power consumption in sleep mode, the problem should be solved. */
+
switch (level) {
case 3:
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
***************
*** 489,494 ****
--- 505,519 ----
.divisor	= 1,
};

+ #ifdef HIGH_SPEED_UART
+ static struct s3c24xx_uart_clksrc tmp_hs_clksrc = {
+	.name	= "sclk_uart",
+	.min_baud	= 0,
+	.max_baud	= 0,
+	.divisor	= 1,
+ };
+ #endif
+
static inline int
s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
{
***************
*** 508,515 ****
struct baud_calc {
struct s3c24xx_uart_clksrc	*clksrc;
unsigned int	calc;
-	unsigned int	divslot;
unsigned int	quot;
struct clk	*src;
};

--- 533,540 ----
struct baud_calc {
struct s3c24xx_uart_clksrc	*clksrc;
unsigned int	calc;
unsigned int	quot;
+ unsigned int slot;
struct clk	*src;
};

***************
*** 518,575 ****
struct s3c24xx_uart_clksrc *clksrc,
unsigned int baud)
{
!	struct s3c24xx_uart_port *ourport = to_ourport(port);
!	unsigned long rate;

calc->src = clk_get(port->dev, clksrc->name);
if (calc->src == NULL || IS_ERR(calc->src))
return 0;

rate = clk_get_rate(calc->src);
rate /= clksrc->divisor;

calc->clksrc = clksrc;

!	if (ourport->info->has_divslot) {
!	unsigned long div = rate / baud;
!
!	/* The UDIVSLOT register on the newer UARTs allows us to
!	* get a divisor adjustment of 1/16th on the baud clock.
!	*
!	* We don't keep the UDIVSLOT value (the 16ths we calculated
!	* by not multiplying the baud by 16) as it is easy enough
!	* to recalculate.
!	*/
!
!	calc->quot = div / 16;
!	calc->calc = rate / div;
!	} else {
!	calc->quot = (rate + (8 * baud)) / (16 * baud);
!	calc->calc = (rate / (calc->quot * 16));
}

-	calc->quot--;
return 1;
}

static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
struct s3c24xx_uart_clksrc **clksrc,
struct clk **clk,
!	unsigned int baud)
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_clksrc *clkp;
struct baud_calc res[MAX_CLKS];
struct baud_calc *resptr, *best, *sptr;
int i;

clkp = cfg->clocks;
best = NULL;

if (cfg->clocks_size < 2) {
if (cfg->clocks_size == 0)
clkp = &tmp_clksrc;
!
/* check to see if we're sourcing fclk, and if so we're
* going to have to update the clock source
*/
--- 543,610 ----
struct s3c24xx_uart_clksrc *clksrc,
unsigned int baud)
{
!	unsigned long rate,nslot;
!	unsigned long tempdiv;
!	unsigned int serial_result_1,serial_result_2;

calc->src = clk_get(port->dev, clksrc->name);
if (calc->src == NULL || IS_ERR(calc->src))
return 0;

+	baud/=100;
+
rate = clk_get_rate(calc->src);
rate /= clksrc->divisor;

calc->clksrc = clksrc;

!	tempdiv = (rate*10/(baud*16))-1000;
!	serial_result_1 = ((tempdiv%1000)*16)/1000;
!	serial_result_2 = (((tempdiv%1000)*16) - (serial_result_1*1000));
!
!	nslot = serial_result_1;
!
!	calc->quot = tempdiv/1000;
!	if (calc->quot == 0) {
!	printk(KERN_ERR "uart: UBRDIV is zero, baudrate isn't affected by UDIVSOLT\n");
!	return 0;
}
+	calc->calc = (rate / (calc->quot * 16));
+	calc->slot = nSlotTable[nslot];

return 1;
}

static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
struct s3c24xx_uart_clksrc **clksrc,
struct clk **clk,
! unsigned int baud, unsigned int *slot)
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_clksrc *clkp;
struct baud_calc res[MAX_CLKS];
struct baud_calc *resptr, *best, *sptr;
+	struct clk *uclk;
int i;

clkp = cfg->clocks;
best = NULL;

if (cfg->clocks_size < 2) {
+ #ifdef HIGH_SPEED_UART
+	if (cfg->clocks_size == 0) {
+	if (cfg->hwport == 0)	/* Bluetooth UART Port */
+	{
+	clkp = &tmp_hs_clksrc;
+	printk("@@@@@@@@@@@@@@ BT HIGHSPEED CLOCK @@@@@@@@@@@@@@\n");
+	}
+	else
+	clkp = &tmp_clksrc;
+	}
+ #else
if (cfg->clocks_size == 0)
clkp = &tmp_clksrc;
! #endif
/* check to see if we're sourcing fclk, and if so we're
* going to have to update the clock source
*/
***************
*** 621,658 ****
}
}

/* store results to pass back */

*clksrc = best->clksrc;
*clk = best->src;

return best->quot;
}

- /* udivslot_table[]
- *
- * This table takes the fractional value of the baud divisor and gives
- * the recommended setting for the UDIVSLOT register.
- */
- static u16 udivslot_table[16] = {
-	[0] = 0x0000,
-	[1] = 0x0080,
-	[2] = 0x0808,
-	[3] = 0x0888,
-	[4] = 0x2222,
-	[5] = 0x4924,
-	[6] = 0x4A52,
-	[7] = 0x54AA,
-	[8] = 0x5555,
-	[9] = 0xD555,
-	[10] = 0xD5D5,
-	[11] = 0xDDD5,
-	[12] = 0xDDDD,
-	[13] = 0xDFDD,
-	[14] = 0xDFDF,
-	[15] = 0xFFDF,
- };
-
static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
--- 656,674 ----
}
}

+	if(best) {
/* store results to pass back */

*clksrc = best->clksrc;
*clk = best->src;
+	*slot = best->slot;

return best->quot;
+	} else {
+	return -EINVAL;
+	}
}

static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
***************
*** 665,693 ****
unsigned int baud, quot;
unsigned int ulcon;
unsigned int umcon;
!	unsigned int udivslot = 0;
!
/*
* We don't support modem control lines.
*/
termios->c_cflag &= ~(HUPCL | CMSPAR);
termios->c_cflag |= CLOCAL;
!
/*
* Ask the core to calculate the divisor for us.
*/

!	baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);

if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
!	quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);

/* check to see if we need to change clock source */

if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
-	dbg("selecting clock %p\n", clk);
s3c24xx_serial_setsource(port, clksrc);

if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
--- 681,709 ----
unsigned int baud, quot;
unsigned int ulcon;
unsigned int umcon;
!	unsigned int slot = 0;
/*
* We don't support modem control lines.
*/
termios->c_cflag &= ~(HUPCL | CMSPAR);
termios->c_cflag |= CLOCAL;
!	if (port->line == 0)	/* BT UART port */
!	termios->c_cflag |= CRTSCTS;
!
/*
* Ask the core to calculate the divisor for us.
*/

!	baud = uart_get_baud_rate(port, termios, old, 0, 4000000);

if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
!	quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud, &slot);

/* check to see if we need to change clock source */

if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clksrc);

if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
***************
*** 702,714 ****
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}

-	if (ourport->info->has_divslot) {
-	unsigned int div = ourport->baudclk_rate / baud;
-
-	udivslot = udivslot_table[div & 15];
-	dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
-	}
-
switch (termios->c_cflag & CSIZE) {
case CS5:
dbg("config: 5bits/char\n");
--- 718,723 ----
***************
*** 748,763 ****

spin_lock_irqsave(&port->lock, flags);

!	dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
!	ulcon, quot, udivslot);

wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot);
wr_regl(port, S3C2410_UMCON, umcon);

-	if (ourport->info->has_divslot)
-	wr_regl(port, S3C2443_DIVSLOT, udivslot);
-
dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
rd_regl(port, S3C2410_ULCON),
rd_regl(port, S3C2410_UCON),
--- 757,769 ----

spin_lock_irqsave(&port->lock, flags);

!	dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);

wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot);
+	wr_regl(port, S3C_UDIVSLOT, slot);
wr_regl(port, S3C2410_UMCON, umcon);

dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
rd_regl(port, S3C2410_ULCON),
rd_regl(port, S3C2410_UCON),
***************
*** 1111,1116 ****
--- 1117,1127 ----
ourport->tx_irq = ret;

ourport->clk	= clk_get(&platdev->dev, "uart");
+	if (IS_ERR(ourport->clk)) {
+	dev_err(&platdev->dev, "failed to find uart clock source\n");
+	return PTR_ERR(ourport->clk);
+	}
+	clk_enable(ourport->clk);

dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
port->mapbase, port->membase, port->irq,
***************
*** 1118,1123 ****
--- 1129,1135 ----

/* reset the fifos (and setup the uart) */
s3c24xx_serial_resetport(port, cfg);
+	s3c_setup_uart_cfg_gpio(cfg->hwport);
return 0;
}

***************
*** 1192,1198 ****
/* UART power management code */

#ifdef CONFIG_PM
!
static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
--- 1204,1210 ----
/* UART power management code */

#ifdef CONFIG_PM
! extern void bluetooth_enable_irq(int enable);
static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
diff -crB linux/drivers/serial/samsung.h g3/drivers/serial/samsung.h
*** linux/drivers/serial/samsung.h	2010-02-23 07:38:51.000000000 -0800
--- g3/drivers/serial/samsung.h	2011-02-26 04:41:49.000000000 -0800
***************
*** 21,30 ****
unsigned long	tx_fifoshift;
unsigned long	tx_fifofull;

-	/* uart port features */
-
-	unsigned int	has_divslot:1;
-
/* clock source control */

int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
--- 21,26 ----
***************
*** 79,84 ****
--- 75,81 ----

extern int s3c24xx_serial_init(struct platform_driver *drv,
struct s3c24xx_uart_info *info);
+ extern void s3c_setup_uart_cfg_gpio(unsigned char port);

#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE

diff -crB linux/drivers/serial/serial_core.c g3/drivers/serial/serial_core.c
*** linux/drivers/serial/serial_core.c	2010-02-23 07:38:51.000000000 -0800
--- g3/drivers/serial/serial_core.c	2011-02-26 04:41:49.000000000 -0800
***************
*** 94,99 ****
--- 94,102 ----
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;

+	if (port->ops->wake_peer)
+	port->ops->wake_peer(port);
+
if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&
!tty->stopped && !tty->hw_stopped)
port->ops->start_tx(port);