import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / common / mali_dlbu.c
CommitLineData
6fa3eb70
S
1/*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2012-2013 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11#include "mali_dlbu.h"
12#include "mali_memory.h"
13#include "mali_pp.h"
14#include "mali_group.h"
15#include "mali_osk.h"
16#include "mali_hw_core.h"
17
18/**
19 * Size of DLBU registers in bytes
20 */
21#define MALI_DLBU_SIZE 0x400
22
23u32 mali_dlbu_phys_addr = 0;
24static mali_io_address mali_dlbu_cpu_addr = 0;
25
26/**
27 * DLBU register numbers
28 * Used in the register read/write routines.
29 * See the hardware documentation for more information about each register
30 */
31typedef enum mali_dlbu_register {
32 MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address;
33 31:12 Physical address to the page used for the DLBU
34 0 DLBU enable - set this bit to 1 enables the AXI bus
35 between PPs and L2s, setting to 0 disables the router and
36 no further transactions are sent to DLBU */
37 MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address;
38 31:12 Virtual address to the page used for the DLBU */
39 MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address;
40 31:12 Virtual address to the tile list. This address is used when
41 calculating the call address sent to PP.*/
42 MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension;
43 23:16 Number of tiles in Y direction-1
44 7:0 Number of tiles in X direction-1 */
45 MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration;
46 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024
47 21:16 2^n number of tiles to be binned to one tile list in Y direction
48 5:0 2^n number of tiles to be binned to one tile list in X direction */
49 MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions;
50 31:24 start position in Y direction for group 1
51 23:16 start position in X direction for group 1
52 15:8 start position in Y direction for group 0
53 7:0 start position in X direction for group 0 */
54 MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask;
55 7 enable PP7 for load balancing
56 6 enable PP6 for load balancing
57 5 enable PP5 for load balancing
58 4 enable PP4 for load balancing
59 3 enable PP3 for load balancing
60 2 enable PP2 for load balancing
61 1 enable PP1 for load balancing
62 0 enable PP0 for load balancing */
63} mali_dlbu_register;
64
65typedef enum {
66 PP0ENABLE = 0,
67 PP1ENABLE,
68 PP2ENABLE,
69 PP3ENABLE,
70 PP4ENABLE,
71 PP5ENABLE,
72 PP6ENABLE,
73 PP7ENABLE
74} mali_dlbu_pp_enable;
75
76struct mali_dlbu_core {
77 struct mali_hw_core hw_core; /**< Common for all HW cores */
78 u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU
79 see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */
80};
81
82_mali_osk_errcode_t mali_dlbu_initialize(void)
83{
84
85 MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n"));
86
87 if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) {
88 MALI_SUCCESS;
89 }
90
91 return _MALI_OSK_ERR_FAULT;
92}
93
94void mali_dlbu_terminate(void)
95{
96 MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n"));
97
98 mali_mmu_release_table_page(mali_dlbu_phys_addr, mali_dlbu_cpu_addr);
99}
100
101struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
102{
103 struct mali_dlbu_core *core = NULL;
104
105 MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description));
106
107 core = _mali_osk_malloc(sizeof(struct mali_dlbu_core));
108 if (NULL != core) {
109 if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) {
110 core->pp_cores_mask = 0;
111 if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) {
112 return core;
113 }
114 MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description));
115 mali_hw_core_delete(&core->hw_core);
116 }
117
118 _mali_osk_free(core);
119 } else {
120 MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n"));
121 }
122
123 return NULL;
124}
125
126void mali_dlbu_delete(struct mali_dlbu_core *dlbu)
127{
128 MALI_DEBUG_ASSERT_POINTER(dlbu);
129
130 mali_dlbu_reset(dlbu);
131 mali_hw_core_delete(&dlbu->hw_core);
132 _mali_osk_free(dlbu);
133}
134
135_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu)
136{
137 u32 dlbu_registers[7];
138 _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
139 MALI_DEBUG_ASSERT_POINTER(dlbu);
140
141 MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description));
142
143 dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */
144 dlbu_registers[1] = MALI_DLBU_VIRT_ADDR;
145 dlbu_registers[2] = 0;
146 dlbu_registers[3] = 0;
147 dlbu_registers[4] = 0;
148 dlbu_registers[5] = 0;
149 dlbu_registers[6] = dlbu->pp_cores_mask;
150
151 /* write reset values to core registers */
152 mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7);
153
154 err = _MALI_OSK_ERR_OK;
155
156 return err;
157}
158
159void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu)
160{
161 MALI_DEBUG_ASSERT_POINTER(dlbu);
162
163 mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
164}
165
166void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
167{
168 struct mali_pp_core *pp_core;
169 u32 bcast_id;
170
171 MALI_DEBUG_ASSERT_POINTER( dlbu );
172 MALI_DEBUG_ASSERT_POINTER( group );
173
174 pp_core = mali_group_get_pp_core(group);
175 bcast_id = mali_pp_core_get_bcast_id(pp_core);
176
177 dlbu->pp_cores_mask |= bcast_id;
178 MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask));
179}
180
181/* Remove a group from the DLBU */
182void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
183{
184 struct mali_pp_core *pp_core;
185 u32 bcast_id;
186
187 MALI_DEBUG_ASSERT_POINTER( dlbu );
188 MALI_DEBUG_ASSERT_POINTER( group );
189
190 pp_core = mali_group_get_pp_core(group);
191 bcast_id = mali_pp_core_get_bcast_id(pp_core);
192
193 dlbu->pp_cores_mask &= ~bcast_id;
194 MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask));
195}
196
197/* Configure the DLBU for \a job. This needs to be done before the job is started on the groups in the DLBU. */
198void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job)
199{
200 u32 *registers;
201 MALI_DEBUG_ASSERT(job);
202 registers = mali_pp_job_get_dlbu_registers(job);
203 MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n"));
204
205 /* Writing 4 registers:
206 * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */
207 mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4);
208
209}