Skip to content

Commit 5ee063f

Browse files
MrVanabelvesa
authored andcommitted
clk: imx: lpcg-scu: SW workaround for errata (e10858)
Back-to-back LPCG writes can be ignored by the LPCG register due to a HW bug. The writes need to be separated by at least 4 cycles of the gated clock. See https://www.nxp.com.cn/docs/en/errata/IMX8_1N94W.pdf The workaround is implemented as follows: 1. For clocks running greater than or equal to 24MHz, a read followed by the write will provide sufficient delay. 2. For clocks running below 24MHz, add a delay of 4 clock cylces after the write to the LPCG register. Fixes: 2f77296 ("clk: imx: add lpcg clock support") Signed-off-by: Peng Fan <[email protected]> Reviewed-by: Abel Vesa <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Abel Vesa <[email protected]>
1 parent a27bfff commit 5ee063f

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

drivers/clk/imx/clk-lpcg-scu.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
#include <linux/bits.h>
88
#include <linux/clk-provider.h>
9+
#include <linux/delay.h>
910
#include <linux/err.h>
1011
#include <linux/io.h>
1112
#include <linux/slab.h>
1213
#include <linux/spinlock.h>
14+
#include <linux/units.h>
1315

1416
#include "clk-scu.h"
1517

@@ -41,6 +43,29 @@ struct clk_lpcg_scu {
4143

4244
#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
4345

46+
/* e10858 -LPCG clock gating register synchronization errata */
47+
static void lpcg_e10858_writel(unsigned long rate, void __iomem *reg, u32 val)
48+
{
49+
writel(val, reg);
50+
51+
if (rate >= 24 * HZ_PER_MHZ || rate == 0) {
52+
/*
53+
* The time taken to access the LPCG registers from the AP core
54+
* through the interconnect is longer than the minimum delay
55+
* of 4 clock cycles required by the errata.
56+
* Adding a readl will provide sufficient delay to prevent
57+
* back-to-back writes.
58+
*/
59+
readl(reg);
60+
} else {
61+
/*
62+
* For clocks running below 24MHz, wait a minimum of
63+
* 4 clock cycles.
64+
*/
65+
ndelay(4 * (DIV_ROUND_UP(1000 * HZ_PER_MHZ, rate)));
66+
}
67+
}
68+
4469
static int clk_lpcg_scu_enable(struct clk_hw *hw)
4570
{
4671
struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
@@ -57,7 +82,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw)
5782
val |= CLK_GATE_SCU_LPCG_HW_SEL;
5883

5984
reg |= val << clk->bit_idx;
60-
writel(reg, clk->reg);
85+
86+
lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
6187

6288
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
6389

@@ -74,7 +100,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw)
74100

75101
reg = readl_relaxed(clk->reg);
76102
reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
77-
writel(reg, clk->reg);
103+
lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
78104

79105
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
80106
}
@@ -145,13 +171,8 @@ static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
145171
{
146172
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
147173

148-
/*
149-
* FIXME: Sometimes writes don't work unless the CPU issues
150-
* them twice
151-
*/
152-
153-
writel(clk->state, clk->reg);
154174
writel(clk->state, clk->reg);
175+
lpcg_e10858_writel(0, clk->reg, clk->state);
155176
dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
156177

157178
return 0;

0 commit comments

Comments
 (0)