clk: qcom: clk-pll: Round off req_rate in determine rate

The current PLL set rate does not support determining
the L val at runtime. This updates the determine rate
by doing round off for this requirement. Add support
for the list_register to clk_pll_ops.

Change-Id: Ica85e1408fd7d1b2154b01150728419dbb81de90
Signed-off-by: Chetan C R <cchinnad@codeaurora.org>
Signed-off-by: Veera Vegivada <vvegivad@codeaurora.org>
This commit is contained in:
Veera Vegivada 2021-04-14 15:40:31 +05:30
commit 674820ec74
2 changed files with 79 additions and 3 deletions

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
* Copyright (c) 2013, 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@ -14,6 +14,7 @@
#include <asm/div64.h>
#include "clk-debug.h"
#include "clk-pll.h"
#include "common.h"
@ -130,7 +131,8 @@ clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
f = find_freq(pll->freq_tbl, req->rate);
if (!f)
req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
req->rate = DIV_ROUND_UP_ULL(req->rate, req->best_parent_rate)
* req->best_parent_rate;
else
req->rate = f->freq;
@ -334,3 +336,76 @@ const struct clk_ops clk_pll_sr2_ops = {
.determine_rate = clk_pll_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
static int
clk_pll_hf_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
{
struct clk_pll *pll = to_clk_pll(hw);
bool enabled;
u32 mode, l_val;
u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
l_val = rate / prate;
regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
enabled = (mode & enable_mask) == enable_mask;
if (enabled)
clk_pll_disable(hw);
regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, l_val);
regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, 0);
regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, 1);
if (enabled)
clk_pll_sr2_enable(hw);
return 0;
}
static void clk_pll_hf_list_registers(struct seq_file *f, struct clk_hw *hw)
{
struct clk_pll *pll = to_clk_pll(hw);
int size, i, val;
static struct clk_register_data data[] = {
{"PLL_MODE", 0x0},
{"PLL_L_VAL", 0x4},
{"PLL_M_VAL", 0x8},
{"PLL_N_VAL", 0xC},
{"PLL_USER_CTL", 0x10},
{"PLL_CONFIG_CTL", 0x14},
{"PLL_STATUS_CTL", 0x1C},
};
size = ARRAY_SIZE(data);
for (i = 0; i < size; i++) {
regmap_read(pll->clkr.regmap, pll->mode_reg + data[i].offset,
&val);
clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val);
}
}
static struct clk_regmap_ops clk_pll_hf_regmap_ops = {
.list_registers = &clk_pll_hf_list_registers,
};
static void clk_pll_hf_init(struct clk_hw *hw)
{
struct clk_regmap *rclk = to_clk_regmap(hw);
if (!rclk->ops)
rclk->ops = &clk_pll_hf_regmap_ops;
}
const struct clk_ops clk_pll_hf_ops = {
.enable = clk_pll_sr2_enable,
.disable = clk_pll_disable,
.set_rate = clk_pll_hf_set_rate,
.recalc_rate = clk_pll_recalc_rate,
.determine_rate = clk_pll_determine_rate,
.debug_init = clk_common_debug_init,
.init = clk_pll_hf_init,
};
EXPORT_SYMBOL(clk_pll_hf_ops);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
* Copyright (c) 2013, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef __QCOM_CLK_PLL_H__
@ -55,6 +55,7 @@ struct clk_pll {
extern const struct clk_ops clk_pll_ops;
extern const struct clk_ops clk_pll_vote_ops;
extern const struct clk_ops clk_pll_sr2_ops;
extern const struct clk_ops clk_pll_hf_ops;
#define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)