1 /*
2 *
3 * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
4 *
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
8 * of such GNU licence.
9 *
10 * A copy of the licence is included with the program, and can also be obtained
11 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12 * Boston, MA 02110-1301, USA.
13 *
14 */
15
16
17
18 /*
19 * A core availability policy implementing core mask selection from devfreq OPPs
20 *
21 */
22
23 #include <mali_kbase.h>
24 #include <mali_kbase_pm.h>
25 #include <backend/gpu/mali_kbase_pm_internal.h>
26 #include <linux/version.h>
27
kbase_devfreq_set_core_mask(struct kbase_device * kbdev,u64 core_mask)28 void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
29 {
30 struct kbasep_pm_ca_policy_devfreq *data =
31 &kbdev->pm.backend.ca_policy_data.devfreq;
32 unsigned long flags;
33
34 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
35
36 data->cores_desired = core_mask;
37
38 /* Disable any cores that are now unwanted */
39 data->cores_enabled &= data->cores_desired;
40
41 kbdev->pm.backend.ca_in_transition = true;
42
43 /* If there are no cores to be powered off then power on desired cores
44 */
45 if (!(data->cores_used & ~data->cores_desired)) {
46 data->cores_enabled = data->cores_desired;
47 kbdev->pm.backend.ca_in_transition = false;
48 }
49
50 kbase_pm_update_cores_state_nolock(kbdev);
51
52 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
53
54 dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX %llX\n",
55 data->cores_desired, data->cores_enabled);
56 }
57
devfreq_init(struct kbase_device * kbdev)58 static void devfreq_init(struct kbase_device *kbdev)
59 {
60 struct kbasep_pm_ca_policy_devfreq *data =
61 &kbdev->pm.backend.ca_policy_data.devfreq;
62
63 if (kbdev->current_core_mask) {
64 data->cores_enabled = kbdev->current_core_mask;
65 data->cores_desired = kbdev->current_core_mask;
66 } else {
67 data->cores_enabled =
68 kbdev->gpu_props.props.raw_props.shader_present;
69 data->cores_desired =
70 kbdev->gpu_props.props.raw_props.shader_present;
71 }
72 data->cores_used = 0;
73 kbdev->pm.backend.ca_in_transition = false;
74 }
75
devfreq_term(struct kbase_device * kbdev)76 static void devfreq_term(struct kbase_device *kbdev)
77 {
78 }
79
devfreq_get_core_mask(struct kbase_device * kbdev)80 static u64 devfreq_get_core_mask(struct kbase_device *kbdev)
81 {
82 return kbdev->pm.backend.ca_policy_data.devfreq.cores_enabled;
83 }
84
devfreq_update_core_status(struct kbase_device * kbdev,u64 cores_ready,u64 cores_transitioning)85 static void devfreq_update_core_status(struct kbase_device *kbdev,
86 u64 cores_ready,
87 u64 cores_transitioning)
88 {
89 struct kbasep_pm_ca_policy_devfreq *data =
90 &kbdev->pm.backend.ca_policy_data.devfreq;
91
92 lockdep_assert_held(&kbdev->hwaccess_lock);
93
94 data->cores_used = cores_ready | cores_transitioning;
95
96 /* If in desired state then clear transition flag */
97 if (data->cores_enabled == data->cores_desired)
98 kbdev->pm.backend.ca_in_transition = false;
99
100 /* If all undesired cores are now off then power on desired cores.
101 * The direct comparison against cores_enabled limits potential
102 * recursion to one level */
103 if (!(data->cores_used & ~data->cores_desired) &&
104 data->cores_enabled != data->cores_desired) {
105 data->cores_enabled = data->cores_desired;
106
107 kbase_pm_update_cores_state_nolock(kbdev);
108
109 kbdev->pm.backend.ca_in_transition = false;
110 }
111 }
112
113 /*
114 * The struct kbase_pm_ca_policy structure for the devfreq core availability
115 * policy.
116 *
117 * This is the static structure that defines the devfreq core availability power
118 * policy's callback and name.
119 */
120 const struct kbase_pm_ca_policy kbase_pm_ca_devfreq_policy_ops = {
121 "devfreq", /* name */
122 devfreq_init, /* init */
123 devfreq_term, /* term */
124 devfreq_get_core_mask, /* get_core_mask */
125 devfreq_update_core_status, /* update_core_status */
126 0u, /* flags */
127 KBASE_PM_CA_POLICY_ID_DEVFREQ, /* id */
128 };
129
130