Skip to content

Commit 5f0d472

Browse files
Gabriel-Fernandzbebarino
authored andcommitted
clk: stm32mp13: add composite clock
Just to introduce management of stm32 composite clock. Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com> Link: https://lore.kernel.org/r/20220516070600.7692-7-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent 720e34a commit 5f0d472

3 files changed

Lines changed: 225 additions & 0 deletions

File tree

drivers/clk/stm32/clk-stm32-core.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,159 @@ const struct clk_ops clk_stm32_divider_ops = {
389389
.set_rate = clk_stm32_divider_set_rate,
390390
};
391391

392+
static int clk_stm32_composite_set_rate(struct clk_hw *hw, unsigned long rate,
393+
unsigned long parent_rate)
394+
{
395+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
396+
unsigned long flags = 0;
397+
int ret;
398+
399+
if (composite->div_id == NO_STM32_DIV)
400+
return rate;
401+
402+
spin_lock_irqsave(composite->lock, flags);
403+
404+
ret = stm32_divider_set_rate(composite->base, composite->clock_data,
405+
composite->div_id, rate, parent_rate);
406+
407+
spin_unlock_irqrestore(composite->lock, flags);
408+
409+
return ret;
410+
}
411+
412+
static unsigned long clk_stm32_composite_recalc_rate(struct clk_hw *hw,
413+
unsigned long parent_rate)
414+
{
415+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
416+
417+
if (composite->div_id == NO_STM32_DIV)
418+
return parent_rate;
419+
420+
return stm32_divider_get_rate(composite->base, composite->clock_data,
421+
composite->div_id, parent_rate);
422+
}
423+
424+
static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate,
425+
unsigned long *prate)
426+
{
427+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
428+
429+
const struct stm32_div_cfg *divider;
430+
431+
if (composite->div_id == NO_STM32_DIV)
432+
return rate;
433+
434+
divider = &composite->clock_data->dividers[composite->div_id];
435+
436+
/* if read only, just return current value */
437+
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
438+
u32 val;
439+
440+
val = readl(composite->base + divider->offset) >> divider->shift;
441+
val &= clk_div_mask(divider->width);
442+
443+
return divider_ro_round_rate(hw, rate, prate, divider->table,
444+
divider->width, divider->flags,
445+
val);
446+
}
447+
448+
return divider_round_rate_parent(hw, clk_hw_get_parent(hw),
449+
rate, prate, divider->table,
450+
divider->width, divider->flags);
451+
}
452+
453+
static u8 clk_stm32_composite_get_parent(struct clk_hw *hw)
454+
{
455+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
456+
457+
return stm32_mux_get_parent(composite->base, composite->clock_data, composite->mux_id);
458+
}
459+
460+
static int clk_stm32_composite_set_parent(struct clk_hw *hw, u8 index)
461+
{
462+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
463+
unsigned long flags = 0;
464+
465+
spin_lock_irqsave(composite->lock, flags);
466+
467+
stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, index);
468+
469+
spin_unlock_irqrestore(composite->lock, flags);
470+
471+
return 0;
472+
}
473+
474+
static int clk_stm32_composite_is_enabled(struct clk_hw *hw)
475+
{
476+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
477+
478+
if (composite->gate_id == NO_STM32_GATE)
479+
return (__clk_get_enable_count(hw->clk) > 0);
480+
481+
return stm32_gate_is_enabled(composite->base, composite->clock_data, composite->gate_id);
482+
}
483+
484+
static void clk_stm32_composite_gate_endisable(struct clk_hw *hw, int enable)
485+
{
486+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
487+
unsigned long flags = 0;
488+
489+
spin_lock_irqsave(composite->lock, flags);
490+
491+
stm32_gate_endisable(composite->base, composite->clock_data, composite->gate_id, enable);
492+
493+
spin_unlock_irqrestore(composite->lock, flags);
494+
}
495+
496+
static int clk_stm32_composite_gate_enable(struct clk_hw *hw)
497+
{
498+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
499+
500+
if (composite->gate_id == NO_STM32_GATE)
501+
return 0;
502+
503+
clk_stm32_composite_gate_endisable(hw, 1);
504+
505+
return 0;
506+
}
507+
508+
static void clk_stm32_composite_gate_disable(struct clk_hw *hw)
509+
{
510+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
511+
512+
if (composite->gate_id == NO_STM32_GATE)
513+
return;
514+
515+
clk_stm32_composite_gate_endisable(hw, 0);
516+
}
517+
518+
static void clk_stm32_composite_disable_unused(struct clk_hw *hw)
519+
{
520+
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
521+
unsigned long flags = 0;
522+
523+
if (composite->gate_id == NO_STM32_GATE)
524+
return;
525+
526+
spin_lock_irqsave(composite->lock, flags);
527+
528+
stm32_gate_disable_unused(composite->base, composite->clock_data, composite->gate_id);
529+
530+
spin_unlock_irqrestore(composite->lock, flags);
531+
}
532+
533+
const struct clk_ops clk_stm32_composite_ops = {
534+
.set_rate = clk_stm32_composite_set_rate,
535+
.recalc_rate = clk_stm32_composite_recalc_rate,
536+
.round_rate = clk_stm32_composite_round_rate,
537+
.get_parent = clk_stm32_composite_get_parent,
538+
.set_parent = clk_stm32_composite_set_parent,
539+
.enable = clk_stm32_composite_gate_enable,
540+
.disable = clk_stm32_composite_gate_disable,
541+
.is_enabled = clk_stm32_composite_is_enabled,
542+
.disable_unused = clk_stm32_composite_disable_unused,
543+
};
544+
392545
struct clk_hw *clk_stm32_mux_register(struct device *dev,
393546
const struct stm32_rcc_match_data *data,
394547
void __iomem *base,
@@ -451,3 +604,24 @@ struct clk_hw *clk_stm32_div_register(struct device *dev,
451604

452605
return hw;
453606
}
607+
608+
struct clk_hw *clk_stm32_composite_register(struct device *dev,
609+
const struct stm32_rcc_match_data *data,
610+
void __iomem *base,
611+
spinlock_t *lock,
612+
const struct clock_config *cfg)
613+
{
614+
struct clk_stm32_composite *composite = cfg->clock_cfg;
615+
struct clk_hw *hw = &composite->hw;
616+
int err;
617+
618+
composite->base = base;
619+
composite->lock = lock;
620+
composite->clock_data = data->clock_data;
621+
622+
err = clk_hw_register(dev, hw);
623+
if (err)
624+
return ERR_PTR(err);
625+
626+
return hw;
627+
}

drivers/clk/stm32/clk-stm32-core.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,23 @@ struct clk_stm32_div {
114114

115115
#define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw)
116116

117+
struct clk_stm32_composite {
118+
u16 gate_id;
119+
u16 mux_id;
120+
u16 div_id;
121+
struct clk_hw hw;
122+
void __iomem *base;
123+
struct clk_stm32_clock_data *clock_data;
124+
spinlock_t *lock; /* spin lock */
125+
};
126+
127+
#define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw)
128+
117129
/* Clock operators */
118130
extern const struct clk_ops clk_stm32_mux_ops;
119131
extern const struct clk_ops clk_stm32_gate_ops;
120132
extern const struct clk_ops clk_stm32_divider_ops;
133+
extern const struct clk_ops clk_stm32_composite_ops;
121134

122135
/* Clock registering */
123136
struct clk_hw *clk_stm32_mux_register(struct device *dev,
@@ -138,6 +151,12 @@ struct clk_hw *clk_stm32_div_register(struct device *dev,
138151
spinlock_t *lock,
139152
const struct clock_config *cfg);
140153

154+
struct clk_hw *clk_stm32_composite_register(struct device *dev,
155+
const struct stm32_rcc_match_data *data,
156+
void __iomem *base,
157+
spinlock_t *lock,
158+
const struct clock_config *cfg);
159+
141160
#define STM32_CLOCK_CFG(_binding, _clk, _struct, _register)\
142161
{\
143162
.id = (_binding),\
@@ -156,3 +175,7 @@ struct clk_hw *clk_stm32_div_register(struct device *dev,
156175
#define STM32_DIV_CFG(_binding, _clk)\
157176
STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_div *,\
158177
&clk_stm32_div_register)
178+
179+
#define STM32_COMPOSITE_CFG(_binding, _clk)\
180+
STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_composite *,\
181+
&clk_stm32_composite_register)

drivers/clk/stm32/clk-stm32mp13.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,14 @@ static const char * const eth12_src[] = {
404404
"pll4_p", "pll3_q"
405405
};
406406

407+
static const char * const mco1_src[] = {
408+
"ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse"
409+
};
410+
411+
static const char * const mco2_src[] = {
412+
"ck_mpu", "ck_axi", "ck_mlahb", "pll4_p", "ck_hse", "ck_hsi"
413+
};
414+
407415
static struct clk_stm32_mux ck_ker_eth1 = {
408416
.mux_id = MUX_ETH1,
409417
.hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth1", eth12_src, &clk_stm32_mux_ops,
@@ -421,10 +429,30 @@ static struct clk_stm32_div eth1ptp_k = {
421429
CLK_SET_RATE_NO_REPARENT),
422430
};
423431

432+
static struct clk_stm32_composite ck_mco1 = {
433+
.gate_id = GATE_MCO1,
434+
.mux_id = MUX_MCO1,
435+
.div_id = DIV_MCO1,
436+
.hw.init = CLK_HW_INIT_PARENTS("ck_mco1", mco1_src, &clk_stm32_composite_ops,
437+
CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT |
438+
CLK_IGNORE_UNUSED),
439+
};
440+
441+
static struct clk_stm32_composite ck_mco2 = {
442+
.gate_id = GATE_MCO2,
443+
.mux_id = MUX_MCO2,
444+
.div_id = DIV_MCO2,
445+
.hw.init = CLK_HW_INIT_PARENTS("ck_mco2", mco2_src, &clk_stm32_composite_ops,
446+
CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT |
447+
CLK_IGNORE_UNUSED),
448+
};
449+
424450
static const struct clock_config stm32mp13_clock_cfg[] = {
425451
STM32_MUX_CFG(NO_ID, ck_ker_eth1),
426452
STM32_GATE_CFG(ETH1CK_K, eth1ck_k),
427453
STM32_DIV_CFG(ETH1PTP_K, eth1ptp_k),
454+
STM32_COMPOSITE_CFG(CK_MCO1, ck_mco1),
455+
STM32_COMPOSITE_CFG(CK_MCO2, ck_mco2),
428456
};
429457

430458
static u16 stm32mp13_cpt_gate[GATE_NB];

0 commit comments

Comments
 (0)