2 * Copyright (C) 2014 Philipp Zabel, Pengutronix
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * PWM (mis)used as clock output
10 #include <linux/clk-provider.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/pwm.h>
19 struct pwm_device
*pwm
;
23 static inline struct clk_pwm
*to_clk_pwm(struct clk_hw
*hw
)
25 return container_of(hw
, struct clk_pwm
, hw
);
28 static int clk_pwm_prepare(struct clk_hw
*hw
)
30 struct clk_pwm
*clk_pwm
= to_clk_pwm(hw
);
32 return pwm_enable(clk_pwm
->pwm
);
35 static void clk_pwm_unprepare(struct clk_hw
*hw
)
37 struct clk_pwm
*clk_pwm
= to_clk_pwm(hw
);
39 pwm_disable(clk_pwm
->pwm
);
42 static unsigned long clk_pwm_recalc_rate(struct clk_hw
*hw
,
43 unsigned long parent_rate
)
45 struct clk_pwm
*clk_pwm
= to_clk_pwm(hw
);
47 return clk_pwm
->fixed_rate
;
50 static const struct clk_ops clk_pwm_ops
= {
51 .prepare
= clk_pwm_prepare
,
52 .unprepare
= clk_pwm_unprepare
,
53 .recalc_rate
= clk_pwm_recalc_rate
,
56 static int clk_pwm_probe(struct platform_device
*pdev
)
58 struct device_node
*node
= pdev
->dev
.of_node
;
59 struct clk_init_data init
;
60 struct clk_pwm
*clk_pwm
;
61 struct pwm_device
*pwm
;
66 clk_pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*clk_pwm
), GFP_KERNEL
);
70 pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
75 dev_err(&pdev
->dev
, "invalid PWM period\n");
79 if (of_property_read_u32(node
, "clock-frequency", &clk_pwm
->fixed_rate
))
80 clk_pwm
->fixed_rate
= NSEC_PER_SEC
/ pwm
->period
;
82 if (pwm
->period
!= NSEC_PER_SEC
/ clk_pwm
->fixed_rate
&&
83 pwm
->period
!= DIV_ROUND_UP(NSEC_PER_SEC
, clk_pwm
->fixed_rate
)) {
85 "clock-frequency does not match PWM period\n");
89 ret
= pwm_config(pwm
, (pwm
->period
+ 1) >> 1, pwm
->period
);
93 clk_name
= node
->name
;
94 of_property_read_string(node
, "clock-output-names", &clk_name
);
97 init
.ops
= &clk_pwm_ops
;
98 init
.flags
= CLK_IS_BASIC
| CLK_IS_ROOT
;
102 clk_pwm
->hw
.init
= &init
;
103 clk
= devm_clk_register(&pdev
->dev
, &clk_pwm
->hw
);
107 return of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
110 static int clk_pwm_remove(struct platform_device
*pdev
)
112 of_clk_del_provider(pdev
->dev
.of_node
);
117 static const struct of_device_id clk_pwm_dt_ids
[] = {
118 { .compatible
= "pwm-clock" },
121 MODULE_DEVICE_TABLE(of
, clk_pwm_dt_ids
);
123 static struct platform_driver clk_pwm_driver
= {
124 .probe
= clk_pwm_probe
,
125 .remove
= clk_pwm_remove
,
128 .of_match_table
= of_match_ptr(clk_pwm_dt_ids
),
132 module_platform_driver(clk_pwm_driver
);
134 MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
135 MODULE_DESCRIPTION("PWM clock driver");
136 MODULE_LICENSE("GPL");