diff options
Diffstat (limited to 'drivers/clk/qcom/clk-dummy.c')
| -rw-r--r-- | drivers/clk/qcom/clk-dummy.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/drivers/clk/qcom/clk-dummy.c b/drivers/clk/qcom/clk-dummy.c new file mode 100644 index 000000000000..c08136563e31 --- /dev/null +++ b/drivers/clk/qcom/clk-dummy.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/reset-controller.h> + +#include "clk-debug.h" + +struct clk_dummy { + struct clk_hw hw; + struct reset_controller_dev reset; + unsigned long rrate; +}; + +#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("set rate: %lu\n", 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("clock rate: %lu\n", dummy->rrate); + + return dummy->rrate; +} + +static int dummy_clk_set_flags(struct clk_hw *hw, unsigned flags) +{ + return 0; +} + +struct clk_ops clk_dummy_ops = { + .set_rate = dummy_clk_set_rate, + .round_rate = dummy_clk_round_rate, + .recalc_rate = dummy_clk_recalc_rate, + .set_flags = dummy_clk_set_flags, + .debug_init = clk_debug_measure_add, +}; +EXPORT_SYMBOL_GPL(clk_dummy_ops); + +static int dummy_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + pr_debug("%s\n", __func__); + return 0; +} + +static int dummy_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + pr_debug("%s\n", __func__); + 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 a 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 for %s\n", clk_name); +} +CLK_OF_DECLARE(dummy_clk, "qcom,dummycc", of_dummy_clk_setup); |
