blob: 3b3f095855d87288271c1ef9af049e76893052f3 [file] [log] [blame]
/*
*
* (C) COPYRIGHT 2015 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_kbase.h>
#include <mali_kbase_defs.h>
#include <backend/gpu/mali_kbase_device_internal.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/io.h>
void *reg_base_hiubus = NULL;
u32 override_value_aml = 0;
static int first = 1;
static void Mali_pwr_on_with_kdev ( struct kbase_device *kbdev, uint32_t mask)
{
uint32_t part1_done;
part1_done = 0;
Mali_WrReg(0x0, 0x0, 0x0000024, 0xffffffff); // clear interrupts
if ((mask & 0x1) != 0 ) {
Mali_WrReg(0x0, 0x0, 0x00000190, 0xffffffff); // Power on all cores
Mali_WrReg(0x0, 0x0, 0x00000194, 0xffffffff); // Power on all cores
Mali_WrReg(0x0, 0x0, 0x000001a0, 0xffffffff); // Power on all cores
Mali_WrReg(0x0, 0x0, 0x000001a4, 0xffffffff); // Power on all cores
}
if ( (mask >> 1) != 0 ) {
Mali_WrReg(0x0, 0x0, 0x00000180, mask >> 1); // Power on all cores
Mali_WrReg(0x0, 0x0, 0x00000184, 0x0); // Power on all cores
}
if ( mask != 0 ) {
udelay(10);
part1_done = Mali_RdReg(0x0, 0x0, 0x0000020);
//printk("%s, %d\n", __func__, __LINE__);
while((part1_done ==0)) { part1_done = Mali_RdReg(0x0, 0x0, 0x00000020); udelay(10); }
//printk("Mali_pwr_on:gpu_irq : %x\n", part1_done);
Mali_WrReg(0x0, 0x0, 0x0000024, 0xffffffff); // clear interrupts
}
}
static void gpu_power_main( struct kbase_device *kbdev) {
Mali_pwr_on ( 0x7);
printk("%s, %d\n", __func__, __LINE__);
}
static int pm_callback_power_on(struct kbase_device *kbdev)
{
int ret;
struct platform_device *pdev = to_platform_device(kbdev->dev);
struct resource *reg_res;
u64 core_ready;
u64 l2_ready;
u64 tiler_ready;
u32 value;
//printk("20151013, %s, %d\n", __FILE__, __LINE__);
if (first == 0) goto ret;
reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!reg_res) {
dev_err(kbdev->dev, "Invalid register resource\n");
ret = -ENOENT;
}
//printk("%s, %d\n", __FILE__, __LINE__);
if (NULL == reg_base_hiubus)
reg_base_hiubus = ioremap(reg_res->start, resource_size(reg_res));
//printk("%s, %d\n", __FILE__, __LINE__);
if (NULL == reg_base_hiubus) {
dev_err(kbdev->dev, "Invalid register resource\n");
ret = -ENOENT;
}
//printk("%s, %d\n", __FILE__, __LINE__);
//JOHNT
// Level reset mail
// Level reset mail
//Wr(P_RESET2_MASK, ~(0x1<<14));
//Wr(P_RESET2_LEVEL, ~(0x1<<14));
//Wr(P_RESET2_LEVEL, 0xffffffff);
//Wr(P_RESET0_LEVEL, 0xffffffff);
value = Rd(RESET0_MASK);
value = value & (~(0x1<<20));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET0_MASK, value);
value = Rd(RESET0_LEVEL);
value = value & (~(0x1<<20));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET0_LEVEL, value);
///////////////
value = Rd(RESET2_MASK);
value = value & (~(0x1<<14));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET2_MASK, value);
value = Rd(RESET2_LEVEL);
value = value & (~(0x1<<14));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET2_LEVEL, value);
value = Rd(RESET0_LEVEL);
value = value | ((0x1<<20));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET0_LEVEL, value);
value = Rd(RESET2_LEVEL);
value = value | ((0x1<<14));
//printk("line(%d), value=%x\n", __LINE__, value);
Wr(RESET2_LEVEL, value);
udelay(10); // OR POLL for reset done
kbase_reg_write(kbdev, GPU_CONTROL_REG(PWR_KEY), 0x2968A819, NULL);
kbase_reg_write(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1), 0xfff | (0x20<<16), NULL);
gpu_power_main(kbdev);
//printk("set PWR_ORRIDE, reg=%p, reg_start=%llx, reg_size=%zx, reg_mapped=%p\n",
// kbdev->reg, kbdev->reg_start, kbdev->reg_size, reg_base_hiubus);
dev_dbg(kbdev->dev, "pm_callback_power_on %p\n",
(void *)kbdev->dev->pm_domain);
first = 0;
//printk("%s, %d\n", __FILE__, __LINE__);
ret:
ret = pm_runtime_get_sync(kbdev->dev);
udelay(100);
#if 1
core_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER);
l2_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2);
tiler_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER);
//printk("core_ready=%llx, l2_ready=%llx, tiler_ready=%llx\n", core_ready, l2_ready, tiler_ready);
#endif
dev_dbg(kbdev->dev, "pm_runtime_get returned %d\n", ret);
return 1;
}
static void pm_callback_power_off(struct kbase_device *kbdev)
{
//printk("%s, %d\n", __FILE__, __LINE__);
#if 0
iounmap(reg_base_hiubus);
reg_base_hiubus = NULL;
#endif
u64 core_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER);
u64 l2_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2);
u64 tiler_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER);
dev_dbg(kbdev->dev, "pm_callback_power_off\n");
if (core_ready)
kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, core_ready, ACTION_PWROFF);
if (l2_ready)
kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_ready, ACTION_PWROFF);
if (tiler_ready)
kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, tiler_ready, ACTION_PWROFF);
pm_runtime_put_autosuspend(kbdev->dev);
}
int kbase_device_runtime_init(struct kbase_device *kbdev)
{
dev_dbg(kbdev->dev, "kbase_device_runtime_init\n");
pm_runtime_enable(kbdev->dev);
return 0;
}
void kbase_device_runtime_disable(struct kbase_device *kbdev)
{
dev_dbg(kbdev->dev, "kbase_device_runtime_disable\n");
pm_runtime_disable(kbdev->dev);
}
static int pm_callback_runtime_on(struct kbase_device *kbdev)
{
dev_dbg(kbdev->dev, "pm_callback_runtime_on\n");
return 0;
}
static void pm_callback_runtime_off(struct kbase_device *kbdev)
{
dev_dbg(kbdev->dev, "pm_callback_runtime_off\n");
}
static void pm_callback_resume(struct kbase_device *kbdev)
{
int ret = pm_callback_runtime_on(kbdev);
WARN_ON(ret);
}
static void pm_callback_suspend(struct kbase_device *kbdev)
{
pm_callback_runtime_off(kbdev);
}
struct kbase_pm_callback_conf pm_callbacks = {
.power_on_callback = pm_callback_power_on,
.power_off_callback = pm_callback_power_off,
.power_suspend_callback = pm_callback_suspend,
.power_resume_callback = pm_callback_resume,
#ifdef KBASE_PM_RUNTIME
.power_runtime_init_callback = kbase_device_runtime_init,
.power_runtime_term_callback = kbase_device_runtime_disable,
.power_runtime_on_callback = pm_callback_runtime_on,
.power_runtime_off_callback = pm_callback_runtime_off,
#else /* KBASE_PM_RUNTIME */
.power_runtime_init_callback = NULL,
.power_runtime_term_callback = NULL,
.power_runtime_on_callback = NULL,
.power_runtime_off_callback = NULL,
#endif /* KBASE_PM_RUNTIME */
};