aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-max77686.c
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javier.martinez@collabora.co.uk>2014-08-18 04:33:01 -0400
committerMike Turquette <mturquette@linaro.org>2014-09-09 16:55:49 -0400
commit1887d69308f94eec12d581b4dbab67c28274039d (patch)
tree0846001dbdb969832735b2d1d4395d200b8c36f9 /drivers/clk/clk-max77686.c
parent5dbbb00f712edff8454f9741db61f9e0a4fec919 (diff)
clk: max77686: Convert to the generic max clock driver
Clocks drivers for Maxim PMIC are very similar so they can be converted to use the generic Maxim clock driver. Also, while being there use module_platform_driver() helper macro to eliminate more boilerplate code. Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk-max77686.c')
-rw-r--r--drivers/clk/clk-max77686.c176
1 files changed, 8 insertions, 168 deletions
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index 185b611c957e..ed0beb4cb39b 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -31,187 +31,37 @@
31#include <linux/clkdev.h> 31#include <linux/clkdev.h>
32 32
33#include <dt-bindings/clock/maxim,max77686.h> 33#include <dt-bindings/clock/maxim,max77686.h>
34 34#include "clk-max-gen.h"
35struct max77686_clk {
36 struct max77686_dev *iodev;
37 u32 mask;
38 struct clk_hw hw;
39 struct clk_lookup *lookup;
40};
41
42static struct max77686_clk *to_max77686_clk(struct clk_hw *hw)
43{
44 return container_of(hw, struct max77686_clk, hw);
45}
46
47static int max77686_clk_prepare(struct clk_hw *hw)
48{
49 struct max77686_clk *max77686 = to_max77686_clk(hw);
50
51 return regmap_update_bits(max77686->iodev->regmap,
52 MAX77686_REG_32KHZ, max77686->mask,
53 max77686->mask);
54}
55
56static void max77686_clk_unprepare(struct clk_hw *hw)
57{
58 struct max77686_clk *max77686 = to_max77686_clk(hw);
59
60 regmap_update_bits(max77686->iodev->regmap,
61 MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
62}
63
64static int max77686_clk_is_prepared(struct clk_hw *hw)
65{
66 struct max77686_clk *max77686 = to_max77686_clk(hw);
67 int ret;
68 u32 val;
69
70 ret = regmap_read(max77686->iodev->regmap,
71 MAX77686_REG_32KHZ, &val);
72
73 if (ret < 0)
74 return -EINVAL;
75
76 return val & max77686->mask;
77}
78
79static unsigned long max77686_recalc_rate(struct clk_hw *hw,
80 unsigned long parent_rate)
81{
82 return 32768;
83}
84
85static struct clk_ops max77686_clk_ops = {
86 .prepare = max77686_clk_prepare,
87 .unprepare = max77686_clk_unprepare,
88 .is_prepared = max77686_clk_is_prepared,
89 .recalc_rate = max77686_recalc_rate,
90};
91 35
92static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { 36static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
93 [MAX77686_CLK_AP] = { 37 [MAX77686_CLK_AP] = {
94 .name = "32khz_ap", 38 .name = "32khz_ap",
95 .ops = &max77686_clk_ops, 39 .ops = &max_gen_clk_ops,
96 .flags = CLK_IS_ROOT, 40 .flags = CLK_IS_ROOT,
97 }, 41 },
98 [MAX77686_CLK_CP] = { 42 [MAX77686_CLK_CP] = {
99 .name = "32khz_cp", 43 .name = "32khz_cp",
100 .ops = &max77686_clk_ops, 44 .ops = &max_gen_clk_ops,
101 .flags = CLK_IS_ROOT, 45 .flags = CLK_IS_ROOT,
102 }, 46 },
103 [MAX77686_CLK_PMIC] = { 47 [MAX77686_CLK_PMIC] = {
104 .name = "32khz_pmic", 48 .name = "32khz_pmic",
105 .ops = &max77686_clk_ops, 49 .ops = &max_gen_clk_ops,
106 .flags = CLK_IS_ROOT, 50 .flags = CLK_IS_ROOT,
107 }, 51 },
108}; 52};
109 53
110static struct clk *max77686_clk_register(struct device *dev,
111 struct max77686_clk *max77686)
112{
113 struct clk *clk;
114 struct clk_hw *hw = &max77686->hw;
115
116 clk = clk_register(dev, hw);
117 if (IS_ERR(clk))
118 return clk;
119
120 max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
121 if (!max77686->lookup)
122 return ERR_PTR(-ENOMEM);
123
124 max77686->lookup->con_id = hw->init->name;
125 max77686->lookup->clk = clk;
126
127 clkdev_add(max77686->lookup);
128
129 return clk;
130}
131
132static int max77686_clk_probe(struct platform_device *pdev) 54static int max77686_clk_probe(struct platform_device *pdev)
133{ 55{
134 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 56 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
135 struct max77686_clk *max77686_clks[MAX77686_CLKS_NUM];
136 struct clk **clocks;
137 int i, ret;
138
139 clocks = devm_kzalloc(&pdev->dev, sizeof(struct clk *)
140 * MAX77686_CLKS_NUM, GFP_KERNEL);
141 if (!clocks)
142 return -ENOMEM;
143
144 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
145 max77686_clks[i] = devm_kzalloc(&pdev->dev,
146 sizeof(struct max77686_clk), GFP_KERNEL);
147 if (!max77686_clks[i])
148 return -ENOMEM;
149 }
150
151 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
152 max77686_clks[i]->iodev = iodev;
153 max77686_clks[i]->mask = 1 << i;
154 max77686_clks[i]->hw.init = &max77686_clks_init[i];
155
156 clocks[i] = max77686_clk_register(&pdev->dev, max77686_clks[i]);
157 if (IS_ERR(clocks[i])) {
158 ret = PTR_ERR(clocks[i]);
159 dev_err(&pdev->dev, "failed to register %s\n",
160 max77686_clks[i]->hw.init->name);
161 goto err_clocks;
162 }
163 }
164
165 platform_set_drvdata(pdev, clocks);
166
167 if (iodev->dev->of_node) {
168 struct clk_onecell_data *of_data;
169
170 of_data = devm_kzalloc(&pdev->dev,
171 sizeof(*of_data), GFP_KERNEL);
172 if (!of_data) {
173 ret = -ENOMEM;
174 goto err_clocks;
175 }
176 57
177 of_data->clks = clocks; 58 return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ,
178 of_data->clk_num = MAX77686_CLKS_NUM; 59 max77686_clks_init, MAX77686_CLKS_NUM);
179 ret = of_clk_add_provider(iodev->dev->of_node,
180 of_clk_src_onecell_get, of_data);
181 if (ret) {
182 dev_err(&pdev->dev, "failed to register OF clock provider\n");
183 goto err_clocks;
184 }
185 }
186
187 return 0;
188
189err_clocks:
190 for (--i; i >= 0; --i) {
191 clkdev_drop(max77686_clks[i]->lookup);
192 clk_unregister(max77686_clks[i]->hw.clk);
193 }
194
195 return ret;
196} 60}
197 61
198static int max77686_clk_remove(struct platform_device *pdev) 62static int max77686_clk_remove(struct platform_device *pdev)
199{ 63{
200 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 64 return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM);
201 struct clk **clocks = platform_get_drvdata(pdev);
202 int i;
203
204 if (iodev->dev->of_node)
205 of_clk_del_provider(iodev->dev->of_node);
206
207 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
208 struct clk_hw *hw = __clk_get_hw(clocks[i]);
209 struct max77686_clk *max77686 = to_max77686_clk(hw);
210
211 clkdev_drop(max77686->lookup);
212 clk_unregister(clocks[i]);
213 }
214 return 0;
215} 65}
216 66
217static const struct platform_device_id max77686_clk_id[] = { 67static const struct platform_device_id max77686_clk_id[] = {
@@ -230,17 +80,7 @@ static struct platform_driver max77686_clk_driver = {
230 .id_table = max77686_clk_id, 80 .id_table = max77686_clk_id,
231}; 81};
232 82
233static int __init max77686_clk_init(void) 83module_platform_driver(max77686_clk_driver);
234{
235 return platform_driver_register(&max77686_clk_driver);
236}
237subsys_initcall(max77686_clk_init);
238
239static void __init max77686_clk_cleanup(void)
240{
241 platform_driver_unregister(&max77686_clk_driver);
242}
243module_exit(max77686_clk_cleanup);
244 84
245MODULE_DESCRIPTION("MAXIM 77686 Clock Driver"); 85MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
246MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>"); 86MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");