diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch')
| -rw-r--r-- | extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch b/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch new file mode 100644 index 00000000..16335ccb --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | From 6fb7bd2b3da02e6e799d3c7661a1acb6572f9add Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Thara Gopinath <thara@ti.com> | ||
| 3 | Date: Wed, 18 Aug 2010 16:22:32 +0530 | ||
| 4 | Subject: [PATCH 14/20] OMAP3: Introduce custom set rate and get rate APIs for scalable devices | ||
| 5 | |||
| 6 | This patch also introduces omap3_mpu_set_rate, omap3_iva_set_rate, | ||
| 7 | omap3_l3_set_rate, omap3_mpu_get_rate, omap3_iva_get_rate, | ||
| 8 | omap3_l3_get_rate as device specific set rate and get rate | ||
| 9 | APIs for OMAP3 mpu, iva and l3_main devices. This patch also | ||
| 10 | calls into omap_device_populate_rate_fns during system init to register | ||
| 11 | various set_rate and get_rate APIs with the omap device layer | ||
| 12 | |||
| 13 | Signed-off-by: Thara Gopinath <thara@ti.com> | ||
| 14 | --- | ||
| 15 | arch/arm/mach-omap2/pm.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
| 16 | 1 files changed, 110 insertions(+), 0 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c | ||
| 19 | index d5a102c..94ab0dd 100644 | ||
| 20 | --- a/arch/arm/mach-omap2/pm.c | ||
| 21 | +++ b/arch/arm/mach-omap2/pm.c | ||
| 22 | @@ -14,6 +14,7 @@ | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/err.h> | ||
| 25 | #include <linux/opp.h> | ||
| 26 | +#include <linux/delay.h> | ||
| 27 | |||
| 28 | #include <plat/omap-pm.h> | ||
| 29 | #include <plat/omap_device.h> | ||
| 30 | @@ -22,6 +23,8 @@ | ||
| 31 | |||
| 32 | #include "powerdomain.h" | ||
| 33 | #include "clockdomain.h" | ||
| 34 | +#include "cm-regbits-34xx.h" | ||
| 35 | +#include "cm2xxx_3xxx.h" | ||
| 36 | #include "pm.h" | ||
| 37 | |||
| 38 | static struct omap_device_pm_latency *pm_lats; | ||
| 39 | @@ -31,6 +34,8 @@ static struct device *iva_dev; | ||
| 40 | static struct device *l3_dev; | ||
| 41 | static struct device *dsp_dev; | ||
| 42 | |||
| 43 | +static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk; | ||
| 44 | + | ||
| 45 | struct device *omap2_get_mpuss_device(void) | ||
| 46 | { | ||
| 47 | WARN_ON_ONCE(!mpu_dev); | ||
| 48 | @@ -56,6 +61,26 @@ struct device *omap4_get_dsp_device(void) | ||
| 49 | } | ||
| 50 | EXPORT_SYMBOL(omap4_get_dsp_device); | ||
| 51 | |||
| 52 | +static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult) | ||
| 53 | +{ | ||
| 54 | + unsigned long new_jiffy_l, new_jiffy_h; | ||
| 55 | + | ||
| 56 | + /* | ||
| 57 | + * Recalculate loops_per_jiffy. We do it this way to | ||
| 58 | + * avoid math overflow on 32-bit machines. Maybe we | ||
| 59 | + * should make this architecture dependent? If you have | ||
| 60 | + * a better way of doing this, please replace! | ||
| 61 | + * | ||
| 62 | + * new = old * mult / div | ||
| 63 | + */ | ||
| 64 | + new_jiffy_h = ref / div; | ||
| 65 | + new_jiffy_l = (ref % div) / 100; | ||
| 66 | + new_jiffy_h *= mult; | ||
| 67 | + new_jiffy_l = new_jiffy_l * mult / div; | ||
| 68 | + | ||
| 69 | + return new_jiffy_h + new_jiffy_l * 100; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */ | ||
| 73 | static int _init_omap_device(char *name, struct device **new_dev) | ||
| 74 | { | ||
| 75 | @@ -77,6 +102,74 @@ static int _init_omap_device(char *name, struct device **new_dev) | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | +static unsigned long omap3_mpu_get_rate(struct device *dev) | ||
| 80 | +{ | ||
| 81 | + return dpll1_clk->rate; | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +static int omap3_mpu_set_rate(struct device *dev, unsigned long rate) | ||
| 85 | +{ | ||
| 86 | + unsigned long cur_rate = omap3_mpu_get_rate(dev); | ||
| 87 | + int ret; | ||
| 88 | + | ||
| 89 | +#ifdef CONFIG_CPU_FREQ | ||
| 90 | + struct cpufreq_freqs freqs_notify; | ||
| 91 | + | ||
| 92 | + freqs_notify.old = cur_rate / 1000; | ||
| 93 | + freqs_notify.new = rate / 1000; | ||
| 94 | + freqs_notify.cpu = 0; | ||
| 95 | + /* Send pre notification to CPUFreq */ | ||
| 96 | + cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE); | ||
| 97 | +#endif | ||
| 98 | + ret = clk_set_rate(dpll1_clk, rate); | ||
| 99 | + if (ret) { | ||
| 100 | + dev_warn(dev, "%s: Unable to set rate to %ld\n", | ||
| 101 | + __func__, rate); | ||
| 102 | + return ret; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | +#ifdef CONFIG_CPU_FREQ | ||
| 106 | + /* Send a post notification to CPUFreq */ | ||
| 107 | + cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE); | ||
| 108 | +#endif | ||
| 109 | + | ||
| 110 | +#ifndef CONFIG_CPU_FREQ | ||
| 111 | + /*Update loops_per_jiffy if processor speed is being changed*/ | ||
| 112 | + loops_per_jiffy = compute_lpj(loops_per_jiffy, | ||
| 113 | + cur_rate / 1000, rate / 1000); | ||
| 114 | +#endif | ||
| 115 | + return 0; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +static int omap3_iva_set_rate(struct device *dev, unsigned long rate) | ||
| 119 | +{ | ||
| 120 | + return clk_set_rate(dpll2_clk, rate); | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +static unsigned long omap3_iva_get_rate(struct device *dev) | ||
| 124 | +{ | ||
| 125 | + return dpll2_clk->rate; | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +static int omap3_l3_set_rate(struct device *dev, unsigned long rate) | ||
| 129 | +{ | ||
| 130 | + int l3_div; | ||
| 131 | + | ||
| 132 | + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & | ||
| 133 | + OMAP3430_CLKSEL_L3_MASK; | ||
| 134 | + | ||
| 135 | + return clk_set_rate(dpll3_clk, rate * l3_div); | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +static unsigned long omap3_l3_get_rate(struct device *dev) | ||
| 139 | +{ | ||
| 140 | + int l3_div; | ||
| 141 | + | ||
| 142 | + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & | ||
| 143 | + OMAP3430_CLKSEL_L3_MASK; | ||
| 144 | + return dpll3_clk->rate / l3_div; | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | /* | ||
| 148 | * Build omap_devices for processors and bus. | ||
| 149 | */ | ||
| 150 | @@ -90,6 +183,23 @@ static void omap2_init_processor_devices(void) | ||
| 151 | } else { | ||
| 152 | _init_omap_device("l3_main", &l3_dev); | ||
| 153 | } | ||
| 154 | + | ||
| 155 | + if (cpu_is_omap34xx()) { | ||
| 156 | + dpll1_clk = clk_get(NULL, "dpll1_ck"); | ||
| 157 | + dpll2_clk = clk_get(NULL, "dpll2_ck"); | ||
| 158 | + dpll3_clk = clk_get(NULL, "dpll3_m2_ck"); | ||
| 159 | + | ||
| 160 | + if (mpu_dev) | ||
| 161 | + omap_device_populate_rate_fns(mpu_dev, | ||
| 162 | + omap3_mpu_set_rate, omap3_mpu_get_rate); | ||
| 163 | + if (iva_dev) | ||
| 164 | + omap_device_populate_rate_fns(iva_dev, | ||
| 165 | + omap3_iva_set_rate, omap3_iva_get_rate); | ||
| 166 | + if (l3_dev) | ||
| 167 | + omap_device_populate_rate_fns(l3_dev, | ||
| 168 | + omap3_l3_set_rate, omap3_l3_get_rate); | ||
| 169 | + | ||
| 170 | + } | ||
| 171 | } | ||
| 172 | |||
| 173 | /* Types of sleep_switch used in omap_set_pwrdm_state */ | ||
| 174 | -- | ||
| 175 | 1.6.6.1 | ||
| 176 | |||
