diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 2e20e650b6c01b..8a509d6b28a937 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -29,7 +29,7 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) else addr = common->base + common->reg; - WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000)); + WARN_ON(readl_relaxed_poll_timeout_atomic(addr, reg, reg & lock, 100, 70000)); } /* diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index bda87b38c45c93..b481265605b229 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -204,6 +204,14 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, spin_lock_irqsave(nkmp->common.lock, flags); + reg = readl(nkmp->common.base + nkmp->common.reg); + reg &= ~BIT(29); + writel(reg, nkmp->common.base + nkmp->common.reg); + + reg = readl(nkmp->common.base + nkmp->common.reg); + reg &= ~BIT(28); + writel(reg, nkmp->common.base + nkmp->common.reg); + reg = readl(nkmp->common.base + nkmp->common.reg); reg &= ~(n_mask | k_mask | m_mask | p_mask); @@ -214,10 +222,26 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, writel(reg, nkmp->common.base + nkmp->common.reg); - spin_unlock_irqrestore(nkmp->common.lock, flags); + reg = readl(nkmp->common.base + nkmp->common.reg); + reg |= BIT(28); + writel(reg, nkmp->common.base + nkmp->common.reg); + + reg = readl(nkmp->common.base + nkmp->common.reg); + reg |= BIT(29); + writel(reg, nkmp->common.base + nkmp->common.reg); ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock); + reg = readl(nkmp->common.base + nkmp->common.reg); + reg &= ~BIT(29); + writel(reg, nkmp->common.base + nkmp->common.reg); + + reg = readl(nkmp->common.base + nkmp->common.reg); + reg &= ~BIT(28); + writel(reg, nkmp->common.base + nkmp->common.reg); + + spin_unlock_irqrestore(nkmp->common.lock, flags); + return 0; }