xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca_devfreq.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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