123601752SDmitry Osipenko // SPDX-License-Identifier: GPL-2.0-only 223601752SDmitry Osipenko /* 323601752SDmitry Osipenko * A devfreq driver for NVIDIA Tegra SoCs 423601752SDmitry Osipenko * 523601752SDmitry Osipenko * Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. 623601752SDmitry Osipenko * Copyright (C) 2014 Google, Inc 723601752SDmitry Osipenko */ 823601752SDmitry Osipenko 923601752SDmitry Osipenko #include <linux/clk.h> 1023601752SDmitry Osipenko #include <linux/cpufreq.h> 1123601752SDmitry Osipenko #include <linux/devfreq.h> 1223601752SDmitry Osipenko #include <linux/interrupt.h> 1323601752SDmitry Osipenko #include <linux/io.h> 14d49eeb1eSDmitry Osipenko #include <linux/irq.h> 1523601752SDmitry Osipenko #include <linux/module.h> 169cff2177SDmitry Osipenko #include <linux/of_device.h> 1723601752SDmitry Osipenko #include <linux/platform_device.h> 1823601752SDmitry Osipenko #include <linux/pm_opp.h> 1923601752SDmitry Osipenko #include <linux/reset.h> 2011eb6ec5SDmitry Osipenko #include <linux/workqueue.h> 2123601752SDmitry Osipenko 2216e8b2a7SDmitry Osipenko #include <soc/tegra/fuse.h> 2316e8b2a7SDmitry Osipenko 2423601752SDmitry Osipenko #include "governor.h" 2523601752SDmitry Osipenko 2623601752SDmitry Osipenko #define ACTMON_GLB_STATUS 0x0 2723601752SDmitry Osipenko #define ACTMON_GLB_PERIOD_CTRL 0x4 2823601752SDmitry Osipenko 2923601752SDmitry Osipenko #define ACTMON_DEV_CTRL 0x0 3023601752SDmitry Osipenko #define ACTMON_DEV_CTRL_K_VAL_SHIFT 10 3123601752SDmitry Osipenko #define ACTMON_DEV_CTRL_ENB_PERIODIC BIT(18) 3223601752SDmitry Osipenko #define ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN BIT(20) 3323601752SDmitry Osipenko #define ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN BIT(21) 3423601752SDmitry Osipenko #define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT 23 3523601752SDmitry Osipenko #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT 26 3623601752SDmitry Osipenko #define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN BIT(29) 3723601752SDmitry Osipenko #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30) 3823601752SDmitry Osipenko #define ACTMON_DEV_CTRL_ENB BIT(31) 3923601752SDmitry Osipenko 4011eb6ec5SDmitry Osipenko #define ACTMON_DEV_CTRL_STOP 0x00000000 4111eb6ec5SDmitry Osipenko 4223601752SDmitry Osipenko #define ACTMON_DEV_UPPER_WMARK 0x4 4323601752SDmitry Osipenko #define ACTMON_DEV_LOWER_WMARK 0x8 4423601752SDmitry Osipenko #define ACTMON_DEV_INIT_AVG 0xc 4523601752SDmitry Osipenko #define ACTMON_DEV_AVG_UPPER_WMARK 0x10 4623601752SDmitry Osipenko #define ACTMON_DEV_AVG_LOWER_WMARK 0x14 4723601752SDmitry Osipenko #define ACTMON_DEV_COUNT_WEIGHT 0x18 4823601752SDmitry Osipenko #define ACTMON_DEV_AVG_COUNT 0x20 4923601752SDmitry Osipenko #define ACTMON_DEV_INTR_STATUS 0x24 5023601752SDmitry Osipenko 5123601752SDmitry Osipenko #define ACTMON_INTR_STATUS_CLEAR 0xffffffff 5223601752SDmitry Osipenko 5323601752SDmitry Osipenko #define ACTMON_DEV_INTR_CONSECUTIVE_UPPER BIT(31) 5423601752SDmitry Osipenko #define ACTMON_DEV_INTR_CONSECUTIVE_LOWER BIT(30) 5523601752SDmitry Osipenko 5623601752SDmitry Osipenko #define ACTMON_ABOVE_WMARK_WINDOW 1 5723601752SDmitry Osipenko #define ACTMON_BELOW_WMARK_WINDOW 3 5823601752SDmitry Osipenko #define ACTMON_BOOST_FREQ_STEP 16000 5923601752SDmitry Osipenko 6023601752SDmitry Osipenko /* 6123601752SDmitry Osipenko * ACTMON_AVERAGE_WINDOW_LOG2: default value for @DEV_CTRL_K_VAL, which 6223601752SDmitry Osipenko * translates to 2 ^ (K_VAL + 1). ex: 2 ^ (6 + 1) = 128 6323601752SDmitry Osipenko */ 6423601752SDmitry Osipenko #define ACTMON_AVERAGE_WINDOW_LOG2 6 6523601752SDmitry Osipenko #define ACTMON_SAMPLING_PERIOD 12 /* ms */ 6623601752SDmitry Osipenko #define ACTMON_DEFAULT_AVG_BAND 6 /* 1/10 of % */ 6723601752SDmitry Osipenko 6823601752SDmitry Osipenko #define KHZ 1000 6923601752SDmitry Osipenko 7053b4b2aeSDmitry Osipenko #define KHZ_MAX (ULONG_MAX / KHZ) 7153b4b2aeSDmitry Osipenko 7223601752SDmitry Osipenko /* Assume that the bus is saturated if the utilization is 25% */ 7323601752SDmitry Osipenko #define BUS_SATURATION_RATIO 25 7423601752SDmitry Osipenko 7523601752SDmitry Osipenko /** 7623601752SDmitry Osipenko * struct tegra_devfreq_device_config - configuration specific to an ACTMON 7723601752SDmitry Osipenko * device 7823601752SDmitry Osipenko * 7923601752SDmitry Osipenko * Coefficients and thresholds are percentages unless otherwise noted 8023601752SDmitry Osipenko */ 8123601752SDmitry Osipenko struct tegra_devfreq_device_config { 8223601752SDmitry Osipenko u32 offset; 8323601752SDmitry Osipenko u32 irq_mask; 8423601752SDmitry Osipenko 8523601752SDmitry Osipenko /* Factors applied to boost_freq every consecutive watermark breach */ 8623601752SDmitry Osipenko unsigned int boost_up_coeff; 8723601752SDmitry Osipenko unsigned int boost_down_coeff; 8823601752SDmitry Osipenko 8923601752SDmitry Osipenko /* Define the watermark bounds when applied to the current avg */ 9023601752SDmitry Osipenko unsigned int boost_up_threshold; 9123601752SDmitry Osipenko unsigned int boost_down_threshold; 9223601752SDmitry Osipenko 9323601752SDmitry Osipenko /* 9428615e37SDmitry Osipenko * Threshold of activity (cycles translated to kHz) below which the 9528615e37SDmitry Osipenko * CPU frequency isn't to be taken into account. This is to avoid 9628615e37SDmitry Osipenko * increasing the EMC frequency when the CPU is very busy but not 9728615e37SDmitry Osipenko * accessing the bus often. 9823601752SDmitry Osipenko */ 9923601752SDmitry Osipenko u32 avg_dependency_threshold; 10023601752SDmitry Osipenko }; 10123601752SDmitry Osipenko 10223601752SDmitry Osipenko enum tegra_actmon_device { 10323601752SDmitry Osipenko MCALL = 0, 10423601752SDmitry Osipenko MCCPU, 10523601752SDmitry Osipenko }; 10623601752SDmitry Osipenko 1076a575e84SDmitry Osipenko static const struct tegra_devfreq_device_config tegra124_device_configs[] = { 10823601752SDmitry Osipenko { 10923601752SDmitry Osipenko /* MCALL: All memory accesses (including from the CPUs) */ 11023601752SDmitry Osipenko .offset = 0x1c0, 11123601752SDmitry Osipenko .irq_mask = 1 << 26, 11223601752SDmitry Osipenko .boost_up_coeff = 200, 11323601752SDmitry Osipenko .boost_down_coeff = 50, 11423601752SDmitry Osipenko .boost_up_threshold = 60, 11523601752SDmitry Osipenko .boost_down_threshold = 40, 11623601752SDmitry Osipenko }, 11723601752SDmitry Osipenko { 11823601752SDmitry Osipenko /* MCCPU: memory accesses from the CPUs */ 11923601752SDmitry Osipenko .offset = 0x200, 12023601752SDmitry Osipenko .irq_mask = 1 << 25, 12123601752SDmitry Osipenko .boost_up_coeff = 800, 122fee22854SDmitry Osipenko .boost_down_coeff = 40, 12323601752SDmitry Osipenko .boost_up_threshold = 27, 12423601752SDmitry Osipenko .boost_down_threshold = 10, 12528615e37SDmitry Osipenko .avg_dependency_threshold = 16000, /* 16MHz in kHz units */ 12623601752SDmitry Osipenko }, 12723601752SDmitry Osipenko }; 12823601752SDmitry Osipenko 1296a575e84SDmitry Osipenko static const struct tegra_devfreq_device_config tegra30_device_configs[] = { 1306a575e84SDmitry Osipenko { 1316a575e84SDmitry Osipenko /* MCALL: All memory accesses (including from the CPUs) */ 1326a575e84SDmitry Osipenko .offset = 0x1c0, 1336a575e84SDmitry Osipenko .irq_mask = 1 << 26, 1346a575e84SDmitry Osipenko .boost_up_coeff = 200, 1356a575e84SDmitry Osipenko .boost_down_coeff = 50, 1366a575e84SDmitry Osipenko .boost_up_threshold = 20, 1376a575e84SDmitry Osipenko .boost_down_threshold = 10, 1386a575e84SDmitry Osipenko }, 1396a575e84SDmitry Osipenko { 1406a575e84SDmitry Osipenko /* MCCPU: memory accesses from the CPUs */ 1416a575e84SDmitry Osipenko .offset = 0x200, 1426a575e84SDmitry Osipenko .irq_mask = 1 << 25, 1436a575e84SDmitry Osipenko .boost_up_coeff = 800, 1446a575e84SDmitry Osipenko .boost_down_coeff = 40, 1456a575e84SDmitry Osipenko .boost_up_threshold = 27, 1466a575e84SDmitry Osipenko .boost_down_threshold = 10, 1476a575e84SDmitry Osipenko .avg_dependency_threshold = 16000, /* 16MHz in kHz units */ 1486a575e84SDmitry Osipenko }, 1496a575e84SDmitry Osipenko }; 1506a575e84SDmitry Osipenko 15123601752SDmitry Osipenko /** 15223601752SDmitry Osipenko * struct tegra_devfreq_device - state specific to an ACTMON device 15323601752SDmitry Osipenko * 15423601752SDmitry Osipenko * Frequencies are in kHz. 15523601752SDmitry Osipenko */ 15623601752SDmitry Osipenko struct tegra_devfreq_device { 15723601752SDmitry Osipenko const struct tegra_devfreq_device_config *config; 15823601752SDmitry Osipenko void __iomem *regs; 15923601752SDmitry Osipenko 16023601752SDmitry Osipenko /* Average event count sampled in the last interrupt */ 16123601752SDmitry Osipenko u32 avg_count; 16223601752SDmitry Osipenko 16323601752SDmitry Osipenko /* 16423601752SDmitry Osipenko * Extra frequency to increase the target by due to consecutive 16523601752SDmitry Osipenko * watermark breaches. 16623601752SDmitry Osipenko */ 16723601752SDmitry Osipenko unsigned long boost_freq; 16823601752SDmitry Osipenko 16923601752SDmitry Osipenko /* Optimal frequency calculated from the stats for this device */ 17023601752SDmitry Osipenko unsigned long target_freq; 17123601752SDmitry Osipenko }; 17223601752SDmitry Osipenko 1736a575e84SDmitry Osipenko struct tegra_devfreq_soc_data { 1746a575e84SDmitry Osipenko const struct tegra_devfreq_device_config *configs; 1756a575e84SDmitry Osipenko /* Weight value for count measurements */ 1766a575e84SDmitry Osipenko unsigned int count_weight; 1776a575e84SDmitry Osipenko }; 1786a575e84SDmitry Osipenko 17923601752SDmitry Osipenko struct tegra_devfreq { 18023601752SDmitry Osipenko struct devfreq *devfreq; 18123601752SDmitry Osipenko 18223601752SDmitry Osipenko struct reset_control *reset; 18323601752SDmitry Osipenko struct clk *clock; 18423601752SDmitry Osipenko void __iomem *regs; 18523601752SDmitry Osipenko 18623601752SDmitry Osipenko struct clk *emc_clock; 18723601752SDmitry Osipenko unsigned long max_freq; 18823601752SDmitry Osipenko unsigned long cur_freq; 18911eb6ec5SDmitry Osipenko struct notifier_block clk_rate_change_nb; 19011eb6ec5SDmitry Osipenko 19111eb6ec5SDmitry Osipenko struct delayed_work cpufreq_update_work; 19211eb6ec5SDmitry Osipenko struct notifier_block cpu_rate_change_nb; 19323601752SDmitry Osipenko 1946a575e84SDmitry Osipenko struct tegra_devfreq_device devices[2]; 19523601752SDmitry Osipenko 196dccdea01SDmitry Osipenko unsigned int irq; 197f61ee201SDmitry Osipenko 198f61ee201SDmitry Osipenko bool started; 1996a575e84SDmitry Osipenko 2006a575e84SDmitry Osipenko const struct tegra_devfreq_soc_data *soc; 20123601752SDmitry Osipenko }; 20223601752SDmitry Osipenko 20323601752SDmitry Osipenko struct tegra_actmon_emc_ratio { 20423601752SDmitry Osipenko unsigned long cpu_freq; 20523601752SDmitry Osipenko unsigned long emc_freq; 20623601752SDmitry Osipenko }; 20723601752SDmitry Osipenko 208b87dea3bSDmitry Osipenko static const struct tegra_actmon_emc_ratio actmon_emc_ratios[] = { 20953b4b2aeSDmitry Osipenko { 1400000, KHZ_MAX }, 21023601752SDmitry Osipenko { 1200000, 750000 }, 21123601752SDmitry Osipenko { 1100000, 600000 }, 21223601752SDmitry Osipenko { 1000000, 500000 }, 21323601752SDmitry Osipenko { 800000, 375000 }, 21423601752SDmitry Osipenko { 500000, 200000 }, 21523601752SDmitry Osipenko { 250000, 100000 }, 21623601752SDmitry Osipenko }; 21723601752SDmitry Osipenko 21823601752SDmitry Osipenko static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset) 21923601752SDmitry Osipenko { 22023601752SDmitry Osipenko return readl_relaxed(tegra->regs + offset); 22123601752SDmitry Osipenko } 22223601752SDmitry Osipenko 22323601752SDmitry Osipenko static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset) 22423601752SDmitry Osipenko { 22523601752SDmitry Osipenko writel_relaxed(val, tegra->regs + offset); 22623601752SDmitry Osipenko } 22723601752SDmitry Osipenko 22823601752SDmitry Osipenko static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset) 22923601752SDmitry Osipenko { 23023601752SDmitry Osipenko return readl_relaxed(dev->regs + offset); 23123601752SDmitry Osipenko } 23223601752SDmitry Osipenko 23323601752SDmitry Osipenko static void device_writel(struct tegra_devfreq_device *dev, u32 val, 23423601752SDmitry Osipenko u32 offset) 23523601752SDmitry Osipenko { 23623601752SDmitry Osipenko writel_relaxed(val, dev->regs + offset); 23723601752SDmitry Osipenko } 23823601752SDmitry Osipenko 239f61ee201SDmitry Osipenko static unsigned long do_percent(unsigned long long val, unsigned int pct) 24023601752SDmitry Osipenko { 241f61ee201SDmitry Osipenko val = val * pct; 242f61ee201SDmitry Osipenko do_div(val, 100); 243f61ee201SDmitry Osipenko 244f61ee201SDmitry Osipenko /* 245f61ee201SDmitry Osipenko * High freq + high boosting percent + large polling interval are 246f61ee201SDmitry Osipenko * resulting in integer overflow when watermarks are calculated. 247f61ee201SDmitry Osipenko */ 248f61ee201SDmitry Osipenko return min_t(u64, val, U32_MAX); 24923601752SDmitry Osipenko } 25023601752SDmitry Osipenko 25123601752SDmitry Osipenko static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq *tegra, 25223601752SDmitry Osipenko struct tegra_devfreq_device *dev) 25323601752SDmitry Osipenko { 25423601752SDmitry Osipenko u32 avg_band_freq = tegra->max_freq * ACTMON_DEFAULT_AVG_BAND / KHZ; 255f61ee201SDmitry Osipenko u32 band = avg_band_freq * tegra->devfreq->profile->polling_ms; 256f61ee201SDmitry Osipenko u32 avg; 25723601752SDmitry Osipenko 258f61ee201SDmitry Osipenko avg = min(dev->avg_count, U32_MAX - band); 25923601752SDmitry Osipenko device_writel(dev, avg + band, ACTMON_DEV_AVG_UPPER_WMARK); 26023601752SDmitry Osipenko 26123601752SDmitry Osipenko avg = max(dev->avg_count, band); 26223601752SDmitry Osipenko device_writel(dev, avg - band, ACTMON_DEV_AVG_LOWER_WMARK); 26323601752SDmitry Osipenko } 26423601752SDmitry Osipenko 26523601752SDmitry Osipenko static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra, 26623601752SDmitry Osipenko struct tegra_devfreq_device *dev) 26723601752SDmitry Osipenko { 268f61ee201SDmitry Osipenko u32 val = tegra->cur_freq * tegra->devfreq->profile->polling_ms; 26923601752SDmitry Osipenko 27023601752SDmitry Osipenko device_writel(dev, do_percent(val, dev->config->boost_up_threshold), 27123601752SDmitry Osipenko ACTMON_DEV_UPPER_WMARK); 27223601752SDmitry Osipenko 27323601752SDmitry Osipenko device_writel(dev, do_percent(val, dev->config->boost_down_threshold), 27423601752SDmitry Osipenko ACTMON_DEV_LOWER_WMARK); 27523601752SDmitry Osipenko } 27623601752SDmitry Osipenko 27723601752SDmitry Osipenko static void actmon_isr_device(struct tegra_devfreq *tegra, 27823601752SDmitry Osipenko struct tegra_devfreq_device *dev) 27923601752SDmitry Osipenko { 28023601752SDmitry Osipenko u32 intr_status, dev_ctrl; 28123601752SDmitry Osipenko 28223601752SDmitry Osipenko dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT); 28323601752SDmitry Osipenko tegra_devfreq_update_avg_wmark(tegra, dev); 28423601752SDmitry Osipenko 28523601752SDmitry Osipenko intr_status = device_readl(dev, ACTMON_DEV_INTR_STATUS); 28623601752SDmitry Osipenko dev_ctrl = device_readl(dev, ACTMON_DEV_CTRL); 28723601752SDmitry Osipenko 28823601752SDmitry Osipenko if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_UPPER) { 28923601752SDmitry Osipenko /* 29023601752SDmitry Osipenko * new_boost = min(old_boost * up_coef + step, max_freq) 29123601752SDmitry Osipenko */ 29223601752SDmitry Osipenko dev->boost_freq = do_percent(dev->boost_freq, 29323601752SDmitry Osipenko dev->config->boost_up_coeff); 29423601752SDmitry Osipenko dev->boost_freq += ACTMON_BOOST_FREQ_STEP; 29523601752SDmitry Osipenko 29623601752SDmitry Osipenko dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 29723601752SDmitry Osipenko 29888ec8164SDmitry Osipenko if (dev->boost_freq >= tegra->max_freq) { 29988ec8164SDmitry Osipenko dev_ctrl &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 30023601752SDmitry Osipenko dev->boost_freq = tegra->max_freq; 30188ec8164SDmitry Osipenko } 30223601752SDmitry Osipenko } else if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_LOWER) { 30323601752SDmitry Osipenko /* 30423601752SDmitry Osipenko * new_boost = old_boost * down_coef 30523601752SDmitry Osipenko * or 0 if (old_boost * down_coef < step / 2) 30623601752SDmitry Osipenko */ 30723601752SDmitry Osipenko dev->boost_freq = do_percent(dev->boost_freq, 30823601752SDmitry Osipenko dev->config->boost_down_coeff); 30923601752SDmitry Osipenko 31023601752SDmitry Osipenko dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 31123601752SDmitry Osipenko 31288ec8164SDmitry Osipenko if (dev->boost_freq < (ACTMON_BOOST_FREQ_STEP >> 1)) { 31388ec8164SDmitry Osipenko dev_ctrl &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 31423601752SDmitry Osipenko dev->boost_freq = 0; 31523601752SDmitry Osipenko } 31623601752SDmitry Osipenko } 31723601752SDmitry Osipenko 31823601752SDmitry Osipenko device_writel(dev, dev_ctrl, ACTMON_DEV_CTRL); 31923601752SDmitry Osipenko 32023601752SDmitry Osipenko device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS); 32123601752SDmitry Osipenko } 32223601752SDmitry Osipenko 32323601752SDmitry Osipenko static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra, 32423601752SDmitry Osipenko unsigned long cpu_freq) 32523601752SDmitry Osipenko { 32623601752SDmitry Osipenko unsigned int i; 327b87dea3bSDmitry Osipenko const struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios; 32823601752SDmitry Osipenko 32923601752SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) { 33023601752SDmitry Osipenko if (cpu_freq >= ratio->cpu_freq) { 33123601752SDmitry Osipenko if (ratio->emc_freq >= tegra->max_freq) 33223601752SDmitry Osipenko return tegra->max_freq; 33323601752SDmitry Osipenko else 33423601752SDmitry Osipenko return ratio->emc_freq; 33523601752SDmitry Osipenko } 33623601752SDmitry Osipenko } 33723601752SDmitry Osipenko 33823601752SDmitry Osipenko return 0; 33923601752SDmitry Osipenko } 34023601752SDmitry Osipenko 34111eb6ec5SDmitry Osipenko static unsigned long actmon_device_target_freq(struct tegra_devfreq *tegra, 34211eb6ec5SDmitry Osipenko struct tegra_devfreq_device *dev) 34311eb6ec5SDmitry Osipenko { 34411eb6ec5SDmitry Osipenko unsigned int avg_sustain_coef; 34511eb6ec5SDmitry Osipenko unsigned long target_freq; 34611eb6ec5SDmitry Osipenko 347f61ee201SDmitry Osipenko target_freq = dev->avg_count / tegra->devfreq->profile->polling_ms; 34811eb6ec5SDmitry Osipenko avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold; 34911eb6ec5SDmitry Osipenko target_freq = do_percent(target_freq, avg_sustain_coef); 35011eb6ec5SDmitry Osipenko 35111eb6ec5SDmitry Osipenko return target_freq; 35211eb6ec5SDmitry Osipenko } 35311eb6ec5SDmitry Osipenko 35423601752SDmitry Osipenko static void actmon_update_target(struct tegra_devfreq *tegra, 35523601752SDmitry Osipenko struct tegra_devfreq_device *dev) 35623601752SDmitry Osipenko { 35723601752SDmitry Osipenko unsigned long cpu_freq = 0; 35823601752SDmitry Osipenko unsigned long static_cpu_emc_freq = 0; 35923601752SDmitry Osipenko 36011eb6ec5SDmitry Osipenko dev->target_freq = actmon_device_target_freq(tegra, dev); 36123601752SDmitry Osipenko 36228615e37SDmitry Osipenko if (dev->config->avg_dependency_threshold && 36328615e37SDmitry Osipenko dev->config->avg_dependency_threshold <= dev->target_freq) { 36428615e37SDmitry Osipenko cpu_freq = cpufreq_quick_get(0); 36528615e37SDmitry Osipenko static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq); 36628615e37SDmitry Osipenko 36728615e37SDmitry Osipenko dev->target_freq += dev->boost_freq; 36823601752SDmitry Osipenko dev->target_freq = max(dev->target_freq, static_cpu_emc_freq); 36928615e37SDmitry Osipenko } else { 37028615e37SDmitry Osipenko dev->target_freq += dev->boost_freq; 37128615e37SDmitry Osipenko } 37223601752SDmitry Osipenko } 37323601752SDmitry Osipenko 37423601752SDmitry Osipenko static irqreturn_t actmon_thread_isr(int irq, void *data) 37523601752SDmitry Osipenko { 37623601752SDmitry Osipenko struct tegra_devfreq *tegra = data; 37723601752SDmitry Osipenko bool handled = false; 37823601752SDmitry Osipenko unsigned int i; 37923601752SDmitry Osipenko u32 val; 38023601752SDmitry Osipenko 38123601752SDmitry Osipenko mutex_lock(&tegra->devfreq->lock); 38223601752SDmitry Osipenko 38323601752SDmitry Osipenko val = actmon_readl(tegra, ACTMON_GLB_STATUS); 38423601752SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 38523601752SDmitry Osipenko if (val & tegra->devices[i].config->irq_mask) { 38623601752SDmitry Osipenko actmon_isr_device(tegra, tegra->devices + i); 38723601752SDmitry Osipenko handled = true; 38823601752SDmitry Osipenko } 38923601752SDmitry Osipenko } 39023601752SDmitry Osipenko 39123601752SDmitry Osipenko if (handled) 39223601752SDmitry Osipenko update_devfreq(tegra->devfreq); 39323601752SDmitry Osipenko 39423601752SDmitry Osipenko mutex_unlock(&tegra->devfreq->lock); 39523601752SDmitry Osipenko 39623601752SDmitry Osipenko return handled ? IRQ_HANDLED : IRQ_NONE; 39723601752SDmitry Osipenko } 39823601752SDmitry Osipenko 39911eb6ec5SDmitry Osipenko static int tegra_actmon_clk_notify_cb(struct notifier_block *nb, 40023601752SDmitry Osipenko unsigned long action, void *ptr) 40123601752SDmitry Osipenko { 40223601752SDmitry Osipenko struct clk_notifier_data *data = ptr; 40323601752SDmitry Osipenko struct tegra_devfreq *tegra; 40423601752SDmitry Osipenko struct tegra_devfreq_device *dev; 40523601752SDmitry Osipenko unsigned int i; 40623601752SDmitry Osipenko 40723601752SDmitry Osipenko if (action != POST_RATE_CHANGE) 40823601752SDmitry Osipenko return NOTIFY_OK; 40923601752SDmitry Osipenko 41011eb6ec5SDmitry Osipenko tegra = container_of(nb, struct tegra_devfreq, clk_rate_change_nb); 41123601752SDmitry Osipenko 41223601752SDmitry Osipenko tegra->cur_freq = data->new_rate / KHZ; 41323601752SDmitry Osipenko 41423601752SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 41523601752SDmitry Osipenko dev = &tegra->devices[i]; 41623601752SDmitry Osipenko 41723601752SDmitry Osipenko tegra_devfreq_update_wmark(tegra, dev); 41823601752SDmitry Osipenko } 41923601752SDmitry Osipenko 42023601752SDmitry Osipenko return NOTIFY_OK; 42123601752SDmitry Osipenko } 42223601752SDmitry Osipenko 42311eb6ec5SDmitry Osipenko static void tegra_actmon_delayed_update(struct work_struct *work) 42411eb6ec5SDmitry Osipenko { 42511eb6ec5SDmitry Osipenko struct tegra_devfreq *tegra = container_of(work, struct tegra_devfreq, 42611eb6ec5SDmitry Osipenko cpufreq_update_work.work); 42711eb6ec5SDmitry Osipenko 42811eb6ec5SDmitry Osipenko mutex_lock(&tegra->devfreq->lock); 42911eb6ec5SDmitry Osipenko update_devfreq(tegra->devfreq); 43011eb6ec5SDmitry Osipenko mutex_unlock(&tegra->devfreq->lock); 43111eb6ec5SDmitry Osipenko } 43211eb6ec5SDmitry Osipenko 43311eb6ec5SDmitry Osipenko static unsigned long 43411eb6ec5SDmitry Osipenko tegra_actmon_cpufreq_contribution(struct tegra_devfreq *tegra, 43511eb6ec5SDmitry Osipenko unsigned int cpu_freq) 43611eb6ec5SDmitry Osipenko { 43728615e37SDmitry Osipenko struct tegra_devfreq_device *actmon_dev = &tegra->devices[MCCPU]; 43811eb6ec5SDmitry Osipenko unsigned long static_cpu_emc_freq, dev_freq; 43911eb6ec5SDmitry Osipenko 44028615e37SDmitry Osipenko dev_freq = actmon_device_target_freq(tegra, actmon_dev); 44128615e37SDmitry Osipenko 44211eb6ec5SDmitry Osipenko /* check whether CPU's freq is taken into account at all */ 44328615e37SDmitry Osipenko if (dev_freq < actmon_dev->config->avg_dependency_threshold) 44411eb6ec5SDmitry Osipenko return 0; 44511eb6ec5SDmitry Osipenko 44611eb6ec5SDmitry Osipenko static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq); 44711eb6ec5SDmitry Osipenko 448d2216ba3SDmitry Osipenko if (dev_freq + actmon_dev->boost_freq >= static_cpu_emc_freq) 44911eb6ec5SDmitry Osipenko return 0; 45011eb6ec5SDmitry Osipenko 45111eb6ec5SDmitry Osipenko return static_cpu_emc_freq; 45211eb6ec5SDmitry Osipenko } 45311eb6ec5SDmitry Osipenko 45411eb6ec5SDmitry Osipenko static int tegra_actmon_cpu_notify_cb(struct notifier_block *nb, 45511eb6ec5SDmitry Osipenko unsigned long action, void *ptr) 45611eb6ec5SDmitry Osipenko { 45711eb6ec5SDmitry Osipenko struct cpufreq_freqs *freqs = ptr; 45811eb6ec5SDmitry Osipenko struct tegra_devfreq *tegra; 45911eb6ec5SDmitry Osipenko unsigned long old, new, delay; 46011eb6ec5SDmitry Osipenko 46111eb6ec5SDmitry Osipenko if (action != CPUFREQ_POSTCHANGE) 46211eb6ec5SDmitry Osipenko return NOTIFY_OK; 46311eb6ec5SDmitry Osipenko 46411eb6ec5SDmitry Osipenko tegra = container_of(nb, struct tegra_devfreq, cpu_rate_change_nb); 46511eb6ec5SDmitry Osipenko 46611eb6ec5SDmitry Osipenko /* 46711eb6ec5SDmitry Osipenko * Quickly check whether CPU frequency should be taken into account 46811eb6ec5SDmitry Osipenko * at all, without blocking CPUFreq's core. 46911eb6ec5SDmitry Osipenko */ 47011eb6ec5SDmitry Osipenko if (mutex_trylock(&tegra->devfreq->lock)) { 47111eb6ec5SDmitry Osipenko old = tegra_actmon_cpufreq_contribution(tegra, freqs->old); 47211eb6ec5SDmitry Osipenko new = tegra_actmon_cpufreq_contribution(tegra, freqs->new); 47311eb6ec5SDmitry Osipenko mutex_unlock(&tegra->devfreq->lock); 47411eb6ec5SDmitry Osipenko 47511eb6ec5SDmitry Osipenko /* 47611eb6ec5SDmitry Osipenko * If CPU's frequency shouldn't be taken into account at 47711eb6ec5SDmitry Osipenko * the moment, then there is no need to update the devfreq's 47811eb6ec5SDmitry Osipenko * state because ISR will re-check CPU's frequency on the 47911eb6ec5SDmitry Osipenko * next interrupt. 48011eb6ec5SDmitry Osipenko */ 48111eb6ec5SDmitry Osipenko if (old == new) 48211eb6ec5SDmitry Osipenko return NOTIFY_OK; 48311eb6ec5SDmitry Osipenko } 48411eb6ec5SDmitry Osipenko 48511eb6ec5SDmitry Osipenko /* 48611eb6ec5SDmitry Osipenko * CPUFreq driver should support CPUFREQ_ASYNC_NOTIFICATION in order 48711eb6ec5SDmitry Osipenko * to allow asynchronous notifications. This means we can't block 48811eb6ec5SDmitry Osipenko * here for too long, otherwise CPUFreq's core will complain with a 48911eb6ec5SDmitry Osipenko * warning splat. 49011eb6ec5SDmitry Osipenko */ 49111eb6ec5SDmitry Osipenko delay = msecs_to_jiffies(ACTMON_SAMPLING_PERIOD); 49211eb6ec5SDmitry Osipenko schedule_delayed_work(&tegra->cpufreq_update_work, delay); 49311eb6ec5SDmitry Osipenko 49411eb6ec5SDmitry Osipenko return NOTIFY_OK; 49511eb6ec5SDmitry Osipenko } 49611eb6ec5SDmitry Osipenko 49723601752SDmitry Osipenko static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, 49823601752SDmitry Osipenko struct tegra_devfreq_device *dev) 49923601752SDmitry Osipenko { 50023601752SDmitry Osipenko u32 val = 0; 50123601752SDmitry Osipenko 50214266558SDmitry Osipenko /* reset boosting on governor's restart */ 50314266558SDmitry Osipenko dev->boost_freq = 0; 50414266558SDmitry Osipenko 50523601752SDmitry Osipenko dev->target_freq = tegra->cur_freq; 50623601752SDmitry Osipenko 507f61ee201SDmitry Osipenko dev->avg_count = tegra->cur_freq * tegra->devfreq->profile->polling_ms; 50823601752SDmitry Osipenko device_writel(dev, dev->avg_count, ACTMON_DEV_INIT_AVG); 50923601752SDmitry Osipenko 51023601752SDmitry Osipenko tegra_devfreq_update_avg_wmark(tegra, dev); 51123601752SDmitry Osipenko tegra_devfreq_update_wmark(tegra, dev); 51223601752SDmitry Osipenko 5136a575e84SDmitry Osipenko device_writel(dev, tegra->soc->count_weight, ACTMON_DEV_COUNT_WEIGHT); 51423601752SDmitry Osipenko device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS); 51523601752SDmitry Osipenko 51623601752SDmitry Osipenko val |= ACTMON_DEV_CTRL_ENB_PERIODIC; 51723601752SDmitry Osipenko val |= (ACTMON_AVERAGE_WINDOW_LOG2 - 1) 51823601752SDmitry Osipenko << ACTMON_DEV_CTRL_K_VAL_SHIFT; 51923601752SDmitry Osipenko val |= (ACTMON_BELOW_WMARK_WINDOW - 1) 52023601752SDmitry Osipenko << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT; 52123601752SDmitry Osipenko val |= (ACTMON_ABOVE_WMARK_WINDOW - 1) 52223601752SDmitry Osipenko << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT; 52323601752SDmitry Osipenko val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; 52423601752SDmitry Osipenko val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; 52523601752SDmitry Osipenko val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 52623601752SDmitry Osipenko val |= ACTMON_DEV_CTRL_ENB; 52723601752SDmitry Osipenko 52823601752SDmitry Osipenko device_writel(dev, val, ACTMON_DEV_CTRL); 52923601752SDmitry Osipenko } 53023601752SDmitry Osipenko 53111eb6ec5SDmitry Osipenko static void tegra_actmon_stop_devices(struct tegra_devfreq *tegra) 53211eb6ec5SDmitry Osipenko { 53311eb6ec5SDmitry Osipenko struct tegra_devfreq_device *dev = tegra->devices; 53411eb6ec5SDmitry Osipenko unsigned int i; 53511eb6ec5SDmitry Osipenko 53611eb6ec5SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++, dev++) { 53711eb6ec5SDmitry Osipenko device_writel(dev, ACTMON_DEV_CTRL_STOP, ACTMON_DEV_CTRL); 53811eb6ec5SDmitry Osipenko device_writel(dev, ACTMON_INTR_STATUS_CLEAR, 53911eb6ec5SDmitry Osipenko ACTMON_DEV_INTR_STATUS); 54011eb6ec5SDmitry Osipenko } 54111eb6ec5SDmitry Osipenko } 54211eb6ec5SDmitry Osipenko 543f61ee201SDmitry Osipenko static int tegra_actmon_resume(struct tegra_devfreq *tegra) 54423601752SDmitry Osipenko { 54523601752SDmitry Osipenko unsigned int i; 54611eb6ec5SDmitry Osipenko int err; 54723601752SDmitry Osipenko 548f61ee201SDmitry Osipenko if (!tegra->devfreq->profile->polling_ms || !tegra->started) 549f61ee201SDmitry Osipenko return 0; 550f61ee201SDmitry Osipenko 551f61ee201SDmitry Osipenko actmon_writel(tegra, tegra->devfreq->profile->polling_ms - 1, 55223601752SDmitry Osipenko ACTMON_GLB_PERIOD_CTRL); 55323601752SDmitry Osipenko 5546f2a35d6SDmitry Osipenko /* 5556f2a35d6SDmitry Osipenko * CLK notifications are needed in order to reconfigure the upper 5566f2a35d6SDmitry Osipenko * consecutive watermark in accordance to the actual clock rate 5576f2a35d6SDmitry Osipenko * to avoid unnecessary upper interrupts. 5586f2a35d6SDmitry Osipenko */ 5596f2a35d6SDmitry Osipenko err = clk_notifier_register(tegra->emc_clock, 5606f2a35d6SDmitry Osipenko &tegra->clk_rate_change_nb); 5616f2a35d6SDmitry Osipenko if (err) { 5626f2a35d6SDmitry Osipenko dev_err(tegra->devfreq->dev.parent, 5636f2a35d6SDmitry Osipenko "Failed to register rate change notifier\n"); 5646f2a35d6SDmitry Osipenko return err; 5656f2a35d6SDmitry Osipenko } 5666f2a35d6SDmitry Osipenko 5676f2a35d6SDmitry Osipenko tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ; 5686f2a35d6SDmitry Osipenko 56923601752SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) 57023601752SDmitry Osipenko tegra_actmon_configure_device(tegra, &tegra->devices[i]); 57123601752SDmitry Osipenko 57211eb6ec5SDmitry Osipenko /* 57311eb6ec5SDmitry Osipenko * We are estimating CPU's memory bandwidth requirement based on 57411eb6ec5SDmitry Osipenko * amount of memory accesses and system's load, judging by CPU's 57511eb6ec5SDmitry Osipenko * frequency. We also don't want to receive events about CPU's 57611eb6ec5SDmitry Osipenko * frequency transaction when governor is stopped, hence notifier 57711eb6ec5SDmitry Osipenko * is registered dynamically. 57811eb6ec5SDmitry Osipenko */ 57911eb6ec5SDmitry Osipenko err = cpufreq_register_notifier(&tegra->cpu_rate_change_nb, 58011eb6ec5SDmitry Osipenko CPUFREQ_TRANSITION_NOTIFIER); 58111eb6ec5SDmitry Osipenko if (err) { 58211eb6ec5SDmitry Osipenko dev_err(tegra->devfreq->dev.parent, 58311eb6ec5SDmitry Osipenko "Failed to register rate change notifier: %d\n", err); 58411eb6ec5SDmitry Osipenko goto err_stop; 58511eb6ec5SDmitry Osipenko } 58611eb6ec5SDmitry Osipenko 58723601752SDmitry Osipenko enable_irq(tegra->irq); 58811eb6ec5SDmitry Osipenko 58911eb6ec5SDmitry Osipenko return 0; 59011eb6ec5SDmitry Osipenko 59111eb6ec5SDmitry Osipenko err_stop: 59211eb6ec5SDmitry Osipenko tegra_actmon_stop_devices(tegra); 59311eb6ec5SDmitry Osipenko 5946f2a35d6SDmitry Osipenko clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb); 5956f2a35d6SDmitry Osipenko 59611eb6ec5SDmitry Osipenko return err; 59723601752SDmitry Osipenko } 59823601752SDmitry Osipenko 599f61ee201SDmitry Osipenko static int tegra_actmon_start(struct tegra_devfreq *tegra) 60023601752SDmitry Osipenko { 601f61ee201SDmitry Osipenko int ret = 0; 602f61ee201SDmitry Osipenko 603f61ee201SDmitry Osipenko if (!tegra->started) { 604f61ee201SDmitry Osipenko tegra->started = true; 605f61ee201SDmitry Osipenko 606f61ee201SDmitry Osipenko ret = tegra_actmon_resume(tegra); 607f61ee201SDmitry Osipenko if (ret) 608f61ee201SDmitry Osipenko tegra->started = false; 609f61ee201SDmitry Osipenko } 610f61ee201SDmitry Osipenko 611f61ee201SDmitry Osipenko return ret; 612f61ee201SDmitry Osipenko } 613f61ee201SDmitry Osipenko 614f61ee201SDmitry Osipenko static void tegra_actmon_pause(struct tegra_devfreq *tegra) 615f61ee201SDmitry Osipenko { 616f61ee201SDmitry Osipenko if (!tegra->devfreq->profile->polling_ms || !tegra->started) 617f61ee201SDmitry Osipenko return; 618f61ee201SDmitry Osipenko 61923601752SDmitry Osipenko disable_irq(tegra->irq); 62023601752SDmitry Osipenko 62111eb6ec5SDmitry Osipenko cpufreq_unregister_notifier(&tegra->cpu_rate_change_nb, 62211eb6ec5SDmitry Osipenko CPUFREQ_TRANSITION_NOTIFIER); 62311eb6ec5SDmitry Osipenko 62411eb6ec5SDmitry Osipenko cancel_delayed_work_sync(&tegra->cpufreq_update_work); 62511eb6ec5SDmitry Osipenko 62611eb6ec5SDmitry Osipenko tegra_actmon_stop_devices(tegra); 6276f2a35d6SDmitry Osipenko 6286f2a35d6SDmitry Osipenko clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb); 62923601752SDmitry Osipenko } 63023601752SDmitry Osipenko 631f61ee201SDmitry Osipenko static void tegra_actmon_stop(struct tegra_devfreq *tegra) 632f61ee201SDmitry Osipenko { 633f61ee201SDmitry Osipenko tegra_actmon_pause(tegra); 634f61ee201SDmitry Osipenko tegra->started = false; 635f61ee201SDmitry Osipenko } 636f61ee201SDmitry Osipenko 63723601752SDmitry Osipenko static int tegra_devfreq_target(struct device *dev, unsigned long *freq, 63823601752SDmitry Osipenko u32 flags) 63923601752SDmitry Osipenko { 64023601752SDmitry Osipenko struct dev_pm_opp *opp; 64116e8b2a7SDmitry Osipenko int ret; 64223601752SDmitry Osipenko 64323601752SDmitry Osipenko opp = devfreq_recommended_opp(dev, freq, flags); 64423601752SDmitry Osipenko if (IS_ERR(opp)) { 64523601752SDmitry Osipenko dev_err(dev, "Failed to find opp for %lu Hz\n", *freq); 64623601752SDmitry Osipenko return PTR_ERR(opp); 64723601752SDmitry Osipenko } 64816e8b2a7SDmitry Osipenko 649c7f14219SViresh Kumar ret = dev_pm_opp_set_opp(dev, opp); 65023601752SDmitry Osipenko dev_pm_opp_put(opp); 65123601752SDmitry Osipenko 65216e8b2a7SDmitry Osipenko return ret; 65323601752SDmitry Osipenko } 65423601752SDmitry Osipenko 65523601752SDmitry Osipenko static int tegra_devfreq_get_dev_status(struct device *dev, 65623601752SDmitry Osipenko struct devfreq_dev_status *stat) 65723601752SDmitry Osipenko { 65823601752SDmitry Osipenko struct tegra_devfreq *tegra = dev_get_drvdata(dev); 65923601752SDmitry Osipenko struct tegra_devfreq_device *actmon_dev; 66023601752SDmitry Osipenko unsigned long cur_freq; 66123601752SDmitry Osipenko 66223601752SDmitry Osipenko cur_freq = READ_ONCE(tegra->cur_freq); 66323601752SDmitry Osipenko 66423601752SDmitry Osipenko /* To be used by the tegra governor */ 66523601752SDmitry Osipenko stat->private_data = tegra; 66623601752SDmitry Osipenko 66723601752SDmitry Osipenko /* The below are to be used by the other governors */ 66816e8b2a7SDmitry Osipenko stat->current_frequency = cur_freq * KHZ; 66923601752SDmitry Osipenko 67023601752SDmitry Osipenko actmon_dev = &tegra->devices[MCALL]; 67123601752SDmitry Osipenko 67223601752SDmitry Osipenko /* Number of cycles spent on memory access */ 67323601752SDmitry Osipenko stat->busy_time = device_readl(actmon_dev, ACTMON_DEV_AVG_COUNT); 67423601752SDmitry Osipenko 67523601752SDmitry Osipenko /* The bus can be considered to be saturated way before 100% */ 67623601752SDmitry Osipenko stat->busy_time *= 100 / BUS_SATURATION_RATIO; 67723601752SDmitry Osipenko 67823601752SDmitry Osipenko /* Number of cycles in a sampling period */ 679f61ee201SDmitry Osipenko stat->total_time = tegra->devfreq->profile->polling_ms * cur_freq; 68023601752SDmitry Osipenko 68123601752SDmitry Osipenko stat->busy_time = min(stat->busy_time, stat->total_time); 68223601752SDmitry Osipenko 68323601752SDmitry Osipenko return 0; 68423601752SDmitry Osipenko } 68523601752SDmitry Osipenko 68623601752SDmitry Osipenko static struct devfreq_dev_profile tegra_devfreq_profile = { 687f61ee201SDmitry Osipenko .polling_ms = ACTMON_SAMPLING_PERIOD, 68823601752SDmitry Osipenko .target = tegra_devfreq_target, 68923601752SDmitry Osipenko .get_dev_status = tegra_devfreq_get_dev_status, 6905e480ab9SDmitry Osipenko .is_cooling_device = true, 69123601752SDmitry Osipenko }; 69223601752SDmitry Osipenko 69323601752SDmitry Osipenko static int tegra_governor_get_target(struct devfreq *devfreq, 69423601752SDmitry Osipenko unsigned long *freq) 69523601752SDmitry Osipenko { 69623601752SDmitry Osipenko struct devfreq_dev_status *stat; 69723601752SDmitry Osipenko struct tegra_devfreq *tegra; 69823601752SDmitry Osipenko struct tegra_devfreq_device *dev; 69923601752SDmitry Osipenko unsigned long target_freq = 0; 70023601752SDmitry Osipenko unsigned int i; 70123601752SDmitry Osipenko int err; 70223601752SDmitry Osipenko 70323601752SDmitry Osipenko err = devfreq_update_stats(devfreq); 70423601752SDmitry Osipenko if (err) 70523601752SDmitry Osipenko return err; 70623601752SDmitry Osipenko 70723601752SDmitry Osipenko stat = &devfreq->last_status; 70823601752SDmitry Osipenko 70923601752SDmitry Osipenko tegra = stat->private_data; 71023601752SDmitry Osipenko 71123601752SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 71223601752SDmitry Osipenko dev = &tegra->devices[i]; 71323601752SDmitry Osipenko 71423601752SDmitry Osipenko actmon_update_target(tegra, dev); 71523601752SDmitry Osipenko 71623601752SDmitry Osipenko target_freq = max(target_freq, dev->target_freq); 71723601752SDmitry Osipenko } 71823601752SDmitry Osipenko 71916e8b2a7SDmitry Osipenko /* 72016e8b2a7SDmitry Osipenko * tegra-devfreq driver operates with KHz units, while OPP table 72116e8b2a7SDmitry Osipenko * entries use Hz units. Hence we need to convert the units for the 72216e8b2a7SDmitry Osipenko * devfreq core. 72316e8b2a7SDmitry Osipenko */ 72416e8b2a7SDmitry Osipenko *freq = target_freq * KHZ; 72523601752SDmitry Osipenko 72623601752SDmitry Osipenko return 0; 72723601752SDmitry Osipenko } 72823601752SDmitry Osipenko 72923601752SDmitry Osipenko static int tegra_governor_event_handler(struct devfreq *devfreq, 73023601752SDmitry Osipenko unsigned int event, void *data) 73123601752SDmitry Osipenko { 73223601752SDmitry Osipenko struct tegra_devfreq *tegra = dev_get_drvdata(devfreq->dev.parent); 733f61ee201SDmitry Osipenko unsigned int *new_delay = data; 73411eb6ec5SDmitry Osipenko int ret = 0; 73523601752SDmitry Osipenko 736d49eeb1eSDmitry Osipenko /* 737d49eeb1eSDmitry Osipenko * Couple devfreq-device with the governor early because it is 738d49eeb1eSDmitry Osipenko * needed at the moment of governor's start (used by ISR). 739d49eeb1eSDmitry Osipenko */ 740d49eeb1eSDmitry Osipenko tegra->devfreq = devfreq; 741d49eeb1eSDmitry Osipenko 74223601752SDmitry Osipenko switch (event) { 74323601752SDmitry Osipenko case DEVFREQ_GOV_START: 74423601752SDmitry Osipenko devfreq_monitor_start(devfreq); 74511eb6ec5SDmitry Osipenko ret = tegra_actmon_start(tegra); 74623601752SDmitry Osipenko break; 74723601752SDmitry Osipenko 74823601752SDmitry Osipenko case DEVFREQ_GOV_STOP: 74923601752SDmitry Osipenko tegra_actmon_stop(tegra); 75023601752SDmitry Osipenko devfreq_monitor_stop(devfreq); 75123601752SDmitry Osipenko break; 75223601752SDmitry Osipenko 7533a1ec2e8SChanwoo Choi case DEVFREQ_GOV_UPDATE_INTERVAL: 754f61ee201SDmitry Osipenko /* 755f61ee201SDmitry Osipenko * ACTMON hardware supports up to 256 milliseconds for the 756f61ee201SDmitry Osipenko * sampling period. 757f61ee201SDmitry Osipenko */ 758f61ee201SDmitry Osipenko if (*new_delay > 256) { 759f61ee201SDmitry Osipenko ret = -EINVAL; 760f61ee201SDmitry Osipenko break; 761f61ee201SDmitry Osipenko } 762f61ee201SDmitry Osipenko 763f61ee201SDmitry Osipenko tegra_actmon_pause(tegra); 7643a1ec2e8SChanwoo Choi devfreq_update_interval(devfreq, new_delay); 765f61ee201SDmitry Osipenko ret = tegra_actmon_resume(tegra); 766f61ee201SDmitry Osipenko break; 767f61ee201SDmitry Osipenko 76823601752SDmitry Osipenko case DEVFREQ_GOV_SUSPEND: 76923601752SDmitry Osipenko tegra_actmon_stop(tegra); 77023601752SDmitry Osipenko devfreq_monitor_suspend(devfreq); 77123601752SDmitry Osipenko break; 77223601752SDmitry Osipenko 77323601752SDmitry Osipenko case DEVFREQ_GOV_RESUME: 77423601752SDmitry Osipenko devfreq_monitor_resume(devfreq); 77511eb6ec5SDmitry Osipenko ret = tegra_actmon_start(tegra); 77623601752SDmitry Osipenko break; 77723601752SDmitry Osipenko } 77823601752SDmitry Osipenko 77911eb6ec5SDmitry Osipenko return ret; 78023601752SDmitry Osipenko } 78123601752SDmitry Osipenko 78223601752SDmitry Osipenko static struct devfreq_governor tegra_devfreq_governor = { 78323601752SDmitry Osipenko .name = "tegra_actmon", 7845f1a9066SChanwoo Choi .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL, 7850dd25a0dSChanwoo Choi .flags = DEVFREQ_GOV_FLAG_IMMUTABLE 7860dd25a0dSChanwoo Choi | DEVFREQ_GOV_FLAG_IRQ_DRIVEN, 78723601752SDmitry Osipenko .get_target_freq = tegra_governor_get_target, 78823601752SDmitry Osipenko .event_handler = tegra_governor_event_handler, 78923601752SDmitry Osipenko }; 79023601752SDmitry Osipenko 79168b79f28SDmitry Osipenko static void devm_tegra_devfreq_deinit_hw(void *data) 79268b79f28SDmitry Osipenko { 79368b79f28SDmitry Osipenko struct tegra_devfreq *tegra = data; 79468b79f28SDmitry Osipenko 79568b79f28SDmitry Osipenko reset_control_reset(tegra->reset); 79668b79f28SDmitry Osipenko clk_disable_unprepare(tegra->clock); 79768b79f28SDmitry Osipenko } 79868b79f28SDmitry Osipenko 79968b79f28SDmitry Osipenko static int devm_tegra_devfreq_init_hw(struct device *dev, 80068b79f28SDmitry Osipenko struct tegra_devfreq *tegra) 80168b79f28SDmitry Osipenko { 80268b79f28SDmitry Osipenko int err; 80368b79f28SDmitry Osipenko 80468b79f28SDmitry Osipenko err = clk_prepare_enable(tegra->clock); 80568b79f28SDmitry Osipenko if (err) { 80668b79f28SDmitry Osipenko dev_err(dev, "Failed to prepare and enable ACTMON clock\n"); 80768b79f28SDmitry Osipenko return err; 80868b79f28SDmitry Osipenko } 80968b79f28SDmitry Osipenko 81068b79f28SDmitry Osipenko err = devm_add_action_or_reset(dev, devm_tegra_devfreq_deinit_hw, 81168b79f28SDmitry Osipenko tegra); 81268b79f28SDmitry Osipenko if (err) 81368b79f28SDmitry Osipenko return err; 81468b79f28SDmitry Osipenko 81568b79f28SDmitry Osipenko err = reset_control_reset(tegra->reset); 81668b79f28SDmitry Osipenko if (err) { 81768b79f28SDmitry Osipenko dev_err(dev, "Failed to reset hardware: %d\n", err); 81868b79f28SDmitry Osipenko return err; 81968b79f28SDmitry Osipenko } 82068b79f28SDmitry Osipenko 82168b79f28SDmitry Osipenko return err; 82268b79f28SDmitry Osipenko } 82368b79f28SDmitry Osipenko 82423601752SDmitry Osipenko static int tegra_devfreq_probe(struct platform_device *pdev) 82523601752SDmitry Osipenko { 82616e8b2a7SDmitry Osipenko u32 hw_version = BIT(tegra_sku_info.soc_speedo_id); 82723601752SDmitry Osipenko struct tegra_devfreq_device *dev; 828d49eeb1eSDmitry Osipenko struct tegra_devfreq *tegra; 829d49eeb1eSDmitry Osipenko struct devfreq *devfreq; 830d49eeb1eSDmitry Osipenko unsigned int i; 8317296443bSDmitry Osipenko long rate; 83223601752SDmitry Osipenko int err; 83323601752SDmitry Osipenko 83423601752SDmitry Osipenko tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 83523601752SDmitry Osipenko if (!tegra) 83623601752SDmitry Osipenko return -ENOMEM; 83723601752SDmitry Osipenko 8386a575e84SDmitry Osipenko tegra->soc = of_device_get_match_data(&pdev->dev); 8396a575e84SDmitry Osipenko 84023601752SDmitry Osipenko tegra->regs = devm_platform_ioremap_resource(pdev, 0); 84123601752SDmitry Osipenko if (IS_ERR(tegra->regs)) 84223601752SDmitry Osipenko return PTR_ERR(tegra->regs); 84323601752SDmitry Osipenko 84423601752SDmitry Osipenko tegra->reset = devm_reset_control_get(&pdev->dev, "actmon"); 84523601752SDmitry Osipenko if (IS_ERR(tegra->reset)) { 84623601752SDmitry Osipenko dev_err(&pdev->dev, "Failed to get reset\n"); 84723601752SDmitry Osipenko return PTR_ERR(tegra->reset); 84823601752SDmitry Osipenko } 84923601752SDmitry Osipenko 85023601752SDmitry Osipenko tegra->clock = devm_clk_get(&pdev->dev, "actmon"); 85123601752SDmitry Osipenko if (IS_ERR(tegra->clock)) { 85223601752SDmitry Osipenko dev_err(&pdev->dev, "Failed to get actmon clock\n"); 85323601752SDmitry Osipenko return PTR_ERR(tegra->clock); 85423601752SDmitry Osipenko } 85523601752SDmitry Osipenko 85623601752SDmitry Osipenko tegra->emc_clock = devm_clk_get(&pdev->dev, "emc"); 85709d56d92SDmitry Osipenko if (IS_ERR(tegra->emc_clock)) 85809d56d92SDmitry Osipenko return dev_err_probe(&pdev->dev, PTR_ERR(tegra->emc_clock), 85909d56d92SDmitry Osipenko "Failed to get emc clock\n"); 86023601752SDmitry Osipenko 861dccdea01SDmitry Osipenko err = platform_get_irq(pdev, 0); 8620716f9fdSMarkus Elfring if (err < 0) 86323601752SDmitry Osipenko return err; 8640716f9fdSMarkus Elfring 865dccdea01SDmitry Osipenko tegra->irq = err; 86623601752SDmitry Osipenko 867d49eeb1eSDmitry Osipenko irq_set_status_flags(tegra->irq, IRQ_NOAUTOEN); 868d49eeb1eSDmitry Osipenko 869d49eeb1eSDmitry Osipenko err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL, 870d49eeb1eSDmitry Osipenko actmon_thread_isr, IRQF_ONESHOT, 871d49eeb1eSDmitry Osipenko "tegra-devfreq", tegra); 872d49eeb1eSDmitry Osipenko if (err) { 873d49eeb1eSDmitry Osipenko dev_err(&pdev->dev, "Interrupt request failed: %d\n", err); 874d49eeb1eSDmitry Osipenko return err; 875d49eeb1eSDmitry Osipenko } 876d49eeb1eSDmitry Osipenko 87768b79f28SDmitry Osipenko err = devm_pm_opp_set_supported_hw(&pdev->dev, &hw_version, 1); 87816e8b2a7SDmitry Osipenko if (err) { 87916e8b2a7SDmitry Osipenko dev_err(&pdev->dev, "Failed to set supported HW: %d\n", err); 88016e8b2a7SDmitry Osipenko return err; 88116e8b2a7SDmitry Osipenko } 88216e8b2a7SDmitry Osipenko 88368b79f28SDmitry Osipenko err = devm_pm_opp_of_add_table_noclk(&pdev->dev, 0); 88416e8b2a7SDmitry Osipenko if (err) { 88516e8b2a7SDmitry Osipenko dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err); 88668b79f28SDmitry Osipenko return err; 88716e8b2a7SDmitry Osipenko } 88816e8b2a7SDmitry Osipenko 88968b79f28SDmitry Osipenko err = devm_tegra_devfreq_init_hw(&pdev->dev, tegra); 89068b79f28SDmitry Osipenko if (err) 89168b79f28SDmitry Osipenko return err; 89223601752SDmitry Osipenko 8937296443bSDmitry Osipenko rate = clk_round_rate(tegra->emc_clock, ULONG_MAX); 894*4844bdbeSDmitry Osipenko if (rate <= 0) { 8957296443bSDmitry Osipenko dev_err(&pdev->dev, "Failed to round clock rate: %ld\n", rate); 896*4844bdbeSDmitry Osipenko return rate ?: -EINVAL; 8977296443bSDmitry Osipenko } 8987296443bSDmitry Osipenko 8997296443bSDmitry Osipenko tegra->max_freq = rate / KHZ; 90023601752SDmitry Osipenko 9016a575e84SDmitry Osipenko for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 90223601752SDmitry Osipenko dev = tegra->devices + i; 9036a575e84SDmitry Osipenko dev->config = tegra->soc->configs + i; 90423601752SDmitry Osipenko dev->regs = tegra->regs + dev->config->offset; 90523601752SDmitry Osipenko } 90623601752SDmitry Osipenko 90723601752SDmitry Osipenko platform_set_drvdata(pdev, tegra); 90823601752SDmitry Osipenko 9096f2a35d6SDmitry Osipenko tegra->clk_rate_change_nb.notifier_call = tegra_actmon_clk_notify_cb; 91011eb6ec5SDmitry Osipenko tegra->cpu_rate_change_nb.notifier_call = tegra_actmon_cpu_notify_cb; 91111eb6ec5SDmitry Osipenko 91211eb6ec5SDmitry Osipenko INIT_DELAYED_WORK(&tegra->cpufreq_update_work, 91311eb6ec5SDmitry Osipenko tegra_actmon_delayed_update); 91411eb6ec5SDmitry Osipenko 91568b79f28SDmitry Osipenko err = devm_devfreq_add_governor(&pdev->dev, &tegra_devfreq_governor); 91623601752SDmitry Osipenko if (err) { 91723601752SDmitry Osipenko dev_err(&pdev->dev, "Failed to add governor: %d\n", err); 91868b79f28SDmitry Osipenko return err; 91923601752SDmitry Osipenko } 92023601752SDmitry Osipenko 9216f2a35d6SDmitry Osipenko tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); 9220ce38846SDmitry Osipenko 92368b79f28SDmitry Osipenko devfreq = devm_devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, 924d49eeb1eSDmitry Osipenko "tegra_actmon", NULL); 92568b79f28SDmitry Osipenko if (IS_ERR(devfreq)) 92668b79f28SDmitry Osipenko return PTR_ERR(devfreq); 92716e8b2a7SDmitry Osipenko 92823601752SDmitry Osipenko return 0; 92923601752SDmitry Osipenko } 93023601752SDmitry Osipenko 9316a575e84SDmitry Osipenko static const struct tegra_devfreq_soc_data tegra124_soc = { 9326a575e84SDmitry Osipenko .configs = tegra124_device_configs, 9336a575e84SDmitry Osipenko 9346a575e84SDmitry Osipenko /* 9356a575e84SDmitry Osipenko * Activity counter is incremented every 256 memory transactions, 9366a575e84SDmitry Osipenko * and each transaction takes 4 EMC clocks. 9376a575e84SDmitry Osipenko */ 9386a575e84SDmitry Osipenko .count_weight = 4 * 256, 9396a575e84SDmitry Osipenko }; 9406a575e84SDmitry Osipenko 9416a575e84SDmitry Osipenko static const struct tegra_devfreq_soc_data tegra30_soc = { 9426a575e84SDmitry Osipenko .configs = tegra30_device_configs, 9436a575e84SDmitry Osipenko .count_weight = 2 * 256, 9446a575e84SDmitry Osipenko }; 9456a575e84SDmitry Osipenko 94623601752SDmitry Osipenko static const struct of_device_id tegra_devfreq_of_match[] = { 9476a575e84SDmitry Osipenko { .compatible = "nvidia,tegra30-actmon", .data = &tegra30_soc, }, 9486a575e84SDmitry Osipenko { .compatible = "nvidia,tegra124-actmon", .data = &tegra124_soc, }, 94923601752SDmitry Osipenko { }, 95023601752SDmitry Osipenko }; 95123601752SDmitry Osipenko 95223601752SDmitry Osipenko MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match); 95323601752SDmitry Osipenko 95423601752SDmitry Osipenko static struct platform_driver tegra_devfreq_driver = { 95523601752SDmitry Osipenko .probe = tegra_devfreq_probe, 95623601752SDmitry Osipenko .driver = { 95723601752SDmitry Osipenko .name = "tegra-devfreq", 95823601752SDmitry Osipenko .of_match_table = tegra_devfreq_of_match, 95923601752SDmitry Osipenko }, 96023601752SDmitry Osipenko }; 96123601752SDmitry Osipenko module_platform_driver(tegra_devfreq_driver); 96223601752SDmitry Osipenko 96323601752SDmitry Osipenko MODULE_LICENSE("GPL v2"); 96423601752SDmitry Osipenko MODULE_DESCRIPTION("Tegra devfreq driver"); 96523601752SDmitry Osipenko MODULE_AUTHOR("Tomeu Vizoso <tomeu.vizoso@collabora.com>"); 966