@@ -56,6 +56,7 @@ struct ccu_gate {
5656
5757struct ccu_div {
5858 u32 enable ;
59+ u32 div_en ;
5960 struct ccu_div_internal div ;
6061 struct ccu_internal mux ;
6162 struct ccu_common common ;
@@ -192,6 +193,55 @@ static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
192193 return rate ;
193194}
194195
196+ static int ccu_div_determine_rate (struct clk_hw * hw ,
197+ struct clk_rate_request * req )
198+ {
199+ struct ccu_div * cd = hw_to_ccu_div (hw );
200+ unsigned int val ;
201+
202+ if (cd -> div_en )
203+ return divider_determine_rate (hw , req , NULL ,
204+ cd -> div .width , cd -> div .flags );
205+
206+ regmap_read (cd -> common .map , cd -> common .cfg0 , & val );
207+ val = val >> cd -> div .shift ;
208+ val &= GENMASK (cd -> div .width - 1 , 0 );
209+ return divider_ro_determine_rate (hw , req , NULL , cd -> div .width ,
210+ cd -> div .flags , val );
211+ }
212+
213+ static int ccu_div_set_rate (struct clk_hw * hw , unsigned long rate ,
214+ unsigned long parent_rate )
215+ {
216+ struct ccu_div * cd = hw_to_ccu_div (hw );
217+ int val = divider_get_val (rate , parent_rate , NULL ,
218+ cd -> div .width , cd -> div .flags );
219+ unsigned int curr_val , reg_val ;
220+
221+ if (val < 0 )
222+ return val ;
223+
224+ regmap_read (cd -> common .map , cd -> common .cfg0 , & reg_val );
225+ curr_val = reg_val >> cd -> div .shift ;
226+ curr_val &= GENMASK (cd -> div .width - 1 , 0 );
227+
228+ if (!cd -> div_en && curr_val != val )
229+ return - EINVAL ;
230+
231+ reg_val &= ~cd -> div_en ;
232+ regmap_write (cd -> common .map , cd -> common .cfg0 , reg_val );
233+ udelay (1 );
234+
235+ reg_val &= ~GENMASK (cd -> div .width + cd -> div .shift - 1 , cd -> div .shift );
236+ reg_val |= val << cd -> div .shift ;
237+ regmap_write (cd -> common .map , cd -> common .cfg0 , reg_val );
238+
239+ reg_val |= cd -> div_en ;
240+ regmap_write (cd -> common .map , cd -> common .cfg0 , reg_val );
241+
242+ return 0 ;
243+ }
244+
195245static u8 ccu_div_get_parent (struct clk_hw * hw )
196246{
197247 struct ccu_div * cd = hw_to_ccu_div (hw );
@@ -234,7 +284,8 @@ static const struct clk_ops ccu_div_ops = {
234284 .get_parent = ccu_div_get_parent ,
235285 .set_parent = ccu_div_set_parent ,
236286 .recalc_rate = ccu_div_recalc_rate ,
237- .determine_rate = clk_hw_determine_rate_no_reparent ,
287+ .set_rate = ccu_div_set_rate ,
288+ .determine_rate = ccu_div_determine_rate ,
238289};
239290
240291static void ccu_pll_disable (struct clk_hw * hw )
@@ -778,14 +829,15 @@ static struct ccu_div venc_clk = {
778829};
779830
780831static struct ccu_div dpu0_clk = {
832+ .div_en = BIT (8 ),
781833 .div = TH_CCU_DIV_FLAGS (0 , 8 , CLK_DIVIDER_ONE_BASED ),
782834 .common = {
783835 .clkid = CLK_DPU0 ,
784836 .cfg0 = 0x1e8 ,
785837 .hw .init = CLK_HW_INIT_PARENTS_HW ("dpu0" ,
786838 dpu0_pll_clk_parent ,
787839 & ccu_div_ops ,
788- 0 ),
840+ CLK_SET_RATE_UNGATE ),
789841 },
790842};
791843
@@ -794,14 +846,15 @@ static const struct clk_parent_data dpu0_clk_pd[] = {
794846};
795847
796848static struct ccu_div dpu1_clk = {
849+ .div_en = BIT (8 ),
797850 .div = TH_CCU_DIV_FLAGS (0 , 8 , CLK_DIVIDER_ONE_BASED ),
798851 .common = {
799852 .clkid = CLK_DPU1 ,
800853 .cfg0 = 0x1ec ,
801854 .hw .init = CLK_HW_INIT_PARENTS_HW ("dpu1" ,
802855 dpu1_pll_clk_parent ,
803856 & ccu_div_ops ,
804- 0 ),
857+ CLK_SET_RATE_UNGATE ),
805858 },
806859};
807860
@@ -889,9 +942,9 @@ static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
889942static CCU_GATE (CLK_GPU_CFG_ACLK , gpu_cfg_aclk , "gpu-cfg-aclk" ,
890943 video_pll_clk_pd , 0x0 , 4 , 0 );
891944static CCU_GATE (CLK_DPU_PIXELCLK0 , dpu0_pixelclk , "dpu0-pixelclk" ,
892- dpu0_clk_pd , 0x0 , 5 , 0 );
945+ dpu0_clk_pd , 0x0 , 5 , CLK_SET_RATE_PARENT );
893946static CCU_GATE (CLK_DPU_PIXELCLK1 , dpu1_pixelclk , "dpu1-pixelclk" ,
894- dpu1_clk_pd , 0x0 , 6 , 0 );
947+ dpu1_clk_pd , 0x0 , 6 , CLK_SET_RATE_PARENT );
895948static CCU_GATE (CLK_DPU_HCLK , dpu_hclk , "dpu-hclk" , video_pll_clk_pd , 0x0 ,
896949 7 , 0 );
897950static CCU_GATE (CLK_DPU_ACLK , dpu_aclk , "dpu-aclk" , video_pll_clk_pd , 0x0 ,
0 commit comments