satip-axe/kernel/drivers/stm/mali/linux/mali_kernel_pm.c

802 lines
23 KiB
C
Raw Normal View History

/**
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
* Copyright (C) 2011 STMicroelectronics R&D 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.
*/
/* Even if the knl has no PM we need to configure it here so we have access to ARM's
* platform driver code implementation. */
#ifndef CONFIG_PM
#define CONFIG_PM
#endif
/**
* @file mali_kernel_pm.c
* Implementation of the Linux Power Management for Mali GPU kernel driver
*/
#if USING_MALI_PMM
#include <linux/sched.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_RUNTIME
#include <linux/pm_runtime.h>
#endif /* CONFIG_PM_RUNTIME */
#include <linux/platform_device.h>
#include <linux/version.h>
#include <asm/current.h>
#include <asm/delay.h>
#include <linux/suspend.h>
#include "mali_platform.h"
#include "mali_osk.h"
#include "mali_uk_types.h"
#include "mali_pmm.h"
#include "mali_ukk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_license.h"
#include "mali_kernel_pm.h"
#include "mali_device_pause_resume.h"
#include "mali_linux_pm.h"
#if MALI_GPU_UTILIZATION
#include "mali_kernel_utilization.h"
#endif /* MALI_GPU_UTILIZATION */
#if MALI_POWER_MGMT_TEST_SUITE
#ifdef CONFIG_PM
#include "mali_linux_pm_testsuite.h"
unsigned int pwr_mgmt_status_reg = 0;
#endif /* CONFIG_PM */
#endif /* MALI_POWER_MGMT_TEST_SUITE */
#if MALI_STATE_TRACKING
int is_os_pmm_thread_waiting = -1;
#endif /* MALI_STATE_TRACKING */
extern struct platform_device *mali_platform_device;
/* kernel should be configured with power management support */
#ifdef CONFIG_PM
/* License should be GPL */
#if MALI_LICENSE_IS_GPL
/* Linux kernel major version */
#define LINUX_KERNEL_MAJOR_VERSION 2
/* Linux kernel minor version */
#define LINUX_KERNEL_MINOR_VERSION 6
/* Linux kernel development version */
#define LINUX_KERNEL_DEVELOPMENT_VERSION 29
#ifdef CONFIG_PM_DEBUG
static const char* const mali_states[_MALI_MAX_DEBUG_OPERATIONS] = {
[_MALI_DEVICE_SUSPEND] = "suspend",
[_MALI_DEVICE_RESUME] = "resume",
#ifdef CONFIG_HAS_EARLYSUSPEND
[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB] = "early_suspend_level_disable_framebuffer",
[_MALI_DEVICE_LATERESUME] = "late_resume",
#endif /* CONFIG_HAS_EARLYSUSPEND */
[_MALI_DVFS_PAUSE_EVENT] = "dvfs_pause",
[_MALI_DVFS_RESUME_EVENT] = "dvfs_resume",
};
#endif /* CONFIG_PM_DEBUG */
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
extern void set_mali_parent_power_domain(struct platform_device* dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_HAS_EARLYSUSPEND
static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy);
static struct notifier_block mali_pwr_notif_block = {
.notifier_call = mali_pwr_suspend_notifier
};
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/* Power management thread pointer */
struct task_struct *pm_thread;
/* dvfs power management thread */
struct task_struct *dvfs_pm_thread;
/* is wake up needed */
short is_wake_up_needed = 0;
int timeout_fired = 2;
unsigned int is_mali_pmm_testsuite_enabled = 0;
_mali_device_power_states mali_device_state = _MALI_DEVICE_RESUME;
_mali_device_power_states mali_dvfs_device_state = _MALI_DEVICE_RESUME;
_mali_osk_lock_t *lock;
#if MALI_POWER_MGMT_TEST_SUITE
const char* const mali_pmm_recording_events[_MALI_DEVICE_MAX_PMM_EVENTS] = {
[_MALI_DEVICE_PMM_TIMEOUT_EVENT] = "timeout",
[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS] = "job_scheduling",
[_MALI_DEVICE_PMM_REGISTERED_CORES] = "cores",
};
unsigned int mali_timeout_event_recording_on = 0;
unsigned int mali_job_scheduling_events_recording_on = 0;
unsigned int is_mali_pmu_present = 0;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
/* Function prototypes */
static int mali_pm_probe(struct platform_device *pdev);
static int mali_pm_remove(struct platform_device *pdev);
/* Mali device suspend function */
static int mali_pm_suspend(struct device *dev);
/* Mali device resume function */
static int mali_pm_resume(struct device *dev);
/* Run time suspend and resume functions */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
static int mali_device_runtime_suspend(struct device *dev);
static int mali_device_runtime_resume(struct device *dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/* Early suspend functions */
#ifdef CONFIG_HAS_EARLYSUSPEND
static void mali_pm_early_suspend(struct early_suspend *mali_dev);
static void mali_pm_late_resume(struct early_suspend *mali_dev);
#endif /* CONFIG_HAS_EARLYSUSPEND */
/* OS suspend and resume callbacks */
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_PM_RUNTIME
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state);
#else
static int mali_pm_os_suspend(struct device *dev);
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_resume(struct platform_device *pdev);
#else
static int mali_pm_os_resume(struct device *dev);
#endif
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
/* OS Hibernation suspend callback */
static int mali_pm_os_suspend_on_hibernation(struct device *dev);
/* OS Hibernation resume callback */
static int mali_pm_os_resume_on_hibernation(struct device *dev);
static void _mali_release_pm(struct device* device);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static const struct dev_pm_ops mali_dev_pm_ops = {
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
.runtime_suspend = mali_device_runtime_suspend,
.runtime_resume = mali_device_runtime_resume,
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
.suspend = mali_pm_os_suspend,
.resume = mali_pm_os_resume,
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
.freeze = mali_pm_os_suspend_on_hibernation,
.poweroff = mali_pm_os_suspend_on_hibernation,
.thaw = mali_pm_os_resume_on_hibernation,
.restore = mali_pm_os_resume_on_hibernation,
};
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
struct pm_ext_ops mali_pm_operations = {
.base = {
.freeze = mali_pm_os_suspend_on_hibernation,
.thaw = mali_pm_os_resume_on_hibernation,
.poweroff = mali_pm_os_resume_on_hibernation,
.restore = mali_pm_os_resume_on_hibernation,
},
};
#endif
static struct platform_driver mali_plat_driver = {
.probe = mali_pm_probe,
.remove = mali_pm_remove,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
.suspend = mali_pm_os_suspend,
.resume = mali_pm_os_resume,
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
.pm = &mali_pm_operations,
#endif
.driver = {
.name = "mali",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
.pm = &mali_dev_pm_ops,
#endif
},
};
#ifdef CONFIG_HAS_EARLYSUSPEND
/* Early suspend hooks */
static struct early_suspend mali_dev_early_suspend = {
.suspend = mali_pm_early_suspend,
.resume = mali_pm_late_resume,
.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
};
#endif /* CONFIG_HAS_EARLYSUSPEND */
/* Mali GPU platform device */
struct platform_device mali_gpu_device = {
.name = "mali_dev",
.id = 0,
.dev.release = _mali_release_pm
};
/** This function is called when platform device is unregistered. This function
* is necessary when the platform device is unregistered.
*/
static void _mali_release_pm(struct device *device)
{
MALI_DEBUG_PRINT(4, ("OSPMM: MALI Platform device removed\n" ));
}
#if MALI_POWER_MGMT_TEST_SUITE
void mali_is_pmu_present(void)
{
int temp = 0;
temp = pmu_get_power_up_down_info();
if (4095 == temp)
{
is_mali_pmu_present = 0;
}
else
{
is_mali_pmu_present = 1;
}
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
#endif /* MALI_LICENSE_IS_GPL */
#if MALI_LICENSE_IS_GPL
static int mali_wait_for_power_management_policy_event(void)
{
int err = 0;
for (; ;)
{
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
{
err = -EINTR;
break;
}
if (is_wake_up_needed == 1)
{
break;
}
schedule();
}
__set_current_state(TASK_RUNNING);
is_wake_up_needed =0;
return err;
}
/** This function is invoked when mali device is suspended
*/
int mali_device_suspend(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
{
int err = 0;
_mali_uk_pmm_message_s event = {
NULL,
event_id,
timeout_fired};
*pwr_mgmt_thread = current;
MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being suspended\n" ));
_mali_ukk_pmm_event_message(&event);
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 1;
#endif /* MALI_STATE_TRACKING */
err = mali_wait_for_power_management_policy_event();
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 0;
#endif /* MALI_STATE_TRACKING */
return err;
}
/** This function is called when Operating system wants to power down
* the mali GPU device.
*/
static int mali_pm_suspend(struct device *dev)
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
#if MALI_GPU_UTILIZATION
mali_utilization_suspend();
#endif /* MALI_GPU_UTILIZATION */
if ((mali_device_state == _MALI_DEVICE_SUSPEND)
#ifdef CONFIG_HAS_EARLYSUSPEND
|| mali_device_state == (_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
#else
)
#endif /* CONFIG_HAS_EARLYSUSPEND */
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
mali_device_state = _MALI_DEVICE_SUSPEND_IN_PROGRESS;
err = mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread);
mali_device_state = _MALI_DEVICE_SUSPEND;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state)
#else
static int mali_pm_os_suspend(struct device *dev)
#endif
{
int err = 0;
err = mali_pm_suspend(NULL);
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_HAS_EARLYSUSPEND
static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy)
{
int err = 0;
switch (event)
{
case PM_SUSPEND_PREPARE:
err = mali_pm_suspend(NULL);
break;
case PM_POST_SUSPEND:
err = mali_pm_resume(NULL);
break;
default:
break;
}
return 0;
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/** This function is called when mali GPU device is to be resumed.
*/
int mali_device_resume(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
{
int err = 0;
_mali_uk_pmm_message_s event = {
NULL,
event_id,
timeout_fired};
*pwr_mgmt_thread = current;
MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being resumed\n" ));
_mali_ukk_pmm_event_message(&event);
MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power up event is scheduled\n" ));
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 1;
#endif /* MALI_STATE_TRACKING */
err = mali_wait_for_power_management_policy_event();
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 0;
#endif /* MALI_STATE_TRACKING */
return err;
}
/** This function is called when mali GPU device is to be resumed
*/
static int mali_pm_resume(struct device *dev)
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if (mali_device_state == _MALI_DEVICE_RESUME)
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
err = mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread);
mali_device_state = _MALI_DEVICE_RESUME;
mali_dvfs_device_state = _MALI_DEVICE_RESUME;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_resume(struct platform_device *pdev)
#else
static int mali_pm_os_resume(struct device *dev)
#endif
{
int err = 0;
err = mali_pm_resume(NULL);
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
static int mali_pm_os_suspend_on_hibernation(struct device *dev)
{
int err = 0;
err = mali_pm_suspend(NULL);
return err;
}
static int mali_pm_os_resume_on_hibernation(struct device *dev)
{
int err = 0;
err = mali_pm_resume(NULL);
return err;
}
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
/** This function is called when runtime suspend of mali device is required.
*/
static int mali_device_runtime_suspend(struct device *dev)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time suspended \n" ));
return 0;
}
/** This function is called when runtime resume of mali device is required.
*/
static int mali_device_runtime_resume(struct device *dev)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time Resumed \n" ));
return 0;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_HAS_EARLYSUSPEND
/* This function is called from android framework.
*/
static void mali_pm_early_suspend(struct early_suspend *mali_dev)
{
switch(mali_dev->level)
{
/* Screen should be turned off but framebuffer will be accessible */
case EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Screen is off\n" ));
break;
case EARLY_SUSPEND_LEVEL_STOP_DRAWING:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level stop drawing\n" ));
break;
/* Turn off the framebuffer. In our case No Mali GPU operation */
case EARLY_SUSPEND_LEVEL_DISABLE_FB:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level Disable framebuffer\n" ));
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
#if MALI_GPU_UTILIZATION
mali_utilization_suspend();
#endif /* MALI_GPU_UTILIZATION */
if ((mali_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return;
}
mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread);
mali_device_state = _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
break;
default:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Suspend Mode\n" ));
break;
}
}
/* This function is invoked from android framework when mali device needs to be
* resumed.
*/
static void mali_pm_late_resume(struct early_suspend *mali_dev)
{
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if (mali_device_state == _MALI_DEVICE_RESUME)
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return;
}
if (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)
{
mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread);
mali_dvfs_device_state = _MALI_DEVICE_RESUME;
mali_device_state = _MALI_DEVICE_RESUME;
}
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_DEBUG
/** This function is used for debugging purposes when the user want to see
* which power management operations are supported for
* mali device.
*/
static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
{
char *str = buf;
#if !MALI_POWER_MGMT_TEST_SUITE
int pm_counter = 0;
for (pm_counter = 0; pm_counter<_MALI_MAX_DEBUG_OPERATIONS; pm_counter++)
{
str += sprintf(str, "%s ", mali_states[pm_counter]);
}
#else
str += sprintf(str, "%d ",pwr_mgmt_status_reg);
#endif
if (str != buf)
{
*(str-1) = '\n';
}
return (str-buf);
}
/** This function is called when user wants to suspend the mali GPU device in order
* to simulate the power up and power down events.
*/
static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend mali_dev;
#endif /* CONFIG_HAS_EARLYSUSPEND */
#if MALI_POWER_MGMT_TEST_SUITE
int test_flag_dvfs = 0;
pwr_mgmt_status_reg = 0;
mali_is_pmu_present();
#endif
if (!strncmp(buf,mali_states[_MALI_DEVICE_SUSPEND],strlen(mali_states[_MALI_DEVICE_SUSPEND])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI suspend Power operation is scheduled\n" ));
err = mali_pm_suspend(NULL);
}
#if MALI_POWER_MGMT_TEST_SUITE
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Device get number of registerd cores\n" ));
pwr_mgmt_status_reg = _mali_pmm_cores_list();
return count;
}
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI timeout event recording is enabled\n" ));
mali_timeout_event_recording_on = 1;
}
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Job scheduling events recording is enabled\n" ));
mali_job_scheduling_events_recording_on = 1;
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
else if (!strncmp(buf,mali_states[_MALI_DEVICE_RESUME],strlen(mali_states[_MALI_DEVICE_RESUME])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" ));
err = mali_pm_resume(NULL);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
else if (!strncmp(buf,mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB],strlen(mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB])))
{
mali_dev.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Android early suspend operation is scheduled\n" ));
mali_pm_early_suspend(&mali_dev);
}
else if (!strncmp(buf,mali_states[_MALI_DEVICE_LATERESUME],strlen(mali_states[_MALI_DEVICE_LATERESUME])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" ));
mali_pm_late_resume(NULL);
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
else if (!strncmp(buf,mali_states[_MALI_DVFS_PAUSE_EVENT],strlen(mali_states[_MALI_DVFS_PAUSE_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Pause Power operation is scheduled\n" ));
err = mali_dev_pause();
#if MALI_POWER_MGMT_TEST_SUITE
test_flag_dvfs = 1;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
}
else if (!strncmp(buf,mali_states[_MALI_DVFS_RESUME_EVENT],strlen(mali_states[_MALI_DVFS_RESUME_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Resume Power operation is scheduled\n" ));
err = mali_dev_resume();
#if MALI_POWER_MGMT_TEST_SUITE
test_flag_dvfs = 1;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
}
else
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Power Mode Operation selected\n" ));
}
#if MALI_POWER_MGMT_TEST_SUITE
if (test_flag_dvfs == 1)
{
if (err)
{
pwr_mgmt_status_reg = 2;
}
else
{
pwr_mgmt_status_reg = 1;
}
}
else
{
if (1 == is_mali_pmu_present)
{
pwr_mgmt_status_reg = pmu_get_power_up_down_info();
}
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
return count;
}
/* Device attribute file */
static DEVICE_ATTR(file, 0644, show_file, store_file);
#endif /* CONFIG_PM_DEBUG */
static int mali_pm_remove(struct platform_device *pdev)
{
#ifdef CONFIG_PM_DEBUG
device_remove_file(&mali_gpu_device.dev, &dev_attr_file);
#endif /* CONFIG_PM_DEBUG */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
pm_runtime_disable(&pdev->dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
return 0;
}
/** This function is called when the device is probed */
static int mali_pm_probe(struct platform_device *pdev)
{
MALI_DEBUG_PRINT(2, ("Mali Platform device probe id = %d num_resources = %d resource = %p.\n",pdev->id,pdev->num_resources,pdev->resource));
/*
* As OS init has already created the platform device we record it in the global
*/
mali_platform_device = pdev;
#ifdef CONFIG_PM_DEBUG
int err;
err = device_create_file(&mali_gpu_device.dev, &dev_attr_file);
if (err)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Error in creating device file\n" ));
}
#endif /* CONFIG_PM_DEBUG */
return 0;
}
/** This function is called when Mali GPU device is initialized
*/
int _mali_dev_platform_register(void)
{
int err;
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
set_mali_parent_power_domain(&mali_gpu_device);
#endif
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
err = register_pm_notifier(&mali_pwr_notif_block);
if (err)
{
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
/* The platform device is actually registered by the OS startup code so we don't
* need to do it here. All we do is register the platform driver
*/
MALI_DEBUG_PRINT(3, ("[%s] Not registering platform device\n", __FUNCTION__));
lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0);
err = platform_driver_register(&mali_plat_driver);
if (!err)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
register_early_suspend(&mali_dev_early_suspend);
#endif /* CONFIG_HAS_EARLYSUSPEND */
}
else
{
_mali_osk_lock_term(lock);
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
unregister_pm_notifier(&mali_pwr_notif_block);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
}
return err;
}
/** This function is called when Mali GPU device is unloaded
*/
void _mali_dev_platform_unregister(void)
{
_mali_osk_lock_term(lock);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&mali_dev_early_suspend);
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
unregister_pm_notifier(&mali_pwr_notif_block);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
platform_driver_unregister(&mali_plat_driver);
/* We dont unregister the platform_device as it was registered by the OS not us */
}
#endif /* MALI_LICENSE_IS_GPL */
#endif /* CONFIG_PM */
#if MALI_STATE_TRACKING
u32 mali_pmm_dump_os_thread_state( char *buf, u32 size )
{
return snprintf(buf, size, "OSPMM: OS PMM thread is waiting: %s\n", is_os_pmm_thread_waiting ? "true" : "false");
}
#endif /* MALI_STATE_TRACKING */
#endif /* USING_MALI_PMM */