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