xref: /linux/drivers/clk/clk-max77686.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
1 /*
2  * clk-max77686.c - Clock driver for Maxim 77686/MAX77802
3  *
4  * Copyright (C) 2012 Samsung Electornics
5  * Jonghwa Lee <jonghwa3.lee@samsung.com>
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22 
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>
34 #include <linux/of.h>
35 #include <linux/regmap.h>
36 
37 #include <dt-bindings/clock/maxim,max77686.h>
38 #include <dt-bindings/clock/maxim,max77802.h>
39 #include <dt-bindings/clock/maxim,max77620.h>
40 
41 #define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
42 
43 enum max77686_chip_name {
44 	CHIP_MAX77686,
45 	CHIP_MAX77802,
46 	CHIP_MAX77620,
47 };
48 
49 struct max77686_hw_clk_info {
50 	const char *name;
51 	u32 clk_reg;
52 	u32 clk_enable_mask;
53 	u32 flags;
54 };
55 
56 struct max77686_clk_init_data {
57 	struct regmap *regmap;
58 	struct clk_hw hw;
59 	struct clk_init_data clk_idata;
60 	const struct max77686_hw_clk_info *clk_info;
61 };
62 
63 struct max77686_clk_driver_data {
64 	enum max77686_chip_name chip;
65 	struct max77686_clk_init_data *max_clk_data;
66 	size_t num_clks;
67 };
68 
69 static const struct
70 max77686_hw_clk_info max77686_hw_clks_info[MAX77686_CLKS_NUM] = {
71 	[MAX77686_CLK_AP] = {
72 		.name = "32khz_ap",
73 		.clk_reg = MAX77686_REG_32KHZ,
74 		.clk_enable_mask = BIT(MAX77686_CLK_AP),
75 	},
76 	[MAX77686_CLK_CP] = {
77 		.name = "32khz_cp",
78 		.clk_reg = MAX77686_REG_32KHZ,
79 		.clk_enable_mask = BIT(MAX77686_CLK_CP),
80 	},
81 	[MAX77686_CLK_PMIC] = {
82 		.name = "32khz_pmic",
83 		.clk_reg = MAX77686_REG_32KHZ,
84 		.clk_enable_mask = BIT(MAX77686_CLK_PMIC),
85 	},
86 };
87 
88 static const struct
89 max77686_hw_clk_info max77802_hw_clks_info[MAX77802_CLKS_NUM] = {
90 	[MAX77802_CLK_32K_AP] = {
91 		.name = "32khz_ap",
92 		.clk_reg = MAX77802_REG_32KHZ,
93 		.clk_enable_mask = BIT(MAX77802_CLK_32K_AP),
94 	},
95 	[MAX77802_CLK_32K_CP] = {
96 		.name = "32khz_cp",
97 		.clk_reg = MAX77802_REG_32KHZ,
98 		.clk_enable_mask = BIT(MAX77802_CLK_32K_CP),
99 	},
100 };
101 
102 static const struct
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,
108 	},
109 };
110 
111 static struct max77686_clk_init_data *to_max77686_clk_init_data(
112 				struct clk_hw *hw)
113 {
114 	return container_of(hw, struct max77686_clk_init_data, hw);
115 }
116 
117 static int max77686_clk_prepare(struct clk_hw *hw)
118 {
119 	struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
120 
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);
124 }
125 
126 static void max77686_clk_unprepare(struct clk_hw *hw)
127 {
128 	struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
129 
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);
133 }
134 
135 static int max77686_clk_is_prepared(struct clk_hw *hw)
136 {
137 	struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw);
138 	int ret;
139 	u32 val;
140 
141 	ret = regmap_read(max77686->regmap, max77686->clk_info->clk_reg, &val);
142 
143 	if (ret < 0)
144 		return -EINVAL;
145 
146 	return val & max77686->clk_info->clk_enable_mask;
147 }
148 
149 static unsigned long max77686_recalc_rate(struct clk_hw *hw,
150 					  unsigned long parent_rate)
151 {
152 	return 32768;
153 }
154 
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,
160 };
161 
162 static struct clk_hw *
163 of_clk_max77686_get(struct of_phandle_args *clkspec, void *data)
164 {
165 	struct max77686_clk_driver_data *drv_data = data;
166 	unsigned int idx = clkspec->args[0];
167 
168 	if (idx >= drv_data->num_clks) {
169 		pr_err("%s: invalid index %u\n", __func__, idx);
170 		return ERR_PTR(-EINVAL);
171 	}
172 
173 	return &drv_data->max_clk_data[idx].hw;
174 }
175 
176 static int max77686_clk_probe(struct platform_device *pdev)
177 {
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;
185 
186 	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
187 	if (!drv_data)
188 		return -ENOMEM;
189 
190 	regmap = dev_get_regmap(parent, NULL);
191 	if (!regmap) {
192 		dev_err(dev, "Failed to get rtc regmap\n");
193 		return -ENODEV;
194 	}
195 
196 	drv_data->chip = id->driver_data;
197 
198 	switch (drv_data->chip) {
199 	case CHIP_MAX77686:
200 		num_clks = MAX77686_CLKS_NUM;
201 		hw_clks = max77686_hw_clks_info;
202 		break;
203 
204 	case CHIP_MAX77802:
205 		num_clks = MAX77802_CLKS_NUM;
206 		hw_clks = max77802_hw_clks_info;
207 		break;
208 
209 	case CHIP_MAX77620:
210 		num_clks = MAX77620_CLKS_NUM;
211 		hw_clks = max77620_hw_clks_info;
212 		break;
213 
214 	default:
215 		dev_err(dev, "Unknown Chip ID\n");
216 		return -EINVAL;
217 	}
218 
219 	drv_data->num_clks = num_clks;
220 	drv_data->max_clk_data = devm_kcalloc(dev, num_clks,
221 					      sizeof(*drv_data->max_clk_data),
222 					      GFP_KERNEL);
223 	if (!drv_data->max_clk_data)
224 		return -ENOMEM;
225 
226 	for (i = 0; i < num_clks; i++) {
227 		struct max77686_clk_init_data *max_clk_data;
228 		const char *clk_name;
229 
230 		max_clk_data = &drv_data->max_clk_data[i];
231 
232 		max_clk_data->regmap = regmap;
233 		max_clk_data->clk_info = &hw_clks[i];
234 		max_clk_data->clk_idata.flags = hw_clks[i].flags;
235 		max_clk_data->clk_idata.ops = &max77686_clk_ops;
236 
237 		if (parent->of_node &&
238 		    !of_property_read_string_index(parent->of_node,
239 						   "clock-output-names",
240 						   i, &clk_name))
241 			max_clk_data->clk_idata.name = clk_name;
242 		else
243 			max_clk_data->clk_idata.name = hw_clks[i].name;
244 
245 		max_clk_data->hw.init = &max_clk_data->clk_idata;
246 
247 		ret = devm_clk_hw_register(dev, &max_clk_data->hw);
248 		if (ret) {
249 			dev_err(dev, "Failed to clock register: %d\n", ret);
250 			return ret;
251 		}
252 
253 		ret = clk_hw_register_clkdev(&max_clk_data->hw,
254 					     max_clk_data->clk_idata.name, NULL);
255 		if (ret < 0) {
256 			dev_err(dev, "Failed to clkdev register: %d\n", ret);
257 			return ret;
258 		}
259 	}
260 
261 	if (parent->of_node) {
262 		ret = of_clk_add_hw_provider(parent->of_node, of_clk_max77686_get,
263 					     drv_data);
264 
265 		if (ret < 0) {
266 			dev_err(dev, "Failed to register OF clock provider: %d\n",
267 				ret);
268 			return ret;
269 		}
270 	}
271 
272 	/* MAX77802: Enable low-jitter mode on the 32khz clocks. */
273 	if (drv_data->chip == CHIP_MAX77802) {
274 		ret = regmap_update_bits(regmap, MAX77802_REG_32KHZ,
275 					 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT,
276 					 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
277 		if (ret < 0) {
278 			dev_err(dev, "Failed to config low-jitter: %d\n", ret);
279 			goto remove_of_clk_provider;
280 		}
281 	}
282 
283 	return 0;
284 
285 remove_of_clk_provider:
286 	if (parent->of_node)
287 		of_clk_del_provider(parent->of_node);
288 
289 	return ret;
290 }
291 
292 static int max77686_clk_remove(struct platform_device *pdev)
293 {
294 	struct device *parent = pdev->dev.parent;
295 
296 	if (parent->of_node)
297 		of_clk_del_provider(parent->of_node);
298 
299 	return 0;
300 }
301 
302 static const struct platform_device_id max77686_clk_id[] = {
303 	{ "max77686-clk", .driver_data = CHIP_MAX77686, },
304 	{ "max77802-clk", .driver_data = CHIP_MAX77802, },
305 	{ "max77620-clock", .driver_data = CHIP_MAX77620, },
306 	{},
307 };
308 MODULE_DEVICE_TABLE(platform, max77686_clk_id);
309 
310 static struct platform_driver max77686_clk_driver = {
311 	.driver = {
312 		.name  = "max77686-clk",
313 	},
314 	.probe = max77686_clk_probe,
315 	.remove = max77686_clk_remove,
316 	.id_table = max77686_clk_id,
317 };
318 
319 module_platform_driver(max77686_clk_driver);
320 
321 MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
322 MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
323 MODULE_LICENSE("GPL");
324