35
35
*
36
36
* @hw: handle between common and hardware-specific interfaces
37
37
* @gpiod: gpio descriptor
38
+ * @dev: device pointer for acquire/release operations
38
39
*
39
40
* Clock with a gpio control for enabling and disabling the parent clock
40
41
* or switching between two parents by asserting or deasserting the gpio.
46
47
struct clk_gpio {
47
48
struct clk_hw hw ;
48
49
struct gpio_desc * gpiod ;
50
+ struct device * dev ;
49
51
};
50
52
51
53
#define to_clk_gpio (_hw ) container_of(_hw, struct clk_gpio, hw)
54
+ static int clk_gpio_gate_acquire (struct clk_hw * hw )
55
+ {
56
+ struct clk_gpio * clk = to_clk_gpio (hw );
57
+ struct device * dev = clk -> dev ;
58
+
59
+ clk -> gpiod = devm_gpiod_get (dev , "enable" , GPIOD_OUT_LOW );
60
+ if (IS_ERR (clk -> gpiod )) {
61
+ int ret = PTR_ERR (clk -> gpiod );
62
+
63
+ clk -> gpiod = NULL ;
64
+ return ret ;
65
+ }
66
+
67
+ return 0 ;
68
+ }
69
+
70
+ static bool clk_gpio_gate_is_acquired (struct clk_hw * hw )
71
+ {
72
+ struct clk_gpio * clk = to_clk_gpio (hw );
73
+
74
+ return !!clk -> gpiod ;
75
+ }
76
+
77
+ static void clk_gpio_gate_release (struct clk_hw * hw )
78
+ {
79
+ struct clk_gpio * clk = to_clk_gpio (hw );
80
+ struct device * dev = clk -> dev ;
81
+
82
+ devm_gpiod_put (dev , clk -> gpiod );
83
+ clk -> gpiod = NULL ;
84
+ }
52
85
53
86
static int clk_gpio_gate_enable (struct clk_hw * hw )
54
87
{
@@ -79,6 +112,37 @@ static const struct clk_ops clk_gpio_gate_ops = {
79
112
.is_enabled = clk_gpio_gate_is_enabled ,
80
113
};
81
114
115
+ static int clk_gpio_gate_releasing_enable (struct clk_hw * hw )
116
+ {
117
+ int ret ;
118
+
119
+ ret = clk_gpio_gate_acquire (hw );
120
+ if (ret )
121
+ return ret ;
122
+
123
+ return clk_gpio_gate_enable (hw );
124
+ }
125
+
126
+ static void clk_gpio_gate_releasing_disable (struct clk_hw * hw )
127
+ {
128
+ clk_gpio_gate_disable (hw );
129
+ clk_gpio_gate_release (hw );
130
+ }
131
+
132
+ static int clk_gpio_gate_releasing_is_enabled (struct clk_hw * hw )
133
+ {
134
+ if (!clk_gpio_gate_is_acquired (hw ))
135
+ return 0 ;
136
+
137
+ return clk_gpio_gate_is_enabled (hw );
138
+ }
139
+
140
+ static const struct clk_ops clk_gpio_gate_releasing_ops = {
141
+ .enable = clk_gpio_gate_releasing_enable ,
142
+ .disable = clk_gpio_gate_releasing_disable ,
143
+ .is_enabled = clk_gpio_gate_releasing_is_enabled ,
144
+ };
145
+
82
146
static int clk_sleeping_gpio_gate_prepare (struct clk_hw * hw )
83
147
{
84
148
struct clk_gpio * clk = to_clk_gpio (hw );
@@ -108,6 +172,37 @@ static const struct clk_ops clk_sleeping_gpio_gate_ops = {
108
172
.is_prepared = clk_sleeping_gpio_gate_is_prepared ,
109
173
};
110
174
175
+ static int clk_sleeping_gpio_gate_releasing_prepare (struct clk_hw * hw )
176
+ {
177
+ int ret ;
178
+
179
+ ret = clk_gpio_gate_acquire (hw );
180
+ if (ret )
181
+ return ret ;
182
+
183
+ return clk_sleeping_gpio_gate_prepare (hw );
184
+ }
185
+
186
+ static void clk_sleeping_gpio_gate_releasing_unprepare (struct clk_hw * hw )
187
+ {
188
+ clk_sleeping_gpio_gate_unprepare (hw );
189
+ clk_gpio_gate_release (hw );
190
+ }
191
+
192
+ static int clk_sleeping_gpio_gate_releasing_is_prepared (struct clk_hw * hw )
193
+ {
194
+ if (!clk_gpio_gate_is_acquired (hw ))
195
+ return 0 ;
196
+
197
+ return clk_sleeping_gpio_gate_is_prepared (hw );
198
+ }
199
+
200
+ static const struct clk_ops clk_sleeping_gpio_gate_releasing_ops = {
201
+ .prepare = clk_sleeping_gpio_gate_releasing_prepare ,
202
+ .unprepare = clk_sleeping_gpio_gate_releasing_unprepare ,
203
+ .is_prepared = clk_sleeping_gpio_gate_releasing_is_prepared ,
204
+ };
205
+
111
206
/**
112
207
* DOC: basic clock multiplexer which can be controlled with a gpio output
113
208
* Traits of this clock:
@@ -162,6 +257,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
162
257
init .flags = CLK_SET_RATE_PARENT ;
163
258
164
259
clk_gpio -> gpiod = gpiod ;
260
+ clk_gpio -> dev = dev ;
165
261
clk_gpio -> hw .init = & init ;
166
262
167
263
hw = & clk_gpio -> hw ;
@@ -174,14 +270,29 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
174
270
175
271
static struct clk_hw * clk_hw_register_gpio_gate (struct device * dev ,
176
272
int num_parents ,
177
- struct gpio_desc * gpiod )
273
+ struct gpio_desc * gpiod ,
274
+ bool releasing )
178
275
{
179
276
const struct clk_ops * ops ;
180
277
181
- if (gpiod_cansleep (gpiod ))
182
- ops = & clk_sleeping_gpio_gate_ops ;
183
- else
184
- ops = & clk_gpio_gate_ops ;
278
+ if (releasing ) {
279
+ /* For releasing variant, confirm GPIO works then release it
280
+ * for acquire/release semantics
281
+ */
282
+ if (gpiod_cansleep (gpiod ))
283
+ ops = & clk_sleeping_gpio_gate_releasing_ops ;
284
+ else
285
+ ops = & clk_gpio_gate_releasing_ops ;
286
+
287
+ devm_gpiod_put (dev , gpiod );
288
+ gpiod = NULL ;
289
+ } else {
290
+ /* Regular variant - keep GPIO and choose appropriate ops */
291
+ if (gpiod_cansleep (gpiod ))
292
+ ops = & clk_sleeping_gpio_gate_ops ;
293
+ else
294
+ ops = & clk_gpio_gate_ops ;
295
+ }
185
296
186
297
return clk_register_gpio (dev , num_parents , gpiod , ops );
187
298
}
@@ -201,8 +312,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
201
312
struct gpio_desc * gpiod ;
202
313
struct clk_hw * hw ;
203
314
bool is_mux ;
315
+ bool is_releasing ;
204
316
205
317
is_mux = of_device_is_compatible (node , "gpio-mux-clock" );
318
+ is_releasing =
319
+ of_device_is_compatible (node , "gpio-gate-clock-releasing" );
206
320
207
321
num_parents = of_clk_get_parent_count (node );
208
322
if (is_mux && num_parents != 2 ) {
@@ -219,7 +333,9 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
219
333
if (is_mux )
220
334
hw = clk_hw_register_gpio_mux (dev , gpiod );
221
335
else
222
- hw = clk_hw_register_gpio_gate (dev , num_parents , gpiod );
336
+ hw = clk_hw_register_gpio_gate (dev , num_parents , gpiod ,
337
+ is_releasing );
338
+
223
339
if (IS_ERR (hw ))
224
340
return PTR_ERR (hw );
225
341
@@ -229,6 +345,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
229
345
static const struct of_device_id gpio_clk_match_table [] = {
230
346
{ .compatible = "gpio-mux-clock" },
231
347
{ .compatible = "gpio-gate-clock" },
348
+ { .compatible = "gpio-gate-clock-releasing" },
232
349
{ }
233
350
};
234
351
0 commit comments