11
11
#define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk"
12
12
#define to_socfpga_gate_clk (p ) container_of(p, struct socfpga_gate_clk, hw.hw)
13
13
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
+
14
21
static unsigned long socfpga_gate_clk_recalc_rate (struct clk_hw * hwclk ,
15
22
unsigned long parent_rate )
16
23
{
@@ -44,14 +51,61 @@ static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
44
51
static u8 socfpga_gate_get_parent (struct clk_hw * hwclk )
45
52
{
46
53
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 ;
48
85
u8 parent = 0 ;
86
+ const char * name = clk_hw_get_name (hwclk );
49
87
50
88
if (socfpgaclk -> bypass_reg ) {
51
89
mask = (0x1 << socfpgaclk -> bypass_shift );
52
90
parent = ((readl (socfpgaclk -> bypass_reg ) & mask ) >>
53
91
socfpgaclk -> bypass_shift );
54
92
}
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
+
55
109
return parent ;
56
110
}
57
111
@@ -60,6 +114,11 @@ static struct clk_ops gateclk_ops = {
60
114
.get_parent = socfpga_gate_get_parent ,
61
115
};
62
116
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
+
63
122
static const struct clk_ops dbgclk_ops = {
64
123
.recalc_rate = socfpga_dbg_clk_recalc_rate ,
65
124
.get_parent = socfpga_gate_get_parent ,
@@ -122,3 +181,61 @@ struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void _
122
181
}
123
182
return hw_clk ;
124
183
}
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