brintos

brintos / linux-shallow public Read only

0
0
Text · 2.5 KiB · 596e939 Raw
112 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * clkgen-mux.c: ST GEN-MUX Clock driver4 *5 * Copyright (C) 2014 STMicroelectronics (R&D) Limited6 *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	struct device_node *parent_np;60 61	/*62	 * First check for reg property within the node to keep backward63	 * compatibility, then if reg doesn't exist look at the parent node64	 */65	reg = of_iomap(np, 0);66	if (!reg) {67		parent_np = of_get_parent(np);68		reg = of_iomap(parent_np, 0);69		of_node_put(parent_np);70		if (!reg) {71			pr_err("%s: Failed to get base address\n", __func__);72			return;73		}74	}75 76	parents = clkgen_mux_get_parents(np, &num_parents);77	if (IS_ERR(parents)) {78		pr_err("%s: Failed to get parents (%ld)\n",79				__func__, PTR_ERR(parents));80		goto err_parents;81	}82 83	clk = clk_register_mux(NULL, np->name, parents, num_parents,84				data->clk_flags | CLK_SET_RATE_PARENT,85				reg + data->offset,86				data->shift, data->width, data->mux_flags,87				data->lock);88	if (IS_ERR(clk))89		goto err;90 91	pr_debug("%s: parent %s rate %u\n",92			__clk_get_name(clk),93			__clk_get_name(clk_get_parent(clk)),94			(unsigned int)clk_get_rate(clk));95 96	kfree(parents);97	of_clk_add_provider(np, of_clk_src_simple_get, clk);98	return;99 100err:101	kfree(parents);102err_parents:103	iounmap(reg);104}105 106static void __init st_of_clkgen_a9_mux_setup(struct device_node *np)107{108	st_of_clkgen_mux_setup(np, &stih407_a9_mux_data);109}110CLK_OF_DECLARE(clkgen_a9mux, "st,stih407-clkgen-a9-mux",111		st_of_clkgen_a9_mux_setup);112