linux/drivers/clk/clk-bulk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2017 NXP
   4 *
   5 * Dong Aisheng <aisheng.dong@nxp.com>
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/clk-provider.h>
  10#include <linux/device.h>
  11#include <linux/export.h>
  12#include <linux/of.h>
  13#include <linux/slab.h>
  14
  15static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
  16                                        struct clk_bulk_data *clks)
  17{
  18        int ret;
  19        int i;
  20
  21        for (i = 0; i < num_clks; i++) {
  22                clks[i].id = NULL;
  23                clks[i].clk = NULL;
  24        }
  25
  26        for (i = 0; i < num_clks; i++) {
  27                of_property_read_string_index(np, "clock-names", i, &clks[i].id);
  28                clks[i].clk = of_clk_get(np, i);
  29                if (IS_ERR(clks[i].clk)) {
  30                        ret = PTR_ERR(clks[i].clk);
  31                        pr_err("%pOF: Failed to get clk index: %d ret: %d\n",
  32                               np, i, ret);
  33                        clks[i].clk = NULL;
  34                        goto err;
  35                }
  36        }
  37
  38        return 0;
  39
  40err:
  41        clk_bulk_put(i, clks);
  42
  43        return ret;
  44}
  45
  46static int __must_check of_clk_bulk_get_all(struct device_node *np,
  47                                            struct clk_bulk_data **clks)
  48{
  49        struct clk_bulk_data *clk_bulk;
  50        int num_clks;
  51        int ret;
  52
  53        num_clks = of_clk_get_parent_count(np);
  54        if (!num_clks)
  55                return 0;
  56
  57        clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
  58        if (!clk_bulk)
  59                return -ENOMEM;
  60
  61        ret = of_clk_bulk_get(np, num_clks, clk_bulk);
  62        if (ret) {
  63                kfree(clk_bulk);
  64                return ret;
  65        }
  66
  67        *clks = clk_bulk;
  68
  69        return num_clks;
  70}
  71
  72void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
  73{
  74        while (--num_clks >= 0) {
  75                clk_put(clks[num_clks].clk);
  76                clks[num_clks].clk = NULL;
  77        }
  78}
  79EXPORT_SYMBOL_GPL(clk_bulk_put);
  80
  81static int __clk_bulk_get(struct device *dev, int num_clks,
  82                          struct clk_bulk_data *clks, bool optional)
  83{
  84        int ret;
  85        int i;
  86
  87        for (i = 0; i < num_clks; i++)
  88                clks[i].clk = NULL;
  89
  90        for (i = 0; i < num_clks; i++) {
  91                clks[i].clk = clk_get(dev, clks[i].id);
  92                if (IS_ERR(clks[i].clk)) {
  93                        ret = PTR_ERR(clks[i].clk);
  94                        clks[i].clk = NULL;
  95
  96                        if (ret == -ENOENT && optional)
  97                                continue;
  98
  99                        if (ret != -EPROBE_DEFER)
 100                                dev_err(dev, "Failed to get clk '%s': %d\n",
 101                                        clks[i].id, ret);
 102                        goto err;
 103                }
 104        }
 105
 106        return 0;
 107
 108err:
 109        clk_bulk_put(i, clks);
 110
 111        return ret;
 112}
 113
 114int __must_check clk_bulk_get(struct device *dev, int num_clks,
 115                              struct clk_bulk_data *clks)
 116{
 117        return __clk_bulk_get(dev, num_clks, clks, false);
 118}
 119EXPORT_SYMBOL(clk_bulk_get);
 120
 121int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
 122                                       struct clk_bulk_data *clks)
 123{
 124        return __clk_bulk_get(dev, num_clks, clks, true);
 125}
 126EXPORT_SYMBOL_GPL(clk_bulk_get_optional);
 127
 128void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
 129{
 130        if (IS_ERR_OR_NULL(clks))
 131                return;
 132
 133        clk_bulk_put(num_clks, clks);
 134
 135        kfree(clks);
 136}
 137EXPORT_SYMBOL(clk_bulk_put_all);
 138
 139int __must_check clk_bulk_get_all(struct device *dev,
 140                                  struct clk_bulk_data **clks)
 141{
 142        struct device_node *np = dev_of_node(dev);
 143
 144        if (!np)
 145                return 0;
 146
 147        return of_clk_bulk_get_all(np, clks);
 148}
 149EXPORT_SYMBOL(clk_bulk_get_all);
 150
 151#ifdef CONFIG_HAVE_CLK_PREPARE
 152
 153/**
 154 * clk_bulk_unprepare - undo preparation of a set of clock sources
 155 * @num_clks: the number of clk_bulk_data
 156 * @clks: the clk_bulk_data table being unprepared
 157 *
 158 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
 159 * Returns 0 on success, -EERROR otherwise.
 160 */
 161void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
 162{
 163        while (--num_clks >= 0)
 164                clk_unprepare(clks[num_clks].clk);
 165}
 166EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
 167
 168/**
 169 * clk_bulk_prepare - prepare a set of clocks
 170 * @num_clks: the number of clk_bulk_data
 171 * @clks: the clk_bulk_data table being prepared
 172 *
 173 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
 174 * Returns 0 on success, -EERROR otherwise.
 175 */
 176int __must_check clk_bulk_prepare(int num_clks,
 177                                  const struct clk_bulk_data *clks)
 178{
 179        int ret;
 180        int i;
 181
 182        for (i = 0; i < num_clks; i++) {
 183                ret = clk_prepare(clks[i].clk);
 184                if (ret) {
 185                        pr_err("Failed to prepare clk '%s': %d\n",
 186                                clks[i].id, ret);
 187                        goto err;
 188                }
 189        }
 190
 191        return 0;
 192
 193err:
 194        clk_bulk_unprepare(i, clks);
 195
 196        return  ret;
 197}
 198EXPORT_SYMBOL_GPL(clk_bulk_prepare);
 199
 200#endif /* CONFIG_HAVE_CLK_PREPARE */
 201
 202/**
 203 * clk_bulk_disable - gate a set of clocks
 204 * @num_clks: the number of clk_bulk_data
 205 * @clks: the clk_bulk_data table being gated
 206 *
 207 * clk_bulk_disable must not sleep, which differentiates it from
 208 * clk_bulk_unprepare. clk_bulk_disable must be called before
 209 * clk_bulk_unprepare.
 210 */
 211void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)
 212{
 213
 214        while (--num_clks >= 0)
 215                clk_disable(clks[num_clks].clk);
 216}
 217EXPORT_SYMBOL_GPL(clk_bulk_disable);
 218
 219/**
 220 * clk_bulk_enable - ungate a set of clocks
 221 * @num_clks: the number of clk_bulk_data
 222 * @clks: the clk_bulk_data table being ungated
 223 *
 224 * clk_bulk_enable must not sleep
 225 * Returns 0 on success, -EERROR otherwise.
 226 */
 227int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)
 228{
 229        int ret;
 230        int i;
 231
 232        for (i = 0; i < num_clks; i++) {
 233                ret = clk_enable(clks[i].clk);
 234                if (ret) {
 235                        pr_err("Failed to enable clk '%s': %d\n",
 236                                clks[i].id, ret);
 237                        goto err;
 238                }
 239        }
 240
 241        return 0;
 242
 243err:
 244        clk_bulk_disable(i, clks);
 245
 246        return  ret;
 247}
 248EXPORT_SYMBOL_GPL(clk_bulk_enable);
 249