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

clkgen-mux.c (2473B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * clkgen-mux.c: ST GEN-MUX Clock driver
      4 *
      5 * Copyright (C) 2014 STMicroelectronics (R&D) Limited
      6 *
      7 * Authors: Stephen Gallimore <stephen.gallimore@st.com>
      8 *	    Pankaj Dev <pankaj.dev@st.com>
      9 */
     10
     11#include <linux/slab.h>
     12#include <linux/io.h>
     13#include <linux/of_address.h>
     14#include <linux/clk.h>
     15#include <linux/clk-provider.h>
     16#include "clkgen.h"
     17
     18static const char ** __init clkgen_mux_get_parents(struct device_node *np,
     19						       int *num_parents)
     20{
     21	const char **parents;
     22	unsigned int nparents;
     23
     24	nparents = of_clk_get_parent_count(np);
     25	if (WARN_ON(!nparents))
     26		return ERR_PTR(-EINVAL);
     27
     28	parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
     29	if (!parents)
     30		return ERR_PTR(-ENOMEM);
     31
     32	*num_parents = of_clk_parent_fill(np, parents, nparents);
     33	return parents;
     34}
     35
     36struct clkgen_mux_data {
     37	u32 offset;
     38	u8 shift;
     39	u8 width;
     40	spinlock_t *lock;
     41	unsigned long clk_flags;
     42	u8 mux_flags;
     43};
     44
     45static struct clkgen_mux_data stih407_a9_mux_data = {
     46	.offset = 0x1a4,
     47	.shift = 0,
     48	.width = 2,
     49	.lock = &clkgen_a9_lock,
     50};
     51
     52static void __init st_of_clkgen_mux_setup(struct device_node *np,
     53		struct clkgen_mux_data *data)
     54{
     55	struct clk *clk;
     56	void __iomem *reg;
     57	const char **parents;
     58	int num_parents = 0;
     59
     60	/*
     61	 * First check for reg property within the node to keep backward
     62	 * compatibility, then if reg doesn't exist look at the parent node
     63	 */
     64	reg = of_iomap(np, 0);
     65	if (!reg) {
     66		reg = of_iomap(of_get_parent(np), 0);
     67		if (!reg) {
     68			pr_err("%s: Failed to get base address\n", __func__);
     69			return;
     70		}
     71	}
     72
     73	parents = clkgen_mux_get_parents(np, &num_parents);
     74	if (IS_ERR(parents)) {
     75		pr_err("%s: Failed to get parents (%ld)\n",
     76				__func__, PTR_ERR(parents));
     77		goto err_parents;
     78	}
     79
     80	clk = clk_register_mux(NULL, np->name, parents, num_parents,
     81				data->clk_flags | CLK_SET_RATE_PARENT,
     82				reg + data->offset,
     83				data->shift, data->width, data->mux_flags,
     84				data->lock);
     85	if (IS_ERR(clk))
     86		goto err;
     87
     88	pr_debug("%s: parent %s rate %u\n",
     89			__clk_get_name(clk),
     90			__clk_get_name(clk_get_parent(clk)),
     91			(unsigned int)clk_get_rate(clk));
     92
     93	kfree(parents);
     94	of_clk_add_provider(np, of_clk_src_simple_get, clk);
     95	return;
     96
     97err:
     98	kfree(parents);
     99err_parents:
    100	iounmap(reg);
    101}
    102
    103static void __init st_of_clkgen_a9_mux_setup(struct device_node *np)
    104{
    105	st_of_clkgen_mux_setup(np, &stih407_a9_mux_data);
    106}
    107CLK_OF_DECLARE(clkgen_a9mux, "st,stih407-clkgen-a9-mux",
    108		st_of_clkgen_a9_mux_setup);