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 109 #endif /* CONFIG_HAVE_CLK_PREPARE */ 110 111 /** 112 * clk_bulk_disable - gate a set of clocks 113 * @num_clks: the number of clk_bulk_data 114 * @clks: the clk_bulk_data table being gated 115 * 116 * clk_bulk_disable must not sleep, which differentiates it from 117 * clk_bulk_unprepare. clk_bulk_disable must be called before 118 * clk_bulk_unprepare. 119 */ 120 void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) 121 { 122 123 while (--num_clks >= 0) 124 clk_disable(clks[num_clks].clk); 125 } 126 EXPORT_SYMBOL_GPL(clk_bulk_disable); 127 128 /** 129 * clk_bulk_enable - ungate a set of clocks 130 * @num_clks: the number of clk_bulk_data 131 * @clks: the clk_bulk_data table being ungated 132 * 133 * clk_bulk_enable must not sleep 134 * Returns 0 on success, -EERROR otherwise. 135 */ 136 int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) 137 { 138 int ret; 139 int i; 140 141 for (i = 0; i < num_clks; i++) { 142 ret = clk_enable(clks[i].clk); 143 if (ret) { 144 pr_err("Failed to enable clk '%s': %d\n", 145 clks[i].id, ret); 146 goto err; 147 } 148 } 149 150 return 0; 151 152 err: 153 clk_bulk_disable(i, clks); 154 155 return ret; 156 } 157 EXPORT_SYMBOL_GPL(clk_bulk_enable); 158