]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
tegra: nvadsp: Use table to choose frequency
authorAjay Nandakumar <anandakumarm@nvidia.com>
Mon, 29 Sep 2014 07:03:58 +0000 (12:33 +0530)
committerNitin Kumbhar <nkumbhar@nvidia.com>
Tue, 7 Oct 2014 09:19:43 +0000 (02:19 -0700)
Use a frequency table so that the adsp clk frequency is a multiple of
the lowest frequency. This is so that timer prescalar values set does
not result in errors.

Bug 200007507

Change-Id: I03e8dc055e74cada13221d76126d77e006f2aab5
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>
Reviewed-on: http://git-master/r/542548
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Puneet Saxena <puneets@nvidia.com>
Tested-by: Puneet Saxena <puneets@nvidia.com>
Reviewed-by: Nitin Kumbhar <nkumbhar@nvidia.com>
drivers/platform/tegra/nvadsp/adsp_dfs.c
drivers/platform/tegra/nvadsp/dev.c
drivers/platform/tegra/nvadsp/dev.h
drivers/platform/tegra/nvadsp/os.c

index 2e8625a29668b00615c4f71cf67968dc7a0729dc..ce723dea085e50b4d7e7c2a03c64f29c4a065c6b 100644 (file)
@@ -39,6 +39,20 @@ enum adsp_dfs_reply {
        NACK,
 };
 
+/*
+ * Freqency in Hz.The frequency always needs to be a multiple of 12.8 Mhz and
+ * should be extended with a slab 51.2 Mhz.
+ */
+static unsigned long adsp_cpu_freq_table[] = {
+       51200000,
+       102400000,
+       153600000,
+       204800000,
+       256000000,
+       307200000,
+       358400000,
+};
+
 struct adsp_dfs_policy {
        bool enable;
  /*
@@ -91,6 +105,33 @@ static struct adsp_dfs_policy dfs_policy =  {
                .notifier_call = adsp_dfs_rc_callback,
        },
 };
+
+static unsigned long adsp_get_target_freq(unsigned long tfreq, int *index)
+{
+       int i;
+       int size = sizeof(adsp_cpu_freq_table) / sizeof(adsp_cpu_freq_table[0]);
+
+       if (tfreq <= adsp_cpu_freq_table[0]) {
+               *index = 0;
+               return adsp_cpu_freq_table[0];
+       }
+
+       if (tfreq >= adsp_cpu_freq_table[size - 1]) {
+               *index = size - 1;
+               return adsp_cpu_freq_table[size - 1];
+       }
+
+       for (i = 1; i < size; i++) {
+               if ((tfreq <= adsp_cpu_freq_table[i]) &&
+                               (tfreq > adsp_cpu_freq_table[i - 1])) {
+                       *index = i;
+                       return adsp_cpu_freq_table[i];
+               }
+       }
+
+       return 0;
+}
+
 /**
  * update_policy - update adsp freq and ask adsp to work post change
  *             in freq tasks
@@ -106,12 +147,19 @@ static unsigned long update_policy(unsigned long tfreq)
 {
        enum adsp_dfs_reply reply;
        struct nvadsp_mbox *mbx = &policy->mbox;
-       int ret;
        unsigned long old_freq;
+       int index;
+       int ret;
 
        old_freq = policy->cur;
 
-       ret = clk_set_rate(policy->adsp_clk, tfreq * 1000);
+       tfreq = adsp_get_target_freq(tfreq * 1000, &index);
+       if (!tfreq) {
+               pr_info("unable set the target freq\n");
+               return 0;
+       }
+
+       ret = clk_set_rate(policy->adsp_clk, tfreq);
        if (ret) {
                pr_err("failed to set adsp freq:%d\n", ret);
                policy->update_freq_flag = false;
@@ -123,8 +171,11 @@ static unsigned long update_policy(unsigned long tfreq)
        mutex_lock(&policy_mutex);
 
        pr_debug("sending change in freq:%lu\n", tfreq);
-       /* Ask adsp to do action upon change in freq */
-       ret = nvadsp_mbox_send(mbx, tfreq,
+       /*
+        * Ask adsp to do action upon change in freq. ADSP and Host need to
+        * maintain the same freq table.
+        */
+       ret = nvadsp_mbox_send(mbx, index,
                                NVADSP_MBOX_SMSG, true, 100);
        if (ret) {
                pr_err("%s:host to adsp, mbox_send failure ....\n", __func__);
index a6f4d209dbc389f3f31a62d95d8582de6b2fa246..edac98dfe9dc8d04ed6a075f2cae2e286076ab1f 100644 (file)
@@ -162,6 +162,13 @@ int nvadsp_clocks_enable(struct platform_device *pdev)
        udelay(10);
        dev_dbg(dev, "adsp clock enabled and asserted\n");
 
+       drv_data->adsp_cpu_clk = clk_get_sys(NULL, "adsp_cpu");
+       if (IS_ERR_OR_NULL(drv_data->adsp_cpu_clk)) {
+               dev_err(dev, "unable to find adsp cpu clock\n");
+               ret = PTR_ERR(drv_data->adsp_cpu_clk);
+               goto end;
+       }
+
        drv_data->ape_uart_clk = clk_get_sys("uartape", NULL);
        if (IS_ERR_OR_NULL(drv_data->ape_uart_clk)) {
                dev_err(dev, "unable to find uart ape clk\n");
index 57c43d02ad3b3b93ccbcbc2da7ba728d0eb403d3..26ae375308ec9e5ae6acdffce3317f638b2fa95c 100644 (file)
@@ -85,6 +85,7 @@ struct nvadsp_drv_data {
 #endif
        struct clk *ape_clk;
        struct clk *adsp_clk;
+       struct clk *adsp_cpu_clk;
        struct clk *ape_uart_clk;
 
        struct nvadsp_pm_state state;
index 568047fe8d95e69f8bb4800be03f86ce41f44272..2bd195a906469db924d259c33a60b35cb2cf1674 100644 (file)
@@ -79,6 +79,8 @@
 
 #define LOGGER_TIMEOUT 20 /* in ms */
 
+#define LOAD_ADSP_FREQ 51200000lu /* in Hz */
+
 struct nvadsp_debug_log {
        struct device *dev;
        char *debug_ram_rdr;
@@ -691,6 +693,11 @@ int __nvadsp_os_start(void)
                     drv_data->state.evp,
                     AMC_EVP_SIZE);
 
+       if (drv_data->adsp_cpu_clk) {
+               dev_info(dev, "setting adsp cpu to %lu...\n", LOAD_ADSP_FREQ);
+               clk_set_rate(drv_data->adsp_cpu_clk, LOAD_ADSP_FREQ);
+       }
+
        dev_info(dev, "Starting ADSP OS...\n");
        if (drv_data->adsp_clk) {
                dev_info(dev, "deasserting adsp...\n");