1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2012 ARM Limited
7 #include <linux/clkdev.h>
8 #include <linux/clk-provider.h>
10 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/slab.h>
14 #include <linux/vexpress.h>
19 unsigned long rate_min
;
20 unsigned long rate_max
;
23 #define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw)
25 static unsigned long vexpress_osc_recalc_rate(struct clk_hw
*hw
,
26 unsigned long parent_rate
)
28 struct vexpress_osc
*osc
= to_vexpress_osc(hw
);
31 regmap_read(osc
->reg
, 0, &rate
);
36 static long vexpress_osc_round_rate(struct clk_hw
*hw
, unsigned long rate
,
37 unsigned long *parent_rate
)
39 struct vexpress_osc
*osc
= to_vexpress_osc(hw
);
41 if (osc
->rate_min
&& rate
< osc
->rate_min
)
44 if (osc
->rate_max
&& rate
> osc
->rate_max
)
50 static int vexpress_osc_set_rate(struct clk_hw
*hw
, unsigned long rate
,
51 unsigned long parent_rate
)
53 struct vexpress_osc
*osc
= to_vexpress_osc(hw
);
55 return regmap_write(osc
->reg
, 0, rate
);
58 static const struct clk_ops vexpress_osc_ops
= {
59 .recalc_rate
= vexpress_osc_recalc_rate
,
60 .round_rate
= vexpress_osc_round_rate
,
61 .set_rate
= vexpress_osc_set_rate
,
65 static int vexpress_osc_probe(struct platform_device
*pdev
)
67 struct clk_init_data init
;
68 struct vexpress_osc
*osc
;
72 osc
= devm_kzalloc(&pdev
->dev
, sizeof(*osc
), GFP_KERNEL
);
76 osc
->reg
= devm_regmap_init_vexpress_config(&pdev
->dev
);
78 return PTR_ERR(osc
->reg
);
80 if (of_property_read_u32_array(pdev
->dev
.of_node
, "freq-range", range
,
81 ARRAY_SIZE(range
)) == 0) {
82 osc
->rate_min
= range
[0];
83 osc
->rate_max
= range
[1];
86 if (of_property_read_string(pdev
->dev
.of_node
, "clock-output-names",
88 init
.name
= dev_name(&pdev
->dev
);
90 init
.ops
= &vexpress_osc_ops
;
96 ret
= devm_clk_hw_register(&pdev
->dev
, &osc
->hw
);
100 devm_of_clk_add_hw_provider(&pdev
->dev
, of_clk_hw_simple_get
, &osc
->hw
);
101 clk_hw_set_rate_range(&osc
->hw
, osc
->rate_min
, osc
->rate_max
);
103 dev_dbg(&pdev
->dev
, "Registered clock '%s'\n", init
.name
);
108 static const struct of_device_id vexpress_osc_of_match
[] = {
109 { .compatible
= "arm,vexpress-osc", },
112 MODULE_DEVICE_TABLE(of
, vexpress_osc_of_match
);
114 static struct platform_driver vexpress_osc_driver
= {
116 .name
= "vexpress-osc",
117 .of_match_table
= vexpress_osc_of_match
,
119 .probe
= vexpress_osc_probe
,
121 module_platform_driver(vexpress_osc_driver
);
122 MODULE_LICENSE("GPL v2");