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