Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  1) // SPDX-License-Identifier: (GPL-2.0 OR MIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  3)  * Copyright (c) 2019 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  4)  * Author: Neil Armstrong <narmstrong@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "clk-regmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "clk-cpu-dyndiv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static inline struct meson_clk_cpu_dyndiv_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) 	return (struct meson_clk_cpu_dyndiv_data *)clk->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 						      unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 	struct clk_regmap *clk = to_clk_regmap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) 	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) 	return divider_recalc_rate(hw, prate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 				   meson_parm_read(clk->map, &data->div),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) 				   NULL, 0, data->div.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 					    unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 					    unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 	struct clk_regmap *clk = to_clk_regmap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 	return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 					  unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 	struct clk_regmap *clk = to_clk_regmap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 	ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 	val = (unsigned int)ret << data->div.shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 	/* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 	meson_parm_write(clk->map, &data->dyn, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 	/* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 	return regmap_update_bits(clk->map, data->div.reg_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) 				  SETPMASK(data->div.width, data->div.shift) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 				  SETPMASK(data->dyn.width, data->dyn.shift),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 				  val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const struct clk_ops meson_clk_cpu_dyndiv_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 	.recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 	.round_rate = meson_clk_cpu_dyndiv_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 	.set_rate = meson_clk_cpu_dyndiv_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) MODULE_LICENSE("GPL v2");