mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
add ddr tst node
This commit is contained in:
@@ -19,6 +19,9 @@
|
||||
#include <linux/rockchip/common.h>
|
||||
#include <linux/rockchip/dvfs.h>
|
||||
#include <dt-bindings/clock/ddr.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/rockchip/grf.h>
|
||||
#include <linux/rockchip/iomap.h>
|
||||
|
||||
enum {
|
||||
DEBUG_DDR = 1U << 0,
|
||||
@@ -344,12 +347,16 @@ int of_init_ddr_freq_table(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_RK_PM_TESTS)
|
||||
static void ddrfreq_tst_init(void);
|
||||
#endif
|
||||
static int ddrfreq_init(void)
|
||||
{
|
||||
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_RK_PM_TESTS)
|
||||
ddrfreq_tst_init();
|
||||
#endif
|
||||
ddr.clk_dvfs_node = clk_get_dvfs_node("clk_ddr");
|
||||
if (!ddr.clk_dvfs_node){
|
||||
return -EINVAL;
|
||||
@@ -434,3 +441,154 @@ err:
|
||||
return ret;
|
||||
}
|
||||
late_initcall(ddrfreq_init);
|
||||
|
||||
/****************************ddr bandwith tst************************************/
|
||||
#if defined(CONFIG_RK_PM_TESTS)
|
||||
|
||||
#define USE_NORMAL_TIME
|
||||
|
||||
#ifdef USE_NORMAL_TIME
|
||||
static struct timer_list ddrbw_timer;
|
||||
#else
|
||||
static struct hrtimer ddrbw_hrtimer;
|
||||
#endif
|
||||
enum ddr_bandwidth_id{
|
||||
ddrbw_wr_num=0,
|
||||
ddrbw_rd_num,
|
||||
ddrbw_act_num,
|
||||
ddrbw_time_num,
|
||||
ddrbw_eff,
|
||||
ddrbw_id_end
|
||||
};
|
||||
#define grf_readl(offset) readl_relaxed(RK_GRF_VIRT + offset)
|
||||
#define grf_writel(v, offset) do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
|
||||
|
||||
static u32 ddr_bw_show_st=0;
|
||||
|
||||
#define ddr_monitor_start() grf_writel(0xc000c000,RK3288_GRF_SOC_CON4)
|
||||
#define ddr_monitor_end() grf_writel(0xc0000000,RK3288_GRF_SOC_CON4)
|
||||
|
||||
static ssize_t ddrbw_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
char *s = buf;
|
||||
return (s - buf);
|
||||
}
|
||||
|
||||
static ssize_t ddrbw_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t n)
|
||||
{
|
||||
//const char *pbuf;
|
||||
|
||||
if((strncmp(buf, "start", strlen("start")) == 0)) {
|
||||
ddr_bw_show_st=1;
|
||||
ddr_monitor_start();
|
||||
|
||||
#ifdef USE_NORMAL_TIME
|
||||
mod_timer(&ddrbw_timer, jiffies + msecs_to_jiffies(500));
|
||||
#else
|
||||
hrtimer_start(&ddrbw_hrtimer, ktime_set(0, 5 * 1000 * 1000*1000), HRTIMER_MODE_REL);
|
||||
#endif
|
||||
|
||||
} else if((strncmp(buf, "stop", strlen("stop")) == 0)) {
|
||||
ddr_bw_show_st=0;
|
||||
ddr_monitor_end();
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void ddr_bandwidth_get(void)
|
||||
{
|
||||
u32 ddr_bw_val[2][ddrbw_id_end];
|
||||
int i,j;
|
||||
u64 temp64;
|
||||
|
||||
|
||||
for(j=0;j<2;j++)
|
||||
for(i=0;i<ddrbw_eff;i++)
|
||||
{
|
||||
ddr_bw_val[j][i]=grf_readl(RK3288_GRF_SOC_STATUS11+i*4+j*16);
|
||||
}
|
||||
ddr_monitor_end();//stop
|
||||
ddr_monitor_start();
|
||||
|
||||
temp64=((u64)ddr_bw_val[0][0]+ddr_bw_val[0][1])*8*100;
|
||||
|
||||
// printk("ch0 %llu\n",temp64);
|
||||
|
||||
do_div(temp64,ddr_bw_val[0][ddrbw_time_num]);
|
||||
ddr_bw_val[0][ddrbw_eff]= temp64;
|
||||
temp64=((u64)ddr_bw_val[1][0]+ddr_bw_val[1][1])*8*100;
|
||||
|
||||
//printk("ch1 %llu\n",temp64);
|
||||
|
||||
do_div(temp64,ddr_bw_val[1][ddrbw_time_num]);
|
||||
ddr_bw_val[1][ddrbw_eff]= temp64;
|
||||
|
||||
printk("ddrch0,wr,rd,act,time,percent(%x,%x,%x,%x,%d)\n",
|
||||
ddr_bw_val[0][0],ddr_bw_val[0][1],ddr_bw_val[0][2],ddr_bw_val[0][3],ddr_bw_val[0][4]);
|
||||
printk("ddrch1,wr,rd,act,time,percent(%x,%x,%x,%x,%d)\n",
|
||||
ddr_bw_val[1][0],ddr_bw_val[1][1],ddr_bw_val[1][2],ddr_bw_val[1][3],ddr_bw_val[1][4]);
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_NORMAL_TIME
|
||||
static void ddrbw_timer_fn(unsigned long data)
|
||||
{
|
||||
//int i;
|
||||
ddr_bandwidth_get();
|
||||
if(ddr_bw_show_st)
|
||||
{
|
||||
mod_timer(&ddrbw_timer, jiffies + msecs_to_jiffies(500));
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct hrtimer ddrbw_hrtimer;
|
||||
static enum hrtimer_restart ddrbw_hrtimer_timer_func(struct hrtimer *timer)
|
||||
{
|
||||
int i;
|
||||
ddr_bandwidth_get();
|
||||
if(ddr_bw_show_st)
|
||||
hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ddrfreq_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf);
|
||||
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t n);
|
||||
};
|
||||
|
||||
static struct ddrfreq_attribute ddrfreq_attrs[] = {
|
||||
/* node_name permision show_func store_func */
|
||||
__ATTR(ddrbw, S_IRUSR | S_IRGRP | S_IWUSR,ddrbw_dyn_show, ddrbw_dyn_store),
|
||||
};
|
||||
int rk_pm_tests_kobj_atrradd(const struct attribute *attr);
|
||||
|
||||
static void ddrfreq_tst_init(void)
|
||||
{
|
||||
int i,ret;
|
||||
#ifdef USE_NORMAL_TIME
|
||||
init_timer(&ddrbw_timer);
|
||||
//ddrbw_timer.expires = jiffies+msecs_to_jiffies(1);
|
||||
ddrbw_timer.function = ddrbw_timer_fn;
|
||||
//mod_timer(&ddrbw_timer,jiffies+msecs_to_jiffies(1));
|
||||
#else
|
||||
hrtimer_init(&ddrbw_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
ddrbw_hrtimer.function = ddrbw_hrtimer_timer_func;
|
||||
//hrtimer_start(&ddrbw_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);
|
||||
#endif
|
||||
printk("*****%s*****\n",__FUNCTION__);
|
||||
|
||||
ret = rk_pm_tests_kobj_atrradd(&ddrfreq_attrs[0].attr);
|
||||
if (ret != 0) {
|
||||
printk("create ddrfreq sysfs node error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
42
arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c
Normal file → Executable file
42
arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c
Normal file → Executable file
@@ -53,7 +53,7 @@ REVISION 0.01
|
||||
#include "cpu_usage.h"
|
||||
#include "dvfs_table_scan.h"
|
||||
|
||||
static struct kobject *pm_tests_kobj;
|
||||
struct kobject *rk_pm_tests_kobj=NULL;
|
||||
struct pm_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
@@ -79,19 +79,51 @@ static struct pm_attribute pm_attrs[] = {
|
||||
|
||||
static void __exit rk_pm_tests_exit(void)
|
||||
{
|
||||
kobject_put(pm_tests_kobj);
|
||||
kobject_put(rk_pm_tests_kobj);
|
||||
}
|
||||
|
||||
|
||||
struct kobject *get_rk_pm_tests_kobj(void)
|
||||
{
|
||||
|
||||
if(rk_pm_tests_kobj==NULL)
|
||||
{
|
||||
rk_pm_tests_kobj = kobject_create_and_add("pm_tests", NULL);
|
||||
|
||||
if (!rk_pm_tests_kobj)
|
||||
return NULL;
|
||||
}
|
||||
return rk_pm_tests_kobj;
|
||||
}
|
||||
|
||||
int rk_pm_tests_kobj_atrradd(const struct attribute *attr)
|
||||
{
|
||||
int ret;
|
||||
struct kobject * pm_kobj;
|
||||
pm_kobj =get_rk_pm_tests_kobj();
|
||||
|
||||
if (!pm_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_file(pm_kobj,attr);
|
||||
if (ret != 0) {
|
||||
PM_ERR("pm tests create %s node error\n",attr->name);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init rk_pm_tests_init(void)
|
||||
{
|
||||
int i, ret = 0;
|
||||
pm_tests_kobj = kobject_create_and_add("pm_tests", NULL);
|
||||
struct kobject * pm_kobj;
|
||||
pm_kobj =get_rk_pm_tests_kobj();
|
||||
|
||||
if (!pm_tests_kobj)
|
||||
if (!pm_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pm_attrs); i++) {
|
||||
ret = sysfs_create_file(pm_tests_kobj, &pm_attrs[i].attr);
|
||||
ret = sysfs_create_file(pm_kobj, &pm_attrs[i].attr);
|
||||
if (ret != 0) {
|
||||
PM_ERR("create index %d error\n", i);
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user