1/* 2 * Copyright (c) 2012 Samsung Electronics Co., Ltd. 3 * http://www.samsung.com/ 4 * 5 * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework 6 * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com> 7 * Support for only EXYNOS5250 is present. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14 15#include <linux/module.h> 16#include <linux/devfreq.h> 17#include <linux/io.h> 18#include <linux/pm_opp.h> 19#include <linux/slab.h> 20#include <linux/suspend.h> 21#include <linux/clk.h> 22#include <linux/delay.h> 23#include <linux/platform_device.h> 24#include <linux/pm_qos.h> 25#include <linux/regulator/consumer.h> 26#include <linux/of_address.h> 27#include <linux/of_platform.h> 28 29#include "exynos_ppmu.h" 30 31#define MAX_SAFEVOLT 1100000 /* 1.10V */ 32/* Assume that the bus is saturated if the utilization is 25% */ 33#define INT_BUS_SATURATION_RATIO 25 34 35enum int_level_idx { 36 LV_0, 37 LV_1, 38 LV_2, 39 LV_3, 40 LV_4, 41 _LV_END 42}; 43 44enum exynos_ppmu_list { 45 PPMU_RIGHT, 46 PPMU_END, 47}; 48 49struct busfreq_data_int { 50 struct device *dev; 51 struct devfreq *devfreq; 52 struct regulator *vdd_int; 53 struct busfreq_ppmu_data ppmu_data; 54 unsigned long curr_freq; 55 bool disabled; 56 57 struct notifier_block pm_notifier; 58 struct mutex lock; 59 struct pm_qos_request int_req; 60 struct clk *int_clk; 61}; 62 63struct int_bus_opp_table { 64 unsigned int idx; 65 unsigned long clk; 66 unsigned long volt; 67}; 68 69static struct int_bus_opp_table exynos5_int_opp_table[] = { 70 {LV_0, 266000, 1025000}, 71 {LV_1, 200000, 1025000}, 72 {LV_2, 160000, 1025000}, 73 {LV_3, 133000, 1025000}, 74 {LV_4, 100000, 1025000}, 75 {0, 0, 0}, 76}; 77 78static int exynos5_int_setvolt(struct busfreq_data_int *data, 79 unsigned long volt) 80{ 81 return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT); 82} 83 84static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq, 85 u32 flags) 86{ 87 int err = 0; 88 struct platform_device *pdev = container_of(dev, struct platform_device, 89 dev); 90 struct busfreq_data_int *data = platform_get_drvdata(pdev); 91 struct dev_pm_opp *opp; 92 unsigned long old_freq, freq; 93 unsigned long volt; 94 95 rcu_read_lock(); 96 opp = devfreq_recommended_opp(dev, _freq, flags); 97 if (IS_ERR(opp)) { 98 rcu_read_unlock(); 99 dev_err(dev, "%s: Invalid OPP.\n", __func__); 100 return PTR_ERR(opp); 101 } 102 103 freq = dev_pm_opp_get_freq(opp); 104 volt = dev_pm_opp_get_voltage(opp); 105 rcu_read_unlock(); 106 107 old_freq = data->curr_freq; 108 109 if (old_freq == freq) 110 return 0; 111 112 dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt); 113 114 mutex_lock(&data->lock); 115 116 if (data->disabled) 117 goto out; 118 119 if (freq > exynos5_int_opp_table[0].clk) 120 pm_qos_update_request(&data->int_req, freq * 16 / 1000); 121 else 122 pm_qos_update_request(&data->int_req, -1); 123 124 if (old_freq < freq) 125 err = exynos5_int_setvolt(data, volt); 126 if (err) 127 goto out; 128 129 err = clk_set_rate(data->int_clk, freq * 1000); 130 131 if (err) 132 goto out; 133 134 if (old_freq > freq) 135 err = exynos5_int_setvolt(data, volt); 136 if (err) 137 goto out; 138 139 data->curr_freq = freq; 140out: 141 mutex_unlock(&data->lock); 142 return err; 143} 144 145static int exynos5_int_get_dev_status(struct device *dev, 146 struct devfreq_dev_status *stat) 147{ 148 struct platform_device *pdev = container_of(dev, struct platform_device, 149 dev); 150 struct busfreq_data_int *data = platform_get_drvdata(pdev); 151 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; 152 int busier_dmc; 153 154 exynos_read_ppmu(ppmu_data); 155 busier_dmc = exynos_get_busier_ppmu(ppmu_data); 156 157 stat->current_frequency = data->curr_freq; 158 159 /* Number of cycles spent on memory access */ 160 stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3]; 161 stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO; 162 stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt; 163 164 return 0; 165} 166 167static struct devfreq_dev_profile exynos5_devfreq_int_profile = { 168 .initial_freq = 160000, 169 .polling_ms = 100, 170 .target = exynos5_busfreq_int_target, 171 .get_dev_status = exynos5_int_get_dev_status, 172}; 173 174static int exynos5250_init_int_tables(struct busfreq_data_int *data) 175{ 176 int i, err = 0; 177 178 for (i = LV_0; i < _LV_END; i++) { 179 err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk, 180 exynos5_int_opp_table[i].volt); 181 if (err) { 182 dev_err(data->dev, "Cannot add opp entries.\n"); 183 return err; 184 } 185 } 186 187 return 0; 188} 189 190static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this, 191 unsigned long event, void *ptr) 192{ 193 struct busfreq_data_int *data = container_of(this, 194 struct busfreq_data_int, pm_notifier); 195 struct dev_pm_opp *opp; 196 unsigned long maxfreq = ULONG_MAX; 197 unsigned long freq; 198 unsigned long volt; 199 int err = 0; 200 201 switch (event) { 202 case PM_SUSPEND_PREPARE: 203 /* Set Fastest and Deactivate DVFS */ 204 mutex_lock(&data->lock); 205 206 data->disabled = true; 207 208 rcu_read_lock(); 209 opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq); 210 if (IS_ERR(opp)) { 211 rcu_read_unlock(); 212 err = PTR_ERR(opp); 213 goto unlock; 214 } 215 freq = dev_pm_opp_get_freq(opp); 216 volt = dev_pm_opp_get_voltage(opp); 217 rcu_read_unlock(); 218 219 err = exynos5_int_setvolt(data, volt); 220 if (err) 221 goto unlock; 222 223 err = clk_set_rate(data->int_clk, freq * 1000); 224 225 if (err) 226 goto unlock; 227 228 data->curr_freq = freq; 229unlock: 230 mutex_unlock(&data->lock); 231 if (err) 232 return NOTIFY_BAD; 233 return NOTIFY_OK; 234 case PM_POST_RESTORE: 235 case PM_POST_SUSPEND: 236 /* Reactivate */ 237 mutex_lock(&data->lock); 238 data->disabled = false; 239 mutex_unlock(&data->lock); 240 return NOTIFY_OK; 241 } 242 243 return NOTIFY_DONE; 244} 245 246static int exynos5_busfreq_int_probe(struct platform_device *pdev) 247{ 248 struct busfreq_data_int *data; 249 struct busfreq_ppmu_data *ppmu_data; 250 struct dev_pm_opp *opp; 251 struct device *dev = &pdev->dev; 252 struct device_node *np; 253 unsigned long initial_freq; 254 unsigned long initial_volt; 255 int err = 0; 256 int i; 257 258 data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int), 259 GFP_KERNEL); 260 if (data == NULL) { 261 dev_err(dev, "Cannot allocate memory.\n"); 262 return -ENOMEM; 263 } 264 265 ppmu_data = &data->ppmu_data; 266 ppmu_data->ppmu_end = PPMU_END; 267 ppmu_data->ppmu = devm_kzalloc(dev, 268 sizeof(struct exynos_ppmu) * PPMU_END, 269 GFP_KERNEL); 270 if (!ppmu_data->ppmu) { 271 dev_err(dev, "Failed to allocate memory for exynos_ppmu\n"); 272 return -ENOMEM; 273 } 274 275 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu"); 276 if (np == NULL) { 277 pr_err("Unable to find PPMU node\n"); 278 return -ENOENT; 279 } 280 281 for (i = 0; i < ppmu_data->ppmu_end; i++) { 282 /* map PPMU memory region */ 283 ppmu_data->ppmu[i].hw_base = of_iomap(np, i); 284 if (ppmu_data->ppmu[i].hw_base == NULL) { 285 dev_err(&pdev->dev, "failed to map memory region\n"); 286 return -ENOMEM; 287 } 288 } 289 data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event; 290 data->dev = dev; 291 mutex_init(&data->lock); 292 293 err = exynos5250_init_int_tables(data); 294 if (err) 295 return err; 296 297 data->vdd_int = devm_regulator_get(dev, "vdd_int"); 298 if (IS_ERR(data->vdd_int)) { 299 dev_err(dev, "Cannot get the regulator \"vdd_int\"\n"); 300 return PTR_ERR(data->vdd_int); 301 } 302 303 data->int_clk = devm_clk_get(dev, "int_clk"); 304 if (IS_ERR(data->int_clk)) { 305 dev_err(dev, "Cannot get clock \"int_clk\"\n"); 306 return PTR_ERR(data->int_clk); 307 } 308 309 rcu_read_lock(); 310 opp = dev_pm_opp_find_freq_floor(dev, 311 &exynos5_devfreq_int_profile.initial_freq); 312 if (IS_ERR(opp)) { 313 rcu_read_unlock(); 314 dev_err(dev, "Invalid initial frequency %lu kHz.\n", 315 exynos5_devfreq_int_profile.initial_freq); 316 return PTR_ERR(opp); 317 } 318 initial_freq = dev_pm_opp_get_freq(opp); 319 initial_volt = dev_pm_opp_get_voltage(opp); 320 rcu_read_unlock(); 321 data->curr_freq = initial_freq; 322 323 err = clk_set_rate(data->int_clk, initial_freq * 1000); 324 if (err) { 325 dev_err(dev, "Failed to set initial frequency\n"); 326 return err; 327 } 328 329 err = exynos5_int_setvolt(data, initial_volt); 330 if (err) 331 return err; 332 333 platform_set_drvdata(pdev, data); 334 335 busfreq_mon_reset(ppmu_data); 336 337 data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile, 338 "simple_ondemand", NULL); 339 if (IS_ERR(data->devfreq)) 340 return PTR_ERR(data->devfreq); 341 342 err = devm_devfreq_register_opp_notifier(dev, data->devfreq); 343 if (err < 0) { 344 dev_err(dev, "Failed to register opp notifier\n"); 345 return err; 346 } 347 348 err = register_pm_notifier(&data->pm_notifier); 349 if (err) { 350 dev_err(dev, "Failed to setup pm notifier\n"); 351 return err; 352 } 353 354 /* TODO: Add a new QOS class for int/mif bus */ 355 pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1); 356 357 return 0; 358} 359 360static int exynos5_busfreq_int_remove(struct platform_device *pdev) 361{ 362 struct busfreq_data_int *data = platform_get_drvdata(pdev); 363 364 pm_qos_remove_request(&data->int_req); 365 unregister_pm_notifier(&data->pm_notifier); 366 367 return 0; 368} 369 370#ifdef CONFIG_PM_SLEEP 371static int exynos5_busfreq_int_resume(struct device *dev) 372{ 373 struct platform_device *pdev = container_of(dev, struct platform_device, 374 dev); 375 struct busfreq_data_int *data = platform_get_drvdata(pdev); 376 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; 377 378 busfreq_mon_reset(ppmu_data); 379 return 0; 380} 381static const struct dev_pm_ops exynos5_busfreq_int_pm = { 382 .resume = exynos5_busfreq_int_resume, 383}; 384#endif 385static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL, 386 exynos5_busfreq_int_resume); 387 388/* platform device pointer for exynos5 devfreq device. */ 389static struct platform_device *exynos5_devfreq_pdev; 390 391static struct platform_driver exynos5_busfreq_int_driver = { 392 .probe = exynos5_busfreq_int_probe, 393 .remove = exynos5_busfreq_int_remove, 394 .driver = { 395 .name = "exynos5-bus-int", 396 .pm = &exynos5_busfreq_int_pm_ops, 397 }, 398}; 399 400static int __init exynos5_busfreq_int_init(void) 401{ 402 int ret; 403 404 ret = platform_driver_register(&exynos5_busfreq_int_driver); 405 if (ret < 0) 406 goto out; 407 408 exynos5_devfreq_pdev = 409 platform_device_register_simple("exynos5-bus-int", -1, NULL, 0); 410 if (IS_ERR(exynos5_devfreq_pdev)) { 411 ret = PTR_ERR(exynos5_devfreq_pdev); 412 goto out1; 413 } 414 415 return 0; 416out1: 417 platform_driver_unregister(&exynos5_busfreq_int_driver); 418out: 419 return ret; 420} 421late_initcall(exynos5_busfreq_int_init); 422 423static void __exit exynos5_busfreq_int_exit(void) 424{ 425 platform_device_unregister(exynos5_devfreq_pdev); 426 platform_driver_unregister(&exynos5_busfreq_int_driver); 427} 428module_exit(exynos5_busfreq_int_exit); 429 430MODULE_LICENSE("GPL"); 431MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework"); 432