summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-09-28 20:36:06 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 01:13:05 -0700
commit81b47eb8690c8ac42cf1acbf66d13462e3ecd519 (patch)
tree5ea1c61d0101e9c22a4a5e763fd7c72d8d308c8c /drivers/spi
parentb9aecc25367c9fb424aad24da63d467eb854dab4 (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.c59
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;
}