diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 10:43:56 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 10:43:56 -0700 |
commit | 660fc1f4d88b0f5e4bb936e4a5a9b95b70df9e58 (patch) | |
tree | a5b5de254f9b4378d77171e2a5d6496ec8e3e3f5 /drivers/serial | |
parent | 3dd730f2b49f101b90d283c3efc4e6cd826dd8f6 (diff) | |
parent | ce0ad7f0952581ba75ab6aee55bb1ed9bb22cf4f (diff) | |
download | blackbird-op-linux-660fc1f4d88b0f5e4bb936e4a5a9b95b70df9e58.tar.gz blackbird-op-linux-660fc1f4d88b0f5e4bb936e4a5a9b95b70df9e58.zip |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
powerpc/mm: Lockless get_user_pages_fast() for 64-bit (v3)
powerpc: Don't use the wrong thread_struct for ptrace get/set VSX regs
powerpc: Fix ptrace buffer size for VSX
powerpc: Correctly hookup PTRACE_GET/SETVSRREGS for 32 bit processes
ide/powermac: Fix use of uninitialized pointer on media-bay
powerpc: Allow non-hcall return values for lparcfg writes
ipmi/powerpc: Use linux/of_{device,platform}.h instead of asm
powerpc/fsl: proliferate simple-bus compatibility to soc nodes
Documentation: remove old sbc8260 board specific information
cpm2: Rework baud rate generators configuration to support external clocks.
powerpc: rtc_cmos_setup: assign interrupts only if there is i8259 PIC
cpm_uart: Add generic clock API support to set baudrates
cpm_uart: Modem control lines support
powerpc: implement GPIO LIB API on CPM1 Freescale SoC.
cpm2: Implement GPIO LIB API on CPM2 Freescale SoC.
powerpc: Fix 8xx build failure
powerpc: clean up the Book-E HW watchpoint support
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart.h | 11 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 66 |
2 files changed, 67 insertions, 10 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 5c76e0ae0582..7274b527a3c1 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -50,6 +50,15 @@ #define SCC_WAIT_CLOSING 100 +#define GPIO_CTS 0 +#define GPIO_RTS 1 +#define GPIO_DCD 2 +#define GPIO_DSR 3 +#define GPIO_DTR 4 +#define GPIO_RI 5 + +#define NUM_GPIOS (GPIO_RI+1) + struct uart_cpm_port { struct uart_port port; u16 rx_nrfifos; @@ -68,6 +77,7 @@ struct uart_cpm_port { unsigned char *rx_buf; u32 flags; void (*set_lineif)(struct uart_cpm_port *); + struct clk *clk; u8 brg; uint dp_addr; void *mem_addr; @@ -82,6 +92,7 @@ struct uart_cpm_port { int wait_closing; /* value to combine with opcode to form cpm command */ u32 command; + int gpios[NUM_GPIOS]; }; extern int cpm_uart_nr; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index a4f86927a74b..25efca5a7a1f 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -43,6 +43,9 @@ #include <linux/dma-mapping.h> #include <linux/fs_uart_pd.h> #include <linux/of_platform.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <linux/clk.h> #include <asm/io.h> #include <asm/irq.h> @@ -96,13 +99,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port) static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* Whee. Do nothing. */ + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + + if (pinfo->gpios[GPIO_RTS] >= 0) + gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); + + if (pinfo->gpios[GPIO_DTR] >= 0) + gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR)); } static unsigned int cpm_uart_get_mctrl(struct uart_port *port) { - /* Whee. Do nothing. */ - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + if (pinfo->gpios[GPIO_CTS] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_CTS])) + mctrl &= ~TIOCM_CTS; + } + + if (pinfo->gpios[GPIO_DSR] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_DSR])) + mctrl &= ~TIOCM_DSR; + } + + if (pinfo->gpios[GPIO_DCD] >= 0) { + if (gpio_get_value(pinfo->gpios[GPIO_DCD])) + mctrl &= ~TIOCM_CAR; + } + + if (pinfo->gpios[GPIO_RI] >= 0) { + if (!gpio_get_value(pinfo->gpios[GPIO_RI])) + mctrl |= TIOCM_RNG; + } + + return mctrl; } /* @@ -566,7 +597,10 @@ static void cpm_uart_set_termios(struct uart_port *port, out_be16(&sccp->scc_psmr, (sbits << 12) | scval); } - cpm_set_brg(pinfo->brg - 1, baud); + if (pinfo->clk) + clk_set_rate(pinfo->clk, baud); + else + cpm_set_brg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); } @@ -991,14 +1025,23 @@ static int cpm_uart_init_port(struct device_node *np, void __iomem *mem, *pram; int len; int ret; + int i; - data = of_get_property(np, "fsl,cpm-brg", &len); - if (!data || len != 4) { - printk(KERN_ERR "CPM UART %s has no/invalid " - "fsl,cpm-brg property.\n", np->name); - return -EINVAL; + data = of_get_property(np, "clock", NULL); + if (data) { + struct clk *clk = clk_get(NULL, (const char*)data); + if (!IS_ERR(clk)) + pinfo->clk = clk; + } + if (!pinfo->clk) { + data = of_get_property(np, "fsl,cpm-brg", &len); + if (!data || len != 4) { + printk(KERN_ERR "CPM UART %s has no/invalid " + "fsl,cpm-brg property.\n", np->name); + return -EINVAL; + } + pinfo->brg = *data; } - pinfo->brg = *data; data = of_get_property(np, "fsl,cpm-command", &len); if (!data || len != 4) { @@ -1050,6 +1093,9 @@ static int cpm_uart_init_port(struct device_node *np, goto out_pram; } + for (i = 0; i < NUM_GPIOS; i++) + pinfo->gpios[i] = of_get_gpio(np, i); + return cpm_uart_request_port(&pinfo->port); out_pram: |