867814ef1489c182bea8bebbe42c313253d8c50a
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_osk_mali.c
1 /*
2  * Copyright (C) 2010-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
12 /**
13  * @file mali_osk_mali.c
14  * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver
15  */
16 #include "../platform/rk30/custom_log.h"
17
18 #include <linux/kernel.h>
19 #include <asm/uaccess.h>
20 #include <linux/platform_device.h>
21 #include <linux/mali/mali_utgard.h>
22 #include <linux/of.h>
23 #include <linux/of_device.h>
24
25 #include "mali_osk_mali.h"
26 #include "mali_kernel_common.h" /* MALI_xxx macros */
27 #include "mali_osk.h"           /* kernel side OS functions */
28 #include "mali_kernel_linux.h"
29
30 static mali_bool mali_secure_mode_enabled = MALI_FALSE;
31 static mali_bool mali_secure_mode_supported = MALI_FALSE;
32
33 /* Function that init the mali gpu secure mode */
34 void (*mali_secure_mode_deinit)(void) = NULL;
35 /* Function that enable the mali gpu secure mode */
36 int (*mali_secure_mode_enable)(void) = NULL;
37 /* Function that disable the mali gpu secure mode */
38 int (*mali_secure_mode_disable)(void) = NULL;
39
40
41 #ifdef CONFIG_MALI_DT
42
43 #define MALI_OSK_INVALID_RESOURCE_ADDRESS 0xFFFFFFFF
44
45 /**
46  * Define the max number of resource we could have.
47  */
48 #define MALI_OSK_MAX_RESOURCE_NUMBER 27
49
50 /**
51  * Define the max number of resource with interrupts, and they are
52  * the first 20 elements in array mali_osk_resource_bank.
53  */
54 #define MALI_OSK_RESOURCE_WITH_IRQ_NUMBER 20
55
56 /**
57  * pp core start and end location in mali_osk_resource_bank array.
58  */
59 #define MALI_OSK_RESOURCE_PP_LOCATION_START 2
60 #define MALI_OSK_RESOURCE_PP_LOCATION_END 17
61
62 /**
63  * L2 cache start and end location in mali_osk_resource_bank array.
64  */
65 #define MALI_OSK_RESOURCE_L2_LOCATION_START 20
66 #define MALI_OSK_RESOURCE_l2_LOCATION_END 22
67
68 /**
69  * DMA unit location.
70  */
71 #define MALI_OSK_RESOURCE_DMA_LOCATION 26
72
73 static _mali_osk_resource_t mali_osk_resource_bank[MALI_OSK_MAX_RESOURCE_NUMBER] = {
74         /*-------------------------------------------------------*/
75         /* rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0. */
76         /* {.description = "Mali_GP", .base = MALI_OFFSET_GP, .irq_name = "IRQGP",}, */
77         {.description = "Mali_GP", .base = MALI_OFFSET_GP, .irq_name = "Mali_GP_IRQ",},
78         /* {.description = "Mali_GP_MMU", .base = MALI_OFFSET_GP_MMU, .irq_name = "IRQGPMMU",}, */
79         {.description = "Mali_GP_MMU", .base = MALI_OFFSET_GP_MMU, .irq_name = "Mali_GP_MMU_IRQ",},
80         /* {.description = "Mali_PP0", .base = MALI_OFFSET_PP0, .irq_name = "IRQPP0",}, */
81         {.description = "Mali_PP0", .base = MALI_OFFSET_PP0, .irq_name = "Mali_PP0_IRQ",},
82         /* {.description = "Mali_PP0_MMU", .base = MALI_OFFSET_PP0_MMU, .irq_name = "IRQPPMMU0",}, */
83         {.description = "Mali_PP0_MMU", .base = MALI_OFFSET_PP0_MMU, .irq_name = "Mali_PP0_MMU_IRQ",},
84         /* {.description = "Mali_PP1", .base = MALI_OFFSET_PP1, .irq_name = "IRQPP1",}, */
85         {.description = "Mali_PP1", .base = MALI_OFFSET_PP1, .irq_name = "Mali_PP1_IRQ",},
86         /* {.description = "Mali_PP1_MMU", .base = MALI_OFFSET_PP1_MMU, .irq_name = "IRQPPMMU1",}, */
87         {.description = "Mali_PP1_MMU", .base = MALI_OFFSET_PP1_MMU, .irq_name = "Mali_PP1_MMU_IRQ",},
88         /*-------------------------------------------------------*/
89         {.description = "Mali_PP2", .base = MALI_OFFSET_PP2, .irq_name = "IRQPP2",},
90         {.description = "Mali_PP2_MMU", .base = MALI_OFFSET_PP2_MMU, .irq_name = "IRQPPMMU2",},
91         {.description = "Mali_PP3", .base = MALI_OFFSET_PP3, .irq_name = "IRQPP3",},
92         {.description = "Mali_PP3_MMU", .base = MALI_OFFSET_PP3_MMU, .irq_name = "IRQPPMMU3",},
93         {.description = "Mali_PP4", .base = MALI_OFFSET_PP4, .irq_name = "IRQPP4",},
94         {.description = "Mali_PP4_MMU", .base = MALI_OFFSET_PP4_MMU, .irq_name = "IRQPPMMU4",},
95         {.description = "Mali_PP5", .base = MALI_OFFSET_PP5, .irq_name = "IRQPP5",},
96         {.description = "Mali_PP5_MMU", .base = MALI_OFFSET_PP5_MMU, .irq_name = "IRQPPMMU5",},
97         {.description = "Mali_PP6", .base = MALI_OFFSET_PP6, .irq_name = "IRQPP6",},
98         {.description = "Mali_PP6_MMU", .base = MALI_OFFSET_PP6_MMU, .irq_name = "IRQPPMMU6",},
99         {.description = "Mali_PP7", .base = MALI_OFFSET_PP7, .irq_name = "IRQPP7",},
100         {.description = "Mali_PP7_MMU", .base = MALI_OFFSET_PP7_MMU, .irq_name = "IRQPPMMU",},
101         {.description = "Mali_PP_Broadcast", .base = MALI_OFFSET_PP_BCAST, .irq_name = "IRQPP",},
102         {.description = "Mali_PMU", .base = MALI_OFFSET_PMU, .irq_name = "IRQPMU",},
103         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE0,},
104         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE1,},
105         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE2,},
106         {.description = "Mali_PP_MMU_Broadcast", .base = MALI_OFFSET_PP_BCAST_MMU,},
107         {.description = "Mali_Broadcast", .base = MALI_OFFSET_BCAST,},
108         {.description = "Mali_DLBU", .base = MALI_OFFSET_DLBU,},
109         {.description = "Mali_DMA", .base = MALI_OFFSET_DMA,},
110 };
111
112 static int _mali_osk_get_compatible_name(const char **out_string)
113 {
114         struct device_node *node = mali_platform_device->dev.of_node;
115
116         MALI_DEBUG_ASSERT(NULL != node);
117
118         return of_property_read_string(node, "compatible", out_string);
119 }
120
121 _mali_osk_errcode_t _mali_osk_resource_initialize(void)
122 {
123         mali_bool mali_is_450 = MALI_FALSE, mali_is_470 = MALI_FALSE;
124         int i, pp_core_num = 0, l2_core_num = 0;
125         struct resource *res;
126         const char *compatible_name = NULL;
127
128         if (0 == _mali_osk_get_compatible_name(&compatible_name)) {
129                 if (0 == strncmp(compatible_name, "arm,mali-450", strlen("arm,mali-450"))) {
130                         mali_is_450 = MALI_TRUE;
131                         MALI_DEBUG_PRINT(2, ("mali-450 device tree detected."));
132                 } else if (0 == strncmp(compatible_name, "arm,mali-470", strlen("arm,mali-470"))) {
133                         mali_is_470 = MALI_TRUE;
134                         MALI_DEBUG_PRINT(2, ("mali-470 device tree detected."));
135                 }
136         }
137
138         for (i = 0; i < MALI_OSK_RESOURCE_WITH_IRQ_NUMBER; i++) {
139                 res = platform_get_resource_byname(mali_platform_device, IORESOURCE_IRQ, mali_osk_resource_bank[i].irq_name);
140                 if (res) {
141                         mali_osk_resource_bank[i].irq = res->start;
142                 } else {
143                         mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
144                 }
145         }
146
147         for (i = MALI_OSK_RESOURCE_PP_LOCATION_START; i <= MALI_OSK_RESOURCE_PP_LOCATION_END; i++) {
148                 if (MALI_OSK_INVALID_RESOURCE_ADDRESS != mali_osk_resource_bank[i].base) {
149                         pp_core_num++;
150                 }
151         }
152
153         /* We have to divide by 2, because we caculate twice for only one pp(pp_core and pp_mmu_core). */
154         if (0 != pp_core_num % 2) {
155                 MALI_DEBUG_PRINT(2, ("The value of pp core number isn't normal."));
156                 return _MALI_OSK_ERR_FAULT;
157         }
158
159         pp_core_num /= 2;
160
161         /**
162          * we can caculate the number of l2 cache core according the number of pp core number
163          * and device type(mali400/mali450/mali470).
164          */
165         l2_core_num = 1;
166         if (mali_is_450) {
167                 if (pp_core_num > 4) {
168                         l2_core_num = 3;
169                 } else if (pp_core_num <= 4) {
170                         l2_core_num = 2;
171                 }
172         }
173
174         for (i = MALI_OSK_RESOURCE_l2_LOCATION_END; i > MALI_OSK_RESOURCE_L2_LOCATION_START + l2_core_num - 1; i--) {
175                 mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
176         }
177
178         /* If device is not mali-450 type, we have to remove related resource from resource bank. */
179         if (!(mali_is_450 || mali_is_470)) {
180                 for (i = MALI_OSK_RESOURCE_l2_LOCATION_END + 1; i < MALI_OSK_MAX_RESOURCE_NUMBER; i++) {
181                         mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
182                 }
183         }
184
185         if (mali_is_470)
186                 mali_osk_resource_bank[MALI_OSK_RESOURCE_DMA_LOCATION].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
187
188         return _MALI_OSK_ERR_OK;
189 }
190
191 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
192 {
193         int i;
194
195         if (NULL == mali_platform_device) {
196                 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
197         }
198
199         /* Traverse all of resources in resources bank to find the matching one. */
200         for (i = 0; i < MALI_OSK_MAX_RESOURCE_NUMBER; i++) {
201                 if (mali_osk_resource_bank[i].base == addr) {
202                         if (NULL != res) {
203                                 res->base = addr + _mali_osk_resource_base_address();
204                                 res->description = mali_osk_resource_bank[i].description;
205                                 res->irq = mali_osk_resource_bank[i].irq;
206                         }
207                         return _MALI_OSK_ERR_OK;
208                 }
209         }
210
211         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
212 }
213
214 uintptr_t _mali_osk_resource_base_address(void)
215 {
216         struct resource *reg_res = NULL;
217         uintptr_t ret = 0;
218
219         // reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 0);
220     /* 
221      * rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0. 
222      * 关于下面的 "1" : 
223      *      dts_for_mali_ko_befor_r5p0-01rel0 中,
224      *      base_addr 定义在 reg 的 第二个 (index 为 "1") 的 item.
225      */
226         reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 1);
227
228         if (NULL != reg_res) {
229                 ret = reg_res->start;
230         }
231     // D_HEX( (unsigned int)ret);
232
233         return ret;
234 }
235
236 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
237 {
238         struct device_node *node = mali_platform_device->dev.of_node;
239         struct property *prop;
240         const __be32 *p;
241         int length = 0, i = 0;
242         u32 u;
243
244         MALI_DEBUG_PRINT(2, ("Get pmu config from device tree configuration.\n"));
245
246         MALI_DEBUG_ASSERT(NULL != node);
247
248         if (!of_get_property(node, "pmu_domain_config", &length)) {
249                 return;
250         }
251
252         if (array_size != length / sizeof(u32)) {
253                 MALI_PRINT_ERROR(("Wrong pmu domain config in device tree."));
254                 return;
255         }
256
257         of_property_for_each_u32(node, "pmu_domain_config", prop, p, u) {
258                 domain_config_array[i] = (u16)u;
259                 i++;
260         }
261
262         return;
263 }
264
265 u32 _mali_osk_get_pmu_switch_delay(void)
266 {
267         struct device_node *node = mali_platform_device->dev.of_node;
268         u32 switch_delay;
269
270         MALI_DEBUG_ASSERT(NULL != node);
271
272         if (0 == of_property_read_u32(node, "pmu_switch_delay", &switch_delay)) {
273                 return switch_delay;
274         } else {
275                 MALI_DEBUG_PRINT(2, ("Couldn't find pmu_switch_delay in device tree configuration.\n"));
276         }
277
278         return 0;
279 }
280
281 #else /* CONFIG_MALI_DT */  /* 若未 定义 CONFIG_MALI_DT. */
282
283 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
284 {
285         int i;
286         uintptr_t phys_addr;
287
288         if (NULL == mali_platform_device) {
289                 /* Not connected to a device */
290                 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
291         }
292
293         phys_addr = addr + _mali_osk_resource_base_address();
294         for (i = 0; i < mali_platform_device->num_resources; i++) {
295                 if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) &&
296                     mali_platform_device->resource[i].start == phys_addr) {
297                         if (NULL != res) {
298                                 res->base = phys_addr;
299                                 res->description = mali_platform_device->resource[i].name;
300
301                                 /* Any (optional) IRQ resource belonging to this resource will follow */
302                                 if ((i + 1) < mali_platform_device->num_resources &&
303                                     IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i + 1]))) {
304                                         res->irq = mali_platform_device->resource[i + 1].start;
305                                 } else {
306                                         res->irq = -1;
307                                 }
308                         }
309                         return _MALI_OSK_ERR_OK;
310                 }
311         }
312
313         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
314 }
315
316 uintptr_t _mali_osk_resource_base_address(void)
317 {
318         uintptr_t lowest_addr = (uintptr_t)(0 - 1);
319         uintptr_t ret = 0;
320
321         if (NULL != mali_platform_device) {
322                 int i;
323                 for (i = 0; i < mali_platform_device->num_resources; i++) {
324                         if (mali_platform_device->resource[i].flags & IORESOURCE_MEM &&
325                             mali_platform_device->resource[i].start < lowest_addr) {
326                                 lowest_addr = mali_platform_device->resource[i].start;
327                                 ret = lowest_addr;
328                         }
329                 }
330         }
331
332         return ret;
333 }
334
335 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
336 {
337         _mali_osk_device_data data = { 0, };
338
339         MALI_DEBUG_PRINT(2, ("Get pmu config from platform device data.\n"));
340         if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
341                 /* Copy the custom customer power domain config */
342                 _mali_osk_memcpy(domain_config_array, data.pmu_domain_config, sizeof(data.pmu_domain_config));
343         }
344
345         return;
346 }
347
348 u32 _mali_osk_get_pmu_switch_delay(void)
349 {
350         _mali_osk_errcode_t err;
351         _mali_osk_device_data data = { 0, };
352
353         err = _mali_osk_device_data_get(&data);
354
355         if (_MALI_OSK_ERR_OK == err) {
356                 return data.pmu_switch_delay;
357         }
358
359         return 0;
360 }
361 #endif /* CONFIG_MALI_DT */
362
363 _mali_osk_errcode_t _mali_osk_device_data_get(_mali_osk_device_data *data)
364 {
365         MALI_DEBUG_ASSERT_POINTER(data);
366
367         if (NULL != mali_platform_device) {
368                 struct mali_gpu_device_data *os_data = NULL;
369
370                 os_data = (struct mali_gpu_device_data *)mali_platform_device->dev.platform_data;
371                 if (NULL != os_data) {
372                         /* Copy data from OS dependant struct to Mali neutral struct (identical!) */
373                         BUILD_BUG_ON(sizeof(*os_data) != sizeof(*data));
374                         _mali_osk_memcpy(data, os_data, sizeof(*os_data));
375
376                         return _MALI_OSK_ERR_OK;
377                 }
378         }
379
380         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
381 }
382
383 u32 _mali_osk_identify_gpu_resource(void)
384 {
385         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_L2_RESOURCE1, NULL))
386                 /* Mali 450 */
387                 return 0x450;
388
389         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_DLBU, NULL))
390                 /* Mali 470 */
391                 return 0x470;
392
393         /* Mali 400 */
394         return 0x400;
395 }
396
397 mali_bool _mali_osk_shared_interrupts(void)
398 {
399         u32 irqs[128];
400         u32 i, j, irq, num_irqs_found = 0;
401
402         MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
403         MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources);
404
405         for (i = 0; i < mali_platform_device->num_resources; i++) {
406                 if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags) {
407                         irq = mali_platform_device->resource[i].start;
408
409                         for (j = 0; j < num_irqs_found; ++j) {
410                                 if (irq == irqs[j]) {
411                                         return MALI_TRUE;
412                                 }
413                         }
414
415                         irqs[num_irqs_found++] = irq;
416                 }
417         }
418
419         return MALI_FALSE;
420 }
421
422 _mali_osk_errcode_t _mali_osk_gpu_secure_mode_init(void)
423 {
424         _mali_osk_device_data data = { 0, };
425
426         if (_MALI_OSK_ERR_OK ==  _mali_osk_device_data_get(&data)) {
427                 if ((NULL != data.secure_mode_init) && (NULL != data.secure_mode_deinit)
428                     && (NULL != data.secure_mode_enable) && (NULL != data.secure_mode_disable)) {
429                         int err = data.secure_mode_init();
430                         if (err) {
431                                 MALI_DEBUG_PRINT(1, ("Failed to init gpu secure mode.\n"));
432                                 return _MALI_OSK_ERR_FAULT;
433                         }
434
435                         mali_secure_mode_deinit = data.secure_mode_deinit;
436                         mali_secure_mode_enable = data.secure_mode_enable;
437                         mali_secure_mode_disable = data.secure_mode_disable;
438
439                         mali_secure_mode_supported = MALI_TRUE;
440                         mali_secure_mode_enabled = MALI_FALSE;
441                         return _MALI_OSK_ERR_OK;
442                 }
443         }
444         MALI_DEBUG_PRINT(3, ("GPU secure mode not supported.\n"));
445         return _MALI_OSK_ERR_UNSUPPORTED;
446
447 }
448
449 _mali_osk_errcode_t _mali_osk_gpu_secure_mode_deinit(void)
450 {
451         if (NULL !=  mali_secure_mode_deinit) {
452                 mali_secure_mode_deinit();
453                 mali_secure_mode_enabled = MALI_FALSE;
454                 mali_secure_mode_supported = MALI_FALSE;
455                 return _MALI_OSK_ERR_OK;
456         }
457         MALI_DEBUG_PRINT(3, ("GPU secure mode not supported.\n"));
458         return _MALI_OSK_ERR_UNSUPPORTED;
459
460 }
461
462
463 _mali_osk_errcode_t _mali_osk_gpu_secure_mode_enable(void)
464 {
465         /* the mali executor lock must be held before enter this function. */
466
467         MALI_DEBUG_ASSERT(MALI_FALSE == mali_secure_mode_enabled);
468
469         if (NULL !=  mali_secure_mode_enable) {
470                 if (mali_secure_mode_enable()) {
471                         MALI_DEBUG_PRINT(1, ("Failed to enable gpu secure mode.\n"));
472                         return _MALI_OSK_ERR_FAULT;
473                 }
474                 mali_secure_mode_enabled = MALI_TRUE;
475                 return _MALI_OSK_ERR_OK;
476         }
477         MALI_DEBUG_PRINT(1, ("GPU secure mode not supported.\n"));
478         return _MALI_OSK_ERR_UNSUPPORTED;
479 }
480
481 _mali_osk_errcode_t _mali_osk_gpu_secure_mode_disable(void)
482 {
483         /* the mali executor lock must be held before enter this function. */
484
485         MALI_DEBUG_ASSERT(MALI_TRUE == mali_secure_mode_enabled);
486
487         if (NULL != mali_secure_mode_disable) {
488                 if (mali_secure_mode_disable()) {
489                         MALI_DEBUG_PRINT(1, ("Failed to disable gpu secure mode.\n"));
490                         return _MALI_OSK_ERR_FAULT;
491                 }
492                 mali_secure_mode_enabled = MALI_FALSE;
493
494                 return _MALI_OSK_ERR_OK;
495
496         }
497         MALI_DEBUG_PRINT(1, ("GPU secure mode not supported.\n"));
498         return _MALI_OSK_ERR_UNSUPPORTED;
499
500 }
501
502 mali_bool _mali_osk_gpu_secure_mode_is_enabled(void)
503 {
504         return mali_secure_mode_enabled;
505 }
506
507 mali_bool _mali_osk_gpu_secure_mode_is_supported(void)
508 {
509         return mali_secure_mode_supported;
510 }
511
512