dbf985e6d37b0ac27d7c7648a21c7febefae8375
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_pm_domain.c
1 /*
2  * Copyright (C) 2013-2015 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
21 void mali_pm_domain_initialize(void)
22 {
23         /* Domains will be initialized/created on demand */
24 }
25
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
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
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
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
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
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
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
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
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
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)
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