2 * Copyright (C) 2010-2015 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.
13 * @file mali_osk_mali.c
14 * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver
16 #include "../platform/rk30/custom_log.h"
18 #include <linux/kernel.h>
19 #include <asm/uaccess.h>
20 #include <linux/platform_device.h>
21 #include <linux/mali/mali_utgard.h>
23 #include <linux/of_device.h>
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"
34 #define MALI_OSK_INVALID_RESOURCE_ADDRESS 0xFFFFFFFF
37 * Define the max number of resource we could have.
39 #define MALI_OSK_MAX_RESOURCE_NUMBER 27
42 * Define the max number of resource with interrupts, and they are
43 * the first 20 elements in array mali_osk_resource_bank.
45 #define MALI_OSK_RESOURCE_WITH_IRQ_NUMBER 20
48 * pp core start and end location in mali_osk_resource_bank array.
50 #define MALI_OSK_RESOURCE_PP_LOCATION_START 2
51 #define MALI_OSK_RESOURCE_PP_LOCATION_END 17
54 * L2 cache start and end location in mali_osk_resource_bank array.
56 #define MALI_OSK_RESOURCE_L2_LOCATION_START 20
57 #define MALI_OSK_RESOURCE_l2_LOCATION_END 22
62 #define MALI_OSK_RESOURCE_DMA_LOCATION 26
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,},
103 static int _mali_osk_get_compatible_name(const char **out_string)
105 struct device_node *node = mali_platform_device->dev.of_node;
107 MALI_DEBUG_ASSERT(NULL != node);
109 return of_property_read_string(node, "compatible", out_string);
112 _mali_osk_errcode_t _mali_osk_resource_initialize(void)
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;
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."));
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);
132 mali_osk_resource_bank[i].irq = res->start;
134 mali_osk_resource_bank[i].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
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) {
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;
153 * we can caculate the number of l2 cache core according the number of pp core number
154 * and device type(mali400/mali450/mali470).
158 if (pp_core_num > 4) {
160 } else if (pp_core_num <= 4) {
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;
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;
177 mali_osk_resource_bank[MALI_OSK_RESOURCE_DMA_LOCATION].base = MALI_OSK_INVALID_RESOURCE_ADDRESS;
179 return _MALI_OSK_ERR_OK;
182 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
186 if (NULL == mali_platform_device) {
187 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
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) {
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;
198 return _MALI_OSK_ERR_OK;
202 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
205 uintptr_t _mali_osk_resource_base_address(void)
207 struct resource *reg_res = NULL;
210 // reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 0);
212 * rk_ext : to use dts_for_mali_ko_befor_r5p0-01rel0.
214 * dts_for_mali_ko_befor_r5p0-01rel0 中,
215 * base_addr 定义在 reg 的 第二个 (index 为 "1") 的 item.
217 reg_res = platform_get_resource(mali_platform_device, IORESOURCE_MEM, 1);
219 if (NULL != reg_res) {
220 ret = reg_res->start;
222 // D_HEX( (unsigned int)ret);
227 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
229 struct device_node *node = mali_platform_device->dev.of_node;
230 struct property *prop;
232 int length = 0, i = 0;
235 MALI_DEBUG_PRINT(2, ("Get pmu config from device tree configuration.\n"));
237 MALI_DEBUG_ASSERT(NULL != node);
239 if (!of_get_property(node, "pmu_domain_config", &length)) {
243 if (array_size != length / sizeof(u32)) {
244 MALI_PRINT_ERROR(("Wrong pmu domain config in device tree."));
248 of_property_for_each_u32(node, "pmu_domain_config", prop, p, u) {
249 domain_config_array[i] = (u16)u;
256 u32 _mali_osk_get_pmu_switch_delay(void)
258 struct device_node *node = mali_platform_device->dev.of_node;
261 MALI_DEBUG_ASSERT(NULL != node);
263 if (0 == of_property_read_u32(node, "pmu_switch_delay", &switch_delay)) {
266 MALI_DEBUG_PRINT(2, ("Couldn't find pmu_switch_delay in device tree configuration.\n"));
272 #else /* CONFIG_MALI_DT */ /* 若未 定义 CONFIG_MALI_DT. */
274 _mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
279 if (NULL == mali_platform_device) {
280 /* Not connected to a device */
281 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
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) {
289 res->base = phys_addr;
290 res->description = mali_platform_device->resource[i].name;
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;
300 return _MALI_OSK_ERR_OK;
304 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
307 uintptr_t _mali_osk_resource_base_address(void)
309 uintptr_t lowest_addr = (uintptr_t)(0 - 1);
312 if (NULL != mali_platform_device) {
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;
326 void _mali_osk_device_data_pmu_config_get(u16 *domain_config_array, int array_size)
328 _mali_osk_device_data data = { 0, };
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));
339 u32 _mali_osk_get_pmu_switch_delay(void)
341 _mali_osk_errcode_t err;
342 _mali_osk_device_data data = { 0, };
344 err = _mali_osk_device_data_get(&data);
346 if (_MALI_OSK_ERR_OK == err) {
347 return data.pmu_switch_delay;
352 #endif /* CONFIG_MALI_DT */
354 _mali_osk_errcode_t _mali_osk_device_data_get(_mali_osk_device_data *data)
356 MALI_DEBUG_ASSERT_POINTER(data);
358 if (NULL != mali_platform_device) {
359 struct mali_gpu_device_data *os_data = NULL;
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));
367 return _MALI_OSK_ERR_OK;
371 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
374 u32 _mali_osk_identify_gpu_resource(void)
376 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_L2_RESOURCE1, NULL))
380 if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(MALI_OFFSET_DLBU, NULL))
388 mali_bool _mali_osk_shared_interrupts(void)
391 u32 i, j, irq, num_irqs_found = 0;
393 MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
394 MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources);
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;
400 for (j = 0; j < num_irqs_found; ++j) {
401 if (irq == irqs[j]) {
406 irqs[num_irqs_found++] = irq;