Branch data Line data Source code
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 : : 15 : 0 : static 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 : 0 : for (i = 0; i < num_clks; i++) { 22 : 0 : clks[i].id = NULL; 23 : 0 : clks[i].clk = NULL; 24 : : } 25 : : 26 : 0 : for (i = 0; i < num_clks; i++) { 27 : 0 : of_property_read_string_index(np, "clock-names", i, &clks[i].id); 28 : 0 : clks[i].clk = of_clk_get(np, i); 29 : 0 : if (IS_ERR(clks[i].clk)) { 30 : 0 : ret = PTR_ERR(clks[i].clk); 31 : : pr_err("%pOF: Failed to get clk index: %d ret: %d\n", 32 : : np, i, ret); 33 : 0 : clks[i].clk = NULL; 34 : : goto err; 35 : : } 36 : : } 37 : : 38 : : return 0; 39 : : 40 : : err: 41 : 0 : clk_bulk_put(i, clks); 42 : : 43 : 0 : return ret; 44 : : } 45 : : 46 : 0 : static 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 : 0 : num_clks = of_clk_get_parent_count(np); 54 : 0 : if (!num_clks) 55 : : return 0; 56 : : 57 : 0 : clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL); 58 : 0 : if (!clk_bulk) 59 : : return -ENOMEM; 60 : : 61 : 0 : ret = of_clk_bulk_get(np, num_clks, clk_bulk); 62 : 0 : if (ret) { 63 : 0 : kfree(clk_bulk); 64 : 0 : return ret; 65 : : } 66 : : 67 : 0 : *clks = clk_bulk; 68 : : 69 : 0 : return num_clks; 70 : : } 71 : : 72 : 0 : void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) 73 : : { 74 : 0 : while (--num_clks >= 0) { 75 : 0 : clk_put(clks[num_clks].clk); 76 : 0 : clks[num_clks].clk = NULL; 77 : : } 78 : 0 : } 79 : : EXPORT_SYMBOL_GPL(clk_bulk_put); 80 : : 81 : 0 : static 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 : 0 : for (i = 0; i < num_clks; i++) 88 : 0 : clks[i].clk = NULL; 89 : : 90 : 0 : for (i = 0; i < num_clks; i++) { 91 : 0 : clks[i].clk = clk_get(dev, clks[i].id); 92 : 0 : if (IS_ERR(clks[i].clk)) { 93 : : ret = PTR_ERR(clks[i].clk); 94 : 0 : clks[i].clk = NULL; 95 : : 96 : 0 : if (ret == -ENOENT && optional) 97 : 0 : continue; 98 : : 99 : 0 : if (ret != -EPROBE_DEFER) 100 : 0 : 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 : : 108 : : err: 109 : 0 : clk_bulk_put(i, clks); 110 : : 111 : 0 : return ret; 112 : : } 113 : : 114 : 0 : int __must_check clk_bulk_get(struct device *dev, int num_clks, 115 : : struct clk_bulk_data *clks) 116 : : { 117 : 0 : return __clk_bulk_get(dev, num_clks, clks, false); 118 : : } 119 : : EXPORT_SYMBOL(clk_bulk_get); 120 : : 121 : 0 : int __must_check clk_bulk_get_optional(struct device *dev, int num_clks, 122 : : struct clk_bulk_data *clks) 123 : : { 124 : 0 : return __clk_bulk_get(dev, num_clks, clks, true); 125 : : } 126 : : EXPORT_SYMBOL_GPL(clk_bulk_get_optional); 127 : : 128 : 0 : void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) 129 : : { 130 : 0 : if (IS_ERR_OR_NULL(clks)) 131 : 0 : return; 132 : : 133 : 0 : clk_bulk_put(num_clks, clks); 134 : : 135 : 0 : kfree(clks); 136 : : } 137 : : EXPORT_SYMBOL(clk_bulk_put_all); 138 : : 139 : 0 : int __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 : 0 : if (!np) 145 : : return 0; 146 : : 147 : 0 : return of_clk_bulk_get_all(np, clks); 148 : : } 149 : : EXPORT_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 : : */ 161 : 0 : void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks) 162 : : { 163 : 0 : while (--num_clks >= 0) 164 : 0 : clk_unprepare(clks[num_clks].clk); 165 : 0 : } 166 : : EXPORT_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 : : */ 176 : 0 : int __must_check clk_bulk_prepare(int num_clks, 177 : : const struct clk_bulk_data *clks) 178 : : { 179 : : int ret; 180 : : int i; 181 : : 182 : 0 : for (i = 0; i < num_clks; i++) { 183 : 0 : ret = clk_prepare(clks[i].clk); 184 : 0 : if (ret) { 185 : 0 : pr_err("Failed to prepare clk '%s': %d\n", 186 : : clks[i].id, ret); 187 : : goto err; 188 : : } 189 : : } 190 : : 191 : : return 0; 192 : : 193 : : err: 194 : : clk_bulk_unprepare(i, clks); 195 : : 196 : 0 : return ret; 197 : : } 198 : : EXPORT_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 : : */ 211 : 0 : void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) 212 : : { 213 : : 214 : 0 : while (--num_clks >= 0) 215 : 0 : clk_disable(clks[num_clks].clk); 216 : 0 : } 217 : : EXPORT_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 : : */ 227 : 0 : int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) 228 : : { 229 : : int ret; 230 : : int i; 231 : : 232 : 0 : for (i = 0; i < num_clks; i++) { 233 : 0 : ret = clk_enable(clks[i].clk); 234 : 0 : if (ret) { 235 : 0 : pr_err("Failed to enable clk '%s': %d\n", 236 : : clks[i].id, ret); 237 : : goto err; 238 : : } 239 : : } 240 : : 241 : : return 0; 242 : : 243 : : err: 244 : : clk_bulk_disable(i, clks); 245 : : 246 : 0 : return ret; 247 : : } 248 : : EXPORT_SYMBOL_GPL(clk_bulk_enable);