mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
RK3168/RK3188:add DDR_CHANGE_FREQ_IN_LCDC_VSYNC
This commit is contained in:
@@ -23,10 +23,11 @@
|
||||
#include <mach/ddr.h>
|
||||
#include <mach/cpu.h>
|
||||
#include <plat/efuse.h>
|
||||
#include <linux/rk_fb.h>
|
||||
|
||||
typedef uint32_t uint32;
|
||||
|
||||
#define ENABLE_DDR_CLCOK_GPLL_PATH //for RK3188
|
||||
//#define ENABLE_DDR_CLCOK_GPLL_PATH //for RK3188
|
||||
|
||||
#define DDR3_DDR2_DLL_DISABLE_FREQ (125)
|
||||
#define DDR3_DDR2_ODT_DISABLE_FREQ (333)
|
||||
@@ -3525,7 +3526,7 @@ int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t mi
|
||||
data8_dqstr[dqstr_value][3]=pPHY_Reg->DATX8[0].DXDQSTR;
|
||||
|
||||
ddr_print("training %luMhz[%d]:0x%x-0x%x-0x%x-0x%x\n",
|
||||
clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000,dqstr_value,data8_dqstr[dqstr_value][0],data8_dqstr[dqstr_value][1],
|
||||
clk_get_rate(clk_get(NULL, "ddr"))/1000000,dqstr_value,data8_dqstr[dqstr_value][0],data8_dqstr[dqstr_value][1],
|
||||
data8_dqstr[dqstr_value][2],data8_dqstr[dqstr_value][3]);
|
||||
return 0;
|
||||
}
|
||||
@@ -3594,7 +3595,7 @@ void __sramlocalfunc ddr_set_pll_exit_3168(uint32 freq_slew,uint32_t dqstr_value
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
|
||||
uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz , struct ddr_freq_t ddr_freq_t)
|
||||
{
|
||||
uint32_t ret;
|
||||
u32 i;
|
||||
@@ -3608,7 +3609,7 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
|
||||
uint32_t freq_slew=0,dqstr_value=0;
|
||||
if(dqstr_flag==true)
|
||||
{
|
||||
dqstr_value=(nMHz-min_ddr_freq+1)/50;
|
||||
dqstr_value=((nMHz-min_ddr_freq+1)/25 + 1) /2;
|
||||
freq_slew = (nMHz>ddr_freq)? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
@@ -3653,6 +3654,26 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
|
||||
#endif
|
||||
dsb();
|
||||
|
||||
#if defined (DDR_CHANGE_FREQ_IN_LCDC_VSYNC)
|
||||
if(ddr_freq_t.screen_ft_us > 0)
|
||||
{
|
||||
ddr_freq_t.t1 = cpu_clock(0);
|
||||
ddr_freq_t.t2 = (u32)(ddr_freq_t.t1 - ddr_freq_t.t0)/1000;
|
||||
|
||||
if(ddr_freq_t.t2 > ddr_freq_t.screen_ft_us)
|
||||
{
|
||||
DDR_RESTORE_SP(save_sp);
|
||||
local_fiq_enable();
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rk_fb_poll_wait_frame_complete();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** 2. ddr enter self-refresh mode or precharge power-down mode */
|
||||
idle_port();
|
||||
#if defined(CONFIG_ARCH_RK3066B)
|
||||
@@ -3682,6 +3703,8 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
|
||||
uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
|
||||
{
|
||||
uint32_t gpll_freq,gpll_div;
|
||||
struct ddr_freq_t ddr_freq_t;
|
||||
ddr_freq_t.screen_ft_us = 0;
|
||||
|
||||
gpllvaluel = ddr_get_pll_freq(GPLL);
|
||||
|
||||
@@ -3704,7 +3727,7 @@ uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
|
||||
}
|
||||
|
||||
ddr_select_gpll_div=gpll_div; //select GPLL
|
||||
ddr_change_freq_sram(gpll_freq);
|
||||
ddr_change_freq_sram(gpll_freq,ddr_freq_t);
|
||||
ddr_select_gpll_div=0;
|
||||
|
||||
ddr_set_pll(nMHz,0); //count DPLL
|
||||
@@ -3715,7 +3738,7 @@ uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
|
||||
ddr_print("GPLL frequency = %dMHz,Not suitable for ddr_clock \n",gpllvaluel);
|
||||
}
|
||||
|
||||
return ddr_change_freq_sram(nMHz);
|
||||
return ddr_change_freq_sram(nMHz,ddr_freq_t);
|
||||
|
||||
}
|
||||
|
||||
@@ -3729,19 +3752,14 @@ if rk3188 DPLL is bad,use GPLL
|
||||
******************************************/
|
||||
uint32_t ddr_change_freq(uint32_t nMHz)
|
||||
{
|
||||
struct ddr_freq_t ddr_freq_t;
|
||||
ddr_freq_t.screen_ft_us = 0;
|
||||
|
||||
if(ddr_rk3188_dpll_is_good == false) //if rk3188 DPLL is bad,use GPLL
|
||||
{
|
||||
return ddr_change_freq_sram(nMHz);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(ENABLE_DDR_CLCOK_GPLL_PATH) && defined(CONFIG_ARCH_RK3188)
|
||||
return ddr_change_freq_gpll_dpll(nMHz);
|
||||
return ddr_change_freq_gpll_dpll(nMHz);
|
||||
#else
|
||||
return ddr_change_freq_sram(nMHz);
|
||||
return ddr_change_freq_sram(nMHz,ddr_freq_t);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ddr_change_freq);
|
||||
|
||||
@@ -3982,7 +4000,7 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
|
||||
uint32_t die=1;
|
||||
uint32_t gsr,dqstr;
|
||||
|
||||
ddr_print("version 1.00 20130712 \n");
|
||||
ddr_print("version 1.00 20130805 0 \n");
|
||||
|
||||
mem_type = pPHY_Reg->DCR.b.DDRMD;
|
||||
ddr_speed_bin = dram_speed_bin;
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
#include <mach/ddr.h>
|
||||
#include <mach/dvfs.h>
|
||||
|
||||
#include <linux/rk_fb.h>
|
||||
//#include <linux/delay.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
enum {
|
||||
DEBUG_DDR = 1U << 0,
|
||||
DEBUG_VIDEO_STATE = 1U << 1,
|
||||
@@ -34,13 +41,15 @@ module_param(debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
|
||||
enum SYS_STATUS {
|
||||
SYS_STATUS_SUSPEND = 0, // 0x01
|
||||
SYS_STATUS_VIDEO, // 0x02
|
||||
SYS_STATUS_GPU, // 0x04
|
||||
SYS_STATUS_RGA, // 0x08
|
||||
SYS_STATUS_CIF0, // 0x10
|
||||
SYS_STATUS_CIF1, // 0x20
|
||||
SYS_STATUS_REBOOT, // 0x40
|
||||
SYS_STATUS_LCDC0, // 0x80
|
||||
SYS_STATUS_LCDC1, // 0x100
|
||||
SYS_STATUS_VIDEO_720P, // 0x04
|
||||
SYS_STATUS_VIDEO_1080P, // 0x08
|
||||
SYS_STATUS_GPU, // 0x10
|
||||
SYS_STATUS_RGA, // 0x20
|
||||
SYS_STATUS_CIF0, // 0x40
|
||||
SYS_STATUS_CIF1, // 0x80
|
||||
SYS_STATUS_REBOOT, // 0x100
|
||||
SYS_STATUS_LCDC0, // 0x200
|
||||
SYS_STATUS_LCDC1, // 0x400
|
||||
};
|
||||
|
||||
struct ddr {
|
||||
@@ -51,6 +60,7 @@ struct ddr {
|
||||
struct clk *clk;
|
||||
unsigned long normal_rate;
|
||||
unsigned long video_rate;
|
||||
unsigned long video_low_rate;
|
||||
unsigned long dualview_rate;
|
||||
unsigned long idle_rate;
|
||||
unsigned long suspend_rate;
|
||||
@@ -117,8 +127,13 @@ static noinline void ddrfreq_work(unsigned long sys_status)
|
||||
&& (s & (1 << SYS_STATUS_LCDC1))
|
||||
) {
|
||||
ddrfreq_mode(false, &ddr.dualview_rate, "dual-view");
|
||||
} else if (ddr.video_rate && (s & (1 << SYS_STATUS_VIDEO))) {
|
||||
ddrfreq_mode(false, &ddr.video_rate, "video");
|
||||
} else if ((ddr.video_rate || ddr.video_low_rate) && (s & (1 << SYS_STATUS_VIDEO))) {
|
||||
if(ddr.video_low_rate && (s & (1 << SYS_STATUS_VIDEO_720P)))
|
||||
ddrfreq_mode(false, &ddr.video_low_rate, "video low");
|
||||
else if(ddr.video_rate && (s & (1 << SYS_STATUS_VIDEO_1080P)))
|
||||
ddrfreq_mode(false, &ddr.video_rate, "video");
|
||||
else
|
||||
ddrfreq_mode(false, &ddr.normal_rate, "video normal");
|
||||
} else if (ddr.idle_rate
|
||||
&& !(s & (1 << SYS_STATUS_GPU))
|
||||
&& !(s & (1 << SYS_STATUS_RGA))
|
||||
@@ -174,11 +189,12 @@ static void __sramfunc pause_cpu(void *info)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void _ddr_change_freq(uint32_t nMHz)
|
||||
static int _ddr_change_freq_(uint32_t nMHz,struct ddr_freq_t ddr_freq_t)
|
||||
{
|
||||
u32 timeout = MAX_TIMEOUT;
|
||||
unsigned int cpu;
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
int ret;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
|
||||
@@ -195,12 +211,45 @@ static void _ddr_change_freq(uint32_t nMHz)
|
||||
}
|
||||
}
|
||||
|
||||
ddr_change_freq(nMHz);
|
||||
ret = ddr_change_freq_sram(nMHz,ddr_freq_t);
|
||||
|
||||
set_other_cpus_pause(false);
|
||||
|
||||
out:
|
||||
cpu_maps_update_done();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _ddr_change_freq(uint32_t nMHz)
|
||||
{
|
||||
struct ddr_freq_t ddr_freq_t;
|
||||
int test_count=0;
|
||||
|
||||
ddr_freq_t.screen_ft_us = 0;
|
||||
ddr_freq_t.t0 = 0;
|
||||
ddr_freq_t.t1 = 0;
|
||||
|
||||
#if defined (DDR_CHANGE_FREQ_IN_LCDC_VSYNC)
|
||||
do
|
||||
{
|
||||
if(rk_fb_poll_wait_frame_complete() == true)
|
||||
{
|
||||
ddr_freq_t.t0 = cpu_clock(0);
|
||||
ddr_freq_t.screen_ft_us = rk_fb_get_prmry_screen_ft();
|
||||
|
||||
test_count++;
|
||||
//dprintk(DEBUG_VERBOSE,"test_count=%d\n",test_count);
|
||||
usleep_range(ddr_freq_t.screen_ft_us-test_count*1000,ddr_freq_t.screen_ft_us-test_count*1000);
|
||||
|
||||
flush_cache_all();
|
||||
outer_flush_all();
|
||||
flush_tlb_all();
|
||||
}
|
||||
}while(_ddr_change_freq_(nMHz,ddr_freq_t)==0);
|
||||
#else
|
||||
_ddr_change_freq_(nMHz,ddr_freq_t);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void _ddr_change_freq(uint32_t nMHz)
|
||||
@@ -237,27 +286,67 @@ static int video_state_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VIDEO_LOW_RESOLUTION (1080*720)
|
||||
static ssize_t video_state_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char state;
|
||||
char *cookie_pot;
|
||||
char *p;
|
||||
char *buf = vzalloc(count);
|
||||
uint32_t v_width=0,v_height=0,v_sync=0;
|
||||
cookie_pot = buf;
|
||||
|
||||
if (count < 1)
|
||||
return count;
|
||||
if (copy_from_user(&state, buffer, 1)) {
|
||||
if (copy_from_user(cookie_pot, buffer, count)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dprintk(DEBUG_VIDEO_STATE, "video_state write %c\n", state);
|
||||
dprintk(DEBUG_VIDEO_STATE, "video_state write %s,len %d\n", cookie_pot,count);
|
||||
|
||||
state=cookie_pot[0];
|
||||
if( (count>=3) && (cookie_pot[2]=='w') )
|
||||
{
|
||||
strsep(&cookie_pot,",");
|
||||
strsep(&cookie_pot,"=");
|
||||
p=strsep(&cookie_pot,",");
|
||||
v_width = simple_strtol(p,NULL,10);
|
||||
strsep(&cookie_pot,"=");
|
||||
p=strsep(&cookie_pot,",");
|
||||
v_height= simple_strtol(p,NULL,10);
|
||||
strsep(&cookie_pot,"=");
|
||||
p=strsep(&cookie_pot,",");
|
||||
v_sync= simple_strtol(p,NULL,10);
|
||||
dprintk(DEBUG_VIDEO_STATE, "video_state %c,width=%d,height=%d,sync=%d\n", state,v_width,v_height,v_sync);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case '0':
|
||||
ddrfreq_clear_sys_status(SYS_STATUS_VIDEO);
|
||||
ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_720P);
|
||||
ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_1080P);
|
||||
break;
|
||||
case '1':
|
||||
ddrfreq_set_sys_status(SYS_STATUS_VIDEO);
|
||||
|
||||
if( (v_width == 0) && (v_height == 0)){
|
||||
ddrfreq_set_sys_status(SYS_STATUS_VIDEO_1080P);
|
||||
}
|
||||
else if(v_sync==1){
|
||||
if(ddr.video_low_rate && ((v_width*v_height) <= VIDEO_LOW_RESOLUTION) )
|
||||
ddrfreq_set_sys_status(SYS_STATUS_VIDEO_720P);
|
||||
else
|
||||
ddrfreq_set_sys_status(SYS_STATUS_VIDEO_1080P);
|
||||
}
|
||||
else{
|
||||
ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_720P);
|
||||
ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_1080P);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
ddr.video_state = state;
|
||||
return count;
|
||||
@@ -383,7 +472,7 @@ static int ddrfreq_init(void)
|
||||
{
|
||||
int i, ret;
|
||||
struct cpufreq_frequency_table *table;
|
||||
bool new_version = false;
|
||||
int ddrfreq_version = 0;
|
||||
|
||||
init_waitqueue_head(&ddr.wait);
|
||||
ddr.video_state = '0';
|
||||
@@ -409,16 +498,22 @@ static int ddrfreq_init(void)
|
||||
|
||||
for (i = 0; table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
if (table[i].frequency % 1000) {
|
||||
new_version = true;
|
||||
ddrfreq_version = 1;
|
||||
}
|
||||
|
||||
if (table[i].frequency % 1000 > 100) {
|
||||
ddrfreq_version = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!new_version) {
|
||||
|
||||
if (ddrfreq_version==0) {
|
||||
ddr.video_rate = 300 * MHZ;
|
||||
ddr.dualview_rate = ddr.normal_rate;
|
||||
ddr.suspend_rate = 200 * MHZ;
|
||||
}
|
||||
for (i = 0; new_version && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
|
||||
for (i = 0; ddrfreq_version == 1 && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned int mode = table[i].frequency % 1000;
|
||||
unsigned long rate;
|
||||
|
||||
@@ -429,6 +524,9 @@ static int ddrfreq_init(void)
|
||||
case DDR_FREQ_NORMAL:
|
||||
ddr.normal_rate = rate;
|
||||
break;
|
||||
case DDR_FREQ_VIDEO_LOW:
|
||||
ddr.video_low_rate = rate;
|
||||
break;
|
||||
case DDR_FREQ_VIDEO:
|
||||
ddr.video_rate = rate;
|
||||
break;
|
||||
@@ -444,6 +542,32 @@ static int ddrfreq_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; ddrfreq_version == 2 && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
unsigned int mode = table[i].frequency % 1000;
|
||||
unsigned long rate;
|
||||
|
||||
table[i].frequency -= mode;
|
||||
rate = table[i].frequency * 1000;
|
||||
|
||||
if( (mode&DDR_FREQ_NORMAL) == DDR_FREQ_NORMAL)
|
||||
ddr.normal_rate = rate;
|
||||
|
||||
if( (mode&DDR_FREQ_VIDEO_LOW) == DDR_FREQ_VIDEO_LOW)
|
||||
ddr.video_low_rate = rate;
|
||||
|
||||
if( (mode&DDR_FREQ_VIDEO) == DDR_FREQ_VIDEO)
|
||||
ddr.video_rate = rate;
|
||||
|
||||
if( (mode&DDR_FREQ_DUALVIEW) == DDR_FREQ_DUALVIEW)
|
||||
ddr.dualview_rate= rate;
|
||||
|
||||
if( (mode&DDR_FREQ_IDLE) == DDR_FREQ_IDLE)
|
||||
ddr.idle_rate = rate;
|
||||
|
||||
if( (mode&DDR_FREQ_SUSPEND) == DDR_FREQ_SUSPEND)
|
||||
ddr.suspend_rate = rate;
|
||||
}
|
||||
|
||||
if (ddr.idle_rate) {
|
||||
REGISTER_CLK_NOTIFIER(pd_gpu);
|
||||
REGISTER_CLK_NOTIFIER(pd_rga);
|
||||
@@ -501,9 +625,9 @@ static int ddrfreq_late_init(void)
|
||||
|
||||
register_reboot_notifier(&ddrfreq_reboot_notifier);
|
||||
|
||||
pr_info("verion 2.4 20130427\n");
|
||||
dprintk(DEBUG_DDR, "normal %luMHz video %luMHz dualview %luMHz idle %luMHz suspend %luMHz reboot %luMHz\n",
|
||||
ddr.normal_rate / MHZ, ddr.video_rate / MHZ, ddr.dualview_rate / MHZ,ddr.idle_rate / MHZ, ddr.suspend_rate / MHZ, ddr.reboot_rate / MHZ);
|
||||
pr_info("verion 3.1 20130805\n");
|
||||
dprintk(DEBUG_DDR, "normal %luMHz video %luMHz video_low %luMHz dualview %luMHz idle %luMHz suspend %luMHz reboot %luMHz\n",
|
||||
ddr.normal_rate / MHZ, ddr.video_rate / MHZ, ddr.video_low_rate / MHZ, ddr.dualview_rate / MHZ, ddr.idle_rate / MHZ, ddr.suspend_rate / MHZ, ddr.reboot_rate / MHZ);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
87
arch/arm/plat-rk/ddr_test.c
Normal file → Executable file
87
arch/arm/plat-rk/ddr_test.c
Normal file → Executable file
@@ -8,6 +8,21 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <mach/ddr.h>
|
||||
|
||||
struct ddrtest {
|
||||
struct clk *pll;
|
||||
struct clk *clk;
|
||||
volatile unsigned int freq;
|
||||
volatile bool change_end;
|
||||
struct task_struct *task;
|
||||
wait_queue_head_t wait;
|
||||
};
|
||||
static struct ddrtest ddrtest;
|
||||
|
||||
static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
unsigned long len, void *data)
|
||||
{
|
||||
@@ -52,10 +67,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
p=strsep(&cookie_pot,"M");
|
||||
value = simple_strtol(p,NULL,10);
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
clk_set_rate(clk_ddr, value * 1000000);
|
||||
//clk_set_rate(clk_ddr, value * 1000000);
|
||||
ddrtest.freq = value;
|
||||
ddrtest.change_end = false;
|
||||
wake_up(&ddrtest.wait);
|
||||
while(ddrtest.change_end != true); //wait change freq end
|
||||
value = clk_get_rate(clk_ddr) / 1000000;
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
msleep(32);
|
||||
msleep(64);
|
||||
printk("\n");
|
||||
}
|
||||
else
|
||||
@@ -92,10 +111,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
}while(value < value1);
|
||||
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
clk_set_rate(clk_ddr, value * 1000000);
|
||||
//clk_set_rate(clk_ddr, value * 1000000);
|
||||
ddrtest.freq = value;
|
||||
ddrtest.change_end = false;
|
||||
wake_up(&ddrtest.wait);
|
||||
while(ddrtest.change_end != true); //wait change freq end
|
||||
value = clk_get_rate(clk_ddr) / 1000000;
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
msleep(32);
|
||||
msleep(64);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -140,10 +163,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
}
|
||||
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
clk_set_rate(clk_ddr, value * 1000000);
|
||||
//clk_set_rate(clk_ddr, value * 1000000);
|
||||
ddrtest.freq = value;
|
||||
ddrtest.change_end = false;
|
||||
wake_up(&ddrtest.wait);
|
||||
while(ddrtest.change_end != true); //wait change freq end
|
||||
value = clk_get_rate(clk_ddr) / 1000000;
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
msleep(32);
|
||||
msleep(64);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -176,19 +203,65 @@ static const struct file_operations ddr_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void ddrtest_work(unsigned int value)
|
||||
{
|
||||
|
||||
clk_set_rate(ddrtest.clk, value * 1000000);
|
||||
ddrtest.change_end = true;
|
||||
}
|
||||
|
||||
static int ddrtest_task(void *data)
|
||||
{
|
||||
set_freezable();
|
||||
|
||||
do {
|
||||
//unsigned long status = ddr.sys_status;
|
||||
ddrtest_work(ddrtest.freq);
|
||||
wait_event_freezable(ddrtest.wait, (ddrtest.change_end == false ) || kthread_should_stop());
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ddr_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *ddr_proc_entry;
|
||||
int ret;
|
||||
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
|
||||
init_waitqueue_head(&ddrtest.wait);
|
||||
|
||||
ddrtest.pll = clk_get(NULL, "ddr_pll");
|
||||
ddrtest.clk = clk_get(NULL, "ddr");
|
||||
if (IS_ERR(ddrtest.clk)) {
|
||||
ret = PTR_ERR(ddrtest.clk);
|
||||
ddrtest.clk = NULL;
|
||||
pr_err("failed to get ddr clk, error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ddr_proc_entry = create_proc_entry("driver/ddr_ts", 0777, NULL);
|
||||
if(ddr_proc_entry != NULL)
|
||||
{
|
||||
ddr_proc_entry->write_proc = ddr_proc_write;
|
||||
return -1;
|
||||
//return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("create proc error !\n");
|
||||
}
|
||||
|
||||
ddrtest.task = kthread_create(ddrtest_task, NULL, "ddrtestd");
|
||||
if (IS_ERR(ddrtest.task)) {
|
||||
ret = PTR_ERR(ddrtest.task);
|
||||
pr_err("failed to create kthread! error %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
sched_setscheduler_nocheck(ddrtest.task,SCHED_FIFO, ¶m);
|
||||
get_task_struct(ddrtest.task);
|
||||
kthread_bind(ddrtest.task, 0);
|
||||
wake_up_process(ddrtest.task);
|
||||
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -555,8 +555,7 @@ void __sramfunc board_pmu_resume(void);
|
||||
* For DDR frequency scaling setup. Board code something like this:
|
||||
*
|
||||
* This array _must_ be sorted in ascending frequency (without DDR_FREQ_*) order.
|
||||
* 必须按频率(不必考虑DDR_FREQ_*)递增。
|
||||
*static struct cpufreq_frequency_table dvfs_ddr_table[] = {
|
||||
* 必须按频率(不必考虑DDR_FREQ_*)递增<EFBFBD><EFBFBD>? *static struct cpufreq_frequency_table dvfs_ddr_table[] = {
|
||||
* {.frequency = 200 * 1000 + DDR_FREQ_SUSPEND, .index = xxxx * 1000},
|
||||
* {.frequency = 200 * 1000 + DDR_FREQ_IDLE, .index = xxxx * 1000},
|
||||
* {.frequency = 300 * 1000 + DDR_FREQ_VIDEO, .index = xxxx * 1000},
|
||||
@@ -565,11 +564,12 @@ void __sramfunc board_pmu_resume(void);
|
||||
*};
|
||||
*/
|
||||
enum ddr_freq_mode {
|
||||
DDR_FREQ_NORMAL = 1, // default
|
||||
DDR_FREQ_VIDEO, // when video is playing
|
||||
DDR_FREQ_DUALVIEW, // when dual view,lcdc0 and lcdc1 open at the same time
|
||||
DDR_FREQ_IDLE, // when screen is idle
|
||||
DDR_FREQ_SUSPEND, // when early suspend
|
||||
DDR_FREQ_SUSPEND=(0x1<<0), // when early suspend
|
||||
DDR_FREQ_VIDEO=(0x1<<1), // when video is playing
|
||||
DDR_FREQ_VIDEO_LOW=(0x1<<2), // when video is playing low
|
||||
DDR_FREQ_DUALVIEW=(0x1<<3), // when dual view,lcdc0 and lcdc1 open at the same time
|
||||
DDR_FREQ_IDLE=(0x1<<4), // when screen is idle
|
||||
DDR_FREQ_NORMAL=(0x1<<8), // default
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -149,7 +149,14 @@ void __sramfunc ddr_resume(void);
|
||||
#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026)
|
||||
uint32_t __sramfunc ddr_change_freq(uint32_t nMHz);
|
||||
#else
|
||||
struct ddr_freq_t {
|
||||
unsigned long screen_ft_us;
|
||||
unsigned long long t0;
|
||||
unsigned long long t1;
|
||||
unsigned long t2;
|
||||
};
|
||||
uint32_t ddr_change_freq(uint32_t nMHz);
|
||||
uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz , struct ddr_freq_t ddr_freq_t);
|
||||
#endif
|
||||
uint32_t ddr_get_cap(void);
|
||||
int ddr_init(uint32_t dram_type, uint32_t freq);
|
||||
@@ -160,4 +167,8 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set);
|
||||
int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t min_freq);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
|
||||
#define DDR_CHANGE_FREQ_IN_LCDC_VSYNC
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user