Skip to content

Commit 4940071

Browse files
mmindbebarino
authored andcommitted
clk: clk-gpio: add driver for gated-fixed-clocks
In contrast to fixed clocks that are described as ungateable, boards sometimes use additional oscillators for things like PCIe reference clocks, that need actual supplies to get enabled and enable-gpios to be toggled for them to work. This adds a driver for those generic gated-fixed-clocks that can show up in schematics looking like ---------------- Enable - | 100MHz,3.3V, | - VDD | 3225 | GND - | | - OUT ---------------- The new driver gets grouped together with the existing gpio-gate and gpio-mux, as it for one re-uses a lot of the gpio-gate functions and also in its core it's just another gpio-controlled clock, just with a fixed rate and a regulator-supply added in. The regulator-API provides function stubs for the !CONFIG_REGULATOR case, so no special handling is necessary. Signed-off-by: Heiko Stuebner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 36abe81 commit 4940071

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

drivers/clk/clk-gpio.c

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/device.h>
1818
#include <linux/of.h>
1919
#include <linux/platform_device.h>
20+
#include <linux/regulator/consumer.h>
2021

2122
/**
2223
* DOC: basic gpio gated clock which can be enabled and disabled
@@ -239,3 +240,187 @@ static struct platform_driver gpio_clk_driver = {
239240
},
240241
};
241242
builtin_platform_driver(gpio_clk_driver);
243+
244+
/**
245+
* DOC: gated fixed clock, controlled with a gpio output and a regulator
246+
* Traits of this clock:
247+
* prepare - clk_prepare and clk_unprepare are function & control regulator
248+
* optionally a gpio that can sleep
249+
* enable - clk_enable and clk_disable are functional & control gpio
250+
* rate - rate is fixed and set on clock registration
251+
* parent - fixed clock is a root clock and has no parent
252+
*/
253+
254+
/**
255+
* struct clk_gated_fixed - Gateable fixed rate clock
256+
* @clk_gpio: instance of clk_gpio for gate-gpio
257+
* @supply: supply regulator
258+
* @rate: fixed rate
259+
*/
260+
struct clk_gated_fixed {
261+
struct clk_gpio clk_gpio;
262+
struct regulator *supply;
263+
unsigned long rate;
264+
};
265+
266+
#define to_clk_gated_fixed(_clk_gpio) container_of(_clk_gpio, struct clk_gated_fixed, clk_gpio)
267+
268+
static unsigned long clk_gated_fixed_recalc_rate(struct clk_hw *hw,
269+
unsigned long parent_rate)
270+
{
271+
return to_clk_gated_fixed(to_clk_gpio(hw))->rate;
272+
}
273+
274+
static int clk_gated_fixed_prepare(struct clk_hw *hw)
275+
{
276+
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
277+
278+
if (!clk->supply)
279+
return 0;
280+
281+
return regulator_enable(clk->supply);
282+
}
283+
284+
static void clk_gated_fixed_unprepare(struct clk_hw *hw)
285+
{
286+
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
287+
288+
if (!clk->supply)
289+
return;
290+
291+
regulator_disable(clk->supply);
292+
}
293+
294+
static int clk_gated_fixed_is_prepared(struct clk_hw *hw)
295+
{
296+
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
297+
298+
if (!clk->supply)
299+
return true;
300+
301+
return regulator_is_enabled(clk->supply);
302+
}
303+
304+
/*
305+
* Fixed gated clock with non-sleeping gpio.
306+
*
307+
* Prepare operation turns on the supply regulator
308+
* and the enable operation switches the enable-gpio.
309+
*/
310+
static const struct clk_ops clk_gated_fixed_ops = {
311+
.prepare = clk_gated_fixed_prepare,
312+
.unprepare = clk_gated_fixed_unprepare,
313+
.is_prepared = clk_gated_fixed_is_prepared,
314+
.enable = clk_gpio_gate_enable,
315+
.disable = clk_gpio_gate_disable,
316+
.is_enabled = clk_gpio_gate_is_enabled,
317+
.recalc_rate = clk_gated_fixed_recalc_rate,
318+
};
319+
320+
static int clk_sleeping_gated_fixed_prepare(struct clk_hw *hw)
321+
{
322+
int ret;
323+
324+
ret = clk_gated_fixed_prepare(hw);
325+
if (ret)
326+
return ret;
327+
328+
ret = clk_sleeping_gpio_gate_prepare(hw);
329+
if (ret)
330+
clk_gated_fixed_unprepare(hw);
331+
332+
return ret;
333+
}
334+
335+
static void clk_sleeping_gated_fixed_unprepare(struct clk_hw *hw)
336+
{
337+
clk_gated_fixed_unprepare(hw);
338+
clk_sleeping_gpio_gate_unprepare(hw);
339+
}
340+
341+
/*
342+
* Fixed gated clock with non-sleeping gpio.
343+
*
344+
* Enabling the supply regulator and switching the enable-gpio happens
345+
* both in the prepare step.
346+
* is_prepared only needs to check the gpio state, as toggling the
347+
* gpio is the last step when preparing.
348+
*/
349+
static const struct clk_ops clk_sleeping_gated_fixed_ops = {
350+
.prepare = clk_sleeping_gated_fixed_prepare,
351+
.unprepare = clk_sleeping_gated_fixed_unprepare,
352+
.is_prepared = clk_sleeping_gpio_gate_is_prepared,
353+
.recalc_rate = clk_gated_fixed_recalc_rate,
354+
};
355+
356+
static int clk_gated_fixed_probe(struct platform_device *pdev)
357+
{
358+
struct device *dev = &pdev->dev;
359+
struct clk_gated_fixed *clk;
360+
const struct clk_ops *ops;
361+
const char *clk_name;
362+
u32 rate;
363+
int ret;
364+
365+
clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
366+
if (!clk)
367+
return -ENOMEM;
368+
369+
ret = device_property_read_u32(dev, "clock-frequency", &rate);
370+
if (ret)
371+
return dev_err_probe(dev, ret, "Failed to get clock-frequency\n");
372+
clk->rate = rate;
373+
374+
ret = device_property_read_string(dev, "clock-output-names", &clk_name);
375+
if (ret)
376+
clk_name = fwnode_get_name(dev->fwnode);
377+
378+
clk->supply = devm_regulator_get_optional(dev, "vdd");
379+
if (IS_ERR(clk->supply)) {
380+
if (PTR_ERR(clk->supply) != -ENODEV)
381+
return dev_err_probe(dev, PTR_ERR(clk->supply),
382+
"Failed to get regulator\n");
383+
clk->supply = NULL;
384+
}
385+
386+
clk->clk_gpio.gpiod = devm_gpiod_get_optional(dev, "enable",
387+
GPIOD_OUT_LOW);
388+
if (IS_ERR(clk->clk_gpio.gpiod))
389+
return dev_err_probe(dev, PTR_ERR(clk->clk_gpio.gpiod),
390+
"Failed to get gpio\n");
391+
392+
if (gpiod_cansleep(clk->clk_gpio.gpiod))
393+
ops = &clk_sleeping_gated_fixed_ops;
394+
else
395+
ops = &clk_gated_fixed_ops;
396+
397+
clk->clk_gpio.hw.init = CLK_HW_INIT_NO_PARENT(clk_name, ops, 0);
398+
399+
/* register the clock */
400+
ret = devm_clk_hw_register(dev, &clk->clk_gpio.hw);
401+
if (ret)
402+
return dev_err_probe(dev, ret,
403+
"Failed to register clock\n");
404+
405+
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
406+
&clk->clk_gpio.hw);
407+
if (ret)
408+
return dev_err_probe(dev, ret,
409+
"Failed to register clock provider\n");
410+
411+
return 0;
412+
}
413+
414+
static const struct of_device_id gated_fixed_clk_match_table[] = {
415+
{ .compatible = "gated-fixed-clock" },
416+
{ /* sentinel */ }
417+
};
418+
419+
static struct platform_driver gated_fixed_clk_driver = {
420+
.probe = clk_gated_fixed_probe,
421+
.driver = {
422+
.name = "gated-fixed-clk",
423+
.of_match_table = gated_fixed_clk_match_table,
424+
},
425+
};
426+
builtin_platform_driver(gated_fixed_clk_driver);

0 commit comments

Comments
 (0)