clk-aspeed.c (98f3118debb3876399a8da59d72b4908431f1027) clk-aspeed.c (15ed8ce5f84e2b3718690915dbee12ebd497dc0f)
1// SPDX-License-Identifier: GPL-2.0+
2
3#define pr_fmt(fmt) "clk-aspeed: " fmt
4
5#include <linux/clk-provider.h>
6#include <linux/mfd/syscon.h>
7#include <linux/of_address.h>
8#include <linux/of_device.h>

--- 190 unchanged lines hidden (view full) ---

199};
200
201static const struct aspeed_clk_soc_data ast2400_data = {
202 .div_table = ast2400_div_table,
203 .mac_div_table = ast2400_div_table,
204 .calc_pll = aspeed_ast2400_calc_pll,
205};
206
1// SPDX-License-Identifier: GPL-2.0+
2
3#define pr_fmt(fmt) "clk-aspeed: " fmt
4
5#include <linux/clk-provider.h>
6#include <linux/mfd/syscon.h>
7#include <linux/of_address.h>
8#include <linux/of_device.h>

--- 190 unchanged lines hidden (view full) ---

199};
200
201static const struct aspeed_clk_soc_data ast2400_data = {
202 .div_table = ast2400_div_table,
203 .mac_div_table = ast2400_div_table,
204 .calc_pll = aspeed_ast2400_calc_pll,
205};
206
207static int aspeed_clk_enable(struct clk_hw *hw)
208{
209 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
210 unsigned long flags;
211 u32 clk = BIT(gate->clock_idx);
212 u32 rst = BIT(gate->reset_idx);
213
214 spin_lock_irqsave(gate->lock, flags);
215
216 if (gate->reset_idx >= 0) {
217 /* Put IP in reset */
218 regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
219
220 /* Delay 100us */
221 udelay(100);
222 }
223
224 /* Enable clock */
225 regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, 0);
226
227 if (gate->reset_idx >= 0) {
228 /* A delay of 10ms is specified by the ASPEED docs */
229 mdelay(10);
230
231 /* Take IP out of reset */
232 regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0);
233 }
234
235 spin_unlock_irqrestore(gate->lock, flags);
236
237 return 0;
238}
239
240static void aspeed_clk_disable(struct clk_hw *hw)
241{
242 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
243 unsigned long flags;
244 u32 clk = BIT(gate->clock_idx);
245
246 spin_lock_irqsave(gate->lock, flags);
247
248 regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, clk);
249
250 spin_unlock_irqrestore(gate->lock, flags);
251}
252
253static int aspeed_clk_is_enabled(struct clk_hw *hw)
254{
255 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
256 u32 clk = BIT(gate->clock_idx);
257 u32 reg;
258
259 regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, &reg);
260
261 return (reg & clk) ? 0 : 1;
262}
263
264static const struct clk_ops aspeed_clk_gate_ops = {
265 .enable = aspeed_clk_enable,
266 .disable = aspeed_clk_disable,
267 .is_enabled = aspeed_clk_is_enabled,
268};
269
270static struct clk_hw *aspeed_clk_hw_register_gate(struct device *dev,
271 const char *name, const char *parent_name, unsigned long flags,
272 struct regmap *map, u8 clock_idx, u8 reset_idx,
273 u8 clk_gate_flags, spinlock_t *lock)
274{
275 struct aspeed_clk_gate *gate;
276 struct clk_init_data init;
277 struct clk_hw *hw;
278 int ret;
279
280 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
281 if (!gate)
282 return ERR_PTR(-ENOMEM);
283
284 init.name = name;
285 init.ops = &aspeed_clk_gate_ops;
286 init.flags = flags;
287 init.parent_names = parent_name ? &parent_name : NULL;
288 init.num_parents = parent_name ? 1 : 0;
289
290 gate->map = map;
291 gate->clock_idx = clock_idx;
292 gate->reset_idx = reset_idx;
293 gate->flags = clk_gate_flags;
294 gate->lock = lock;
295 gate->hw.init = &init;
296
297 hw = &gate->hw;
298 ret = clk_hw_register(dev, hw);
299 if (ret) {
300 kfree(gate);
301 hw = ERR_PTR(ret);
302 }
303
304 return hw;
305}
306
207static int aspeed_clk_probe(struct platform_device *pdev)
208{
209 const struct aspeed_clk_soc_data *soc_data;
210 struct device *dev = &pdev->dev;
211 struct regmap *map;
212 struct clk_hw *hw;
213 u32 val, rate;
307static int aspeed_clk_probe(struct platform_device *pdev)
308{
309 const struct aspeed_clk_soc_data *soc_data;
310 struct device *dev = &pdev->dev;
311 struct regmap *map;
312 struct clk_hw *hw;
313 u32 val, rate;
314 int i;
214
215 map = syscon_node_to_regmap(dev->of_node);
216 if (IS_ERR(map)) {
217 dev_err(dev, "no syscon regmap\n");
218 return PTR_ERR(map);
219 }
220
221 /* SoC generations share common layouts but have different divisors */

--- 56 unchanged lines hidden (view full) ---

278 hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0,
279 scu_base + ASPEED_CLK_SELECTION_2, 0, 2, 0,
280 soc_data->div_table,
281 &aspeed_clk_lock);
282 if (IS_ERR(hw))
283 return PTR_ERR(hw);
284 aspeed_clk_data->hws[ASPEED_CLK_BCLK] = hw;
285
315
316 map = syscon_node_to_regmap(dev->of_node);
317 if (IS_ERR(map)) {
318 dev_err(dev, "no syscon regmap\n");
319 return PTR_ERR(map);
320 }
321
322 /* SoC generations share common layouts but have different divisors */

--- 56 unchanged lines hidden (view full) ---

379 hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0,
380 scu_base + ASPEED_CLK_SELECTION_2, 0, 2, 0,
381 soc_data->div_table,
382 &aspeed_clk_lock);
383 if (IS_ERR(hw))
384 return PTR_ERR(hw);
385 aspeed_clk_data->hws[ASPEED_CLK_BCLK] = hw;
386
387 /*
388 * TODO: There are a number of clocks that not included in this driver
389 * as more information is required:
390 * D2-PLL
391 * D-PLL
392 * YCLK
393 * RGMII
394 * RMII
395 * UART[1..5] clock source mux
396 * Video Engine (ECLK) mux and clock divider
397 */
398
399 for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) {
400 const struct aspeed_gate_data *gd = &aspeed_gates[i];
401
402 hw = aspeed_clk_hw_register_gate(dev,
403 gd->name,
404 gd->parent_name,
405 gd->flags,
406 map,
407 gd->clock_idx,
408 gd->reset_idx,
409 CLK_GATE_SET_TO_DISABLE,
410 &aspeed_clk_lock);
411 if (IS_ERR(hw))
412 return PTR_ERR(hw);
413 aspeed_clk_data->hws[i] = hw;
414 }
415
286 return 0;
287};
288
289static const struct of_device_id aspeed_clk_dt_ids[] = {
290 { .compatible = "aspeed,ast2400-scu", .data = &ast2400_data },
291 { .compatible = "aspeed,ast2500-scu", .data = &ast2500_data },
292 { }
293};

--- 155 unchanged lines hidden ---
416 return 0;
417};
418
419static const struct of_device_id aspeed_clk_dt_ids[] = {
420 { .compatible = "aspeed,ast2400-scu", .data = &ast2400_data },
421 { .compatible = "aspeed,ast2500-scu", .data = &ast2500_data },
422 { }
423};

--- 155 unchanged lines hidden ---