.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | | - * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com |
---|
| 3 | + * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - https://www.ti.com |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: |
---|
5 | 6 | * Jyri Sarha <jsarha@ti.com> |
---|
6 | 7 | * Sergej Sawazki <ce3a@gmx.de> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | * |
---|
12 | 9 | * Gpio controlled clock implementation |
---|
13 | 10 | */ |
---|
.. | .. |
---|
30 | 27 | * rate - inherits rate from parent. No clk_set_rate support |
---|
31 | 28 | * parent - fixed parent. No clk_set_parent support |
---|
32 | 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) |
---|
33 | 50 | |
---|
34 | 51 | static int clk_gpio_gate_enable(struct clk_hw *hw) |
---|
35 | 52 | { |
---|
.. | .. |
---|
54 | 71 | return gpiod_get_value(clk->gpiod); |
---|
55 | 72 | } |
---|
56 | 73 | |
---|
57 | | -const struct clk_ops clk_gpio_gate_ops = { |
---|
| 74 | +static const struct clk_ops clk_gpio_gate_ops = { |
---|
58 | 75 | .enable = clk_gpio_gate_enable, |
---|
59 | 76 | .disable = clk_gpio_gate_disable, |
---|
60 | 77 | .is_enabled = clk_gpio_gate_is_enabled, |
---|
61 | 78 | }; |
---|
62 | | -EXPORT_SYMBOL_GPL(clk_gpio_gate_ops); |
---|
| 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 | +}; |
---|
63 | 108 | |
---|
64 | 109 | /** |
---|
65 | 110 | * DOC: basic clock multiplexer which can be controlled with a gpio output |
---|
.. | .. |
---|
85 | 130 | return 0; |
---|
86 | 131 | } |
---|
87 | 132 | |
---|
88 | | -const struct clk_ops clk_gpio_mux_ops = { |
---|
| 133 | +static const struct clk_ops clk_gpio_mux_ops = { |
---|
89 | 134 | .get_parent = clk_gpio_mux_get_parent, |
---|
90 | 135 | .set_parent = clk_gpio_mux_set_parent, |
---|
91 | 136 | .determine_rate = __clk_mux_determine_rate, |
---|
92 | 137 | }; |
---|
93 | | -EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); |
---|
94 | 138 | |
---|
95 | | -static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, |
---|
96 | | - const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, |
---|
97 | | - unsigned long flags, const struct clk_ops *clk_gpio_ops) |
---|
| 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) |
---|
98 | 142 | { |
---|
99 | 143 | struct clk_gpio *clk_gpio; |
---|
100 | 144 | struct clk_hw *hw; |
---|
101 | 145 | struct clk_init_data init = {}; |
---|
102 | 146 | int err; |
---|
| 147 | + const struct clk_parent_data gpio_parent_data[] = { |
---|
| 148 | + { .index = 0 }, |
---|
| 149 | + { .index = 1 }, |
---|
| 150 | + }; |
---|
103 | 151 | |
---|
104 | | - if (dev) |
---|
105 | | - clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL); |
---|
106 | | - else |
---|
107 | | - clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL); |
---|
108 | | - |
---|
| 152 | + clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL); |
---|
109 | 153 | if (!clk_gpio) |
---|
110 | 154 | return ERR_PTR(-ENOMEM); |
---|
111 | 155 | |
---|
112 | | - init.name = name; |
---|
| 156 | + init.name = dev->of_node->name; |
---|
113 | 157 | init.ops = clk_gpio_ops; |
---|
114 | | - init.flags = flags | CLK_IS_BASIC; |
---|
115 | | - init.parent_names = parent_names; |
---|
| 158 | + init.parent_data = gpio_parent_data; |
---|
116 | 159 | init.num_parents = num_parents; |
---|
| 160 | + init.flags = CLK_SET_RATE_PARENT; |
---|
117 | 161 | |
---|
118 | 162 | clk_gpio->gpiod = gpiod; |
---|
119 | 163 | clk_gpio->hw.init = &init; |
---|
120 | 164 | |
---|
121 | 165 | hw = &clk_gpio->hw; |
---|
122 | | - if (dev) |
---|
123 | | - err = devm_clk_hw_register(dev, 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; |
---|
124 | 181 | else |
---|
125 | | - err = clk_hw_register(NULL, hw); |
---|
| 182 | + ops = &clk_gpio_gate_ops; |
---|
126 | 183 | |
---|
127 | | - if (!err) |
---|
128 | | - return hw; |
---|
129 | | - |
---|
130 | | - if (!dev) { |
---|
131 | | - kfree(clk_gpio); |
---|
132 | | - } |
---|
133 | | - |
---|
134 | | - return ERR_PTR(err); |
---|
| 184 | + return clk_register_gpio(dev, num_parents, gpiod, ops); |
---|
135 | 185 | } |
---|
136 | 186 | |
---|
137 | | -/** |
---|
138 | | - * clk_hw_register_gpio_gate - register a gpio clock gate with the clock |
---|
139 | | - * framework |
---|
140 | | - * @dev: device that is registering this clock |
---|
141 | | - * @name: name of this clock |
---|
142 | | - * @parent_name: name of this clock's parent |
---|
143 | | - * @gpiod: gpio descriptor to gate this clock |
---|
144 | | - * @flags: clock flags |
---|
145 | | - */ |
---|
146 | | -struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, |
---|
147 | | - const char *parent_name, struct gpio_desc *gpiod, |
---|
148 | | - unsigned long flags) |
---|
| 187 | +static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, |
---|
| 188 | + struct gpio_desc *gpiod) |
---|
149 | 189 | { |
---|
150 | | - return clk_register_gpio(dev, name, |
---|
151 | | - (parent_name ? &parent_name : NULL), |
---|
152 | | - (parent_name ? 1 : 0), gpiod, flags, |
---|
153 | | - &clk_gpio_gate_ops); |
---|
| 190 | + return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops); |
---|
154 | 191 | } |
---|
155 | | -EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate); |
---|
156 | | - |
---|
157 | | -struct clk *clk_register_gpio_gate(struct device *dev, const char *name, |
---|
158 | | - const char *parent_name, struct gpio_desc *gpiod, |
---|
159 | | - unsigned long flags) |
---|
160 | | -{ |
---|
161 | | - struct clk_hw *hw; |
---|
162 | | - |
---|
163 | | - hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags); |
---|
164 | | - if (IS_ERR(hw)) |
---|
165 | | - return ERR_CAST(hw); |
---|
166 | | - return hw->clk; |
---|
167 | | -} |
---|
168 | | -EXPORT_SYMBOL_GPL(clk_register_gpio_gate); |
---|
169 | | - |
---|
170 | | -/** |
---|
171 | | - * clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework |
---|
172 | | - * @dev: device that is registering this clock |
---|
173 | | - * @name: name of this clock |
---|
174 | | - * @parent_names: names of this clock's parents |
---|
175 | | - * @num_parents: number of parents listed in @parent_names |
---|
176 | | - * @gpiod: gpio descriptor to gate this clock |
---|
177 | | - * @flags: clock flags |
---|
178 | | - */ |
---|
179 | | -struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, |
---|
180 | | - const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, |
---|
181 | | - unsigned long flags) |
---|
182 | | -{ |
---|
183 | | - if (num_parents != 2) { |
---|
184 | | - pr_err("mux-clock %s must have 2 parents\n", name); |
---|
185 | | - return ERR_PTR(-EINVAL); |
---|
186 | | - } |
---|
187 | | - |
---|
188 | | - return clk_register_gpio(dev, name, parent_names, num_parents, |
---|
189 | | - gpiod, flags, &clk_gpio_mux_ops); |
---|
190 | | -} |
---|
191 | | -EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux); |
---|
192 | | - |
---|
193 | | -struct clk *clk_register_gpio_mux(struct device *dev, const char *name, |
---|
194 | | - const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, |
---|
195 | | - unsigned long flags) |
---|
196 | | -{ |
---|
197 | | - struct clk_hw *hw; |
---|
198 | | - |
---|
199 | | - hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents, |
---|
200 | | - gpiod, flags); |
---|
201 | | - if (IS_ERR(hw)) |
---|
202 | | - return ERR_CAST(hw); |
---|
203 | | - return hw->clk; |
---|
204 | | -} |
---|
205 | | -EXPORT_SYMBOL_GPL(clk_register_gpio_mux); |
---|
206 | 192 | |
---|
207 | 193 | static int gpio_clk_driver_probe(struct platform_device *pdev) |
---|
208 | 194 | { |
---|
209 | | - struct device_node *node = pdev->dev.of_node; |
---|
210 | | - const char **parent_names, *gpio_name; |
---|
| 195 | + struct device *dev = &pdev->dev; |
---|
| 196 | + struct device_node *node = dev->of_node; |
---|
| 197 | + const char *gpio_name; |
---|
211 | 198 | unsigned int num_parents; |
---|
212 | 199 | struct gpio_desc *gpiod; |
---|
213 | | - struct clk *clk; |
---|
| 200 | + struct clk_hw *hw; |
---|
214 | 201 | bool is_mux; |
---|
215 | 202 | int ret; |
---|
216 | 203 | |
---|
217 | | - num_parents = of_clk_get_parent_count(node); |
---|
218 | | - if (num_parents) { |
---|
219 | | - parent_names = devm_kcalloc(&pdev->dev, num_parents, |
---|
220 | | - sizeof(char *), GFP_KERNEL); |
---|
221 | | - if (!parent_names) |
---|
222 | | - return -ENOMEM; |
---|
223 | | - |
---|
224 | | - of_clk_parent_fill(node, parent_names, num_parents); |
---|
225 | | - } else { |
---|
226 | | - parent_names = NULL; |
---|
227 | | - } |
---|
228 | | - |
---|
229 | 204 | is_mux = of_device_is_compatible(node, "gpio-mux-clock"); |
---|
230 | 205 | |
---|
| 206 | + num_parents = of_clk_get_parent_count(node); |
---|
| 207 | + if (is_mux && num_parents != 2) { |
---|
| 208 | + dev_err(dev, "mux-clock must have 2 parents\n"); |
---|
| 209 | + return -EINVAL; |
---|
| 210 | + } |
---|
| 211 | + |
---|
231 | 212 | gpio_name = is_mux ? "select" : "enable"; |
---|
232 | | - gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW); |
---|
| 213 | + gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW); |
---|
233 | 214 | if (IS_ERR(gpiod)) { |
---|
234 | 215 | ret = PTR_ERR(gpiod); |
---|
235 | 216 | if (ret == -EPROBE_DEFER) |
---|
236 | | - pr_debug("%s: %s: GPIOs not yet available, retry later\n", |
---|
237 | | - node->name, __func__); |
---|
| 217 | + pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n", |
---|
| 218 | + node, __func__); |
---|
238 | 219 | else |
---|
239 | | - pr_err("%s: %s: Can't get '%s' named GPIO property\n", |
---|
240 | | - node->name, __func__, |
---|
| 220 | + pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n", |
---|
| 221 | + node, __func__, |
---|
241 | 222 | gpio_name); |
---|
242 | 223 | return ret; |
---|
243 | 224 | } |
---|
244 | 225 | |
---|
245 | 226 | if (is_mux) |
---|
246 | | - clk = clk_register_gpio_mux(&pdev->dev, node->name, |
---|
247 | | - parent_names, num_parents, gpiod, 0); |
---|
| 227 | + hw = clk_hw_register_gpio_mux(dev, gpiod); |
---|
248 | 228 | else |
---|
249 | | - clk = clk_register_gpio_gate(&pdev->dev, node->name, |
---|
250 | | - parent_names ? parent_names[0] : NULL, gpiod, |
---|
251 | | - CLK_SET_RATE_PARENT); |
---|
252 | | - if (IS_ERR(clk)) |
---|
253 | | - return PTR_ERR(clk); |
---|
| 229 | + hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod); |
---|
| 230 | + if (IS_ERR(hw)) |
---|
| 231 | + return PTR_ERR(hw); |
---|
254 | 232 | |
---|
255 | | - return of_clk_add_provider(node, of_clk_src_simple_get, clk); |
---|
| 233 | + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); |
---|
256 | 234 | } |
---|
257 | 235 | |
---|
258 | 236 | static const struct of_device_id gpio_clk_match_table[] = { |
---|