aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabriel Fernandez <gabriel.fernandez@st.com>2018-03-08 11:53:58 -0500
committerMichael Turquette <mturquette@baylibre.com>2018-03-11 18:40:33 -0400
commitc6cf4d3248980c5e1998ce21f3c2d86502f7e1a9 (patch)
tree29720b145816929e73d9e32a3e2f3aef535a1b73
parentdc32eaac4926b02fddba3ff02030827429394ad7 (diff)
clk: stm32mp1: add PLL clocks
STMP32MP1 has 4 PLLs. PLL supports integer and fractional mode. Each PLL has 3 output dividers (p, q, r) Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
-rw-r--r--drivers/clk/clk-stm32mp1.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 47984f36494b..d62a3a94cc67 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -7,6 +7,7 @@
7 7
8#include <linux/clk.h> 8#include <linux/clk.h>
9#include <linux/clk-provider.h> 9#include <linux/clk-provider.h>
10#include <linux/delay.h>
10#include <linux/err.h> 11#include <linux/err.h>
11#include <linux/io.h> 12#include <linux/io.h>
12#include <linux/of.h> 13#include <linux/of.h>
@@ -321,6 +322,196 @@ clk_stm32_register_gate_ops(struct device *dev,
321 return hw; 322 return hw;
322} 323}
323 324
325/* STM32 PLL */
326
327struct stm32_pll_obj {
328 /* lock pll enable/disable registers */
329 spinlock_t *lock;
330 void __iomem *reg;
331 struct clk_hw hw;
332};
333
334#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
335
336#define PLL_ON BIT(0)
337#define PLL_RDY BIT(1)
338#define DIVN_MASK 0x1FF
339#define DIVM_MASK 0x3F
340#define DIVM_SHIFT 16
341#define DIVN_SHIFT 0
342#define FRAC_OFFSET 0xC
343#define FRAC_MASK 0x1FFF
344#define FRAC_SHIFT 3
345#define FRACLE BIT(16)
346
347static int __pll_is_enabled(struct clk_hw *hw)
348{
349 struct stm32_pll_obj *clk_elem = to_pll(hw);
350
351 return readl_relaxed(clk_elem->reg) & PLL_ON;
352}
353
354#define TIMEOUT 5
355
356static int pll_enable(struct clk_hw *hw)
357{
358 struct stm32_pll_obj *clk_elem = to_pll(hw);
359 u32 reg;
360 unsigned long flags = 0;
361 unsigned int timeout = TIMEOUT;
362 int bit_status = 0;
363
364 spin_lock_irqsave(clk_elem->lock, flags);
365
366 if (__pll_is_enabled(hw))
367 goto unlock;
368
369 reg = readl_relaxed(clk_elem->reg);
370 reg |= PLL_ON;
371 writel_relaxed(reg, clk_elem->reg);
372
373 /* We can't use readl_poll_timeout() because we can be blocked if
374 * someone enables this clock before clocksource changes.
375 * Only jiffies counter is available. Jiffies are incremented by
376 * interruptions and enable op does not allow to be interrupted.
377 */
378 do {
379 bit_status = !(readl_relaxed(clk_elem->reg) & PLL_RDY);
380
381 if (bit_status)
382 udelay(120);
383
384 } while (bit_status && --timeout);
385
386unlock:
387 spin_unlock_irqrestore(clk_elem->lock, flags);
388
389 return bit_status;
390}
391
392static void pll_disable(struct clk_hw *hw)
393{
394 struct stm32_pll_obj *clk_elem = to_pll(hw);
395 u32 reg;
396 unsigned long flags = 0;
397
398 spin_lock_irqsave(clk_elem->lock, flags);
399
400 reg = readl_relaxed(clk_elem->reg);
401 reg &= ~PLL_ON;
402 writel_relaxed(reg, clk_elem->reg);
403
404 spin_unlock_irqrestore(clk_elem->lock, flags);
405}
406
407static u32 pll_frac_val(struct clk_hw *hw)
408{
409 struct stm32_pll_obj *clk_elem = to_pll(hw);
410 u32 reg, frac = 0;
411
412 reg = readl_relaxed(clk_elem->reg + FRAC_OFFSET);
413 if (reg & FRACLE)
414 frac = (reg >> FRAC_SHIFT) & FRAC_MASK;
415
416 return frac;
417}
418
419static unsigned long pll_recalc_rate(struct clk_hw *hw,
420 unsigned long parent_rate)
421{
422 struct stm32_pll_obj *clk_elem = to_pll(hw);
423 u32 reg;
424 u32 frac, divm, divn;
425 u64 rate, rate_frac = 0;
426
427 reg = readl_relaxed(clk_elem->reg + 4);
428
429 divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1;
430 divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1;
431 rate = (u64)parent_rate * divn;
432
433 do_div(rate, divm);
434
435 frac = pll_frac_val(hw);
436 if (frac) {
437 rate_frac = (u64)parent_rate * (u64)frac;
438 do_div(rate_frac, (divm * 8192));
439 }
440
441 return rate + rate_frac;
442}
443
444static int pll_is_enabled(struct clk_hw *hw)
445{
446 struct stm32_pll_obj *clk_elem = to_pll(hw);
447 unsigned long flags = 0;
448 int ret;
449
450 spin_lock_irqsave(clk_elem->lock, flags);
451 ret = __pll_is_enabled(hw);
452 spin_unlock_irqrestore(clk_elem->lock, flags);
453
454 return ret;
455}
456
457static const struct clk_ops pll_ops = {
458 .enable = pll_enable,
459 .disable = pll_disable,
460 .recalc_rate = pll_recalc_rate,
461 .is_enabled = pll_is_enabled,
462};
463
464static struct clk_hw *clk_register_pll(struct device *dev, const char *name,
465 const char *parent_name,
466 void __iomem *reg,
467 unsigned long flags,
468 spinlock_t *lock)
469{
470 struct stm32_pll_obj *element;
471 struct clk_init_data init;
472 struct clk_hw *hw;
473 int err;
474
475 element = kzalloc(sizeof(*element), GFP_KERNEL);
476 if (!element)
477 return ERR_PTR(-ENOMEM);
478
479 init.name = name;
480 init.ops = &pll_ops;
481 init.flags = flags;
482 init.parent_names = &parent_name;
483 init.num_parents = 1;
484
485 element->hw.init = &init;
486 element->reg = reg;
487 element->lock = lock;
488
489 hw = &element->hw;
490 err = clk_hw_register(dev, hw);
491
492 if (err) {
493 kfree(element);
494 return ERR_PTR(err);
495 }
496
497 return hw;
498}
499
500struct stm32_pll_cfg {
501 u32 offset;
502};
503
504struct clk_hw *_clk_register_pll(struct device *dev,
505 struct clk_hw_onecell_data *clk_data,
506 void __iomem *base, spinlock_t *lock,
507 const struct clock_config *cfg)
508{
509 struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg;
510
511 return clk_register_pll(dev, cfg->name, cfg->parent_name,
512 base + stm_pll_cfg->offset, cfg->flags, lock);
513}
514
324static struct clk_hw * 515static struct clk_hw *
325_clk_stm32_register_gate(struct device *dev, 516_clk_stm32_register_gate(struct device *dev,
326 struct clk_hw_onecell_data *clk_data, 517 struct clk_hw_onecell_data *clk_data,
@@ -400,6 +591,18 @@ _clk_stm32_register_gate(struct device *dev,
400 .func = _clk_hw_register_mux,\ 591 .func = _clk_hw_register_mux,\
401} 592}
402 593
594#define PLL(_id, _name, _parent, _flags, _offset)\
595{\
596 .id = _id,\
597 .name = _name,\
598 .parent_name = _parent,\
599 .flags = _flags,\
600 .cfg = &(struct stm32_pll_cfg) {\
601 .offset = _offset,\
602 },\
603 .func = _clk_register_pll,\
604}
605
403/* STM32 GATE */ 606/* STM32 GATE */
404#define STM32_GATE(_id, _name, _parent, _flags, _gate)\ 607#define STM32_GATE(_id, _name, _parent, _flags, _gate)\
405{\ 608{\
@@ -452,6 +655,12 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
452 655
453 MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR, 656 MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR,
454 0, 2, CLK_MUX_READ_ONLY), 657 0, 2, CLK_MUX_READ_ONLY),
658
659 /* PLLs */
660 PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR),
661 PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR),
662 PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR),
663 PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR),
455}; 664};
456 665
457struct stm32_clock_match_data { 666struct stm32_clock_match_data {