1111#define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk"
1212#define to_socfpga_gate_clk (p ) container_of(p, struct socfpga_gate_clk, hw.hw)
1313
14+ #define SOCFPGA_EMAC0_CLK "emac0_clk"
15+ #define SOCFPGA_EMAC1_CLK "emac1_clk"
16+ #define SOCFPGA_EMAC2_CLK "emac2_clk"
17+ #define AGILEX_BYPASS_OFFSET 0xC
18+ #define STRATIX10_BYPASS_OFFSET 0x2C
19+ #define BOOTCLK_BYPASS 2
20+
1421static unsigned long socfpga_gate_clk_recalc_rate (struct clk_hw * hwclk ,
1522 unsigned long parent_rate )
1623{
@@ -44,14 +51,61 @@ static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
4451static u8 socfpga_gate_get_parent (struct clk_hw * hwclk )
4552{
4653 struct socfpga_gate_clk * socfpgaclk = to_socfpga_gate_clk (hwclk );
47- u32 mask ;
54+ u32 mask , second_bypass ;
55+ u8 parent = 0 ;
56+ const char * name = clk_hw_get_name (hwclk );
57+
58+ if (socfpgaclk -> bypass_reg ) {
59+ mask = (0x1 << socfpgaclk -> bypass_shift );
60+ parent = ((readl (socfpgaclk -> bypass_reg ) & mask ) >>
61+ socfpgaclk -> bypass_shift );
62+ }
63+
64+ if (streq (name , SOCFPGA_EMAC0_CLK ) ||
65+ streq (name , SOCFPGA_EMAC1_CLK ) ||
66+ streq (name , SOCFPGA_EMAC2_CLK )) {
67+ second_bypass = readl (socfpgaclk -> bypass_reg -
68+ STRATIX10_BYPASS_OFFSET );
69+ /* EMACA bypass to bootclk @0xB0 offset */
70+ if (second_bypass & 0x1 )
71+ if (parent == 0 ) /* only applicable if parent is maca */
72+ parent = BOOTCLK_BYPASS ;
73+
74+ if (second_bypass & 0x2 )
75+ if (parent == 1 ) /* only applicable if parent is macb */
76+ parent = BOOTCLK_BYPASS ;
77+ }
78+ return parent ;
79+ }
80+
81+ static u8 socfpga_agilex_gate_get_parent (struct clk_hw * hwclk )
82+ {
83+ struct socfpga_gate_clk * socfpgaclk = to_socfpga_gate_clk (hwclk );
84+ u32 mask , second_bypass ;
4885 u8 parent = 0 ;
86+ const char * name = clk_hw_get_name (hwclk );
4987
5088 if (socfpgaclk -> bypass_reg ) {
5189 mask = (0x1 << socfpgaclk -> bypass_shift );
5290 parent = ((readl (socfpgaclk -> bypass_reg ) & mask ) >>
5391 socfpgaclk -> bypass_shift );
5492 }
93+
94+ if (streq (name , SOCFPGA_EMAC0_CLK ) ||
95+ streq (name , SOCFPGA_EMAC1_CLK ) ||
96+ streq (name , SOCFPGA_EMAC2_CLK )) {
97+ second_bypass = readl (socfpgaclk -> bypass_reg -
98+ AGILEX_BYPASS_OFFSET );
99+ /* EMACA bypass to bootclk @0x88 offset */
100+ if (second_bypass & 0x1 )
101+ if (parent == 0 ) /* only applicable if parent is maca */
102+ parent = BOOTCLK_BYPASS ;
103+
104+ if (second_bypass & 0x2 )
105+ if (parent == 1 ) /* only applicable if parent is macb */
106+ parent = BOOTCLK_BYPASS ;
107+ }
108+
55109 return parent ;
56110}
57111
@@ -60,6 +114,11 @@ static struct clk_ops gateclk_ops = {
60114 .get_parent = socfpga_gate_get_parent ,
61115};
62116
117+ static const struct clk_ops agilex_gateclk_ops = {
118+ .recalc_rate = socfpga_gate_clk_recalc_rate ,
119+ .get_parent = socfpga_agilex_gate_get_parent ,
120+ };
121+
63122static const struct clk_ops dbgclk_ops = {
64123 .recalc_rate = socfpga_dbg_clk_recalc_rate ,
65124 .get_parent = socfpga_gate_get_parent ,
@@ -122,3 +181,61 @@ struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void _
122181 }
123182 return hw_clk ;
124183}
184+
185+ struct clk_hw * agilex_register_gate (const struct stratix10_gate_clock * clks , void __iomem * regbase )
186+ {
187+ struct clk_hw * hw_clk ;
188+ struct socfpga_gate_clk * socfpga_clk ;
189+ struct clk_init_data init ;
190+ const char * parent_name = clks -> parent_name ;
191+ int ret ;
192+
193+ socfpga_clk = kzalloc (sizeof (* socfpga_clk ), GFP_KERNEL );
194+ if (!socfpga_clk )
195+ return NULL ;
196+
197+ socfpga_clk -> hw .reg = regbase + clks -> gate_reg ;
198+ socfpga_clk -> hw .bit_idx = clks -> gate_idx ;
199+
200+ gateclk_ops .enable = clk_gate_ops .enable ;
201+ gateclk_ops .disable = clk_gate_ops .disable ;
202+
203+ socfpga_clk -> fixed_div = clks -> fixed_div ;
204+
205+ if (clks -> div_reg )
206+ socfpga_clk -> div_reg = regbase + clks -> div_reg ;
207+ else
208+ socfpga_clk -> div_reg = NULL ;
209+
210+ socfpga_clk -> width = clks -> div_width ;
211+ socfpga_clk -> shift = clks -> div_offset ;
212+
213+ if (clks -> bypass_reg )
214+ socfpga_clk -> bypass_reg = regbase + clks -> bypass_reg ;
215+ else
216+ socfpga_clk -> bypass_reg = NULL ;
217+ socfpga_clk -> bypass_shift = clks -> bypass_shift ;
218+
219+ if (streq (clks -> name , "cs_pdbg_clk" ))
220+ init .ops = & dbgclk_ops ;
221+ else
222+ init .ops = & agilex_gateclk_ops ;
223+
224+ init .name = clks -> name ;
225+ init .flags = clks -> flags ;
226+
227+ init .num_parents = clks -> num_parents ;
228+ init .parent_names = parent_name ? & parent_name : NULL ;
229+ if (init .parent_names == NULL )
230+ init .parent_data = clks -> parent_data ;
231+ socfpga_clk -> hw .hw .init = & init ;
232+
233+ hw_clk = & socfpga_clk -> hw .hw ;
234+
235+ ret = clk_hw_register (NULL , & socfpga_clk -> hw .hw );
236+ if (ret ) {
237+ kfree (socfpga_clk );
238+ return ERR_PTR (ret );
239+ }
240+ return hw_clk ;
241+ }
0 commit comments