^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * NVIDIA Tegra20 devfreq driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 GRATE-DRIVER project
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/devfreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pm_opp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <soc/tegra/mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "governor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MC_STAT_CONTROL 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MC_STAT_EMC_CLOCK_LIMIT 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MC_STAT_EMC_CLOCKS 0xa4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MC_STAT_EMC_CONTROL 0xa8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MC_STAT_EMC_COUNT 0xb8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define EMC_GATHER_CLEAR (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define EMC_GATHER_ENABLE (3 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct tegra_devfreq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct devfreq *devfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct clk *emc_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct tegra_devfreq *tegra = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct devfreq *devfreq = tegra->devfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct dev_pm_opp *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) opp = devfreq_recommended_opp(dev, freq, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (IS_ERR(opp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return PTR_ERR(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) rate = dev_pm_opp_get_freq(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dev_pm_opp_put(opp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) err = clk_set_min_rate(tegra->emc_clock, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) err = clk_set_rate(tegra->emc_clock, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) goto restore_min_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) restore_min_rate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int tegra_devfreq_get_dev_status(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct devfreq_dev_status *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct tegra_devfreq *tegra = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * EMC_COUNT returns number of memory events, that number is lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * than the number of clocks. Conversion ratio of 1/8 results in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * bit higher bandwidth than actually needed, it is good enough for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * the time being because drivers don't support requesting minimum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * needed memory bandwidth yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * TODO: adjust the ratio value once relevant drivers will support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * memory bandwidth management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) stat->busy_time = readl_relaxed(tegra->regs + MC_STAT_EMC_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) stat->total_time = readl_relaxed(tegra->regs + MC_STAT_EMC_CLOCKS) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) stat->current_frequency = clk_get_rate(tegra->emc_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) writel_relaxed(EMC_GATHER_CLEAR, tegra->regs + MC_STAT_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) writel_relaxed(EMC_GATHER_ENABLE, tegra->regs + MC_STAT_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static struct devfreq_dev_profile tegra_devfreq_profile = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .polling_ms = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .target = tegra_devfreq_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .get_dev_status = tegra_devfreq_get_dev_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct tegra_mc *tegra_get_memory_controller(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct tegra_mc *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) np = of_find_compatible_node(NULL, NULL, "nvidia,tegra20-mc-gart");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) pdev = of_find_device_by_node(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return ERR_PTR(-EPROBE_DEFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int tegra_devfreq_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct tegra_devfreq *tegra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct tegra_mc *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long max_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) mc = tegra_get_memory_controller();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (IS_ERR(mc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) err = PTR_ERR(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dev_err(&pdev->dev, "failed to get memory controller: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!tegra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* EMC is a system-critical clock that is always enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) tegra->emc_clock = devm_clk_get(&pdev->dev, "emc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (IS_ERR(tegra->emc_clock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = PTR_ERR(tegra->emc_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) tegra->regs = mc->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) max_rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (rate = 0; rate <= max_rate; rate++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rate = clk_round_rate(tegra->emc_clock, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) err = dev_pm_opp_add(&pdev->dev, rate, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dev_err(&pdev->dev, "failed to add opp: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto remove_opps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Reset statistic gathers state, select global bandwidth for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * statistics collection mode and set clocks counter saturation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * limit to maximum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) writel_relaxed(0x00000000, tegra->regs + MC_STAT_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) writel_relaxed(0x00000000, tegra->regs + MC_STAT_EMC_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) writel_relaxed(0xffffffff, tegra->regs + MC_STAT_EMC_CLOCK_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) platform_set_drvdata(pdev, tegra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tegra->devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (IS_ERR(tegra->devfreq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) err = PTR_ERR(tegra->devfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto remove_opps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) remove_opps:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) dev_pm_opp_remove_all_dynamic(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int tegra_devfreq_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct tegra_devfreq *tegra = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) devfreq_remove_device(tegra->devfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dev_pm_opp_remove_all_dynamic(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static struct platform_driver tegra_devfreq_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .probe = tegra_devfreq_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .remove = tegra_devfreq_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .name = "tegra20-devfreq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) module_platform_driver(tegra_devfreq_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) MODULE_ALIAS("platform:tegra20-devfreq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MODULE_DESCRIPTION("NVIDIA Tegra20 devfreq driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) MODULE_LICENSE("GPL v2");