From: Komal-Bajaj <[email protected]>
This patch series does the following -
* Add secure qfprom driver for reading secure fuse region in qfprom driver
* Add dt-bindings for secure qfprom
* Refactor LLCC driver to support multiple configuration
* Add support for multi channel DDR configuration in LLCC
* Add LLCC support for the Qualcomm QDU1000 and QRU1000 SoCs
Changes in v4 -
- Created a separate driver for reading from secure fuse region as suggested.
- Added patch for dt-bindings of secure qfprom driver accordingly.
- Added new properties in the dt-bindings for LLCC.
- Implemented new logic to read the nvmem cell as suggested by Bjorn.
- Separating the DT patches from this series as per suggestion.
Changes in v3-
- Addressed comments from Krzysztof and Mani.
- Using qfprom to read DDR configuration from feature register.
Changes in v2:
- Addressing comments from Konrad.
Komal Bajaj (6):
dt-bindings: nvmem: sec-qfprom: Add bindings for secure qfprom
dt-bindings: cache: qcom,llcc: Add LLCC compatible for QDU1000/QRU1000
nvmem: sec-qfprom: Add Qualcomm secure QFPROM support.
soc: qcom: llcc: Refactor llcc driver to support multiple
configuration
soc: qcom: Add LLCC support for multi channel DDR
soc: qcom: llcc: Add QDU1000 and QRU1000 LLCC support
.../devicetree/bindings/cache/qcom,llcc.yaml | 10 +
.../bindings/nvmem/qcom,sec-qfprom.yaml | 58 ++++
drivers/nvmem/Kconfig | 12 +
drivers/nvmem/Makefile | 2 +
drivers/nvmem/sec-qfprom.c | 116 +++++++
drivers/soc/qcom/Kconfig | 2 +
drivers/soc/qcom/llcc-qcom.c | 304 +++++++++++++-----
include/linux/soc/qcom/llcc-qcom.h | 2 +-
8 files changed, 416 insertions(+), 90 deletions(-)
create mode 100644 Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml
create mode 100644 drivers/nvmem/sec-qfprom.c
--
2.40.1
Add LLCC support for multi channel DDR configuration
based on a feature register. Reading DDR channel
confiuration uses nvmem framework, so select the
dependency in Kconfig. Without this, there will be
errors while building the driver with COMPILE_TEST only.
Signed-off-by: Komal Bajaj <[email protected]>
---
drivers/soc/qcom/Kconfig | 2 ++
drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index a491718f8064..cc9ad41c63aa 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -64,6 +64,8 @@ config QCOM_LLCC
tristate "Qualcomm Technologies, Inc. LLCC driver"
depends on ARCH_QCOM || COMPILE_TEST
select REGMAP_MMIO
+ select NVMEM
+ select QCOM_SCM
help
Qualcomm Technologies, Inc. platform specific
Last Level Cache Controller(LLCC) driver for platforms such as,
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 6cf373da5df9..3c29612da1c5 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
@@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
return ret;
}
+static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
+{
+ int ret;
+
+ ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
+ if (ret == -ENOENT) {
+ *cfg_index = 0;
+ return 0;
+ }
+
+ return ret;
+}
+
static int qcom_llcc_remove(struct platform_device *pdev)
{
/* Set the global pointer to a error code to avoid referencing it */
@@ -975,11 +989,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;
u32 sz;
+ u8 cfg_index;
u32 version;
struct regmap *regmap;
+ u32 num_entries = 0;
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
if (!drv_data) {
@@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->version = version;
- 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++, num_entries++)
+ ;
+ if (cfg_index >= num_entries || cfg_index < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ 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)
--
2.40.1
On Fri, 23 Jun 2023 at 17:19, Komal Bajaj <[email protected]> wrote:
>
> Add LLCC support for multi channel DDR configuration
> based on a feature register. Reading DDR channel
> confiuration uses nvmem framework, so select the
> dependency in Kconfig. Without this, there will be
> errors while building the driver with COMPILE_TEST only.
>
> Signed-off-by: Komal Bajaj <[email protected]>
> ---
> drivers/soc/qcom/Kconfig | 2 ++
> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index a491718f8064..cc9ad41c63aa 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -64,6 +64,8 @@ config QCOM_LLCC
> tristate "Qualcomm Technologies, Inc. LLCC driver"
> depends on ARCH_QCOM || COMPILE_TEST
> select REGMAP_MMIO
> + select NVMEM
No need to select NVMEM. The used functions are stubbed if NVMEM is disabled
> + select QCOM_SCM
> help
> Qualcomm Technologies, Inc. platform specific
> Last Level Cache Controller(LLCC) driver for platforms such as,
> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
> index 6cf373da5df9..3c29612da1c5 100644
> --- a/drivers/soc/qcom/llcc-qcom.c
> +++ b/drivers/soc/qcom/llcc-qcom.c
> @@ -12,6 +12,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/nvmem-consumer.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/regmap.h>
> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
> return ret;
> }
>
> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
> +{
> + int ret;
> +
> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
> + if (ret == -ENOENT) {
|| ret == -EOPNOTSUPP ?
> + *cfg_index = 0;
> + return 0;
> + }
> +
> + return ret;
> +}
> +
> static int qcom_llcc_remove(struct platform_device *pdev)
> {
> /* Set the global pointer to a error code to avoid referencing it */
> @@ -975,11 +989,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;
> u32 sz;
> + u8 cfg_index;
> u32 version;
> struct regmap *regmap;
> + u32 num_entries = 0;
>
> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
> if (!drv_data) {
> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>
> drv_data->version = version;
>
> - 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++, num_entries++)
> + ;
Please add num_cfgs to the configuration data instead.
> + if (cfg_index >= num_entries || cfg_index < 0) {
cfg_index is unsigned, so it can not be less than 0.
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + 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)
> --
> 2.40.1
>
--
With best wishes
Dmitry
Add LLCC configuration data for QDU1000 and QRU1000 SoCs
and updating macro name for LLCC_DRE to LLCC_ECC as per
the latest specification.
Signed-off-by: Komal Bajaj <[email protected]>
---
drivers/soc/qcom/llcc-qcom.c | 65 +++++++++++++++++++++++++++++-
include/linux/soc/qcom/llcc-qcom.h | 2 +-
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 3c29612da1c5..d2826158ae60 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -187,7 +187,7 @@ static const struct llcc_slice_config sc8280xp_data[] = {
{ LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
{ LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
{ LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_DRE, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_ECC, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
{ LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
{ LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
{ LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
@@ -358,6 +358,36 @@ static const struct llcc_slice_config sm8550_data[] = {
{LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
};
+static const struct llcc_slice_config qdu1000_data_2ch[] = {
+ {LLCC_MDMHPGRW, 7, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MODHW, 9, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MDMPNG, 21, 256, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_ECC, 26, 512, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {LLCC_MODPE, 29, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_APTCM, 30, 256, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
+ {LLCC_WRCACHE, 31, 128, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+};
+
+static const struct llcc_slice_config qdu1000_data_4ch[] = {
+ {LLCC_MDMHPGRW, 7, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MODHW, 9, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MDMPNG, 21, 512, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_ECC, 26, 1024, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {LLCC_MODPE, 29, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_APTCM, 30, 512, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
+ {LLCC_WRCACHE, 31, 256, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+};
+
+static const struct llcc_slice_config qdu1000_data_8ch[] = {
+ {LLCC_MDMHPGRW, 7, 2048, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_MDMPNG, 21, 1024, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_ECC, 26, 2048, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {LLCC_MODPE, 29, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
+ {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
+ {LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+};
+
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
.trp_ecc_error_status0 = 0x20344,
.trp_ecc_error_status1 = 0x20348,
@@ -557,6 +587,38 @@ static const struct qcom_llcc_config sm8550_cfg[] = {
{ },
};
+static const struct qcom_llcc_config qdu1000_cfg[] = {
+ {
+ .sct_data = qdu1000_data_8ch,
+ .size = ARRAY_SIZE(qdu1000_data_8ch),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ {
+ .sct_data = qdu1000_data_4ch,
+ .size = ARRAY_SIZE(qdu1000_data_4ch),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ {
+ .sct_data = qdu1000_data_4ch,
+ .size = ARRAY_SIZE(qdu1000_data_4ch),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ {
+ .sct_data = qdu1000_data_2ch,
+ .size = ARRAY_SIZE(qdu1000_data_2ch),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ { },
+};
+
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
/**
@@ -1114,6 +1176,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_llcc_of_match[] = {
+ { .compatible = "qcom,qdu1000-llcc", .data = qdu1000_cfg},
{ .compatible = "qcom,sc7180-llcc", .data = sc7180_cfg },
{ .compatible = "qcom,sc7280-llcc", .data = sc7280_cfg },
{ .compatible = "qcom,sc8180x-llcc", .data = sc8180x_cfg },
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
index 93417ba1ead4..1a886666bbb6 100644
--- a/include/linux/soc/qcom/llcc-qcom.h
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -30,7 +30,7 @@
#define LLCC_NPU 23
#define LLCC_WLHW 24
#define LLCC_PIMEM 25
-#define LLCC_DRE 26
+#define LLCC_ECC 26
#define LLCC_CVP 28
#define LLCC_MODPE 29
#define LLCC_APTCM 30
--
2.40.1
Refactor driver to support multiple configuration for llcc on a target.
Reviewed-by: Abel Vesa <[email protected]>
Signed-off-by: Komal Bajaj <[email protected]>
---
drivers/soc/qcom/llcc-qcom.c | 210 ++++++++++++++++++++---------------
1 file changed, 123 insertions(+), 87 deletions(-)
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 67c19ed2219a..6cf373da5df9 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -423,101 +423,137 @@ static const u32 llcc_v2_1_reg_offset[] = {
[LLCC_COMMON_STATUS0] = 0x0003400c,
};
-static const struct qcom_llcc_config sc7180_cfg = {
- .sct_data = sc7180_data,
- .size = ARRAY_SIZE(sc7180_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sc7180_cfg[] = {
+ {
+ .sct_data = sc7180_data,
+ .size = ARRAY_SIZE(sc7180_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sc7280_cfg = {
- .sct_data = sc7280_data,
- .size = ARRAY_SIZE(sc7280_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sc7280_cfg[] = {
+ {
+ .sct_data = sc7280_data,
+ .size = ARRAY_SIZE(sc7280_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sc8180x_cfg = {
- .sct_data = sc8180x_data,
- .size = ARRAY_SIZE(sc8180x_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sc8180x_cfg[] = {
+ {
+ .sct_data = sc8180x_data,
+ .size = ARRAY_SIZE(sc8180x_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sc8280xp_cfg = {
- .sct_data = sc8280xp_data,
- .size = ARRAY_SIZE(sc8280xp_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sc8280xp_cfg[] = {
+ {
+ .sct_data = sc8280xp_data,
+ .size = ARRAY_SIZE(sc8280xp_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sdm845_cfg = {
- .sct_data = sdm845_data,
- .size = ARRAY_SIZE(sdm845_data),
- .need_llcc_cfg = false,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
- .no_edac = true,
+static const struct qcom_llcc_config sdm845_cfg[] = {
+ {
+ .sct_data = sdm845_data,
+ .size = ARRAY_SIZE(sdm845_data),
+ .need_llcc_cfg = false,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ .no_edac = true,
+ },
+ { },
};
-static const struct qcom_llcc_config sm6350_cfg = {
- .sct_data = sm6350_data,
- .size = ARRAY_SIZE(sm6350_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sm6350_cfg[] = {
+ {
+ .sct_data = sm6350_data,
+ .size = ARRAY_SIZE(sm6350_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm7150_cfg = {
- .sct_data = sm7150_data,
- .size = ARRAY_SIZE(sm7150_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sm7150_cfg[] = {
+ {
+ .sct_data = sm7150_data,
+ .size = ARRAY_SIZE(sm7150_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm8150_cfg = {
- .sct_data = sm8150_data,
- .size = ARRAY_SIZE(sm8150_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sm8150_cfg[] = {
+ {
+ .sct_data = sm8150_data,
+ .size = ARRAY_SIZE(sm8150_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm8250_cfg = {
- .sct_data = sm8250_data,
- .size = ARRAY_SIZE(sm8250_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sm8250_cfg[] = {
+ {
+ .sct_data = sm8250_data,
+ .size = ARRAY_SIZE(sm8250_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm8350_cfg = {
- .sct_data = sm8350_data,
- .size = ARRAY_SIZE(sm8350_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v1_reg_offset,
- .edac_reg_offset = &llcc_v1_edac_reg_offset,
+static const struct qcom_llcc_config sm8350_cfg[] = {
+ {
+ .sct_data = sm8350_data,
+ .size = ARRAY_SIZE(sm8350_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm8450_cfg = {
- .sct_data = sm8450_data,
- .size = ARRAY_SIZE(sm8450_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v2_1_reg_offset,
- .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+static const struct qcom_llcc_config sm8450_cfg[] = {
+ {
+ .sct_data = sm8450_data,
+ .size = ARRAY_SIZE(sm8450_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ { },
};
-static const struct qcom_llcc_config sm8550_cfg = {
- .sct_data = sm8550_data,
- .size = ARRAY_SIZE(sm8550_data),
- .need_llcc_cfg = true,
- .reg_offset = llcc_v2_1_reg_offset,
- .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+static const struct qcom_llcc_config sm8550_cfg[] = {
+ {
+ .sct_data = sm8550_data,
+ .size = ARRAY_SIZE(sm8550_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+ { },
};
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
@@ -1004,8 +1040,8 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->version = version;
- llcc_cfg = cfg->sct_data;
- sz = cfg->size;
+ llcc_cfg = cfg[0]->sct_data;
+ sz = cfg[0]->size;
for (i = 0; i < sz; i++)
if (llcc_cfg[i].slice_id > drv_data->max_slices)
@@ -1051,18 +1087,18 @@ static int qcom_llcc_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_llcc_of_match[] = {
- { .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg },
- { .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfg },
- { .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfg },
- { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfg },
- { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
- { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg },
- { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfg },
- { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
- { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
- { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg },
- { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg },
- { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfg },
+ { .compatible = "qcom,sc7180-llcc", .data = sc7180_cfg },
+ { .compatible = "qcom,sc7280-llcc", .data = sc7280_cfg },
+ { .compatible = "qcom,sc8180x-llcc", .data = sc8180x_cfg },
+ { .compatible = "qcom,sc8280xp-llcc", .data = sc8280xp_cfg },
+ { .compatible = "qcom,sdm845-llcc", .data = sdm845_cfg },
+ { .compatible = "qcom,sm6350-llcc", .data = sm6350_cfg },
+ { .compatible = "qcom,sm7150-llcc", .data = sm7150_cfg },
+ { .compatible = "qcom,sm8150-llcc", .data = sm8150_cfg },
+ { .compatible = "qcom,sm8250-llcc", .data = sm8250_cfg },
+ { .compatible = "qcom,sm8350-llcc", .data = sm8350_cfg },
+ { .compatible = "qcom,sm8450-llcc", .data = sm8450_cfg },
+ { .compatible = "qcom,sm8550-llcc", .data = sm8550_cfg },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_llcc_of_match);
--
2.40.1
On Fri, 23 Jun 2023 at 17:19, Komal Bajaj <[email protected]> wrote:
>
> Add LLCC configuration data for QDU1000 and QRU1000 SoCs
> and updating macro name for LLCC_DRE to LLCC_ECC as per
> the latest specification.
Two commits please.
>
> Signed-off-by: Komal Bajaj <[email protected]>
> ---
> drivers/soc/qcom/llcc-qcom.c | 65 +++++++++++++++++++++++++++++-
> include/linux/soc/qcom/llcc-qcom.h | 2 +-
> 2 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
> index 3c29612da1c5..d2826158ae60 100644
> --- a/drivers/soc/qcom/llcc-qcom.c
> +++ b/drivers/soc/qcom/llcc-qcom.c
> @@ -187,7 +187,7 @@ static const struct llcc_slice_config sc8280xp_data[] = {
> { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
> { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> - { LLCC_DRE, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> + { LLCC_ECC, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
> { LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
> @@ -358,6 +358,36 @@ static const struct llcc_slice_config sm8550_data[] = {
> {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
> };
>
> +static const struct llcc_slice_config qdu1000_data_2ch[] = {
> + {LLCC_MDMHPGRW, 7, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 256, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 512, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 256, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 128, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> +};
> +
> +static const struct llcc_slice_config qdu1000_data_4ch[] = {
> + {LLCC_MDMHPGRW, 7, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 512, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 1024, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 512, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 256, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> +};
> +
> +static const struct llcc_slice_config qdu1000_data_8ch[] = {
> + {LLCC_MDMHPGRW, 7, 2048, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 1024, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 2048, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> +};
> +
> static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
> .trp_ecc_error_status0 = 0x20344,
> .trp_ecc_error_status1 = 0x20348,
> @@ -557,6 +587,38 @@ static const struct qcom_llcc_config sm8550_cfg[] = {
> { },
> };
>
> +static const struct qcom_llcc_config qdu1000_cfg[] = {
> + {
> + .sct_data = qdu1000_data_8ch,
> + .size = ARRAY_SIZE(qdu1000_data_8ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_4ch,
> + .size = ARRAY_SIZE(qdu1000_data_4ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_4ch,
> + .size = ARRAY_SIZE(qdu1000_data_4ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_2ch,
> + .size = ARRAY_SIZE(qdu1000_data_2ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + { },
> +};
> +
> static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
>
> /**
> @@ -1114,6 +1176,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
> }
>
> static const struct of_device_id qcom_llcc_of_match[] = {
> + { .compatible = "qcom,qdu1000-llcc", .data = qdu1000_cfg},
> { .compatible = "qcom,sc7180-llcc", .data = sc7180_cfg },
> { .compatible = "qcom,sc7280-llcc", .data = sc7280_cfg },
> { .compatible = "qcom,sc8180x-llcc", .data = sc8180x_cfg },
> diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
> index 93417ba1ead4..1a886666bbb6 100644
> --- a/include/linux/soc/qcom/llcc-qcom.h
> +++ b/include/linux/soc/qcom/llcc-qcom.h
> @@ -30,7 +30,7 @@
> #define LLCC_NPU 23
> #define LLCC_WLHW 24
> #define LLCC_PIMEM 25
> -#define LLCC_DRE 26
> +#define LLCC_ECC 26
> #define LLCC_CVP 28
> #define LLCC_MODPE 29
> #define LLCC_APTCM 30
> --
> 2.40.1
>
--
With best wishes
Dmitry
On 23.06.2023 16:18, Komal Bajaj wrote:
> Add LLCC configuration data for QDU1000 and QRU1000 SoCs
> and updating macro name for LLCC_DRE to LLCC_ECC as per
> the latest specification.
>
> Signed-off-by: Komal Bajaj <[email protected]>
> ---
> drivers/soc/qcom/llcc-qcom.c | 65 +++++++++++++++++++++++++++++-
> include/linux/soc/qcom/llcc-qcom.h | 2 +-
> 2 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
> index 3c29612da1c5..d2826158ae60 100644
> --- a/drivers/soc/qcom/llcc-qcom.c
> +++ b/drivers/soc/qcom/llcc-qcom.c
> @@ -187,7 +187,7 @@ static const struct llcc_slice_config sc8280xp_data[] = {
> { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
> { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> - { LLCC_DRE, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> + { LLCC_ECC, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
> { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
> { LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
> @@ -358,6 +358,36 @@ static const struct llcc_slice_config sm8550_data[] = {
> {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
> };
>
> +static const struct llcc_slice_config qdu1000_data_2ch[] = {
> + {LLCC_MDMHPGRW, 7, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 256, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 512, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 256, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 128, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
Please keep the style coherent with existing entries, so:
- spacing between curly braces and data
- tabs/spaces
- hex should be lowercase
Konrad
> +};
> +
> +static const struct llcc_slice_config qdu1000_data_4ch[] = {
> + {LLCC_MDMHPGRW, 7, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 512, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 1024, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 512, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 256, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> +};
> +
> +static const struct llcc_slice_config qdu1000_data_8ch[] = {
> + {LLCC_MDMHPGRW, 7, 2048, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_MDMPNG, 21, 1024, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_ECC, 26, 2048, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> + {LLCC_MODPE, 29, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
> + {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
> + {LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
> +};
> +
> static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
> .trp_ecc_error_status0 = 0x20344,
> .trp_ecc_error_status1 = 0x20348,
> @@ -557,6 +587,38 @@ static const struct qcom_llcc_config sm8550_cfg[] = {
> { },
> };
>
> +static const struct qcom_llcc_config qdu1000_cfg[] = {
> + {
> + .sct_data = qdu1000_data_8ch,
> + .size = ARRAY_SIZE(qdu1000_data_8ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_4ch,
> + .size = ARRAY_SIZE(qdu1000_data_4ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_4ch,
> + .size = ARRAY_SIZE(qdu1000_data_4ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + {
> + .sct_data = qdu1000_data_2ch,
> + .size = ARRAY_SIZE(qdu1000_data_2ch),
> + .need_llcc_cfg = true,
> + .reg_offset = llcc_v2_1_reg_offset,
> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
> + },
> + { },
> +};
> +
> static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
>
> /**
> @@ -1114,6 +1176,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
> }
>
> static const struct of_device_id qcom_llcc_of_match[] = {
> + { .compatible = "qcom,qdu1000-llcc", .data = qdu1000_cfg},
> { .compatible = "qcom,sc7180-llcc", .data = sc7180_cfg },
> { .compatible = "qcom,sc7280-llcc", .data = sc7280_cfg },
> { .compatible = "qcom,sc8180x-llcc", .data = sc8180x_cfg },
> diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
> index 93417ba1ead4..1a886666bbb6 100644
> --- a/include/linux/soc/qcom/llcc-qcom.h
> +++ b/include/linux/soc/qcom/llcc-qcom.h
> @@ -30,7 +30,7 @@
> #define LLCC_NPU 23
> #define LLCC_WLHW 24
> #define LLCC_PIMEM 25
> -#define LLCC_DRE 26
> +#define LLCC_ECC 26
> #define LLCC_CVP 28
> #define LLCC_MODPE 29
> #define LLCC_APTCM 30
On 23.06.2023 16:18, Komal Bajaj wrote:
> Add LLCC support for multi channel DDR configuration
> based on a feature register. Reading DDR channel
> confiuration uses nvmem framework, so select the
> dependency in Kconfig. Without this, there will be
> errors while building the driver with COMPILE_TEST only.
>
> Signed-off-by: Komal Bajaj <[email protected]>
> ---
> drivers/soc/qcom/Kconfig | 2 ++
> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index a491718f8064..cc9ad41c63aa 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -64,6 +64,8 @@ config QCOM_LLCC
> tristate "Qualcomm Technologies, Inc. LLCC driver"
> depends on ARCH_QCOM || COMPILE_TEST
> select REGMAP_MMIO
> + select NVMEM
> + select QCOM_SCM
> help
> Qualcomm Technologies, Inc. platform specific
> Last Level Cache Controller(LLCC) driver for platforms such as,
> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
> index 6cf373da5df9..3c29612da1c5 100644
> --- a/drivers/soc/qcom/llcc-qcom.c
> +++ b/drivers/soc/qcom/llcc-qcom.c
> @@ -12,6 +12,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/nvmem-consumer.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/regmap.h>
> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
> return ret;
> }
>
> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
> +{
> + int ret;
> +
> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
> + if (ret == -ENOENT) {
> + *cfg_index = 0;
> + return 0;
> + }
> +
> + return ret;
> +}
> +
> static int qcom_llcc_remove(struct platform_device *pdev)
> {
> /* Set the global pointer to a error code to avoid referencing it */
> @@ -975,11 +989,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;
> u32 sz;
> + u8 cfg_index;
> u32 version;
> struct regmap *regmap;
> + u32 num_entries = 0;
>
> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
> if (!drv_data) {
> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>
> drv_data->version = version;
>
> - 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++, num_entries++)
> + ;
> + if (cfg_index >= num_entries || cfg_index < 0) {
cfg_index is an unsigned variable, it can never be < 0
> + ret = -EINVAL;
> + goto err;
> + }
> +
if (cfg_index >= entry->size)? With that, you can also keep the config
entries non-0-terminated in the previous patch, saving a whole lot of RAM.
Konrad
> + 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)
On 6/23/2023 7:57 PM, Dmitry Baryshkov wrote:
> On Fri, 23 Jun 2023 at 17:19, Komal Bajaj <[email protected]> wrote:
>> Add LLCC configuration data for QDU1000 and QRU1000 SoCs
>> and updating macro name for LLCC_DRE to LLCC_ECC as per
>> the latest specification.
> Two commits please.
Okay, will split this into two commits.
Thanks
Komal
>
>> Signed-off-by: Komal Bajaj <[email protected]>
>> ---
>> drivers/soc/qcom/llcc-qcom.c | 65 +++++++++++++++++++++++++++++-
>> include/linux/soc/qcom/llcc-qcom.h | 2 +-
>> 2 files changed, 65 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
>> index 3c29612da1c5..d2826158ae60 100644
>> --- a/drivers/soc/qcom/llcc-qcom.c
>> +++ b/drivers/soc/qcom/llcc-qcom.c
>> @@ -187,7 +187,7 @@ static const struct llcc_slice_config sc8280xp_data[] = {
>> { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
>> { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
>> { LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
>> - { LLCC_DRE, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
>> + { LLCC_ECC, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
>> { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
>> { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
>> { LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
>> @@ -358,6 +358,36 @@ static const struct llcc_slice_config sm8550_data[] = {
>> {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
>> };
>>
>> +static const struct llcc_slice_config qdu1000_data_2ch[] = {
>> + {LLCC_MDMHPGRW, 7, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MODHW, 9, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MDMPNG, 21, 256, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_ECC, 26, 512, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> + {LLCC_MODPE, 29, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_APTCM, 30, 256, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_WRCACHE, 31, 128, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> +};
>> +
>> +static const struct llcc_slice_config qdu1000_data_4ch[] = {
>> + {LLCC_MDMHPGRW, 7, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MODHW, 9, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MDMPNG, 21, 512, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_ECC, 26, 1024, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> + {LLCC_MODPE, 29, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_APTCM, 30, 512, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_WRCACHE, 31, 256, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> +};
>> +
>> +static const struct llcc_slice_config qdu1000_data_8ch[] = {
>> + {LLCC_MDMHPGRW, 7, 2048, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_MDMPNG, 21, 1024, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_ECC, 26, 2048, 3, 1, 0xFFC, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> + {LLCC_MODPE, 29, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xC, 1, 0, 0, 1, 0, 0, 0 },
>> + {LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
>> +};
>> +
>> static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
>> .trp_ecc_error_status0 = 0x20344,
>> .trp_ecc_error_status1 = 0x20348,
>> @@ -557,6 +587,38 @@ static const struct qcom_llcc_config sm8550_cfg[] = {
>> { },
>> };
>>
>> +static const struct qcom_llcc_config qdu1000_cfg[] = {
>> + {
>> + .sct_data = qdu1000_data_8ch,
>> + .size = ARRAY_SIZE(qdu1000_data_8ch),
>> + .need_llcc_cfg = true,
>> + .reg_offset = llcc_v2_1_reg_offset,
>> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
>> + },
>> + {
>> + .sct_data = qdu1000_data_4ch,
>> + .size = ARRAY_SIZE(qdu1000_data_4ch),
>> + .need_llcc_cfg = true,
>> + .reg_offset = llcc_v2_1_reg_offset,
>> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
>> + },
>> + {
>> + .sct_data = qdu1000_data_4ch,
>> + .size = ARRAY_SIZE(qdu1000_data_4ch),
>> + .need_llcc_cfg = true,
>> + .reg_offset = llcc_v2_1_reg_offset,
>> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
>> + },
>> + {
>> + .sct_data = qdu1000_data_2ch,
>> + .size = ARRAY_SIZE(qdu1000_data_2ch),
>> + .need_llcc_cfg = true,
>> + .reg_offset = llcc_v2_1_reg_offset,
>> + .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
>> + },
>> + { },
>> +};
>> +
>> static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
>>
>> /**
>> @@ -1114,6 +1176,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>> }
>>
>> static const struct of_device_id qcom_llcc_of_match[] = {
>> + { .compatible = "qcom,qdu1000-llcc", .data = qdu1000_cfg},
>> { .compatible = "qcom,sc7180-llcc", .data = sc7180_cfg },
>> { .compatible = "qcom,sc7280-llcc", .data = sc7280_cfg },
>> { .compatible = "qcom,sc8180x-llcc", .data = sc8180x_cfg },
>> diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
>> index 93417ba1ead4..1a886666bbb6 100644
>> --- a/include/linux/soc/qcom/llcc-qcom.h
>> +++ b/include/linux/soc/qcom/llcc-qcom.h
>> @@ -30,7 +30,7 @@
>> #define LLCC_NPU 23
>> #define LLCC_WLHW 24
>> #define LLCC_PIMEM 25
>> -#define LLCC_DRE 26
>> +#define LLCC_ECC 26
>> #define LLCC_CVP 28
>> #define LLCC_MODPE 29
>> #define LLCC_APTCM 30
>> --
>> 2.40.1
>>
>
On 6/23/2023 8:28 PM, Konrad Dybcio wrote:
> On 23.06.2023 16:18, Komal Bajaj wrote:
>> Add LLCC support for multi channel DDR configuration
>> based on a feature register. Reading DDR channel
>> confiuration uses nvmem framework, so select the
>> dependency in Kconfig. Without this, there will be
>> errors while building the driver with COMPILE_TEST only.
>>
>> Signed-off-by: Komal Bajaj <[email protected]>
>> ---
>> drivers/soc/qcom/Kconfig | 2 ++
>> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>> index a491718f8064..cc9ad41c63aa 100644
>> --- a/drivers/soc/qcom/Kconfig
>> +++ b/drivers/soc/qcom/Kconfig
>> @@ -64,6 +64,8 @@ config QCOM_LLCC
>> tristate "Qualcomm Technologies, Inc. LLCC driver"
>> depends on ARCH_QCOM || COMPILE_TEST
>> select REGMAP_MMIO
>> + select NVMEM
>> + select QCOM_SCM
>> help
>> Qualcomm Technologies, Inc. platform specific
>> Last Level Cache Controller(LLCC) driver for platforms such as,
>> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
>> index 6cf373da5df9..3c29612da1c5 100644
>> --- a/drivers/soc/qcom/llcc-qcom.c
>> +++ b/drivers/soc/qcom/llcc-qcom.c
>> @@ -12,6 +12,7 @@
>> #include <linux/kernel.h>
>> #include <linux/module.h>
>> #include <linux/mutex.h>
>> +#include <linux/nvmem-consumer.h>
>> #include <linux/of.h>
>> #include <linux/of_device.h>
>> #include <linux/regmap.h>
>> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
>> return ret;
>> }
>>
>> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
>> +{
>> + int ret;
>> +
>> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
>> + if (ret == -ENOENT) {
>> + *cfg_index = 0;
>> + return 0;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> static int qcom_llcc_remove(struct platform_device *pdev)
>> {
>> /* Set the global pointer to a error code to avoid referencing it */
>> @@ -975,11 +989,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;
>> u32 sz;
>> + u8 cfg_index;
>> u32 version;
>> struct regmap *regmap;
>> + u32 num_entries = 0;
>>
>> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
>> if (!drv_data) {
>> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>>
>> drv_data->version = version;
>>
>> - 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++, num_entries++)
>> + ;
>> + if (cfg_index >= num_entries || cfg_index < 0) {
> cfg_index is an unsigned variable, it can never be < 0
Okay, will remove this condition.
>
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> +
> if (cfg_index >= entry->size)? With that, you can also keep the config
> entries non-0-terminated in the previous patch, saving a whole lot of RAM.
entry->size represents the size of sct table whereas num_entries
represents the number
of sct tables that we can have. And by this check we are validating the
value read from the
fuse register. Am I understanding your comment correctly?
>
> Konrad
>> + 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)
On 28.06.2023 10:52, Komal Bajaj wrote:
>
>
> On 6/23/2023 8:28 PM, Konrad Dybcio wrote:
>> On 23.06.2023 16:18, Komal Bajaj wrote:
>>> Add LLCC support for multi channel DDR configuration
>>> based on a feature register. Reading DDR channel
>>> confiuration uses nvmem framework, so select the
>>> dependency in Kconfig. Without this, there will be
>>> errors while building the driver with COMPILE_TEST only.
>>>
>>> Signed-off-by: Komal Bajaj <[email protected]>
>>> ---
>>> drivers/soc/qcom/Kconfig | 2 ++
>>> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>>> index a491718f8064..cc9ad41c63aa 100644
>>> --- a/drivers/soc/qcom/Kconfig
>>> +++ b/drivers/soc/qcom/Kconfig
>>> @@ -64,6 +64,8 @@ config QCOM_LLCC
>>> tristate "Qualcomm Technologies, Inc. LLCC driver"
>>> depends on ARCH_QCOM || COMPILE_TEST
>>> select REGMAP_MMIO
>>> + select NVMEM
>>> + select QCOM_SCM
>>> help
>>> Qualcomm Technologies, Inc. platform specific
>>> Last Level Cache Controller(LLCC) driver for platforms such as,
>>> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
>>> index 6cf373da5df9..3c29612da1c5 100644
>>> --- a/drivers/soc/qcom/llcc-qcom.c
>>> +++ b/drivers/soc/qcom/llcc-qcom.c
>>> @@ -12,6 +12,7 @@
>>> #include <linux/kernel.h>
>>> #include <linux/module.h>
>>> #include <linux/mutex.h>
>>> +#include <linux/nvmem-consumer.h>
>>> #include <linux/of.h>
>>> #include <linux/of_device.h>
>>> #include <linux/regmap.h>
>>> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
>>> return ret;
>>> }
>>> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
>>> +{
>>> + int ret;
>>> +
>>> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
>>> + if (ret == -ENOENT) {
>>> + *cfg_index = 0;
>>> + return 0;
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> static int qcom_llcc_remove(struct platform_device *pdev)
>>> {
>>> /* Set the global pointer to a error code to avoid referencing it */
>>> @@ -975,11 +989,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;
>>> u32 sz;
>>> + u8 cfg_index;
>>> u32 version;
>>> struct regmap *regmap;
>>> + u32 num_entries = 0;
>>> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
>>> if (!drv_data) {
>>> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>>> drv_data->version = version;
>>> - 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++, num_entries++)
>>> + ;
>>> + if (cfg_index >= num_entries || cfg_index < 0) {
>> cfg_index is an unsigned variable, it can never be < 0
>
> Okay, will remove this condition.
>
>>
>>> + ret = -EINVAL;
>>> + goto err;
>>> + }
>>> +
>> if (cfg_index >= entry->size)? With that, you can also keep the config
>> entries non-0-terminated in the previous patch, saving a whole lot of RAM.
>
> entry->size represents the size of sct table whereas num_entries represents the number
> of sct tables that we can have. And by this check we are validating the value read from the
> fuse register. Am I understanding your comment correctly?
Oh you're right.
I still see room for improvement, though.
For example, you duplicate assigning need_llcc_cfg, reg_offset
and edac_reg_offset. You can add a new struct, like "sct_config" and add
a pointer to sct_config[] & the length of this array to qcom_llcc_config.
Konrad
>
>>
>> Konrad
>>> + 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)
>
On 28/06/2023 11:45, Komal Bajaj wrote:
No HTML emails on public mailing lists, please.
>
>
> On 6/23/2023 7:56 PM, Dmitry Baryshkov wrote:
>> On Fri, 23 Jun 2023 at 17:19, Komal Bajaj<[email protected]> wrote:
>>> Add LLCC support for multi channel DDR configuration
>>> based on a feature register. Reading DDR channel
>>> confiuration uses nvmem framework, so select the
>>> dependency in Kconfig. Without this, there will be
>>> errors while building the driver with COMPILE_TEST only.
>>>
>>> Signed-off-by: Komal Bajaj<[email protected]>
>>> ---
>>> drivers/soc/qcom/Kconfig | 2 ++
>>> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>>> index a491718f8064..cc9ad41c63aa 100644
>>> --- a/drivers/soc/qcom/Kconfig
>>> +++ b/drivers/soc/qcom/Kconfig
>>> @@ -64,6 +64,8 @@ config QCOM_LLCC
>>> tristate "Qualcomm Technologies, Inc. LLCC driver"
>>> depends on ARCH_QCOM || COMPILE_TEST
>>> select REGMAP_MMIO
>>> + select NVMEM
>> No need to select NVMEM. The used functions are stubbed if NVMEM is disabled
>
> With the previous patch, where this config was not selected, below error
> was flagged by kernel test robot -
>
> drivers/soc/qcom/llcc-qcom.c: In function 'qcom_llcc_get_cfg_index':
> >> drivers/soc/qcom/llcc-qcom.c:951:15: error: implicit declaration
> of function 'nvmem_cell_read_u8'; did you mean
> 'nvmem_cell_read_u64'? [-Werror=implicit-function-declaration]
> 951 | ret = nvmem_cell_read_u8(&pdev->dev,
> "multi_chan_ddr", cfg_index);
> | ^~~~~~~~~~~~~~~~~~
> | nvmem_cell_read_u64
> cc1: some warnings being treated as errors
Judging from the rest of nvmem-consumer.h, it appears that not having
stubs for this function is an omission. Please fix the header instead.
>
>>> + select QCOM_SCM
>>> help
>>> Qualcomm Technologies, Inc. platform specific
>>> Last Level Cache Controller(LLCC) driver for platforms such as,
>>> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
>>> index 6cf373da5df9..3c29612da1c5 100644
>>> --- a/drivers/soc/qcom/llcc-qcom.c
>>> +++ b/drivers/soc/qcom/llcc-qcom.c
>>> @@ -12,6 +12,7 @@
>>> #include <linux/kernel.h>
>>> #include <linux/module.h>
>>> #include <linux/mutex.h>
>>> +#include <linux/nvmem-consumer.h>
>>> #include <linux/of.h>
>>> #include <linux/of_device.h>
>>> #include <linux/regmap.h>
>>> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
>>> return ret;
>>> }
>>>
>>> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
>>> +{
>>> + int ret;
>>> +
>>> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
>>> + if (ret == -ENOENT) {
>> || ret == -EOPNOTSUPP ?
>
> Okay
>
>>> + *cfg_index = 0;
>>> + return 0;
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> static int qcom_llcc_remove(struct platform_device *pdev)
>>> {
>>> /* Set the global pointer to a error code to avoid referencing it */
>>> @@ -975,11 +989,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;
>>> u32 sz;
>>> + u8 cfg_index;
>>> u32 version;
>>> struct regmap *regmap;
>>> + u32 num_entries = 0;
>>>
>>> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
>>> if (!drv_data) {
>>> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>>>
>>> drv_data->version = version;
>>>
>>> - 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++, num_entries++)
>>> + ;
>> Please add num_cfgs to the configuration data instead.
>
> Shall I create a new wrapper struct having a field num_cfg and a pointer
> to those cfgs
> because configuration data is itself an instance of "struct
> qcom_llcc_config" and
> we can have multiple instances of it.
A wrapper struct is a better approach in my opinion.
>
>
>>> + if (cfg_index >= num_entries || cfg_index < 0) {
>> cfg_index is unsigned, so it can not be less than 0.
>
> Okay.
>
>>> + ret = -EINVAL;
>>> + goto err;
>>> + }
>>> +
>>> + 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)
>>> --
>>> 2.40.1
>>>
>
--
With best wishes
Dmitry
On 6/28/2023 4:43 PM, Konrad Dybcio wrote:
> On 28.06.2023 10:52, Komal Bajaj wrote:
>>
>> On 6/23/2023 8:28 PM, Konrad Dybcio wrote:
>>> On 23.06.2023 16:18, Komal Bajaj wrote:
>>>> Add LLCC support for multi channel DDR configuration
>>>> based on a feature register. Reading DDR channel
>>>> confiuration uses nvmem framework, so select the
>>>> dependency in Kconfig. Without this, there will be
>>>> errors while building the driver with COMPILE_TEST only.
>>>>
>>>> Signed-off-by: Komal Bajaj <[email protected]>
>>>> ---
>>>> drivers/soc/qcom/Kconfig | 2 ++
>>>> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
>>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>>>> index a491718f8064..cc9ad41c63aa 100644
>>>> --- a/drivers/soc/qcom/Kconfig
>>>> +++ b/drivers/soc/qcom/Kconfig
>>>> @@ -64,6 +64,8 @@ config QCOM_LLCC
>>>> tristate "Qualcomm Technologies, Inc. LLCC driver"
>>>> depends on ARCH_QCOM || COMPILE_TEST
>>>> select REGMAP_MMIO
>>>> + select NVMEM
>>>> + select QCOM_SCM
>>>> help
>>>> Qualcomm Technologies, Inc. platform specific
>>>> Last Level Cache Controller(LLCC) driver for platforms such as,
>>>> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
>>>> index 6cf373da5df9..3c29612da1c5 100644
>>>> --- a/drivers/soc/qcom/llcc-qcom.c
>>>> +++ b/drivers/soc/qcom/llcc-qcom.c
>>>> @@ -12,6 +12,7 @@
>>>> #include <linux/kernel.h>
>>>> #include <linux/module.h>
>>>> #include <linux/mutex.h>
>>>> +#include <linux/nvmem-consumer.h>
>>>> #include <linux/of.h>
>>>> #include <linux/of_device.h>
>>>> #include <linux/regmap.h>
>>>> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
>>>> return ret;
>>>> }
>>>> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
>>>> + if (ret == -ENOENT) {
>>>> + *cfg_index = 0;
>>>> + return 0;
>>>> + }
>>>> +
>>>> + return ret;
>>>> +}
>>>> +
>>>> static int qcom_llcc_remove(struct platform_device *pdev)
>>>> {
>>>> /* Set the global pointer to a error code to avoid referencing it */
>>>> @@ -975,11 +989,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;
>>>> u32 sz;
>>>> + u8 cfg_index;
>>>> u32 version;
>>>> struct regmap *regmap;
>>>> + u32 num_entries = 0;
>>>> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
>>>> if (!drv_data) {
>>>> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>>>> drv_data->version = version;
>>>> - 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++, num_entries++)
>>>> + ;
>>>> + if (cfg_index >= num_entries || cfg_index < 0) {
>>> cfg_index is an unsigned variable, it can never be < 0
>> Okay, will remove this condition.
>>
>>>> + ret = -EINVAL;
>>>> + goto err;
>>>> + }
>>>> +
>>> if (cfg_index >= entry->size)? With that, you can also keep the config
>>> entries non-0-terminated in the previous patch, saving a whole lot of RAM.
>> entry->size represents the size of sct table whereas num_entries represents the number
>> of sct tables that we can have. And by this check we are validating the value read from the
>> fuse register. Am I understanding your comment correctly?
> Oh you're right.
>
> I still see room for improvement, though.
>
> For example, you duplicate assigning need_llcc_cfg, reg_offset
> and edac_reg_offset. You can add a new struct, like "sct_config" and add
> a pointer to sct_config[] & the length of this array to qcom_llcc_config.
>
> Konrad
Okay, will follow this approach.
>
>>> Konrad
>>>> + 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)
On 6/28/2023 6:44 PM, Dmitry Baryshkov wrote:
> On 28/06/2023 11:45, Komal Bajaj wrote:
>
> No HTML emails on public mailing lists, please.
>
>>
>>
>> On 6/23/2023 7:56 PM, Dmitry Baryshkov wrote:
>>> On Fri, 23 Jun 2023 at 17:19, Komal Bajaj<[email protected]>
>>> wrote:
>>>> Add LLCC support for multi channel DDR configuration
>>>> based on a feature register. Reading DDR channel
>>>> confiuration uses nvmem framework, so select the
>>>> dependency in Kconfig. Without this, there will be
>>>> errors while building the driver with COMPILE_TEST only.
>>>>
>>>> Signed-off-by: Komal Bajaj<[email protected]>
>>>> ---
>>>> drivers/soc/qcom/Kconfig | 2 ++
>>>> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
>>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
>>>> index a491718f8064..cc9ad41c63aa 100644
>>>> --- a/drivers/soc/qcom/Kconfig
>>>> +++ b/drivers/soc/qcom/Kconfig
>>>> @@ -64,6 +64,8 @@ config QCOM_LLCC
>>>> tristate "Qualcomm Technologies, Inc. LLCC driver"
>>>> depends on ARCH_QCOM || COMPILE_TEST
>>>> select REGMAP_MMIO
>>>> + select NVMEM
>>> No need to select NVMEM. The used functions are stubbed if NVMEM is
>>> disabled
>>
>> With the previous patch, where this config was not selected, below
>> error was flagged by kernel test robot -
>>
>> drivers/soc/qcom/llcc-qcom.c: In function 'qcom_llcc_get_cfg_index':
>> >> drivers/soc/qcom/llcc-qcom.c:951:15: error: implicit declaration
>> of function 'nvmem_cell_read_u8'; did you mean
>> 'nvmem_cell_read_u64'? [-Werror=implicit-function-declaration]
>> 951 | ret = nvmem_cell_read_u8(&pdev->dev,
>> "multi_chan_ddr", cfg_index);
>> | ^~~~~~~~~~~~~~~~~~
>> | nvmem_cell_read_u64
>> cc1: some warnings being treated as errors
>
> Judging from the rest of nvmem-consumer.h, it appears that not having
> stubs for this function is an omission. Please fix the header instead.
Okay, I will add the stub for this function in the header.
>
>>
>>>> + select QCOM_SCM
>>>> help
>>>> Qualcomm Technologies, Inc. platform specific
>>>> Last Level Cache Controller(LLCC) driver for platforms
>>>> such as,
>>>> diff --git a/drivers/soc/qcom/llcc-qcom.c
>>>> b/drivers/soc/qcom/llcc-qcom.c
>>>> index 6cf373da5df9..3c29612da1c5 100644
>>>> --- a/drivers/soc/qcom/llcc-qcom.c
>>>> +++ b/drivers/soc/qcom/llcc-qcom.c
>>>> @@ -12,6 +12,7 @@
>>>> #include <linux/kernel.h>
>>>> #include <linux/module.h>
>>>> #include <linux/mutex.h>
>>>> +#include <linux/nvmem-consumer.h>
>>>> #include <linux/of.h>
>>>> #include <linux/of_device.h>
>>>> #include <linux/regmap.h>
>>>> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct
>>>> platform_device *pdev,
>>>> return ret;
>>>> }
>>>>
>>>> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev,
>>>> u8 *cfg_index)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr",
>>>> cfg_index);
>>>> + if (ret == -ENOENT) {
>>> || ret == -EOPNOTSUPP ?
>>
>> Okay
>>
>>>> + *cfg_index = 0;
>>>> + return 0;
>>>> + }
>>>> +
>>>> + return ret;
>>>> +}
>>>> +
>>>> static int qcom_llcc_remove(struct platform_device *pdev)
>>>> {
>>>> /* Set the global pointer to a error code to avoid
>>>> referencing it */
>>>> @@ -975,11 +989,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;
>>>> u32 sz;
>>>> + u8 cfg_index;
>>>> u32 version;
>>>> struct regmap *regmap;
>>>> + u32 num_entries = 0;
>>>>
>>>> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
>>>> if (!drv_data) {
>>>> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct
>>>> platform_device *pdev)
>>>>
>>>> drv_data->version = version;
>>>>
>>>> - 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++, num_entries++)
>>>> + ;
>>> Please add num_cfgs to the configuration data instead.
>>
>> Shall I create a new wrapper struct having a field num_cfg and a
>> pointer to those cfgs
>> because configuration data is itself an instance of "struct
>> qcom_llcc_config" and
>> we can have multiple instances of it.
>
> A wrapper struct is a better approach in my opinion.
Okay, will follow this approach then.
Thanks
Komal
>
>>
>>
>>>> + if (cfg_index >= num_entries || cfg_index < 0) {
>>> cfg_index is unsigned, so it can not be less than 0.
>>
>> Okay.
>>
>>>> + ret = -EINVAL;
>>>> + goto err;
>>>> + }
>>>> +
>>>> + 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)
>>>> --
>>>> 2.40.1
>>>>
>>
>
On Fri, Jun 23, 2023 at 07:48:05PM +0530, Komal Bajaj wrote:
> Add LLCC support for multi channel DDR configuration
> based on a feature register. Reading DDR channel
> confiuration uses nvmem framework, so select the
> dependency in Kconfig. Without this, there will be
> errors while building the driver with COMPILE_TEST only.
You may drop the last sentence, I don't think it's entirely correct.
>
> Signed-off-by: Komal Bajaj <[email protected]>
> ---
> drivers/soc/qcom/Kconfig | 2 ++
> drivers/soc/qcom/llcc-qcom.c | 33 ++++++++++++++++++++++++++++++---
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index a491718f8064..cc9ad41c63aa 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -64,6 +64,8 @@ config QCOM_LLCC
> tristate "Qualcomm Technologies, Inc. LLCC driver"
> depends on ARCH_QCOM || COMPILE_TEST
> select REGMAP_MMIO
> + select NVMEM
> + select QCOM_SCM
I don't see anything your patch that warrants adding QCOM_SCM here,
is it needed, should it be a separate commit?
> help
> Qualcomm Technologies, Inc. platform specific
> Last Level Cache Controller(LLCC) driver for platforms such as,
> diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
> index 6cf373da5df9..3c29612da1c5 100644
> --- a/drivers/soc/qcom/llcc-qcom.c
> +++ b/drivers/soc/qcom/llcc-qcom.c
> @@ -12,6 +12,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/nvmem-consumer.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/regmap.h>
> @@ -943,6 +944,19 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
> return ret;
> }
>
> +static int qcom_llcc_get_cfg_index(struct platform_device *pdev, u8 *cfg_index)
> +{
> + int ret;
> +
> + ret = nvmem_cell_read_u8(&pdev->dev, "multi-chan-ddr", cfg_index);
> + if (ret == -ENOENT) {
> + *cfg_index = 0;
> + return 0;
> + }
> +
> + return ret;
> +}
> +
> static int qcom_llcc_remove(struct platform_device *pdev)
> {
> /* Set the global pointer to a error code to avoid referencing it */
> @@ -975,11 +989,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;
> u32 sz;
> + u8 cfg_index;
> u32 version;
> struct regmap *regmap;
> + u32 num_entries = 0;
>
> drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
> if (!drv_data) {
> @@ -1040,8 +1056,19 @@ static int qcom_llcc_probe(struct platform_device *pdev)
>
> drv_data->version = version;
>
> - 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++, num_entries++)
> + ;
This is still unnecessarily "clever":
"For each valid entry, do nothing, while incrementing num_entries".
How about just writing:
"For each valid entry, increment num_entries"
for (entry = cfg; entry->sct_data; entry++)
num_entries++;
> + if (cfg_index >= num_entries || cfg_index < 0) {
cfg_index is an unsiged number, so it's unlikely to be negative.
Also, "cfg_index" and "num_entries" are values in the same domain, so
keeping their names related is beneficial - i.e. rename num_entries to
num_cfgs.
Regards,
Bjorn
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + 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)
> --
> 2.40.1
>
On Fri, Jun 23, 2023 at 07:48:00PM +0530, Komal Bajaj wrote:
> From: Komal-Bajaj <[email protected]>
>
The patches in this series are going to be merged by two different
maintainers, the interface between them is an existing, clean API, so it
will be possible to merge the two halfs independently.
So please split this into one series for the addition of the nvmem
driver and one for the llcc pieces (with the nvmem interface/stub update
in the llcc one).
Thanks,
Bjorn
> This patch series does the following -
> * Add secure qfprom driver for reading secure fuse region in qfprom driver
> * Add dt-bindings for secure qfprom
> * Refactor LLCC driver to support multiple configuration
> * Add support for multi channel DDR configuration in LLCC
> * Add LLCC support for the Qualcomm QDU1000 and QRU1000 SoCs
>
> Changes in v4 -
> - Created a separate driver for reading from secure fuse region as suggested.
> - Added patch for dt-bindings of secure qfprom driver accordingly.
> - Added new properties in the dt-bindings for LLCC.
> - Implemented new logic to read the nvmem cell as suggested by Bjorn.
> - Separating the DT patches from this series as per suggestion.
>
> Changes in v3-
> - Addressed comments from Krzysztof and Mani.
> - Using qfprom to read DDR configuration from feature register.
>
> Changes in v2:
> - Addressing comments from Konrad.
>
> Komal Bajaj (6):
> dt-bindings: nvmem: sec-qfprom: Add bindings for secure qfprom
> dt-bindings: cache: qcom,llcc: Add LLCC compatible for QDU1000/QRU1000
> nvmem: sec-qfprom: Add Qualcomm secure QFPROM support.
> soc: qcom: llcc: Refactor llcc driver to support multiple
> configuration
> soc: qcom: Add LLCC support for multi channel DDR
> soc: qcom: llcc: Add QDU1000 and QRU1000 LLCC support
>
> .../devicetree/bindings/cache/qcom,llcc.yaml | 10 +
> .../bindings/nvmem/qcom,sec-qfprom.yaml | 58 ++++
> drivers/nvmem/Kconfig | 12 +
> drivers/nvmem/Makefile | 2 +
> drivers/nvmem/sec-qfprom.c | 116 +++++++
> drivers/soc/qcom/Kconfig | 2 +
> drivers/soc/qcom/llcc-qcom.c | 304 +++++++++++++-----
> include/linux/soc/qcom/llcc-qcom.h | 2 +-
> 8 files changed, 416 insertions(+), 90 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml
> create mode 100644 drivers/nvmem/sec-qfprom.c
>
> --
> 2.40.1
>