2 * Copyright (C) 2013-2015 ARM Limited. All rights reserved.
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.
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.
11 #include "mali_kernel_common.h"
13 #include "mali_pm_domain.h"
15 #include "mali_group.h"
18 static struct mali_pm_domain *mali_pm_domains[MALI_MAX_NUMBER_OF_DOMAINS] =
21 void mali_pm_domain_initialize(void)
23 /* Domains will be initialized/created on demand */
26 void mali_pm_domain_terminate(void)
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;
37 struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask)
39 struct mali_pm_domain *domain = NULL;
42 domain = mali_pm_domain_get_from_mask(pmu_mask);
43 if (NULL != domain) return domain;
46 ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n",
49 domain = (struct mali_pm_domain *)_mali_osk_malloc(
50 sizeof(struct mali_pm_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);
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;
67 MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n"));
73 void mali_pm_domain_delete(struct mali_pm_domain *domain)
79 _mali_osk_list_delinit(&domain->group_list);
80 _mali_osk_list_delinit(&domain->l2_cache_list);
82 _mali_osk_free(domain);
85 void mali_pm_domain_add_group(struct mali_pm_domain *domain,
86 struct mali_group *group)
88 MALI_DEBUG_ASSERT_POINTER(domain);
89 MALI_DEBUG_ASSERT_POINTER(group);
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
96 _mali_osk_list_addtail(&group->pm_domain_list, &domain->group_list);
99 void mali_pm_domain_add_l2_cache(struct mali_pm_domain *domain,
100 struct mali_l2_cache_core *l2_cache)
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);
107 struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask)
115 id = _mali_osk_fls(mask) - 1;
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);
121 return mali_pm_domains[id];
124 struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id)
126 MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
128 return mali_pm_domains[id];
131 u32 mali_pm_domain_ref_get(struct mali_pm_domain *domain)
133 MALI_DEBUG_ASSERT_POINTER(domain);
135 if (0 == domain->use_count) {
136 _mali_osk_pm_dev_ref_get_async();
140 MALI_DEBUG_PRINT(4, ("PM domain %p: ref_get, use_count => %u\n", domain, domain->use_count));
142 /* Return our mask so caller can check this against wanted mask */
143 return domain->pmu_mask;
146 u32 mali_pm_domain_ref_put(struct mali_pm_domain *domain)
148 MALI_DEBUG_ASSERT_POINTER(domain);
151 MALI_DEBUG_PRINT(4, ("PM domain %p: ref_put, use_count => %u\n", domain, domain->use_count));
153 if (0 == domain->use_count) {
154 _mali_osk_pm_dev_ref_put();
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)
162 return (0 == domain->use_count ? domain->pmu_mask : 0);
165 #if MALI_STATE_TRACKING
166 u32 mali_pm_domain_get_id(struct mali_pm_domain *domain)
170 MALI_DEBUG_ASSERT_POINTER(domain);
171 MALI_DEBUG_ASSERT(0 != domain->pmu_mask);
173 id = _mali_osk_fls(domain->pmu_mask) - 1;
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]);
186 mali_bool mali_pm_domain_all_unused(void)
190 for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
191 if (NULL == mali_pm_domains[i]) {
192 /* Nothing to check */
196 if (MALI_TRUE == mali_pm_domains[i]->power_is_on) {
197 /* Not ready for suspend! */
201 if (0 != mali_pm_domains[i]->use_count) {
202 /* Not ready for suspend! */