1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
7 #include <linux/clk-provider.h>
8 #include <linux/module.h>
10 #include "clk-regmap.h"
11 #include "clk-cpu-dyndiv.h"
13 static inline struct meson_clk_cpu_dyndiv_data
*
14 meson_clk_cpu_dyndiv_data(struct clk_regmap
*clk
)
16 return (struct meson_clk_cpu_dyndiv_data
*)clk
->data
;
19 static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw
*hw
,
22 struct clk_regmap
*clk
= to_clk_regmap(hw
);
23 struct meson_clk_cpu_dyndiv_data
*data
= meson_clk_cpu_dyndiv_data(clk
);
25 return divider_recalc_rate(hw
, prate
,
26 meson_parm_read(clk
->map
, &data
->div
),
27 NULL
, 0, data
->div
.width
);
30 static int meson_clk_cpu_dyndiv_determine_rate(struct clk_hw
*hw
,
31 struct clk_rate_request
*req
)
33 struct clk_regmap
*clk
= to_clk_regmap(hw
);
34 struct meson_clk_cpu_dyndiv_data
*data
= meson_clk_cpu_dyndiv_data(clk
);
36 return divider_determine_rate(hw
, req
, NULL
, data
->div
.width
, 0);
39 static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw
*hw
, unsigned long rate
,
40 unsigned long parent_rate
)
42 struct clk_regmap
*clk
= to_clk_regmap(hw
);
43 struct meson_clk_cpu_dyndiv_data
*data
= meson_clk_cpu_dyndiv_data(clk
);
47 ret
= divider_get_val(rate
, parent_rate
, NULL
, data
->div
.width
, 0);
51 val
= (unsigned int)ret
<< data
->div
.shift
;
53 /* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
54 meson_parm_write(clk
->map
, &data
->dyn
, 1);
56 /* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
57 return regmap_update_bits(clk
->map
, data
->div
.reg_off
,
58 SETPMASK(data
->div
.width
, data
->div
.shift
) |
59 SETPMASK(data
->dyn
.width
, data
->dyn
.shift
),
63 const struct clk_ops meson_clk_cpu_dyndiv_ops
= {
64 .recalc_rate
= meson_clk_cpu_dyndiv_recalc_rate
,
65 .determine_rate
= meson_clk_cpu_dyndiv_determine_rate
,
66 .set_rate
= meson_clk_cpu_dyndiv_set_rate
,
68 EXPORT_SYMBOL_NS_GPL(meson_clk_cpu_dyndiv_ops
, CLK_MESON
);
70 MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
71 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
72 MODULE_LICENSE("GPL");
73 MODULE_IMPORT_NS(CLK_MESON
);