1266e4e9dSDong Aisheng /* 2266e4e9dSDong Aisheng * Copyright 2017 NXP 3266e4e9dSDong Aisheng * 4266e4e9dSDong Aisheng * Dong Aisheng <aisheng.dong@nxp.com> 5266e4e9dSDong Aisheng * 6266e4e9dSDong Aisheng * This program is free software; you can redistribute it and/or modify it 7266e4e9dSDong Aisheng * under the terms and conditions of the GNU General Public License, 8266e4e9dSDong Aisheng * version 2, as published by the Free Software Foundation. 9266e4e9dSDong Aisheng * 10266e4e9dSDong Aisheng * This program is distributed in the hope it will be useful, but WITHOUT 11266e4e9dSDong Aisheng * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12266e4e9dSDong Aisheng * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13266e4e9dSDong Aisheng * more details. 14266e4e9dSDong Aisheng * 15266e4e9dSDong Aisheng * You should have received a copy of the GNU General Public License 16266e4e9dSDong Aisheng * along with this program. If not, see <http://www.gnu.org/licenses/>. 17266e4e9dSDong Aisheng */ 18266e4e9dSDong Aisheng 19266e4e9dSDong Aisheng #include <linux/clk.h> 20266e4e9dSDong Aisheng #include <linux/device.h> 21266e4e9dSDong Aisheng #include <linux/export.h> 22*cfdc0411SDong Aisheng #include <linux/of.h> 23*cfdc0411SDong Aisheng 24*cfdc0411SDong Aisheng static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, 25*cfdc0411SDong Aisheng struct clk_bulk_data *clks) 26*cfdc0411SDong Aisheng { 27*cfdc0411SDong Aisheng int ret; 28*cfdc0411SDong Aisheng int i; 29*cfdc0411SDong Aisheng 30*cfdc0411SDong Aisheng for (i = 0; i < num_clks; i++) 31*cfdc0411SDong Aisheng clks[i].clk = NULL; 32*cfdc0411SDong Aisheng 33*cfdc0411SDong Aisheng for (i = 0; i < num_clks; i++) { 34*cfdc0411SDong Aisheng clks[i].clk = of_clk_get(np, i); 35*cfdc0411SDong Aisheng if (IS_ERR(clks[i].clk)) { 36*cfdc0411SDong Aisheng ret = PTR_ERR(clks[i].clk); 37*cfdc0411SDong Aisheng pr_err("%pOF: Failed to get clk index: %d ret: %d\n", 38*cfdc0411SDong Aisheng np, i, ret); 39*cfdc0411SDong Aisheng clks[i].clk = NULL; 40*cfdc0411SDong Aisheng goto err; 41*cfdc0411SDong Aisheng } 42*cfdc0411SDong Aisheng } 43*cfdc0411SDong Aisheng 44*cfdc0411SDong Aisheng return 0; 45*cfdc0411SDong Aisheng 46*cfdc0411SDong Aisheng err: 47*cfdc0411SDong Aisheng clk_bulk_put(i, clks); 48*cfdc0411SDong Aisheng 49*cfdc0411SDong Aisheng return ret; 50*cfdc0411SDong Aisheng } 51266e4e9dSDong Aisheng 52266e4e9dSDong Aisheng void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) 53266e4e9dSDong Aisheng { 54266e4e9dSDong Aisheng while (--num_clks >= 0) { 55266e4e9dSDong Aisheng clk_put(clks[num_clks].clk); 56266e4e9dSDong Aisheng clks[num_clks].clk = NULL; 57266e4e9dSDong Aisheng } 58266e4e9dSDong Aisheng } 59266e4e9dSDong Aisheng EXPORT_SYMBOL_GPL(clk_bulk_put); 60266e4e9dSDong Aisheng 61266e4e9dSDong Aisheng int __must_check clk_bulk_get(struct device *dev, int num_clks, 62266e4e9dSDong Aisheng struct clk_bulk_data *clks) 63266e4e9dSDong Aisheng { 64266e4e9dSDong Aisheng int ret; 65266e4e9dSDong Aisheng int i; 66266e4e9dSDong Aisheng 67266e4e9dSDong Aisheng for (i = 0; i < num_clks; i++) 68266e4e9dSDong Aisheng clks[i].clk = NULL; 69266e4e9dSDong Aisheng 70266e4e9dSDong Aisheng for (i = 0; i < num_clks; i++) { 71266e4e9dSDong Aisheng clks[i].clk = clk_get(dev, clks[i].id); 72266e4e9dSDong Aisheng if (IS_ERR(clks[i].clk)) { 73266e4e9dSDong Aisheng ret = PTR_ERR(clks[i].clk); 74329470f2SJerome Brunet if (ret != -EPROBE_DEFER) 75266e4e9dSDong Aisheng dev_err(dev, "Failed to get clk '%s': %d\n", 76266e4e9dSDong Aisheng clks[i].id, ret); 77266e4e9dSDong Aisheng clks[i].clk = NULL; 78266e4e9dSDong Aisheng goto err; 79266e4e9dSDong Aisheng } 80266e4e9dSDong Aisheng } 81266e4e9dSDong Aisheng 82266e4e9dSDong Aisheng return 0; 83266e4e9dSDong Aisheng 84266e4e9dSDong Aisheng err: 85266e4e9dSDong Aisheng clk_bulk_put(i, clks); 86266e4e9dSDong Aisheng 87266e4e9dSDong Aisheng return ret; 88266e4e9dSDong Aisheng } 89266e4e9dSDong Aisheng EXPORT_SYMBOL(clk_bulk_get); 90266e4e9dSDong Aisheng 91266e4e9dSDong Aisheng #ifdef CONFIG_HAVE_CLK_PREPARE 92266e4e9dSDong Aisheng 93266e4e9dSDong Aisheng /** 94266e4e9dSDong Aisheng * clk_bulk_unprepare - undo preparation of a set of clock sources 95266e4e9dSDong Aisheng * @num_clks: the number of clk_bulk_data 96266e4e9dSDong Aisheng * @clks: the clk_bulk_data table being unprepared 97266e4e9dSDong Aisheng * 98266e4e9dSDong Aisheng * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable. 99266e4e9dSDong Aisheng * Returns 0 on success, -EERROR otherwise. 100266e4e9dSDong Aisheng */ 101266e4e9dSDong Aisheng void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks) 102266e4e9dSDong Aisheng { 103266e4e9dSDong Aisheng while (--num_clks >= 0) 104266e4e9dSDong Aisheng clk_unprepare(clks[num_clks].clk); 105266e4e9dSDong Aisheng } 106266e4e9dSDong Aisheng EXPORT_SYMBOL_GPL(clk_bulk_unprepare); 107266e4e9dSDong Aisheng 108266e4e9dSDong Aisheng /** 109266e4e9dSDong Aisheng * clk_bulk_prepare - prepare a set of clocks 110266e4e9dSDong Aisheng * @num_clks: the number of clk_bulk_data 111266e4e9dSDong Aisheng * @clks: the clk_bulk_data table being prepared 112266e4e9dSDong Aisheng * 113266e4e9dSDong Aisheng * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable. 114266e4e9dSDong Aisheng * Returns 0 on success, -EERROR otherwise. 115266e4e9dSDong Aisheng */ 116266e4e9dSDong Aisheng int __must_check clk_bulk_prepare(int num_clks, 117266e4e9dSDong Aisheng const struct clk_bulk_data *clks) 118266e4e9dSDong Aisheng { 119266e4e9dSDong Aisheng int ret; 120266e4e9dSDong Aisheng int i; 121266e4e9dSDong Aisheng 122266e4e9dSDong Aisheng for (i = 0; i < num_clks; i++) { 123266e4e9dSDong Aisheng ret = clk_prepare(clks[i].clk); 124266e4e9dSDong Aisheng if (ret) { 125266e4e9dSDong Aisheng pr_err("Failed to prepare clk '%s': %d\n", 126266e4e9dSDong Aisheng clks[i].id, ret); 127266e4e9dSDong Aisheng goto err; 128266e4e9dSDong Aisheng } 129266e4e9dSDong Aisheng } 130266e4e9dSDong Aisheng 131266e4e9dSDong Aisheng return 0; 132266e4e9dSDong Aisheng 133266e4e9dSDong Aisheng err: 134266e4e9dSDong Aisheng clk_bulk_unprepare(i, clks); 135266e4e9dSDong Aisheng 136266e4e9dSDong Aisheng return ret; 137266e4e9dSDong Aisheng } 1389792bf5aSBjorn Andersson EXPORT_SYMBOL_GPL(clk_bulk_prepare); 139266e4e9dSDong Aisheng 140266e4e9dSDong Aisheng #endif /* CONFIG_HAVE_CLK_PREPARE */ 141266e4e9dSDong Aisheng 142266e4e9dSDong Aisheng /** 143266e4e9dSDong Aisheng * clk_bulk_disable - gate a set of clocks 144266e4e9dSDong Aisheng * @num_clks: the number of clk_bulk_data 145266e4e9dSDong Aisheng * @clks: the clk_bulk_data table being gated 146266e4e9dSDong Aisheng * 147266e4e9dSDong Aisheng * clk_bulk_disable must not sleep, which differentiates it from 148266e4e9dSDong Aisheng * clk_bulk_unprepare. clk_bulk_disable must be called before 149266e4e9dSDong Aisheng * clk_bulk_unprepare. 150266e4e9dSDong Aisheng */ 151266e4e9dSDong Aisheng void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) 152266e4e9dSDong Aisheng { 153266e4e9dSDong Aisheng 154266e4e9dSDong Aisheng while (--num_clks >= 0) 155266e4e9dSDong Aisheng clk_disable(clks[num_clks].clk); 156266e4e9dSDong Aisheng } 157266e4e9dSDong Aisheng EXPORT_SYMBOL_GPL(clk_bulk_disable); 158266e4e9dSDong Aisheng 159266e4e9dSDong Aisheng /** 160266e4e9dSDong Aisheng * clk_bulk_enable - ungate a set of clocks 161266e4e9dSDong Aisheng * @num_clks: the number of clk_bulk_data 162266e4e9dSDong Aisheng * @clks: the clk_bulk_data table being ungated 163266e4e9dSDong Aisheng * 164266e4e9dSDong Aisheng * clk_bulk_enable must not sleep 165266e4e9dSDong Aisheng * Returns 0 on success, -EERROR otherwise. 166266e4e9dSDong Aisheng */ 167266e4e9dSDong Aisheng int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) 168266e4e9dSDong Aisheng { 169266e4e9dSDong Aisheng int ret; 170266e4e9dSDong Aisheng int i; 171266e4e9dSDong Aisheng 172266e4e9dSDong Aisheng for (i = 0; i < num_clks; i++) { 173266e4e9dSDong Aisheng ret = clk_enable(clks[i].clk); 174266e4e9dSDong Aisheng if (ret) { 175266e4e9dSDong Aisheng pr_err("Failed to enable clk '%s': %d\n", 176266e4e9dSDong Aisheng clks[i].id, ret); 177266e4e9dSDong Aisheng goto err; 178266e4e9dSDong Aisheng } 179266e4e9dSDong Aisheng } 180266e4e9dSDong Aisheng 181266e4e9dSDong Aisheng return 0; 182266e4e9dSDong Aisheng 183266e4e9dSDong Aisheng err: 184266e4e9dSDong Aisheng clk_bulk_disable(i, clks); 185266e4e9dSDong Aisheng 186266e4e9dSDong Aisheng return ret; 187266e4e9dSDong Aisheng } 188266e4e9dSDong Aisheng EXPORT_SYMBOL_GPL(clk_bulk_enable); 189