summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2016-06-17 06:51:04 -0400
committerStephen Boyd <sboyd@codeaurora.org>2016-08-15 18:32:41 -0400
commit8ad313fe4e0016bac5dc6a7fbb323b8551977bd9 (patch)
tree84207c740e559aeacba1db2e1d83cfa1c9efb35e
parentd336e9a71eedb1970b81bc8c042334b70fd4ddf7 (diff)
clk: max77686: Combine Maxim max77686 and max77802 driver
The clock IP used on the Maxim PMICs max77686 and max77802 are same. The configuration of clock register is also same except the number of clocks. Part of common code utilisation, there is 3 files for these chips clock driver, one for common and two files for driver registration. Combine both drivers into single file and move common code into same common file reduces the 2 files and make max77686 and max77802 clock driver in single fine. This driver does not depends on the parent driver structure. The regmap handle is acquired through regmap APIs for the register access. This combination of driver helps on adding clock driver for different Maxim PMICs which has similar clock IP like MAX77620 and MAX20024. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> CC: Krzysztof Kozlowski <k.kozlowski@samsung.com> CC: Javier Martinez Canillas <javier@dowhile0.org> Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com> Tested-by: Javier Martinez Canillas <javier@osg.samsung.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r--drivers/clk/Kconfig15
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/clk-max-gen.c194
-rw-r--r--drivers/clk/clk-max-gen.h32
-rw-r--r--drivers/clk/clk-max77686.c244
-rw-r--r--drivers/clk/clk-max77802.c96
6 files changed, 234 insertions, 349 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e2d9bd760c84..d7d2993a889c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -31,22 +31,11 @@ config COMMON_CLK_WM831X
31 31
32source "drivers/clk/versatile/Kconfig" 32source "drivers/clk/versatile/Kconfig"
33 33
34config COMMON_CLK_MAX_GEN
35 bool
36
37config COMMON_CLK_MAX77686 34config COMMON_CLK_MAX77686
38 tristate "Clock driver for Maxim 77686 MFD" 35 tristate "Clock driver for Maxim 77686/77802 MFD"
39 depends on MFD_MAX77686
40 select COMMON_CLK_MAX_GEN
41 ---help---
42 This driver supports Maxim 77686 crystal oscillator clock.
43
44config COMMON_CLK_MAX77802
45 tristate "Clock driver for Maxim 77802 PMIC"
46 depends on MFD_MAX77686 36 depends on MFD_MAX77686
47 select COMMON_CLK_MAX_GEN
48 ---help--- 37 ---help---
49 This driver supports Maxim 77802 crystal oscillator clock. 38 This driver supports Maxim 77686/77802 crystal oscillator clock.
50 39
51config COMMON_CLK_RK808 40config COMMON_CLK_RK808
52 tristate "Clock driver for RK808/RK818" 41 tristate "Clock driver for RK808/RK818"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3b6f9cf3464a..e775a836247c 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -27,9 +27,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
27obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 27obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
28obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 28obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
29obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o 29obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o
30obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o
31obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o 30obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
32obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o
33obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o 31obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o
34obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o 32obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
35obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o 33obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
deleted file mode 100644
index 35af9cb6da4f..000000000000
--- a/drivers/clk/clk-max-gen.c
+++ /dev/null
@@ -1,194 +0,0 @@
1/*
2 * clk-max-gen.c - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 *
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/err.h>
26#include <linux/regmap.h>
27#include <linux/platform_device.h>
28#include <linux/clk-provider.h>
29#include <linux/mutex.h>
30#include <linux/clkdev.h>
31#include <linux/of.h>
32#include <linux/export.h>
33
34#include "clk-max-gen.h"
35
36struct max_gen_clk {
37 struct regmap *regmap;
38 u32 mask;
39 u32 reg;
40 struct clk_hw hw;
41};
42
43static struct max_gen_clk *to_max_gen_clk(struct clk_hw *hw)
44{
45 return container_of(hw, struct max_gen_clk, hw);
46}
47
48static int max_gen_clk_prepare(struct clk_hw *hw)
49{
50 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
51
52 return regmap_update_bits(max_gen->regmap, max_gen->reg,
53 max_gen->mask, max_gen->mask);
54}
55
56static void max_gen_clk_unprepare(struct clk_hw *hw)
57{
58 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
59
60 regmap_update_bits(max_gen->regmap, max_gen->reg,
61 max_gen->mask, ~max_gen->mask);
62}
63
64static int max_gen_clk_is_prepared(struct clk_hw *hw)
65{
66 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
67 int ret;
68 u32 val;
69
70 ret = regmap_read(max_gen->regmap, max_gen->reg, &val);
71
72 if (ret < 0)
73 return -EINVAL;
74
75 return val & max_gen->mask;
76}
77
78static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
79 unsigned long parent_rate)
80{
81 return 32768;
82}
83
84struct clk_ops max_gen_clk_ops = {
85 .prepare = max_gen_clk_prepare,
86 .unprepare = max_gen_clk_unprepare,
87 .is_prepared = max_gen_clk_is_prepared,
88 .recalc_rate = max_gen_recalc_rate,
89};
90EXPORT_SYMBOL_GPL(max_gen_clk_ops);
91
92static struct clk *max_gen_clk_register(struct device *dev,
93 struct max_gen_clk *max_gen)
94{
95 struct clk *clk;
96 struct clk_hw *hw = &max_gen->hw;
97 int ret;
98
99 clk = devm_clk_register(dev, hw);
100 if (IS_ERR(clk))
101 return clk;
102
103 ret = clk_register_clkdev(clk, hw->init->name, NULL);
104
105 if (ret)
106 return ERR_PTR(ret);
107
108 return clk;
109}
110
111int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
112 u32 reg, struct clk_init_data *clks_init, int num_init)
113{
114 int i, ret;
115 struct max_gen_clk *max_gen_clks;
116 struct clk **clocks;
117 struct device *dev = pdev->dev.parent;
118 const char *clk_name;
119 struct clk_init_data *init;
120
121 clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, GFP_KERNEL);
122 if (!clocks)
123 return -ENOMEM;
124
125 max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
126 * num_init, GFP_KERNEL);
127 if (!max_gen_clks)
128 return -ENOMEM;
129
130 for (i = 0; i < num_init; i++) {
131 max_gen_clks[i].regmap = regmap;
132 max_gen_clks[i].mask = 1 << i;
133 max_gen_clks[i].reg = reg;
134
135 init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL);
136 if (!init)
137 return -ENOMEM;
138
139 if (dev->of_node &&
140 !of_property_read_string_index(dev->of_node,
141 "clock-output-names",
142 i, &clk_name))
143 init->name = clk_name;
144 else
145 init->name = clks_init[i].name;
146
147 init->ops = clks_init[i].ops;
148 init->flags = clks_init[i].flags;
149
150 max_gen_clks[i].hw.init = init;
151
152 clocks[i] = max_gen_clk_register(dev, &max_gen_clks[i]);
153 if (IS_ERR(clocks[i])) {
154 ret = PTR_ERR(clocks[i]);
155 dev_err(dev, "failed to register %s\n",
156 max_gen_clks[i].hw.init->name);
157 return ret;
158 }
159 }
160
161 platform_set_drvdata(pdev, clocks);
162
163 if (dev->of_node) {
164 struct clk_onecell_data *of_data;
165
166 of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
167 if (!of_data)
168 return -ENOMEM;
169
170 of_data->clks = clocks;
171 of_data->clk_num = num_init;
172 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
173 of_data);
174
175 if (ret) {
176 dev_err(dev, "failed to register OF clock provider\n");
177 return ret;
178 }
179 }
180
181 return 0;
182}
183EXPORT_SYMBOL_GPL(max_gen_clk_probe);
184
185int max_gen_clk_remove(struct platform_device *pdev, int num_init)
186{
187 struct device *dev = pdev->dev.parent;
188
189 if (dev->of_node)
190 of_clk_del_provider(dev->of_node);
191
192 return 0;
193}
194EXPORT_SYMBOL_GPL(max_gen_clk_remove);
diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h
deleted file mode 100644
index 997e86fc3f4d..000000000000
--- a/drivers/clk/clk-max-gen.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __CLK_MAX_GEN_H__
19#define __CLK_MAX_GEN_H__
20
21#include <linux/types.h>
22#include <linux/device.h>
23#include <linux/clkdev.h>
24#include <linux/regmap.h>
25#include <linux/platform_device.h>
26
27int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
28 u32 reg, struct clk_init_data *clks_init, int num_init);
29int max_gen_clk_remove(struct platform_device *pdev, int num_init);
30extern struct clk_ops max_gen_clk_ops;
31
32#endif /* __CLK_MAX_GEN_H__ */
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index 9b6f2772e948..9aba3a8245e1 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * clk-max77686.c - Clock driver for Maxim 77686 2 * clk-max77686.c - Clock driver for Maxim 77686/MAX77802
3 * 3 *
4 * Copyright (C) 2012 Samsung Electornics 4 * Copyright (C) 2012 Samsung Electornics
5 * Jonghwa Lee <jonghwa3.lee@samsung.com> 5 * Jonghwa Lee <jonghwa3.lee@samsung.com>
@@ -30,41 +30,261 @@
30#include <linux/clk-provider.h> 30#include <linux/clk-provider.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/clkdev.h> 32#include <linux/clkdev.h>
33#include <linux/of.h>
34#include <linux/regmap.h>
33 35
34#include <dt-bindings/clock/maxim,max77686.h> 36#include <dt-bindings/clock/maxim,max77686.h>
35#include "clk-max-gen.h" 37#include <dt-bindings/clock/maxim,max77802.h>
36 38
37static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { 39#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
40
41enum max77686_chip_name {
42 CHIP_MAX77686,
43 CHIP_MAX77802,
44};
45
46struct max77686_hw_clk_info {
47 const char *name;
48 u32 clk_reg;
49 u32 clk_enable_mask;
50 u32 flags;
51};
52
53struct max77686_clk_init_data {
54 struct regmap *regmap;
55 struct clk_hw hw;
56 struct clk_init_data clk_idata;
57 const struct max77686_hw_clk_info *clk_info;
58};
59
60struct max77686_clk_driver_data {
61 enum max77686_chip_name chip;
62 struct clk **clks;
63 struct max77686_clk_init_data *max_clk_data;
64 struct clk_onecell_data of_data;
65};
66
67static const struct
68max77686_hw_clk_info max77686_hw_clks_info[MAX77686_CLKS_NUM] = {
38 [MAX77686_CLK_AP] = { 69 [MAX77686_CLK_AP] = {
39 .name = "32khz_ap", 70 .name = "32khz_ap",
40 .ops = &max_gen_clk_ops, 71 .clk_reg = MAX77686_REG_32KHZ,
72 .clk_enable_mask = BIT(MAX77686_CLK_AP),
41 }, 73 },
42 [MAX77686_CLK_CP] = { 74 [MAX77686_CLK_CP] = {
43 .name = "32khz_cp", 75 .name = "32khz_cp",
44 .ops = &max_gen_clk_ops, 76 .clk_reg = MAX77686_REG_32KHZ,
77 .clk_enable_mask = BIT(MAX77686_CLK_CP),
45 }, 78 },
46 [MAX77686_CLK_PMIC] = { 79 [MAX77686_CLK_PMIC] = {
47 .name = "32khz_pmic", 80 .name = "32khz_pmic",
48 .ops = &max_gen_clk_ops, 81 .clk_reg = MAX77686_REG_32KHZ,
82 .clk_enable_mask = BIT(MAX77686_CLK_PMIC),
83 },
84};
85
86static const struct
87max77686_hw_clk_info max77802_hw_clks_info[MAX77802_CLKS_NUM] = {
88 [MAX77802_CLK_32K_AP] = {
89 .name = "32khz_ap",
90 .clk_reg = MAX77802_REG_32KHZ,
91 .clk_enable_mask = BIT(MAX77802_CLK_32K_AP),
92 },
93 [MAX77802_CLK_32K_CP] = {
94 .name = "32khz_cp",
95 .clk_reg = MAX77802_REG_32KHZ,
96 .clk_enable_mask = BIT(MAX77802_CLK_32K_CP),
49 }, 97 },
50}; 98};
51 99
100static struct max77686_clk_init_data *to_max77686_clk_init_data(
101 struct clk_hw *hw)
102{
103 return container_of(hw, struct max77686_clk_init_data, hw);
104}
105
106static int max77686_clk_prepare(struct clk_hw *hw)
107{
108 struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
109
110 return regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg,
111 max77686->clk_info->clk_enable_mask,
112 max77686->clk_info->clk_enable_mask);
113}
114
115static void max77686_clk_unprepare(struct clk_hw *hw)
116{
117 struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
118
119 regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg,
120 max77686->clk_info->clk_enable_mask,
121 ~max77686->clk_info->clk_enable_mask);
122}
123
124static int max77686_clk_is_prepared(struct clk_hw *hw)
125{
126 struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
127 int ret;
128 u32 val;
129
130 ret = regmap_read(max77686->regmap, max77686->clk_info->clk_reg, &val);
131
132 if (ret < 0)
133 return -EINVAL;
134
135 return val & max77686->clk_info->clk_enable_mask;
136}
137
138static unsigned long max77686_recalc_rate(struct clk_hw *hw,
139 unsigned long parent_rate)
140{
141 return 32768;
142}
143
144static struct clk_ops max77686_clk_ops = {
145 .prepare = max77686_clk_prepare,
146 .unprepare = max77686_clk_unprepare,
147 .is_prepared = max77686_clk_is_prepared,
148 .recalc_rate = max77686_recalc_rate,
149};
150
52static int max77686_clk_probe(struct platform_device *pdev) 151static int max77686_clk_probe(struct platform_device *pdev)
53{ 152{
54 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 153 struct device *dev = &pdev->dev;
154 struct device *parent = dev->parent;
155 const struct platform_device_id *id = platform_get_device_id(pdev);
156 struct max77686_clk_driver_data *drv_data;
157 const struct max77686_hw_clk_info *hw_clks;
158 struct regmap *regmap;
159 int i, ret, num_clks;
160
161 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
162 if (!drv_data)
163 return -ENOMEM;
164
165 regmap = dev_get_regmap(parent, NULL);
166 if (!regmap) {
167 dev_err(dev, "Failed to get rtc regmap\n");
168 return -ENODEV;
169 }
170
171 drv_data->chip = id->driver_data;
172
173 switch (drv_data->chip) {
174 case CHIP_MAX77686:
175 num_clks = MAX77686_CLKS_NUM;
176 hw_clks = max77686_hw_clks_info;
177 break;
178
179 case CHIP_MAX77802:
180 num_clks = MAX77802_CLKS_NUM;
181 hw_clks = max77802_hw_clks_info;
182 break;
183
184 default:
185 dev_err(dev, "Unknown Chip ID\n");
186 return -EINVAL;
187 }
188
189 drv_data->max_clk_data = devm_kcalloc(dev, num_clks,
190 sizeof(*drv_data->max_clk_data),
191 GFP_KERNEL);
192 if (!drv_data->max_clk_data)
193 return -ENOMEM;
194
195 drv_data->clks = devm_kcalloc(dev, num_clks,
196 sizeof(*drv_data->clks), GFP_KERNEL);
197 if (!drv_data->clks)
198 return -ENOMEM;
55 199
56 return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ, 200 for (i = 0; i < num_clks; i++) {
57 max77686_clks_init, MAX77686_CLKS_NUM); 201 struct max77686_clk_init_data *max_clk_data;
202 struct clk *clk;
203 const char *clk_name;
204
205 max_clk_data = &drv_data->max_clk_data[i];
206
207 max_clk_data->regmap = regmap;
208 max_clk_data->clk_info = &hw_clks[i];
209 max_clk_data->clk_idata.flags = hw_clks[i].flags;
210 max_clk_data->clk_idata.ops = &max77686_clk_ops;
211
212 if (parent->of_node &&
213 !of_property_read_string_index(parent->of_node,
214 "clock-output-names",
215 i, &clk_name))
216 max_clk_data->clk_idata.name = clk_name;
217 else
218 max_clk_data->clk_idata.name = hw_clks[i].name;
219
220 max_clk_data->hw.init = &max_clk_data->clk_idata;
221
222 clk = devm_clk_register(dev, &max_clk_data->hw);
223 if (IS_ERR(clk)) {
224 ret = PTR_ERR(clk);
225 dev_err(dev, "Failed to clock register: %d\n", ret);
226 return ret;
227 }
228
229 ret = clk_register_clkdev(clk, max_clk_data->clk_idata.name,
230 NULL);
231 if (ret < 0) {
232 dev_err(dev, "Failed to clkdev register: %d\n", ret);
233 return ret;
234 }
235 drv_data->clks[i] = clk;
236 }
237
238 platform_set_drvdata(pdev, drv_data);
239
240 if (parent->of_node) {
241 drv_data->of_data.clks = drv_data->clks;
242 drv_data->of_data.clk_num = num_clks;
243 ret = of_clk_add_provider(parent->of_node,
244 of_clk_src_onecell_get,
245 &drv_data->of_data);
246
247 if (ret < 0) {
248 dev_err(dev, "Failed to register OF clock provider: %d\n",
249 ret);
250 return ret;
251 }
252 }
253
254 /* MAX77802: Enable low-jitter mode on the 32khz clocks. */
255 if (drv_data->chip == CHIP_MAX77802) {
256 ret = regmap_update_bits(regmap, MAX77802_REG_32KHZ,
257 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT,
258 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
259 if (ret < 0) {
260 dev_err(dev, "Failed to config low-jitter: %d\n", ret);
261 goto remove_of_clk_provider;
262 }
263 }
264
265 return 0;
266
267remove_of_clk_provider:
268 if (parent->of_node)
269 of_clk_del_provider(parent->of_node);
270
271 return ret;
58} 272}
59 273
60static int max77686_clk_remove(struct platform_device *pdev) 274static int max77686_clk_remove(struct platform_device *pdev)
61{ 275{
62 return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM); 276 struct device *parent = pdev->dev.parent;
277
278 if (parent->of_node)
279 of_clk_del_provider(parent->of_node);
280
281 return 0;
63} 282}
64 283
65static const struct platform_device_id max77686_clk_id[] = { 284static const struct platform_device_id max77686_clk_id[] = {
66 { "max77686-clk", 0}, 285 { "max77686-clk", .driver_data = CHIP_MAX77686, },
67 { }, 286 { "max77802-clk", .driver_data = CHIP_MAX77802, },
287 {},
68}; 288};
69MODULE_DEVICE_TABLE(platform, max77686_clk_id); 289MODULE_DEVICE_TABLE(platform, max77686_clk_id);
70 290
diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c
deleted file mode 100644
index 355dd2e522c3..000000000000
--- a/drivers/clk/clk-max77802.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 * clk-max77802.c - Clock driver for Maxim 77802
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 */
21
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/err.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/mfd/max77686-private.h>
28#include <linux/clk-provider.h>
29#include <linux/mutex.h>
30#include <linux/clkdev.h>
31
32#include <dt-bindings/clock/maxim,max77802.h>
33#include "clk-max-gen.h"
34
35#define MAX77802_CLOCK_OPMODE_MASK 0x1
36#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
37
38static struct clk_init_data max77802_clks_init[MAX77802_CLKS_NUM] = {
39 [MAX77802_CLK_32K_AP] = {
40 .name = "32khz_ap",
41 .ops = &max_gen_clk_ops,
42 },
43 [MAX77802_CLK_32K_CP] = {
44 .name = "32khz_cp",
45 .ops = &max_gen_clk_ops,
46 },
47};
48
49static int max77802_clk_probe(struct platform_device *pdev)
50{
51 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
52 int ret;
53
54 ret = max_gen_clk_probe(pdev, iodev->regmap, MAX77802_REG_32KHZ,
55 max77802_clks_init, MAX77802_CLKS_NUM);
56
57 if (ret) {
58 dev_err(&pdev->dev, "generic probe failed %d\n", ret);
59 return ret;
60 }
61
62 /* Enable low-jitter mode on the 32khz clocks. */
63 ret = regmap_update_bits(iodev->regmap, MAX77802_REG_32KHZ,
64 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT,
65 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
66 if (ret < 0)
67 dev_err(&pdev->dev, "failed to enable low-jitter mode\n");
68
69 return ret;
70}
71
72static int max77802_clk_remove(struct platform_device *pdev)
73{
74 return max_gen_clk_remove(pdev, MAX77802_CLKS_NUM);
75}
76
77static const struct platform_device_id max77802_clk_id[] = {
78 { "max77802-clk", 0},
79 { },
80};
81MODULE_DEVICE_TABLE(platform, max77802_clk_id);
82
83static struct platform_driver max77802_clk_driver = {
84 .driver = {
85 .name = "max77802-clk",
86 },
87 .probe = max77802_clk_probe,
88 .remove = max77802_clk_remove,
89 .id_table = max77802_clk_id,
90};
91
92module_platform_driver(max77802_clk_driver);
93
94MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
95MODULE_AUTHOR("Javier Martinez Canillas <javier@osg.samsung.com");
96MODULE_LICENSE("GPL");