2 * Copyright (C) 2011-2012 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.
10 #include "mali_kernel_common.h"
12 #include "mali_l2_cache.h"
13 #include "mali_hw_core.h"
14 #include "mali_scheduler.h"
17 * Size of the Mali L2 cache registers in bytes
19 #define MALI400_L2_CACHE_REGISTERS_SIZE 0x30
22 * Mali L2 cache register numbers
23 * Used in the register read/write routines.
24 * See the hardware documentation for more information about each register
26 typedef enum mali_l2_cache_register {
27 MALI400_L2_CACHE_REGISTER_STATUS = 0x0008,
29 MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */
30 MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014,
31 MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */
32 MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */
33 MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020,
34 MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024,
35 MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028,
36 MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C,
37 } mali_l2_cache_register;
40 * Mali L2 cache commands
41 * These are the commands that can be sent to the Mali L2 cache unit
43 typedef enum mali_l2_cache_command
45 MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */
46 /* Read HW TRM carefully before adding/using other commands than the clear above */
47 } mali_l2_cache_command;
50 * Mali L2 cache commands
51 * These are the commands that can be sent to the Mali L2 cache unit
53 typedef enum mali_l2_cache_enable
55 MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */
56 MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */
57 MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */
58 } mali_l2_cache_enable;
61 * Mali L2 cache status bits
63 typedef enum mali_l2_cache_status
65 MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */
66 MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */
67 } mali_l2_cache_status;
70 * Definition of the L2 cache core struct
71 * Used to track a L2 cache unit in the system.
72 * Contains information about the mapping of the registers
74 struct mali_l2_cache_core
76 struct mali_hw_core hw_core; /**< Common for all HW cores */
77 u32 core_id; /**< Unique core ID */
78 _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */
79 _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */
80 u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
81 u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
82 u32 last_invalidated_id;
83 mali_bool power_is_enabled;
86 #define MALI400_L2_MAX_READS_DEFAULT 0x1C
88 static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES];
89 static u32 mali_global_num_l2_cache_cores = 0;
91 int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
93 /* Local helper functions */
94 static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val);
97 struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
99 struct mali_l2_cache_core *cache = NULL;
100 _mali_osk_lock_flags_t lock_flags;
102 #if defined(MALI_UPPER_HALF_SCHEDULING)
103 lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
105 lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
108 MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description));
110 if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES)
112 MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n"));
116 cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core));
119 cache->core_id = mali_global_num_l2_cache_cores;
120 cache->counter_src0 = MALI_HW_CORE_NO_COUNTER;
121 cache->counter_src1 = MALI_HW_CORE_NO_COUNTER;
122 if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE))
124 cache->command_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
125 if (NULL != cache->command_lock)
127 cache->counter_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER);
128 if (NULL != cache->counter_lock)
130 mali_l2_cache_reset(cache);
132 cache->last_invalidated_id = 0;
133 cache->power_is_enabled = MALI_TRUE;
135 mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache;
136 mali_global_num_l2_cache_cores++;
142 MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description));
145 _mali_osk_lock_term(cache->command_lock);
149 MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description));
152 mali_hw_core_delete(&cache->hw_core);
155 _mali_osk_free(cache);
159 MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n"));
165 void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
169 /* reset to defaults */
170 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
171 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
173 _mali_osk_lock_term(cache->counter_lock);
174 _mali_osk_lock_term(cache->command_lock);
175 mali_hw_core_delete(&cache->hw_core);
177 for (i = 0; i < MALI_MAX_NUMBER_OF_L2_CACHE_CORES; i++)
179 if (mali_global_l2_cache_cores[i] == cache)
181 mali_global_l2_cache_cores[i] = NULL;
182 mali_global_num_l2_cache_cores--;
186 _mali_osk_free(cache);
189 void mali_l2_cache_power_is_enabled_set(struct mali_l2_cache_core * core, mali_bool power_is_enabled)
191 core->power_is_enabled = power_is_enabled;
194 mali_bool mali_l2_cache_power_is_enabled_get(struct mali_l2_cache_core * core)
196 return core->power_is_enabled;
199 u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache)
201 return cache->core_id;
204 mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter)
206 u32 value = 0; /* disabled src */
207 mali_bool core_is_on;
209 MALI_DEBUG_ASSERT_POINTER(cache);
211 core_is_on = mali_l2_cache_lock_power_state(cache);
213 _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
215 cache->counter_src0 = counter;
217 if (MALI_HW_CORE_NO_COUNTER != counter)
222 if (MALI_TRUE == core_is_on)
224 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value);
227 _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
229 mali_l2_cache_unlock_power_state(cache);
234 mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter)
236 u32 value = 0; /* disabled src */
237 mali_bool core_is_on;
239 MALI_DEBUG_ASSERT_POINTER(cache);
241 core_is_on = mali_l2_cache_lock_power_state(cache);
243 _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
245 cache->counter_src1 = counter;
247 if (MALI_HW_CORE_NO_COUNTER != counter)
252 if (MALI_TRUE == core_is_on)
254 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value);
257 _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
259 mali_l2_cache_unlock_power_state(cache);
264 u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache)
266 return cache->counter_src0;
269 u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache)
271 return cache->counter_src1;
274 void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1)
276 MALI_DEBUG_ASSERT(NULL != src0);
277 MALI_DEBUG_ASSERT(NULL != value0);
278 MALI_DEBUG_ASSERT(NULL != src1);
279 MALI_DEBUG_ASSERT(NULL != value1);
281 /* Caller must hold the PM lock and know that we are powered on */
283 _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
285 *src0 = cache->counter_src0;
286 *src1 = cache->counter_src1;
288 if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
290 *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
293 if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER)
295 *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
298 _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
301 struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index)
303 if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index)
305 return mali_global_l2_cache_cores[index];
311 u32 mali_l2_cache_core_get_glob_num_l2_cores(void)
313 return mali_global_num_l2_cache_cores;
316 void mali_l2_cache_reset(struct mali_l2_cache_core *cache)
318 /* Invalidate cache (just to keep it in a known state at startup) */
319 mali_l2_cache_invalidate_all(cache);
322 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE);
323 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
325 /* Restart any performance counters (if enabled) */
326 _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
328 if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
330 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0);
333 if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER)
335 mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1);
338 _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
341 void mali_l2_cache_reset_all(void)
344 u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores();
346 for (i = 0; i < num_cores; i++)
348 mali_l2_cache_reset(mali_l2_cache_core_get_glob_l2_core(i));
352 _mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache)
354 return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
357 mali_bool mali_l2_cache_invalidate_all_conditional(struct mali_l2_cache_core *cache, u32 id)
359 MALI_DEBUG_ASSERT_POINTER(cache);
363 /* If the last cache invalidation was done by a job with a higher id we
364 * don't have to flush. Since user space will store jobs w/ their
365 * corresponding memory in sequence (first job #0, then job #1, ...),
366 * we don't have to flush for job n-1 if job n has already invalidated
367 * the cache since we know for sure that job n-1's memory was already
368 * written when job n was started. */
369 if (((s32)id) <= ((s32)cache->last_invalidated_id))
375 cache->last_invalidated_id = mali_scheduler_get_new_id();
378 mali_l2_cache_invalidate_all(cache);
383 void mali_l2_cache_invalidate_all_force(struct mali_l2_cache_core *cache)
385 MALI_DEBUG_ASSERT_POINTER(cache);
389 cache->last_invalidated_id = mali_scheduler_get_new_id();
390 mali_l2_cache_invalidate_all(cache);
394 _mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages)
397 _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK;
399 for (i = 0; i < num_pages; i++)
401 ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]);
402 if (_MALI_OSK_ERR_OK != ret1)
411 void mali_l2_cache_invalidate_pages_conditional(u32 *pages, u32 num_pages)
415 for (i = 0; i < mali_global_num_l2_cache_cores; i++)
418 if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i]))
420 mali_l2_cache_invalidate_pages(mali_global_l2_cache_cores[i], pages, num_pages);
422 mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]);
423 /*check for failed power locking???*/
427 mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache)
429 return _mali_osk_pm_dev_ref_add_no_power_on();
432 void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache)
434 _mali_osk_pm_dev_ref_dec_no_power_on();
437 /* -------- local helper functions below -------- */
440 static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val)
443 const int loop_count = 100000;
446 * Grab lock in order to send commands to the L2 cache in a serialized fashion.
447 * The L2 cache will ignore commands if it is busy.
449 _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
451 /* First, wait for L2 cache command handler to go idle */
453 for (i = 0; i < loop_count; i++)
455 if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY))
463 _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
464 MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n"));
465 MALI_ERROR( _MALI_OSK_ERR_FAULT );
468 /* then issue the command */
469 mali_hw_core_register_write(&cache->hw_core, reg, val);
471 _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW);