summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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");