^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) }