30
30
#define MSSPLL_POSTDIV_WIDTH 0x07u
31
31
#define MSSPLL_FIXED_DIV 4u
32
32
33
+ /*
34
+ * This clock ID is defined here, rather than the binding headers, as it is an
35
+ * internal clock only, and therefore has no consumers in other peripheral
36
+ * blocks.
37
+ */
38
+ #define CLK_MSSPLL_INTERNAL 38u
39
+
33
40
struct mpfs_clock_data {
34
41
struct device * dev ;
35
42
void __iomem * base ;
@@ -39,16 +46,26 @@ struct mpfs_clock_data {
39
46
40
47
struct mpfs_msspll_hw_clock {
41
48
void __iomem * base ;
49
+ struct clk_hw hw ;
50
+ struct clk_init_data init ;
42
51
unsigned int id ;
43
52
u32 reg_offset ;
44
53
u32 shift ;
45
54
u32 width ;
46
55
u32 flags ;
56
+ };
57
+
58
+ #define to_mpfs_msspll_clk (_hw ) container_of(_hw, struct mpfs_msspll_hw_clock, hw)
59
+
60
+ struct mpfs_msspll_out_hw_clock {
61
+ void __iomem * base ;
47
62
struct clk_hw hw ;
48
63
struct clk_init_data init ;
64
+ unsigned int id ;
65
+ u32 flags ;
49
66
};
50
67
51
- #define to_mpfs_msspll_clk (_hw ) container_of(_hw, struct mpfs_msspll_hw_clock , hw)
68
+ #define to_mpfs_msspll_out_clk (_hw ) container_of(_hw, struct mpfs_msspll_out_hw_clock , hw)
52
69
53
70
struct mpfs_cfg_hw_clock {
54
71
struct clk_divider cfg ;
@@ -93,61 +110,99 @@ static const struct clk_div_table mpfs_div_rtcref_table[] = {
93
110
{ 0 , 0 }
94
111
};
95
112
113
+ /*
114
+ * MSS PLL internal clock
115
+ */
116
+
96
117
static unsigned long mpfs_clk_msspll_recalc_rate (struct clk_hw * hw , unsigned long prate )
97
118
{
98
119
struct mpfs_msspll_hw_clock * msspll_hw = to_mpfs_msspll_clk (hw );
99
120
void __iomem * mult_addr = msspll_hw -> base + msspll_hw -> reg_offset ;
100
121
void __iomem * ref_div_addr = msspll_hw -> base + REG_MSSPLL_REF_CR ;
101
- void __iomem * postdiv_addr = msspll_hw -> base + REG_MSSPLL_POSTDIV_CR ;
102
- u32 mult , ref_div , postdiv ;
122
+ u32 mult , ref_div ;
103
123
104
124
mult = readl_relaxed (mult_addr ) >> MSSPLL_FBDIV_SHIFT ;
105
125
mult &= clk_div_mask (MSSPLL_FBDIV_WIDTH );
106
126
ref_div = readl_relaxed (ref_div_addr ) >> MSSPLL_REFDIV_SHIFT ;
107
127
ref_div &= clk_div_mask (MSSPLL_REFDIV_WIDTH );
108
- postdiv = readl_relaxed (postdiv_addr ) >> MSSPLL_POSTDIV_SHIFT ;
109
- postdiv &= clk_div_mask (MSSPLL_POSTDIV_WIDTH );
110
128
111
- return prate * mult / (ref_div * MSSPLL_FIXED_DIV * postdiv );
129
+ return prate * mult / (ref_div * MSSPLL_FIXED_DIV );
112
130
}
113
131
114
- static long mpfs_clk_msspll_round_rate (struct clk_hw * hw , unsigned long rate , unsigned long * prate )
132
+ static const struct clk_ops mpfs_clk_msspll_ops = {
133
+ .recalc_rate = mpfs_clk_msspll_recalc_rate ,
134
+ };
135
+
136
+ #define CLK_PLL (_id , _name , _parent , _shift , _width , _flags , _offset ) { \
137
+ .id = _id, \
138
+ .flags = _flags, \
139
+ .shift = _shift, \
140
+ .width = _width, \
141
+ .reg_offset = _offset, \
142
+ .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_msspll_ops, 0), \
143
+ }
144
+
145
+ static struct mpfs_msspll_hw_clock mpfs_msspll_clks [] = {
146
+ CLK_PLL (CLK_MSSPLL_INTERNAL , "clk_msspll_internal" , mpfs_ext_ref , MSSPLL_FBDIV_SHIFT ,
147
+ MSSPLL_FBDIV_WIDTH , 0 , REG_MSSPLL_SSCG_2_CR ),
148
+ };
149
+
150
+ static int mpfs_clk_register_mssplls (struct device * dev , struct mpfs_msspll_hw_clock * msspll_hws ,
151
+ unsigned int num_clks , struct mpfs_clock_data * data )
115
152
{
116
- struct mpfs_msspll_hw_clock * msspll_hw = to_mpfs_msspll_clk (hw );
117
- void __iomem * mult_addr = msspll_hw -> base + msspll_hw -> reg_offset ;
118
- void __iomem * ref_div_addr = msspll_hw -> base + REG_MSSPLL_REF_CR ;
119
- u32 mult , ref_div ;
120
- unsigned long rate_before_ctrl ;
153
+ unsigned int i ;
154
+ int ret ;
121
155
122
- mult = readl_relaxed (mult_addr ) >> MSSPLL_FBDIV_SHIFT ;
123
- mult &= clk_div_mask (MSSPLL_FBDIV_WIDTH );
124
- ref_div = readl_relaxed (ref_div_addr ) >> MSSPLL_REFDIV_SHIFT ;
125
- ref_div &= clk_div_mask (MSSPLL_REFDIV_WIDTH );
156
+ for (i = 0 ; i < num_clks ; i ++ ) {
157
+ struct mpfs_msspll_hw_clock * msspll_hw = & msspll_hws [i ];
158
+
159
+ msspll_hw -> base = data -> msspll_base ;
160
+ ret = devm_clk_hw_register (dev , & msspll_hw -> hw );
161
+ if (ret )
162
+ return dev_err_probe (dev , ret , "failed to register msspll id: %d\n" ,
163
+ CLK_MSSPLL_INTERNAL );
126
164
127
- rate_before_ctrl = rate * (ref_div * MSSPLL_FIXED_DIV ) / mult ;
165
+ data -> hw_data .hws [msspll_hw -> id ] = & msspll_hw -> hw ;
166
+ }
128
167
129
- return divider_round_rate (hw , rate_before_ctrl , prate , NULL , MSSPLL_POSTDIV_WIDTH ,
130
- msspll_hw -> flags );
168
+ return 0 ;
131
169
}
132
170
133
- static int mpfs_clk_msspll_set_rate (struct clk_hw * hw , unsigned long rate , unsigned long prate )
171
+ /*
172
+ * MSS PLL output clocks
173
+ */
174
+
175
+ static unsigned long mpfs_clk_msspll_out_recalc_rate (struct clk_hw * hw , unsigned long prate )
134
176
{
135
- struct mpfs_msspll_hw_clock * msspll_hw = to_mpfs_msspll_clk (hw );
136
- void __iomem * mult_addr = msspll_hw -> base + msspll_hw -> reg_offset ;
137
- void __iomem * ref_div_addr = msspll_hw -> base + REG_MSSPLL_REF_CR ;
138
- void __iomem * postdiv_addr = msspll_hw -> base + REG_MSSPLL_POSTDIV_CR ;
139
- u32 mult , ref_div , postdiv ;
140
- int divider_setting ;
141
- unsigned long rate_before_ctrl , flags ;
177
+ struct mpfs_msspll_out_hw_clock * msspll_out_hw = to_mpfs_msspll_out_clk (hw );
178
+ void __iomem * postdiv_addr = msspll_out_hw -> base + REG_MSSPLL_POSTDIV_CR ;
179
+ u32 postdiv ;
142
180
143
- mult = readl_relaxed (mult_addr ) >> MSSPLL_FBDIV_SHIFT ;
144
- mult &= clk_div_mask (MSSPLL_FBDIV_WIDTH );
145
- ref_div = readl_relaxed (ref_div_addr ) >> MSSPLL_REFDIV_SHIFT ;
146
- ref_div &= clk_div_mask (MSSPLL_REFDIV_WIDTH );
181
+ postdiv = readl_relaxed (postdiv_addr ) >> MSSPLL_POSTDIV_SHIFT ;
182
+ postdiv &= clk_div_mask (MSSPLL_POSTDIV_WIDTH );
147
183
148
- rate_before_ctrl = rate * (ref_div * MSSPLL_FIXED_DIV ) / mult ;
149
- divider_setting = divider_get_val (rate_before_ctrl , prate , NULL , MSSPLL_POSTDIV_WIDTH ,
150
- msspll_hw -> flags );
184
+ return prate / postdiv ;
185
+ }
186
+
187
+ static long mpfs_clk_msspll_out_round_rate (struct clk_hw * hw , unsigned long rate ,
188
+ unsigned long * prate )
189
+ {
190
+ struct mpfs_msspll_out_hw_clock * msspll_out_hw = to_mpfs_msspll_out_clk (hw );
191
+
192
+ return divider_round_rate (hw , rate , prate , NULL , MSSPLL_POSTDIV_WIDTH ,
193
+ msspll_out_hw -> flags );
194
+ }
195
+
196
+ static int mpfs_clk_msspll_out_set_rate (struct clk_hw * hw , unsigned long rate , unsigned long prate )
197
+ {
198
+ struct mpfs_msspll_out_hw_clock * msspll_out_hw = to_mpfs_msspll_out_clk (hw );
199
+ void __iomem * postdiv_addr = msspll_out_hw -> base + REG_MSSPLL_POSTDIV_CR ;
200
+ u32 postdiv ;
201
+ int divider_setting ;
202
+ unsigned long flags ;
203
+
204
+ divider_setting = divider_get_val (rate , prate , NULL , MSSPLL_POSTDIV_WIDTH ,
205
+ msspll_out_hw -> flags );
151
206
152
207
if (divider_setting < 0 )
153
208
return divider_setting ;
@@ -163,42 +218,39 @@ static int mpfs_clk_msspll_set_rate(struct clk_hw *hw, unsigned long rate, unsig
163
218
return 0 ;
164
219
}
165
220
166
- static const struct clk_ops mpfs_clk_msspll_ops = {
167
- .recalc_rate = mpfs_clk_msspll_recalc_rate ,
168
- .round_rate = mpfs_clk_msspll_round_rate ,
169
- .set_rate = mpfs_clk_msspll_set_rate ,
221
+ static const struct clk_ops mpfs_clk_msspll_out_ops = {
222
+ .recalc_rate = mpfs_clk_msspll_out_recalc_rate ,
223
+ .round_rate = mpfs_clk_msspll_out_round_rate ,
224
+ .set_rate = mpfs_clk_msspll_out_set_rate ,
170
225
};
171
226
172
- #define CLK_PLL (_id , _name , _parent , _shift , _width , _flags , _offset ) { \
173
- .id = _id, \
174
- .shift = _shift, \
175
- .width = _width, \
176
- .reg_offset = _offset, \
177
- .flags = _flags, \
178
- .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_msspll_ops, 0), \
227
+ #define CLK_PLL_OUT (_id , _name , _parent , _flags ) { \
228
+ .id = _id, \
229
+ .flags = _flags, \
230
+ .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_msspll_out_ops, 0), \
179
231
}
180
232
181
- static struct mpfs_msspll_hw_clock mpfs_msspll_clks [] = {
182
- CLK_PLL (CLK_MSSPLL , "clk_msspll" , mpfs_ext_ref , MSSPLL_FBDIV_SHIFT ,
183
- MSSPLL_FBDIV_WIDTH , 0 , REG_MSSPLL_SSCG_2_CR ),
233
+ static struct mpfs_msspll_out_hw_clock mpfs_msspll_out_clks [] = {
234
+ CLK_PLL_OUT (CLK_MSSPLL0 , "clk_msspll" , "clk_msspll_internal" , 0 ),
184
235
};
185
236
186
- static int mpfs_clk_register_mssplls (struct device * dev , struct mpfs_msspll_hw_clock * msspll_hws ,
187
- unsigned int num_clks , struct mpfs_clock_data * data )
237
+ static int mpfs_clk_register_msspll_outs (struct device * dev ,
238
+ struct mpfs_msspll_out_hw_clock * msspll_out_hws ,
239
+ unsigned int num_clks , struct mpfs_clock_data * data )
188
240
{
189
241
unsigned int i ;
190
242
int ret ;
191
243
192
244
for (i = 0 ; i < num_clks ; i ++ ) {
193
- struct mpfs_msspll_hw_clock * msspll_hw = & msspll_hws [i ];
245
+ struct mpfs_msspll_out_hw_clock * msspll_out_hw = & msspll_out_hws [i ];
194
246
195
- msspll_hw -> base = data -> msspll_base ;
196
- ret = devm_clk_hw_register (dev , & msspll_hw -> hw );
247
+ msspll_out_hw -> base = data -> msspll_base ;
248
+ ret = devm_clk_hw_register (dev , & msspll_out_hw -> hw );
197
249
if (ret )
198
- return dev_err_probe (dev , ret , "failed to register msspll id: %d\n" ,
199
- CLK_MSSPLL );
250
+ return dev_err_probe (dev , ret , "failed to register msspll out id: %d\n" ,
251
+ msspll_out_hw -> id );
200
252
201
- data -> hw_data .hws [msspll_hw -> id ] = & msspll_hw -> hw ;
253
+ data -> hw_data .hws [msspll_out_hw -> id ] = & msspll_out_hw -> hw ;
202
254
}
203
255
204
256
return 0 ;
@@ -442,8 +494,8 @@ static int mpfs_clk_probe(struct platform_device *pdev)
442
494
int ret ;
443
495
444
496
/* CLK_RESERVED is not part of clock arrays, so add 1 */
445
- num_clks = ARRAY_SIZE (mpfs_msspll_clks ) + ARRAY_SIZE (mpfs_cfg_clks )
446
- + ARRAY_SIZE (mpfs_periph_clks ) + 1 ;
497
+ num_clks = ARRAY_SIZE (mpfs_msspll_clks ) + ARRAY_SIZE (mpfs_msspll_out_clks )
498
+ + ARRAY_SIZE (mpfs_cfg_clks ) + ARRAY_SIZE ( mpfs_periph_clks ) + 1 ;
447
499
448
500
clk_data = devm_kzalloc (dev , struct_size (clk_data , hw_data .hws , num_clks ), GFP_KERNEL );
449
501
if (!clk_data )
@@ -466,6 +518,12 @@ static int mpfs_clk_probe(struct platform_device *pdev)
466
518
if (ret )
467
519
return ret ;
468
520
521
+ ret = mpfs_clk_register_msspll_outs (dev , mpfs_msspll_out_clks ,
522
+ ARRAY_SIZE (mpfs_msspll_out_clks ),
523
+ clk_data );
524
+ if (ret )
525
+ return ret ;
526
+
469
527
ret = mpfs_clk_register_cfgs (dev , mpfs_cfg_clks , ARRAY_SIZE (mpfs_cfg_clks ), clk_data );
470
528
if (ret )
471
529
return ret ;
0 commit comments