clk: tegra: Changes for v5.19-rc1

This contains a boot time optimization for Tegra chips with BPMP and a
 switch from .round_rate() to .determine_rate() to take into account any
 maximum rate that might have been set.
 
 Other than that this contains a fix for a DFLL regression on Tegra210
 and kerneldoc fixups to avoid build warnings.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmJ1KuUTHHRyZWRpbmdA
 bnZpZGlhLmNvbQAKCRDdI6zXfz6zoXXwD/9Vs+njCehoJeiQno5fPMBzISFCrHka
 kP9R3NoTiaEfX8ujIqlBXJKFI8z7/C4j2z8lpgO/tcjoJLlv6B3Dt5KBak6WEThJ
 511e9b1RCR4UlOb6gks1aq63ise1ZEBUBXXaOpwliC9l8WL6JiORunWRVqb7NQ2s
 v9lWBRhvBY5/GTotaBmn0E3zVc1b46m/GZ62xIgsj6RGoJQrN6QRPYsKHKMdgxz8
 el9LKVN+8RJcRTG1DpXszJMdkW6WtuWgAS3+olXDA2gmGqvp6pcfMeWypGomvgBw
 4sjBawd6ztxDgUo46K9xox81Bs479bHWO3CfFJiG54jVu7n092b85a52jH3RPkv7
 X+sbEBs7sKVRJK0ce9BjpfqxfhV5bg59NaNKNZ/nPBOh9JjaqXxwKf+Iq8u3NuDx
 GVCTCIG3lz9zl4nSqoWskKg+YkopmZbp93mnKnRwyEd1lzY5qpPMfVYyZBGjm/xJ
 G8fLvOcvDmTUxHVnSEVxa+GFh6cRRRKNE7+VIrxwD5VaIB16yvoZ1notKrnoGvdS
 BsPsOHq8idQGqx8PqBtSI9utx4Y6szXwL3EJmE94zNdjgauMiW9vuszGVn9gQvb+
 UvG8zAdc8P9GB52W76vU2U1KYtBuPWXEv6TiAdxboXxPZInQnFwISmh1GlFXRgM/
 /WzebGRN8gfmLw==
 =fV6o
 -----END PGP SIGNATURE-----

Merge tag 'for-5.19-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-tegra

Pull Tegra clk driver updates from Thierry Reding:

This contains a boot time optimization for Tegra chips with BPMP and a
switch from .round_rate() to .determine_rate() to take into account any
maximum rate that might have been set.

Other than that this contains a fix for a DFLL regression on Tegra210
and kerneldoc fixups to avoid build warnings.

* tag 'for-5.19-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  clk: tegra: Update kerneldoc to match prototypes
  clk: tegra: Replace .round_rate() with .determine_rate()
  clk: tegra: Register clocks from root to leaf
  clk: tegra: Add missing reset deassertion
This commit is contained in:
Stephen Boyd 2022-05-16 23:53:06 -07:00
commit 8b9d9e9f8e
2 changed files with 82 additions and 25 deletions

View File

@ -164,15 +164,18 @@ static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
return response.rate;
}
static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int tegra_bpmp_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *rate_req)
{
struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
struct cmd_clk_round_rate_response response;
struct cmd_clk_round_rate_request request;
struct tegra_bpmp_clk_message msg;
unsigned long rate;
int err;
rate = min(max(rate_req->rate, rate_req->min_rate), rate_req->max_rate);
memset(&request, 0, sizeof(request));
request.rate = min_t(u64, rate, S64_MAX);
@ -188,7 +191,9 @@ static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
if (err < 0)
return err;
return response.rate;
rate_req->rate = (unsigned long)response.rate;
return 0;
}
static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index)
@ -290,7 +295,7 @@ static const struct clk_ops tegra_bpmp_clk_rate_ops = {
.unprepare = tegra_bpmp_clk_unprepare,
.is_prepared = tegra_bpmp_clk_is_prepared,
.recalc_rate = tegra_bpmp_clk_recalc_rate,
.round_rate = tegra_bpmp_clk_round_rate,
.determine_rate = tegra_bpmp_clk_determine_rate,
.set_rate = tegra_bpmp_clk_set_rate,
};
@ -299,7 +304,7 @@ static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
.unprepare = tegra_bpmp_clk_unprepare,
.is_prepared = tegra_bpmp_clk_is_prepared,
.recalc_rate = tegra_bpmp_clk_recalc_rate,
.round_rate = tegra_bpmp_clk_round_rate,
.determine_rate = tegra_bpmp_clk_determine_rate,
.set_parent = tegra_bpmp_clk_set_parent,
.get_parent = tegra_bpmp_clk_get_parent,
.set_rate = tegra_bpmp_clk_set_rate,
@ -448,15 +453,29 @@ static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
return count;
}
static unsigned int
tegra_bpmp_clk_id_to_index(const struct tegra_bpmp_clk_info *clocks,
unsigned int num_clocks, unsigned int id)
{
unsigned int i;
for (i = 0; i < num_clocks; i++)
if (clocks[i].id == id)
return i;
return UINT_MAX;
}
static const struct tegra_bpmp_clk_info *
tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks,
unsigned int num_clocks, unsigned int id)
{
unsigned int i;
for (i = 0; i < num_clocks; i++)
if (clocks[i].id == id)
return &clocks[i];
i = tegra_bpmp_clk_id_to_index(clocks, num_clocks, id);
if (i < num_clocks)
return &clocks[i];
return NULL;
}
@ -539,31 +558,57 @@ tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
return clk;
}
static void tegra_bpmp_register_clocks_one(struct tegra_bpmp *bpmp,
struct tegra_bpmp_clk_info *infos,
unsigned int i,
unsigned int count)
{
unsigned int j;
struct tegra_bpmp_clk_info *info;
struct tegra_bpmp_clk *clk;
if (bpmp->clocks[i]) {
/* already registered */
return;
}
info = &infos[i];
for (j = 0; j < info->num_parents; ++j) {
unsigned int p_id = info->parents[j];
unsigned int p_i = tegra_bpmp_clk_id_to_index(infos, count,
p_id);
if (p_i < count)
tegra_bpmp_register_clocks_one(bpmp, infos, p_i, count);
}
clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
if (IS_ERR(clk)) {
dev_err(bpmp->dev,
"failed to register clock %u (%s): %ld\n",
info->id, info->name, PTR_ERR(clk));
/* intentionally store the error pointer to
* bpmp->clocks[i] to avoid re-attempting the
* registration later
*/
}
bpmp->clocks[i] = clk;
}
static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
struct tegra_bpmp_clk_info *infos,
unsigned int count)
{
struct tegra_bpmp_clk *clk;
unsigned int i;
bpmp->num_clocks = count;
bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL);
bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(struct tegra_bpmp_clk), GFP_KERNEL);
if (!bpmp->clocks)
return -ENOMEM;
for (i = 0; i < count; i++) {
struct tegra_bpmp_clk_info *info = &infos[i];
clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
if (IS_ERR(clk)) {
dev_err(bpmp->dev,
"failed to register clock %u (%s): %ld\n",
info->id, info->name, PTR_ERR(clk));
continue;
}
bpmp->clocks[i] = clk;
tegra_bpmp_register_clocks_one(bpmp, infos, i, count);
}
return 0;

View File

@ -271,6 +271,7 @@ struct tegra_dfll {
struct clk *ref_clk;
struct clk *i2c_clk;
struct clk *dfll_clk;
struct reset_control *dfll_rst;
struct reset_control *dvco_rst;
unsigned long ref_rate;
unsigned long i2c_clk_rate;
@ -666,7 +667,7 @@ static int dfll_force_output(struct tegra_dfll *td, unsigned int out_sel)
}
/**
* dfll_load_lut - load the voltage lookup table
* dfll_load_i2c_lut - load the voltage lookup table
* @td: struct tegra_dfll *
*
* Load the voltage-to-PMIC register value lookup table into the DFLL
@ -897,7 +898,7 @@ static void dfll_set_frequency_request(struct tegra_dfll *td,
}
/**
* tegra_dfll_request_rate - set the next rate for the DFLL to tune to
* dfll_request_rate - set the next rate for the DFLL to tune to
* @td: DFLL instance
* @rate: clock rate to target
*
@ -1005,7 +1006,7 @@ static void dfll_set_open_loop_config(struct tegra_dfll *td)
}
/**
* tegra_dfll_lock - switch from open-loop to closed-loop mode
* dfll_lock - switch from open-loop to closed-loop mode
* @td: DFLL instance
*
* Switch from OPEN_LOOP state to CLOSED_LOOP state. Returns 0 upon success,
@ -1046,7 +1047,7 @@ static int dfll_lock(struct tegra_dfll *td)
}
/**
* tegra_dfll_unlock - switch from closed-loop to open-loop mode
* dfll_unlock - switch from closed-loop to open-loop mode
* @td: DFLL instance
*
* Switch from CLOSED_LOOP state to OPEN_LOOP state. Returns 0 upon success,
@ -1464,6 +1465,7 @@ static int dfll_init(struct tegra_dfll *td)
return -EINVAL;
}
reset_control_deassert(td->dfll_rst);
reset_control_deassert(td->dvco_rst);
ret = clk_prepare(td->ref_clk);
@ -1509,6 +1511,7 @@ static int dfll_init(struct tegra_dfll *td)
clk_unprepare(td->ref_clk);
reset_control_assert(td->dvco_rst);
reset_control_assert(td->dfll_rst);
return ret;
}
@ -1530,6 +1533,7 @@ int tegra_dfll_suspend(struct device *dev)
}
reset_control_assert(td->dvco_rst);
reset_control_assert(td->dfll_rst);
return 0;
}
@ -1548,6 +1552,7 @@ int tegra_dfll_resume(struct device *dev)
{
struct tegra_dfll *td = dev_get_drvdata(dev);
reset_control_deassert(td->dfll_rst);
reset_control_deassert(td->dvco_rst);
pm_runtime_get_sync(td->dev);
@ -1951,6 +1956,12 @@ int tegra_dfll_register(struct platform_device *pdev,
td->soc = soc;
td->dfll_rst = devm_reset_control_get_optional(td->dev, "dfll");
if (IS_ERR(td->dfll_rst)) {
dev_err(td->dev, "couldn't get dfll reset\n");
return PTR_ERR(td->dfll_rst);
}
td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
if (IS_ERR(td->dvco_rst)) {
dev_err(td->dev, "couldn't get dvco reset\n");
@ -2087,6 +2098,7 @@ struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev)
clk_unprepare(td->i2c_clk);
reset_control_assert(td->dvco_rst);
reset_control_assert(td->dfll_rst);
return td->soc;
}