Skip to content

Commit

Permalink
Merge branch 'sh-fixes-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed Aug 29, 2011
2 parents f9557a4 + 21d41f2 commit c42a263
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 15 deletions.
2 changes: 1 addition & 1 deletion arch/sh/include/asm/ptrace.h
Expand Up @@ -123,7 +123,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
struct perf_event;
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);

#define task_pt_regs(task) \
Expand Down
1 change: 1 addition & 0 deletions arch/sh/kernel/cpu/sh4a/setup-sh7757.c
Expand Up @@ -15,6 +15,7 @@
#include <linux/serial_sci.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/sh_timer.h>
#include <linux/sh_dma.h>

Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/idle.c
Expand Up @@ -22,7 +22,7 @@
#include <linux/atomic.h>
#include <asm/smp.h>

static void (*pm_idle)(void);
void (*pm_idle)(void);

static int hlt_counter;

Expand Down
37 changes: 37 additions & 0 deletions arch/sh/kernel/traps_32.c
Expand Up @@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
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;

Expand Down Expand Up @@ -466,6 +495,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
case 0x0500: /* mov.w @(disp,Rm),R0 */
goto simple;
case 0x0B00: /* bf lab - no delayslot*/
ret = 0;
break;
case 0x0F00: /* bf/s lab */
ret = handle_delayslot(regs, instruction, ma);
Expand All @@ -479,6 +509,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
}
break;
case 0x0900: /* bt lab - no delayslot */
ret = 0;
break;
case 0x0D00: /* bt/s lab */
ret = handle_delayslot(regs, instruction, ma);
Expand All @@ -494,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
}
break;

case 0x9000: /* mov.w @(disp,Rm),Rn */
goto simple;

case 0xA000: /* bra label */
ret = handle_delayslot(regs, instruction, ma);
if (ret==0)
Expand All @@ -507,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
regs->pc += SH_PC_12BIT_OFFSET(instruction);
}
break;

case 0xD000: /* mov.l @(disp,Rm),Rn */
goto simple;
}
return ret;

Expand Down
34 changes: 32 additions & 2 deletions drivers/clocksource/sh_cmt.c
Expand Up @@ -26,6 +26,7 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/sh_timer.h>
Expand Down Expand Up @@ -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)
{
int ret;
int k, ret;

/* enable clock */
ret = clk_enable(p->clk);
if (ret) {
dev_err(&p->pdev->dev, "cannot enable clock\n");
return ret;
goto err0;
}

/* make sure channel is disabled */
Expand All @@ -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, 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 */
sh_cmt_start_stop_ch(p, 1);
return 0;
err1:
/* stop clock */
clk_disable(p->clk);

err0:
return ret;
}

static void sh_cmt_disable(struct sh_cmt_priv *p)
Expand Down
3 changes: 3 additions & 0 deletions drivers/sh/intc/chip.c
Expand Up @@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
!defined(CONFIG_CPU_SUBTYPE_SH7709)
[IRQ_TYPE_LEVEL_HIGH] = VALID(3),
#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)
Expand Down
71 changes: 60 additions & 11 deletions drivers/tty/serial/sh-sci.c
Expand Up @@ -47,6 +47,7 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>

Expand Down Expand Up @@ -95,6 +96,12 @@ struct sci_port {
#endif

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 */
Expand Down Expand Up @@ -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,
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
Expand Down Expand Up @@ -1633,11 +1640,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
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,
struct ktermios *old)
{
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;
u16 scfcr = 0;

Expand All @@ -1657,14 +1678,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,

sci_port_enable(s);

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 | SCFCR_RFRST | SCFCR_TFRST);
sci_reset(port);

smr_val = sci_in(port, SCSMR) & 3;

Expand Down Expand Up @@ -2037,7 +2051,8 @@ static int __devinit serial_console_setup(struct console *co, char *options)
if (options)
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);
}

Expand Down Expand Up @@ -2080,6 +2095,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
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)

#else
Expand All @@ -2089,6 +2134,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
}

#define SCI_CONSOLE NULL
#define sci_runtime_suspend NULL
#define sci_runtime_resume NULL

#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */

Expand Down Expand Up @@ -2204,6 +2251,8 @@ static int sci_resume(struct device *dev)
}

static const struct dev_pm_ops sci_dev_pm_ops = {
.runtime_suspend = sci_runtime_suspend,
.runtime_resume = sci_runtime_resume,
.suspend = sci_suspend,
.resume = sci_resume,
};
Expand Down

0 comments on commit c42a263

Please sign in to comment.