diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-22 15:04:56 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-22 15:04:56 +0200 |
commit | b99374450c03bf5081b88995d91d34fb9b2fd040 (patch) | |
tree | b6f525d915504ad8bd99bdb2dadcca345a4ad3a3 /drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c | |
parent | a39819e88ea4546218b581d7f061a99ca91d825b (diff) | |
parent | e2f984e707f517f24041b70018770b20b71cb6a6 (diff) | |
download | kernel_samsung_smdk4412-b99374450c03bf5081b88995d91d34fb9b2fd040.zip kernel_samsung_smdk4412-b99374450c03bf5081b88995d91d34fb9b2fd040.tar.gz kernel_samsung_smdk4412-b99374450c03bf5081b88995d91d34fb9b2fd040.tar.bz2 |
Merge remote-tracking branch 'github/cm-11.0'
Conflicts:
firmware/Makefile
firmware/epen/W9001_B713.bin.ihex
firmware/epen/W9001_B746.bin.ihex
firmware/epen/W9001_B746JD.bin.ihex
firmware/epen/W9001_B746L.bin.ihex
firmware/epen/W9001_B746S.bin.ihex
Diffstat (limited to 'drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c')
-rw-r--r-- | drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c new file mode 100644 index 0000000..9193778 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_pm_domain.h" +#include "mali_pmu.h" +#include "mali_pm.h" +#include "mali_group.h" + +#define MALI_PM_DOMAIN_MAX_DOMAINS 7 + +static struct mali_pm_domain *mali_pm_domains[MALI_PM_DOMAIN_MAX_DOMAINS] = { NULL, }; + +static void mali_pm_domain_lock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_wait(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +static void mali_pm_domain_unlock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_signal(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state) +{ + domain->state = state; +} + +struct mali_pm_domain *mali_pm_domain_create(u32 id, u32 pmu_mask) +{ + struct mali_pm_domain* domain; + + MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask)); + + domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain)); + if (NULL != domain) + { + _mali_osk_lock_flags_t flags = _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; + domain->lock = _mali_osk_lock_init(flags, 0, _MALI_OSK_LOCK_ORDER_PM_DOMAIN); + if (NULL == domain->lock) + { + _mali_osk_free(domain); + return NULL; + } + + domain->state = MALI_PM_DOMAIN_ON; + domain->pmu_mask = pmu_mask; + domain->use_count = 0; + domain->group_list = NULL; + domain->group_count = 0; + domain->l2 = NULL; + + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + mali_pm_domains[id] = domain; + + return domain; + } + else + { + MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n")); + } + + return NULL; +} + +void mali_pm_domain_delete(struct mali_pm_domain *domain) +{ + if (NULL == domain) + { + return; + } + _mali_osk_lock_term(domain->lock); + + _mali_osk_free(domain); +} + +void mali_pm_domain_terminate(void) +{ + int i; + + /* Delete all domains */ + for (i = 0; i < MALI_PM_DOMAIN_MAX_DOMAINS; i++) + { + mali_pm_domain_delete(mali_pm_domains[i]); + } +} + +void mali_pm_domain_add_group(u32 id, struct mali_group *group) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + struct mali_group *next; + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT_POINTER(group); + + /* Assume domain is on and group is enabled initially. */ + mali_pm_domain_ref_get(domain); + + ++domain->group_count; + next = domain->group_list; + + domain->group_list = group; + + group->pm_domain_list = next; + + mali_group_set_pm_domain(group, domain); +} + +void mali_pm_domain_add_l2(u32 id, struct mali_l2_cache_core *l2) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT(NULL == domain->l2); + MALI_DEBUG_ASSERT(NULL != l2); + + domain->l2 = l2; + + mali_l2_cache_set_pm_domain(l2, domain); +} + +struct mali_pm_domain *mali_pm_domain_get(u32 id) +{ + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + + return mali_pm_domains[id]; +} + +void mali_pm_domain_ref_get(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + /* Power on */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask)); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_up(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power up PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON); + } + else + { + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain)); + } + + mali_pm_domain_unlock(domain); +} + +void mali_pm_domain_ref_put(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + --domain->use_count; + + if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) + { + /* Power off */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask)); + + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_down(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power down PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + } + mali_pm_domain_unlock(domain); +} + +mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain) +{ + mali_bool is_powered = MALI_TRUE; + + /* Take a reference without powering on */ + if (NULL != domain) + { + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + is_powered = MALI_FALSE; + } + mali_pm_domain_unlock(domain); + } + + if(!_mali_osk_pm_dev_ref_add_no_power_on()) + { + is_powered = MALI_FALSE; + } + + return is_powered; +} + +void mali_pm_domain_unlock_state(struct mali_pm_domain *domain) +{ + _mali_osk_pm_dev_ref_dec_no_power_on(); + + if (NULL != domain) + { + mali_pm_domain_ref_put(domain); + } +} |