1
2
3
4
5
6
7#include <linux/clk.h>
8#include <linux/clk-provider.h>
9#include <linux/errno.h>
10#include <linux/io.h>
11#include <linux/module.h>
12#include <linux/of_device.h>
13#include <linux/platform_device.h>
14
15struct fclk_state {
16 struct device *dev;
17 struct clk *pl;
18};
19
20
21static const struct of_device_id fclk_of_match[] = {
22 { .compatible = "xlnx,fclk",},
23 { },
24};
25MODULE_DEVICE_TABLE(of, fclk_of_match);
26
27static ssize_t set_rate_show(struct device *dev,
28 struct device_attribute *attr, char *buf)
29{
30 struct fclk_state *st = dev_get_drvdata(dev);
31
32 return scnprintf(buf, PAGE_SIZE, "%lu\n", clk_get_rate(st->pl));
33}
34
35static ssize_t set_rate_store(struct device *dev,
36 struct device_attribute *attr,
37 const char *buf, size_t count)
38{
39 int ret = 0;
40 unsigned long rate;
41 struct fclk_state *st = dev_get_drvdata(dev);
42
43 ret = kstrtoul(buf, 0, &rate);
44 if (ret)
45 return -EINVAL;
46
47 rate = clk_round_rate(st->pl, rate);
48 ret = clk_set_rate(st->pl, rate);
49
50 return ret ? ret : count;
51}
52
53static DEVICE_ATTR_RW(set_rate);
54
55static const struct attribute *fclk_ctrl_attrs[] = {
56 &dev_attr_set_rate.attr,
57 NULL,
58};
59
60static const struct attribute_group fclk_ctrl_attr_grp = {
61 .attrs = (struct attribute **)fclk_ctrl_attrs,
62};
63
64static int fclk_probe(struct platform_device *pdev)
65{
66 struct fclk_state *st;
67 int ret;
68 struct device *dev = &pdev->dev;
69
70 st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
71 if (!st)
72 return -ENOMEM;
73
74 st->dev = dev;
75 platform_set_drvdata(pdev, st);
76
77 st->pl = devm_clk_get(&pdev->dev, NULL);
78 if (IS_ERR(st->pl))
79 return PTR_ERR(st->pl);
80
81 ret = clk_prepare_enable(st->pl);
82 if (ret) {
83 dev_err(&pdev->dev, "Unable to enable clock.\n");
84 return ret;
85 }
86
87 ret = sysfs_create_group(&dev->kobj, &fclk_ctrl_attr_grp);
88 if (ret)
89 return ret;
90
91 return 0;
92}
93
94static int fclk_remove(struct platform_device *pdev)
95{
96 struct fclk_state *st = platform_get_drvdata(pdev);
97
98 clk_disable_unprepare(st->pl);
99 return 0;
100}
101
102static struct platform_driver fclk_driver = {
103 .driver = {
104 .name = KBUILD_MODNAME,
105 .of_match_table = fclk_of_match,
106 },
107 .probe = fclk_probe,
108 .remove = fclk_remove,
109};
110
111module_platform_driver(fclk_driver);
112
113MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>");
114MODULE_DESCRIPTION("fclk enable");
115MODULE_LICENSE("GPL v2");
116