Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/actions/owl-divider.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0+
2
//
3
// OWL divider clock driver
4
//
5
// Copyright (c) 2014 Actions Semi Inc.
6
// Author: David Liu <[email protected]>
7
//
8
// Copyright (c) 2018 Linaro Ltd.
9
// Author: Manivannan Sadhasivam <[email protected]>
10
11
#include <linux/clk-provider.h>
12
#include <linux/regmap.h>
13
14
#include "owl-divider.h"
15
16
long owl_divider_helper_round_rate(struct owl_clk_common *common,
17
const struct owl_divider_hw *div_hw,
18
unsigned long rate,
19
unsigned long *parent_rate)
20
{
21
return divider_round_rate(&common->hw, rate, parent_rate,
22
div_hw->table, div_hw->width,
23
div_hw->div_flags);
24
}
25
26
static long owl_divider_round_rate(struct clk_hw *hw, unsigned long rate,
27
unsigned long *parent_rate)
28
{
29
struct owl_divider *div = hw_to_owl_divider(hw);
30
31
return owl_divider_helper_round_rate(&div->common, &div->div_hw,
32
rate, parent_rate);
33
}
34
35
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
36
const struct owl_divider_hw *div_hw,
37
unsigned long parent_rate)
38
{
39
unsigned long val;
40
unsigned int reg;
41
42
regmap_read(common->regmap, div_hw->reg, &reg);
43
val = reg >> div_hw->shift;
44
val &= (1 << div_hw->width) - 1;
45
46
return divider_recalc_rate(&common->hw, parent_rate,
47
val, div_hw->table,
48
div_hw->div_flags,
49
div_hw->width);
50
}
51
52
static unsigned long owl_divider_recalc_rate(struct clk_hw *hw,
53
unsigned long parent_rate)
54
{
55
struct owl_divider *div = hw_to_owl_divider(hw);
56
57
return owl_divider_helper_recalc_rate(&div->common,
58
&div->div_hw, parent_rate);
59
}
60
61
int owl_divider_helper_set_rate(const struct owl_clk_common *common,
62
const struct owl_divider_hw *div_hw,
63
unsigned long rate,
64
unsigned long parent_rate)
65
{
66
unsigned long val;
67
unsigned int reg;
68
69
val = divider_get_val(rate, parent_rate, div_hw->table,
70
div_hw->width, 0);
71
72
regmap_read(common->regmap, div_hw->reg, &reg);
73
reg &= ~GENMASK(div_hw->width + div_hw->shift - 1, div_hw->shift);
74
75
regmap_write(common->regmap, div_hw->reg,
76
reg | (val << div_hw->shift));
77
78
return 0;
79
}
80
81
static int owl_divider_set_rate(struct clk_hw *hw, unsigned long rate,
82
unsigned long parent_rate)
83
{
84
struct owl_divider *div = hw_to_owl_divider(hw);
85
86
return owl_divider_helper_set_rate(&div->common, &div->div_hw,
87
rate, parent_rate);
88
}
89
90
const struct clk_ops owl_divider_ops = {
91
.recalc_rate = owl_divider_recalc_rate,
92
.round_rate = owl_divider_round_rate,
93
.set_rate = owl_divider_set_rate,
94
};
95
96