blob: 262219612e848c648215661f43545797c6c23880 [file] [log] [blame]
/*
* ../vendor/amlogic/common/gpu/utgard/platform/meson_m450/mali_clock.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/pm.h>
#include <mach/register.h>
#include <mach/irqs.h>
#include <linux/io.h>
#include <mach/io.h>
#include <plat/io.h>
#include <asm/io.h>
#include "meson_main.h"
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD
#define FCLK_MPLL2 (2 << 9)
static DEFINE_SPINLOCK(lock);
static mali_plat_info_t* pmali_plat = NULL;
static u32 mali_extr_backup = 0;
static u32 mali_extr_sample_backup = 0;
int mali_clock_init(mali_plat_info_t* mali_plat)
{
u32 def_clk_data;
if (mali_plat == NULL) {
printk(" Mali platform data is NULL!!!\n");
return -1;
}
pmali_plat = mali_plat;
if (pmali_plat->have_switch) {
def_clk_data = pmali_plat->clk[pmali_plat->def_clock];
writel(def_clk_data | (def_clk_data << 16), (u32*)P_HHI_MALI_CLK_CNTL);
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 24);
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
} else {
mali_clock_set(pmali_plat->def_clock);
}
mali_extr_backup = pmali_plat->clk[pmali_plat->clk_len - 1];
mali_extr_sample_backup = pmali_plat->clk_sample[pmali_plat->clk_len - 1];
return 0;
}
int mali_clock_critical(critical_t critical, size_t param)
{
int ret = 0;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
ret = critical(param);
spin_unlock_irqrestore(&lock, flags);
return ret;
}
static int critical_clock_set(size_t param)
{
unsigned int idx = param;
if (pmali_plat->have_switch) {
u32 clk_value;
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
clk_value = readl((u32 *)P_HHI_MALI_CLK_CNTL) & 0xffff0000;
clk_value = clk_value | pmali_plat->clk[idx] | (1 << 8);
writel(clk_value, (u32*)P_HHI_MALI_CLK_CNTL);
clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
} else {
clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, (0x7F | (0x7 << 9)));
writel(pmali_plat->clk[idx], (u32*)P_HHI_MALI_CLK_CNTL);
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
}
return 0;
}
int mali_clock_set(unsigned int clock)
{
return mali_clock_critical(critical_clock_set, (size_t)clock);
}
void disable_clock(void)
{
unsigned long flags;
spin_lock_irqsave(&lock, flags);
clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
spin_unlock_irqrestore(&lock, flags);
}
void enable_clock(void)
{
u32 ret;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
ret = readl((u32 *)P_HHI_MALI_CLK_CNTL) & (1 << 8);
spin_unlock_irqrestore(&lock, flags);
}
u32 get_mali_freq(u32 idx)
{
if (!mali_pm_statue) {
return pmali_plat->clk_sample[idx];
} else {
return 0;
}
}
void set_str_src(u32 data)
{
if (data == 11) {
writel(0x0004d000, (u32*)P_HHI_MPLL_CNTL9);
} else if (data > 11) {
writel(data, (u32*)P_HHI_MPLL_CNTL9);
}
if (data == 0) {
pmali_plat->clk[pmali_plat->clk_len - 1] = mali_extr_backup;
pmali_plat->clk_sample[pmali_plat->clk_len - 1] = mali_extr_sample_backup;
} else if (data > 10) {
pmali_plat->clk_sample[pmali_plat->clk_len - 1] = 600;
pmali_plat->clk[pmali_plat->clk_len - 1] = FCLK_MPLL2;
}
}
#endif