From c8623487a0716301221dfbceee63856ed6f0c15f Mon Sep 17 00:00:00 2001 From: Dien Pham Date: Wed, 11 Apr 2018 16:19:03 +0700 Subject: [PATCH 1/6] soc: renesas: rcar-sysc: Update power control flow for SYSCEXTMASK register On H3 v3.0, it can observe the system hang up after changing power domains many times (~2000 times) continuously. This occurs because there is conflict when changing state of power domains. To overcome this issue, power domain on/off control flow need to be updated. It needs to set/clear value of SYSCEXTMASK register. This patch is updated for above purpose. Signed-off-by: Dien Pham --- drivers/soc/renesas/rcar-sysc.c | 22 +++++++++++++++++++++- drivers/soc/renesas/rcar-sysc.h | 8 ++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index a063887..b170f9b 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -96,10 +96,24 @@ static void __iomem *rcar_sysc_base; static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ - +static struct rcar_sysc_extra_regs *extra_regs; static const char *to_pd_name(const struct rcar_sysc_ch *sysc_ch); +static void rcar_sysc_extmask_ctrl(bool on) +{ + u32 extmask_msks = 0; + + if (!extra_regs || !extra_regs->sysc_extmask_msks) + return; + + if (on) + extmask_msks = extra_regs->sysc_extmask_msks; + + iowrite32(extmask_msks, + rcar_sysc_base + extra_regs->sysc_extmask_offs); +} + static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) { unsigned int sr_bit, reg_offs; @@ -147,6 +161,7 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) spin_lock_irqsave(&rcar_sysc_lock, flags); + rcar_sysc_extmask_ctrl(1); /* set EXTMSK0 */ iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); /* Submit power shutoff or resume request until it was accepted */ @@ -181,6 +196,7 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); out: + rcar_sysc_extmask_ctrl(0); /* clear EXTMSK0 */ spin_unlock_irqrestore(&rcar_sysc_lock, flags); pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", @@ -436,6 +452,10 @@ static int __init rcar_sysc_pd_init(void) rcar_sysc_base = base; + /* Check and get extra registers */ + if (info->extra_regs) + extra_regs = info->extra_regs; + domains = kzalloc(sizeof(*domains), GFP_KERNEL); if (!domains) { error = -ENOMEM; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index cfc7e30..1c3aedb 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -38,6 +38,13 @@ struct rcar_sysc_area { unsigned int flags; /* See PD_* */ }; +/* + * List of registers that are not common in all platform. + */ +struct rcar_sysc_extra_regs { + u16 sysc_extmask_offs; /* Offset of SYSCEXTMASK register */ + u32 sysc_extmask_msks; /* Mask value of SYSCEXTMASK register */ +}; /* * SoC-specific Power Area Description @@ -47,6 +54,7 @@ struct rcar_sysc_info { int (*init)(void); /* Optional */ const struct rcar_sysc_area *areas; unsigned int num_areas; + struct rcar_sysc_extra_regs *extra_regs; }; extern const struct rcar_sysc_info r8a7743_sysc_info; -- 1.9.1