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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Base on code in drivers/clk/clk-fractional-divider.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * See clk-fractional-divider.c for further copyright information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/rational.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "clk-regmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #define to_clk_regmap_fractional_divider(_hw)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 		container_of(_hw, struct clk_regmap_fractional_divider, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) clk_regmap_fractional_divider_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 					  unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	struct clk_regmap_fractional_divider *fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 			to_clk_regmap_fractional_divider(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	unsigned long m, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	u64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	regmap_read(fd->regmap, fd->reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	m = (val & fd->mmask) >> fd->mshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	n = (val & fd->nmask) >> fd->nshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	if (!n || !m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	ret = (u64)parent_rate * m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	do_div(ret, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	return ret;
^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 void clk_regmap_fractional_divider_approximation(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		unsigned long rate, unsigned long *parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		unsigned long *m, unsigned long *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct clk_regmap_fractional_divider *fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 			to_clk_regmap_fractional_divider(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	unsigned long p_rate, p_parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct clk_hw *p_parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	unsigned long scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		p_parent_rate = clk_hw_get_rate(p_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		*parent_rate = p_parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	 * Get rate closer to *parent_rate to guarantee there is no overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	 * for m and n. In the result it will be the nearest rate left shifted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	 * by (scale - fd->nwidth) bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	scale = fls_long(*parent_rate / rate - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (scale > fd->nwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		rate <<= scale - fd->nwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	rational_best_approximation(rate, *parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 				    GENMASK(fd->mwidth - 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 				    GENMASK(fd->nwidth - 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				    m, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) clk_regmap_fractional_divider_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 					 unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned long m, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	u64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return *parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (rate >= *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return *parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	clk_regmap_fractional_divider_approximation(hw, rate, parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 						    &m, &n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	ret = (u64)*parent_rate * m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	do_div(ret, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) clk_regmap_fractional_divider_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 				       unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct clk_regmap_fractional_divider *fd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			to_clk_regmap_fractional_divider(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	unsigned long m, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	rational_best_approximation(rate, parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			&m, &n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	dev_dbg(fd->dev, "%s: parent_rate=%ld, m=%ld, n=%ld, rate=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		clk_hw_get_name(hw), parent_rate, m, n, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	regmap_read(fd->regmap, fd->reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	val &= ~(fd->mmask | fd->nmask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	val |= (m << fd->mshift) | (n << fd->nshift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return regmap_write(fd->regmap, fd->reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) const struct clk_ops clk_regmap_fractional_divider_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	.recalc_rate = clk_regmap_fractional_divider_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	.round_rate = clk_regmap_fractional_divider_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	.set_rate = clk_regmap_fractional_divider_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) EXPORT_SYMBOL_GPL(clk_regmap_fractional_divider_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct clk *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) devm_clk_regmap_register_fractional_divider(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 					    const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 					    const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 					    struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 					    u32 reg, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct clk_regmap_fractional_divider *fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	fd = devm_kzalloc(dev, sizeof(*fd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (!fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	init.ops = &clk_regmap_fractional_divider_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	init.parent_names = (parent_name ? &parent_name : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	init.num_parents = (parent_name ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	fd->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	fd->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	fd->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	fd->mshift = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	fd->mwidth = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	fd->mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	fd->nshift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	fd->nwidth = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	fd->nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	fd->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	return devm_clk_register(dev, &fd->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) EXPORT_SYMBOL_GPL(devm_clk_regmap_register_fractional_divider);