1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/device.h>
7 #include <linux/clk-provider.h>
8 #include <linux/regmap.h>
9 #include <linux/export.h>
10 
11 #include "clk-regmap.h"
12 
13 /**
14  * clk_is_enabled_regmap - standard is_enabled() for regmap users
15  *
16  * @hw: clk to operate on
17  *
18  * Clocks that use regmap for their register I/O can set the
19  * enable_reg and enable_mask fields in their struct clk_regmap and then use
20  * this as their is_enabled operation, saving some code.
21  */
clk_is_enabled_regmap(struct clk_hw * hw)22 int clk_is_enabled_regmap(struct clk_hw *hw)
23 {
24 	struct clk_regmap *rclk = to_clk_regmap(hw);
25 	unsigned int val;
26 	int ret;
27 
28 	ret = regmap_read(rclk->regmap, rclk->enable_reg, &val);
29 	if (ret != 0)
30 		return ret;
31 
32 	if (rclk->enable_is_inverted)
33 		return (val & rclk->enable_mask) == 0;
34 	else
35 		return (val & rclk->enable_mask) != 0;
36 }
37 EXPORT_SYMBOL_GPL(clk_is_enabled_regmap);
38 
39 /**
40  * clk_enable_regmap - standard enable() for regmap users
41  *
42  * @hw: clk to operate on
43  *
44  * Clocks that use regmap for their register I/O can set the
45  * enable_reg and enable_mask fields in their struct clk_regmap and then use
46  * this as their enable() operation, saving some code.
47  */
clk_enable_regmap(struct clk_hw * hw)48 int clk_enable_regmap(struct clk_hw *hw)
49 {
50 	struct clk_regmap *rclk = to_clk_regmap(hw);
51 	unsigned int val;
52 
53 	if (rclk->enable_is_inverted)
54 		val = 0;
55 	else
56 		val = rclk->enable_mask;
57 
58 	return regmap_update_bits(rclk->regmap, rclk->enable_reg,
59 				  rclk->enable_mask, val);
60 }
61 EXPORT_SYMBOL_GPL(clk_enable_regmap);
62 
63 /**
64  * clk_disable_regmap - standard disable() for regmap users
65  *
66  * @hw: clk to operate on
67  *
68  * Clocks that use regmap for their register I/O can set the
69  * enable_reg and enable_mask fields in their struct clk_regmap and then use
70  * this as their disable() operation, saving some code.
71  */
clk_disable_regmap(struct clk_hw * hw)72 void clk_disable_regmap(struct clk_hw *hw)
73 {
74 	struct clk_regmap *rclk = to_clk_regmap(hw);
75 	unsigned int val;
76 
77 	if (rclk->enable_is_inverted)
78 		val = rclk->enable_mask;
79 	else
80 		val = 0;
81 
82 	regmap_update_bits(rclk->regmap, rclk->enable_reg, rclk->enable_mask,
83 			   val);
84 }
85 EXPORT_SYMBOL_GPL(clk_disable_regmap);
86 
87 /**
88  * devm_clk_register_regmap - register a clk_regmap clock
89  *
90  * @dev: reference to the caller's device
91  * @rclk: clk to operate on
92  *
93  * Clocks that use regmap for their register I/O should register their
94  * clk_regmap struct via this function so that the regmap is initialized
95  * and so that the clock is registered with the common clock framework.
96  */
devm_clk_register_regmap(struct device * dev,struct clk_regmap * rclk)97 int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk)
98 {
99 	if (dev && dev_get_regmap(dev, NULL))
100 		rclk->regmap = dev_get_regmap(dev, NULL);
101 	else if (dev && dev->parent)
102 		rclk->regmap = dev_get_regmap(dev->parent, NULL);
103 
104 	return devm_clk_hw_register(dev, &rclk->hw);
105 }
106 EXPORT_SYMBOL_GPL(devm_clk_register_regmap);
107