xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/common/mali_pm_domain.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2013-2014, 2016-2017 ARM Limited. All rights reserved.
3  *
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  *
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10 
11 #include "mali_kernel_common.h"
12 #include "mali_osk.h"
13 #include "mali_pm_domain.h"
14 #include "mali_pmu.h"
15 #include "mali_group.h"
16 #include "mali_pm.h"
17 
18 static struct mali_pm_domain *mali_pm_domains[MALI_MAX_NUMBER_OF_DOMAINS] =
19 { NULL, };
20 
mali_pm_domain_initialize(void)21 void mali_pm_domain_initialize(void)
22 {
23 	/* Domains will be initialized/created on demand */
24 }
25 
mali_pm_domain_terminate(void)26 void mali_pm_domain_terminate(void)
27 {
28 	int i;
29 
30 	/* Delete all domains that has been created */
31 	for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
32 		mali_pm_domain_delete(mali_pm_domains[i]);
33 		mali_pm_domains[i] = NULL;
34 	}
35 }
36 
mali_pm_domain_create(u32 pmu_mask)37 struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask)
38 {
39 	struct mali_pm_domain *domain = NULL;
40 	u32 domain_id = 0;
41 
42 	domain = mali_pm_domain_get_from_mask(pmu_mask);
43 	if (NULL != domain) return domain;
44 
45 	MALI_DEBUG_PRINT(2,
46 			 ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n",
47 			  pmu_mask));
48 
49 	domain = (struct mali_pm_domain *)_mali_osk_malloc(
50 			 sizeof(struct mali_pm_domain));
51 	if (NULL != domain) {
52 		domain->power_is_on = MALI_FALSE;
53 		domain->pmu_mask = pmu_mask;
54 		domain->use_count = 0;
55 		_mali_osk_list_init(&domain->group_list);
56 		_mali_osk_list_init(&domain->l2_cache_list);
57 
58 		domain_id = _mali_osk_fls(pmu_mask) - 1;
59 		/* Verify the domain_id */
60 		MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > domain_id);
61 		/* Verify that pmu_mask only one bit is set */
62 		MALI_DEBUG_ASSERT((1 << domain_id) == pmu_mask);
63 		mali_pm_domains[domain_id] = domain;
64 
65 		return domain;
66 	} else {
67 		MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n"));
68 	}
69 
70 	return NULL;
71 }
72 
mali_pm_domain_delete(struct mali_pm_domain * domain)73 void mali_pm_domain_delete(struct mali_pm_domain *domain)
74 {
75 	if (NULL == domain) {
76 		return;
77 	}
78 
79 	_mali_osk_list_delinit(&domain->group_list);
80 	_mali_osk_list_delinit(&domain->l2_cache_list);
81 
82 	_mali_osk_free(domain);
83 }
84 
mali_pm_domain_add_group(struct mali_pm_domain * domain,struct mali_group * group)85 void mali_pm_domain_add_group(struct mali_pm_domain *domain,
86 			      struct mali_group *group)
87 {
88 	MALI_DEBUG_ASSERT_POINTER(domain);
89 	MALI_DEBUG_ASSERT_POINTER(group);
90 
91 	/*
92 	 * Use addtail because virtual group is created last and it needs
93 	 * to be at the end of the list (in order to be activated after
94 	 * all children.
95 	 */
96 	_mali_osk_list_addtail(&group->pm_domain_list, &domain->group_list);
97 }
98 
mali_pm_domain_add_l2_cache(struct mali_pm_domain * domain,struct mali_l2_cache_core * l2_cache)99 void mali_pm_domain_add_l2_cache(struct mali_pm_domain *domain,
100 				 struct mali_l2_cache_core *l2_cache)
101 {
102 	MALI_DEBUG_ASSERT_POINTER(domain);
103 	MALI_DEBUG_ASSERT_POINTER(l2_cache);
104 	_mali_osk_list_add(&l2_cache->pm_domain_list, &domain->l2_cache_list);
105 }
106 
mali_pm_domain_get_from_mask(u32 mask)107 struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask)
108 {
109 	u32 id = 0;
110 
111 	if (0 == mask) {
112 		return NULL;
113 	}
114 
115 	id = _mali_osk_fls(mask) - 1;
116 
117 	MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
118 	/* Verify that pmu_mask only one bit is set */
119 	MALI_DEBUG_ASSERT((1 << id) == mask);
120 
121 	return mali_pm_domains[id];
122 }
123 
mali_pm_domain_get_from_index(u32 id)124 struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id)
125 {
126 	MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
127 
128 	return mali_pm_domains[id];
129 }
130 
mali_pm_domain_ref_get(struct mali_pm_domain * domain)131 u32 mali_pm_domain_ref_get(struct mali_pm_domain *domain)
132 {
133 	MALI_DEBUG_ASSERT_POINTER(domain);
134 
135 	if (0 == domain->use_count) {
136 		_mali_osk_pm_dev_ref_get_async();
137 	}
138 
139 	++domain->use_count;
140 	MALI_DEBUG_PRINT(4, ("PM domain %p: ref_get, use_count => %u\n", domain, domain->use_count));
141 
142 	/* Return our mask so caller can check this against wanted mask */
143 	return domain->pmu_mask;
144 }
145 
mali_pm_domain_ref_put(struct mali_pm_domain * domain)146 u32 mali_pm_domain_ref_put(struct mali_pm_domain *domain)
147 {
148 	MALI_DEBUG_ASSERT_POINTER(domain);
149 
150 	--domain->use_count;
151 	MALI_DEBUG_PRINT(4, ("PM domain %p: ref_put, use_count => %u\n", domain, domain->use_count));
152 
153 	if (0 == domain->use_count) {
154 		_mali_osk_pm_dev_ref_put();
155 	}
156 
157 	/*
158 	 * Return the PMU mask which now could be be powered down
159 	 * (the bit for this domain).
160 	 * This is the responsibility of the caller (mali_pm)
161 	 */
162 	return (0 == domain->use_count ? domain->pmu_mask : 0);
163 }
164 
165 #if MALI_STATE_TRACKING
mali_pm_domain_get_id(struct mali_pm_domain * domain)166 u32 mali_pm_domain_get_id(struct mali_pm_domain *domain)
167 {
168 	u32 id = 0;
169 
170 	MALI_DEBUG_ASSERT_POINTER(domain);
171 	MALI_DEBUG_ASSERT(0 != domain->pmu_mask);
172 
173 	id = _mali_osk_fls(domain->pmu_mask) - 1;
174 
175 	MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
176 	/* Verify that pmu_mask only one bit is set */
177 	MALI_DEBUG_ASSERT((1 << id) == domain->pmu_mask);
178 	/* Verify that we have stored the domain at right id/index */
179 	MALI_DEBUG_ASSERT(domain == mali_pm_domains[id]);
180 
181 	return id;
182 }
183 #endif
184 
185 #if defined(DEBUG)
mali_pm_domain_all_unused(void)186 mali_bool mali_pm_domain_all_unused(void)
187 {
188 	int i;
189 
190 	for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
191 		if (NULL == mali_pm_domains[i]) {
192 			/* Nothing to check */
193 			continue;
194 		}
195 
196 		if (MALI_TRUE == mali_pm_domains[i]->power_is_on) {
197 			/* Not ready for suspend! */
198 			return MALI_FALSE;
199 		}
200 
201 		if (0 != mali_pm_domains[i]->use_count) {
202 			/* Not ready for suspend! */
203 			return MALI_FALSE;
204 		}
205 	}
206 
207 	return MALI_TRUE;
208 }
209 #endif
210