diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 19:49:42 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 19:49:42 +0200 |
commit | 39eda2aba6be642b71f2e0ad623dcb09fd9d79cf (patch) | |
tree | cd0c8f547847641af73e38aab2478f3119dee490 /drivers/tty | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jik... (diff) | |
parent | powerpc: Correct FSCR bit definitions (diff) | |
download | linux-39eda2aba6be642b71f2e0ad623dcb09fd9d79cf.tar.xz linux-39eda2aba6be642b71f2e0ad623dcb09fd9d79cf.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Ben Herrenschmidt:
"Here's the powerpc batch for this merge window. Some of the
highlights are:
- A bunch of endian fixes ! We don't have full LE support yet in that
release but this contains a lot of fixes all over arch/powerpc to
use the proper accessors, call the firmware with the right endian
mode, etc...
- A few updates to our "powernv" platform (non-virtualized, the one
to run KVM on), among other, support for bridging the P8 LPC bus
for UARTs, support and some EEH fixes.
- Some mpc51xx clock API cleanups in preparation for a clock API
overhaul
- A pile of cleanups of our old math emulation code, including better
support for using it to emulate optional FP instructions on
embedded chips that otherwise have a HW FPU.
- Some infrastructure in selftest, for powerpc now, but could be
generalized, initially used by some tests for our perf instruction
counting code.
- A pile of fixes for hotplug on pseries (that was seriously
bitrotting)
- The usual slew of freescale embedded updates, new boards, 64-bit
hiberation support, e6500 core PMU support, etc..."
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (146 commits)
powerpc: Correct FSCR bit definitions
powerpc/xmon: Fix printing of set of CPUs in xmon
powerpc/pseries: Move lparcfg.c to platforms/pseries
powerpc/powernv: Return secondary CPUs to firmware on kexec
powerpc/btext: Fix CONFIG_PPC_EARLY_DEBUG_BOOTX on ppc32
powerpc: Cleanup handling of the DSCR bit in the FSCR register
powerpc/pseries: Child nodes are not detached by dlpar_detach_node
powerpc/pseries: Add mising of_node_put in delete_dt_node
powerpc/pseries: Make dlpar_configure_connector parent node aware
powerpc/pseries: Do all node initialization in dlpar_parse_cc_node
powerpc/pseries: Fix parsing of initial node path in update_dt_node
powerpc/pseries: Pack update_props_workarea to map correctly to rtas buffer header
powerpc/pseries: Fix over writing of rtas return code in update_dt_node
powerpc/pseries: Fix creation of loop in device node property list
powerpc: Skip emulating & leave interrupts off for kernel program checks
powerpc: Add more exception trampolines for hypervisor exceptions
powerpc: Fix location and rename exception trampolines
powerpc: Add more trap names to xmon
powerpc/pseries: Add a warning in the case of cross-cpu VPA registration
powerpc: Update the 00-Index in Documentation/powerpc
...
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/hvc/hvc_vio.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/mpc52xx_uart.c | 98 |
2 files changed, 83 insertions, 19 deletions
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index 0c629807610e..c791b18cdd08 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -404,7 +404,7 @@ module_exit(hvc_vio_exit); void __init hvc_vio_init_early(void) { struct device_node *stdout_node; - const u32 *termno; + const __be32 *termno; const char *name; const struct hv_ops *ops; @@ -429,7 +429,7 @@ void __init hvc_vio_init_early(void) termno = of_get_property(stdout_node, "reg", NULL); if (termno == NULL) goto out; - hvterm_priv0.termno = *termno; + hvterm_priv0.termno = of_read_number(termno, 1); spin_lock_init(&hvterm_priv0.buf_lock); hvterm_privs[0] = &hvterm_priv0; diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index e1280a20b7a2..5be1df39f9f5 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -107,6 +107,8 @@ struct psc_ops { unsigned int (*set_baudrate)(struct uart_port *port, struct ktermios *new, struct ktermios *old); + int (*clock_alloc)(struct uart_port *port); + void (*clock_relse)(struct uart_port *port); int (*clock)(struct uart_port *port, int enable); int (*fifoc_init)(void); void (*fifoc_uninit)(void); @@ -616,31 +618,73 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port) return IRQ_NONE; } -static int mpc512x_psc_clock(struct uart_port *port, int enable) +static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM]; + +/* called from within the .request_port() callback (allocation) */ +static int mpc512x_psc_alloc_clock(struct uart_port *port) { - struct clk *psc_clk; int psc_num; - char clk_name[10]; + char clk_name[16]; + struct clk *clk; + int err; + + psc_num = (port->mapbase & 0xf00) >> 8; + snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num); + clk = devm_clk_get(port->dev, clk_name); + if (IS_ERR(clk)) { + dev_err(port->dev, "Failed to get MCLK!\n"); + return PTR_ERR(clk); + } + err = clk_prepare_enable(clk); + if (err) { + dev_err(port->dev, "Failed to enable MCLK!\n"); + return err; + } + psc_mclk_clk[psc_num] = clk; + return 0; +} + +/* called from within the .release_port() callback (release) */ +static void mpc512x_psc_relse_clock(struct uart_port *port) +{ + int psc_num; + struct clk *clk; + + psc_num = (port->mapbase & 0xf00) >> 8; + clk = psc_mclk_clk[psc_num]; + if (clk) { + clk_disable_unprepare(clk); + psc_mclk_clk[psc_num] = NULL; + } +} + +/* implementation of the .clock() callback (enable/disable) */ +static int mpc512x_psc_endis_clock(struct uart_port *port, int enable) +{ + int psc_num; + struct clk *psc_clk; + int ret; if (uart_console(port)) return 0; psc_num = (port->mapbase & 0xf00) >> 8; - snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num); - psc_clk = clk_get(port->dev, clk_name); - if (IS_ERR(psc_clk)) { + psc_clk = psc_mclk_clk[psc_num]; + if (!psc_clk) { dev_err(port->dev, "Failed to get PSC clock entry!\n"); return -ENODEV; } - dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis"); - - if (enable) - clk_enable(psc_clk); - else + dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis"); + if (enable) { + ret = clk_enable(psc_clk); + if (ret) + dev_err(port->dev, "Failed to enable MCLK!\n"); + return ret; + } else { clk_disable(psc_clk); - - return 0; + return 0; + } } static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) @@ -873,7 +917,9 @@ static struct psc_ops mpc5125_psc_ops = { .cw_disable_ints = mpc5125_psc_cw_disable_ints, .cw_restore_ints = mpc5125_psc_cw_restore_ints, .set_baudrate = mpc5125_psc_set_baudrate, - .clock = mpc512x_psc_clock, + .clock_alloc = mpc512x_psc_alloc_clock, + .clock_relse = mpc512x_psc_relse_clock, + .clock = mpc512x_psc_endis_clock, .fifoc_init = mpc512x_psc_fifoc_init, .fifoc_uninit = mpc512x_psc_fifoc_uninit, .get_irq = mpc512x_psc_get_irq, @@ -906,7 +952,9 @@ static struct psc_ops mpc512x_psc_ops = { .cw_disable_ints = mpc512x_psc_cw_disable_ints, .cw_restore_ints = mpc512x_psc_cw_restore_ints, .set_baudrate = mpc512x_psc_set_baudrate, - .clock = mpc512x_psc_clock, + .clock_alloc = mpc512x_psc_alloc_clock, + .clock_relse = mpc512x_psc_relse_clock, + .clock = mpc512x_psc_endis_clock, .fifoc_init = mpc512x_psc_fifoc_init, .fifoc_uninit = mpc512x_psc_fifoc_uninit, .get_irq = mpc512x_psc_get_irq, @@ -1166,6 +1214,9 @@ mpc52xx_uart_type(struct uart_port *port) static void mpc52xx_uart_release_port(struct uart_port *port) { + if (psc_ops->clock_relse) + psc_ops->clock_relse(port); + /* remapped by us ? */ if (port->flags & UPF_IOREMAP) { iounmap(port->membase); @@ -1190,11 +1241,24 @@ mpc52xx_uart_request_port(struct uart_port *port) err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; - if (err && (port->flags & UPF_IOREMAP)) { + if (err) + goto out_membase; + + if (psc_ops->clock_alloc) { + err = psc_ops->clock_alloc(port); + if (err) + goto out_mapregion; + } + + return 0; + +out_mapregion: + release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); +out_membase: + if (port->flags & UPF_IOREMAP) { iounmap(port->membase); port->membase = NULL; } - return err; } |