Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright 2019 Collabora ltd. */
0003 
0004 #include <linux/clk.h>
0005 #include <linux/devfreq.h>
0006 #include <linux/devfreq_cooling.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/pm_opp.h>
0009 
0010 #include "panfrost_device.h"
0011 #include "panfrost_devfreq.h"
0012 
0013 static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq)
0014 {
0015     ktime_t now, last;
0016 
0017     now = ktime_get();
0018     last = pfdevfreq->time_last_update;
0019 
0020     if (pfdevfreq->busy_count > 0)
0021         pfdevfreq->busy_time += ktime_sub(now, last);
0022     else
0023         pfdevfreq->idle_time += ktime_sub(now, last);
0024 
0025     pfdevfreq->time_last_update = now;
0026 }
0027 
0028 static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
0029                    u32 flags)
0030 {
0031     struct dev_pm_opp *opp;
0032 
0033     opp = devfreq_recommended_opp(dev, freq, flags);
0034     if (IS_ERR(opp))
0035         return PTR_ERR(opp);
0036     dev_pm_opp_put(opp);
0037 
0038     return dev_pm_opp_set_rate(dev, *freq);
0039 }
0040 
0041 static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq)
0042 {
0043     pfdevfreq->busy_time = 0;
0044     pfdevfreq->idle_time = 0;
0045     pfdevfreq->time_last_update = ktime_get();
0046 }
0047 
0048 static int panfrost_devfreq_get_dev_status(struct device *dev,
0049                        struct devfreq_dev_status *status)
0050 {
0051     struct panfrost_device *pfdev = dev_get_drvdata(dev);
0052     struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
0053     unsigned long irqflags;
0054 
0055     status->current_frequency = clk_get_rate(pfdev->clock);
0056 
0057     spin_lock_irqsave(&pfdevfreq->lock, irqflags);
0058 
0059     panfrost_devfreq_update_utilization(pfdevfreq);
0060 
0061     status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time,
0062                            pfdevfreq->idle_time));
0063 
0064     status->busy_time = ktime_to_ns(pfdevfreq->busy_time);
0065 
0066     panfrost_devfreq_reset(pfdevfreq);
0067 
0068     spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
0069 
0070     dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n",
0071         status->busy_time, status->total_time,
0072         status->busy_time / (status->total_time / 100),
0073         status->current_frequency / 1000 / 1000);
0074 
0075     return 0;
0076 }
0077 
0078 static struct devfreq_dev_profile panfrost_devfreq_profile = {
0079     .timer = DEVFREQ_TIMER_DELAYED,
0080     .polling_ms = 50, /* ~3 frames */
0081     .target = panfrost_devfreq_target,
0082     .get_dev_status = panfrost_devfreq_get_dev_status,
0083 };
0084 
0085 int panfrost_devfreq_init(struct panfrost_device *pfdev)
0086 {
0087     int ret;
0088     struct dev_pm_opp *opp;
0089     unsigned long cur_freq;
0090     struct device *dev = &pfdev->pdev->dev;
0091     struct devfreq *devfreq;
0092     struct thermal_cooling_device *cooling;
0093     struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
0094 
0095     if (pfdev->comp->num_supplies > 1) {
0096         /*
0097          * GPUs with more than 1 supply require platform-specific handling:
0098          * continue without devfreq
0099          */
0100         DRM_DEV_INFO(dev, "More than 1 supply is not supported yet\n");
0101         return 0;
0102     }
0103 
0104     ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names);
0105     if (ret) {
0106         /* Continue if the optional regulator is missing */
0107         if (ret != -ENODEV) {
0108             if (ret != -EPROBE_DEFER)
0109                 DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
0110             return ret;
0111         }
0112     }
0113 
0114     ret = devm_pm_opp_of_add_table(dev);
0115     if (ret) {
0116         /* Optional, continue without devfreq */
0117         if (ret == -ENODEV)
0118             ret = 0;
0119         return ret;
0120     }
0121     pfdevfreq->opp_of_table_added = true;
0122 
0123     spin_lock_init(&pfdevfreq->lock);
0124 
0125     panfrost_devfreq_reset(pfdevfreq);
0126 
0127     cur_freq = clk_get_rate(pfdev->clock);
0128 
0129     opp = devfreq_recommended_opp(dev, &cur_freq, 0);
0130     if (IS_ERR(opp))
0131         return PTR_ERR(opp);
0132 
0133     panfrost_devfreq_profile.initial_freq = cur_freq;
0134 
0135     /*
0136      * Set the recommend OPP this will enable and configure the regulator
0137      * if any and will avoid a switch off by regulator_late_cleanup()
0138      */
0139     ret = dev_pm_opp_set_opp(dev, opp);
0140     if (ret) {
0141         DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
0142         return ret;
0143     }
0144 
0145     dev_pm_opp_put(opp);
0146 
0147     /*
0148      * Setup default thresholds for the simple_ondemand governor.
0149      * The values are chosen based on experiments.
0150      */
0151     pfdevfreq->gov_data.upthreshold = 45;
0152     pfdevfreq->gov_data.downdifferential = 5;
0153 
0154     devfreq = devm_devfreq_add_device(dev, &panfrost_devfreq_profile,
0155                       DEVFREQ_GOV_SIMPLE_ONDEMAND,
0156                       &pfdevfreq->gov_data);
0157     if (IS_ERR(devfreq)) {
0158         DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
0159         return PTR_ERR(devfreq);
0160     }
0161     pfdevfreq->devfreq = devfreq;
0162 
0163     cooling = devfreq_cooling_em_register(devfreq, NULL);
0164     if (IS_ERR(cooling))
0165         DRM_DEV_INFO(dev, "Failed to register cooling device\n");
0166     else
0167         pfdevfreq->cooling = cooling;
0168 
0169     return 0;
0170 }
0171 
0172 void panfrost_devfreq_fini(struct panfrost_device *pfdev)
0173 {
0174     struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
0175 
0176     if (pfdevfreq->cooling) {
0177         devfreq_cooling_unregister(pfdevfreq->cooling);
0178         pfdevfreq->cooling = NULL;
0179     }
0180 }
0181 
0182 void panfrost_devfreq_resume(struct panfrost_device *pfdev)
0183 {
0184     struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
0185 
0186     if (!pfdevfreq->devfreq)
0187         return;
0188 
0189     panfrost_devfreq_reset(pfdevfreq);
0190 
0191     devfreq_resume_device(pfdevfreq->devfreq);
0192 }
0193 
0194 void panfrost_devfreq_suspend(struct panfrost_device *pfdev)
0195 {
0196     struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
0197 
0198     if (!pfdevfreq->devfreq)
0199         return;
0200 
0201     devfreq_suspend_device(pfdevfreq->devfreq);
0202 }
0203 
0204 void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq)
0205 {
0206     unsigned long irqflags;
0207 
0208     if (!pfdevfreq->devfreq)
0209         return;
0210 
0211     spin_lock_irqsave(&pfdevfreq->lock, irqflags);
0212 
0213     panfrost_devfreq_update_utilization(pfdevfreq);
0214 
0215     pfdevfreq->busy_count++;
0216 
0217     spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
0218 }
0219 
0220 void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq)
0221 {
0222     unsigned long irqflags;
0223 
0224     if (!pfdevfreq->devfreq)
0225         return;
0226 
0227     spin_lock_irqsave(&pfdevfreq->lock, irqflags);
0228 
0229     panfrost_devfreq_update_utilization(pfdevfreq);
0230 
0231     WARN_ON(--pfdevfreq->busy_count < 0);
0232 
0233     spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
0234 }