On Mon, Mar 13, 2023 at 06:10:39PM +0530, Komal Bajaj wrote: > Add LLCC support for multi channel DDR configurations > based off of a feature register. > Please elaborate more in the commit message on why this patch is needed and how it is implemented. > Signed-off-by: Komal Bajaj <quic_kbajaj@xxxxxxxxxxx> > --- > drivers/soc/qcom/llcc-qcom.c | 56 ++++++++++++++++++++++++++++-- > include/linux/soc/qcom/llcc-qcom.h | 2 ++ > 2 files changed, 55 insertions(+), 3 deletions(-) > > diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c > index 00699a0c047e..f4d3e266c629 100644 > --- a/drivers/soc/qcom/llcc-qcom.c > +++ b/drivers/soc/qcom/llcc-qcom.c > @@ -17,6 +17,7 @@ > #include <linux/regmap.h> > #include <linux/sizes.h> > #include <linux/slab.h> > +#include <linux/firmware/qcom/qcom_scm.h> Sort the includes alphabetically > #include <linux/soc/qcom/llcc-qcom.h> > > #define ACTIVATE BIT(0) > @@ -924,6 +925,40 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev, > return ret; > } > > +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u32 *cfg_index) > +{ > + struct device *dev = &pdev->dev; > + struct resource *ch_res = NULL; No need to initialize the pointer > + No need of a newline > + u32 ch_reg_sz; > + u32 ch_reg_off; > + u32 val; > + int ret = 0; > + > + ch_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "multi_channel_register"); > + if (ch_res) { > + if (of_property_read_u32(dev->of_node, "multi-ch-bit-off", &ch_reg_off)) { > + dev_err(&pdev->dev, > + "Couldn't get offset for multi channel feature register\n"); > + return -ENODEV; > + } > + if (of_property_read_u32_index(dev->of_node, "multi-ch-bit-off", 1, &ch_reg_sz)) { > + dev_err(&pdev->dev, > + "Couldn't get size of multi channel feature register\n"); > + return -ENODEV; > + } > + > + if (qcom_scm_io_readl(ch_res->start, &val)) { You didn't mention this SCM call in the commit message. Also, for SCM, you need to select the driver in Kconfig. > + dev_err(&pdev->dev, "Couldn't access multi channel feature register\n"); > + ret = -EINVAL; Catch the actual error no from qcom_scm_io_readl(). So in the case of failure, you still want to calculate cfg_index? > + } > + *cfg_index = (val >> ch_reg_off) & ((1 << ch_reg_sz) - 1); > + } else Use braces for else condition > + *cfg_index = 0; > + > + return ret; > +} > + > static int qcom_llcc_remove(struct platform_device *pdev) > { > /* Set the global pointer to a error code to avoid referencing it */ > @@ -956,10 +991,13 @@ static int qcom_llcc_probe(struct platform_device *pdev) > struct device *dev = &pdev->dev; > int ret, i; > struct platform_device *llcc_edac; > - const struct qcom_llcc_config *cfg; > + const struct qcom_llcc_config *cfg, *entry; > const struct llcc_slice_config *llcc_cfg; > + No need of newline > u32 sz; > + u32 cfg_index; > u32 version; > + u32 no_of_entries = 0; num_entries? > > drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); > if (!drv_data) { > @@ -999,8 +1037,20 @@ static int qcom_llcc_probe(struct platform_device *pdev) > num_banks >>= LLCC_LB_CNT_SHIFT; > drv_data->num_banks = num_banks; > > - llcc_cfg = cfg[0].sct_data; > - sz = cfg[0].size; > + ret = qcom_llcc_get_cfg_index(pdev, &cfg_index); > + if (ret) > + goto err; > + > + for (entry = cfg; entry->sct_data; entry++, no_of_entries++) > + ; Wrap ; in the above line itself > + if (cfg_index >= no_of_entries) { > + ret = -EINVAL; > + goto err; > + } > + > + drv_data->cfg_index = cfg_index; Where is this cached value used? Thanks, Mani > + llcc_cfg = cfg[cfg_index].sct_data; > + sz = cfg[cfg_index].size; > > for (i = 0; i < sz; i++) > if (llcc_cfg[i].slice_id > drv_data->max_slices) > diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h > index ad1fd718169d..225891a02f5d 100644 > --- a/include/linux/soc/qcom/llcc-qcom.h > +++ b/include/linux/soc/qcom/llcc-qcom.h > @@ -125,6 +125,7 @@ struct llcc_edac_reg_offset { > * @cfg: pointer to the data structure for slice configuration > * @edac_reg_offset: Offset of the LLCC EDAC registers > * @lock: mutex associated with each slice > + * @cfg_index: index of config table if multiple configs present for a target > * @cfg_size: size of the config data table > * @max_slices: max slices as read from device tree > * @num_banks: Number of llcc banks > @@ -139,6 +140,7 @@ struct llcc_drv_data { > const struct llcc_slice_config *cfg; > const struct llcc_edac_reg_offset *edac_reg_offset; > struct mutex lock; > + u32 cfg_index; > u32 cfg_size; > u32 max_slices; > u32 num_banks; > -- > 2.39.1 > -- மணிவண்ணன் சதாசிவம்