Skip to content

Commit

Permalink
Merge tag 'for-5.19-clk' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Stephen Boyd committed May 17, 2022
2 parents 3123109 + 6f6baf6 commit 8b9d9e9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 25 deletions.
87 changes: 66 additions & 21 deletions drivers/clk/tegra/clk-bpmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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)
Expand Down Expand Up @@ -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,
};

Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
20 changes: 16 additions & 4 deletions drivers/clk/tegra/clk-dfll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 8b9d9e9

Please sign in to comment.