diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-01 18:20:08 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-01 18:20:08 -0400 |
| commit | 66776a67f7b1aeb4b0fac83df0a3379ed47af05c (patch) | |
| tree | 198dc4fd8f53d4fe7ea821c15152b0963655167c | |
| parent | e42391cd048809d903291d07f86ed3934ce138e9 (diff) | |
| parent | 358b615f5812e28dd763d2aa1297563927a2f89d (diff) | |
Merge tag 'pull_req_20150331' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq updates for v4.1 from MyungJoo Ham.
"This set includes tegra driver update and style fixes."
* tag 'pull_req_20150331' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq:
PM / devfreq: tegra: Register governor on module init
PM / devfreq: tegra: Enable interrupts after resuming the devfreq monitor
PM / devfreq: tegra: Set drvdata before enabling the irq
PM / devfreq: tegra: remove operating-points
PM / devfreq: tegra: Use clock rate constraints
PM / devfreq: tegra: Update to v5 of the submitted patches
PM / devfreq: correct misleading comment
PM / devfreq: event: Add const keyword for devfreq_event_ops structure
| -rw-r--r-- | drivers/devfreq/devfreq.c | 1 | ||||
| -rw-r--r-- | drivers/devfreq/event/exynos-ppmu.c | 2 | ||||
| -rw-r--r-- | drivers/devfreq/tegra-devfreq.c | 509 | ||||
| -rw-r--r-- | include/linux/devfreq-event.h | 2 |
4 files changed, 290 insertions, 224 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 30b538d8cc90..ca1b362d77e2 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -392,7 +392,6 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, | |||
| 392 | /** | 392 | /** |
| 393 | * _remove_devfreq() - Remove devfreq from the list and release its resources. | 393 | * _remove_devfreq() - Remove devfreq from the list and release its resources. |
| 394 | * @devfreq: the devfreq struct | 394 | * @devfreq: the devfreq struct |
| 395 | * @skip: skip calling device_unregister(). | ||
| 396 | */ | 395 | */ |
| 397 | static void _remove_devfreq(struct devfreq *devfreq) | 396 | static void _remove_devfreq(struct devfreq *devfreq) |
| 398 | { | 397 | { |
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index ad8347385f53..7d99d13bacd8 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c | |||
| @@ -194,7 +194,7 @@ static int exynos_ppmu_get_event(struct devfreq_event_dev *edev, | |||
| 194 | return 0; | 194 | return 0; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static struct devfreq_event_ops exynos_ppmu_ops = { | 197 | static const struct devfreq_event_ops exynos_ppmu_ops = { |
| 198 | .disable = exynos_ppmu_disable, | 198 | .disable = exynos_ppmu_disable, |
| 199 | .set_event = exynos_ppmu_set_event, | 199 | .set_event = exynos_ppmu_set_event, |
| 200 | .get_event = exynos_ppmu_get_event, | 200 | .get_event = exynos_ppmu_get_event, |
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 34790961af5a..13a1a6e8108c 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c | |||
| @@ -62,7 +62,8 @@ | |||
| 62 | #define ACTMON_BELOW_WMARK_WINDOW 3 | 62 | #define ACTMON_BELOW_WMARK_WINDOW 3 |
| 63 | #define ACTMON_BOOST_FREQ_STEP 16000 | 63 | #define ACTMON_BOOST_FREQ_STEP 16000 |
| 64 | 64 | ||
| 65 | /* activity counter is incremented every 256 memory transactions, and each | 65 | /* |
| 66 | * Activity counter is incremented every 256 memory transactions, and each | ||
| 66 | * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is | 67 | * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is |
| 67 | * 4 * 256 = 1024. | 68 | * 4 * 256 = 1024. |
| 68 | */ | 69 | */ |
| @@ -85,16 +86,25 @@ | |||
| 85 | * struct tegra_devfreq_device_config - configuration specific to an ACTMON | 86 | * struct tegra_devfreq_device_config - configuration specific to an ACTMON |
| 86 | * device | 87 | * device |
| 87 | * | 88 | * |
| 88 | * Coefficients and thresholds are in % | 89 | * Coefficients and thresholds are percentages unless otherwise noted |
| 89 | */ | 90 | */ |
| 90 | struct tegra_devfreq_device_config { | 91 | struct tegra_devfreq_device_config { |
| 91 | u32 offset; | 92 | u32 offset; |
| 92 | u32 irq_mask; | 93 | u32 irq_mask; |
| 93 | 94 | ||
| 95 | /* Factors applied to boost_freq every consecutive watermark breach */ | ||
| 94 | unsigned int boost_up_coeff; | 96 | unsigned int boost_up_coeff; |
| 95 | unsigned int boost_down_coeff; | 97 | unsigned int boost_down_coeff; |
| 98 | |||
| 99 | /* Define the watermark bounds when applied to the current avg */ | ||
| 96 | unsigned int boost_up_threshold; | 100 | unsigned int boost_up_threshold; |
| 97 | unsigned int boost_down_threshold; | 101 | unsigned int boost_down_threshold; |
| 102 | |||
| 103 | /* | ||
| 104 | * Threshold of activity (cycles) below which the CPU frequency isn't | ||
| 105 | * to be taken into account. This is to avoid increasing the EMC | ||
| 106 | * frequency when the CPU is very busy but not accessing the bus often. | ||
| 107 | */ | ||
| 98 | u32 avg_dependency_threshold; | 108 | u32 avg_dependency_threshold; |
| 99 | }; | 109 | }; |
| 100 | 110 | ||
| @@ -105,7 +115,7 @@ enum tegra_actmon_device { | |||
| 105 | 115 | ||
| 106 | static struct tegra_devfreq_device_config actmon_device_configs[] = { | 116 | static struct tegra_devfreq_device_config actmon_device_configs[] = { |
| 107 | { | 117 | { |
| 108 | /* MCALL */ | 118 | /* MCALL: All memory accesses (including from the CPUs) */ |
| 109 | .offset = 0x1c0, | 119 | .offset = 0x1c0, |
| 110 | .irq_mask = 1 << 26, | 120 | .irq_mask = 1 << 26, |
| 111 | .boost_up_coeff = 200, | 121 | .boost_up_coeff = 200, |
| @@ -114,7 +124,7 @@ static struct tegra_devfreq_device_config actmon_device_configs[] = { | |||
| 114 | .boost_down_threshold = 40, | 124 | .boost_down_threshold = 40, |
| 115 | }, | 125 | }, |
| 116 | { | 126 | { |
| 117 | /* MCCPU */ | 127 | /* MCCPU: memory accesses from the CPUs */ |
| 118 | .offset = 0x200, | 128 | .offset = 0x200, |
| 119 | .irq_mask = 1 << 25, | 129 | .irq_mask = 1 << 25, |
| 120 | .boost_up_coeff = 800, | 130 | .boost_up_coeff = 800, |
| @@ -132,25 +142,29 @@ static struct tegra_devfreq_device_config actmon_device_configs[] = { | |||
| 132 | */ | 142 | */ |
| 133 | struct tegra_devfreq_device { | 143 | struct tegra_devfreq_device { |
| 134 | const struct tegra_devfreq_device_config *config; | 144 | const struct tegra_devfreq_device_config *config; |
| 145 | void __iomem *regs; | ||
| 146 | spinlock_t lock; | ||
| 147 | |||
| 148 | /* Average event count sampled in the last interrupt */ | ||
| 149 | u32 avg_count; | ||
| 135 | 150 | ||
| 136 | void __iomem *regs; | 151 | /* |
| 137 | u32 avg_band_freq; | 152 | * Extra frequency to increase the target by due to consecutive |
| 138 | u32 avg_count; | 153 | * watermark breaches. |
| 154 | */ | ||
| 155 | unsigned long boost_freq; | ||
| 139 | 156 | ||
| 140 | unsigned long target_freq; | 157 | /* Optimal frequency calculated from the stats for this device */ |
| 141 | unsigned long boost_freq; | 158 | unsigned long target_freq; |
| 142 | }; | 159 | }; |
| 143 | 160 | ||
| 144 | struct tegra_devfreq { | 161 | struct tegra_devfreq { |
| 145 | struct devfreq *devfreq; | 162 | struct devfreq *devfreq; |
| 146 | 163 | ||
| 147 | struct platform_device *pdev; | ||
| 148 | struct reset_control *reset; | 164 | struct reset_control *reset; |
| 149 | struct clk *clock; | 165 | struct clk *clock; |
| 150 | void __iomem *regs; | 166 | void __iomem *regs; |
| 151 | 167 | ||
| 152 | spinlock_t lock; | ||
| 153 | |||
| 154 | struct clk *emc_clock; | 168 | struct clk *emc_clock; |
| 155 | unsigned long max_freq; | 169 | unsigned long max_freq; |
| 156 | unsigned long cur_freq; | 170 | unsigned long cur_freq; |
| @@ -174,19 +188,43 @@ static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = { | |||
| 174 | { 250000, 100000 }, | 188 | { 250000, 100000 }, |
| 175 | }; | 189 | }; |
| 176 | 190 | ||
| 191 | static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset) | ||
| 192 | { | ||
| 193 | return readl(tegra->regs + offset); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset) | ||
| 197 | { | ||
| 198 | writel(val, tegra->regs + offset); | ||
| 199 | } | ||
| 200 | |||
| 201 | static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset) | ||
| 202 | { | ||
| 203 | return readl(dev->regs + offset); | ||
| 204 | } | ||
| 205 | |||
| 206 | static void device_writel(struct tegra_devfreq_device *dev, u32 val, | ||
| 207 | u32 offset) | ||
| 208 | { | ||
| 209 | writel(val, dev->regs + offset); | ||
| 210 | } | ||
| 211 | |||
| 177 | static unsigned long do_percent(unsigned long val, unsigned int pct) | 212 | static unsigned long do_percent(unsigned long val, unsigned int pct) |
| 178 | { | 213 | { |
| 179 | return val * pct / 100; | 214 | return val * pct / 100; |
| 180 | } | 215 | } |
| 181 | 216 | ||
| 182 | static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq_device *dev) | 217 | static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq *tegra, |
| 218 | struct tegra_devfreq_device *dev) | ||
| 183 | { | 219 | { |
| 184 | u32 avg = dev->avg_count; | 220 | u32 avg = dev->avg_count; |
| 185 | u32 band = dev->avg_band_freq * ACTMON_SAMPLING_PERIOD; | 221 | u32 avg_band_freq = tegra->max_freq * ACTMON_DEFAULT_AVG_BAND / KHZ; |
| 222 | u32 band = avg_band_freq * ACTMON_SAMPLING_PERIOD; | ||
| 223 | |||
| 224 | device_writel(dev, avg + band, ACTMON_DEV_AVG_UPPER_WMARK); | ||
| 186 | 225 | ||
| 187 | writel(avg + band, dev->regs + ACTMON_DEV_AVG_UPPER_WMARK); | 226 | avg = max(dev->avg_count, band); |
| 188 | avg = max(avg, band); | 227 | device_writel(dev, avg - band, ACTMON_DEV_AVG_LOWER_WMARK); |
| 189 | writel(avg - band, dev->regs + ACTMON_DEV_AVG_LOWER_WMARK); | ||
| 190 | } | 228 | } |
| 191 | 229 | ||
| 192 | static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra, | 230 | static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra, |
| @@ -194,96 +232,96 @@ static void tegra_devfreq_update_wmark(struct tegra | |||
