Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: samsung: Add enable/disable operation for PLL36XX clocks

The existing enable/disable ops for PLL35XX are made more generic
and used also for PLL36XX. This fixes issues in the kernel with
PLL36XX PLLs when the PLL has not been already enabled by bootloader.

Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

+50 -37
+50 -37
drivers/clk/samsung/clk-pll.c
··· 23 23 struct clk_hw hw; 24 24 void __iomem *lock_reg; 25 25 void __iomem *con_reg; 26 + /* PLL enable control bit offset in @con_reg register */ 27 + unsigned short enable_offs; 28 + /* PLL lock status bit offset in @con_reg register */ 29 + unsigned short lock_offs; 26 30 enum samsung_pll_type type; 27 31 unsigned int rate_count; 28 32 const struct samsung_pll_rate_table *rate_table; ··· 63 59 64 60 /* return minimum supported value */ 65 61 return rate_table[i - 1].rate; 62 + } 63 + 64 + static int samsung_pll3xxx_enable(struct clk_hw *hw) 65 + { 66 + struct samsung_clk_pll *pll = to_clk_pll(hw); 67 + u32 tmp; 68 + 69 + tmp = readl_relaxed(pll->con_reg); 70 + tmp |= BIT(pll->enable_offs); 71 + writel_relaxed(tmp, pll->con_reg); 72 + 73 + /* wait lock time */ 74 + do { 75 + cpu_relax(); 76 + tmp = readl_relaxed(pll->con_reg); 77 + } while (!(tmp & BIT(pll->lock_offs))); 78 + 79 + return 0; 80 + } 81 + 82 + static void samsung_pll3xxx_disable(struct clk_hw *hw) 83 + { 84 + struct samsung_clk_pll *pll = to_clk_pll(hw); 85 + u32 tmp; 86 + 87 + tmp = readl_relaxed(pll->con_reg); 88 + tmp &= ~BIT(pll->enable_offs); 89 + writel_relaxed(tmp, pll->con_reg); 66 90 } 67 91 68 92 /* ··· 174 142 #define PLL35XX_LOCK_STAT_SHIFT (29) 175 143 #define PLL35XX_ENABLE_SHIFT (31) 176 144 177 - static int samsung_pll35xx_enable(struct clk_hw *hw) 178 - { 179 - struct samsung_clk_pll *pll = to_clk_pll(hw); 180 - u32 tmp; 181 - 182 - tmp = readl_relaxed(pll->con_reg); 183 - tmp |= BIT(PLL35XX_ENABLE_SHIFT); 184 - writel_relaxed(tmp, pll->con_reg); 185 - 186 - /* wait_lock_time */ 187 - do { 188 - cpu_relax(); 189 - tmp = readl_relaxed(pll->con_reg); 190 - } while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT))); 191 - 192 - return 0; 193 - } 194 - 195 - static void samsung_pll35xx_disable(struct clk_hw *hw) 196 - { 197 - struct samsung_clk_pll *pll = to_clk_pll(hw); 198 - u32 tmp; 199 - 200 - tmp = readl_relaxed(pll->con_reg); 201 - tmp &= ~BIT(PLL35XX_ENABLE_SHIFT); 202 - writel_relaxed(tmp, pll->con_reg); 203 - } 204 - 205 145 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, 206 146 unsigned long parent_rate) 207 147 { ··· 242 238 (rate->sdiv << PLL35XX_SDIV_SHIFT); 243 239 writel_relaxed(tmp, pll->con_reg); 244 240 245 - /* wait_lock_time if enabled */ 246 - if (tmp & BIT(PLL35XX_ENABLE_SHIFT)) { 241 + /* Wait until the PLL is locked if it is enabled. */ 242 + if (tmp & BIT(pll->enable_offs)) { 247 243 do { 248 244 cpu_relax(); 249 245 tmp = readl_relaxed(pll->con_reg); 250 - } while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT))); 246 + } while (!(tmp & BIT(pll->lock_offs))); 251 247 } 252 248 return 0; 253 249 } ··· 256 252 .recalc_rate = samsung_pll35xx_recalc_rate, 257 253 .round_rate = samsung_pll_round_rate, 258 254 .set_rate = samsung_pll35xx_set_rate, 259 - .enable = samsung_pll35xx_enable, 260 - .disable = samsung_pll35xx_disable, 255 + .enable = samsung_pll3xxx_enable, 256 + .disable = samsung_pll3xxx_disable, 261 257 }; 262 258 263 259 static const struct clk_ops samsung_pll35xx_clk_min_ops = { ··· 279 275 #define PLL36XX_SDIV_SHIFT (0) 280 276 #define PLL36XX_KDIV_SHIFT (0) 281 277 #define PLL36XX_LOCK_STAT_SHIFT (29) 278 + #define PLL36XX_ENABLE_SHIFT (31) 282 279 283 280 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, 284 281 unsigned long parent_rate) ··· 359 354 writel_relaxed(pll_con1, pll->con_reg + 4); 360 355 361 356 /* wait_lock_time */ 362 - do { 363 - cpu_relax(); 364 - tmp = readl_relaxed(pll->con_reg); 365 - } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT))); 357 + if (pll_con0 & BIT(pll->enable_offs)) { 358 + do { 359 + cpu_relax(); 360 + tmp = readl_relaxed(pll->con_reg); 361 + } while (!(tmp & BIT(pll->lock_offs))); 362 + } 366 363 367 364 return 0; 368 365 } ··· 373 366 .recalc_rate = samsung_pll36xx_recalc_rate, 374 367 .set_rate = samsung_pll36xx_set_rate, 375 368 .round_rate = samsung_pll_round_rate, 369 + .enable = samsung_pll3xxx_enable, 370 + .disable = samsung_pll3xxx_disable, 376 371 }; 377 372 378 373 static const struct clk_ops samsung_pll36xx_clk_min_ops = { ··· 1296 1287 case pll_1450x: 1297 1288 case pll_1451x: 1298 1289 case pll_1452x: 1290 + pll->enable_offs = PLL35XX_ENABLE_SHIFT; 1291 + pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT; 1299 1292 if (!pll->rate_table) 1300 1293 init.ops = &samsung_pll35xx_clk_min_ops; 1301 1294 else ··· 1316 1305 /* clk_ops for 36xx and 2650 are similar */ 1317 1306 case pll_36xx: 1318 1307 case pll_2650: 1308 + pll->enable_offs = PLL36XX_ENABLE_SHIFT; 1309 + pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT; 1319 1310 if (!pll->rate_table) 1320 1311 init.ops = &samsung_pll36xx_clk_min_ops; 1321 1312 else