mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
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:
commit
8b9d9e9f8e
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user