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 dev_err(dev, "Failed to get clk '%s': %d\n", 46 clks[i].id, ret); 47 clks[i].clk = NULL; 48 goto err; 49 } 50 } 51 52 return 0; 53 54 err: 55 clk_bulk_put(i, clks); 56 57 return ret; 58 } 59 EXPORT_SYMBOL(clk_bulk_get); 60 61 #ifdef CONFIG_HAVE_CLK_PREPARE 62 63 /** 64 * clk_bulk_unprepare - undo preparation of a set of clock sources 65 * @num_clks: the number of clk_bulk_data 66 * @clks: the clk_bulk_data table being unprepared 67 * 68 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable. 69 * Returns 0 on success, -EERROR otherwise. 70 */ 71 void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks) 72 { 73 while (--num_clks >= 0) 74 clk_unprepare(clks[num_clks].clk); 75 } 76 EXPORT_SYMBOL_GPL(clk_bulk_unprepare); 77 78 /** 79 * clk_bulk_prepare - prepare a set of clocks 80 * @num_clks: the number of clk_bulk_data 81 * @clks: the clk_bulk_data table being prepared 82 * 83 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable. 84 * Returns 0 on success, -EERROR otherwise. 85 */ 86 int __must_check clk_bulk_prepare(int num_clks, 87 const struct clk_bulk_data *clks) 88 { 89 int ret; 90 int i; 91 92 for (i = 0; i < num_clks; i++) { 93 ret = clk_prepare(clks[i].clk); 94 if (ret) { 95 pr_err("Failed to prepare clk '%s': %d\n", 96 clks[i].id, ret); 97 goto err; 98 } 99 } 100 101 return 0; 102 103 err: 104 clk_bulk_unprepare(i, clks); 105 106 return ret; 107 } 108 EXPORT_SYMBOL_GPL(clk_bulk_prepare); 109 110 #endif /* CONFIG_HAVE_CLK_PREPARE */ 111 112 /** 113 * clk_bulk_disable - gate a set of clocks 114 * @num_clks: the number of clk_bulk_data 115 * @clks: the clk_bulk_data table being gated 116 * 117 * clk_bulk_disable must not sleep, which differentiates it from 118 * clk_bulk_unprepare. clk_bulk_disable must be called before 119 * clk_bulk_unprepare. 120 */ 121 void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) 122 { 123 124 while (--num_clks >= 0) 125 clk_disable(clks[num_clks].clk); 126 } 127 EXPORT_SYMBOL_GPL(clk_bulk_disable); 128 129 /** 130 * clk_bulk_enable - ungate a set of clocks 131 * @num_clks: the number of clk_bulk_data 132 * @clks: the clk_bulk_data table being ungated 133 * 134 * clk_bulk_enable must not sleep 135 * Returns 0 on success, -EERROR otherwise. 136 */ 137 int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) 138 { 139 int ret; 140 int i; 141 142 for (i = 0; i < num_clks; i++) { 143 ret = clk_enable(clks[i].clk); 144 if (ret) { 145 pr_err("Failed to enable clk '%s': %d\n", 146 clks[i].id, ret); 147 goto err; 148 } 149 } 150 151 return 0; 152 153 err: 154 clk_bulk_disable(i, clks); 155 156 return ret; 157 } 158 EXPORT_SYMBOL_GPL(clk_bulk_enable); 159