1 /* 2 * Copyright 2017 NXP 3 * 4 * Dong Aisheng <aisheng.dong@nxp.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <linux/clk.h> 20 #include <linux/device.h> 21 #include <linux/export.h> 22 23 void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) 24 { 25 while (--num_clks >= 0) { 26 clk_put(clks[num_clks].clk); 27 clks[num_clks].clk = NULL; 28 } 29 } 30 EXPORT_SYMBOL_GPL(clk_bulk_put); 31 32 int __must_check clk_bulk_get(struct device *dev, int num_clks, 33 struct clk_bulk_data *clks) 34 { 35 int ret; 36 int i; 37 38 for (i = 0; i < num_clks; i++) 39 clks[i].clk = NULL; 40 41 for (i = 0; i < num_clks; i++) { 42 clks[i].clk = clk_get(dev, clks[i].id); 43 if (IS_ERR(clks[i].clk)) { 44 ret = PTR_ERR(clks[i].clk); 45 if (ret != -EPROBE_DEFER) 46 dev_err(dev, "Failed to get clk '%s': %d\n", 47 clks[i].id, ret); 48 clks[i].clk = NULL; 49 goto err; 50 } 51 } 52 53 return 0; 54 55 err: 56 clk_bulk_put(i, clks); 57 58 return ret; 59 } 60 EXPORT_SYMBOL(clk_bulk_get); 61 62 #ifdef CONFIG_HAVE_CLK_PREPARE 63 64 /** 65 * clk_bulk_unprepare - undo preparation of a set of clock sources 66 * @num_clks: the number of clk_bulk_data 67 * @clks: the clk_bulk_data table being unprepared 68 * 69 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable. 70 * Returns 0 on success, -EERROR otherwise. 71 */ 72 void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks) 73 { 74 while (--num_clks >= 0) 75 clk_unprepare(clks[num_clks].clk); 76 } 77 EXPORT_SYMBOL_GPL(clk_bulk_unprepare); 78 79 /** 80 * clk_bulk_prepare - prepare a set of clocks 81 * @num_clks: the number of clk_bulk_data 82 * @clks: the clk_bulk_data table being prepared 83 * 84 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable. 85 * Returns 0 on success, -EERROR otherwise. 86 */ 87 int __must_check clk_bulk_prepare(int num_clks, 88 const struct clk_bulk_data *clks) 89 { 90 int ret; 91 int i; 92 93 for (i = 0; i < num_clks; i++) { 94 ret = clk_prepare(clks[i].clk); 95 if (ret) { 96 pr_err("Failed to prepare clk '%s': %d\n", 97 clks[i].id, ret); 98 goto err; 99 } 100 } 101 102 return 0; 103 104 err: 105 clk_bulk_unprepare(i, clks); 106 107 return ret; 108 } 109 EXPORT_SYMBOL_GPL(clk_bulk_prepare); 110 111 #endif /* CONFIG_HAVE_CLK_PREPARE */ 112 113 /** 114 * clk_bulk_disable - gate a set of clocks 115 * @num_clks: the number of clk_bulk_data 116 * @clks: the clk_bulk_data table being gated 117 * 118 * clk_bulk_disable must not sleep, which differentiates it from 119 * clk_bulk_unprepare. clk_bulk_disable must be called before 120 * clk_bulk_unprepare. 121 */ 122 void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) 123 { 124 125 while (--num_clks >= 0) 126 clk_disable(clks[num_clks].clk); 127 } 128 EXPORT_SYMBOL_GPL(clk_bulk_disable); 129 130 /** 131 * clk_bulk_enable - ungate a set of clocks 132 * @num_clks: the number of clk_bulk_data 133 * @clks: the clk_bulk_data table being ungated 134 * 135 * clk_bulk_enable must not sleep 136 * Returns 0 on success, -EERROR otherwise. 137 */ 138 int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) 139 { 140 int ret; 141 int i; 142 143 for (i = 0; i < num_clks; i++) { 144 ret = clk_enable(clks[i].clk); 145 if (ret) { 146 pr_err("Failed to enable clk '%s': %d\n", 147 clks[i].id, ret); 148 goto err; 149 } 150 } 151 152 return 0; 153 154 err: 155 clk_bulk_disable(i, clks); 156 157 return ret; 158 } 159 EXPORT_SYMBOL_GPL(clk_bulk_enable); 160