diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-09-28 20:36:06 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 01:13:05 -0700 |
commit | 81b47eb8690c8ac42cf1acbf66d13462e3ecd519 (patch) | |
tree | 5ea1c61d0101e9c22a4a5e763fd7c72d8d308c8c /drivers/spi | |
parent | b9aecc25367c9fb424aad24da63d467eb854dab4 (diff) |
spi: tegra11: setclock source based on the speed
Change the clock source to reach the speed based on minimum power
and nearest require speed.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/139733
(cherry picked from commit 28102ea1efe53fabf033a3ef31797923c2fed77c)
Change-Id: I4150e97fdccb140fbf5b401a68d2ca4e9802e1ac
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/143268
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: R28b87a14a2c9ff8a5b94b2cc438f3a4dc16982f5
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-tegra11.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/spi/spi-tegra11.c b/drivers/spi/spi-tegra11.c index 1b37821ec3c9..8c86c6249253 100644 --- a/drivers/spi/spi-tegra11.c +++ b/drivers/spi/spi-tegra11.c @@ -644,6 +644,64 @@ static int spi_tegra_start_cpu_based_transfer( return 0; } +static void set_best_clk_source(struct spi_tegra_data *tspi, + unsigned long speed) +{ + long new_rate; + unsigned long err_rate; + int rate = speed; + unsigned int fin_err = speed; + int final_index = -1; + int count; + int ret; + struct clk *pclk; + unsigned long prate, crate, nrate; + unsigned long cdiv; + + if (!tspi->parent_clk_count || !tspi->parent_clk_list) + return; + + /* make sure divisor is more than min_div */ + pclk = clk_get_parent(tspi->clk); + prate = clk_get_rate(pclk); + crate = clk_get_rate(tspi->clk); + cdiv = DIV_ROUND_UP(prate, crate); + if (cdiv < tspi->min_div) { + nrate = DIV_ROUND_UP(prate, tspi->min_div); + clk_set_rate(tspi->clk, nrate); + } + + for (count = 0; count < tspi->parent_clk_count; ++count) { + if (!tspi->parent_clk_list[count].parent_clk) + continue; + ret = clk_set_parent(tspi->clk, + tspi->parent_clk_list[count].parent_clk); + if (ret < 0) { + dev_warn(&tspi->pdev->dev, + "Error in setting parent clk src %s\n", + tspi->parent_clk_list[count].name); + continue; + } + + new_rate = clk_round_rate(tspi->clk, rate); + if (new_rate < 0) + continue; + + err_rate = abs(new_rate - rate); + if (err_rate < fin_err) { + final_index = count; + fin_err = err_rate; + } + } + + if (final_index >= 0) { + dev_info(&tspi->pdev->dev, "Setting clk_src %s\n", + tspi->parent_clk_list[final_index].name); + clk_set_parent(tspi->clk, + tspi->parent_clk_list[final_index].parent_clk); + } +} + static void spi_tegra_start_transfer(struct spi_device *spi, struct spi_transfer *t, bool is_first_of_msg, bool is_single_xfer) @@ -665,6 +723,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi, if (!speed) speed = SPI_DEFAULT_SPEED; if (speed != tspi->cur_speed) { + set_best_clk_source(tspi, speed); clk_set_rate(tspi->clk, speed); tspi->cur_speed = speed; } |