1a6d257baa5a30a2a5aa847da1f49e295259d2e6
[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
31
32 #ifdef CONFIG_MALI_DT
33
34 #define MALI_OSK_INVALID_RESOURCE_ADDRESS 0xFFFFFFFF
35
36 /**
37  * Define the max number of resource we could have.
38  */
39 #define MALI_OSK_MAX_RESOURCE_NUMBER 27
40
41 /**
42  * Define the max number of resource with interrupts, and they are
43  * the first 20 elements in array mali_osk_resource_bank.
44  */
45 #define MALI_OSK_RESOURCE_WITH_IRQ_NUMBER 20
46
47 /**
48  * pp core start and end location in mali_osk_resource_bank array.
49  */
50 #define MALI_OSK_RESOURCE_PP_LOCATION_START 2
51 #define MALI_OSK_RESOURCE_PP_LOCATION_END 17
52
53 /**
54  * L2 cache start and end location in mali_osk_resource_bank array.
55  */
56 #define MALI_OSK_RESOURCE_L2_LOCATION_START 20
57 #define MALI_OSK_RESOURCE_l2_LOCATION_END 22
58
59 /**
60  * DMA unit location.
61  */
62 #define MALI_OSK_RESOURCE_DMA_LOCATION 26
63
64 static _mali_osk_resource_t mali_osk_resource_bank[MALI_OSK_MAX_RESOURCE_NUMBER] = {
65         /*-------------------------------------------------------*/
66         /* rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0. */
67         /* {.description = "Mali_GP", .base = MALI_OFFSET_GP, .irq_name = "IRQGP",}, */
68         {.description = "Mali_GP", .base = MALI_OFFSET_GP, .irq_name = "Mali_GP_IRQ",},
69         /* {.description = "Mali_GP_MMU", .base = MALI_OFFSET_GP_MMU, .irq_name = "IRQGPMMU",}, */
70         {.description = "Mali_GP_MMU", .base = MALI_OFFSET_GP_MMU, .irq_name = "Mali_GP_MMU_IRQ",},
71         /* {.description = "Mali_PP0", .base = MALI_OFFSET_PP0, .irq_name = "IRQPP0",}, */
72         {.description = "Mali_PP0", .base = MALI_OFFSET_PP0, .irq_name = "Mali_PP0_IRQ",},
73         /* {.description = "Mali_PP0_MMU", .base = MALI_OFFSET_PP0_MMU, .irq_name = "IRQPPMMU0",}, */
74         {.description = "Mali_PP0_MMU", .base = MALI_OFFSET_PP0_MMU, .irq_name = "Mali_PP0_MMU_IRQ",},
75         /* {.description = "Mali_PP1", .base = MALI_OFFSET_PP1, .irq_name = "IRQPP1",}, */
76         {.description = "Mali_PP1", .base = MALI_OFFSET_PP1, .irq_name = "Mali_PP1_IRQ",},
77         /* {.description = "Mali_PP1_MMU", .base = MALI_OFFSET_PP1_MMU, .irq_name = "IRQPPMMU1",}, */
78         {.description = "Mali_PP1_MMU", .base = MALI_OFFSET_PP1_MMU, .irq_name = "Mali_PP1_MMU_IRQ",},
79         /*-------------------------------------------------------*/
80         {.description = "Mali_PP2", .base = MALI_OFFSET_PP2, .irq_name = "IRQPP2",},
81         {.description = "Mali_PP2_MMU", .base = MALI_OFFSET_PP2_MMU, .irq_name = "IRQPPMMU2",},
82         {.description = "Mali_PP3", .base = MALI_OFFSET_PP3, .irq_name = "IRQPP3",},
83         {.description = "Mali_PP3_MMU", .base = MALI_OFFSET_PP3_MMU, .irq_name = "IRQPPMMU3",},
84         {.description = "Mali_PP4", .base = MALI_OFFSET_PP4, .irq_name = "IRQPP4",},
85         {.description = "Mali_PP4_MMU", .base = MALI_OFFSET_PP4_MMU, .irq_name = "IRQPPMMU4",},
86         {.description = "Mali_PP5", .base = MALI_OFFSET_PP5, .irq_name = "IRQPP5",},
87         {.description = "Mali_PP5_MMU", .base = MALI_OFFSET_PP5_MMU, .irq_name = "IRQPPMMU5",},
88         {.description = "Mali_PP6", .base = MALI_OFFSET_PP6, .irq_name = "IRQPP6",},
89         {.description = "Mali_PP6_MMU", .base = MALI_OFFSET_PP6_MMU, .irq_name = "IRQPPMMU6",},
90         {.description = "Mali_PP7", .base = MALI_OFFSET_PP7, .irq_name = "IRQPP7",},
91         {.description = "Mali_PP7_MMU", .base = MALI_OFFSET_PP7_MMU, .irq_name = "IRQPPMMU",},
92         {.description = "Mali_PP_Broadcast", .base = MALI_OFFSET_PP_BCAST, .irq_name = "IRQPP",},
93         {.description = "Mali_PMU", .base = MALI_OFFSET_PMU, .irq_name = "IRQPMU",},
94         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE0,},
95         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE1,},
96         {.description = "Mali_L2", .base = MALI_OFFSET_L2_RESOURCE2,},
97         {.description = "Mali_PP_MMU_Broadcast", .base = MALI_OFFSET_PP_BCAST_MMU,},
98         {.description = "Mali_Broadcast", .base = MALI_OFFSET_BCAST,},
99         {.description = "Mali_DLBU", .base = MALI_OFFSET_DLBU,},
100         {.description = "Mali_DMA", .base = MALI_OFFSET_DMA,},
101 };
102
103 static int _mali_osk_get_compatible_name(const char **out_string)
104 {
105         struct device_node *node = mali_platform_device->dev.of_node;
106
107         MALI_DEBUG_ASSERT(NULL != node);
108
109         return of_property_read_string(node, "compatible", out_string);
110 }
111
112 _mali_osk_errcode_t _mali_osk_resource_initialize(void)
113 {
114         mali_bool mali_is_450 = MALI_FALSE, mali_is_470 = MALI_FALSE;
115         int i, pp_core_num = 0, l2_core_num = 0;
116         struct resource *res;
117         const char *compatible_name = NULL;
118
119         if (0 == _mali_osk_get_compatible_name(&compatible_name)) {
120                 if (0 == strncmp(compatible_name, "arm,mali-450", strlen("arm,mali-450"))) {
121                         mali_is_450 = MALI_TRUE;
122                         MALI_DEBUG_PRINT(2, ("mali-450 device tree detected."));
123                 } else if (0 == strncmp(compatible_name, "arm,mali-470", strlen("arm,mali-470"))) {
124                         mali_is_470 = MALI_TRUE;
125                         MALI_DEBUG_PRINT(2, ("mali-470 device tree detected."));
126                 }
127         }
128
129         for (i = 0; i < MALI_OSK_RESOURCE_WITH_IRQ_NUMBER; i++) {
130                 res = platform_get_resource_byname(mali_platform_device, IORESOURCE_IRQ, mali_osk_resource_bank[i].irq_name);
131                 if (res) {
132                         mali_osk_resource_bank[i].irq = res->start;
133                 } else {
134                         mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
135                 }
136         }
137
138         for (i = MALI_OSK_RESOURCE_PP_LOCATION_START; i <= MALI_OSK_RESOURCE_PP_LOCATION_END; i++) {
139                 if (MALI_OSK_INVALID_RESOURCE_ADDRESS != mali_osk_resource_bank[i].base) {
140                         pp_core_num++;
141                 }
142         }
143
144         /* We have to divide by 2, because we caculate twice for only one pp(pp_core and pp_mmu_core). */
145         if (0 != pp_core_num % 2) {
146                 MALI_DEBUG_PRINT(2, ("The value of pp core number isn't normal."));
147                 return _MALI_OSK_ERR_FAULT;
148         }
149
150         pp_core_num /= 2;
151
152         /**
153          * we can caculate the number of l2 cache core according the number of pp core number
154          * and device type(mali400/mali450/mali470).
155          */
156         l2_core_num = 1;
157         if (mali_is_450) {
158                 if (pp_core_num > 4) {
159                         l2_core_num = 3;
160                 } else if (pp_core_num <= 4) {
161                         l2_core_num = 2;
162                 }
163         }
164
165         for (i = MALI_OSK_RESOURCE_l2_LOCATION_END; i > MALI_OSK_RESOURCE_L2_LOCATION_START + l2_core_num - 1; i--) {
166                 mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
167         }
168
169         /* If device is not mali-450 type, we have to remove related resource from resource bank. */
170         if (!(mali_is_450 || mali_is_470)) {
171                 for (i = MALI_OSK_RESOURCE_l2_LOCATION_END + 1; i < MALI_OSK_MAX_RESOURCE_NUMBER; i++) {
172                         mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
173                 }
174         }
175
176         if (mali_is_470)
177                 mali_osk_resource_bank[MALI_OSK_RESOURCE_DMA_LOCATION].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
178
179         return _MALI_OSK_ERR_OK;
180 }
181
182 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
183 {
184         int i;
185
186         if (NULL == mali_platform_device) {
187                 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
188         }
189
190         /* Traverse all of resources in resources bank to find the matching one. */
191         for (i = 0; i < MALI_OSK_MAX_RESOURCE_NUMBER; i++) {
192                 if (mali_osk_resource_bank[i].base == addr) {
193                         if (NULL != res) {
194                                 res->base = addr + _mali_osk_resource_base_address();
195                                 res->description = mali_osk_resource_bank[i].description;
196                                 res->irq = mali_osk_resource_bank[i].irq;
197                         }
198                         return _MALI_OSK_ERR_OK;
199                 }
200         }
201
202         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
203 }
204
205 uintptr_t _mali_osk_resource_base_address(void)
206 {
207         struct resource *reg_res = NULL;
208         uintptr_t ret = 0;
209
210         // reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 0);
211     /* 
212      * rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0. 
213      * 关于下面的 "1" : 
214      *      dts_for_mali_ko_befor_r5p0-01rel0 中,
215      *      base_addr 定义在 reg 的 第二个 (index 为 "1") 的 item.
216      */
217         reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 1);
218
219         if (NULL != reg_res) {
220                 ret = reg_res->start;
221         }
222     // D_HEX( (unsigned int)ret);
223
224         return ret;
225 }
226
227 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
228 {
229         struct device_node *node = mali_platform_device->dev.of_node;
230         struct property *prop;
231         const __be32 *p;
232         int length = 0, i = 0;
233         u32 u;
234
235         MALI_DEBUG_PRINT(2, ("Get pmu config from device tree configuration.\n"));
236
237         MALI_DEBUG_ASSERT(NULL != node);
238
239         if (!of_get_property(node, "pmu_domain_config", &length)) {
240                 return;
241         }
242
243         if (array_size != length / sizeof(u32)) {
244                 MALI_PRINT_ERROR(("Wrong pmu domain config in device tree."));
245                 return;
246         }
247
248         of_property_for_each_u32(node, "pmu_domain_config", prop, p, u) {
249                 domain_config_array[i] = (u16)u;
250                 i++;
251         }
252
253         return;
254 }
255
256 u32 _mali_osk_get_pmu_switch_delay(void)
257 {
258         struct device_node *node = mali_platform_device->dev.of_node;
259         u32 switch_delay;
260
261         MALI_DEBUG_ASSERT(NULL != node);
262
263         if (0 == of_property_read_u32(node, "pmu_switch_delay", &switch_delay)) {
264                 return switch_delay;
265         } else {
266                 MALI_DEBUG_PRINT(2, ("Couldn't find pmu_switch_delay in device tree configuration.\n"));
267         }
268
269         return 0;
270 }
271
272 #else /* CONFIG_MALI_DT */  /* 若未 定义 CONFIG_MALI_DT. */
273
274 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
275 {
276         int i;
277         uintptr_t phys_addr;
278
279         if (NULL == mali_platform_device) {
280                 /* Not connected to a device */
281                 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
282         }
283
284         phys_addr = addr + _mali_osk_resource_base_address();
285         for (i = 0; i < mali_platform_device->num_resources; i++) {
286                 if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) &&
287                     mali_platform_device->resource[i].start == phys_addr) {
288                         if (NULL != res) {
289                                 res->base = phys_addr;
290                                 res->description = mali_platform_device->resource[i].name;
291
292                                 /* Any (optional) IRQ resource belonging to this resource will follow */
293                                 if ((i + 1) < mali_platform_device->num_resources &&
294                                     IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i + 1]))) {
295                                         res->irq = mali_platform_device->resource[i + 1].start;
296                                 } else {
297                                         res->irq = -1;
298                                 }
299                         }
300                         return _MALI_OSK_ERR_OK;
301                 }
302         }
303
304         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
305 }
306
307 uintptr_t _mali_osk_resource_base_address(void)
308 {
309         uintptr_t lowest_addr = (uintptr_t)(0 - 1);
310         uintptr_t ret = 0;
311
312         if (NULL != mali_platform_device) {
313                 int i;
314                 for (i = 0; i < mali_platform_device->num_resources; i++) {
315                         if (mali_platform_device->resource[i].flags & IORESOURCE_MEM &&
316                             mali_platform_device->resource[i].start < lowest_addr) {
317                                 lowest_addr = mali_platform_device->resource[i].start;
318                                 ret = lowest_addr;
319                         }
320                 }
321         }
322
323         return ret;
324 }
325
326 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
327 {
328         _mali_osk_device_data data = { 0, };
329
330         MALI_DEBUG_PRINT(2, ("Get pmu config from platform device data.\n"));
331         if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
332                 /* Copy the custom customer power domain config */
333                 _mali_osk_memcpy(domain_config_array, data.pmu_domain_config, sizeof(data.pmu_domain_config));
334         }
335
336         return;
337 }
338
339 u32 _mali_osk_get_pmu_switch_delay(void)
340 {
341         _mali_osk_errcode_t err;
342         _mali_osk_device_data data = { 0, };
343
344         err = _mali_osk_device_data_get(&data);
345
346         if (_MALI_OSK_ERR_OK == err) {
347                 return data.pmu_switch_delay;
348         }
349
350         return 0;
351 }
352 #endif /* CONFIG_MALI_DT */
353
354 _mali_osk_errcode_t _mali_osk_device_data_get(_mali_osk_device_data *data)
355 {
356         MALI_DEBUG_ASSERT_POINTER(data);
357
358         if (NULL != mali_platform_device) {
359                 struct mali_gpu_device_data *os_data = NULL;
360
361                 os_data = (struct mali_gpu_device_data *)mali_platform_device->dev.platform_data;
362                 if (NULL != os_data) {
363                         /* Copy data from OS dependant struct to Mali neutral struct (identical!) */
364                         BUILD_BUG_ON(sizeof(*os_data) != sizeof(*data));
365                         _mali_osk_memcpy(data, os_data, sizeof(*os_data));
366
367                         return _MALI_OSK_ERR_OK;
368                 }
369         }
370
371         return _MALI_OSK_ERR_ITEM_NOT_FOUND;
372 }
373
374 u32 _mali_osk_identify_gpu_resource(void)
375 {
376         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_L2_RESOURCE1, NULL))
377                 /* Mali 450 */
378                 return 0x450;
379
380         if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_DLBU, NULL))
381                 /* Mali 470 */
382                 return 0x470;
383
384         /* Mali 400 */
385         return 0x400;
386 }
387
388 mali_bool _mali_osk_shared_interrupts(void)
389 {
390         u32 irqs[128];
391         u32 i, j, irq, num_irqs_found = 0;
392
393         MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
394         MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources);
395
396         for (i = 0; i < mali_platform_device->num_resources; i++) {
397                 if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags) {
398                         irq = mali_platform_device->resource[i].start;
399
400                         for (j = 0; j < num_irqs_found; ++j) {
401                                 if (irq == irqs[j]) {
402                                         return MALI_TRUE;
403                                 }
404                         }
405
406                         irqs[num_irqs_found++] = irq;
407                 }
408         }
409
410         return MALI_FALSE;
411 }