brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 826b3ff Raw
249 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2017 NXP4 *5 * Dong Aisheng <aisheng.dong@nxp.com>6 */7 8#include <linux/clk.h>9#include <linux/clk-provider.h>10#include <linux/device.h>11#include <linux/export.h>12#include <linux/of.h>13#include <linux/slab.h>14 15static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,16					struct clk_bulk_data *clks)17{18	int ret;19	int i;20 21	for (i = 0; i < num_clks; i++) {22		clks[i].id = NULL;23		clks[i].clk = NULL;24	}25 26	for (i = 0; i < num_clks; i++) {27		of_property_read_string_index(np, "clock-names", i, &clks[i].id);28		clks[i].clk = of_clk_get(np, i);29		if (IS_ERR(clks[i].clk)) {30			ret = PTR_ERR(clks[i].clk);31			pr_err("%pOF: Failed to get clk index: %d ret: %d\n",32			       np, i, ret);33			clks[i].clk = NULL;34			goto err;35		}36	}37 38	return 0;39 40err:41	clk_bulk_put(i, clks);42 43	return ret;44}45 46static int __must_check of_clk_bulk_get_all(struct device_node *np,47					    struct clk_bulk_data **clks)48{49	struct clk_bulk_data *clk_bulk;50	int num_clks;51	int ret;52 53	num_clks = of_clk_get_parent_count(np);54	if (!num_clks)55		return 0;56 57	clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);58	if (!clk_bulk)59		return -ENOMEM;60 61	ret = of_clk_bulk_get(np, num_clks, clk_bulk);62	if (ret) {63		kfree(clk_bulk);64		return ret;65	}66 67	*clks = clk_bulk;68 69	return num_clks;70}71 72void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)73{74	while (--num_clks >= 0) {75		clk_put(clks[num_clks].clk);76		clks[num_clks].clk = NULL;77	}78}79EXPORT_SYMBOL_GPL(clk_bulk_put);80 81static int __clk_bulk_get(struct device *dev, int num_clks,82			  struct clk_bulk_data *clks, bool optional)83{84	int ret;85	int i;86 87	for (i = 0; i < num_clks; i++)88		clks[i].clk = NULL;89 90	for (i = 0; i < num_clks; i++) {91		clks[i].clk = clk_get(dev, clks[i].id);92		if (IS_ERR(clks[i].clk)) {93			ret = PTR_ERR(clks[i].clk);94			clks[i].clk = NULL;95 96			if (ret == -ENOENT && optional)97				continue;98 99			dev_err_probe(dev, ret,100				      "Failed to get clk '%s'\n",101				      clks[i].id);102			goto err;103		}104	}105 106	return 0;107 108err:109	clk_bulk_put(i, clks);110 111	return ret;112}113 114int __must_check clk_bulk_get(struct device *dev, int num_clks,115			      struct clk_bulk_data *clks)116{117	return __clk_bulk_get(dev, num_clks, clks, false);118}119EXPORT_SYMBOL(clk_bulk_get);120 121int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,122				       struct clk_bulk_data *clks)123{124	return __clk_bulk_get(dev, num_clks, clks, true);125}126EXPORT_SYMBOL_GPL(clk_bulk_get_optional);127 128void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)129{130	if (IS_ERR_OR_NULL(clks))131		return;132 133	clk_bulk_put(num_clks, clks);134 135	kfree(clks);136}137EXPORT_SYMBOL(clk_bulk_put_all);138 139int __must_check clk_bulk_get_all(struct device *dev,140				  struct clk_bulk_data **clks)141{142	struct device_node *np = dev_of_node(dev);143 144	if (!np)145		return 0;146 147	return of_clk_bulk_get_all(np, clks);148}149EXPORT_SYMBOL(clk_bulk_get_all);150 151#ifdef CONFIG_HAVE_CLK_PREPARE152 153/**154 * clk_bulk_unprepare - undo preparation of a set of clock sources155 * @num_clks: the number of clk_bulk_data156 * @clks: the clk_bulk_data table being unprepared157 *158 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.159 * Returns 0 on success, -EERROR otherwise.160 */161void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)162{163	while (--num_clks >= 0)164		clk_unprepare(clks[num_clks].clk);165}166EXPORT_SYMBOL_GPL(clk_bulk_unprepare);167 168/**169 * clk_bulk_prepare - prepare a set of clocks170 * @num_clks: the number of clk_bulk_data171 * @clks: the clk_bulk_data table being prepared172 *173 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.174 * Returns 0 on success, -EERROR otherwise.175 */176int __must_check clk_bulk_prepare(int num_clks,177				  const struct clk_bulk_data *clks)178{179	int ret;180	int i;181 182	for (i = 0; i < num_clks; i++) {183		ret = clk_prepare(clks[i].clk);184		if (ret) {185			pr_err("Failed to prepare clk '%s': %d\n",186				clks[i].id, ret);187			goto err;188		}189	}190 191	return 0;192 193err:194	clk_bulk_unprepare(i, clks);195 196	return  ret;197}198EXPORT_SYMBOL_GPL(clk_bulk_prepare);199 200#endif /* CONFIG_HAVE_CLK_PREPARE */201 202/**203 * clk_bulk_disable - gate a set of clocks204 * @num_clks: the number of clk_bulk_data205 * @clks: the clk_bulk_data table being gated206 *207 * clk_bulk_disable must not sleep, which differentiates it from208 * clk_bulk_unprepare. clk_bulk_disable must be called before209 * clk_bulk_unprepare.210 */211void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)212{213 214	while (--num_clks >= 0)215		clk_disable(clks[num_clks].clk);216}217EXPORT_SYMBOL_GPL(clk_bulk_disable);218 219/**220 * clk_bulk_enable - ungate a set of clocks221 * @num_clks: the number of clk_bulk_data222 * @clks: the clk_bulk_data table being ungated223 *224 * clk_bulk_enable must not sleep225 * Returns 0 on success, -EERROR otherwise.226 */227int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)228{229	int ret;230	int i;231 232	for (i = 0; i < num_clks; i++) {233		ret = clk_enable(clks[i].clk);234		if (ret) {235			pr_err("Failed to enable clk '%s': %d\n",236				clks[i].id, ret);237			goto err;238		}239	}240 241	return 0;242 243err:244	clk_bulk_disable(i, clks);245 246	return  ret;247}248EXPORT_SYMBOL_GPL(clk_bulk_enable);249