Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
4 : : *
5 : : * Authors:
6 : : * Jyri Sarha <jsarha@ti.com>
7 : : * Sergej Sawazki <ce3a@gmx.de>
8 : : *
9 : : * Gpio controlled clock implementation
10 : : */
11 : :
12 : : #include <linux/clk-provider.h>
13 : : #include <linux/export.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/gpio/consumer.h>
16 : : #include <linux/err.h>
17 : : #include <linux/device.h>
18 : : #include <linux/platform_device.h>
19 : : #include <linux/of_device.h>
20 : :
21 : : /**
22 : : * DOC: basic gpio gated clock which can be enabled and disabled
23 : : * with gpio output
24 : : * Traits of this clock:
25 : : * prepare - clk_(un)prepare only ensures parent is (un)prepared
26 : : * enable - clk_enable and clk_disable are functional & control gpio
27 : : * rate - inherits rate from parent. No clk_set_rate support
28 : : * parent - fixed parent. No clk_set_parent support
29 : : */
30 : :
31 : : /**
32 : : * struct clk_gpio - gpio gated clock
33 : : *
34 : : * @hw: handle between common and hardware-specific interfaces
35 : : * @gpiod: gpio descriptor
36 : : *
37 : : * Clock with a gpio control for enabling and disabling the parent clock
38 : : * or switching between two parents by asserting or deasserting the gpio.
39 : : *
40 : : * Implements .enable, .disable and .is_enabled or
41 : : * .get_parent, .set_parent and .determine_rate depending on which clk_ops
42 : : * is used.
43 : : */
44 : : struct clk_gpio {
45 : : struct clk_hw hw;
46 : : struct gpio_desc *gpiod;
47 : : };
48 : :
49 : : #define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
50 : :
51 : : static int clk_gpio_gate_enable(struct clk_hw *hw)
52 : : {
53 : : struct clk_gpio *clk = to_clk_gpio(hw);
54 : :
55 : : gpiod_set_value(clk->gpiod, 1);
56 : :
57 : : return 0;
58 : : }
59 : :
60 : : static void clk_gpio_gate_disable(struct clk_hw *hw)
61 : : {
62 : : struct clk_gpio *clk = to_clk_gpio(hw);
63 : :
64 : : gpiod_set_value(clk->gpiod, 0);
65 : : }
66 : :
67 : : static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
68 : : {
69 : : struct clk_gpio *clk = to_clk_gpio(hw);
70 : :
71 : : return gpiod_get_value(clk->gpiod);
72 : : }
73 : :
74 : : static const struct clk_ops clk_gpio_gate_ops = {
75 : : .enable = clk_gpio_gate_enable,
76 : : .disable = clk_gpio_gate_disable,
77 : : .is_enabled = clk_gpio_gate_is_enabled,
78 : : };
79 : :
80 : : static int clk_sleeping_gpio_gate_prepare(struct clk_hw *hw)
81 : : {
82 : : struct clk_gpio *clk = to_clk_gpio(hw);
83 : :
84 : : gpiod_set_value_cansleep(clk->gpiod, 1);
85 : :
86 : : return 0;
87 : : }
88 : :
89 : : static void clk_sleeping_gpio_gate_unprepare(struct clk_hw *hw)
90 : : {
91 : : struct clk_gpio *clk = to_clk_gpio(hw);
92 : :
93 : : gpiod_set_value_cansleep(clk->gpiod, 0);
94 : : }
95 : :
96 : : static int clk_sleeping_gpio_gate_is_prepared(struct clk_hw *hw)
97 : : {
98 : : struct clk_gpio *clk = to_clk_gpio(hw);
99 : :
100 : : return gpiod_get_value_cansleep(clk->gpiod);
101 : : }
102 : :
103 : : static const struct clk_ops clk_sleeping_gpio_gate_ops = {
104 : : .prepare = clk_sleeping_gpio_gate_prepare,
105 : : .unprepare = clk_sleeping_gpio_gate_unprepare,
106 : : .is_prepared = clk_sleeping_gpio_gate_is_prepared,
107 : : };
108 : :
109 : : /**
110 : : * DOC: basic clock multiplexer which can be controlled with a gpio output
111 : : * Traits of this clock:
112 : : * prepare - clk_prepare only ensures that parents are prepared
113 : : * rate - rate is only affected by parent switching. No clk_set_rate support
114 : : * parent - parent is adjustable through clk_set_parent
115 : : */
116 : :
117 : : static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
118 : : {
119 : : struct clk_gpio *clk = to_clk_gpio(hw);
120 : :
121 : : return gpiod_get_value_cansleep(clk->gpiod);
122 : : }
123 : :
124 : : static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
125 : : {
126 : : struct clk_gpio *clk = to_clk_gpio(hw);
127 : :
128 : : gpiod_set_value_cansleep(clk->gpiod, index);
129 : :
130 : : return 0;
131 : : }
132 : :
133 : : static const struct clk_ops clk_gpio_mux_ops = {
134 : : .get_parent = clk_gpio_mux_get_parent,
135 : : .set_parent = clk_gpio_mux_set_parent,
136 : : .determine_rate = __clk_mux_determine_rate,
137 : : };
138 : :
139 : : static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
140 : : struct gpio_desc *gpiod,
141 : : const struct clk_ops *clk_gpio_ops)
142 : : {
143 : : struct clk_gpio *clk_gpio;
144 : : struct clk_hw *hw;
145 : : struct clk_init_data init = {};
146 : : int err;
147 : : const struct clk_parent_data gpio_parent_data[] = {
148 : : { .index = 0 },
149 : : { .index = 1 },
150 : : };
151 : :
152 : : clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
153 : : if (!clk_gpio)
154 : : return ERR_PTR(-ENOMEM);
155 : :
156 : : init.name = dev->of_node->name;
157 : : init.ops = clk_gpio_ops;
158 : : init.parent_data = gpio_parent_data;
159 : : init.num_parents = num_parents;
160 : : init.flags = CLK_SET_RATE_PARENT;
161 : :
162 : : clk_gpio->gpiod = gpiod;
163 : : clk_gpio->hw.init = &init;
164 : :
165 : : hw = &clk_gpio->hw;
166 : : err = devm_clk_hw_register(dev, hw);
167 : : if (err)
168 : : return ERR_PTR(err);
169 : :
170 : : return hw;
171 : : }
172 : :
173 : : static struct clk_hw *clk_hw_register_gpio_gate(struct device *dev,
174 : : int num_parents,
175 : : struct gpio_desc *gpiod)
176 : : {
177 : : const struct clk_ops *ops;
178 : :
179 : : if (gpiod_cansleep(gpiod))
180 : : ops = &clk_sleeping_gpio_gate_ops;
181 : : else
182 : : ops = &clk_gpio_gate_ops;
183 : :
184 : : return clk_register_gpio(dev, num_parents, gpiod, ops);
185 : : }
186 : :
187 : : static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
188 : : struct gpio_desc *gpiod)
189 : : {
190 : : return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
191 : : }
192 : :
193 : 0 : static int gpio_clk_driver_probe(struct platform_device *pdev)
194 : : {
195 : 0 : struct device *dev = &pdev->dev;
196 : 0 : struct device_node *node = dev->of_node;
197 : 0 : const char *gpio_name;
198 : 0 : unsigned int num_parents;
199 : 0 : struct gpio_desc *gpiod;
200 : 0 : struct clk_hw *hw;
201 : 0 : bool is_mux;
202 : 0 : int ret;
203 : :
204 : 0 : is_mux = of_device_is_compatible(node, "gpio-mux-clock");
205 : :
206 : 0 : num_parents = of_clk_get_parent_count(node);
207 : 0 : if (is_mux && num_parents != 2) {
208 : : dev_err(dev, "mux-clock must have 2 parents\n");
209 : : return -EINVAL;
210 : : }
211 : :
212 : 0 : gpio_name = is_mux ? "select" : "enable";
213 : 0 : gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
214 : 0 : if (IS_ERR(gpiod)) {
215 : 0 : ret = PTR_ERR(gpiod);
216 : 0 : if (ret == -EPROBE_DEFER)
217 : : pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n",
218 : : node, __func__);
219 : : else
220 : 0 : pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n",
221 : : node, __func__,
222 : : gpio_name);
223 : 0 : return ret;
224 : : }
225 : :
226 : : if (is_mux)
227 : : hw = clk_hw_register_gpio_mux(dev, gpiod);
228 : : else
229 : : hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod);
230 : : if (IS_ERR(hw))
231 : : return PTR_ERR(hw);
232 : :
233 : : return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
234 : : }
235 : :
236 : : static const struct of_device_id gpio_clk_match_table[] = {
237 : : { .compatible = "gpio-mux-clock" },
238 : : { .compatible = "gpio-gate-clock" },
239 : : { }
240 : : };
241 : :
242 : : static struct platform_driver gpio_clk_driver = {
243 : : .probe = gpio_clk_driver_probe,
244 : : .driver = {
245 : : .name = "gpio-clk",
246 : : .of_match_table = gpio_clk_match_table,
247 : : },
248 : : };
249 : 13 : builtin_platform_driver(gpio_clk_driver);
|