Commit c42a2634 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'sh-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-3.x

* 'sh-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-3.x:
  sh: fix the compile error in setup-sh7757.c
  serial: sh-sci: report CTS as active for get_mctrl
  sh: Add unaligned memory access for PC relative intructions
  sh: Fix unaligned memory access for branches without delay slots
  sh: Fix up fallout from cpuidle changes.
  serial: sh-sci: console Runtime PM support
  sh: Fix conflicting definitions of ptrace_triggered
  serial: sh-sci: fix DMA build by including dma-mapping.h
  serial: sh-sci: Fix up default regtype probing.
  sh: intc: enable both edges GPIO interrupts on sh7372
  shwdt: fix usage of mod_timer
  clocksource: sh_cmt: wait for CMCNT on init V2
parents f9557a44 21d41f2b
...@@ -123,7 +123,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, ...@@ -123,7 +123,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
struct perf_event; struct perf_event;
struct perf_sample_data; struct perf_sample_data;
extern void ptrace_triggered(struct perf_event *bp, int nmi, extern void ptrace_triggered(struct perf_event *bp,
struct perf_sample_data *data, struct pt_regs *regs); struct perf_sample_data *data, struct pt_regs *regs);
#define task_pt_regs(task) \ #define task_pt_regs(task) \
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/serial_sci.h> #include <linux/serial_sci.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/sh_timer.h> #include <linux/sh_timer.h>
#include <linux/sh_dma.h> #include <linux/sh_dma.h>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#include <asm/smp.h> #include <asm/smp.h>
static void (*pm_idle)(void); void (*pm_idle)(void);
static int hlt_counter; static int hlt_counter;
......
...@@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs, ...@@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
break; break;
} }
break; break;
case 9: /* mov.w @(disp,PC),Rn */
srcu = (unsigned char __user *)regs->pc;
srcu += 4;
srcu += (instruction & 0x00FF) << 1;
dst = (unsigned char *)rn;
*(unsigned long *)dst = 0;
#if !defined(__LITTLE_ENDIAN__)
dst += 2;
#endif
if (ma->from(dst, srcu, 2))
goto fetch_fault;
sign_extend(2, dst);
ret = 0;
break;
case 0xd: /* mov.l @(disp,PC),Rn */
srcu = (unsigned char __user *)(regs->pc & ~0x3);
srcu += 4;
srcu += (instruction & 0x00FF) << 2;
dst = (unsigned char *)rn;
*(unsigned long *)dst = 0;
if (ma->from(dst, srcu, 4))
goto fetch_fault;
ret = 0;
break;
} }
return ret; return ret;
...@@ -466,6 +495,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, ...@@ -466,6 +495,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
case 0x0500: /* mov.w @(disp,Rm),R0 */ case 0x0500: /* mov.w @(disp,Rm),R0 */
goto simple; goto simple;
case 0x0B00: /* bf lab - no delayslot*/ case 0x0B00: /* bf lab - no delayslot*/
ret = 0;
break; break;
case 0x0F00: /* bf/s lab */ case 0x0F00: /* bf/s lab */
ret = handle_delayslot(regs, instruction, ma); ret = handle_delayslot(regs, instruction, ma);
...@@ -479,6 +509,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, ...@@ -479,6 +509,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
} }
break; break;
case 0x0900: /* bt lab - no delayslot */ case 0x0900: /* bt lab - no delayslot */
ret = 0;
break; break;
case 0x0D00: /* bt/s lab */ case 0x0D00: /* bt/s lab */
ret = handle_delayslot(regs, instruction, ma); ret = handle_delayslot(regs, instruction, ma);
...@@ -494,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, ...@@ -494,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
} }
break; break;
case 0x9000: /* mov.w @(disp,Rm),Rn */
goto simple;
case 0xA000: /* bra label */ case 0xA000: /* bra label */
ret = handle_delayslot(regs, instruction, ma); ret = handle_delayslot(regs, instruction, ma);
if (ret==0) if (ret==0)
...@@ -507,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, ...@@ -507,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
regs->pc += SH_PC_12BIT_OFFSET(instruction); regs->pc += SH_PC_12BIT_OFFSET(instruction);
} }
break; break;
case 0xD000: /* mov.l @(disp,Rm),Rn */
goto simple;
} }
return ret; return ret;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/sh_timer.h> #include <linux/sh_timer.h>
...@@ -150,13 +151,13 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) ...@@ -150,13 +151,13 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
{ {
int ret; int k, ret;
/* enable clock */ /* enable clock */
ret = clk_enable(p->clk); ret = clk_enable(p->clk);
if (ret) { if (ret) {
dev_err(&p->pdev->dev, "cannot enable clock\n"); dev_err(&p->pdev->dev, "cannot enable clock\n");
return ret; goto err0;
} }
/* make sure channel is disabled */ /* make sure channel is disabled */
...@@ -174,9 +175,38 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) ...@@ -174,9 +175,38 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
sh_cmt_write(p, CMCOR, 0xffffffff); sh_cmt_write(p, CMCOR, 0xffffffff);
sh_cmt_write(p, CMCNT, 0); sh_cmt_write(p, CMCNT, 0);
/*
* According to the sh73a0 user's manual, as CMCNT can be operated
* only by the RCLK (Pseudo 32 KHz), there's one restriction on
* modifying CMCNT register; two RCLK cycles are necessary before
* this register is either read or any modification of the value
* it holds is reflected in the LSI's actual operation.
*
* While at it, we're supposed to clear out the CMCNT as of this
* moment, so make sure it's processed properly here. This will
* take RCLKx2 at maximum.
*/
for (k = 0; k < 100; k++) {
if (!sh_cmt_read(p, CMCNT))
break;
udelay(1);
}
if (sh_cmt_read(p, CMCNT)) {
dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
ret = -ETIMEDOUT;
goto err1;
}
/* enable channel */ /* enable channel */
sh_cmt_start_stop_ch(p, 1); sh_cmt_start_stop_ch(p, 1);
return 0; return 0;
err1:
/* stop clock */
clk_disable(p->clk);
err0:
return ret;
} }
static void sh_cmt_disable(struct sh_cmt_priv *p) static void sh_cmt_disable(struct sh_cmt_priv *p)
......
...@@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { ...@@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
!defined(CONFIG_CPU_SUBTYPE_SH7709) !defined(CONFIG_CPU_SUBTYPE_SH7709)
[IRQ_TYPE_LEVEL_HIGH] = VALID(3), [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
#endif #endif
#if defined(CONFIG_ARCH_SH7372)
[IRQ_TYPE_EDGE_BOTH] = VALID(4),
#endif
}; };
static int intc_set_type(struct irq_data *data, unsigned int type) static int intc_set_type(struct irq_data *data, unsigned int type)
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -95,6 +96,12 @@ struct sci_port { ...@@ -95,6 +96,12 @@ struct sci_port {
#endif #endif
struct notifier_block freq_transition; struct notifier_block freq_transition;
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
unsigned short saved_smr;
unsigned short saved_fcr;
unsigned char saved_brr;
#endif
}; };
/* Function prototypes */ /* Function prototypes */
...@@ -1076,7 +1083,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port) ...@@ -1076,7 +1083,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
/* This routine is used for getting signals of: DTR, DCD, DSR, RI, /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
and CTS/RTS */ and CTS/RTS */
return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
} }
#ifdef CONFIG_SERIAL_SH_SCI_DMA #ifdef CONFIG_SERIAL_SH_SCI_DMA
...@@ -1633,11 +1640,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, ...@@ -1633,11 +1640,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
return ((freq + 16 * bps) / (32 * bps) - 1); return ((freq + 16 * bps) / (32 * bps) - 1);
} }
static void sci_reset(struct uart_port *port)
{
unsigned int status;
do {
status = sci_in(port, SCxSR);
} while (!(status & SCxSR_TEND(port)));
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
if (port->type != PORT_SCI)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
}
static void sci_set_termios(struct uart_port *port, struct ktermios *termios, static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
struct sci_port *s = to_sci_port(port); struct sci_port *s = to_sci_port(port);
unsigned int status, baud, smr_val, max_baud; unsigned int baud, smr_val, max_baud;
int t = -1; int t = -1;
u16 scfcr = 0; u16 scfcr = 0;
...@@ -1657,14 +1678,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1657,14 +1678,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_port_enable(s); sci_port_enable(s);
do { sci_reset(port);
status = sci_in(port, SCxSR);
} while (!(status & SCxSR_TEND(port)));
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
if (port->type != PORT_SCI)
sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
smr_val = sci_in(port, SCSMR) & 3; smr_val = sci_in(port, SCSMR) & 3;
...@@ -2037,7 +2051,8 @@ static int __devinit serial_console_setup(struct console *co, char *options) ...@@ -2037,7 +2051,8 @@ static int __devinit serial_console_setup(struct console *co, char *options)
if (options) if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow); uart_parse_options(options, &baud, &parity, &bits, &flow);
/* TODO: disable clock */ sci_port_disable(sci_port);
return uart_set_options(port, co, baud, parity, bits, flow); return uart_set_options(port, co, baud, parity, bits, flow);
} }
...@@ -2080,6 +2095,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev) ...@@ -2080,6 +2095,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
return 0; return 0;
} }
#define uart_console(port) ((port)->cons->index == (port)->line)
static int sci_runtime_suspend(struct device *dev)
{
struct sci_port *sci_port = dev_get_drvdata(dev);
struct uart_port *port = &sci_port->port;
if (uart_console(port)) {
sci_port->saved_smr = sci_in(port, SCSMR);
sci_port->saved_brr = sci_in(port, SCBRR);
sci_port->saved_fcr = sci_in(port, SCFCR);
}
return 0;
}
static int sci_runtime_resume(struct device *dev)
{
struct sci_port *sci_port = dev_get_drvdata(dev);
struct uart_port *port = &sci_port->port;
if (uart_console(port)) {
sci_reset(port);
sci_out(port, SCSMR, sci_port->saved_smr);
sci_out(port, SCBRR, sci_port->saved_brr);
sci_out(port, SCFCR, sci_port->saved_fcr);
sci_out(port, SCSCR, sci_port->cfg->scscr);
}
return 0;
}
#define SCI_CONSOLE (&serial_console) #define SCI_CONSOLE (&serial_console)
#else #else
...@@ -2089,6 +2134,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev) ...@@ -2089,6 +2134,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
} }
#define SCI_CONSOLE NULL #define SCI_CONSOLE NULL
#define sci_runtime_suspend NULL
#define sci_runtime_resume NULL
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
...@@ -2204,6 +2251,8 @@ static int sci_resume(struct device *dev) ...@@ -2204,6 +2251,8 @@ static int sci_resume(struct device *dev)
} }
static const struct dev_pm_ops sci_dev_pm_ops = { static const struct dev_pm_ops sci_dev_pm_ops = {
.runtime_suspend = sci_runtime_suspend,
.runtime_resume = sci_runtime_resume,
.suspend = sci_suspend, .suspend = sci_suspend,
.resume = sci_resume, .resume = sci_resume,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment