mvebu: Add basic support for WRT1900AC (v1) and Turris Omnia (pre 2019)
[librecmc/librecmc.git] / target / linux / mvebu / patches-4.14 / 504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch
1 From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001
2 From: Gregory CLEMENT <gregory.clement@free-electrons.com>
3 Date: Thu, 30 Nov 2017 14:40:28 +0100
4 Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be
5  used with DVFS
6
7 When DVFS will be enabled then the cpu clk will use a different set of
8 register at run time. That means that we won't be able to use the common
9 callback and need to use our own ones.
10
11 This patch prepares this change by switching on our own set of callbacks
12 without modifying the behavior of the clocks.
13
14 Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
15 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
16 ---
17  drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++----
18  1 file changed, 73 insertions(+), 9 deletions(-)
19
20 --- a/drivers/clk/mvebu/armada-37xx-periph.c
21 +++ b/drivers/clk/mvebu/armada-37xx-periph.c
22 @@ -46,7 +46,17 @@ struct clk_double_div {
23         u8 shift2;
24  };
25  
26 +struct clk_pm_cpu {
27 +       struct clk_hw hw;
28 +       void __iomem *reg_mux;
29 +       u8 shift_mux;
30 +       u32 mask_mux;
31 +       void __iomem *reg_div;
32 +       u8 shift_div;
33 +};
34 +
35  #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
36 +#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
37  
38  struct clk_periph_data {
39         const char *name;
40 @@ -55,6 +65,7 @@ struct clk_periph_data {
41         struct clk_hw *mux_hw;
42         struct clk_hw *rate_hw;
43         struct clk_hw *gate_hw;
44 +       struct clk_hw *muxrate_hw;
45         bool is_double_div;
46  };
47  
48 @@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta
49  };
50  
51  static const struct clk_ops clk_double_div_ops;
52 +static const struct clk_ops clk_pm_cpu_ops;
53  
54  #define PERIPH_GATE(_name, _bit)               \
55  struct clk_gate gate_##_name = {               \
56 @@ -122,6 +134,18 @@ struct clk_divider rate_##_name = {                \
57         }                                       \
58  };
59  
60 +#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2)   \
61 +struct clk_pm_cpu muxrate_##_name = {          \
62 +       .reg_mux = (void *)TBG_SEL,             \
63 +       .mask_mux = 3,                          \
64 +       .shift_mux = _shift1,                   \
65 +       .reg_div = (void *)_reg,                \
66 +       .shift_div = _shift2,                   \
67 +       .hw.init = &(struct clk_init_data){     \
68 +               .ops =  &clk_pm_cpu_ops,        \
69 +       }                                       \
70 +};
71 +
72  #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
73  static PERIPH_GATE(_name, _bit);                           \
74  static PERIPH_MUX(_name, _shift);                          \
75 @@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1,
76  static PERIPH_GATE(_name, _bit);                       \
77  static PERIPH_DIV(_name, _reg, _shift, _table);
78  
79 -#define PERIPH_CLK_MUX_DIV(_name, _shift,  _reg, _shift_div, _table)   \
80 -static PERIPH_MUX(_name, _shift);                          \
81 -static PERIPH_DIV(_name, _reg, _shift_div, _table);
82 -
83  #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
84  static PERIPH_MUX(_name, _shift);                          \
85  static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
86 @@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r
87           .rate_hw = &rate_##_name.hw,                          \
88         }
89  
90 -#define REF_CLK_MUX_DIV(_name)                         \
91 +#define REF_CLK_PM_CPU(_name)                          \
92         { .name = #_name,                               \
93           .parent_names = (const char *[]){ "TBG-A-P",  \
94               "TBG-B-P", "TBG-A-S", "TBG-B-S"},         \
95           .num_parents = 4,                             \
96 -         .mux_hw = &mux_##_name.hw,                    \
97 -         .rate_hw = &rate_##_name.hw,                  \
98 +         .muxrate_hw = &muxrate_##_name.hw,            \
99         }
100  
101  #define REF_CLK_MUX_DD(_name)                          \
102 @@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV
103  PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
104  PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
105  PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
106 -PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
107 +static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
108  
109  static struct clk_periph_data data_nb[] = {
110         REF_CLK_FULL_DD(mmc),
111 @@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[]
112         REF_CLK_FULL(trace),
113         REF_CLK_FULL(counter),
114         REF_CLK_FULL_DD(eip97),
115 -       REF_CLK_MUX_DIV(cpu),
116 +       REF_CLK_PM_CPU(cpu),
117         { },
118  };
119  
120 @@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d
121         .recalc_rate = clk_double_div_recalc_rate,
122  };
123  
124 +static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
125 +{
126 +       struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
127 +       int num_parents = clk_hw_get_num_parents(hw);
128 +       u32 val;
129 +
130 +       val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
131 +       val &= pm_cpu->mask_mux;
132 +
133 +       if (val >= num_parents)
134 +               return -EINVAL;
135 +
136 +       return val;
137 +}
138 +
139 +static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
140 +                                           unsigned long parent_rate)
141 +{
142 +       struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
143 +       unsigned int div;
144 +
145 +       div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
146 +
147 +       return DIV_ROUND_UP_ULL((u64)parent_rate, div);
148 +}
149 +
150 +static const struct clk_ops clk_pm_cpu_ops = {
151 +       .get_parent = clk_pm_cpu_get_parent,
152 +       .recalc_rate = clk_pm_cpu_recalc_rate,
153 +};
154 +
155  static const struct of_device_id armada_3700_periph_clock_of_match[] = {
156         { .compatible = "marvell,armada-3700-periph-clock-nb",
157           .data = data_nb, },
158 @@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk
159                 }
160         }
161  
162 +       if (data->muxrate_hw) {
163 +               struct clk_pm_cpu *pmcpu_clk;
164 +               struct clk_hw *muxrate_hw = data->muxrate_hw;
165 +
166 +               pmcpu_clk =  to_clk_pm_cpu(muxrate_hw);
167 +               pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
168 +               pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
169 +
170 +               mux_hw = muxrate_hw;
171 +               rate_hw = muxrate_hw;
172 +               mux_ops = muxrate_hw->init->ops;
173 +               rate_ops = muxrate_hw->init->ops;
174 +       }
175 +
176         *hw = clk_hw_register_composite(dev, data->name, data->parent_names,
177                                         data->num_parents, mux_hw,
178                                         mux_ops, rate_hw, rate_ops,