3030#define MSSPLL_POSTDIV_WIDTH 0x07u
3131#define MSSPLL_FIXED_DIV 4u
3232
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+
3340struct mpfs_clock_data {
3441 struct device * dev ;
3542 void __iomem * base ;
@@ -39,16 +46,26 @@ struct mpfs_clock_data {
3946
4047struct mpfs_msspll_hw_clock {
4148 void __iomem * base ;
49+ struct clk_hw hw ;
50+ struct clk_init_data init ;
4251 unsigned int id ;
4352 u32 reg_offset ;
4453 u32 shift ;
4554 u32 width ;
4655 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 ;
4762 struct clk_hw hw ;
4863 struct clk_init_data init ;
64+ unsigned int id ;
65+ u32 flags ;
4966};
5067
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)
5269
5370struct mpfs_cfg_hw_clock {
5471 struct clk_divider cfg ;
@@ -93,61 +110,99 @@ static const struct clk_div_table mpfs_div_rtcref_table[] = {
93110 { 0 , 0 }
94111};
95112
113+ /*
114+ * MSS PLL internal clock
115+ */
116+
96117static unsigned long mpfs_clk_msspll_recalc_rate (struct clk_hw * hw , unsigned long prate )
97118{
98119 struct mpfs_msspll_hw_clock * msspll_hw = to_mpfs_msspll_clk (hw );
99120 void __iomem * mult_addr = msspll_hw -> base + msspll_hw -> reg_offset ;
100121 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 ;
103123
104124 mult = readl_relaxed (mult_addr ) >> MSSPLL_FBDIV_SHIFT ;
105125 mult &= clk_div_mask (MSSPLL_FBDIV_WIDTH );
106126 ref_div = readl_relaxed (ref_div_addr ) >> MSSPLL_REFDIV_SHIFT ;
107127 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 );
110128
111- return prate * mult / (ref_div * MSSPLL_FIXED_DIV * postdiv );
129+ return prate * mult / (ref_div * MSSPLL_FIXED_DIV );
112130}
113131
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 )
115152{
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 ;
121155
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 );
126164
127- rate_before_ctrl = rate * (ref_div * MSSPLL_FIXED_DIV ) / mult ;
165+ data -> hw_data .hws [msspll_hw -> id ] = & msspll_hw -> hw ;
166+ }
128167
129- return divider_round_rate (hw , rate_before_ctrl , prate , NULL , MSSPLL_POSTDIV_WIDTH ,
130- msspll_hw -> flags );
168+ return 0 ;
131169}
132170
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 )
134176{
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 ;
142180
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 );
147183
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 );
151206
152207 if (divider_setting < 0 )
153208 return divider_setting ;
@@ -163,42 +218,39 @@ static int mpfs_clk_msspll_set_rate(struct clk_hw *hw, unsigned long rate, unsig
163218 return 0 ;
164219}
165220
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 ,
170225};
171226
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), \
179231}
180232
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 ),
184235};
185236
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 )
188240{
189241 unsigned int i ;
190242 int ret ;
191243
192244 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 ];
194246
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 );
197249 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 );
200252
201- data -> hw_data .hws [msspll_hw -> id ] = & msspll_hw -> hw ;
253+ data -> hw_data .hws [msspll_out_hw -> id ] = & msspll_out_hw -> hw ;
202254 }
203255
204256 return 0 ;
@@ -442,8 +494,8 @@ static int mpfs_clk_probe(struct platform_device *pdev)
442494 int ret ;
443495
444496 /* 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 ;
447499
448500 clk_data = devm_kzalloc (dev , struct_size (clk_data , hw_data .hws , num_clks ), GFP_KERNEL );
449501 if (!clk_data )
@@ -466,6 +518,12 @@ static int mpfs_clk_probe(struct platform_device *pdev)
466518 if (ret )
467519 return ret ;
468520
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+
469527 ret = mpfs_clk_register_cfgs (dev , mpfs_cfg_clks , ARRAY_SIZE (mpfs_cfg_clks ), clk_data );
470528 if (ret )
471529 return ret ;
0 commit comments