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