308 lines
8.9 KiB
C
308 lines
8.9 KiB
C
/*
|
|
* Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
#ifndef __SOC_ROCKCHIP_OPP_SELECT_H
|
|
#define __SOC_ROCKCHIP_OPP_SELECT_H
|
|
|
|
#include <linux/pm_opp.h>
|
|
|
|
#define VOLT_RM_TABLE_END ~1
|
|
|
|
/*
|
|
* [0]: set intermediate rate
|
|
* [1]: scaling up rate or scaling down rate
|
|
* [1]: add length for pvtpll
|
|
* [2:5]: length
|
|
* [2]: use low length for pvtpll
|
|
* [3:5]: reserved
|
|
*/
|
|
#define OPP_RATE_MASK 0x3f
|
|
|
|
/* Set intermediate rate */
|
|
#define OPP_INTERMEDIATE_RATE BIT(0)
|
|
#define OPP_SCALING_UP_RATE BIT(1)
|
|
#define OPP_SCALING_UP_INTER (OPP_INTERMEDIATE_RATE | OPP_SCALING_UP_RATE)
|
|
#define OPP_SCALING_DOWN_INTER OPP_INTERMEDIATE_RATE
|
|
|
|
/* Add length for pvtpll */
|
|
#define OPP_ADD_LENGTH BIT(1)
|
|
#define OPP_LENGTH_MASK 0xf
|
|
#define OPP_LENGTH_SHIFT 2
|
|
|
|
/* Use low length for pvtpll */
|
|
#define OPP_LENGTH_LOW BIT(2)
|
|
|
|
struct rockchip_opp_info;
|
|
|
|
struct volt_rm_table {
|
|
int volt;
|
|
int rm;
|
|
};
|
|
|
|
struct rockchip_opp_data {
|
|
config_clks_t config_clks;
|
|
config_regulators_t config_regulators;
|
|
|
|
int (*get_soc_info)(struct device *dev, struct device_node *np,
|
|
int *bin, int *process);
|
|
int (*set_soc_info)(struct device *dev, struct device_node *np,
|
|
struct rockchip_opp_info *info);
|
|
int (*set_read_margin)(struct device *dev,
|
|
struct rockchip_opp_info *info,
|
|
u32 rm);
|
|
};
|
|
|
|
struct pvtpll_opp_table {
|
|
unsigned long rate;
|
|
unsigned long u_volt;
|
|
unsigned long u_volt_min;
|
|
unsigned long u_volt_max;
|
|
unsigned long u_volt_mem;
|
|
unsigned long u_volt_mem_min;
|
|
unsigned long u_volt_mem_max;
|
|
};
|
|
|
|
/**
|
|
* struct rockchip_opp_info - Rockchip opp info structure
|
|
* @dev: The device.
|
|
* @dvfs_mutex: Mutex to protect changing volage and scmi clock rate.
|
|
* @data: Device-specific opp data.
|
|
* @opp_table: Temporary opp table only used when enable pvtpll calibration.
|
|
* @pvtpll_avg_offset: Register offset of pvtm value.
|
|
* @pvtpll_min_rate: Minimum frequency which needs calibration.
|
|
* @pvtpll_volt_step: Voltage step of pvtpll calibration.
|
|
* @volt_rm_tbl: Pointer to voltage to memory read margin conversion table.
|
|
* @grf: General Register Files regmap.
|
|
* @dsu_grf: DSU General Register Files regmap.
|
|
* @cci_grf: CCI General Register Files regmap.
|
|
* @clocks: Pvtpll clocks.
|
|
* @nclocks: Number of pvtpll clock.
|
|
* @intermediate_threshold_freq: The frequency threshold of intermediate rate.
|
|
* @low_rm: The read margin threshold of intermediate rate.
|
|
* @current_rm: Current memory read margin.
|
|
* @target_rm: Target memory read margin.
|
|
* @is_runtime_active: Marks if device's pd is power on.
|
|
* @opp_token: Integer replacement for opp_table.
|
|
* @scale: Frequency scale.
|
|
* @bin: Soc version.
|
|
* @process: Process version.
|
|
* @volt_sel: Speed grade.
|
|
* @supported_hw: Array of version number to support.
|
|
* @clk: Device's clock handle.
|
|
* @is_scmi_clk: Marks if device's clock is scmi clock.
|
|
* @regulators: Supply regulators.
|
|
* @regulator_count: Number of power supply regulators.
|
|
* @init_freq: Set the initial frequency when init opp table.
|
|
* @is_rate_volt_checked: Marks if device has checked initial rate and voltage.
|
|
* @pvtpll_clk_id: Device's clock id.
|
|
* @pvtpll_smc: Marks if smc call of pvtpll is available.
|
|
* @pvtpll_low_temp: Marks if device has low temperature pvtpll config.
|
|
*/
|
|
struct rockchip_opp_info {
|
|
struct device *dev;
|
|
struct mutex dvfs_mutex;
|
|
const struct rockchip_opp_data *data;
|
|
struct pvtpll_opp_table *opp_table;
|
|
struct regmap *pvtpll_base;
|
|
unsigned int pvtpll_avg_offset;
|
|
unsigned int pvtpll_min_rate;
|
|
unsigned int pvtpll_volt_step;
|
|
|
|
struct volt_rm_table *volt_rm_tbl;
|
|
struct regmap *grf;
|
|
union {
|
|
struct regmap *dsu_grf;
|
|
struct regmap *cci_grf;
|
|
};
|
|
struct clk_bulk_data *clocks;
|
|
int nclocks;
|
|
unsigned long intermediate_threshold_freq;
|
|
u32 low_rm;
|
|
u32 current_rm;
|
|
u32 target_rm;
|
|
bool is_runtime_active;
|
|
|
|
int opp_token;
|
|
int scale;
|
|
int bin;
|
|
int process;
|
|
int volt_sel;
|
|
u32 supported_hw[2];
|
|
|
|
struct clk *clk;
|
|
bool is_scmi_clk;
|
|
struct regulator **regulators;
|
|
int regulator_count;
|
|
unsigned int init_freq;
|
|
bool is_rate_volt_checked;
|
|
|
|
u32 pvtpll_clk_id;
|
|
bool pvtpll_smc;
|
|
bool pvtpll_low_temp;
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_ROCKCHIP_OPP)
|
|
int rockchip_of_get_leakage(struct device *dev, char *lkg_name, int *leakage);
|
|
int rockchip_nvmem_cell_read_u8(struct device_node *np, const char *cell_id,
|
|
u8 *val);
|
|
int rockchip_nvmem_cell_read_u16(struct device_node *np, const char *cell_id,
|
|
u16 *val);
|
|
void rockchip_get_opp_data(const struct of_device_id *matches,
|
|
struct rockchip_opp_info *info);
|
|
void rockchip_opp_dvfs_lock(struct rockchip_opp_info *info);
|
|
void rockchip_opp_dvfs_unlock(struct rockchip_opp_info *info);
|
|
int rockchip_init_opp_info(struct device *dev, struct rockchip_opp_info *info,
|
|
char *clk_name, char *reg_name);
|
|
void rockchip_uninit_opp_info(struct device *dev, struct rockchip_opp_info *info);
|
|
int rockchip_adjust_opp_table(struct device *dev, struct rockchip_opp_info *info);
|
|
int rockchip_get_read_margin(struct device *dev,
|
|
struct rockchip_opp_info *info,
|
|
unsigned long volt, u32 *target_rm);
|
|
int rockchip_set_read_margin(struct device *dev,
|
|
struct rockchip_opp_info *info, u32 rm,
|
|
bool is_set_rm);
|
|
int rockchip_set_intermediate_rate(struct device *dev,
|
|
struct rockchip_opp_info *info,
|
|
struct clk *clk, unsigned long old_freq,
|
|
unsigned long new_freq, bool is_scaling_up,
|
|
bool is_set_clk);
|
|
int rockchip_opp_set_low_length(struct device *dev, struct device_node *np,
|
|
struct rockchip_opp_info *opp_info);
|
|
int rockchip_opp_config_regulators(struct device *dev,
|
|
struct dev_pm_opp *old_opp,
|
|
struct dev_pm_opp *new_opp,
|
|
struct regulator **regulators,
|
|
unsigned int count,
|
|
struct rockchip_opp_info *info);
|
|
int rockchip_opp_config_clks(struct device *dev, struct opp_table *opp_table,
|
|
struct dev_pm_opp *opp, void *data,
|
|
bool scaling_down, struct rockchip_opp_info *info);
|
|
int rockchip_opp_check_rate_volt(struct device *dev, struct rockchip_opp_info *info);
|
|
int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
|
|
char *clk_name, char *reg_name);
|
|
void rockchip_uninit_opp_table(struct device *dev,
|
|
struct rockchip_opp_info *info);
|
|
#else
|
|
static inline int rockchip_of_get_leakage(struct device *dev, char *lkg_name,
|
|
int *leakage)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int rockchip_nvmem_cell_read_u8(struct device_node *np,
|
|
const char *cell_id, u8 *val)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int rockchip_nvmem_cell_read_u16(struct device_node *np,
|
|
const char *cell_id, u16 *val)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void rockchip_get_opp_data(const struct of_device_id *matches,
|
|
struct rockchip_opp_info *info)
|
|
{
|
|
}
|
|
|
|
static inline void rockchip_opp_dvfs_lock(struct rockchip_opp_info *info)
|
|
{
|
|
}
|
|
|
|
static inline void rockchip_opp_dvfs_unlock(struct rockchip_opp_info *info)
|
|
{
|
|
}
|
|
|
|
static inline int
|
|
rockchip_init_opp_info(struct device *dev, struct rockchip_opp_info *info,
|
|
char *clk_name, char *reg_name)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void
|
|
rockchip_uninit_opp_info(struct device *dev, struct rockchip_opp_info *info)
|
|
{
|
|
}
|
|
|
|
static inline int
|
|
rockchip_adjust_opp_table(struct device *dev, struct rockchip_opp_info *info)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int rockchip_get_read_margin(struct device *dev,
|
|
struct rockchip_opp_info *info,
|
|
unsigned long volt, u32 *target_rm)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
static inline int rockchip_set_read_margin(struct device *dev,
|
|
struct rockchip_opp_info *info,
|
|
u32 rm, bool is_set_rm)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int
|
|
rockchip_set_intermediate_rate(struct device *dev,
|
|
struct rockchip_opp_info *opp_info,
|
|
struct clk *clk, unsigned long old_freq,
|
|
unsigned long new_freq, bool is_scaling_up,
|
|
bool is_set_clk)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int
|
|
rockchip_opp_set_low_length(struct device *dev, struct device_node *np,
|
|
struct rockchip_opp_info *opp_info)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int
|
|
rockchip_opp_config_regulators(struct device *dev,
|
|
struct dev_pm_opp *old_opp,
|
|
struct dev_pm_opp *new_opp,
|
|
struct regulator **regulators,
|
|
unsigned int count,
|
|
struct rockchip_opp_info *info)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int rockchip_opp_config_clks(struct device *dev,
|
|
struct opp_table *opp_table,
|
|
struct dev_pm_opp *opp, void *data,
|
|
bool scaling_down,
|
|
struct rockchip_opp_info *info)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int rockchip_opp_check_rate_volt(struct device *dev,
|
|
struct rockchip_opp_info *info)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int
|
|
rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
|
|
char *clk_name, char *reg_name)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void rockchip_uninit_opp_table(struct device *dev,
|
|
struct rockchip_opp_info *info)
|
|
{
|
|
}
|
|
|
|
#endif /* CONFIG_ROCKCHIP_OPP */
|
|
|
|
#endif
|