aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishal Mahaveer2024-07-31 17:06:27 -0500
committerPraneeth Bajjuri2024-08-08 12:55:18 -0500
commitbfe8f8b84b1efd6630d9b228325b80631fd9d3c9 (patch)
treed4391896465c7f85d57fe71b9c0ec830a63d20b9
parent3a5205e9803809f18edc59a40fd9df470f98a00f (diff)
downloadti-u-boot-bfe8f8b84b1efd6630d9b228325b80631fd9d3c9.tar.gz
ti-u-boot-bfe8f8b84b1efd6630d9b228325b80631fd9d3c9.tar.xz
ti-u-boot-bfe8f8b84b1efd6630d9b228325b80631fd9d3c9.zip
clk: ti: k3-pll: Add calibration support for non fractional mode
PLL calibration needs to be enabled when operating in non fractional mode. Add the sequence to do a fast calibration when using PLL in this mode. Signed-off-by: Vishal Mahaveer <vishalm@ti.com>
-rw-r--r--drivers/clk/clk-k3-pll.c81
1 files changed, 75 insertions, 6 deletions
diff --git a/drivers/clk/clk-k3-pll.c b/drivers/clk/clk-k3-pll.c
index bf762c558ef..c1158c13290 100644
--- a/drivers/clk/clk-k3-pll.c
+++ b/drivers/clk/clk-k3-pll.c
@@ -25,6 +25,23 @@
25#define PLL_16FFT_FREQ_CTRL0 0x30 25#define PLL_16FFT_FREQ_CTRL0 0x30
26#define PLL_16FFT_FREQ_CTRL1 0x34 26#define PLL_16FFT_FREQ_CTRL1 0x34
27#define PLL_16FFT_DIV_CTRL 0x38 27#define PLL_16FFT_DIV_CTRL 0x38
28#define PLL_16FFT_CAL_CTRL 0x60
29#define PLL_16FFT_CAL_STAT 0x64
30
31/* CAL STAT register bits */
32#define PLL_16FFT_CAL_STAT_CAL_LOCK BIT(31)
33
34/* CFG register bits */
35#define PLL_16FFT_CFG_PLL_TYPE_SHIFT (0)
36#define PLL_16FFT_CFG_PLL_TYPE_MASK (0x3 << 0)
37#define PLL_16FFT_CFG_PLL_TYPE_FRACF 1
38
39/* CAL CTRL register bits */
40#define PLL_16FFT_CAL_CTRL_CAL_EN BIT(31)
41#define PLL_16FFT_CAL_CTRL_FAST_CAL BIT(20)
42#define PLL_16FFT_CAL_CTRL_CAL_BYP BIT(15)
43#define PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT 16
44#define PLL_16FFT_CAL_CTRL_CAL_CNT_MASK (0x7 << 16)
28 45
29/* CTRL register bits */ 46/* CTRL register bits */
30#define PLL_16FFT_CTRL_BYPASS_EN BIT(31) 47#define PLL_16FFT_CTRL_BYPASS_EN BIT(31)
@@ -40,9 +57,14 @@
40/* DIV CTRL register bits */ 57/* DIV CTRL register bits */
41#define PLL_16FFT_DIV_CTRL_REF_DIV_MASK 0x3f 58#define PLL_16FFT_DIV_CTRL_REF_DIV_MASK 0x3f
42 59
43#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24 60/* HSDIV register bits*/
44#define PLL_16FFT_HSDIV_CTRL_CLKOUT_EN BIT(15) 61#define PLL_16FFT_HSDIV_CTRL_CLKOUT_EN BIT(15)
45 62
63/* FREQ_CTRL1 bits */
64#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24
65#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK 0xffffff
66#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT 0
67
46/* KICK register magic values */ 68/* KICK register magic values */
47#define PLL_KICK0_VALUE 0x68ef3490 69#define PLL_KICK0_VALUE 0x68ef3490
48#define PLL_KICK1_VALUE 0xd172bc5a 70#define PLL_KICK1_VALUE 0xd172bc5a
@@ -63,18 +85,65 @@ static int ti_pll_wait_for_lock(struct clk *clk)
63{ 85{
64 struct ti_pll_clk *pll = to_clk_pll(clk); 86 struct ti_pll_clk *pll = to_clk_pll(clk);
65 u32 stat; 87 u32 stat;
88 u32 cfg;
89 u32 cal;
90 u32 freq_ctrl1;
66 int i; 91 int i;
92 u32 pllfm;
93 u32 pll_type;
94 int success;
67 95
68 for (i = 0; i < 100000; i++) { 96 for (i = 0; i < 100000; i++) {
69 stat = readl(pll->reg + PLL_16FFT_STAT); 97 stat = readl(pll->reg + PLL_16FFT_STAT);
70 if (stat & PLL_16FFT_STAT_LOCK) 98 if (stat & PLL_16FFT_STAT_LOCK) {
71 return 0; 99 success = 1;
100 break;
101 }
72 } 102 }
73 103
74 printf("%s: pll (%s) failed to lock\n", __func__, 104 /* Enable calibration if not in fractional mode of the FRACF PLL */
75 clk->dev->name); 105 freq_ctrl1 = readl(pll->reg + PLL_16FFT_FREQ_CTRL1);
106 pllfm = freq_ctrl1 & PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK;
107 pllfm >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT;
108 cfg = readl(pll->reg + PLL_16FFT_CFG);
109 pll_type = (cfg & PLL_16FFT_CFG_PLL_TYPE_MASK) >> PLL_16FFT_CFG_PLL_TYPE_SHIFT;
110
111 if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF && pllfm == 0) {
112 cal = readl(pll->reg + PLL_16FFT_CAL_CTRL);
76 113
77 return -EBUSY; 114 /* Enable calibration for FRACF */
115 cal |= PLL_16FFT_CAL_CTRL_CAL_EN;
116
117 /* Enable fast cal mode */
118 cal |= PLL_16FFT_CAL_CTRL_FAST_CAL;
119
120 /* Disable calibration bypass */
121 cal &= ~PLL_16FFT_CAL_CTRL_CAL_BYP;
122
123 /* Set CALCNT to 2 */
124 cal &= ~PLL_16FFT_CAL_CTRL_CAL_CNT_MASK;
125 cal |= 2 << PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT;
126
127 /* Note this register does not readback the written value. */
128 writel(cal, pll->reg + PLL_16FFT_CAL_CTRL);
129
130 success = 0;
131 for (i = 0; i < 100000; i++) {
132 stat = readl(pll->reg + PLL_16FFT_CAL_STAT);
133 if (stat & PLL_16FFT_CAL_STAT_CAL_LOCK) {
134 success = 1;
135 break;
136 }
137 }
138 }
139
140 if (success == 0) {
141 printf("%s: pll (%s) failed to lock\n", __func__,
142 clk->dev->name);
143 return -EBUSY;
144 } else {
145 return 0;
146 }
78} 147}
79 148
80static ulong ti_pll_clk_get_rate(struct clk *clk) 149static ulong ti_pll_clk_get_rate(struct clk *clk)