2 * Copyright (C) 2010-2012 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"
17 static struct mali_pm_domain *mali_pm_domains[MALI_MAX_NUMBER_OF_DOMAINS] = { NULL, };
19 static void mali_pm_domain_lock(struct mali_pm_domain *domain)
21 _mali_osk_spinlock_irq_lock(domain->lock);
24 static void mali_pm_domain_unlock(struct mali_pm_domain *domain)
26 _mali_osk_spinlock_irq_unlock(domain->lock);
29 MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state)
31 domain->state = state;
34 struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask)
36 struct mali_pm_domain* domain = NULL;
39 domain = mali_pm_domain_get_from_mask(pmu_mask);
40 if (NULL != domain) return domain;
42 MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask));
44 domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain));
46 domain->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_PM_DOMAIN);
47 if (NULL == domain->lock) {
48 _mali_osk_free(domain);
52 domain->state = MALI_PM_DOMAIN_ON;
53 domain->pmu_mask = pmu_mask;
54 domain->use_count = 0;
55 domain->group_list = NULL;
56 domain->group_count = 0;
59 domain_id = _mali_osk_fls(pmu_mask) - 1;
60 /* Verify the domain_id */
61 MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > domain_id);
62 /* Verify that pmu_mask only one bit is set */
63 MALI_DEBUG_ASSERT((1 << domain_id) == pmu_mask);
64 mali_pm_domains[domain_id] = domain;
68 MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n"));
74 void mali_pm_domain_delete(struct mali_pm_domain *domain)
79 _mali_osk_spinlock_irq_term(domain->lock);
81 _mali_osk_free(domain);
84 void mali_pm_domain_terminate(void)
88 /* Delete all domains */
89 for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
90 mali_pm_domain_delete(mali_pm_domains[i]);
94 void mali_pm_domain_add_group(u32 mask, struct mali_group *group)
96 struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
97 struct mali_group *next;
99 if (NULL == domain) return;
101 MALI_DEBUG_ASSERT_POINTER(group);
103 ++domain->group_count;
104 next = domain->group_list;
106 domain->group_list = group;
108 group->pm_domain_list = next;
110 mali_group_set_pm_domain(group, domain);
112 /* Get pm domain ref after mali_group_set_pm_domain */
113 mali_group_get_pm_domain_ref(group);
116 void mali_pm_domain_add_l2(u32 mask, struct mali_l2_cache_core *l2)
118 struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
120 if (NULL == domain) return;
122 MALI_DEBUG_ASSERT(NULL == domain->l2);
123 MALI_DEBUG_ASSERT(NULL != l2);
127 mali_l2_cache_set_pm_domain(l2, domain);
130 struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask)
134 if (0 == mask) return NULL;
136 id = _mali_osk_fls(mask)-1;
138 MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
139 /* Verify that pmu_mask only one bit is set */
140 MALI_DEBUG_ASSERT((1 << id) == mask);
142 return mali_pm_domains[id];
145 struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id)
147 MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
149 return mali_pm_domains[id];
152 void mali_pm_domain_ref_get(struct mali_pm_domain *domain)
154 if (NULL == domain) return;
156 mali_pm_domain_lock(domain);
159 if (MALI_PM_DOMAIN_ON != domain->state) {
161 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
163 MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask));
166 _mali_osk_errcode_t err;
168 err = mali_pmu_power_up(pmu, domain->pmu_mask);
170 if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) {
171 MALI_PRINT_ERROR(("PM Domain: Failed to power up PM domain 0x%08x\n",
175 mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON);
177 MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain));
180 mali_pm_domain_unlock(domain);
183 void mali_pm_domain_ref_put(struct mali_pm_domain *domain)
185 if (NULL == domain) return;
187 mali_pm_domain_lock(domain);
190 if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) {
192 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
194 MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask));
196 mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF);
199 _mali_osk_errcode_t err;
201 err = mali_pmu_power_down(pmu, domain->pmu_mask);
203 if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) {
204 MALI_PRINT_ERROR(("PM Domain: Failed to power down PM domain 0x%08x\n",
209 mali_pm_domain_unlock(domain);
212 mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain)
214 mali_bool is_powered = MALI_TRUE;
216 /* Take a reference without powering on */
217 if (NULL != domain) {
218 mali_pm_domain_lock(domain);
221 if (MALI_PM_DOMAIN_ON != domain->state) {
222 is_powered = MALI_FALSE;
224 mali_pm_domain_unlock(domain);
227 if(!_mali_osk_pm_dev_ref_add_no_power_on()) {
228 is_powered = MALI_FALSE;
234 void mali_pm_domain_unlock_state(struct mali_pm_domain *domain)
236 _mali_osk_pm_dev_ref_dec_no_power_on();
238 if (NULL != domain) {
239 mali_pm_domain_ref_put(domain);