]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
ARM: tegra: bbc: provide api to save and restore iso
authorVinayak Pane <vpane@nvidia.com>
Thu, 9 May 2013 00:48:26 +0000 (17:48 -0700)
committerDan Willemsen <dwillemsen@nvidia.com>
Sat, 14 Sep 2013 20:14:56 +0000 (13:14 -0700)
The ISO request from BBC must be cleared when BBC is hibernated.
And the ISO bandwidth should be restored back when BBC wakes up.
Adding APIs in bbc proxy driver to support above need to be
controlled from bb power driver.

Bug 1284833

Change-Id: I8313bb1fd529a2f5a0c6f32bac5a5e51bf78509b
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/226866
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Stephane Dion <sdion@nvidia.com>
Reviewed-by: Steve Lin <stlin@nvidia.com>
arch/arm/mach-tegra/include/mach/tegra_bbc_proxy.h
arch/arm/mach-tegra/tegra_bb.c
arch/arm/mach-tegra/tegra_bbc_proxy.c

index d7bddac7dda9ad020757421091554dceb5634c49..f202c89c321eaa9155f9c07e9c48376915c8caf6 100644 (file)
@@ -38,4 +38,7 @@ int tegra_bbc_proxy_edp_request(struct device *dev, u32 mode, u32 state,
 int tegra_bbc_proxy_bw_register(struct device *dev, u32 bw);
 int tegra_bbc_proxy_bw_request(struct device *dev, u32 mode, u32 bw, u32 lt,
                                u32 margin);
-#endif /* __MACH_TEGRA_BBC_PROXY_H */
+
+int tegra_bbc_proxy_restore_iso(struct device *dev);
+int tegra_bbc_proxy_clear_iso(struct device *dev);
+#endif /* __MAC_TEGRA_BBC_PROXY_H */
index 722b57588fea52e118f980a1d150e6f64abc41c0..e73d9121a43e8b84cf9194030e6d41a800b5f2ea 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <mach/clk.h>
 #include <mach/tegra_bb.h>
+#include <mach/tegra_bbc_proxy.h>
 #include <linux/platform_data/nvshm.h>
 
 #include "clock.h"
@@ -133,6 +134,7 @@ struct tegra_bb {
        struct workqueue_struct *workqueue;
        struct work_struct work;
        struct clk *emc_clk;
+       struct device *proxy_dev;
 };
 
 static unsigned long emc_min_freq;
@@ -898,6 +900,9 @@ static void tegra_bb_emc_dvfs(struct work_struct *work)
                clk_set_rate(bb->emc_clk, emc_min_freq);
                pr_debug("bbc setting floor to %lu\n", emc_min_freq/1000000);
 
+               /* restore iso bw request*/
+               tegra_bbc_proxy_restore_iso(bb->proxy_dev);
+
                /* reenable pmc_wake_det irq */
                tegra_bb_enable_pmc_wake();
                irq_set_irq_type(INT_PMC_WAKE_INT, IRQF_TRIGGER_HIGH);
@@ -911,6 +916,9 @@ static void tegra_bb_emc_dvfs(struct work_struct *work)
                bb->prev_state = bb->state;
                spin_unlock_irqrestore(&bb->lock, flags);
 
+               /* remove iso bandwitdh request from bbc */
+               tegra_bbc_proxy_clear_iso(bb->proxy_dev);
+
                /* going from high to 0 */
                if (emc_flags & EMC_DSR)
                        tegra_emc_dsr_override(TEGRA_EMC_DSR_NORMAL);
@@ -1189,6 +1197,15 @@ static int tegra_bb_probe(struct platform_device *pdev)
 
        tegra_bb_set_emc_floor(BBC_MC_MIN_FREQ, 0);
 
+       /* get bbc proxy device struct, it should be registered
+        * before this driver.
+        */
+       bb->proxy_dev = bus_find_device_by_name(&platform_bus_type,  NULL,
+                               "tegra_bbc_proxy");
+       if (!bb->proxy_dev)
+               dev_warn(&pdev->dev, "%s: bbc proxy device not found!\n",
+                               __func__);
+
        ret = request_irq(bb->mem_req_soon, tegra_bb_mem_req_soon,
                        IRQF_TRIGGER_RISING, "bb_mem_req_soon", bb);
        if (ret) {
index 053f9d2a4204a7ee049b1b8829a7ebe9e1f55dc7..0aee23c92317dcc3d31dcfe8167e7966dc85a5a5 100644 (file)
@@ -44,6 +44,9 @@ struct tegra_bbc_proxy {
        unsigned int i_thresh_lte_adjperiod; /* lte i_thresh adj period */
        unsigned int threshold; /* current edp threshold value */
        unsigned int state; /* current edp state value */
+       /* last iso settings with proxy driver */
+       unsigned int last_bw;
+       unsigned int last_ult;
        struct work_struct edp_work;
        struct mutex edp_lock; /* lock for edp operations */
 
@@ -389,6 +392,9 @@ static ssize_t iso_reserve_store(struct device *dev,
        if (!ret)
                dev_err(dev, "can't reserve iso bw\n");
 
+       bbc->last_bw = bw;
+       bbc->last_ult = ult;
+
        tegra_set_latency_allowance(TEGRA_LA_BBCR, bw / 1000);
        tegra_set_latency_allowance(TEGRA_LA_BBCW, bw / 1000);
 
@@ -460,6 +466,9 @@ int tegra_bbc_proxy_bw_request(struct device *dev, u32 mode, u32 bw, u32 lt,
        struct tegra_bbc_proxy *bbc = dev_get_drvdata(dev);
 
        mutex_lock(&bbc->iso_lock);
+       bbc->last_bw = bw;
+       bbc->last_ult = lt;
+
        ret = bbc_bw_request_unlocked(dev, mode, bw, lt, margin);
        mutex_unlock(&bbc->iso_lock);
 
@@ -467,6 +476,40 @@ int tegra_bbc_proxy_bw_request(struct device *dev, u32 mode, u32 bw, u32 lt,
 }
 EXPORT_SYMBOL(tegra_bbc_proxy_bw_request);
 
+int tegra_bbc_proxy_restore_iso(struct device *dev)
+{
+       int ret;
+       struct tegra_bbc_proxy *bbc = dev_get_drvdata(dev);
+
+       if (!bbc)
+               return -EINVAL;
+
+       mutex_lock(&bbc->iso_lock);
+       ret = bbc_bw_request_unlocked(dev, 0, bbc->last_bw,
+                                       bbc->last_ult, bbc->margin);
+       mutex_unlock(&bbc->iso_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_bbc_proxy_restore_iso);
+
+int tegra_bbc_proxy_clear_iso(struct device *dev)
+{
+       int ret;
+       struct tegra_bbc_proxy *bbc = dev_get_drvdata(dev);
+
+       if (!bbc)
+               return -EINVAL;
+
+       mutex_lock(&bbc->iso_lock);
+       ret = bbc_bw_request_unlocked(dev, 0, 0,
+                                       1000, bbc->margin);
+       mutex_unlock(&bbc->iso_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_bbc_proxy_clear_iso);
+
 static ssize_t iso_res_realize_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
@@ -499,6 +542,9 @@ static ssize_t iso_res_realize_store(struct device *dev,
        }
 
        mutex_lock(&bbc->iso_lock);
+       bbc->last_bw = bw;
+       bbc->last_ult = ult;
+
        ret = bbc_bw_request_unlocked(dev, 0, bw, ult, bbc->margin);
        mutex_unlock(&bbc->iso_lock);