clk-bulk.c (5160B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2017 NXP 4 * 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 if (ret != -EPROBE_DEFER) 100 dev_err(dev, "Failed to get clk '%s': %d\n", 101 clks[i].id, ret); 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_PREPARE 152 153/** 154 * clk_bulk_unprepare - undo preparation of a set of clock sources 155 * @num_clks: the number of clk_bulk_data 156 * @clks: the clk_bulk_data table being unprepared 157 * 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 clocks 170 * @num_clks: the number of clk_bulk_data 171 * @clks: the clk_bulk_data table being prepared 172 * 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 clocks 204 * @num_clks: the number of clk_bulk_data 205 * @clks: the clk_bulk_data table being gated 206 * 207 * clk_bulk_disable must not sleep, which differentiates it from 208 * clk_bulk_unprepare. clk_bulk_disable must be called before 209 * 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 clocks 221 * @num_clks: the number of clk_bulk_data 222 * @clks: the clk_bulk_data table being ungated 223 * 224 * clk_bulk_enable must not sleep 225 * 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);