0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/devfreq.h>
0010 #include <linux/devfreq_cooling.h>
0011 #include <linux/device.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm_opp.h>
0014 #include <linux/property.h>
0015
0016 #include "lima_device.h"
0017 #include "lima_devfreq.h"
0018
0019 static void lima_devfreq_update_utilization(struct lima_devfreq *devfreq)
0020 {
0021 ktime_t now, last;
0022
0023 now = ktime_get();
0024 last = devfreq->time_last_update;
0025
0026 if (devfreq->busy_count > 0)
0027 devfreq->busy_time += ktime_sub(now, last);
0028 else
0029 devfreq->idle_time += ktime_sub(now, last);
0030
0031 devfreq->time_last_update = now;
0032 }
0033
0034 static int lima_devfreq_target(struct device *dev, unsigned long *freq,
0035 u32 flags)
0036 {
0037 struct dev_pm_opp *opp;
0038
0039 opp = devfreq_recommended_opp(dev, freq, flags);
0040 if (IS_ERR(opp))
0041 return PTR_ERR(opp);
0042 dev_pm_opp_put(opp);
0043
0044 return dev_pm_opp_set_rate(dev, *freq);
0045 }
0046
0047 static void lima_devfreq_reset(struct lima_devfreq *devfreq)
0048 {
0049 devfreq->busy_time = 0;
0050 devfreq->idle_time = 0;
0051 devfreq->time_last_update = ktime_get();
0052 }
0053
0054 static int lima_devfreq_get_dev_status(struct device *dev,
0055 struct devfreq_dev_status *status)
0056 {
0057 struct lima_device *ldev = dev_get_drvdata(dev);
0058 struct lima_devfreq *devfreq = &ldev->devfreq;
0059 unsigned long irqflags;
0060
0061 status->current_frequency = clk_get_rate(ldev->clk_gpu);
0062
0063 spin_lock_irqsave(&devfreq->lock, irqflags);
0064
0065 lima_devfreq_update_utilization(devfreq);
0066
0067 status->total_time = ktime_to_ns(ktime_add(devfreq->busy_time,
0068 devfreq->idle_time));
0069 status->busy_time = ktime_to_ns(devfreq->busy_time);
0070
0071 lima_devfreq_reset(devfreq);
0072
0073 spin_unlock_irqrestore(&devfreq->lock, irqflags);
0074
0075 dev_dbg(ldev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n",
0076 status->busy_time, status->total_time,
0077 status->busy_time / (status->total_time / 100),
0078 status->current_frequency / 1000 / 1000);
0079
0080 return 0;
0081 }
0082
0083 static struct devfreq_dev_profile lima_devfreq_profile = {
0084 .timer = DEVFREQ_TIMER_DELAYED,
0085 .polling_ms = 50,
0086 .target = lima_devfreq_target,
0087 .get_dev_status = lima_devfreq_get_dev_status,
0088 };
0089
0090 void lima_devfreq_fini(struct lima_device *ldev)
0091 {
0092 struct lima_devfreq *devfreq = &ldev->devfreq;
0093
0094 if (devfreq->cooling) {
0095 devfreq_cooling_unregister(devfreq->cooling);
0096 devfreq->cooling = NULL;
0097 }
0098
0099 if (devfreq->devfreq) {
0100 devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
0101 devfreq->devfreq = NULL;
0102 }
0103 }
0104
0105 int lima_devfreq_init(struct lima_device *ldev)
0106 {
0107 struct thermal_cooling_device *cooling;
0108 struct device *dev = ldev->dev;
0109 struct devfreq *devfreq;
0110 struct lima_devfreq *ldevfreq = &ldev->devfreq;
0111 struct dev_pm_opp *opp;
0112 unsigned long cur_freq;
0113 int ret;
0114 const char *regulator_names[] = { "mali", NULL };
0115 const char *clk_names[] = { "core", NULL };
0116 struct dev_pm_opp_config config = {
0117 .regulator_names = regulator_names,
0118 .clk_names = clk_names,
0119 };
0120
0121 if (!device_property_present(dev, "operating-points-v2"))
0122
0123 return 0;
0124
0125 spin_lock_init(&ldevfreq->lock);
0126
0127 ret = devm_pm_opp_set_config(dev, &config);
0128 if (ret) {
0129
0130 if (ret != -ENODEV)
0131 return ret;
0132 }
0133
0134 ret = devm_pm_opp_of_add_table(dev);
0135 if (ret)
0136 return ret;
0137
0138 lima_devfreq_reset(ldevfreq);
0139
0140 cur_freq = clk_get_rate(ldev->clk_gpu);
0141
0142 opp = devfreq_recommended_opp(dev, &cur_freq, 0);
0143 if (IS_ERR(opp))
0144 return PTR_ERR(opp);
0145
0146 lima_devfreq_profile.initial_freq = cur_freq;
0147 dev_pm_opp_put(opp);
0148
0149
0150
0151
0152
0153 ldevfreq->gov_data.upthreshold = 30;
0154 ldevfreq->gov_data.downdifferential = 5;
0155
0156 devfreq = devm_devfreq_add_device(dev, &lima_devfreq_profile,
0157 DEVFREQ_GOV_SIMPLE_ONDEMAND,
0158 &ldevfreq->gov_data);
0159 if (IS_ERR(devfreq)) {
0160 dev_err(dev, "Couldn't initialize GPU devfreq\n");
0161 return PTR_ERR(devfreq);
0162 }
0163
0164 ldevfreq->devfreq = devfreq;
0165
0166 cooling = of_devfreq_cooling_register(dev->of_node, devfreq);
0167 if (IS_ERR(cooling))
0168 dev_info(dev, "Failed to register cooling device\n");
0169 else
0170 ldevfreq->cooling = cooling;
0171
0172 return 0;
0173 }
0174
0175 void lima_devfreq_record_busy(struct lima_devfreq *devfreq)
0176 {
0177 unsigned long irqflags;
0178
0179 if (!devfreq->devfreq)
0180 return;
0181
0182 spin_lock_irqsave(&devfreq->lock, irqflags);
0183
0184 lima_devfreq_update_utilization(devfreq);
0185
0186 devfreq->busy_count++;
0187
0188 spin_unlock_irqrestore(&devfreq->lock, irqflags);
0189 }
0190
0191 void lima_devfreq_record_idle(struct lima_devfreq *devfreq)
0192 {
0193 unsigned long irqflags;
0194
0195 if (!devfreq->devfreq)
0196 return;
0197
0198 spin_lock_irqsave(&devfreq->lock, irqflags);
0199
0200 lima_devfreq_update_utilization(devfreq);
0201
0202 WARN_ON(--devfreq->busy_count < 0);
0203
0204 spin_unlock_irqrestore(&devfreq->lock, irqflags);
0205 }
0206
0207 int lima_devfreq_resume(struct lima_devfreq *devfreq)
0208 {
0209 unsigned long irqflags;
0210
0211 if (!devfreq->devfreq)
0212 return 0;
0213
0214 spin_lock_irqsave(&devfreq->lock, irqflags);
0215
0216 lima_devfreq_reset(devfreq);
0217
0218 spin_unlock_irqrestore(&devfreq->lock, irqflags);
0219
0220 return devfreq_resume_device(devfreq->devfreq);
0221 }
0222
0223 int lima_devfreq_suspend(struct lima_devfreq *devfreq)
0224 {
0225 if (!devfreq->devfreq)
0226 return 0;
0227
0228 return devfreq_suspend_device(devfreq->devfreq);
0229 }