MIPS: Lantiq: Add locking for PMU register and check status afterwards
The PMU register are accessed in a non atomic way and they could be accessed by different threads simultaneously, which could cause problems this patch adds locking around the PMU registers. In addition we now also wait till the PMU is actually deactivated. [ralf@linux-mips.org: Fix spelling mistake in commit message as noticed by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>.] Signed-off-by: Hauke Mehrtens <hauke.mehrtens@lantiq.com> Acked-by: John Crispin <blogic@openwrt.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11381/ Patchwork: https://patchwork.linux-mips.org/patch/11396/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
d8cfb5037b
commit
cab7b8363c
|
@ -4,6 +4,7 @@
|
||||||
* by the Free Software Foundation.
|
* by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
|
* Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
|
||||||
|
* Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -85,15 +86,19 @@ void __iomem *ltq_ebu_membase;
|
||||||
static u32 ifccr = CGU_IFCCR;
|
static u32 ifccr = CGU_IFCCR;
|
||||||
static u32 pcicr = CGU_PCICR;
|
static u32 pcicr = CGU_PCICR;
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(g_pmu_lock);
|
||||||
|
|
||||||
/* legacy function kept alive to ease clkdev transition */
|
/* legacy function kept alive to ease clkdev transition */
|
||||||
void ltq_pmu_enable(unsigned int module)
|
void ltq_pmu_enable(unsigned int module)
|
||||||
{
|
{
|
||||||
int err = 1000000;
|
int retry = 1000000;
|
||||||
|
|
||||||
|
spin_lock(&g_pmu_lock);
|
||||||
pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
|
pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
|
||||||
do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
|
do {} while (--retry && (pmu_r32(PMU_PWDSR) & module));
|
||||||
|
spin_unlock(&g_pmu_lock);
|
||||||
|
|
||||||
if (!err)
|
if (!retry)
|
||||||
panic("activating PMU module failed!");
|
panic("activating PMU module failed!");
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ltq_pmu_enable);
|
EXPORT_SYMBOL(ltq_pmu_enable);
|
||||||
|
@ -101,7 +106,15 @@ EXPORT_SYMBOL(ltq_pmu_enable);
|
||||||
/* legacy function kept alive to ease clkdev transition */
|
/* legacy function kept alive to ease clkdev transition */
|
||||||
void ltq_pmu_disable(unsigned int module)
|
void ltq_pmu_disable(unsigned int module)
|
||||||
{
|
{
|
||||||
|
int retry = 1000000;
|
||||||
|
|
||||||
|
spin_lock(&g_pmu_lock);
|
||||||
pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
|
pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
|
||||||
|
do {} while (--retry && (!(pmu_r32(PMU_PWDSR) & module)));
|
||||||
|
spin_unlock(&g_pmu_lock);
|
||||||
|
|
||||||
|
if (!retry)
|
||||||
|
pr_warn("deactivating PMU module failed!");
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ltq_pmu_disable);
|
EXPORT_SYMBOL(ltq_pmu_disable);
|
||||||
|
|
||||||
|
@ -123,9 +136,11 @@ static int pmu_enable(struct clk *clk)
|
||||||
{
|
{
|
||||||
int retry = 1000000;
|
int retry = 1000000;
|
||||||
|
|
||||||
|
spin_lock(&g_pmu_lock);
|
||||||
pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
|
pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
|
||||||
PWDCR(clk->module));
|
PWDCR(clk->module));
|
||||||
do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
|
do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
|
||||||
|
spin_unlock(&g_pmu_lock);
|
||||||
|
|
||||||
if (!retry)
|
if (!retry)
|
||||||
panic("activating PMU module failed!");
|
panic("activating PMU module failed!");
|
||||||
|
@ -136,8 +151,15 @@ static int pmu_enable(struct clk *clk)
|
||||||
/* disable a clock gate */
|
/* disable a clock gate */
|
||||||
static void pmu_disable(struct clk *clk)
|
static void pmu_disable(struct clk *clk)
|
||||||
{
|
{
|
||||||
pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
|
int retry = 1000000;
|
||||||
PWDCR(clk->module));
|
|
||||||
|
spin_lock(&g_pmu_lock);
|
||||||
|
pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, PWDCR(clk->module));
|
||||||
|
do {} while (--retry && (!(pmu_r32(PWDSR(clk->module)) & clk->bits)));
|
||||||
|
spin_unlock(&g_pmu_lock);
|
||||||
|
|
||||||
|
if (!retry)
|
||||||
|
pr_warn("deactivating PMU module failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the pci enable helper */
|
/* the pci enable helper */
|
||||||
|
|
Loading…
Reference in New Issue