diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 40d1ec6dc0c0..9882311df2b2 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1294,6 +1294,41 @@ int rockchip_get_volt_rm_table(struct device *dev, struct device_node *np, } EXPORT_SYMBOL(rockchip_get_volt_rm_table); +int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin, + int *process) +{ + u8 value = 0; + int ret = 0; + + if (*bin >= 0 || *process >= 0) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, + "specification_serial_number", + &value); + if (ret) { + dev_err(dev, + "Failed to get specification_serial_number\n"); + return ret; + } + /* M */ + if (value == 0xd) + *bin = 1; + /* J */ + else if (value == 0xa) + *bin = 2; + } + + if (*bin < 0) + *bin = 0; + dev_info(dev, "bin=%d\n", *bin); + + return 0; +} +EXPORT_SYMBOL(rockchip_get_soc_info); + void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, char *reg_name, int bin, int process, int *scale, int *volt_sel) @@ -1349,6 +1384,42 @@ struct opp_table *rockchip_set_opp_prop_name(struct device *dev, int process, } EXPORT_SYMBOL(rockchip_set_opp_prop_name); +struct opp_table *rockchip_set_opp_supported_hw(struct device *dev, + struct device_node *np, + int bin, int volt_sel) +{ + struct opp_table *opp_table; + u32 supported_hw[2]; + u32 version = 0, speed = 0; + + if (!of_property_read_bool(np, "rockchip,supported-hw")) + return NULL; + + opp_table = dev_pm_opp_get_opp_table(dev); + if (!opp_table) + return NULL; + if (opp_table->supported_hw) { + dev_pm_opp_put_opp_table(opp_table); + return NULL; + } + dev_pm_opp_put_opp_table(opp_table); + + if (bin >= 0) + version = bin; + if (volt_sel >= 0) + speed = volt_sel; + + /* SoC Version */ + supported_hw[0] = BIT(version); + /* Speed Grade */ + supported_hw[1] = BIT(speed); + + dev_info(dev, "soc version=%d, speed=%d\n", version, speed); + + return dev_pm_opp_set_supported_hw(dev, supported_hw, 2); +} +EXPORT_SYMBOL(rockchip_set_opp_supported_hw); + static int rockchip_adjust_opp_by_irdrop(struct device *dev, struct device_node *np, unsigned long *safe_rate, @@ -1815,11 +1886,13 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, info->data->get_soc_info(dev, np, &bin, &process); next: + rockchip_get_soc_info(dev, np, &bin, &process); rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, &scale, &volt_sel); if (info && info->data && info->data->set_soc_info) info->data->set_soc_info(dev, np, bin, process, volt_sel); rockchip_set_opp_prop_name(dev, process, volt_sel); + rockchip_set_opp_supported_hw(dev, np, bin, volt_sel); ret = dev_pm_opp_of_add_table(dev); if (ret) { dev_err(dev, "Invalid operating-points in device tree.\n"); diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index 2277fbeac360..fe9ffb64b91d 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -102,11 +102,16 @@ int rockchip_get_volt_rm_table(struct device *dev, struct device_node *np, char *porp_name, struct volt_rm_table **table); void rockchip_get_opp_data(const struct of_device_id *matches, struct rockchip_opp_info *info); +int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin, + int *process); void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, char *reg_name, int bin, int process, int *scale, int *volt_sel); struct opp_table *rockchip_set_opp_prop_name(struct device *dev, int process, int volt_sel); +struct opp_table *rockchip_set_opp_supported_hw(struct device *dev, + struct device_node *np, + int bin, int volt_sel); int rockchip_adjust_power_scale(struct device *dev, int scale); int rockchip_get_read_margin(struct device *dev, struct rockchip_opp_info *opp_info, @@ -191,6 +196,12 @@ static inline void rockchip_get_opp_data(const struct of_device_id *matches, struct rockchip_opp_info *info) { } +static inline int rockchip_get_soc_info(struct device *dev, + struct device_node *np, int *bin, + int *process) +{ + return -EOPNOTSUPP; +} static inline void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, char *reg_name, @@ -206,6 +217,13 @@ static inline struct opp_table *rockchip_set_opp_prop_name(struct device *dev, return ERR_PTR(-EOPNOTSUPP); } +static inline struct opp_table *rockchip_set_opp_supported_hw(struct device *dev, + struct device_node *np, + int bin, int volt_sel) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline int rockchip_adjust_power_scale(struct device *dev, int scale) { return -EOPNOTSUPP;