2 * clk-max77686.c - Clock driver for Maxim 77686/MAX77802
4 * Copyright (C) 2012 Samsung Electornics
5 * Jonghwa Lee <jonghwa3.lee@samsung.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/kernel.h>
24 #include <linux/slab.h>
25 #include <linux/err.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/mfd/max77620.h>
29 #include <linux/mfd/max77686.h>
30 #include <linux/mfd/max77686-private.h>
31 #include <linux/clk-provider.h>
32 #include <linux/mutex.h>
33 #include <linux/clkdev.h>
35 #include <linux/regmap.h>
37 #include <dt-bindings/clock/maxim,max77686.h>
38 #include <dt-bindings/clock/maxim,max77802.h>
39 #include <dt-bindings/clock/maxim,max77620.h>
41 #define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
43 enum max77686_chip_name
{
49 struct max77686_hw_clk_info
{
56 struct max77686_clk_init_data
{
57 struct regmap
*regmap
;
59 struct clk_init_data clk_idata
;
60 const struct max77686_hw_clk_info
*clk_info
;
63 struct max77686_clk_driver_data
{
64 enum max77686_chip_name chip
;
65 struct max77686_clk_init_data
*max_clk_data
;
70 max77686_hw_clk_info max77686_hw_clks_info
[MAX77686_CLKS_NUM
] = {
73 .clk_reg
= MAX77686_REG_32KHZ
,
74 .clk_enable_mask
= BIT(MAX77686_CLK_AP
),
78 .clk_reg
= MAX77686_REG_32KHZ
,
79 .clk_enable_mask
= BIT(MAX77686_CLK_CP
),
81 [MAX77686_CLK_PMIC
] = {
83 .clk_reg
= MAX77686_REG_32KHZ
,
84 .clk_enable_mask
= BIT(MAX77686_CLK_PMIC
),
89 max77686_hw_clk_info max77802_hw_clks_info
[MAX77802_CLKS_NUM
] = {
90 [MAX77802_CLK_32K_AP
] = {
92 .clk_reg
= MAX77802_REG_32KHZ
,
93 .clk_enable_mask
= BIT(MAX77802_CLK_32K_AP
),
95 [MAX77802_CLK_32K_CP
] = {
97 .clk_reg
= MAX77802_REG_32KHZ
,
98 .clk_enable_mask
= BIT(MAX77802_CLK_32K_CP
),
103 max77686_hw_clk_info max77620_hw_clks_info
[MAX77620_CLKS_NUM
] = {
104 [MAX77620_CLK_32K_OUT0
] = {
105 .name
= "32khz_out0",
106 .clk_reg
= MAX77620_REG_CNFG1_32K
,
107 .clk_enable_mask
= MAX77620_CNFG1_32K_OUT0_EN
,
111 static struct max77686_clk_init_data
*to_max77686_clk_init_data(
114 return container_of(hw
, struct max77686_clk_init_data
, hw
);
117 static int max77686_clk_prepare(struct clk_hw
*hw
)
119 struct max77686_clk_init_data
*max77686
= to_max77686_clk_init_data(hw
);
121 return regmap_update_bits(max77686
->regmap
, max77686
->clk_info
->clk_reg
,
122 max77686
->clk_info
->clk_enable_mask
,
123 max77686
->clk_info
->clk_enable_mask
);
126 static void max77686_clk_unprepare(struct clk_hw
*hw
)
128 struct max77686_clk_init_data
*max77686
= to_max77686_clk_init_data(hw
);
130 regmap_update_bits(max77686
->regmap
, max77686
->clk_info
->clk_reg
,
131 max77686
->clk_info
->clk_enable_mask
,
132 ~max77686
->clk_info
->clk_enable_mask
);
135 static int max77686_clk_is_prepared(struct clk_hw
*hw
)
137 struct max77686_clk_init_data
*max77686
= to_max77686_clk_init_data(hw
);
141 ret
= regmap_read(max77686
->regmap
, max77686
->clk_info
->clk_reg
, &val
);
146 return val
& max77686
->clk_info
->clk_enable_mask
;
149 static unsigned long max77686_recalc_rate(struct clk_hw
*hw
,
150 unsigned long parent_rate
)
155 static struct clk_ops max77686_clk_ops
= {
156 .prepare
= max77686_clk_prepare
,
157 .unprepare
= max77686_clk_unprepare
,
158 .is_prepared
= max77686_clk_is_prepared
,
159 .recalc_rate
= max77686_recalc_rate
,
162 static struct clk_hw
*
163 of_clk_max77686_get(struct of_phandle_args
*clkspec
, void *data
)
165 struct max77686_clk_driver_data
*drv_data
= data
;
166 unsigned int idx
= clkspec
->args
[0];
168 if (idx
>= drv_data
->num_clks
) {
169 pr_err("%s: invalid index %u\n", __func__
, idx
);
170 return ERR_PTR(-EINVAL
);
173 return &drv_data
->max_clk_data
[idx
].hw
;
176 static int max77686_clk_probe(struct platform_device
*pdev
)
178 struct device
*dev
= &pdev
->dev
;
179 struct device
*parent
= dev
->parent
;
180 const struct platform_device_id
*id
= platform_get_device_id(pdev
);
181 struct max77686_clk_driver_data
*drv_data
;
182 const struct max77686_hw_clk_info
*hw_clks
;
183 struct regmap
*regmap
;
184 int i
, ret
, num_clks
;
186 drv_data
= devm_kzalloc(dev
, sizeof(*drv_data
), GFP_KERNEL
);
190 regmap
= dev_get_regmap(parent
, NULL
);
192 dev_err(dev
, "Failed to get rtc regmap\n");
196 drv_data
->chip
= id
->driver_data
;
198 switch (drv_data
->chip
) {
200 num_clks
= MAX77686_CLKS_NUM
;
201 hw_clks
= max77686_hw_clks_info
;
205 num_clks
= MAX77802_CLKS_NUM
;
206 hw_clks
= max77802_hw_clks_info
;
210 num_clks
= MAX77620_CLKS_NUM
;
211 hw_clks
= max77620_hw_clks_info
;
215 dev_err(dev
, "Unknown Chip ID\n");
219 drv_data
->max_clk_data
= devm_kcalloc(dev
, num_clks
,
220 sizeof(*drv_data
->max_clk_data
),
222 if (!drv_data
->max_clk_data
)
225 for (i
= 0; i
< num_clks
; i
++) {
226 struct max77686_clk_init_data
*max_clk_data
;
227 const char *clk_name
;
229 max_clk_data
= &drv_data
->max_clk_data
[i
];
231 max_clk_data
->regmap
= regmap
;
232 max_clk_data
->clk_info
= &hw_clks
[i
];
233 max_clk_data
->clk_idata
.flags
= hw_clks
[i
].flags
;
234 max_clk_data
->clk_idata
.ops
= &max77686_clk_ops
;
236 if (parent
->of_node
&&
237 !of_property_read_string_index(parent
->of_node
,
238 "clock-output-names",
240 max_clk_data
->clk_idata
.name
= clk_name
;
242 max_clk_data
->clk_idata
.name
= hw_clks
[i
].name
;
244 max_clk_data
->hw
.init
= &max_clk_data
->clk_idata
;
246 ret
= devm_clk_hw_register(dev
, &max_clk_data
->hw
);
248 dev_err(dev
, "Failed to clock register: %d\n", ret
);
252 ret
= clk_hw_register_clkdev(&max_clk_data
->hw
,
253 max_clk_data
->clk_idata
.name
, NULL
);
255 dev_err(dev
, "Failed to clkdev register: %d\n", ret
);
260 if (parent
->of_node
) {
261 ret
= of_clk_add_hw_provider(parent
->of_node
, of_clk_max77686_get
,
265 dev_err(dev
, "Failed to register OF clock provider: %d\n",
271 /* MAX77802: Enable low-jitter mode on the 32khz clocks. */
272 if (drv_data
->chip
== CHIP_MAX77802
) {
273 ret
= regmap_update_bits(regmap
, MAX77802_REG_32KHZ
,
274 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT
,
275 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT
);
277 dev_err(dev
, "Failed to config low-jitter: %d\n", ret
);
278 goto remove_of_clk_provider
;
284 remove_of_clk_provider
:
286 of_clk_del_provider(parent
->of_node
);
291 static int max77686_clk_remove(struct platform_device
*pdev
)
293 struct device
*parent
= pdev
->dev
.parent
;
296 of_clk_del_provider(parent
->of_node
);
301 static const struct platform_device_id max77686_clk_id
[] = {
302 { "max77686-clk", .driver_data
= CHIP_MAX77686
, },
303 { "max77802-clk", .driver_data
= CHIP_MAX77802
, },
304 { "max77620-clock", .driver_data
= CHIP_MAX77620
, },
307 MODULE_DEVICE_TABLE(platform
, max77686_clk_id
);
309 static struct platform_driver max77686_clk_driver
= {
311 .name
= "max77686-clk",
313 .probe
= max77686_clk_probe
,
314 .remove
= max77686_clk_remove
,
315 .id_table
= max77686_clk_id
,
318 module_platform_driver(max77686_clk_driver
);
320 MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
321 MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
322 MODULE_LICENSE("GPL");