#include <linux/io.h>\r
#include <linux/hrtimer.h>\r
\r
-static int clk_disable_target(struct clk *clk, int on)\r
-{\r
- struct clk_node *dvfs_clk;\r
- int volt_new = 0, clk_volt_store = 0;\r
- struct cpufreq_frequency_table clk_fv;\r
- unsigned long rate_hz;\r
- int ret = 0;\r
-\r
- if (!clk) {\r
- DVFS_ERR("%s is not a clk\n", __func__);\r
- return -1;\r
- }\r
- dvfs_clk = clk_get_dvfs_info(clk);\r
-\r
- if (!dvfs_clk || dvfs_clk->vd == NULL || IS_ERR_OR_NULL(dvfs_clk->vd->regulator)) {\r
- DVFS_ERR("dvfs(%s) is not register regulator\n", dvfs_clk->name);\r
- return -1;\r
- }\r
-\r
- if (dvfs_clk->vd->volt_set_flag == DVFS_SET_VOLT_FAILURE) {\r
- /* It means the last time set voltage error */\r
- ret = dvfs_reset_volt(dvfs_clk->vd);\r
- if (ret < 0) {\r
- return -1;\r
- }\r
- }\r
-\r
- clk_volt_store = dvfs_clk->set_volt; \r
- // firsh up volt in this,next on clk out off this fun\r
- if(on||clk_used_count(clk))\r
- {\r
- rate_hz = clk_get_rate(clk);\r
- /* find the clk corresponding voltage */\r
- if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_hz / 1000, &clk_fv)) {\r
- DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
- return -1;\r
- } \r
- dvfs_clk->set_volt = clk_fv.index;\r
-\r
- }\r
- else// in this clk is real disable\r
- {\r
- dvfs_clk->set_volt =0; \r
- } \r
- \r
-\r
- volt_new = dvfs_vd_get_newvolt_byclk(dvfs_clk);\r
-\r
- DVFS_DBG("**%s:clk=%s(%s),rate=%lu,clk volt=%d,vd volt=%d\n",__FUNCTION__,dvfs_clk->name,\r
- on?"enable":"disable",clk_get_rate(clk)/1000,dvfs_clk->set_volt,volt_new);\r
-\r
-\r
- if (volt_new == dvfs_clk->vd->cur_volt)\r
- return 0;\r
-\r
- ret = dvfs_scale_volt_direct(dvfs_clk->vd, volt_new);\r
- if (ret < 0)\r
- {\r
- printk("%s:clk=%s set volt error\n",__FUNCTION__,dvfs_clk->name);\r
-\r
- if(!clk_used_count(clk)) \r
- dvfs_clk->set_volt = 0;\r
- else\r
- {\r
- rate_hz = clk_get_rate(clk);\r
- /* find the clk corresponding voltage */\r
- if (0 != dvfs_clk_get_ref_volt(dvfs_clk, rate_hz / 1000, &clk_fv)) {\r
- DVFS_ERR("dvfs(%s) rate %luhz is larger,not support\n", dvfs_clk->name, rate_hz);\r
- return -1;\r
- } \r
- dvfs_clk->set_volt = clk_fv.index;\r
- }\r
- }\r
-\r
- return ret;\r
-}\r
static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
unsigned long event, void *ptr)\r
{\r
#else\r
.vd_dvfs_target = dvfs_target_core,\r
#endif\r
- .vd_clk_disable_target= dvfs_vd_clk_disable_target,\r
+\r
};\r
\r
static struct vd_node vd_rtc = {\r
CLK_PDS(NULL),\r
};\r
\r
-#define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb, _disable) \\r
+#define RK_CLKS(_clk_name, _ppds, _dvfs_table, _dvfs_nb) \\r
{ \\r
.name = _clk_name, \\r
.pds = _ppds,\\r
.dvfs_table = _dvfs_table, \\r
.dvfs_nb = _dvfs_nb, \\r
- .disable_ctr = _disable, \\r
}\r
\r
-static struct clk_disable_ctr gpu_disable= {\r
- .disable_work_fn=dvfs_clk_disable_delay_work,\r
- .clk_disable_target=clk_disable_target,\r
- .delay=40,//ms\r
-};\r
static struct clk_node rk30_clks[] = {\r
- RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier, NULL),\r
- RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier, NULL),\r
- RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier,&gpu_disable),\r
- RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier, NULL),\r
+ RK_CLKS("cpu", cpu_pds, cpu_dvfs_table, &rk_dvfs_clk_notifier),\r
+ RK_CLKS("ddr", ddr_pds, ddr_dvfs_table, &rk_dvfs_clk_notifier),\r
+ RK_CLKS("gpu", gpu_pds, gpu_dvfs_table, &rk_dvfs_clk_notifier),\r
+ RK_CLKS("aclk_periph", aclk_periph_pds, peri_aclk_dvfs_table, &rk_dvfs_clk_notifier),\r
};\r
\r
#if 0\r
return ret;
}
/**********************************dvfs****************************************************/
+
+struct clk_node *clk_get_dvfs_info(struct clk *clk)
+{
+ return clk->dvfs_info;
+}
+
int clk_set_rate_locked(struct clk * clk,unsigned long rate)
{
int ret;
{
clk->dvfs_info = dvfs_clk;
}
-int clk_set_enable_locked(struct clk * clk,int on)
-{
- int ret=0;
- LOCK();
- if(on)
- ret=clk_enable_nolock(clk);
- else
- clk_disable_nolock(clk);
- UNLOCK();
- return ret;
-}
-EXPORT_SYMBOL(clk_set_enable_locked);
+
+
/*-------------------------------------------------------------------------
* Optional clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
}
if (rate == clk->rate)
return 0;
- if (dvfs_support_clk_set_rate(clk->dvfs_info)==true)
- return dvfs_vd_clk_set_rate(clk, rate);
+ if (clk->dvfs_info!=NULL&&is_support_dvfs(clk->dvfs_info))
+ return dvfs_set_rate(clk, rate);
LOCK();
ret = clk_set_rate_nolock(clk, rate);
{
if (clk == NULL || IS_ERR(clk))
return;
- if (dvfs_support_clk_disable(clk->dvfs_info)==true)
- return dvfs_vd_clk_disable(clk, 0);
LOCK();
clk_disable_nolock(clk);
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- if (dvfs_support_clk_disable(clk->dvfs_info)==true)
- return dvfs_vd_clk_disable(clk, 1);
LOCK();
ret = clk_enable_nolock(clk);
\r
static int dump_dbg_map(char *buf);\r
\r
-static struct workqueue_struct *dvfs_wq;\r
#define PD_ON 1\r
#define PD_OFF 0\r
-#define DVFS_STR_DISABLE(on) ((on)?"enable":"disable")\r
\r
#define get_volt_up_delay(new_volt, old_volt) \\r
((new_volt) > (old_volt) ? (((new_volt) - (old_volt)) >> 9) : 0)\r
return 0;\r
}\r
\r
-int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate)\r
+int is_support_dvfs(struct clk_node *dvfs_info)\r
{\r
- int ret = -1;\r
- struct clk_node *dvfs_info=clk_get_dvfs_info(clk);\r
- \r
- DVFS_DBG("%s(%s(%lu))\n", __func__, dvfs_info->name, rate);\r
-\r
- #if 0 // judge by reference func in rk\r
- if (dvfs_support_clk_set_rate(dvfs_info)==false) {\r
- DVFS_ERR("dvfs func:%s is not support!\n", __func__);\r
- return ret;\r
- }\r
- #endif\r
- \r
- if(dvfs_info->vd&&dvfs_info->vd->vd_dvfs_target){\r
- // mutex_lock(&vd->dvfs_mutex);\r
- mutex_lock(&rk_dvfs_mutex);\r
- ret = dvfs_info->vd->vd_dvfs_target(clk, rate);\r
- mutex_unlock(&rk_dvfs_mutex);\r
- // mutex_unlock(&vd->dvfs_mutex);\r
- }\r
- DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);\r
- return ret;\r
+ return (dvfs_info->vd && dvfs_info->vd->vd_dvfs_target && dvfs_info->enable_dvfs);\r
}\r
-EXPORT_SYMBOL(dvfs_vd_clk_set_rate);\r
\r
-int dvfs_vd_clk_disable(struct clk *clk, int on)\r
+int dvfs_set_rate(struct clk *clk, unsigned long rate)\r
{\r
- int ret = -1;\r
- struct clk_node *dvfs_info=clk_get_dvfs_info(clk); \r
- DVFS_DBG("%s(%s(%s,%lu))\n", __func__, dvfs_info->name, DVFS_STR_DISABLE(on),clk_get_rate(clk));\r
-\r
-\r
- #if 0 // judge by reference func in rk\r
- if (dvfs_support_clk_disable(dvfs_info)==false) {\r
- DVFS_ERR("dvfs func:%s is not support!\n", __func__);\r
- return ret;\r
- }\r
- #endif\r
- \r
- if(dvfs_info->vd&&dvfs_info->vd->vd_clk_disable_target){\r
+ int ret = 0;\r
+ struct vd_node *vd;\r
+ DVFS_DBG("%s(%s(%lu))\n", __func__, clk->name, rate);\r
+ if (!clk->dvfs_info) {\r
+ DVFS_ERR("%s :This clk do not support dvfs!\n", __func__);\r
+ ret = -1;\r
+ } else {\r
+ vd = clk->dvfs_info->vd;\r
// mutex_lock(&vd->dvfs_mutex);\r
mutex_lock(&rk_dvfs_mutex);\r
- ret = dvfs_info->vd->vd_clk_disable_target(clk, on);\r
+ ret = vd->vd_dvfs_target(clk, rate);\r
mutex_unlock(&rk_dvfs_mutex);\r
// mutex_unlock(&vd->dvfs_mutex);\r
}\r
- DVFS_DBG("%s(%s(%lu)),is end\n", __func__, dvfs_info->name, DVFS_STR_ON(on));\r
-\r
- return ret;\r
-}\r
-\r
-EXPORT_SYMBOL(dvfs_vd_clk_disable);\r
-\r
-\r
-int dvfs_vd_clk_disable_target(struct clk *clk, int on)\r
-{\r
- struct clk_node *dvfs_clk;\r
- struct clk_disable_ctr *disable_ctr;\r
- int ret = 0;\r
- int i;\r
- if (!clk) {\r
- DVFS_ERR("%s is not a clk\n", __func__);\r
- return -1;\r
- }\r
- dvfs_clk = clk_get_dvfs_info(clk);\r
- if(!dvfs_clk)\r
- {\r
- DVFS_ERR("%s is not a dvfs\n", __func__);\r
- return -1;\r
- }\r
-\r
- DVFS_DBG("%s:clk=%s(%s),count=%d\n",__FUNCTION__,dvfs_clk->name,\r
- DVFS_STR_DISABLE,clk_used_count(clk));\r
- if(on)\r
- {\r
- // enable ,is usecount =0,this time will set volt\r
- if(clk_used_count(clk)!= 0)\r
- return clk_set_enable_locked(clk, on);\r
- }\r
- else\r
- {\r
- //disabe, is usecount =1,this time will set volt\r
- if(clk_used_count(clk)!= 1)\r
- return clk_set_enable_locked(clk, on);\r
- }\r
- if(!dvfs_clk->disable_ctr)\r
- return clk_set_enable_locked(clk, on);\r
- else\r
- disable_ctr=dvfs_clk->disable_ctr;\r
- if(on)\r
- { \r
- if(disable_ctr->delay&&disable_ctr->disable_work_fn)\r
- cancel_delayed_work(&disable_ctr->disable_work);\r
- if(disable_ctr->clk_disable_target)\r
- {\r
- for(i=0;i<2;i++)\r
- {\r
- ret = disable_ctr->clk_disable_target(clk, on);\r
- if(ret>=0)\r
- break;\r
- mdelay(1000);\r
- }\r
- }\r
- else\r
- ret=0;\r
- \r
- // volt resume fail, Muse set rate is mini\r
- if(ret<0)\r
- {\r
- clk_set_rate_locked(clk,dvfs_clk->min_rate);\r
- DVFS_WARNING("%s:clk=%s enable set volt fail,set min rate\n",__FUNCTION__,dvfs_clk->name);\r
- }\r
- }\r
-\r
- ret = clk_set_enable_locked(clk, on);\r
- if(ret < 0)\r
- return ret;\r
- if(!on)\r
- {\r
- if(disable_ctr->delay&&disable_ctr->disable_work_fn)\r
- {\r
- DVFS_DBG("%s:clk=%s disable delay=%d\n",__FUNCTION__,dvfs_clk->name,disable_ctr->delay);\r
- queue_delayed_work_on(0,dvfs_wq, &disable_ctr->disable_work, \r
- msecs_to_jiffies(disable_ctr->delay));\r
- }\r
- else\r
- {\r
- DVFS_DBG("%s:clk=%s disable now\n",__FUNCTION__,dvfs_clk->name);\r
- if(disable_ctr->clk_disable_target)\r
- ret=disable_ctr->clk_disable_target(clk, on);\r
- }\r
- }\r
+ DVFS_DBG("%s(%s(%lu)),is end\n", __func__, clk->name, rate);\r
return ret;\r
}\r
\r
-EXPORT_SYMBOL(dvfs_vd_clk_disable_target);\r
-\r
-void dvfs_clk_disable_delay_work(struct work_struct *work)\r
-{\r
- struct clk_disable_ctr *disable_ctr=container_of(work, struct clk_disable_ctr, disable_work.work);\r
- struct clk_node *dvfs_clk;\r
- if(!disable_ctr->dvfs_clk)\r
- return;\r
- dvfs_clk=disable_ctr->dvfs_clk;\r
- mutex_lock(&rk_dvfs_mutex);\r
- DVFS_DBG("%s:clk=%s disable delay work\n",__FUNCTION__,dvfs_clk->name);\r
- if(disable_ctr->clk_disable_target&&(!clk_used_count(dvfs_clk->clk)))\r
- disable_ctr->clk_disable_target(dvfs_clk->clk,0);\r
- mutex_unlock(&rk_dvfs_mutex);\r
-}\r
-EXPORT_SYMBOL(dvfs_clk_disable_delay_work);\r
-\r
static void dvfs_table_round_clk_rate(struct clk_node *dvfs_clk)\r
{\r
int i;\r
struct pd_node *pd;\r
struct clk_list *child;\r
struct clk *clk;\r
- struct clk_disable_ctr *disable_ctr;\r
int i = 0;\r
\r
if (!dvfs_clk)\r
}\r
clk = dvfs_clk_get(NULL, dvfs_clk->name);\r
dvfs_clk->clk = clk;\r
- disable_ctr=dvfs_clk->disable_ctr;\r
- if(disable_ctr)\r
- {\r
- if(disable_ctr->clk_disable_target)\r
- {\r
- disable_ctr->dvfs_clk=dvfs_clk;\r
-\r
- if(disable_ctr->delay&&disable_ctr->disable_work_fn)\r
- {\r
- INIT_DELAYED_WORK(&disable_ctr->disable_work,disable_ctr->disable_work_fn); \r
- }\r
- }else\r
- dvfs_clk->disable_ctr=NULL;\r
- }\r
clk_register_dvfs(dvfs_clk, clk);\r
INIT_LIST_HEAD(&dvfs_clk->depend_list);\r
mutex_unlock(&mutex);\r
return ret;\r
}\r
}\r
- dvfs_wq = create_singlethread_workqueue("rk dvfs wq");\r
\r
return ret;\r
}\r
int clk_set_parent_nolock(struct clk *clk, struct clk *parent);
int clk_set_rate_locked(struct clk * clk,unsigned long rate);
void clk_register_dvfs(struct clk_node *dvfs_clk, struct clk *clk);
+struct clk_node *clk_get_dvfs_info(struct clk *clk);
int is_suport_round_rate(struct clk *clk);
-int clk_set_enable_locked(struct clk * clk,int on);
-/************************inline fun*****************************/
-static inline struct clk_node *clk_get_dvfs_info(struct clk *clk)
-{
- return clk->dvfs_info;
-}
-static inline s16 clk_used_count(struct clk * clk)
-{
- return (clk->usecount);
-}
#ifdef RK30_CLK_OFFBOARD_TEST
#include <linux/device.h>
typedef int (*clk_dvfs_target_callback)(struct clk *clk, unsigned long rate,\r
dvfs_set_rate_callback set_rate);\r
\r
-typedef int (*dvfs_vd_clk_disable_callback)(struct clk *clk,int on);\r
-\r
-typedef void (*dvfs_clk_disable_work_callback)(struct work_struct *work);\r
/**\r
* struct vd_node: To Store All Voltage Domains' info\r
* @name: Voltage Domain's Name\r
struct list_head pd_list;\r
struct list_head req_volt_list;\r
//struct mutex dvfs_mutex;\r
- dvfs_vd_clk_disable_callback vd_clk_disable_target;\r
vd_dvfs_target_callback vd_dvfs_target;\r
unsigned n_voltages;\r
int volt_list[VD_VOL_LIST_CNT];\r
struct cpufreq_frequency_table *dep_table;\r
};\r
\r
-struct clk_disable_ctr {\r
- struct delayed_work disable_work;\r
- dvfs_clk_disable_work_callback disable_work_fn;\r
- dvfs_vd_clk_disable_callback clk_disable_target;\r
- unsigned int delay;//ms\r
- struct clk_node *dvfs_clk;\r
-};\r
/**\r
* struct clk_node: To Store All dvfs clocks' info\r
* @name: Dvfs clock's Name\r
struct notifier_block *dvfs_nb;\r
struct cpufreq_frequency_table *dvfs_table;\r
clk_dvfs_target_callback clk_dvfs_target;\r
- struct clk_disable_ctr *disable_ctr;\r
};\r
\r
struct dvfs_arm_table {\r
#define dvfs_clk_get(a,b) clk_get((a),(b))\r
#define dvfs_clk_get_rate_kz(a) (clk_get_rate((a))/1000)\r
#define dvfs_clk_set_rate(a,b) clk_set_rate((a),(b))\r
+#define dvfs_clk_enable(a) clk_enable((a))\r
+#define dvfs_clk_disable(a) clk_disable((a))\r
\r
\r
\r
int rk_regist_depends(struct depend_lookup *dep_node);\r
struct clk_node *dvfs_get_dvfs_clk_byname(char *name);\r
int vd_regulator_round_volt(struct vd_node *vd, int volt,int flags);\r
-int dvfs_vd_clk_disable_target(struct clk *clk, int on);\r
-void dvfs_clk_disable_delay_work(struct work_struct *work);\r
\r
-/*********************************if not define dvfs ,the following function is need defined func{}******************************/\r
-int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate);\r
-int dvfs_vd_clk_disable(struct clk *clk, int on);\r
+/******************************************************************************/\r
+\r
+int is_support_dvfs(struct clk_node *dvfs_info);\r
+int dvfs_set_rate(struct clk *clk, unsigned long rate);\r
int clk_enable_dvfs(struct clk *clk);\r
int clk_disable_dvfs(struct clk *clk);\r
void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target);\r
int dvfs_clk_enable_limit(struct clk *clk, unsigned int min_rate, unsigned max_rate);\r
int dvfs_clk_disable_limit(struct clk *clk);\r
int dvfs_scale_volt_direct(struct vd_node *vd_clk, int volt_new);\r
-/******************************** inline *******************************/\r
-static inline bool dvfs_support_clk_set_rate(struct clk_node *dvfs_info)\r
-{\r
- return (dvfs_info&&dvfs_info->enable_dvfs);\r
-}\r
-static inline bool dvfs_support_clk_disable(struct clk_node *dvfs_info)\r
-{\r
- return (dvfs_info&&dvfs_info->disable_ctr&&dvfs_info->enable_dvfs);\r
-}\r
-/********************************avs*******************************/\r
+\r
void avs_init(void);\r
void avs_init_val_get(int index,int vol,char *s);\r
int avs_set_scal_val(u8 avs_base);\r
void avs_board_init(struct avs_ctr_st *data);\r
\r
#else\r
-static inline bool dvfs_support_clk_set_rate(struct clk_node *dvfs_info) { return 0; }\r
-static inline bool dvfs_support_clk_disable(struct clk_node *dvfs_info) { return 0; }\r
-\r
-static inline int dvfs_vd_clk_set_rate(struct clk *clk, unsigned long rate) { return 0; }\r
-static inline int dvfs_vd_clk_disable(struct clk *clk, int on) { return 0; }\r
+static inline int is_support_dvfs(struct clk_node *dvfs_info) { return 0; }\r
+static inline int dvfs_set_rate(struct clk *clk, unsigned long rate) { return 0; }\r
static inline int clk_enable_dvfs(struct clk *clk) { return 0; }\r
static inline int clk_disable_dvfs(struct clk *clk) { return 0; }\r
static inline void dvfs_clk_register_set_rate_callback(struct clk *clk, clk_dvfs_target_callback clk_dvfs_target) {}\r