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-conf.c (3833B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2014 Samsung Electronics Co., Ltd.
      4 * Sylwester Nawrocki <s.nawrocki@samsung.com>
      5 */
      6
      7#include <linux/clk.h>
      8#include <linux/clk-provider.h>
      9#include <linux/clk/clk-conf.h>
     10#include <linux/device.h>
     11#include <linux/of.h>
     12#include <linux/printk.h>
     13
     14static int __set_clk_parents(struct device_node *node, bool clk_supplier)
     15{
     16	struct of_phandle_args clkspec;
     17	int index, rc, num_parents;
     18	struct clk *clk, *pclk;
     19
     20	num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
     21						 "#clock-cells");
     22	if (num_parents == -EINVAL)
     23		pr_err("clk: invalid value of clock-parents property at %pOF\n",
     24		       node);
     25
     26	for (index = 0; index < num_parents; index++) {
     27		rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
     28					"#clock-cells",	index, &clkspec);
     29		if (rc < 0) {
     30			/* skip empty (null) phandles */
     31			if (rc == -ENOENT)
     32				continue;
     33			else
     34				return rc;
     35		}
     36		if (clkspec.np == node && !clk_supplier)
     37			return 0;
     38		pclk = of_clk_get_from_provider(&clkspec);
     39		if (IS_ERR(pclk)) {
     40			if (PTR_ERR(pclk) != -EPROBE_DEFER)
     41				pr_warn("clk: couldn't get parent clock %d for %pOF\n",
     42					index, node);
     43			return PTR_ERR(pclk);
     44		}
     45
     46		rc = of_parse_phandle_with_args(node, "assigned-clocks",
     47					"#clock-cells", index, &clkspec);
     48		if (rc < 0)
     49			goto err;
     50		if (clkspec.np == node && !clk_supplier) {
     51			rc = 0;
     52			goto err;
     53		}
     54		clk = of_clk_get_from_provider(&clkspec);
     55		if (IS_ERR(clk)) {
     56			if (PTR_ERR(clk) != -EPROBE_DEFER)
     57				pr_warn("clk: couldn't get assigned clock %d for %pOF\n",
     58					index, node);
     59			rc = PTR_ERR(clk);
     60			goto err;
     61		}
     62
     63		rc = clk_set_parent(clk, pclk);
     64		if (rc < 0)
     65			pr_err("clk: failed to reparent %s to %s: %d\n",
     66			       __clk_get_name(clk), __clk_get_name(pclk), rc);
     67		clk_put(clk);
     68		clk_put(pclk);
     69	}
     70	return 0;
     71err:
     72	clk_put(pclk);
     73	return rc;
     74}
     75
     76static int __set_clk_rates(struct device_node *node, bool clk_supplier)
     77{
     78	struct of_phandle_args clkspec;
     79	struct property	*prop;
     80	const __be32 *cur;
     81	int rc, index = 0;
     82	struct clk *clk;
     83	u32 rate;
     84
     85	of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
     86		if (rate) {
     87			rc = of_parse_phandle_with_args(node, "assigned-clocks",
     88					"#clock-cells",	index, &clkspec);
     89			if (rc < 0) {
     90				/* skip empty (null) phandles */
     91				if (rc == -ENOENT)
     92					continue;
     93				else
     94					return rc;
     95			}
     96			if (clkspec.np == node && !clk_supplier)
     97				return 0;
     98
     99			clk = of_clk_get_from_provider(&clkspec);
    100			if (IS_ERR(clk)) {
    101				if (PTR_ERR(clk) != -EPROBE_DEFER)
    102					pr_warn("clk: couldn't get clock %d for %pOF\n",
    103						index, node);
    104				return PTR_ERR(clk);
    105			}
    106
    107			rc = clk_set_rate(clk, rate);
    108			if (rc < 0)
    109				pr_err("clk: couldn't set %s clk rate to %u (%d), current rate: %lu\n",
    110				       __clk_get_name(clk), rate, rc,
    111				       clk_get_rate(clk));
    112			clk_put(clk);
    113		}
    114		index++;
    115	}
    116	return 0;
    117}
    118
    119/**
    120 * of_clk_set_defaults() - parse and set assigned clocks configuration
    121 * @node: device node to apply clock settings for
    122 * @clk_supplier: true if clocks supplied by @node should also be considered
    123 *
    124 * This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
    125 * and sets any specified clock parents and rates. The @clk_supplier argument
    126 * should be set to true if @node may be also a clock supplier of any clock
    127 * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
    128 * If @clk_supplier is false the function exits returning 0 as soon as it
    129 * determines the @node is also a supplier of any of the clocks.
    130 */
    131int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
    132{
    133	int rc;
    134
    135	if (!node)
    136		return 0;
    137
    138	rc = __set_clk_parents(node, clk_supplier);
    139	if (rc < 0)
    140		return rc;
    141
    142	return __set_clk_rates(node, clk_supplier);
    143}
    144EXPORT_SYMBOL_GPL(of_clk_set_defaults);