/* linux/include/soc/samsung/exynos-dm.h * * Copyright (C) 2016 Samsung Electronics Co., Ltd. * http://www.samsung.com * * EXYNOS5 - Header file for exynos DVFS Manager support * * 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_DM_H #define __EXYNOS_DM_H #include #include #include #include #define EXYNOS_DM_MODULE_NAME "exynos-dm" #define EXYNOS_DM_TYPE_NAME_LEN 16 #define EXYNOS_DM_ATTR_NAME_LEN (EXYNOS_DM_TYPE_NAME_LEN + 12) #define EXYNOS_DM_RELATION_L 0 #define EXYNOS_DM_RELATION_H 1 enum exynos_dm_type { DM_CPU_CL0 = 0, DM_CPU_CL1, DM_CPU_CL2, DM_MIF, DM_INT, DM_NPU, DM_DSU, DM_DISP, DM_AUD, DM_GPU, DM_INTCAM, DM_CAM, DM_CSIS, DM_VPC, DM_MFC, DM_ISP, DM_MFC1, DM_TYPE_END }; enum exynos_constraint_type { CONSTRAINT_MIN = 0, CONSTRAINT_MAX, CONSTRAINT_END }; enum dvfs_direction { DOWN = 0, UP, DIRECTION_END }; struct exynos_dm_freq { u32 master_freq; u32 slave_freq; }; struct exynos_dm_attrs { struct device_attribute attr; char name[EXYNOS_DM_ATTR_NAME_LEN]; }; struct exynos_dm_constraint { int dm_master; int dm_slave; struct list_head master_domain; struct list_head slave_domain; bool guidance; /* check constraint table by hw guide */ bool support_dynamic_disable; u32 table_length; enum exynos_constraint_type constraint_type; char dm_type_name[EXYNOS_DM_TYPE_NAME_LEN]; struct exynos_dm_freq *freq_table; struct exynos_dm_freq *variable_freq_table[2]; bool support_variable_freq_table; u32 const_freq; u32 gov_freq; struct exynos_dm_constraint *sub_constraint; }; struct exynos_dm_data { bool available; /* use for DVFS domain available */ #if defined(CONFIG_EXYNOS_ACPM) || defined(CONFIG_EXYNOS_ACPM_MODULE) bool policy_use; #endif int dm_type; char dm_type_name[EXYNOS_DM_TYPE_NAME_LEN]; int my_order; // Scaling order in domain_order int indegree; // Number of min masters u32 cur_freq; // Current frequency u32 next_target_freq; // Next target frequency determined by current status u32 governor_freq; // Frequency determined by DVFS governor u32 gov_min; // Constraint by current frequency of min master domains u32 policy_min; // Min frequency limition in this domin u32 policy_max; // Min frequency limition in this domin u32 const_min; // Constraint by min frequency of min master domains u32 const_max; // Constraint1 by max frequency of max master domains /* For Fast Switch */ bool fast_switch; // Use Fast Switch bool fast_switch_post_in_progress; struct irq_work fast_switch_post_irq_work; struct task_struct *fast_switch_post_worker; struct mutex fast_switch_lock; int (*freq_scaler)(int dm_type, void *devdata, u32 target_freq, unsigned int relation); struct list_head min_slaves; struct list_head max_slaves; struct list_head min_masters; struct list_head max_masters; #if defined(CONFIG_EXYNOS_ACPM) || defined(CONFIG_EXYNOS_ACPM_MODULE) u32 cal_id; #endif void *devdata; struct exynos_dm_attrs dm_policy_attr; struct exynos_dm_attrs constraint_table_attr; }; struct exynos_dm_device { struct device *dev; struct mutex lock; int domain_count; int constraint_domain_count; int *domain_order; struct exynos_dm_data *dm_data; int dynamic_disable; unsigned int fast_switch_ch; }; struct exynos_dm_fast_switch_notify_data { u32 domain; u32 freq; ktime_t time; }; /* External Function call */ #if defined(CONFIG_EXYNOS_DVFS_MANAGER) || defined(CONFIG_EXYNOS_DVFS_MANAGER_MODULE) extern int exynos_dm_data_init(int dm_type, void *data, u32 min_freq, u32 max_freq, u32 cur_freq); extern int register_exynos_dm_constraint_table(int dm_type, struct exynos_dm_constraint *constraint); extern int unregister_exynos_dm_constraint_table(int dm_type, struct exynos_dm_constraint *constraint); extern int register_exynos_dm_freq_scaler(int dm_type, int (*scaler_func)(int dm_type, void *devdata, u32 target_freq, unsigned int relation)); extern int unregister_exynos_dm_freq_scaler(int dm_type); extern int policy_update_call_to_DM(int dm_type, u32 min_freq, u32 max_freq); extern int DM_CALL(int dm_type, unsigned long *target_freq); extern void exynos_dm_dynamic_disable(int flag); extern int exynos_dm_fast_switch_notifier_register(struct notifier_block *n); extern int exynos_dm_change_freq_table(struct exynos_dm_constraint *constraint, int idx); #else static inline int exynos_dm_data_init(int dm_type, void *data, u32 min_freq, u32 max_freq, u32 cur_freq) { return -ENODEV; } static inline int register_exynos_dm_constraint_table(int dm_type, struct exynos_dm_constraint *constraint) { return -ENODEV; } static inline int unregister_exynos_dm_constraint_table(int dm_type, struct exynos_dm_constraint *constraint) { return -ENODEV; } static inline int register_exynos_dm_freq_scaler(int dm_type, int (*scaler_func)(int dm_type, void *devdata, u32 target_freq, unsigned int relation)) { return -ENODEV; } static inline int unregister_exynos_dm_freq_scaler(int dm_type) { return -ENODEV; } static inline int policy_update_call_to_DM(int dm_type, u32 min_freq, u32 max_freq) { return -ENODEV; } static inline int DM_CALL(int dm_type, unsigned long *target_freq) { return -ENODEV; } static inline void exynos_dm_dynamic_disable(int flag) { return; } static inline int exynos_dm_fast_switch_notifier_register(struct notifier_block *n) { return 0; } static inline int exynos_dm_change_freq_table(struct exynos_dm_constraint *constraint, int idx) { return -ENODEV; } #endif #endif /* __EXYNOS_DM_H */