#include <dt-bindings/clock/thead,th1520-clk-ap.h>
#include <linux/bitfield.h>
#include <linux/clk-provider.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#define TH1520_PLL_STS 0x80
+
#define TH1520_PLL_POSTDIV2 GENMASK(26, 24)
#define TH1520_PLL_POSTDIV1 GENMASK(22, 20)
#define TH1520_PLL_FBDIV GENMASK(19, 8)
#define TH1520_PLL_FRAC GENMASK(23, 0)
#define TH1520_PLL_FRAC_BITS 24
+/*
+ * All PLLs in TH1520 take 21250ns at maximum to lock, let's take its double
+ * for safety.
+ */
+#define TH1520_PLL_LOCK_TIMEOUT_US 44
+#define TH1520_PLL_STABLE_DELAY_US 30
+
struct ccu_internal {
u8 shift;
u8 width;
struct ccu_pll {
struct ccu_common common;
+ u32 lock_sts_mask;
};
#define TH_CCU_ARG(_shift, _width) \
static int ccu_pll_enable(struct clk_hw *hw)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
+ u32 reg;
+ int ret;
- return regmap_clear_bits(pll->common.map, pll->common.cfg1,
- TH1520_PLL_VCO_RST);
+ regmap_clear_bits(pll->common.map, pll->common.cfg1,
+ TH1520_PLL_VCO_RST);
+
+ ret = regmap_read_poll_timeout_atomic(pll->common.map, TH1520_PLL_STS,
+ reg, reg & pll->lock_sts_mask,
+ 5, TH1520_PLL_LOCK_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ udelay(TH1520_PLL_STABLE_DELAY_US);
+
+ return 0;
}
static int ccu_pll_is_enabled(struct clk_hw *hw)
&clk_pll_ops,
CLK_IS_CRITICAL),
},
+ .lock_sts_mask = BIT(1),
};
static struct ccu_pll cpu_pll1_clk = {
&clk_pll_ops,
CLK_IS_CRITICAL),
},
+ .lock_sts_mask = BIT(4),
};
static struct ccu_pll gmac_pll_clk = {
&clk_pll_ops,
CLK_IS_CRITICAL),
},
+ .lock_sts_mask = BIT(3),
};
static const struct clk_hw *gmac_pll_clk_parent[] = {
&clk_pll_ops,
CLK_IS_CRITICAL),
},
+ .lock_sts_mask = BIT(7),
};
static const struct clk_hw *video_pll_clk_parent[] = {
&clk_pll_ops,
0),
},
+ .lock_sts_mask = BIT(8),
};
static const struct clk_hw *dpu0_pll_clk_parent[] = {
&clk_pll_ops,
0),
},
+ .lock_sts_mask = BIT(9),
};
static const struct clk_hw *dpu1_pll_clk_parent[] = {
&clk_pll_ops,
CLK_IS_CRITICAL),
},
+ .lock_sts_mask = BIT(10),
};
static const struct clk_parent_data c910_i0_parents[] = {