1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright 2019 Collabora ltd. */ 3 4 #include <linux/clk.h> 5 #include <linux/devfreq.h> 6 #include <linux/devfreq_cooling.h> 7 #include <linux/platform_device.h> 8 #include <linux/pm_opp.h> 9 10 #include "panfrost_device.h" 11 #include "panfrost_devfreq.h" 12 13 static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) 14 { 15 ktime_t now, last; 16 17 now = ktime_get(); 18 last = pfdevfreq->time_last_update; 19 20 if (pfdevfreq->busy_count > 0) 21 pfdevfreq->busy_time += ktime_sub(now, last); 22 else 23 pfdevfreq->idle_time += ktime_sub(now, last); 24 25 pfdevfreq->time_last_update = now; 26 } 27 28 static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, 29 u32 flags) 30 { 31 struct dev_pm_opp *opp; 32 int err; 33 34 opp = devfreq_recommended_opp(dev, freq, flags); 35 if (IS_ERR(opp)) 36 return PTR_ERR(opp); 37 dev_pm_opp_put(opp); 38 39 err = dev_pm_opp_set_rate(dev, *freq); 40 if (err) 41 return err; 42 43 return 0; 44 } 45 46 static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq) 47 { 48 pfdevfreq->busy_time = 0; 49 pfdevfreq->idle_time = 0; 50 pfdevfreq->time_last_update = ktime_get(); 51 } 52 53 static int panfrost_devfreq_get_dev_status(struct device *dev, 54 struct devfreq_dev_status *status) 55 { 56 struct panfrost_device *pfdev = dev_get_drvdata(dev); 57 struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; 58 unsigned long irqflags; 59 60 status->current_frequency = clk_get_rate(pfdev->clock); 61 62 spin_lock_irqsave(&pfdevfreq->lock, irqflags); 63 64 panfrost_devfreq_update_utilization(pfdevfreq); 65 66 status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, 67 pfdevfreq->idle_time)); 68 69 status->busy_time = ktime_to_ns(pfdevfreq->busy_time); 70 71 panfrost_devfreq_reset(pfdevfreq); 72 73 spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); 74 75 dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", 76 status->busy_time, status->total_time, 77 status->busy_time / (status->total_time / 100), 78 status->current_frequency / 1000 / 1000); 79 80 return 0; 81 } 82 83 static struct devfreq_dev_profile panfrost_devfreq_profile = { 84 .polling_ms = 50, /* ~3 frames */ 85 .target = panfrost_devfreq_target, 86 .get_dev_status = panfrost_devfreq_get_dev_status, 87 }; 88 89 int panfrost_devfreq_init(struct panfrost_device *pfdev) 90 { 91 int ret; 92 struct dev_pm_opp *opp; 93 unsigned long cur_freq; 94 struct device *dev = &pfdev->pdev->dev; 95 struct devfreq *devfreq; 96 struct opp_table *opp_table; 97 struct thermal_cooling_device *cooling; 98 struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; 99 100 opp_table = dev_pm_opp_set_regulators(dev, pfdev->comp->supply_names, 101 pfdev->comp->num_supplies); 102 if (IS_ERR(opp_table)) { 103 ret = PTR_ERR(opp_table); 104 /* Continue if the optional regulator is missing */ 105 if (ret != -ENODEV) { 106 DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); 107 goto err_fini; 108 } 109 } else { 110 pfdevfreq->regulators_opp_table = opp_table; 111 } 112 113 ret = dev_pm_opp_of_add_table(dev); 114 if (ret) { 115 /* Optional, continue without devfreq */ 116 if (ret == -ENODEV) 117 ret = 0; 118 goto err_fini; 119 } 120 pfdevfreq->opp_of_table_added = true; 121 122 spin_lock_init(&pfdevfreq->lock); 123 124 panfrost_devfreq_reset(pfdevfreq); 125 126 cur_freq = clk_get_rate(pfdev->clock); 127 128 opp = devfreq_recommended_opp(dev, &cur_freq, 0); 129 if (IS_ERR(opp)) { 130 ret = PTR_ERR(opp); 131 goto err_fini; 132 } 133 134 panfrost_devfreq_profile.initial_freq = cur_freq; 135 dev_pm_opp_put(opp); 136 137 devfreq = devm_devfreq_add_device(dev, &panfrost_devfreq_profile, 138 DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); 139 if (IS_ERR(devfreq)) { 140 DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); 141 ret = PTR_ERR(devfreq); 142 goto err_fini; 143 } 144 pfdevfreq->devfreq = devfreq; 145 146 cooling = of_devfreq_cooling_register(dev->of_node, devfreq); 147 if (IS_ERR(cooling)) 148 DRM_DEV_INFO(dev, "Failed to register cooling device\n"); 149 else 150 pfdevfreq->cooling = cooling; 151 152 return 0; 153 154 err_fini: 155 panfrost_devfreq_fini(pfdev); 156 return ret; 157 } 158 159 void panfrost_devfreq_fini(struct panfrost_device *pfdev) 160 { 161 struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; 162 163 if (pfdevfreq->cooling) { 164 devfreq_cooling_unregister(pfdevfreq->cooling); 165 pfdevfreq->cooling = NULL; 166 } 167 168 if (pfdevfreq->opp_of_table_added) { 169 dev_pm_opp_of_remove_table(&pfdev->pdev->dev); 170 pfdevfreq->opp_of_table_added = false; 171 } 172 173 if (pfdevfreq->regulators_opp_table) { 174 dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); 175 pfdevfreq->regulators_opp_table = NULL; 176 } 177 } 178 179 void panfrost_devfreq_resume(struct panfrost_device *pfdev) 180 { 181 struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; 182 183 if (!pfdevfreq->devfreq) 184 return; 185 186 panfrost_devfreq_reset(pfdevfreq); 187 188 devfreq_resume_device(pfdevfreq->devfreq); 189 } 190 191 void panfrost_devfreq_suspend(struct panfrost_device *pfdev) 192 { 193 struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; 194 195 if (!pfdevfreq->devfreq) 196 return; 197 198 devfreq_suspend_device(pfdevfreq->devfreq); 199 } 200 201 void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) 202 { 203 unsigned long irqflags; 204 205 if (!pfdevfreq->devfreq) 206 return; 207 208 spin_lock_irqsave(&pfdevfreq->lock, irqflags); 209 210 panfrost_devfreq_update_utilization(pfdevfreq); 211 212 pfdevfreq->busy_count++; 213 214 spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); 215 } 216 217 void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) 218 { 219 unsigned long irqflags; 220 221 if (!pfdevfreq->devfreq) 222 return; 223 224 spin_lock_irqsave(&pfdevfreq->lock, irqflags); 225 226 panfrost_devfreq_update_utilization(pfdevfreq); 227 228 WARN_ON(--pfdevfreq->busy_count < 0); 229 230 spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); 231 } 232