3535 *
3636 * @hw: handle between common and hardware-specific interfaces
3737 * @gpiod: gpio descriptor
38+ * @dev: device pointer for acquire/release operations
3839 *
3940 * Clock with a gpio control for enabling and disabling the parent clock
4041 * or switching between two parents by asserting or deasserting the gpio.
4647struct clk_gpio {
4748 struct clk_hw hw ;
4849 struct gpio_desc * gpiod ;
50+ struct device * dev ;
4951};
5052
5153#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+ }
5285
5386static int clk_gpio_gate_enable (struct clk_hw * hw )
5487{
@@ -79,6 +112,37 @@ static const struct clk_ops clk_gpio_gate_ops = {
79112 .is_enabled = clk_gpio_gate_is_enabled ,
80113};
81114
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+
82146static int clk_sleeping_gpio_gate_prepare (struct clk_hw * hw )
83147{
84148 struct clk_gpio * clk = to_clk_gpio (hw );
@@ -108,6 +172,37 @@ static const struct clk_ops clk_sleeping_gpio_gate_ops = {
108172 .is_prepared = clk_sleeping_gpio_gate_is_prepared ,
109173};
110174
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+
111206/**
112207 * DOC: basic clock multiplexer which can be controlled with a gpio output
113208 * Traits of this clock:
@@ -162,6 +257,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
162257 init .flags = CLK_SET_RATE_PARENT ;
163258
164259 clk_gpio -> gpiod = gpiod ;
260+ clk_gpio -> dev = dev ;
165261 clk_gpio -> hw .init = & init ;
166262
167263 hw = & clk_gpio -> hw ;
@@ -174,14 +270,29 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
174270
175271static struct clk_hw * clk_hw_register_gpio_gate (struct device * dev ,
176272 int num_parents ,
177- struct gpio_desc * gpiod )
273+ struct gpio_desc * gpiod ,
274+ bool releasing )
178275{
179276 const struct clk_ops * ops ;
180277
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+ }
185296
186297 return clk_register_gpio (dev , num_parents , gpiod , ops );
187298}
@@ -201,8 +312,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
201312 struct gpio_desc * gpiod ;
202313 struct clk_hw * hw ;
203314 bool is_mux ;
315+ bool is_releasing ;
204316
205317 is_mux = of_device_is_compatible (node , "gpio-mux-clock" );
318+ is_releasing =
319+ of_device_is_compatible (node , "gpio-gate-clock-releasing" );
206320
207321 num_parents = of_clk_get_parent_count (node );
208322 if (is_mux && num_parents != 2 ) {
@@ -219,7 +333,9 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
219333 if (is_mux )
220334 hw = clk_hw_register_gpio_mux (dev , gpiod );
221335 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+
223339 if (IS_ERR (hw ))
224340 return PTR_ERR (hw );
225341
@@ -229,6 +345,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
229345static const struct of_device_id gpio_clk_match_table [] = {
230346 { .compatible = "gpio-mux-clock" },
231347 { .compatible = "gpio-gate-clock" },
348+ { .compatible = "gpio-gate-clock-releasing" },
232349 { }
233350};
234351
0 commit comments