blob: 03e41041da3fe262d2ba12bbe48233d4ffd2b358 [file] [log] [blame]
/* linux/arch/arm64/mach-exynos/include/mach/exynos-devfreq.h
*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __EXYNOS_DEVFREQ_H_
#define __EXYNOS_DEVFREQ_H_
#include <linux/devfreq.h>
#include <linux/pm_qos.h>
#include <linux/clk.h>
#include <soc/samsung/exynos-devfreq-dep.h>
#include <soc/samsung/exynos-dm.h>
#define EXYNOS_DEVFREQ_MODULE_NAME "exynos-devfreq"
#define VOLT_STEP 25000
#define MAX_NR_CONSTRAINT DM_TYPE_END
#define DATA_INIT 5
#define SET_CONST 1
#define RELEASE 2
enum exynos_devfreq_type {
DEVFREQ_MIF = 0,
DEVFREQ_INT,
DEVFREQ_DISP,
DEVFREQ_CAM,
DEVFREQ_INTCAM,
DEVFREQ_AUD,
DEVFREQ_FSYS,
DEVFREQ_TYPE_END
};
enum exynos_devfreq_gov_type {
SIMPLE_INTERACTIVE = 0,
GOV_TYPE_END
};
/* "Utlization Monitor" type */
enum UM_TYPE {
UM_MIF = 0,
UM_INT,
NONE_UM
};
enum volt_order_type {
KEEP_SET_VOLT = 0,
PRE_SET_VOLT,
POST_SET_VOLT
};
enum exynos_devfreq_lv_index {
DEV_LV0 = 0,
DEV_LV1,
DEV_LV2,
DEV_LV3,
DEV_LV4,
DEV_LV5,
DEV_LV6,
DEV_LV7,
DEV_LV8,
DEV_LV9,
DEV_LV10,
DEV_LV11,
DEV_LV12,
DEV_LV13,
DEV_LV14,
DEV_LV15,
DEV_LV16,
DEV_LV17,
DEV_LV18,
DEV_LV19,
DEV_LV20,
DEV_LV_END,
};
struct exynos_devfreq_opp_table {
u32 idx;
u32 freq;
u32 volt;
};
struct exynos_devfreq_data;
struct um_exynos;
struct exynos_devfreq_ops {
/* ops.init(struct exynos_devfreq_data *data) */
int (*init)(struct exynos_devfreq_data *);
/* ops.exit(struct exynos_devfreq_data *data) */
int (*exit)(struct exynos_devfreq_data *);
/* ops.init_freq_table(struct exynos_devfreq_data *data) */
int (*init_freq_table)(struct exynos_devfreq_data *);
/* ops.get_volt_table(struct device *dev, u32 max_state, struct exynos_devfreq_opp_table *opp_list) */
int (*get_volt_table)(struct device *, u32, struct exynos_devfreq_opp_table *);
/* ops.ppmu_register(struct exynos_devfreq_data *data) */
int (*um_register)(struct exynos_devfreq_data *);
/* ops.ppmu_unregister(struct exynos_devfreq_data *data) */
int (*um_unregister)(struct exynos_devfreq_data *);
/* ops.suspend(struct exynos_devfreq_data *data) */
int (*suspend)(struct exynos_devfreq_data *);
/* ops.resume(struct exynos_devfreq_data *data */
int (*resume)(struct exynos_devfreq_data *);
/* ops.reboot(struct exynos_devfreq_data *data */
int (*reboot)(struct exynos_devfreq_data *);
/* ops.get_switch_voltage(struct device *dev, u32 cur_freq, u32 new_freq, u32 cur_volt, u32 new_volt, u32 *switch_volt) */
int (*get_switch_voltage)(struct device *, u32, u32, u32, u32, u32 *);
/* ops.set_voltage_prepare(struct exynos_devfreq_data *data) */
void (*set_voltage_prepare)(struct exynos_devfreq_data *);
/* ops.set_voltage_post(struct exynos_devfreq_data *data) */
void (*set_voltage_post)(struct exynos_devfreq_data *);
/* ops.get_switch_freq(struct device *dev, u32 cur_freq, u32 new_freq, u32 *switch_freq) */
int (*get_switch_freq)(struct device *, u32, u32, u32 *);
/* ops.get_freq(struct device *dev, u32 *cur_freq, struct clk *clk) */
int (*get_freq)(struct device *, u32 *, struct clk *, struct exynos_devfreq_data *);
/* ops.set_freq(struct device *dev, u32 new_freq, struct clk *clk) */
int (*set_freq)(struct device *, u32, struct clk *, struct exynos_devfreq_data *);
/* ops.set_freq_prepare(struct exynos_devfreq_data *data) */
int (*set_freq_prepare)(struct exynos_devfreq_data *);
/* ops.set_freq_post(struct exynos_devfreq_data) */
int (*set_freq_post)(struct exynos_devfreq_data *);
/* ops.change_to_switch_freq(struct device *dev, void *private_data, struct clk *sw_clk, u32 switch_freq, u32 cur_freq, u32 new_freq) */
int (*change_to_switch_freq)(struct device *, void *, struct clk *, u32, u32, u32);
/* ops.restore_from_switch_freq(struct device *dev, void *priave_data, struct clk *clk, u32 cur_freq, u32 new_freq) */
int (*restore_from_switch_freq)(struct device *, void *, struct clk *, u32, u32);
/* ops.get_dev_status(struct exynos_devfreq_data *data) */
int (*get_dev_status)(struct exynos_devfreq_data *);
/* ops.cl_dvfs_start(struct device *dev) */
int (*cl_dvfs_start)(struct device *);
/* ops.cl_dvfs_stop(struct device *dev, u32 target_idx) */
int (*cl_dvfs_stop)(struct device *, u32);
/* ops.cmu_dump(struct exynos_devfreq_data *data) */
int (*cmu_dump)(struct exynos_devfreq_data *);
/* ops.pm_suspend_prepare(struct exynos_devfreq_data *data) */
int (*pm_suspend_prepare)(struct exynos_devfreq_data *);
/* ops.pm_post_suspend(struct exynos_devfreq_data *data) */
int (*pm_post_suspend)(struct exynos_devfreq_data *);
};
struct um_exynos {
struct list_head node;
void __iomem **va_base;
u32 *pa_base;
u32 *mask_v;
u32 *mask_a;
u32 *channel;
unsigned int um_count;
u64 val_ccnt;
u64 val_pmcnt;
};
struct exynos_devfreq_data {
struct device *dev;
struct devfreq *devfreq;
struct mutex lock;
struct clk *clk;
struct clk *sw_clk;
bool devfreq_disabled;
enum exynos_devfreq_type devfreq_type;
struct exynos_devfreq_opp_table opp_list[DEV_LV_END];
u32 default_qos;
bool use_get_dev;
u32 max_state;
struct devfreq_dev_profile devfreq_profile;
enum exynos_devfreq_gov_type gov_type;
const char *governor_name;
u32 cal_qos_max;
void *governor_data;
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_INTERACTIVE)
struct devfreq_simple_interactive_data simple_interactive_data;
#endif
u32 dfs_id;
s32 old_idx;
s32 new_idx;
u32 old_freq;
u32 new_freq;
u32 min_freq;
u32 max_freq;
u32 reboot_freq;
u32 boot_freq;
u32 old_volt;
u32 new_volt;
u32 volt_offset;
u32 cold_volt_offset;
u32 limit_cold_volt;
u32 min_cold_volt;
u32 reg_max_volt;
bool use_regulator;
bool use_pd_off;
const char *regulator_name;
struct regulator *vdd;
struct mutex regulator_lock;
u32 pm_qos_class;
u32 pm_qos_class_max;
struct pm_qos_request sys_pm_qos_min;
#ifdef CONFIG_ARM_EXYNOS_DEVFREQ_DEBUG
struct pm_qos_request debug_pm_qos_min;
struct pm_qos_request debug_pm_qos_max;
#endif
struct pm_qos_request default_pm_qos_min;
struct pm_qos_request default_pm_qos_max;
struct pm_qos_request boot_pm_qos;
u32 boot_qos_timeout;
struct devfreq_notifier_block *um_nb;
struct um_exynos um_data;
u64 last_monitor_period;
u64 last_monitor_time;
u32 last_um_usage_rate;
bool use_tmu;
struct notifier_block tmu_notifier;
struct notifier_block reboot_notifier;
struct notifier_block pm_notifier;
u32 ess_flag;
bool use_cl_dvfs;
s32 target_delay;
s32 setfreq_delay;
bool use_switch_clk;
u32 switch_freq;
u32 switch_volt;
#ifdef CONFIG_EXYNOS_DVFS_MANAGER
enum exynos_dm_type dm_type;
struct exynos_dm_constraint *constraint[MAX_NR_CONSTRAINT];
#endif
void *private_data;
struct exynos_devfreq_ops ops;
bool use_acpm;
};
int register_exynos_devfreq_init_prepare(enum exynos_devfreq_type type,
int (*func)(struct exynos_devfreq_data *));
s32 exynos_devfreq_get_opp_idx(struct exynos_devfreq_opp_table *table,
unsigned int size, u32 freq);
#if defined(CONFIG_ARM_EXYNOS_DEVFREQ)
int exynos_devfreq_sync_voltage(enum exynos_devfreq_type type, bool turn_on);
#if defined(CONFIG_EXYNOS_DVFS_MANAGER)
enum exynos_dm_type exynos_devfreq_get_dm_type(enum exynos_devfreq_type devfreq_type);
enum exynos_devfreq_type exynos_devfreq_get_devfreq_type(enum exynos_dm_type dm_type);
struct device *find_exynos_devfreq_device(enum exynos_dm_type dm_type);
int find_exynos_devfreq_dm_type(struct device *dev, enum exynos_dm_type *dm_type);
#endif
#else
static inline
int exynos_devfreq_sync_voltage(enum exynos_devfreq_type type, bool turn_on)
{
return 0;
}
#endif
#endif /* __EXYNOS_DEVFREQ_H_ */