tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / r4p0_rel0 / common / mali_pm_domain.c
1 /*
2  * Copyright (C) 2010-2012 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
17 static struct mali_pm_domain *mali_pm_domains[MALI_MAX_NUMBER_OF_DOMAINS] = { NULL, };
18
19 static void mali_pm_domain_lock(struct mali_pm_domain *domain)
20 {
21         _mali_osk_spinlock_irq_lock(domain->lock);
22 }
23
24 static void mali_pm_domain_unlock(struct mali_pm_domain *domain)
25 {
26         _mali_osk_spinlock_irq_unlock(domain->lock);
27 }
28
29 MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state)
30 {
31         domain->state = state;
32 }
33
34 struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask)
35 {
36         struct mali_pm_domain* domain = NULL;
37         u32 domain_id = 0;
38
39         domain = mali_pm_domain_get_from_mask(pmu_mask);
40         if (NULL != domain) return domain;
41
42         MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask));
43
44         domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain));
45         if (NULL != 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);
49                         return NULL;
50                 }
51
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;
57                 domain->l2 = NULL;
58
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;
65
66                 return domain;
67         } else {
68                 MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n"));
69         }
70
71         return NULL;
72 }
73
74 void mali_pm_domain_delete(struct mali_pm_domain *domain)
75 {
76         if (NULL == domain) {
77                 return;
78         }
79         _mali_osk_spinlock_irq_term(domain->lock);
80
81         _mali_osk_free(domain);
82 }
83
84 void mali_pm_domain_terminate(void)
85 {
86         int i;
87
88         /* Delete all domains */
89         for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
90                 mali_pm_domain_delete(mali_pm_domains[i]);
91         }
92 }
93
94 void mali_pm_domain_add_group(u32 mask, struct mali_group *group)
95 {
96         struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
97         struct mali_group *next;
98
99         if (NULL == domain) return;
100
101         MALI_DEBUG_ASSERT_POINTER(group);
102
103         ++domain->group_count;
104         next = domain->group_list;
105
106         domain->group_list = group;
107
108         group->pm_domain_list = next;
109
110         mali_group_set_pm_domain(group, domain);
111
112         /* Get pm domain ref after mali_group_set_pm_domain */
113         mali_group_get_pm_domain_ref(group);
114 }
115
116 void mali_pm_domain_add_l2(u32 mask, struct mali_l2_cache_core *l2)
117 {
118         struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
119
120         if (NULL == domain) return;
121
122         MALI_DEBUG_ASSERT(NULL == domain->l2);
123         MALI_DEBUG_ASSERT(NULL != l2);
124
125         domain->l2 = l2;
126
127         mali_l2_cache_set_pm_domain(l2, domain);
128 }
129
130 struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask)
131 {
132         u32 id = 0;
133
134         if (0 == mask) return NULL;
135
136         id = _mali_osk_fls(mask)-1;
137
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);
141
142         return mali_pm_domains[id];
143 }
144
145 struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id)
146 {
147         MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
148
149         return mali_pm_domains[id];
150 }
151
152 void mali_pm_domain_ref_get(struct mali_pm_domain *domain)
153 {
154         if (NULL == domain) return;
155
156         mali_pm_domain_lock(domain);
157         ++domain->use_count;
158
159         if (MALI_PM_DOMAIN_ON != domain->state) {
160                 /* Power on */
161                 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
162
163                 MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask));
164
165                 if (NULL != pmu) {
166                         _mali_osk_errcode_t err;
167
168                         err = mali_pmu_power_up(pmu, domain->pmu_mask);
169
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",
172                                                   domain->pmu_mask));
173                         }
174                 }
175                 mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON);
176         } else {
177                 MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain));
178         }
179
180         mali_pm_domain_unlock(domain);
181 }
182
183 void mali_pm_domain_ref_put(struct mali_pm_domain *domain)
184 {
185         if (NULL == domain) return;
186
187         mali_pm_domain_lock(domain);
188         --domain->use_count;
189
190         if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) {
191                 /* Power off */
192                 struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
193
194                 MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask));
195
196                 mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF);
197
198                 if (NULL != pmu) {
199                         _mali_osk_errcode_t err;
200
201                         err = mali_pmu_power_down(pmu, domain->pmu_mask);
202
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",
205                                                   domain->pmu_mask));
206                         }
207                 }
208         }
209         mali_pm_domain_unlock(domain);
210 }
211
212 mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain)
213 {
214         mali_bool is_powered = MALI_TRUE;
215
216         /* Take a reference without powering on */
217         if (NULL != domain) {
218                 mali_pm_domain_lock(domain);
219                 ++domain->use_count;
220
221                 if (MALI_PM_DOMAIN_ON != domain->state) {
222                         is_powered = MALI_FALSE;
223                 }
224                 mali_pm_domain_unlock(domain);
225         }
226
227         if(!_mali_osk_pm_dev_ref_add_no_power_on()) {
228                 is_powered = MALI_FALSE;
229         }
230
231         return is_powered;
232 }
233
234 void mali_pm_domain_unlock_state(struct mali_pm_domain *domain)
235 {
236         _mali_osk_pm_dev_ref_dec_no_power_on();
237
238         if (NULL != domain) {
239                 mali_pm_domain_ref_put(domain);
240         }
241 }