From 1e664d4740009ac49c2a2f85ffc994c12ee040bd Mon Sep 17 00:00:00 2001 From: merge Date: Wed, 3 Dec 2008 11:20:14 +0000 Subject: MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-MERGE-via-master-1228302402-1228302766-1228303138 pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-MERGE-via-master-1228302402-1228302766-1228303138 / 27d86638fe294ef1d1a8f527564ec37bb20e7ef2 ... parent commitmessage: From: merge MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-MERGE-via-master-1228302402-1228302766 stable-tracking-hist top was MERGE-via-mokopatches-tracking-MERGE-via-master-1228302402-1228302766 / 66e84c4be853030f1cea816a124cf76a741ecc08 ... parent commitmessage: From: merge MERGE-via-mokopatches-tracking-hist-MERGE-via-master-1228302402 mokopatches-tracking-hist top was MERGE-via-master-1228302402 / de9177f7bd127e9b6fa6213018c7c731b8ca0d0c ... parent commitmessage: From: merge MERGE-via-master- master top was / 3838a80929f91d35c6d987e518bf9ea397f3e13c ... parent commitmessage: From: Andy Green fix-wm8753-DBG.patch Signed-off-by: Andy Green --- drivers/misc/Makefile | 1 + drivers/misc/smdk6410-sleeptest.c | 65 +++++++++++++++++++++++++++++++++++++++ drivers/serial/s3c6400.c | 1 + drivers/serial/samsung.c | 62 +++++++++++++++++++++++++++++++++++-- drivers/serial/samsung.h | 4 +++ drivers/video/s3c-fb.c | 40 ++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 drivers/misc/smdk6410-sleeptest.c (limited to 'drivers') diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 94b8fea5fb8..77efd7a7aab 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o obj-$(CONFIG_SGI_XP) += sgi-xp/ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_HP_ILO) += hpilo.o +obj-$(CONFIG_MACH_SMDK6410) += smdk6410-sleeptest.o obj-$(CONFIG_LOW_MEMORY_KILLER) += lowmemorykiller.o obj-$(CONFIG_MACH_NEO1973) += neo1973_version.o \ neo1973_pm_host.o \ diff --git a/drivers/misc/smdk6410-sleeptest.c b/drivers/misc/smdk6410-sleeptest.c new file mode 100644 index 00000000000..3bf668024fb --- /dev/null +++ b/drivers/misc/smdk6410-sleeptest.c @@ -0,0 +1,65 @@ +/* linux/drivers/misc/smdk6410-sleeptest.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks + * 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 +#include +#include +#include +#include +#include +#include + +#include + +static irqreturn_t sleep_action(int irq, void *pw) +{ + printk(KERN_INFO "%s: irq %d\n", __func__, irq); + return IRQ_HANDLED; +} + +static void sleep_setup(unsigned int irq, unsigned int gpio) +{ + int ret; + + WARN_ON(s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)) < 0); + WARN_ON(s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP) < 0); + + ret = request_irq(irq, sleep_action, IRQF_TRIGGER_FALLING, + "sleep", NULL); + if (ret < 0) + printk(KERN_ERR "%s: request_irq() failed\n", __func__); + + ret = set_irq_wake(irq, 1); + if (ret < 0) + printk(KERN_ERR "%s: set_irq_wake() failed\n", __func__); +} + +static void sleep_led(unsigned int gpio) +{ + gpio_request(gpio, "sleep led"); + gpio_direction_output(gpio, 0); +} + +static __init int smdk6410_sleeptest_init(void) +{ + sleep_setup(IRQ_EINT(10), S3C64XX_GPN(10)); + sleep_led(S3C64XX_GPN(15)); + sleep_led(S3C64XX_GPN(14)); + sleep_led(S3C64XX_GPN(13)); + sleep_led(S3C64XX_GPN(12)); + + return 0; +} + +module_init(smdk6410_sleeptest_init); + +MODULE_AUTHOR("Ben Dooks "); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c index 06936d13393..3e378523368 100644 --- a/drivers/serial/s3c6400.c +++ b/drivers/serial/s3c6400.c @@ -102,6 +102,7 @@ static struct s3c24xx_uart_info s3c6400_uart_inf = { .name = "Samsung S3C6400 UART", .type = PORT_S3C6400, .fifosize = 64, + .has_divslot = 1, .rx_fifomask = S3C2440_UFSTAT_RXMASK, .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, .rx_fifofull = S3C2440_UFSTAT_RXFULL, diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index c262eb1ae20..eca6cab0e20 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -512,6 +512,7 @@ s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) struct baud_calc { struct s3c24xx_uart_clksrc *clksrc; unsigned int calc; + unsigned int divslot; unsigned int quot; struct clk *src; }; @@ -521,6 +522,7 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc, 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); @@ -531,8 +533,24 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc, rate /= clksrc->divisor; calc->clksrc = clksrc; - calc->quot = (rate + (8 * baud)) / (16 * baud); - calc->calc = (rate / (calc->quot * 16)); + + 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; @@ -615,6 +633,30 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, 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) @@ -627,6 +669,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, unsigned int baud, quot; unsigned int ulcon; unsigned int umcon; + unsigned int udivslot = 0; /* * We don't support modem control lines. @@ -648,6 +691,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, /* 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)) { @@ -655,6 +699,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, ourport->baudclk = NULL; } + //dbg("calling clk_enable() for new baud clock\n"); clk_enable(clk); ourport->clksrc = clksrc; @@ -662,6 +707,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, 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"); @@ -701,12 +753,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); - dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); + 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), diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index 9675b2fa267..f259211279f 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h @@ -23,6 +23,10 @@ struct s3c24xx_uart_info { 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); diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 9ffb6b68a8e..09ebbc69b0c 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -962,8 +962,48 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct s3c_fb *sfb = platform_get_drvdata(pdev); + struct s3c_fb_win *win; + int win_no; + + for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) { + win = sfb->windows[win_no]; + if (!win) + continue; + + /* use the blank function to push into power-down */ + s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); + } + + clk_disable(sfb->bus_clk); + return 0; +} + +static int s3c_fb_resume(struct platform_device *pdev) +{ + struct s3c_fb *sfb = platform_get_drvdata(pdev); + struct s3c_fb_win *win; + int win_no; + + clk_enable(sfb->bus_clk); + + for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { + win = sfb->windows[win_no]; + if (!win) + continue; + + s3c_fb_set_par(win->fbinfo); + } + + return 0; +} +#else #define s3c_fb_suspend NULL #define s3c_fb_resume NULL +#endif static struct platform_driver s3c_fb_driver = { .probe = s3c_fb_probe, -- cgit v1.2.3