cpufreq_opp.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Generic OPP helper interface for CPUFreq drivers
  3. *
  4. * Copyright (C) 2009-2014 Texas Instruments Incorporated.
  5. * Nishanth Menon
  6. * Romit Dasgupta
  7. * Kevin Hilman
  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. #include <linux/cpufreq.h>
  14. #include <linux/device.h>
  15. #include <linux/err.h>
  16. #include <linux/errno.h>
  17. #include <linux/export.h>
  18. #include <linux/kernel.h>
  19. #include <linux/pm_opp.h>
  20. #include <linux/rcupdate.h>
  21. #include <linux/slab.h>
  22. /**
  23. * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
  24. * @dev: device for which we do this operation
  25. * @table: Cpufreq table returned back to caller
  26. *
  27. * Generate a cpufreq table for a provided device- this assumes that the
  28. * opp list is already initialized and ready for usage.
  29. *
  30. * This function allocates required memory for the cpufreq table. It is
  31. * expected that the caller does the required maintenance such as freeing
  32. * the table as required.
  33. *
  34. * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
  35. * if no memory available for the operation (table is not populated), returns 0
  36. * if successful and table is populated.
  37. *
  38. * WARNING: It is important for the callers to ensure refreshing their copy of
  39. * the table if any of the mentioned functions have been invoked in the interim.
  40. *
  41. * Locking: The internal device_opp and opp structures are RCU protected.
  42. * Since we just use the regular accessor functions to access the internal data
  43. * structures, we use RCU read lock inside this function. As a result, users of
  44. * this function DONOT need to use explicit locks for invoking.
  45. */
  46. int dev_pm_opp_init_cpufreq_table(struct device *dev,
  47. struct cpufreq_frequency_table **table)
  48. {
  49. struct dev_pm_opp *opp;
  50. struct cpufreq_frequency_table *freq_table = NULL;
  51. int i, max_opps, ret = 0;
  52. unsigned long rate;
  53. rcu_read_lock();
  54. max_opps = dev_pm_opp_get_opp_count(dev);
  55. if (max_opps <= 0) {
  56. ret = max_opps ? max_opps : -ENODATA;
  57. goto out;
  58. }
  59. freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
  60. if (!freq_table) {
  61. ret = -ENOMEM;
  62. goto out;
  63. }
  64. for (i = 0, rate = 0; i < max_opps; i++, rate++) {
  65. /* find next rate */
  66. opp = dev_pm_opp_find_freq_ceil(dev, &rate);
  67. if (IS_ERR(opp)) {
  68. ret = PTR_ERR(opp);
  69. goto out;
  70. }
  71. freq_table[i].driver_data = i;
  72. freq_table[i].frequency = rate / 1000;
  73. }
  74. freq_table[i].driver_data = i;
  75. freq_table[i].frequency = CPUFREQ_TABLE_END;
  76. *table = &freq_table[0];
  77. out:
  78. rcu_read_unlock();
  79. if (ret)
  80. kfree(freq_table);
  81. return ret;
  82. }
  83. EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
  84. /**
  85. * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
  86. * @dev: device for which we do this operation
  87. * @table: table to free
  88. *
  89. * Free up the table allocated by dev_pm_opp_init_cpufreq_table
  90. */
  91. void dev_pm_opp_free_cpufreq_table(struct device *dev,
  92. struct cpufreq_frequency_table **table)
  93. {
  94. if (!table)
  95. return;
  96. kfree(*table);
  97. *table = NULL;
  98. }
  99. EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);