On Wed, Apr 17, 2024 at 10:02:54PM +0200, Konrad Dybcio wrote: > Recent (SM8550+ ish) Qualcomm SoCs have a new mechanism for precisely > identifying the specific SKU and the precise speed bin (in the general > meaning of this word, anyway): a pair of values called Product Code > and Feature Code. > > Based on this information, we can deduce the available frequencies for > things such as Adreno. In the case of Adreno specifically, Pcode is > useless for non-prototype SoCs. > > Introduce a getter for the feature code and export it. > > Signed-off-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxx> > --- > drivers/soc/qcom/smem.c | 33 +++++++++++++++++++++++++++++++++ > include/linux/soc/qcom/smem.h | 1 + > include/linux/soc/qcom/socinfo.h | 26 ++++++++++++++++++++++++++ > 3 files changed, 60 insertions(+) > > diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c > index 7191fa0c087f..29e708789eec 100644 > --- a/drivers/soc/qcom/smem.c > +++ b/drivers/soc/qcom/smem.c > @@ -795,6 +795,39 @@ int qcom_smem_get_soc_id(u32 *id) > } > EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); > > +/** > + * qcom_smem_get_feature_code() - return the feature code > + * @code: On success, return the feature code here. > + * > + * Look up the feature code identifier from SMEM and return it. > + * > + * Return: 0 on success, negative errno on failure. > + */ > +int qcom_smem_get_feature_code(u32 *code) > +{ > + struct socinfo *info; > + u32 raw_code; > + > + info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); > + if (IS_ERR(info)) > + return PTR_ERR(info); > + > + /* This only makes sense for socinfo >= 16 */ > + if (__le32_to_cpu(info->fmt) < SOCINFO_VERSION(0, 16)) > + return -EOPNOTSUPP; > + > + raw_code = __le32_to_cpu(info->feature_code); > + > + /* Ensure the value makes sense */ > + if (raw_code >= SOCINFO_FC_INT_MAX) > + raw_code = SOCINFO_FC_UNKNOWN; > + > + *code = raw_code; > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_smem_get_feature_code); > + > static int qcom_smem_get_sbl_version(struct qcom_smem *smem) > { > struct smem_header *header; > diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h > index a36a3b9d4929..0943bf419e11 100644 > --- a/include/linux/soc/qcom/smem.h > +++ b/include/linux/soc/qcom/smem.h > @@ -13,5 +13,6 @@ int qcom_smem_get_free_space(unsigned host); > phys_addr_t qcom_smem_virt_to_phys(void *p); > > int qcom_smem_get_soc_id(u32 *id); > +int qcom_smem_get_feature_code(u32 *code); > > #endif > diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h > index 10e0a4c287f4..52439f48428f 100644 > --- a/include/linux/soc/qcom/socinfo.h > +++ b/include/linux/soc/qcom/socinfo.h > @@ -3,6 +3,8 @@ > #ifndef __QCOM_SOCINFO_H__ > #define __QCOM_SOCINFO_H__ > > +#include <linux/types.h> > + > /* > * SMEM item id, used to acquire handles to respective > * SMEM region. > @@ -82,4 +84,28 @@ struct socinfo { > __le32 boot_core; > }; > > +/* Internal feature codes */ > +enum qcom_socinfo_feature_code { > + /* External feature codes */ > + SOCINFO_FC_UNKNOWN = 0x0, > + SOCINFO_FC_AA, > + SOCINFO_FC_AB, > + SOCINFO_FC_AC, > + SOCINFO_FC_AD, > + SOCINFO_FC_AE, > + SOCINFO_FC_AF, > + SOCINFO_FC_AG, > + SOCINFO_FC_AH, > +}; > + > +/* Internal feature codes */ > +/* Valid values: 0 <= n <= 0xf */ > +#define SOCINFO_FC_Yn(n) (0xf1 + n) > +#define SOCINFO_FC_INT_MAX SOCINFO_FC_Yn(0x10) This is 0x101 rather than 0x100 or 0xff. Is that expected? > + > +/* Product codes */ > +#define SOCINFO_PC_UNKNOWN 0 > +#define SOCINFO_PCn(n) (n + 1) > +#define SOCINFO_PC_RESERVE (BIT(31) - 1) This patch works on fcodes, why do we have PCode defines here? > + > #endif > > -- > 2.44.0 > -- With best wishes Dmitry