cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-bulk.c (5160B)


      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);