File Index
Files and directories
Sign in
FILE

clk-cpu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/imx/clk-cpu.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
  4 */
  5
  6#include <linux/clk.h>
  7#include <linux/clk-provider.h>
  8#include <linux/export.h>
  9#include <linux/slab.h>
 10#include "clk.h"
 11
 12struct clk_cpu {
 13	struct clk_hw	hw;
 14	struct clk	*div;
 15	struct clk	*mux;
 16	struct clk	*pll;
 17	struct clk	*step;
 18};
 19
 20static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
 21{
 22	return container_of(hw, struct clk_cpu, hw);
 23}
 24
 25static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
 26					 unsigned long parent_rate)
 27{
 28	struct clk_cpu *cpu = to_clk_cpu(hw);
 29
 30	return clk_get_rate(cpu->div);
 31}
 32
 33static int clk_cpu_determine_rate(struct clk_hw *hw,
 34				  struct clk_rate_request *req)
 35{
 36	struct clk_cpu *cpu = to_clk_cpu(hw);
 37
 38	req->rate = clk_round_rate(cpu->pll, req->rate);
 39
 40	return 0;
 41}
 42
 43static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
 44			    unsigned long parent_rate)
 45{
 46	struct clk_cpu *cpu = to_clk_cpu(hw);
 47	int ret;
 48
 49	/* switch to PLL bypass clock */
 50	ret = clk_set_parent(cpu->mux, cpu->step);
 51	if (ret)
 52		return ret;
 53
 54	/* reprogram PLL */
 55	ret = clk_set_rate(cpu->pll, rate);
 56	if (ret) {
 57		clk_set_parent(cpu->mux, cpu->pll);
 58		return ret;
 59	}
 60	/* switch back to PLL clock */
 61	clk_set_parent(cpu->mux, cpu->pll);
 62
 63	/* Ensure the divider is what we expect */
 64	clk_set_rate(cpu->div, rate);
 65
 66	return 0;
 67}
 68
 69static const struct clk_ops clk_cpu_ops = {
 70	.recalc_rate	= clk_cpu_recalc_rate,
 71	.determine_rate = clk_cpu_determine_rate,
 72	.set_rate	= clk_cpu_set_rate,
 73};
 74
 75struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
 76		struct clk *div, struct clk *mux, struct clk *pll,
 77		struct clk *step)
 78{
 79	struct clk_cpu *cpu;
 80	struct clk_hw *hw;
 81	struct clk_init_data init;
 82	int ret;
 83
 84	cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
 85	if (!cpu)
 86		return ERR_PTR(-ENOMEM);
 87
 88	cpu->div = div;
 89	cpu->mux = mux;
 90	cpu->pll = pll;
 91	cpu->step = step;
 92
 93	init.name = name;
 94	init.ops = &clk_cpu_ops;
 95	init.flags = CLK_IS_CRITICAL;
 96	init.parent_names = &parent_name;
 97	init.num_parents = 1;
 98
 99	cpu->hw.init = &init;
100	hw = &cpu->hw;
101
102	ret = clk_hw_register(NULL, hw);
103	if (ret) {
104		kfree(cpu);
105		return ERR_PTR(ret);
106	}
107
108	return hw;
109}
110EXPORT_SYMBOL_GPL(imx_clk_hw_cpu);
~/ Read-only file preview.