Commit | Line | Data |
---|---|---|
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 | ||
23 | u32 mali_dlbu_phys_addr = 0; | |
24 | static 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 | */ | |
31 | typedef 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 | ||
65 | typedef enum { | |
66 | PP0ENABLE = 0, | |
67 | PP1ENABLE, | |
68 | PP2ENABLE, | |
69 | PP3ENABLE, | |
70 | PP4ENABLE, | |
71 | PP5ENABLE, | |
72 | PP6ENABLE, | |
73 | PP7ENABLE | |
74 | } mali_dlbu_pp_enable; | |
75 | ||
76 | struct 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 | ||
94 | void 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 | ||
101 | struct 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 | ||
126 | void 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 | ||
159 | void 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 | ||
166 | void 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 */ | |
182 | void 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. */ | |
198 | void 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 | } |