Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c08eed8 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: qcom: clk-dummy: Add a dummy clock provider"

parents d352284d ff74cb09
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
Qualcomm Technologies, Inc. Dummy Clock Controller Binding

Qualcomm Technologies, Inc. dummy clock controller devices provide
clock API support for driver development during pre-silicon stage.
The clock driver always returns a dummy clock that has no effect on
hardware.

Required properties:
- compatible:		Must be "qcom,dummycc"
- #clock-cells:		Must be <1>. This will allow the common clock device
			tree framework to recognize _this_ device node as a
			clock provider.

Optional properties:
- clock-output-names:	Name of the clock or the clock type.
- #reset-cells:		Must be <1>. This will allow the common reset device
			tree framework to recognize _this_ device node as a
			reset controller provider.

Example:
	clock_gcc: qcom,gcc {
		compatible = "qcom,dummycc";
		clock-output-names = "gcc_clocks";
		#clock-cells = <1>;
		#reset-cells = <1>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ clk-qcom-y += clk-regmap-divider.o
clk-qcom-y += clk-regmap-mux.o
clk-qcom-y += clk-regmap-mux-div.o
clk-qcom-y += reset.o
clk-qcom-y += clk-dummy.o
clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o

# Keep alphabetically sorted by config
+138 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 */

#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "common.h"

#define to_clk_dummy(_hw)	container_of(_hw, struct clk_dummy, hw)

#define RESET_MAX	100

static int dummy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
					unsigned long parent_rate)
{
	struct clk_dummy *dummy = to_clk_dummy(hw);

	dummy->rrate = rate;

	pr_debug("%s: rate %lu\n", __func__, rate);

	return 0;
}

static long dummy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
					unsigned long *parent_rate)
{
	return rate;
}

static unsigned long dummy_clk_recalc_rate(struct clk_hw *hw,
		unsigned long parent_rate)
{
	struct clk_dummy *dummy = to_clk_dummy(hw);

	pr_debug("%s: returning a clock rate of %lu\n",
				__func__, dummy->rrate);

	return dummy->rrate;
}

const struct clk_ops clk_dummy_ops = {
	.set_rate = dummy_clk_set_rate,
	.round_rate = dummy_clk_round_rate,
	.recalc_rate = dummy_clk_recalc_rate,
};
EXPORT_SYMBOL(clk_dummy_ops);

static int dummy_reset_assert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return 0;
}

static int dummy_reset_deassert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return 0;
}

static struct reset_control_ops dummy_reset_ops = {
	.assert         = dummy_reset_assert,
	.deassert       = dummy_reset_deassert,
};

/**
 * clk_register_dummy - register dummy clock with the
 *				   clock framework
 * @dev: device that is registering this clock
 * @name: name of this clock
 * @flags: framework-specific flags
 * @node: device node
 */
static struct clk *clk_register_dummy(struct device *dev, const char *name,
		unsigned long flags, struct device_node *node)
{
	struct clk_dummy *dummy;
	struct clk *clk;
	struct clk_init_data init = {};

	/* allocate dummy clock */
	dummy = kzalloc(sizeof(*dummy), GFP_KERNEL);
	if (!dummy)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &clk_dummy_ops;
	init.flags = flags | CLK_IS_BASIC;
	init.num_parents = 0;
	dummy->hw.init = &init;

	/* register the clock */
	clk = clk_register(dev, &dummy->hw);
	if (IS_ERR(clk)) {
		kfree(dummy);
		return clk;
	}

	dummy->reset.of_node = node;
	dummy->reset.ops = &dummy_reset_ops;
	dummy->reset.nr_resets = RESET_MAX;

	if (reset_controller_register(&dummy->reset))
		pr_err("Failed to register reset controller for %s\n", name);
	else
		pr_info("Successfully registered dummy reset controller for %s\n",
								name);

	return clk;
}

/**
 * of_dummy_clk_setup() - Setup function for simple fixed rate clock
 */
static void of_dummy_clk_setup(struct device_node *node)
{
	struct clk *clk;
	const char *clk_name = "dummy_clk";

	of_property_read_string(node, "clock-output-names", &clk_name);

	clk = clk_register_dummy(NULL, clk_name, 0, node);
	if (!IS_ERR(clk)) {
		of_clk_add_provider(node, of_clk_src_simple_get, clk);
	} else {
		pr_err("Failed to register dummy clock controller for %s\n",
								clk_name);
		return;
	}

	pr_info("Successfully registered dummy clock controller for %s\n",
								clk_name);
}
CLK_OF_DECLARE(dummy_clk, "qcom,dummycc", of_dummy_clk_setup);
+11 −11
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * Copyright (c) 2014, 2018, The Linux Foundation. All rights reserved.
 */
#ifndef __QCOM_CLK_COMMON_H__
#define __QCOM_CLK_COMMON_H__

#include <linux/reset-controller.h>

struct platform_device;
struct regmap_config;
struct clk_regmap;
@@ -48,6 +42,12 @@ struct parent_map {
	u8 cfg;
};

struct clk_dummy {
	struct clk_hw hw;
	struct reset_controller_dev reset;
	unsigned long rrate;
};

extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
					     unsigned long rate);
extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
@@ -68,5 +68,5 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
				struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev,
			 const struct qcom_cc_desc *desc);

extern const struct clk_ops clk_dummy_ops;
#endif