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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * mmp mix(div and mux) clock operation source file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2014 Marvell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Chao Xie <chao.xie@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * The mix clock is a clock combined mux and div type clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Because the div field and mux field need to be set at same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * time, we can not divide it into 2 types of clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define to_clk_mix(hw)	container_of(hw, struct mmp_clk_mix, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static unsigned int _get_maxdiv(struct mmp_clk_mix *mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	unsigned int div_mask = (1 << mix->reg_info.width_div) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	unsigned int maxdiv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct clk_div_table *clkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		return div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		return 1 << div_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	if (mix->div_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		for (clkt = mix->div_table; clkt->div; clkt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 			if (clkt->div > maxdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 				maxdiv = clkt->div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		return maxdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	return div_mask + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	struct clk_div_table *clkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		return 1 << val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (mix->div_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		for (clkt = mix->div_table; clkt->div; clkt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			if (clkt->val == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 				return clkt->div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		if (clkt->div == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	return val + 1;
^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) static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	int num_parents = clk_hw_get_num_parents(&mix->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (mix->mux_flags & CLK_MUX_INDEX_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return ffs(val) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (mix->mux_flags & CLK_MUX_INDEX_ONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		return val - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (mix->mux_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		for (i = 0; i < num_parents; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			if (mix->mux_table[i] == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 				return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		if (i == num_parents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) static unsigned int _get_div_val(struct mmp_clk_mix *mix, unsigned int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	struct clk_div_table *clkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		return __ffs(div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (mix->div_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		for (clkt = mix->div_table; clkt->div; clkt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			if (clkt->div == div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				return clkt->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		if (clkt->div == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	return div - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static unsigned int _get_mux_val(struct mmp_clk_mix *mix, unsigned int mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (mix->mux_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		return mix->mux_table[mux];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static void _filter_clk_table(struct mmp_clk_mix *mix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 				struct mmp_clk_mix_clk_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				unsigned int table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	struct mmp_clk_mix_clk_table *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	struct clk_hw *parent, *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	unsigned long parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	hw = &mix->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	for (i = 0; i < table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		item = &table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		parent = clk_hw_get_parent_by_index(hw, item->parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (parent_rate % item->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			item->valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			item->divisor = parent_rate / item->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			item->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			unsigned int change_mux, unsigned int change_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	u8 width, shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	u32 mux_div, fc_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	int ret, timeout = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (!change_mux && !change_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		spin_lock_irqsave(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (mix->type == MMP_CLK_MIX_TYPE_V1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		|| mix->type == MMP_CLK_MIX_TYPE_V2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		mux_div = readl(ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		mux_div = readl(ri->reg_clk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (change_div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		width = ri->width_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		shift = ri->shift_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		mux_div &= ~MMP_CLK_BITS_MASK(width, shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		mux_div |= MMP_CLK_BITS_SET_VAL(div_val, width, shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (change_mux) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		width = ri->width_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		shift = ri->shift_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		mux_div &= ~MMP_CLK_BITS_MASK(width, shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		mux_div |= MMP_CLK_BITS_SET_VAL(mux_val, width, shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (mix->type == MMP_CLK_MIX_TYPE_V1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		writel(mux_div, ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	} else if (mix->type == MMP_CLK_MIX_TYPE_V2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		mux_div |= (1 << ri->bit_fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		writel(mux_div, ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			fc_req = readl(ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			timeout--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			if (!(fc_req & (1 << ri->bit_fc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		} while (timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		if (timeout == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			pr_err("%s:%s cannot do frequency change\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 				__func__, clk_hw_get_name(&mix->hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		fc_req = readl(ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		fc_req |= 1 << ri->bit_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		writel(fc_req, ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		writel(mux_div, ri->reg_clk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		fc_req &= ~(1 << ri->bit_fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		spin_unlock_irqrestore(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 				      struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct mmp_clk_mix_clk_table *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct clk_hw *parent, *parent_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	unsigned long parent_rate, mix_rate, mix_rate_best, parent_rate_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	unsigned long gap, gap_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	u32 div_val_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	unsigned int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	mix_rate_best = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	parent_rate_best = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	gap_best = ULONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	parent_best = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (mix->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		for (i = 0; i < mix->table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			item = &mix->table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			if (item->valid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			parent = clk_hw_get_parent_by_index(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 							item->parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			mix_rate = parent_rate / item->divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			gap = abs(mix_rate - req->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			if (!parent_best || gap < gap_best) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				parent_best = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 				parent_rate_best = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				mix_rate_best = mix_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				gap_best = gap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 				if (gap_best == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 					goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			parent = clk_hw_get_parent_by_index(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			div_val_max = _get_maxdiv(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 			for (j = 0; j < div_val_max; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				div = _get_div(mix, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				mix_rate = parent_rate / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				gap = abs(mix_rate - req->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 				if (!parent_best || gap < gap_best) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 					parent_best = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 					parent_rate_best = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 					mix_rate_best = mix_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 					gap_best = gap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 					if (gap_best == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 						goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (!parent_best)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	req->best_parent_rate = parent_rate_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	req->best_parent_hw = parent_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	req->rate = mix_rate_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 						unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 						unsigned long parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 						u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	unsigned int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	u32 div_val, mux_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	div = parent_rate / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	div_val = _get_div_val(mix, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	mux_val = _get_mux_val(mix, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return _set_rate(mix, mux_val, div_val, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static u8 mmp_clk_mix_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	u32 mux_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	u8 width, shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	u32 mux_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		spin_lock_irqsave(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	if (mix->type == MMP_CLK_MIX_TYPE_V1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		|| mix->type == MMP_CLK_MIX_TYPE_V2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		mux_div = readl(ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		mux_div = readl(ri->reg_clk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		spin_unlock_irqrestore(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	width = mix->reg_info.width_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	shift = mix->reg_info.shift_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	mux_val = MMP_CLK_BITS_GET_VAL(mux_div, width, shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	return _get_mux(mix, mux_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static unsigned long mmp_clk_mix_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 					unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	u32 mux_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	u8 width, shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	unsigned int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		spin_lock_irqsave(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (mix->type == MMP_CLK_MIX_TYPE_V1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		|| mix->type == MMP_CLK_MIX_TYPE_V2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		mux_div = readl(ri->reg_clk_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		mux_div = readl(ri->reg_clk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (mix->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		spin_unlock_irqrestore(mix->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	width = mix->reg_info.width_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	shift = mix->reg_info.shift_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	div = _get_div(mix, MMP_CLK_BITS_GET_VAL(mux_div, width, shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	return parent_rate / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static int mmp_clk_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	struct mmp_clk_mix_clk_table *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	u32 div_val, mux_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	if (mix->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		for (i = 0; i < mix->table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			item = &mix->table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			if (item->valid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 			if (item->parent_index == index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		if (i < mix->table_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			div_val = _get_div_val(mix, item->divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			mux_val = _get_mux_val(mix, item->parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		mux_val = _get_mux_val(mix, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		div_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	return _set_rate(mix, mux_val, div_val, 1, div_val ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 				unsigned long best_parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	struct mmp_clk_mix_clk_table *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	unsigned long parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	unsigned int best_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	struct clk_hw *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	best_divisor = best_parent_rate / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (mix->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		for (i = 0; i < mix->table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			item = &mix->table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			if (item->valid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			parent = clk_hw_get_parent_by_index(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 							item->parent_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 			if (parent_rate == best_parent_rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 				&& item->divisor == best_divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		if (i < mix->table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			return _set_rate(mix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 					_get_mux_val(mix, item->parent_index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 					_get_div_val(mix, item->divisor),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 					1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			parent = clk_hw_get_parent_by_index(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 			parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			if (parent_rate == best_parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		if (i < clk_hw_get_num_parents(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			return _set_rate(mix, _get_mux_val(mix, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 					_get_div_val(mix, best_divisor), 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int mmp_clk_mix_init(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	struct mmp_clk_mix *mix = to_clk_mix(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	if (mix->table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		_filter_clk_table(mix, mix->table, mix->table_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) const struct clk_ops mmp_clk_mix_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	.determine_rate = mmp_clk_mix_determine_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	.set_rate_and_parent = mmp_clk_mix_set_rate_and_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	.set_rate = mmp_clk_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	.set_parent = mmp_clk_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	.get_parent = mmp_clk_mix_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	.recalc_rate = mmp_clk_mix_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	.init = mmp_clk_mix_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct clk *mmp_clk_register_mix(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 					const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 					const char * const *parent_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 					u8 num_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 					unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 					struct mmp_clk_mix_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 					spinlock_t *lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	struct mmp_clk_mix *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	size_t table_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	if (!mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	init.flags = flags | CLK_GET_RATE_NOCACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	init.parent_names = parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	init.ops = &mmp_clk_mix_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	memcpy(&mix->reg_info, &config->reg_info, sizeof(config->reg_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	if (config->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		table_bytes = sizeof(*config->table) * config->table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (!mix->table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			goto free_mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		mix->table_size = config->table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	if (config->mux_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		table_bytes = sizeof(u32) * num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		mix->mux_table = kmemdup(config->mux_table, table_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 					 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		if (!mix->mux_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 			kfree(mix->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			goto free_mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	mix->div_flags = config->div_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	mix->mux_flags = config->mux_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	mix->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	mix->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	if (config->reg_info.bit_fc >= 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		mix->type = MMP_CLK_MIX_TYPE_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	else if (config->reg_info.reg_clk_sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		mix->type = MMP_CLK_MIX_TYPE_V3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		mix->type = MMP_CLK_MIX_TYPE_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	clk = clk_register(dev, &mix->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		kfree(mix->mux_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		kfree(mix->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		kfree(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) free_mix:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	kfree(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }