From 89e6684538f59093d89eda50e30a6f2644b06ab6 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 9 Sep 2024 12:53:57 -0400 Subject: [PATCH 001/116] dt-bindings: memory-controllers: fsl,ifc: split child node differences ifc can connect nor, nand and fpag. Split "^.*@..." into "nand@..." and "(flash|fpga|board-control|cpld)@..." to better describe the child's node binding requirements. Fix below warning: arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dtb: /soc/memory-controller@1530000/nand@1,0: failed to match any schema with compatible: ['fsl,ifc-nand'] Signed-off-by: Frank Li Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20240909165358.2384975-1-Frank.Li@nxp.com Signed-off-by: Krzysztof Kozlowski --- .../memory-controllers/fsl/fsl,ifc.yaml | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml index d1c3421bee10..f7cf0f91c1c0 100644 --- a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml @@ -58,17 +58,39 @@ properties: access window as configured. patternProperties: - "^.*@[a-f0-9]+(,[a-f0-9]+)+$": + "^nand@[a-f0-9]+(,[a-f0-9]+)+$": type: object - description: | - Child device nodes describe the devices connected to IFC such as NOR (e.g. - cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices - like FPGAs, CPLDs, etc. + properties: + compatible: + const: fsl,ifc-nand + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + patternProperties: + "^partition@[0-9a-f]+": + $ref: /schemas/mtd/partitions/partition.yaml# + deprecated: true required: - compatible - reg + additionalProperties: false + + "(flash|fpga|board-control|cpld)@[a-f0-9]+(,[a-f0-9]+)+$": + type: object + oneOf: + - $ref: /schemas/board/fsl,fpga-qixis.yaml# + - $ref: /schemas/mtd/mtd-physmap.yaml# + unevaluatedProperties: false + required: - compatible - reg From 20a0a05f40faf82f64f1c2ad3e9f5006b80ca0cb Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 10 Sep 2024 17:01:39 +0200 Subject: [PATCH 002/116] soc: qcom: llcc: Use designated initializers for LLC settings The current way of storing the configuration is very much unmaintainable. Convert the data to use designated initializers to make it easier both to understand and add/update the slice configuration data. Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240910-topic-llcc_unwrap-v2-1-f0487c983373@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 2644 ++++++++++++++++++++++++++++++---- 1 file changed, 2375 insertions(+), 269 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8fa4ffd3a9b5..5ac79baab73f 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -152,325 +152,2431 @@ enum llcc_reg_offset { }; static const struct llcc_slice_config sa8775p_data[] = { - {LLCC_CPUSS, 1, 2048, 1, 0, 0x00FF, 0x0, 0, 0, 0, 1, 1, 0, 0}, - {LLCC_VIDSC0, 2, 512, 3, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_CPUSS1, 3, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_CPUHWT, 5, 512, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_AUDIO, 6, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CMPT, 10, 4096, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_GPUHTW, 11, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_GPU, 12, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 1, 0}, - {LLCC_MMUHWT, 13, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 1, 0, 0}, - {LLCC_CMPTDMA, 15, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_DISP, 16, 4096, 2, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_VIDFW, 17, 3072, 1, 0, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_AUDHW, 22, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CVP, 28, 256, 3, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0}, - {LLCC_WRCACHE, 31, 512, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 1, 0, 0}, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 2048, + .priority = 1, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUSS1, + .slice_id = 3, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUHWT, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPTDMA, + .slice_id = 15, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 4096, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDFW, + .slice_id = 17, + .max_cap = 3072, + .priority = 1, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .res_ways = 0xf0, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xff, + .cache_mode = 0, + .activate_on_init = true, + }, }; static const struct llcc_slice_config sc7180_data[] = { - { LLCC_CPUSS, 1, 256, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 1 }, - { LLCC_MDM, 8, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW, 11, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 256, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 128, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 128, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 128, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, }; static const struct llcc_slice_config sc7280_data[] = { - { LLCC_CPUSS, 1, 768, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 1, 0}, - { LLCC_MDMHPGRW, 7, 512, 2, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_CMPT, 10, 768, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_GPUHTW, 11, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_GPU, 12, 512, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 0, 1, 0}, - { LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 768, + .priority = 1, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 768, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 768, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WLHW, + .slice_id = 24, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 64, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3f, + .cache_mode = 0, + .retain_on_pc = true, + }, }; static const struct llcc_slice_config sc8180x_data[] = { - { LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1 }, - { LLCC_VIDSC0, 2, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_VIDSC1, 3, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMHPGRW, 7, 3072, 1, 1, 0x3ff, 0xc00, 0, 0, 0, 1, 0 }, - { LLCC_MDM, 8, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 5120, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1 }, - { LLCC_CMPTDMA, 15, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_VIDFW, 17, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMHPFX, 20, 1024, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMPNG, 21, 1024, 0, 1, 0xc, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_NPU, 23, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_WLHW, 24, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MODPE, 29, 512, 1, 1, 0xc, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_APTCM, 30, 512, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0 }, - { LLCC_WRCACHE, 31, 128, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDSC1, + .slice_id = 3, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3ff, + .res_ways = 0xc00, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 5120, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPTDMA, + .slice_id = 15, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDFW, + .slice_id = 17, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 20, + .max_cap = 1024, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xc, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_NPU, + .slice_id = 23, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WLHW, + .slice_id = 24, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xc, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .res_ways = 0x1, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, }; static const struct llcc_slice_config sc8280xp_data[] = { - { LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 }, - { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, - { LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, - { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_GPU, 12, 4096, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 }, - { 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_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 }, - { LLCC_CVPFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_CPUSS1, 3, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .res_ways = 0x1, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CVPFW, + .slice_id = 17, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUSS1, + .slice_id = 3, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUHWT, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, }; -static const struct llcc_slice_config sdm845_data[] = { - { LLCC_CPUSS, 1, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 1 }, - { LLCC_VIDSC0, 2, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 }, - { LLCC_VIDSC1, 3, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 }, - { LLCC_ROTATOR, 4, 563, 2, 1, 0x0, 0x00e, 2, 0, 1, 1, 0 }, - { LLCC_VOICE, 5, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_AUDIO, 6, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_MDMHPGRW, 7, 1024, 2, 0, 0xfc, 0xf00, 0, 0, 1, 1, 0 }, - { LLCC_MDM, 8, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_CMPT, 10, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_GPUHTW, 11, 512, 1, 1, 0xc, 0x0, 0, 0, 1, 1, 0 }, - { LLCC_GPU, 12, 2304, 1, 0, 0xff0, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_MMUHWT, 13, 256, 2, 0, 0x0, 0x1, 0, 0, 1, 0, 1 }, - { LLCC_CMPTDMA, 15, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_DISP, 16, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_VIDFW, 17, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 }, - { LLCC_MDMHPFX, 20, 1024, 2, 1, 0x0, 0xf00, 0, 0, 1, 1, 0 }, - { LLCC_MDMPNG, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0 }, - { LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0 }, +static const struct llcc_slice_config sdm845_data[] = {{ + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .res_ways = 0xf0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDSC1, + .slice_id = 3, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .res_ways = 0xf0, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_ROTATOR, + .slice_id = 4, + .max_cap = 563, + .priority = 2, + .fixed_size = true, + .res_ways = 0xe, + .cache_mode = 2, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VOICE, + .slice_id = 5, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 1024, + .priority = 2, + .bonus_ways = 0xfc, + .res_ways = 0xf00, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xc, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 2304, + .priority = 1, + .bonus_ways = 0xff0, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 256, + .priority = 2, + .res_ways = 0x1, + .cache_mode = 0, + .dis_cap_alloc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPTDMA, + .slice_id = 15, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDFW, + .slice_id = 17, + .max_cap = 2816, + .priority = 1, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 20, + .max_cap = 1024, + .priority = 2, + .fixed_size = true, + .res_ways = 0xf00, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0x1e, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffc, + .res_ways = 0x2, + .cache_mode = 0, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, }; static const struct llcc_slice_config sm6350_data[] = { - { LLCC_CPUSS, 1, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1 }, - { LLCC_MDM, 8, 512, 2, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW, 11, 256, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 512, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_MDMPNG, 21, 768, 0, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_NPU, 23, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_MODPE, 29, 64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 768, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 512, + .priority = 2, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 256, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 768, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_NPU, + .slice_id = 23, + .max_cap = 768, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 64, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, }; static const struct llcc_slice_config sm7150_data[] = { - { LLCC_CPUSS, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1 }, - { LLCC_MDM, 8, 128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW, 11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_NPU, 23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 128, + .priority = 2, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_NPU, + .slice_id = 23, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, }; static const struct llcc_slice_config sm8150_data[] = { - { LLCC_CPUSS, 1, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 1 }, - { LLCC_VIDSC0, 2, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_VIDSC1, 3, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_AUDIO, 6, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMHPGRW, 7, 3072, 1, 0, 0xFF, 0xF00, 0, 0, 0, 1, 0 }, - { LLCC_MDM, 8, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_CMPT, 10, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW , 11, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 2560, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MMUHWT, 13, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1 }, - { LLCC_CMPTDMA, 15, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_DISP, 16, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMHPFX, 20, 1024, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MDMHPFX, 21, 1024, 0, 1, 0xF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_AUDHW, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_NPU, 23, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_WLHW, 24, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_MODPE, 29, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 }, - { LLCC_APTCM, 30, 256, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0 }, - { LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDSC1, + .slice_id = 3, + .max_cap = 512, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 3072, + .priority = 1, + .bonus_ways = 0xff, + .res_ways = 0xf00, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 2560, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPTDMA, + .slice_id = 15, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 20, + .max_cap = 1024, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 21, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_NPU, + .slice_id = 23, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WLHW, + .slice_id = 24, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .res_ways = 0x1, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, }; static const struct llcc_slice_config sm8250_data[] = { - { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 }, - { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, - { LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, - { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 }, - { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_VIDFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, - { LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 }, - { LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPTDMA, + .slice_id = 15, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDFW, + .slice_id = 17, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_NPU, + .slice_id = 23, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WLHW, + .slice_id = 24, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 128, + .priority = 3, + .res_ways = 0x3, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, }; static const struct llcc_slice_config sm8350_data[] = { - { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 1 }, - { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, - { LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_CMPT, 10, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 }, - { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 }, - { LLCC_DISP, 16, 3072, 2, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_MDMPNG, 21, 1024, 0, 1, 0xf, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_MODPE, 29, 256, 1, 1, 0xf, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 0, 1, 0 }, - { LLCC_WRCACHE, 31, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 }, - { LLCC_CVPFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_CPUSS1, 3, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, - { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 1024, + .priority = 3, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 1024, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .write_scid_en = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 3072, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .res_ways = 0x1, + .cache_mode = 1, + .activate_on_init = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .write_scid_en = true, + }, { + .usecase_id = LLCC_CVPFW, + .slice_id = 17, + .max_cap = 512, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CPUSS1, + .slice_id = 3, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CPUHWT, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .write_scid_en = true, + }, }; static const struct llcc_slice_config sm8450_data[] = { - {LLCC_CPUSS, 1, 3072, 1, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, - {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, - {LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_MODHW, 9, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_GPU, 12, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 1, 0 }, - {LLCC_MMUHWT, 13, 768, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, - {LLCC_DISP, 16, 4096, 2, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_MDMPNG, 21, 1024, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, - {LLCC_CVP, 28, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_MODPE, 29, 64, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0 }, - {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, - {LLCC_CVPFW, 17, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_CPUSS1, 3, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_CAMEXP0, 4, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_CPUMTE, 23, 256, 1, 1, 0x0FFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, - {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, - {LLCC_CAMEXP1, 27, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, - {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 3072, + .priority = 1, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 1024, + .priority = 3, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 768, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 4096, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf000, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 64, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf000, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .res_ways = 0xf0, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CVPFW, + .slice_id = 17, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUSS1, + .slice_id = 3, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CAMEXP0, + .slice_id = 4, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CPUMTE, + .slice_id = 23, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CPUHWT, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CAMEXP1, + .slice_id = 27, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 8, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffff, + .cache_mode = 0, + }, }; static const struct llcc_slice_config sm8550_data[] = { - {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_MDMHPGRW, 25, 1024, 4, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_MDMPNG, 27, 1024, 0, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CVP, 8, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_MODPE, 29, 64, 1, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, - {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CAMEXP0, 4, 256, 4, 1, 0xF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CMPTHCP, 17, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_LCPDARE, 30, 128, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, - {LLCC_AENPU, 3, 3072, 1, 1, 0xFE01FF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_ISLAND1, 12, 1792, 7, 1, 0xFE00, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_ISLAND4, 15, 256, 7, 1, 0x10000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CAMEXP2, 19, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CAMEXP3, 20, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_CAMEXP4, 21, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_DISP_WB, 23, 1024, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_DISP_1, 24, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 5120, + .priority = 1, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 25, + .max_cap = 1024, + .priority = 4, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 26, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 9, + .max_cap = 3096, + .priority = 1, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .write_scid_en = true, + .write_scid_cacheable_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 18, + .max_cap = 768, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 27, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xf00000, + .cache_mode = 0, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 8, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 64, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf00000, + .cache_mode = 0, + .alloc_oneway_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CAMEXP0, + .slice_id = 4, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CPUHWT, + .slice_id = 5, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CAMEXP1, + .slice_id = 7, + .max_cap = 3200, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfffff0, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CMPTHCP, + .slice_id = 17, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_LCPDARE, + .slice_id = 30, + .max_cap = 128, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + .alloc_oneway_en = true, + .vict_prio = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 3, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfe01ff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_ISLAND1, + .slice_id = 12, + .max_cap = 1792, + .priority = 7, + .fixed_size = true, + .bonus_ways = 0xfe00, + .cache_mode = 0, + }, { + .usecase_id = LLCC_ISLAND4, + .slice_id = 15, + .max_cap = 256, + .priority = 7, + .fixed_size = true, + .bonus_ways = 0x10000, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CAMEXP2, + .slice_id = 19, + .max_cap = 3200, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfffff0, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CAMEXP3, + .slice_id = 20, + .max_cap = 3200, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfffff0, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CAMEXP4, + .slice_id = 21, + .max_cap = 3200, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xfffff0, + .cache_mode = 2, + }, { + .usecase_id = LLCC_DISP_WB, + .slice_id = 23, + .max_cap = 1024, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_DISP_1, + .slice_id = 24, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_VIDVSP, + .slice_id = 28, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, }; static const struct llcc_slice_config sm8650_data[] = { - {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_AUDIO, 6, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MDMHPGRW, 25, 1024, 3, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MDMHPFX, 24, 1024, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MDMPNG, 27, 1024, 0, 1, 0x000000, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CVP, 8, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MODPE, 29, 128, 1, 1, 0xF00000, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP0, 4, 256, 3, 1, 0xF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CMPTHCP, 17, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_LCPDARE, 30, 128, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_AENPU, 3, 3072, 1, 1, 0xFFFFFF, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_ISLAND1, 12, 5888, 7, 1, 0x0, 0x7FFFFF, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_DISP_WB, 23, 1024, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_VIDVSP, 28, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 5120, + .priority = 1, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + .stale_en = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 25, + .max_cap = 1024, + .priority = 3, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 26, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 9, + .max_cap = 3096, + .priority = 1, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .write_scid_en = true, + .write_scid_cacheable_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 18, + .max_cap = 768, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 24, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 27, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .cache_mode = 0, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 8, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf00000, + .cache_mode = 0, + .alloc_oneway_en = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CAMEXP0, + .slice_id = 4, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CAMEXP1, + .slice_id = 7, + .max_cap = 3200, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfffff0, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CMPTHCP, + .slice_id = 17, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_LCPDARE, + .slice_id = 30, + .max_cap = 128, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + .activate_on_init = true, + .alloc_oneway_en = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 3, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_ISLAND1, + .slice_id = 12, + .max_cap = 5888, + .priority = 7, + .fixed_size = true, + .res_ways = 0x7fffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_DISP_WB, + .slice_id = 23, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_VIDVSP, + .slice_id = 28, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffffff, + .cache_mode = 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 }, + { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 256, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .res_ways = 0xc, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .activate_on_init = true, + }, }; 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 }, + { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 512, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .res_ways = 0xc, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .activate_on_init = true, + }, }; 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 }, + { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 7, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 9, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 21, + .max_cap = 1024, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 2048, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 30, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .res_ways = 0xc, + .cache_mode = 1, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .activate_on_init = true, + }, }; static const struct llcc_slice_config x1e80100_data[] = { - {LLCC_CPUSS, 1, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CMPT, 10, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_GPU, 9, 4608, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_MMUHWT, 18, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CVP, 8, 512, 4, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_WRCACHE, 31, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP0, 4, 256, 4, 1, 0x3, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP1, 7, 3072, 3, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_LCPDARE, 30, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, - {LLCC_AENPU, 3, 3072, 1, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_ISLAND1, 12, 2048, 7, 1, 0x0, 0xF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP2, 19, 3072, 3, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP3, 20, 3072, 2, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {LLCC_CAMEXP4, 21, 3072, 2, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 9, + .max_cap = 4608, + .priority = 1, + .bonus_ways = 0xfff, + .cache_mode = 0, + .write_scid_en = true, + .write_scid_cacheable_en = true, + .stale_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 18, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 8, + .max_cap = 512, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CAMEXP0, + .slice_id = 4, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CAMEXP1, + .slice_id = 7, + .max_cap = 3072, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 2, + }, { + .usecase_id = LLCC_LCPDARE, + .slice_id = 30, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 0, + .activate_on_init = true, + .alloc_oneway_en = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 3, + .max_cap = 3072, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xfff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_ISLAND1, + .slice_id = 12, + .max_cap = 2048, + .priority = 7, + .fixed_size = true, + .res_ways = 0xf, + .cache_mode = 0, + }, { + .usecase_id = LLCC_CAMEXP2, + .slice_id = 19, + .max_cap = 3072, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CAMEXP3, + .slice_id = 20, + .max_cap = 3072, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 2, + }, { + .usecase_id = LLCC_CAMEXP4, + .slice_id = 21, + .max_cap = 3072, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0xffc, + .cache_mode = 2, + }, }; static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { From eea73fa08e69fec9cdc915592022bec6a9ac8ad7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Sep 2024 13:21:10 +0200 Subject: [PATCH 003/116] soc: qcom: qmi: Reorganize kerneldoc parameter names Reorganize kerneldoc parameter names to match the parameter order in the function header. Problems identified using Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20240930112121.95324-25-Julia.Lawall@inria.fr Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qmi_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index bb98b06e87f8..bc6d6379d8b1 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -195,8 +195,8 @@ static void qmi_send_new_lookup(struct qmi_handle *qmi, struct qmi_service *svc) * qmi_add_lookup() - register a new lookup with the name service * @qmi: qmi handle * @service: service id of the request - * @instance: instance id of the request * @version: version number of the request + * @instance: instance id of the request * * Registering a lookup query with the name server will cause the name server * to send NEW_SERVER and DEL_SERVER control messages to this socket as From 7af26f3c11640c0ca3bd478e46454f4ec0cfc96a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:43 +0200 Subject: [PATCH 004/116] reset: amlogic: convert driver to regmap To allow using the same driver for the main reset controller and the auxiliary ones embedded in the clock controllers, convert the the Amlogic reset driver to regmap. Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-1-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 1 + drivers/reset/reset-meson.c | 79 ++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 5484a65f66b9..c730ba6f678b 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -157,6 +157,7 @@ config RESET_MESON tristate "Meson Reset Driver" depends on ARCH_MESON || COMPILE_TEST default ARCH_MESON + select REGMAP_MMIO help This enables the reset driver for Amlogic Meson SoCs. diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 1e9fca3e30e8..9dd38cc209e2 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -11,36 +11,43 @@ #include #include #include +#include #include #include #include -#define BITS_PER_REG 32 - struct meson_reset_param { int reg_count; int level_offset; }; struct meson_reset { - void __iomem *reg_base; const struct meson_reset_param *param; struct reset_controller_dev rcdev; - spinlock_t lock; + struct regmap *map; }; +static void meson_reset_offset_and_bit(struct meson_reset *data, + unsigned long id, + unsigned int *offset, + unsigned int *bit) +{ + unsigned int stride = regmap_get_reg_stride(data->map); + + *offset = (id / (stride * BITS_PER_BYTE)) * stride; + *bit = id % (stride * BITS_PER_BYTE); +} + static int meson_reset_reset(struct reset_controller_dev *rcdev, - unsigned long id) + unsigned long id) { struct meson_reset *data = container_of(rcdev, struct meson_reset, rcdev); - unsigned int bank = id / BITS_PER_REG; - unsigned int offset = id % BITS_PER_REG; - void __iomem *reg_addr = data->reg_base + (bank << 2); + unsigned int offset, bit; - writel(BIT(offset), reg_addr); + meson_reset_offset_and_bit(data, id, &offset, &bit); - return 0; + return regmap_write(data->map, offset, BIT(bit)); } static int meson_reset_level(struct reset_controller_dev *rcdev, @@ -48,25 +55,13 @@ static int meson_reset_level(struct reset_controller_dev *rcdev, { struct meson_reset *data = container_of(rcdev, struct meson_reset, rcdev); - unsigned int bank = id / BITS_PER_REG; - unsigned int offset = id % BITS_PER_REG; - void __iomem *reg_addr; - unsigned long flags; - u32 reg; + unsigned int offset, bit; - reg_addr = data->reg_base + data->param->level_offset + (bank << 2); + meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->level_offset; - spin_lock_irqsave(&data->lock, flags); - - reg = readl(reg_addr); - if (assert) - writel(reg & ~BIT(offset), reg_addr); - else - writel(reg | BIT(offset), reg_addr); - - spin_unlock_irqrestore(&data->lock, flags); - - return 0; + return regmap_update_bits(data->map, offset, + BIT(bit), assert ? 0 : BIT(bit)); } static int meson_reset_assert(struct reset_controller_dev *rcdev, @@ -119,30 +114,42 @@ static const struct of_device_id meson_reset_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, meson_reset_dt_ids); +static const struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static int meson_reset_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct meson_reset *data; + void __iomem *base; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - data->reg_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->reg_base)) - return PTR_ERR(data->reg_base); + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); - data->param = of_device_get_match_data(&pdev->dev); + data->param = of_device_get_match_data(dev); if (!data->param) return -ENODEV; - spin_lock_init(&data->lock); + data->map = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(data->map)) + return dev_err_probe(dev, PTR_ERR(data->map), + "can't init regmap mmio region\n"); data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = data->param->reg_count * BITS_PER_REG; + data->rcdev.nr_resets = data->param->reg_count * BITS_PER_BYTE + * regmap_config.reg_stride; data->rcdev.ops = &meson_reset_ops; - data->rcdev.of_node = pdev->dev.of_node; + data->rcdev.of_node = dev->of_node; - return devm_reset_controller_register(&pdev->dev, &data->rcdev); + return devm_reset_controller_register(dev, &data->rcdev); } static struct platform_driver meson_reset_driver = { From 58d1d138db3243f1b102c0ae2848738d443abf97 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:44 +0200 Subject: [PATCH 005/116] reset: amlogic: use generic data matching function There is no need to use the DT specific function to get matching data, use the generic one instead Suggested-by: Stephen Boyd Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-2-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 9dd38cc209e2..848c2d88503e 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -134,7 +134,7 @@ static int meson_reset_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - data->param = of_device_get_match_data(dev); + data->param = device_get_match_data(dev); if (!data->param) return -ENODEV; From ee64998610329653d12866bedc941b6f045ee29f Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:45 +0200 Subject: [PATCH 006/116] reset: amlogic: make parameters unsigned register count and offset cannot be negative. Use unsigned integer for this. Suggested-by: Stephen Boyd Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-3-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 848c2d88503e..50bd2241ef2f 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -17,8 +17,8 @@ #include struct meson_reset_param { - int reg_count; - int level_offset; + unsigned int reg_count; + unsigned int level_offset; }; struct meson_reset { From 6b2d2e5c7a10015af554017d071e64818959be9a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:46 +0200 Subject: [PATCH 007/116] reset: amlogic: add driver parameters To allow using the same driver for the main reset controller and the auxiliary ones embedded in the clock controllers, allow to customise the reset offset, same as the level offset. Also add an option to make the level reset active low or high. Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-4-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 50bd2241ef2f..6a90613c8095 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -18,7 +18,9 @@ struct meson_reset_param { unsigned int reg_count; + unsigned int reset_offset; unsigned int level_offset; + bool level_low_reset; }; struct meson_reset { @@ -46,6 +48,7 @@ static int meson_reset_reset(struct reset_controller_dev *rcdev, unsigned int offset, bit; meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->reset_offset; return regmap_write(data->map, offset, BIT(bit)); } @@ -59,9 +62,10 @@ static int meson_reset_level(struct reset_controller_dev *rcdev, meson_reset_offset_and_bit(data, id, &offset, &bit); offset += data->param->level_offset; + assert ^= data->param->level_low_reset; return regmap_update_bits(data->map, offset, - BIT(bit), assert ? 0 : BIT(bit)); + BIT(bit), assert ? BIT(bit) : 0); } static int meson_reset_assert(struct reset_controller_dev *rcdev, @@ -84,22 +88,30 @@ static const struct reset_control_ops meson_reset_ops = { static const struct meson_reset_param meson8b_param = { .reg_count = 8, + .reset_offset = 0x0, .level_offset = 0x7c, + .level_low_reset = true, }; static const struct meson_reset_param meson_a1_param = { .reg_count = 3, + .reset_offset = 0x0, .level_offset = 0x40, + .level_low_reset = true, }; static const struct meson_reset_param meson_s4_param = { .reg_count = 6, + .reset_offset = 0x0, .level_offset = 0x40, + .level_low_reset = true, }; static const struct meson_reset_param t7_param = { .reg_count = 7, + .reset_offset = 0x0, .level_offset = 0x40, + .level_low_reset = true, }; static const struct of_device_id meson_reset_dt_ids[] = { From 83dde3e5df6a5be9631428acdc7bfbb10e8df07c Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:47 +0200 Subject: [PATCH 008/116] reset: amlogic: use reset number instead of register count The reset driver from audio clock controller may register less reset than a register can hold. To avoid making any change while switching to auxiliary support, use the number of reset instead of the register count to define the bounds of the reset controller. Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-5-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 6a90613c8095..e31c1b7c9e4d 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -17,7 +17,7 @@ #include struct meson_reset_param { - unsigned int reg_count; + unsigned int reset_num; unsigned int reset_offset; unsigned int level_offset; bool level_low_reset; @@ -87,28 +87,28 @@ static const struct reset_control_ops meson_reset_ops = { }; static const struct meson_reset_param meson8b_param = { - .reg_count = 8, + .reset_num = 256, .reset_offset = 0x0, .level_offset = 0x7c, .level_low_reset = true, }; static const struct meson_reset_param meson_a1_param = { - .reg_count = 3, + .reset_num = 96, .reset_offset = 0x0, .level_offset = 0x40, .level_low_reset = true, }; static const struct meson_reset_param meson_s4_param = { - .reg_count = 6, + .reset_num = 192, .reset_offset = 0x0, .level_offset = 0x40, .level_low_reset = true, }; static const struct meson_reset_param t7_param = { - .reg_count = 7, + .reset_num = 224, .reset_offset = 0x0, .level_offset = 0x40, .level_low_reset = true, @@ -156,8 +156,7 @@ static int meson_reset_probe(struct platform_device *pdev) "can't init regmap mmio region\n"); data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = data->param->reg_count * BITS_PER_BYTE - * regmap_config.reg_stride; + data->rcdev.nr_resets = data->param->reset_num; data->rcdev.ops = &meson_reset_ops; data->rcdev.of_node = dev->of_node; From d623ee26050f8e9a6d68ee3a1a97b30493cd2b1b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:48 +0200 Subject: [PATCH 009/116] reset: amlogic: add reset status support Add a callback to check the status of the level reset, as done in the reset driver of the audio clock controller. This is done keep the functionality when the audio reset controller get migrated to meson-reset. Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-6-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index e31c1b7c9e4d..af690d3012ec 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -68,6 +68,22 @@ static int meson_reset_level(struct reset_controller_dev *rcdev, BIT(bit), assert ? BIT(bit) : 0); } +static int meson_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int val, offset, bit; + + meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->level_offset; + + regmap_read(data->map, offset, &val); + val = !!(BIT(bit) & val); + + return val ^ data->param->level_low_reset; +} + static int meson_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) { @@ -84,6 +100,7 @@ static const struct reset_control_ops meson_reset_ops = { .reset = meson_reset_reset, .assert = meson_reset_assert, .deassert = meson_reset_deassert, + .status = meson_reset_status, }; static const struct meson_reset_param meson8b_param = { From 2c138ee3354f8088769d05701a2e16d1cb4cc22d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:49 +0200 Subject: [PATCH 010/116] reset: amlogic: move drivers to a dedicated directory The meson reset driver will be split in two part, one implemeting the ops, the other providing the platform driver support. This will be done to facilitate the addition of the auxiliary bus support. To avoid making a mess in drivers/reset/ while doing so, move the amlogic reset drivers to a dedicated directory. Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-7-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 16 +--------------- drivers/reset/Makefile | 3 +-- drivers/reset/amlogic/Kconfig | 14 ++++++++++++++ drivers/reset/amlogic/Makefile | 2 ++ .../reset/{ => amlogic}/reset-meson-audio-arb.c | 0 drivers/reset/{ => amlogic}/reset-meson.c | 0 6 files changed, 18 insertions(+), 17 deletions(-) create mode 100644 drivers/reset/amlogic/Kconfig create mode 100644 drivers/reset/amlogic/Makefile rename drivers/reset/{ => amlogic}/reset-meson-audio-arb.c (100%) rename drivers/reset/{ => amlogic}/reset-meson.c (100%) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c730ba6f678b..d28c4401a310 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -153,21 +153,6 @@ config RESET_MCHP_SPARX5 help This driver supports switch core reset for the Microchip Sparx5 SoC. -config RESET_MESON - tristate "Meson Reset Driver" - depends on ARCH_MESON || COMPILE_TEST - default ARCH_MESON - select REGMAP_MMIO - help - This enables the reset driver for Amlogic Meson SoCs. - -config RESET_MESON_AUDIO_ARB - tristate "Meson Audio Memory Arbiter Reset Driver" - depends on ARCH_MESON || COMPILE_TEST - help - This enables the reset driver for Audio Memory Arbiter of - Amlogic's A113 based SoCs - config RESET_NPCM bool "NPCM BMC Reset Driver" if COMPILE_TEST default ARCH_NPCM @@ -357,6 +342,7 @@ config RESET_ZYNQMP help This enables the reset controller driver for Xilinx ZynqMP SoCs. +source "drivers/reset/amlogic/Kconfig" source "drivers/reset/starfive/Kconfig" source "drivers/reset/sti/Kconfig" source "drivers/reset/hisilicon/Kconfig" diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 4411a2a124d7..677c4d1e2632 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += core.o +obj-y += amlogic/ obj-y += hisilicon/ obj-y += starfive/ obj-y += sti/ @@ -21,8 +22,6 @@ obj-$(CONFIG_RESET_K210) += reset-k210.o obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o -obj-$(CONFIG_RESET_MESON) += reset-meson.o -obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o obj-$(CONFIG_RESET_NPCM) += reset-npcm.o obj-$(CONFIG_RESET_NUVOTON_MA35D1) += reset-ma35d1.o obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o diff --git a/drivers/reset/amlogic/Kconfig b/drivers/reset/amlogic/Kconfig new file mode 100644 index 000000000000..532e6a4f7865 --- /dev/null +++ b/drivers/reset/amlogic/Kconfig @@ -0,0 +1,14 @@ +config RESET_MESON + tristate "Meson Reset Driver" + depends on ARCH_MESON || COMPILE_TEST + default ARCH_MESON + select REGMAP_MMIO + help + This enables the reset driver for Amlogic Meson SoCs. + +config RESET_MESON_AUDIO_ARB + tristate "Meson Audio Memory Arbiter Reset Driver" + depends on ARCH_MESON || COMPILE_TEST + help + This enables the reset driver for Audio Memory Arbiter of + Amlogic's A113 based SoCs diff --git a/drivers/reset/amlogic/Makefile b/drivers/reset/amlogic/Makefile new file mode 100644 index 000000000000..55509fc78513 --- /dev/null +++ b/drivers/reset/amlogic/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_RESET_MESON) += reset-meson.o +obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/amlogic/reset-meson-audio-arb.c similarity index 100% rename from drivers/reset/reset-meson-audio-arb.c rename to drivers/reset/amlogic/reset-meson-audio-arb.c diff --git a/drivers/reset/reset-meson.c b/drivers/reset/amlogic/reset-meson.c similarity index 100% rename from drivers/reset/reset-meson.c rename to drivers/reset/amlogic/reset-meson.c From c38ae95cd31c636ae21fff3e6a9250df680f0cdd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:50 +0200 Subject: [PATCH 011/116] reset: amlogic: split the device core and platform probe To prepare the addition of the auxiliary device support, split out the device coomon functions from the probe of the platform device. The device core function will be common to both the platform and auxiliary driver. Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-8-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/Kconfig | 7 +- drivers/reset/amlogic/Makefile | 1 + drivers/reset/amlogic/reset-meson-common.c | 121 ++++++++++++++++++++ drivers/reset/amlogic/reset-meson.c | 122 +++------------------ drivers/reset/amlogic/reset-meson.h | 24 ++++ 5 files changed, 167 insertions(+), 108 deletions(-) create mode 100644 drivers/reset/amlogic/reset-meson-common.c create mode 100644 drivers/reset/amlogic/reset-meson.h diff --git a/drivers/reset/amlogic/Kconfig b/drivers/reset/amlogic/Kconfig index 532e6a4f7865..1d77987088f4 100644 --- a/drivers/reset/amlogic/Kconfig +++ b/drivers/reset/amlogic/Kconfig @@ -1,10 +1,15 @@ +config RESET_MESON_COMMON + tristate + select REGMAP + config RESET_MESON tristate "Meson Reset Driver" depends on ARCH_MESON || COMPILE_TEST default ARCH_MESON select REGMAP_MMIO + select RESET_MESON_COMMON help - This enables the reset driver for Amlogic Meson SoCs. + This enables the reset driver for Amlogic SoCs. config RESET_MESON_AUDIO_ARB tristate "Meson Audio Memory Arbiter Reset Driver" diff --git a/drivers/reset/amlogic/Makefile b/drivers/reset/amlogic/Makefile index 55509fc78513..74aaa2fb5e13 100644 --- a/drivers/reset/amlogic/Makefile +++ b/drivers/reset/amlogic/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_RESET_MESON) += reset-meson.o +obj-$(CONFIG_RESET_MESON_COMMON) += reset-meson-common.o obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o diff --git a/drivers/reset/amlogic/reset-meson-common.c b/drivers/reset/amlogic/reset-meson-common.c new file mode 100644 index 000000000000..d57544801ae9 --- /dev/null +++ b/drivers/reset/amlogic/reset-meson-common.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Amlogic Meson Reset core functions + * + * Copyright (c) 2016-2024 BayLibre, SAS. + * Authors: Neil Armstrong + * Jerome Brunet + */ + +#include +#include +#include +#include + +#include "reset-meson.h" + +struct meson_reset { + const struct meson_reset_param *param; + struct reset_controller_dev rcdev; + struct regmap *map; +}; + +static void meson_reset_offset_and_bit(struct meson_reset *data, + unsigned long id, + unsigned int *offset, + unsigned int *bit) +{ + unsigned int stride = regmap_get_reg_stride(data->map); + + *offset = (id / (stride * BITS_PER_BYTE)) * stride; + *bit = id % (stride * BITS_PER_BYTE); +} + +static int meson_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int offset, bit; + + meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->reset_offset; + + return regmap_write(data->map, offset, BIT(bit)); +} + +static int meson_reset_level(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int offset, bit; + + meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->level_offset; + assert ^= data->param->level_low_reset; + + return regmap_update_bits(data->map, offset, + BIT(bit), assert ? BIT(bit) : 0); +} + +static int meson_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int val, offset, bit; + + meson_reset_offset_and_bit(data, id, &offset, &bit); + offset += data->param->level_offset; + + regmap_read(data->map, offset, &val); + val = !!(BIT(bit) & val); + + return val ^ data->param->level_low_reset; +} + +static int meson_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return meson_reset_level(rcdev, id, true); +} + +static int meson_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return meson_reset_level(rcdev, id, false); +} + +static const struct reset_control_ops meson_reset_ops = { + .reset = meson_reset_reset, + .assert = meson_reset_assert, + .deassert = meson_reset_deassert, + .status = meson_reset_status, +}; + +int meson_reset_controller_register(struct device *dev, struct regmap *map, + const struct meson_reset_param *param) +{ + struct meson_reset *data; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->param = param; + data->map = map; + data->rcdev.owner = dev->driver->owner; + data->rcdev.nr_resets = param->reset_num; + data->rcdev.ops = &meson_reset_ops; + data->rcdev.of_node = dev->of_node; + + return devm_reset_controller_register(dev, &data->rcdev); +} +EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register, MESON_RESET); + +MODULE_DESCRIPTION("Amlogic Meson Reset Core function"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(MESON_RESET); diff --git a/drivers/reset/amlogic/reset-meson.c b/drivers/reset/amlogic/reset-meson.c index af690d3012ec..feb19bf6da77 100644 --- a/drivers/reset/amlogic/reset-meson.c +++ b/drivers/reset/amlogic/reset-meson.c @@ -2,106 +2,20 @@ /* * Amlogic Meson Reset Controller driver * - * Copyright (c) 2016 BayLibre, SAS. - * Author: Neil Armstrong + * Copyright (c) 2016-2024 BayLibre, SAS. + * Authors: Neil Armstrong + * Jerome Brunet */ + #include -#include #include #include #include #include #include #include -#include -#include -struct meson_reset_param { - unsigned int reset_num; - unsigned int reset_offset; - unsigned int level_offset; - bool level_low_reset; -}; - -struct meson_reset { - const struct meson_reset_param *param; - struct reset_controller_dev rcdev; - struct regmap *map; -}; - -static void meson_reset_offset_and_bit(struct meson_reset *data, - unsigned long id, - unsigned int *offset, - unsigned int *bit) -{ - unsigned int stride = regmap_get_reg_stride(data->map); - - *offset = (id / (stride * BITS_PER_BYTE)) * stride; - *bit = id % (stride * BITS_PER_BYTE); -} - -static int meson_reset_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct meson_reset *data = - container_of(rcdev, struct meson_reset, rcdev); - unsigned int offset, bit; - - meson_reset_offset_and_bit(data, id, &offset, &bit); - offset += data->param->reset_offset; - - return regmap_write(data->map, offset, BIT(bit)); -} - -static int meson_reset_level(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) -{ - struct meson_reset *data = - container_of(rcdev, struct meson_reset, rcdev); - unsigned int offset, bit; - - meson_reset_offset_and_bit(data, id, &offset, &bit); - offset += data->param->level_offset; - assert ^= data->param->level_low_reset; - - return regmap_update_bits(data->map, offset, - BIT(bit), assert ? BIT(bit) : 0); -} - -static int meson_reset_status(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct meson_reset *data = - container_of(rcdev, struct meson_reset, rcdev); - unsigned int val, offset, bit; - - meson_reset_offset_and_bit(data, id, &offset, &bit); - offset += data->param->level_offset; - - regmap_read(data->map, offset, &val); - val = !!(BIT(bit) & val); - - return val ^ data->param->level_low_reset; -} - -static int meson_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - return meson_reset_level(rcdev, id, true); -} - -static int meson_reset_deassert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - return meson_reset_level(rcdev, id, false); -} - -static const struct reset_control_ops meson_reset_ops = { - .reset = meson_reset_reset, - .assert = meson_reset_assert, - .deassert = meson_reset_deassert, - .status = meson_reset_status, -}; +#include "reset-meson.h" static const struct meson_reset_param meson8b_param = { .reset_num = 256, @@ -151,33 +65,25 @@ static const struct regmap_config regmap_config = { static int meson_reset_probe(struct platform_device *pdev) { + const struct meson_reset_param *param; struct device *dev = &pdev->dev; - struct meson_reset *data; + struct regmap *map; void __iomem *base; - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); - data->param = device_get_match_data(dev); - if (!data->param) + param = device_get_match_data(dev); + if (!param) return -ENODEV; - data->map = devm_regmap_init_mmio(dev, base, ®map_config); - if (IS_ERR(data->map)) - return dev_err_probe(dev, PTR_ERR(data->map), + map = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "can't init regmap mmio region\n"); - data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = data->param->reset_num; - data->rcdev.ops = &meson_reset_ops; - data->rcdev.of_node = dev->of_node; - - return devm_reset_controller_register(dev, &data->rcdev); + return meson_reset_controller_register(dev, map, param); } static struct platform_driver meson_reset_driver = { @@ -191,4 +97,6 @@ module_platform_driver(meson_reset_driver); MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver"); MODULE_AUTHOR("Neil Armstrong "); +MODULE_AUTHOR("Jerome Brunet "); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(MESON_RESET); diff --git a/drivers/reset/amlogic/reset-meson.h b/drivers/reset/amlogic/reset-meson.h new file mode 100644 index 000000000000..4e1dbd7569c5 --- /dev/null +++ b/drivers/reset/amlogic/reset-meson.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (c) 2024 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef __MESON_RESET_H +#define __MESON_RESET_H + +#include +#include +#include + +struct meson_reset_param { + unsigned int reset_num; + unsigned int reset_offset; + unsigned int level_offset; + bool level_low_reset; +}; + +int meson_reset_controller_register(struct device *dev, struct regmap *map, + const struct meson_reset_param *param); + +#endif /* __MESON_RESET_H */ From fb4c31587adfa9cd50661a535bdbfcc4da57ee38 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 10 Sep 2024 18:32:51 +0200 Subject: [PATCH 012/116] reset: amlogic: add auxiliary reset driver support Add support for the reset controller present in the audio clock controller of the g12 and sm1 SoC families, using the auxiliary bus. This is expected to replace the driver currently present directly within the related clock driver. Signed-off-by: Jerome Brunet Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20240910-meson-rst-aux-v5-9-60be62635d3e@baylibre.com Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/Kconfig | 8 ++ drivers/reset/amlogic/Makefile | 1 + drivers/reset/amlogic/reset-meson-aux.c | 136 +++++++++++++++++++++ drivers/reset/amlogic/reset-meson-common.c | 25 +++- drivers/reset/amlogic/reset-meson.c | 3 + drivers/reset/amlogic/reset-meson.h | 4 + include/soc/amlogic/reset-meson-aux.h | 23 ++++ 7 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 drivers/reset/amlogic/reset-meson-aux.c create mode 100644 include/soc/amlogic/reset-meson-aux.h diff --git a/drivers/reset/amlogic/Kconfig b/drivers/reset/amlogic/Kconfig index 1d77987088f4..3bee9fd60269 100644 --- a/drivers/reset/amlogic/Kconfig +++ b/drivers/reset/amlogic/Kconfig @@ -11,6 +11,14 @@ config RESET_MESON help This enables the reset driver for Amlogic SoCs. +config RESET_MESON_AUX + tristate "Meson Reset Auxiliary Driver" + depends on ARCH_MESON || COMPILE_TEST + select AUXILIARY_BUS + select RESET_MESON_COMMON + help + This enables the reset auxiliary driver for Amlogic SoCs. + config RESET_MESON_AUDIO_ARB tristate "Meson Audio Memory Arbiter Reset Driver" depends on ARCH_MESON || COMPILE_TEST diff --git a/drivers/reset/amlogic/Makefile b/drivers/reset/amlogic/Makefile index 74aaa2fb5e13..ca99a691282c 100644 --- a/drivers/reset/amlogic/Makefile +++ b/drivers/reset/amlogic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_RESET_MESON) += reset-meson.o +obj-$(CONFIG_RESET_MESON_AUX) += reset-meson-aux.o obj-$(CONFIG_RESET_MESON_COMMON) += reset-meson-common.o obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c new file mode 100644 index 000000000000..dd8453001db9 --- /dev/null +++ b/drivers/reset/amlogic/reset-meson-aux.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Amlogic Meson Reset Auxiliary driver + * + * Copyright (c) 2024 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#include +#include +#include +#include +#include +#include + +#include "reset-meson.h" +#include + +static DEFINE_IDA(meson_rst_aux_ida); + +struct meson_reset_adev { + struct auxiliary_device adev; + struct regmap *map; +}; + +#define to_meson_reset_adev(_adev) \ + container_of((_adev), struct meson_reset_adev, adev) + +static const struct meson_reset_param meson_g12a_audio_param = { + .reset_ops = &meson_reset_toggle_ops, + .reset_num = 26, + .level_offset = 0x24, +}; + +static const struct meson_reset_param meson_sm1_audio_param = { + .reset_ops = &meson_reset_toggle_ops, + .reset_num = 39, + .level_offset = 0x28, +}; + +static const struct auxiliary_device_id meson_reset_aux_ids[] = { + { + .name = "axg-audio-clkc.rst-g12a", + .driver_data = (kernel_ulong_t)&meson_g12a_audio_param, + }, { + .name = "axg-audio-clkc.rst-sm1", + .driver_data = (kernel_ulong_t)&meson_sm1_audio_param, + }, {} +}; +MODULE_DEVICE_TABLE(auxiliary, meson_reset_aux_ids); + +static int meson_reset_aux_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + const struct meson_reset_param *param = + (const struct meson_reset_param *)(id->driver_data); + struct meson_reset_adev *raux = + to_meson_reset_adev(adev); + + return meson_reset_controller_register(&adev->dev, raux->map, param); +} + +static struct auxiliary_driver meson_reset_aux_driver = { + .probe = meson_reset_aux_probe, + .id_table = meson_reset_aux_ids, +}; +module_auxiliary_driver(meson_reset_aux_driver); + +static void meson_rst_aux_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + struct meson_reset_adev *raux = + to_meson_reset_adev(adev); + + ida_free(&meson_rst_aux_ida, adev->id); + kfree(raux); +} + +static void meson_rst_aux_unregister_adev(void *_adev) +{ + struct auxiliary_device *adev = _adev; + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +int devm_meson_rst_aux_register(struct device *dev, + struct regmap *map, + const char *adev_name) +{ + struct meson_reset_adev *raux; + struct auxiliary_device *adev; + int ret; + + raux = kzalloc(sizeof(*raux), GFP_KERNEL); + if (!raux) + return -ENOMEM; + + ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); + if (ret < 0) + goto raux_free; + + raux->map = map; + + adev = &raux->adev; + adev->id = ret; + adev->name = adev_name; + adev->dev.parent = dev; + adev->dev.release = meson_rst_aux_release; + device_set_of_node_from_dev(&adev->dev, dev); + + ret = auxiliary_device_init(adev); + if (ret) + goto ida_free; + + ret = __auxiliary_device_add(adev, dev->driver->name); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev, + adev); + +ida_free: + ida_free(&meson_rst_aux_ida, adev->id); +raux_free: + kfree(raux); + return ret; +} +EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); + +MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(MESON_RESET); diff --git a/drivers/reset/amlogic/reset-meson-common.c b/drivers/reset/amlogic/reset-meson-common.c index d57544801ae9..a7b1b250a64d 100644 --- a/drivers/reset/amlogic/reset-meson-common.c +++ b/drivers/reset/amlogic/reset-meson-common.c @@ -87,12 +87,33 @@ static int meson_reset_deassert(struct reset_controller_dev *rcdev, return meson_reset_level(rcdev, id, false); } -static const struct reset_control_ops meson_reset_ops = { +static int meson_reset_level_toggle(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = meson_reset_assert(rcdev, id); + if (ret) + return ret; + + return meson_reset_deassert(rcdev, id); +} + +const struct reset_control_ops meson_reset_ops = { .reset = meson_reset_reset, .assert = meson_reset_assert, .deassert = meson_reset_deassert, .status = meson_reset_status, }; +EXPORT_SYMBOL_NS_GPL(meson_reset_ops, MESON_RESET); + +const struct reset_control_ops meson_reset_toggle_ops = { + .reset = meson_reset_level_toggle, + .assert = meson_reset_assert, + .deassert = meson_reset_deassert, + .status = meson_reset_status, +}; +EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, MESON_RESET); int meson_reset_controller_register(struct device *dev, struct regmap *map, const struct meson_reset_param *param) @@ -107,7 +128,7 @@ int meson_reset_controller_register(struct device *dev, struct regmap *map, data->map = map; data->rcdev.owner = dev->driver->owner; data->rcdev.nr_resets = param->reset_num; - data->rcdev.ops = &meson_reset_ops; + data->rcdev.ops = data->param->reset_ops; data->rcdev.of_node = dev->of_node; return devm_reset_controller_register(dev, &data->rcdev); diff --git a/drivers/reset/amlogic/reset-meson.c b/drivers/reset/amlogic/reset-meson.c index feb19bf6da77..6ae4ed6b7f8b 100644 --- a/drivers/reset/amlogic/reset-meson.c +++ b/drivers/reset/amlogic/reset-meson.c @@ -18,6 +18,7 @@ #include "reset-meson.h" static const struct meson_reset_param meson8b_param = { + .reset_ops = &meson_reset_ops, .reset_num = 256, .reset_offset = 0x0, .level_offset = 0x7c, @@ -25,6 +26,7 @@ static const struct meson_reset_param meson8b_param = { }; static const struct meson_reset_param meson_a1_param = { + .reset_ops = &meson_reset_ops, .reset_num = 96, .reset_offset = 0x0, .level_offset = 0x40, @@ -32,6 +34,7 @@ static const struct meson_reset_param meson_a1_param = { }; static const struct meson_reset_param meson_s4_param = { + .reset_ops = &meson_reset_ops, .reset_num = 192, .reset_offset = 0x0, .level_offset = 0x40, diff --git a/drivers/reset/amlogic/reset-meson.h b/drivers/reset/amlogic/reset-meson.h index 4e1dbd7569c5..2051e126dc3a 100644 --- a/drivers/reset/amlogic/reset-meson.h +++ b/drivers/reset/amlogic/reset-meson.h @@ -12,6 +12,7 @@ #include struct meson_reset_param { + const struct reset_control_ops *reset_ops; unsigned int reset_num; unsigned int reset_offset; unsigned int level_offset; @@ -21,4 +22,7 @@ struct meson_reset_param { int meson_reset_controller_register(struct device *dev, struct regmap *map, const struct meson_reset_param *param); +extern const struct reset_control_ops meson_reset_ops; +extern const struct reset_control_ops meson_reset_toggle_ops; + #endif /* __MESON_RESET_H */ diff --git a/include/soc/amlogic/reset-meson-aux.h b/include/soc/amlogic/reset-meson-aux.h new file mode 100644 index 000000000000..d8a15d48c984 --- /dev/null +++ b/include/soc/amlogic/reset-meson-aux.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __SOC_RESET_MESON_AUX_H +#define __SOC_RESET_MESON_AUX_H + +#include + +struct device; +struct regmap; + +#if IS_ENABLED(CONFIG_RESET_MESON_AUX) +int devm_meson_rst_aux_register(struct device *dev, + struct regmap *map, + const char *adev_name); +#else +static inline int devm_meson_rst_aux_register(struct device *dev, + struct regmap *map, + const char *adev_name) +{ + return 0; +} +#endif + +#endif /* __SOC_RESET_MESON_AUX_H */ From 5f79c4b659b50e332ba31ed2c322376e38453bb0 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 30 Sep 2024 18:55:56 +0200 Subject: [PATCH 013/116] reset: amlogic: Fix small whitespace issue Fix a checkpatch --strict issue: CHECK: Alignment should match open parenthesis #48: FILE: drivers/reset/amlogic/reset-meson-common.c:48: +static int meson_reset_level(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/20240930-reset-align-amlogic-v1-1-f64ed5c4efc1@pengutronix.de Signed-off-by: Philipp Zabel --- drivers/reset/amlogic/reset-meson-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/amlogic/reset-meson-common.c b/drivers/reset/amlogic/reset-meson-common.c index a7b1b250a64d..38a767c06fc7 100644 --- a/drivers/reset/amlogic/reset-meson-common.c +++ b/drivers/reset/amlogic/reset-meson-common.c @@ -45,7 +45,7 @@ static int meson_reset_reset(struct reset_controller_dev *rcdev, } static int meson_reset_level(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) + unsigned long id, bool assert) { struct meson_reset *data = container_of(rcdev, struct meson_reset, rcdev); From dad35f7d2fc14e446669d4cab100597a6798eae5 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 25 Sep 2024 18:40:09 +0200 Subject: [PATCH 014/116] reset: replace boolean parameters with flags parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce enum reset_control_flags and replace the list of boolean parameters to the internal reset_control_get functions with a single flags parameter, before adding more boolean options. The separate boolean parameters have been shown to be error prone in the past. See for example commit a57f68ddc886 ("reset: Fix devm bulk optional exclusive control getter"). Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240925-reset-get-deasserted-v2-1-b3601bbd0458@pengutronix.de Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 71 +++++++++++-------- include/linux/reset.h | 161 ++++++++++++++++++++++++++---------------- 2 files changed, 139 insertions(+), 93 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 4d509d41456a..682d61812852 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -773,12 +773,19 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_release); static struct reset_control * __reset_control_get_internal(struct reset_controller_dev *rcdev, - unsigned int index, bool shared, bool acquired) + unsigned int index, enum reset_control_flags flags) { + bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED; + bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED; struct reset_control *rstc; lockdep_assert_held(&reset_list_mutex); + /* Expect callers to filter out OPTIONAL and DEASSERTED bits */ + if (WARN_ON(flags & ~(RESET_CONTROL_FLAGS_BIT_SHARED | + RESET_CONTROL_FLAGS_BIT_ACQUIRED))) + return ERR_PTR(-EINVAL); + list_for_each_entry(rstc, &rcdev->reset_control_head, list) { if (rstc->id == index) { /* @@ -994,8 +1001,9 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a struct reset_control * __of_reset_control_get(struct device_node *node, const char *id, int index, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; bool gpio_fallback = false; struct reset_control *rstc; struct reset_controller_dev *rcdev; @@ -1059,8 +1067,10 @@ __of_reset_control_get(struct device_node *node, const char *id, int index, goto out_unlock; } + flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; + /* reset_list_mutex also protects the rcdev's reset_control list */ - rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired); + rstc = __reset_control_get_internal(rcdev, rstc_id, flags); out_unlock: mutex_unlock(&reset_list_mutex); @@ -1091,8 +1101,9 @@ __reset_controller_by_name(const char *name) static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; const char *dev_id = dev_name(dev); @@ -1116,9 +1127,11 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, return ERR_PTR(-EPROBE_DEFER); } + flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; + rstc = __reset_control_get_internal(rcdev, lookup->index, - shared, acquired); + flags); mutex_unlock(&reset_list_mutex); break; } @@ -1133,30 +1146,29 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, } struct reset_control *__reset_control_get(struct device *dev, const char *id, - int index, bool shared, bool optional, - bool acquired) + int index, enum reset_control_flags flags) { + bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED; + bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED; + if (WARN_ON(shared && acquired)) return ERR_PTR(-EINVAL); if (dev->of_node) - return __of_reset_control_get(dev->of_node, id, index, shared, - optional, acquired); + return __of_reset_control_get(dev->of_node, id, index, flags); - return __reset_control_get_from_lookup(dev, id, shared, optional, - acquired); + return __reset_control_get_from_lookup(dev, id, flags); } EXPORT_SYMBOL_GPL(__reset_control_get); int __reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { int ret, i; for (i = 0; i < num_rstcs; i++) { - rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0, - shared, optional, acquired); + rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0, flags); if (IS_ERR(rstcs[i].rstc)) { ret = PTR_ERR(rstcs[i].rstc); goto err; @@ -1226,7 +1238,7 @@ static void devm_reset_control_release(struct device *dev, void *res) struct reset_control * __devm_reset_control_get(struct device *dev, const char *id, int index, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { struct reset_control **ptr, *rstc; @@ -1235,7 +1247,7 @@ __devm_reset_control_get(struct device *dev, const char *id, int index, if (!ptr) return ERR_PTR(-ENOMEM); - rstc = __reset_control_get(dev, id, index, shared, optional, acquired); + rstc = __reset_control_get(dev, id, index, flags); if (IS_ERR_OR_NULL(rstc)) { devres_free(ptr); return rstc; @@ -1262,7 +1274,7 @@ static void devm_reset_control_bulk_release(struct device *dev, void *res) int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { struct reset_control_bulk_devres *ptr; int ret; @@ -1272,7 +1284,7 @@ int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, if (!ptr) return -ENOMEM; - ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired); + ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, flags); if (ret < 0) { devres_free(ptr); return ret; @@ -1298,6 +1310,7 @@ EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get); */ int __device_reset(struct device *dev, bool optional) { + enum reset_control_flags flags; struct reset_control *rstc; int ret; @@ -1313,7 +1326,8 @@ int __device_reset(struct device *dev, bool optional) } #endif - rstc = __reset_control_get(dev, NULL, 0, 0, optional, true); + flags = optional ? RESET_CONTROL_OPTIONAL_EXCLUSIVE : RESET_CONTROL_EXCLUSIVE; + rstc = __reset_control_get(dev, NULL, 0, flags); if (IS_ERR(rstc)) return PTR_ERR(rstc); @@ -1356,17 +1370,14 @@ static int of_reset_control_get_count(struct device_node *node) * device node. * * @np: device node for the device that requests the reset controls array - * @shared: whether reset controls are shared or not - * @optional: whether it is optional to get the reset controls - * @acquired: only one reset control may be acquired for a given controller - * and ID + * @flags: whether reset controls are shared, optional, acquired * * Returns pointer to allocated reset_control on success or error on failure */ struct reset_control * -of_reset_control_array_get(struct device_node *np, bool shared, bool optional, - bool acquired) +of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; struct reset_control_array *resets; struct reset_control *rstc; int num, i; @@ -1381,8 +1392,7 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional, resets->num_rstcs = num; for (i = 0; i < num; i++) { - rstc = __of_reset_control_get(np, NULL, i, shared, optional, - acquired); + rstc = __of_reset_control_get(np, NULL, i, flags); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; @@ -1407,8 +1417,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get); * devm_reset_control_array_get - Resource managed reset control array get * * @dev: device that requests the list of reset controls - * @shared: whether reset controls are shared or not - * @optional: whether it is optional to get the reset controls + * @flags: whether reset controls are shared, optional, acquired * * The reset control array APIs are intended for a list of resets * that just have to be asserted or deasserted, without any @@ -1417,7 +1426,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get); * Returns pointer to allocated reset_control on success or error on failure */ struct reset_control * -devm_reset_control_array_get(struct device *dev, bool shared, bool optional) +devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags) { struct reset_control **ptr, *rstc; @@ -1426,7 +1435,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) if (!ptr) return ERR_PTR(-ENOMEM); - rstc = of_reset_control_array_get(dev->of_node, shared, optional, true); + rstc = of_reset_control_array_get(dev->of_node, flags); if (IS_ERR_OR_NULL(rstc)) { devres_free(ptr); return rstc; diff --git a/include/linux/reset.h b/include/linux/reset.h index 514ddf003efc..99296af98f81 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -25,6 +25,33 @@ struct reset_control_bulk_data { struct reset_control *rstc; }; +#define RESET_CONTROL_FLAGS_BIT_SHARED BIT(0) /* not exclusive */ +#define RESET_CONTROL_FLAGS_BIT_OPTIONAL BIT(1) +#define RESET_CONTROL_FLAGS_BIT_ACQUIRED BIT(2) /* iff exclusive, not released */ + +/** + * enum reset_control_flags - Flags that can be passed to the reset_control_get functions + * to determine the type of reset control. + * These values cannot be OR'd. + * + * @RESET_CONTROL_EXCLUSIVE: exclusive, acquired, + * @RESET_CONTROL_EXCLUSIVE_RELEASED: exclusive, released, + * @RESET_CONTROL_SHARED: shared + * @RESET_CONTROL_OPTIONAL_EXCLUSIVE: optional, exclusive, acquired + * @RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED: optional, exclusive, released + * @RESET_CONTROL_OPTIONAL_SHARED: optional, shared + */ +enum reset_control_flags { + RESET_CONTROL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_ACQUIRED, + RESET_CONTROL_EXCLUSIVE_RELEASED = 0, + RESET_CONTROL_SHARED = RESET_CONTROL_FLAGS_BIT_SHARED, + RESET_CONTROL_OPTIONAL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_OPTIONAL | + RESET_CONTROL_FLAGS_BIT_ACQUIRED, + RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED = RESET_CONTROL_FLAGS_BIT_OPTIONAL, + RESET_CONTROL_OPTIONAL_SHARED = RESET_CONTROL_FLAGS_BIT_OPTIONAL | + RESET_CONTROL_FLAGS_BIT_SHARED, +}; + #ifdef CONFIG_RESET_CONTROLLER int reset_control_reset(struct reset_control *rstc); @@ -42,30 +69,25 @@ int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rs void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs); struct reset_control *__of_reset_control_get(struct device_node *node, - const char *id, int index, bool shared, - bool optional, bool acquired); + const char *id, int index, enum reset_control_flags flags); struct reset_control *__reset_control_get(struct device *dev, const char *id, - int index, bool shared, - bool optional, bool acquired); + int index, enum reset_control_flags flags); void reset_control_put(struct reset_control *rstc); int __reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired); + enum reset_control_flags flags); void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs); int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, - const char *id, int index, bool shared, - bool optional, bool acquired); + const char *id, int index, enum reset_control_flags flags); int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired); + enum reset_control_flags flags); struct reset_control *devm_reset_control_array_get(struct device *dev, - bool shared, bool optional); -struct reset_control *of_reset_control_array_get(struct device_node *np, - bool shared, bool optional, - bool acquired); + enum reset_control_flags flags); +struct reset_control *of_reset_control_array_get(struct device_node *np, enum reset_control_flags); int reset_control_get_count(struct device *dev); @@ -116,17 +138,19 @@ static inline int __device_reset(struct device *dev, bool optional) static inline struct reset_control *__of_reset_control_get( struct device_node *node, - const char *id, int index, bool shared, - bool optional, bool acquired) + const char *id, int index, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__reset_control_get( struct device *dev, const char *id, - int index, bool shared, bool optional, - bool acquired) + int index, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? NULL : ERR_PTR(-ENOTSUPP); } @@ -162,8 +186,10 @@ reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs) static inline int __reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? 0 : -EOPNOTSUPP; } @@ -174,30 +200,36 @@ reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, - int index, bool shared, bool optional, - bool acquired) + int index, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, - bool shared, bool optional, bool acquired) + enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? 0 : -EOPNOTSUPP; } static inline struct reset_control * -devm_reset_control_array_get(struct device *dev, bool shared, bool optional) +devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control * -of_reset_control_array_get(struct device_node *np, bool shared, bool optional, - bool acquired) +of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags) { + bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; + return optional ? NULL : ERR_PTR(-ENOTSUPP); } @@ -236,7 +268,7 @@ static inline int device_reset_optional(struct device *dev) static inline struct reset_control * __must_check reset_control_get_exclusive(struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, false, false, true); + return __reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE); } /** @@ -253,7 +285,7 @@ static inline int __must_check reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_EXCLUSIVE); } /** @@ -274,7 +306,7 @@ static inline struct reset_control * __must_check reset_control_get_exclusive_released(struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, false, false, false); + return __reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_RELEASED); } /** @@ -295,7 +327,7 @@ static inline int __must_check reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_EXCLUSIVE_RELEASED); } /** @@ -316,7 +348,8 @@ static inline int __must_check reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED); } /** @@ -344,7 +377,7 @@ reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_r static inline struct reset_control *reset_control_get_shared( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, true, false, false); + return __reset_control_get(dev, id, 0, RESET_CONTROL_SHARED); } /** @@ -361,7 +394,7 @@ static inline int __must_check reset_control_bulk_get_shared(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED); } /** @@ -378,7 +411,7 @@ reset_control_bulk_get_shared(struct device *dev, int num_rstcs, static inline struct reset_control *reset_control_get_optional_exclusive( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, false, true, true); + return __reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -398,7 +431,7 @@ static inline int __must_check reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -415,7 +448,7 @@ reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, static inline struct reset_control *reset_control_get_optional_shared( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, true, true, false); + return __reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED); } /** @@ -435,7 +468,7 @@ static inline int __must_check reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); + return __reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_SHARED); } /** @@ -451,7 +484,7 @@ reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, static inline struct reset_control *of_reset_control_get_exclusive( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, false, false, true); + return __of_reset_control_get(node, id, 0, RESET_CONTROL_EXCLUSIVE); } /** @@ -471,7 +504,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_optional_exclusive( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, false, true, true); + return __of_reset_control_get(node, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -496,7 +529,7 @@ static inline struct reset_control *of_reset_control_get_optional_exclusive( static inline struct reset_control *of_reset_control_get_shared( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, true, false, false); + return __of_reset_control_get(node, id, 0, RESET_CONTROL_SHARED); } /** @@ -513,7 +546,7 @@ static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_exclusive_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, false, false, true); + return __of_reset_control_get(node, NULL, index, RESET_CONTROL_EXCLUSIVE); } /** @@ -541,7 +574,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, true, false, false); + return __of_reset_control_get(node, NULL, index, RESET_CONTROL_SHARED); } /** @@ -560,7 +593,7 @@ static inline struct reset_control * __must_check devm_reset_control_get_exclusive(struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, false, true); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE); } /** @@ -580,7 +613,8 @@ static inline int __must_check devm_reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_EXCLUSIVE); } /** @@ -599,7 +633,7 @@ static inline struct reset_control * __must_check devm_reset_control_get_exclusive_released(struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, false, false); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_RELEASED); } /** @@ -619,7 +653,8 @@ static inline int __must_check devm_reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_EXCLUSIVE_RELEASED); } /** @@ -638,7 +673,7 @@ static inline struct reset_control * __must_check devm_reset_control_get_optional_exclusive_released(struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, true, false); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED); } /** @@ -658,7 +693,8 @@ static inline int __must_check devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED); } /** @@ -673,7 +709,7 @@ devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int static inline struct reset_control *devm_reset_control_get_shared( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, true, false, false); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED); } /** @@ -693,7 +729,7 @@ static inline int __must_check devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED); } /** @@ -711,7 +747,7 @@ devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs, static inline struct reset_control *devm_reset_control_get_optional_exclusive( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, true, true); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -731,7 +767,8 @@ static inline int __must_check devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_OPTIONAL_EXCLUSIVE); } /** @@ -749,7 +786,7 @@ devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs static inline struct reset_control *devm_reset_control_get_optional_shared( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, true, true, false); + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED); } /** @@ -769,7 +806,7 @@ static inline int __must_check devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs) { - return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_OPTIONAL_SHARED); } /** @@ -787,7 +824,7 @@ devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, static inline struct reset_control * devm_reset_control_get_exclusive_by_index(struct device *dev, int index) { - return __devm_reset_control_get(dev, NULL, index, false, false, true); + return __devm_reset_control_get(dev, NULL, index, RESET_CONTROL_EXCLUSIVE); } /** @@ -803,7 +840,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) static inline struct reset_control * devm_reset_control_get_shared_by_index(struct device *dev, int index) { - return __devm_reset_control_get(dev, NULL, index, true, false, false); + return __devm_reset_control_get(dev, NULL, index, RESET_CONTROL_SHARED); } /* @@ -851,54 +888,54 @@ static inline struct reset_control *devm_reset_control_get_by_index( static inline struct reset_control * devm_reset_control_array_get_exclusive(struct device *dev) { - return devm_reset_control_array_get(dev, false, false); + return devm_reset_control_array_get(dev, RESET_CONTROL_EXCLUSIVE); } static inline struct reset_control * devm_reset_control_array_get_shared(struct device *dev) { - return devm_reset_control_array_get(dev, true, false); + return devm_reset_control_array_get(dev, RESET_CONTROL_SHARED); } static inline struct reset_control * devm_reset_control_array_get_optional_exclusive(struct device *dev) { - return devm_reset_control_array_get(dev, false, true); + return devm_reset_control_array_get(dev, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } static inline struct reset_control * devm_reset_control_array_get_optional_shared(struct device *dev) { - return devm_reset_control_array_get(dev, true, true); + return devm_reset_control_array_get(dev, RESET_CONTROL_OPTIONAL_SHARED); } static inline struct reset_control * of_reset_control_array_get_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, false, false, true); + return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE); } static inline struct reset_control * of_reset_control_array_get_exclusive_released(struct device_node *node) { - return of_reset_control_array_get(node, false, false, false); + return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE_RELEASED); } static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { - return of_reset_control_array_get(node, true, false, true); + return of_reset_control_array_get(node, RESET_CONTROL_SHARED); } static inline struct reset_control * of_reset_control_array_get_optional_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, false, true, true); + return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } static inline struct reset_control * of_reset_control_array_get_optional_shared(struct device_node *node) { - return of_reset_control_array_get(node, true, true, true); + return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_SHARED); } #endif From d872bed85036f5e60c66b0dd0994346b4ea6470c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 25 Sep 2024 18:40:10 +0200 Subject: [PATCH 015/116] reset: Add devres helpers to request pre-deasserted reset controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add devres helpers - devm_reset_control_bulk_get_exclusive_deasserted - devm_reset_control_bulk_get_optional_exclusive_deasserted - devm_reset_control_bulk_get_optional_shared_deasserted - devm_reset_control_bulk_get_shared_deasserted - devm_reset_control_get_exclusive_deasserted - devm_reset_control_get_optional_exclusive_deasserted - devm_reset_control_get_optional_shared_deasserted - devm_reset_control_get_shared_deasserted to request and immediately deassert reset controls. During cleanup, reset_control_assert() will be called automatically on the returned reset controls. Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240925-reset-get-deasserted-v2-2-b3601bbd0458@pengutronix.de Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 48 +++++++++++++++++- include/linux/reset.h | 113 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 2 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 682d61812852..22f67fc77ae5 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -1236,23 +1236,46 @@ static void devm_reset_control_release(struct device *dev, void *res) reset_control_put(*(struct reset_control **)res); } +static void devm_reset_control_release_deasserted(struct device *dev, void *res) +{ + struct reset_control *rstc = *(struct reset_control **)res; + + reset_control_assert(rstc); + reset_control_put(rstc); +} + struct reset_control * __devm_reset_control_get(struct device *dev, const char *id, int index, enum reset_control_flags flags) { struct reset_control **ptr, *rstc; + bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED; - ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr), + ptr = devres_alloc(deasserted ? devm_reset_control_release_deasserted : + devm_reset_control_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return ERR_PTR(-ENOMEM); + flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED; + rstc = __reset_control_get(dev, id, index, flags); if (IS_ERR_OR_NULL(rstc)) { devres_free(ptr); return rstc; } + if (deasserted) { + int ret; + + ret = reset_control_deassert(rstc); + if (ret) { + reset_control_put(rstc); + devres_free(ptr); + return ERR_PTR(ret); + } + } + *ptr = rstc; devres_add(dev, ptr); @@ -1272,24 +1295,45 @@ static void devm_reset_control_bulk_release(struct device *dev, void *res) reset_control_bulk_put(devres->num_rstcs, devres->rstcs); } +static void devm_reset_control_bulk_release_deasserted(struct device *dev, void *res) +{ + struct reset_control_bulk_devres *devres = res; + + reset_control_bulk_assert(devres->num_rstcs, devres->rstcs); + reset_control_bulk_put(devres->num_rstcs, devres->rstcs); +} + int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, enum reset_control_flags flags) { struct reset_control_bulk_devres *ptr; + bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED; int ret; - ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr), + ptr = devres_alloc(deasserted ? devm_reset_control_bulk_release_deasserted : + devm_reset_control_bulk_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; + flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED; + ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, flags); if (ret < 0) { devres_free(ptr); return ret; } + if (deasserted) { + ret = reset_control_bulk_deassert(num_rstcs, rstcs); + if (ret) { + reset_control_bulk_put(num_rstcs, rstcs); + devres_free(ptr); + return ret; + } + } + ptr->num_rstcs = num_rstcs; ptr->rstcs = rstcs; devres_add(dev, ptr); diff --git a/include/linux/reset.h b/include/linux/reset.h index 99296af98f81..2986ced69a02 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -28,6 +28,7 @@ struct reset_control_bulk_data { #define RESET_CONTROL_FLAGS_BIT_SHARED BIT(0) /* not exclusive */ #define RESET_CONTROL_FLAGS_BIT_OPTIONAL BIT(1) #define RESET_CONTROL_FLAGS_BIT_ACQUIRED BIT(2) /* iff exclusive, not released */ +#define RESET_CONTROL_FLAGS_BIT_DEASSERTED BIT(3) /** * enum reset_control_flags - Flags that can be passed to the reset_control_get functions @@ -35,21 +36,35 @@ struct reset_control_bulk_data { * These values cannot be OR'd. * * @RESET_CONTROL_EXCLUSIVE: exclusive, acquired, + * @RESET_CONTROL_EXCLUSIVE_DEASSERTED: exclusive, acquired, deasserted * @RESET_CONTROL_EXCLUSIVE_RELEASED: exclusive, released, * @RESET_CONTROL_SHARED: shared + * @RESET_CONTROL_SHARED_DEASSERTED: shared, deasserted * @RESET_CONTROL_OPTIONAL_EXCLUSIVE: optional, exclusive, acquired + * @RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED: optional, exclusive, acquired, deasserted * @RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED: optional, exclusive, released * @RESET_CONTROL_OPTIONAL_SHARED: optional, shared + * @RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED: optional, shared, deasserted */ enum reset_control_flags { RESET_CONTROL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_ACQUIRED, + RESET_CONTROL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_ACQUIRED | + RESET_CONTROL_FLAGS_BIT_DEASSERTED, RESET_CONTROL_EXCLUSIVE_RELEASED = 0, RESET_CONTROL_SHARED = RESET_CONTROL_FLAGS_BIT_SHARED, + RESET_CONTROL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_SHARED | + RESET_CONTROL_FLAGS_BIT_DEASSERTED, RESET_CONTROL_OPTIONAL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_OPTIONAL | RESET_CONTROL_FLAGS_BIT_ACQUIRED, + RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL | + RESET_CONTROL_FLAGS_BIT_ACQUIRED | + RESET_CONTROL_FLAGS_BIT_DEASSERTED, RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED = RESET_CONTROL_FLAGS_BIT_OPTIONAL, RESET_CONTROL_OPTIONAL_SHARED = RESET_CONTROL_FLAGS_BIT_OPTIONAL | RESET_CONTROL_FLAGS_BIT_SHARED, + RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL | + RESET_CONTROL_FLAGS_BIT_SHARED | + RESET_CONTROL_FLAGS_BIT_DEASSERTED, }; #ifdef CONFIG_RESET_CONTROLLER @@ -596,6 +611,25 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE); } +/** + * devm_reset_control_get_exclusive_deasserted - resource managed + * reset_control_get_exclusive() + + * reset_control_deassert() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_exclusive() + reset_control_deassert(). For reset + * controllers returned from this function, reset_control_assert() + + * reset_control_put() is called automatically on driver detach. + * + * See reset_control_get_exclusive() for more information. + */ +static inline struct reset_control * __must_check +devm_reset_control_get_exclusive_deasserted(struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_DEASSERTED); +} + /** * devm_reset_control_bulk_get_exclusive - resource managed * reset_control_bulk_get_exclusive() @@ -712,6 +746,25 @@ static inline struct reset_control *devm_reset_control_get_shared( return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED); } +/** + * devm_reset_control_get_shared_deasserted - resource managed + * reset_control_get_shared() + + * reset_control_deassert() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_shared() + reset_control_deassert(). For reset + * controllers returned from this function, reset_control_assert() + + * reset_control_put() is called automatically on driver detach. + * + * See devm_reset_control_get_shared() for more information. + */ +static inline struct reset_control * __must_check +devm_reset_control_get_shared_deasserted(struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED_DEASSERTED); +} + /** * devm_reset_control_bulk_get_shared - resource managed * reset_control_bulk_get_shared() @@ -732,6 +785,28 @@ devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs, return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED); } +/** + * devm_reset_control_bulk_get_shared_deasserted - resource managed + * reset_control_bulk_get_shared() + + * reset_control_bulk_deassert() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_shared() + reset_control_bulk_deassert(). For + * reset controllers returned from this function, reset_control_bulk_assert() + + * reset_control_bulk_put() are called automatically on driver detach. + * + * See devm_reset_control_bulk_get_shared() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_shared_deasserted(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, + RESET_CONTROL_SHARED_DEASSERTED); +} + /** * devm_reset_control_get_optional_exclusive - resource managed * reset_control_get_optional_exclusive() @@ -750,6 +825,25 @@ static inline struct reset_control *devm_reset_control_get_optional_exclusive( return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE); } +/** + * devm_reset_control_get_optional_exclusive_deasserted - resource managed + * reset_control_get_optional_exclusive() + + * reset_control_deassert() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_optional_exclusive() + reset_control_deassert(). + * For reset controllers returned from this function, reset_control_assert() + + * reset_control_put() is called automatically on driver detach. + * + * See devm_reset_control_get_optional_exclusive() for more information. + */ +static inline struct reset_control * +devm_reset_control_get_optional_exclusive_deasserted(struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED); +} + /** * devm_reset_control_bulk_get_optional_exclusive - resource managed * reset_control_bulk_get_optional_exclusive() @@ -789,6 +883,25 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED); } +/** + * devm_reset_control_get_optional_shared_deasserted - resource managed + * reset_control_get_optional_shared() + + * reset_control_deassert() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_optional_shared() + reset_control_deassert(). For + * reset controllers returned from this function, reset_control_assert() + + * reset_control_put() is called automatically on driver detach. + * + * See devm_reset_control_get_optional_shared() for more information. + */ +static inline struct reset_control * +devm_reset_control_get_optional_shared_deasserted(struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED); +} + /** * devm_reset_control_bulk_get_optional_shared - resource managed * reset_control_bulk_get_optional_shared() From c0260e2b0ed824a36e99c6a9ec143a336eb37e59 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 25 Sep 2024 18:40:11 +0200 Subject: [PATCH 016/116] reset: uniphier-glue: Use devm_reset_control_bulk_get_shared_deasserted() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the pattern devm_reset_control_bulk_get_shared() / reset_control_bulk_deassert() / devm_add_action_or_reset() with devm_reset_control_bulk_get_shared_deasserted() for some reduction in boilerplate. Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240925-reset-get-deasserted-v2-3-b3601bbd0458@pengutronix.de Signed-off-by: Philipp Zabel --- drivers/reset/reset-uniphier-glue.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/reset/reset-uniphier-glue.c b/drivers/reset/reset-uniphier-glue.c index 5f9f2f7994c0..a2a262bf6bfc 100644 --- a/drivers/reset/reset-uniphier-glue.c +++ b/drivers/reset/reset-uniphier-glue.c @@ -35,13 +35,6 @@ static void uniphier_clk_disable(void *_priv) clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); } -static void uniphier_rst_assert(void *_priv) -{ - struct uniphier_glue_reset_priv *priv = _priv; - - reset_control_bulk_assert(priv->data->nrsts, priv->rst); -} - static int uniphier_glue_reset_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -68,13 +61,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev) if (ret) return ret; - for (i = 0; i < priv->data->nrsts; i++) - priv->rst[i].id = priv->data->reset_names[i]; - ret = devm_reset_control_bulk_get_shared(dev, priv->data->nrsts, - priv->rst); - if (ret) - return ret; - ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk); if (ret) return ret; @@ -83,11 +69,11 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev) if (ret) return ret; - ret = reset_control_bulk_deassert(priv->data->nrsts, priv->rst); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, uniphier_rst_assert, priv); + for (i = 0; i < priv->data->nrsts; i++) + priv->rst[i].id = priv->data->reset_names[i]; + ret = devm_reset_control_bulk_get_shared_deasserted(dev, + priv->data->nrsts, + priv->rst); if (ret) return ret; From 44ed4f90a97ff6f339e50ac01db71544e0990efc Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Sat, 6 Jul 2024 14:51:55 +0800 Subject: [PATCH 017/116] drivers: soc: xilinx: add the missing kfree in xlnx_add_cb_for_suspend() If we fail to allocate memory for cb_data by kmalloc, the memory allocation for eve_data is never freed, add the missing kfree() in the error handling path. Fixes: 05e5ba40ea7a ("driver: soc: xilinx: Add support of multiple callbacks for same event in event management driver") Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20240706065155.452764-1-cuigaosheng1@huawei.com Signed-off-by: Michal Simek --- drivers/soc/xilinx/xlnx_event_manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c index f529e1346247..85df6b9c04ee 100644 --- a/drivers/soc/xilinx/xlnx_event_manager.c +++ b/drivers/soc/xilinx/xlnx_event_manager.c @@ -188,8 +188,10 @@ static int xlnx_add_cb_for_suspend(event_cb_func_t cb_fun, void *data) INIT_LIST_HEAD(&eve_data->cb_list_head); cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); - if (!cb_data) + if (!cb_data) { + kfree(eve_data); return -ENOMEM; + } cb_data->eve_cb = cb_fun; cb_data->agent_data = data; From 848f2bbb363d4cdb4202db328a103fd3c34e21a2 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Tue, 30 Jul 2024 01:43:42 -0700 Subject: [PATCH 018/116] firmware: xilinx: Add missing debug firmware interfaces Add missing PM EEMI APIs interface in debug firmware driver. The debugfs firmware driver interface is intended for testing and debugging the EEMI APIs only. This interface does not contain any checking regarding improper usage, and the number, type and valid ranges of the arguments. This interface must be used with a lot of care. In fact, accessing this interface during normal PM operation will very likely cause unexpected problems. The debugfs interface shouldn't be used in the production system and hence it is disabled by default in defconfig. Signed-off-by: Ronak Jain Signed-off-by: Radhey Shyam Pandey Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20240730084342.1683231-1-ronak.jain@amd.com --- drivers/firmware/xilinx/zynqmp-debug.c | 162 ++++++++++++++++++++++++- include/linux/firmware/xlnx-zynqmp.h | 4 + 2 files changed, 165 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c index 8528850af889..22853ae0efdf 100644 --- a/drivers/firmware/xilinx/zynqmp-debug.c +++ b/drivers/firmware/xilinx/zynqmp-debug.c @@ -31,12 +31,50 @@ static char debugfs_buf[PAGE_SIZE]; #define PM_API(id) {id, #id, strlen(#id)} static struct pm_api_info pm_api_list[] = { + PM_API(PM_FORCE_POWERDOWN), + PM_API(PM_REQUEST_WAKEUP), + PM_API(PM_SYSTEM_SHUTDOWN), + PM_API(PM_REQUEST_NODE), + PM_API(PM_RELEASE_NODE), + PM_API(PM_SET_REQUIREMENT), PM_API(PM_GET_API_VERSION), + PM_API(PM_REGISTER_NOTIFIER), + PM_API(PM_RESET_ASSERT), + PM_API(PM_RESET_GET_STATUS), + PM_API(PM_GET_CHIPID), + PM_API(PM_PINCTRL_SET_FUNCTION), + PM_API(PM_PINCTRL_CONFIG_PARAM_GET), + PM_API(PM_PINCTRL_CONFIG_PARAM_SET), + PM_API(PM_IOCTL), + PM_API(PM_CLOCK_ENABLE), + PM_API(PM_CLOCK_DISABLE), + PM_API(PM_CLOCK_GETSTATE), + PM_API(PM_CLOCK_SETDIVIDER), + PM_API(PM_CLOCK_GETDIVIDER), + PM_API(PM_CLOCK_SETPARENT), + PM_API(PM_CLOCK_GETPARENT), PM_API(PM_QUERY_DATA), }; static struct dentry *firmware_debugfs_root; +/** + * zynqmp_pm_ioctl - PM IOCTL for device control and configs + * @node: Node ID of the device + * @ioctl: ID of the requested IOCTL + * @arg1: Argument 1 of requested IOCTL call + * @arg2: Argument 2 of requested IOCTL call + * @arg3: Argument 3 of requested IOCTL call + * @out: Returned output value + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_ioctl(const u32 node, const u32 ioctl, const u32 arg1, + const u32 arg2, const u32 arg3, u32 *out) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, out, 5, node, ioctl, arg1, arg2, arg3); +} + /** * zynqmp_pm_argument_value() - Extract argument value from a PM-API request * @arg: Entered PM-API argument in string format @@ -95,6 +133,128 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret) sprintf(debugfs_buf, "PM-API Version = %d.%d\n", pm_api_version >> 16, pm_api_version & 0xffff); break; + case PM_FORCE_POWERDOWN: + ret = zynqmp_pm_force_pwrdwn(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_REQUEST_ACK_NO); + break; + case PM_REQUEST_WAKEUP: + ret = zynqmp_pm_request_wake(pm_api_arg[0], + pm_api_arg[1], pm_api_arg[2], + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_NO); + break; + case PM_SYSTEM_SHUTDOWN: + ret = zynqmp_pm_system_shutdown(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_REQUEST_NODE: + ret = zynqmp_pm_request_node(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_CAPABILITY_ACCESS, + pm_api_arg[2] ? pm_api_arg[2] : 0, + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_BLOCKING); + break; + case PM_RELEASE_NODE: + ret = zynqmp_pm_release_node(pm_api_arg[0]); + break; + case PM_SET_REQUIREMENT: + ret = zynqmp_pm_set_requirement(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_CAPABILITY_CONTEXT, + pm_api_arg[2] ? + pm_api_arg[2] : 0, + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_BLOCKING); + break; + case PM_REGISTER_NOTIFIER: + ret = zynqmp_pm_register_notifier(pm_api_arg[0], + pm_api_arg[1] ? + pm_api_arg[1] : 0, + pm_api_arg[2] ? + pm_api_arg[2] : 0, + pm_api_arg[3] ? + pm_api_arg[3] : 0); + break; + case PM_RESET_ASSERT: + ret = zynqmp_pm_reset_assert(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_RESET_GET_STATUS: + ret = zynqmp_pm_reset_get_status(pm_api_arg[0], &pm_api_ret[0]); + if (!ret) + sprintf(debugfs_buf, "Reset status: %u\n", + pm_api_ret[0]); + break; + case PM_GET_CHIPID: + ret = zynqmp_pm_get_chipid(&pm_api_ret[0], &pm_api_ret[1]); + if (!ret) + sprintf(debugfs_buf, "Idcode: %#x, Version:%#x\n", + pm_api_ret[0], pm_api_ret[1]); + break; + case PM_PINCTRL_SET_FUNCTION: + ret = zynqmp_pm_pinctrl_set_function(pm_api_arg[0], + pm_api_arg[1]); + break; + case PM_PINCTRL_CONFIG_PARAM_GET: + ret = zynqmp_pm_pinctrl_get_config(pm_api_arg[0], pm_api_arg[1], + &pm_api_ret[0]); + if (!ret) + sprintf(debugfs_buf, + "Pin: %llu, Param: %llu, Value: %u\n", + pm_api_arg[0], pm_api_arg[1], + pm_api_ret[0]); + break; + case PM_PINCTRL_CONFIG_PARAM_SET: + ret = zynqmp_pm_pinctrl_set_config(pm_api_arg[0], + pm_api_arg[1], + pm_api_arg[2]); + break; + case PM_IOCTL: + ret = zynqmp_pm_ioctl(pm_api_arg[0], pm_api_arg[1], + pm_api_arg[2], pm_api_arg[3], + pm_api_arg[4], &pm_api_ret[0]); + if (!ret && (pm_api_arg[1] == IOCTL_GET_RPU_OPER_MODE || + pm_api_arg[1] == IOCTL_GET_PLL_FRAC_MODE || + pm_api_arg[1] == IOCTL_GET_PLL_FRAC_DATA || + pm_api_arg[1] == IOCTL_READ_GGS || + pm_api_arg[1] == IOCTL_READ_PGGS || + pm_api_arg[1] == IOCTL_READ_REG)) + sprintf(debugfs_buf, "IOCTL return value: %u\n", + pm_api_ret[1]); + if (!ret && pm_api_arg[1] == IOCTL_GET_QOS) + sprintf(debugfs_buf, "Default QoS: %u\nCurrent QoS: %u\n", + pm_api_ret[1], pm_api_ret[2]); + break; + case PM_CLOCK_ENABLE: + ret = zynqmp_pm_clock_enable(pm_api_arg[0]); + break; + case PM_CLOCK_DISABLE: + ret = zynqmp_pm_clock_disable(pm_api_arg[0]); + break; + case PM_CLOCK_GETSTATE: + ret = zynqmp_pm_clock_getstate(pm_api_arg[0], &pm_api_ret[0]); + if (!ret) + sprintf(debugfs_buf, "Clock state: %u\n", + pm_api_ret[0]); + break; + case PM_CLOCK_SETDIVIDER: + ret = zynqmp_pm_clock_setdivider(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_CLOCK_GETDIVIDER: + ret = zynqmp_pm_clock_getdivider(pm_api_arg[0], &pm_api_ret[0]); + if (!ret) + sprintf(debugfs_buf, "Divider Value: %d\n", + pm_api_ret[0]); + break; + case PM_CLOCK_SETPARENT: + ret = zynqmp_pm_clock_setparent(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_CLOCK_GETPARENT: + ret = zynqmp_pm_clock_getparent(pm_api_arg[0], &pm_api_ret[0]); + if (!ret) + sprintf(debugfs_buf, + "Clock parent Index: %u\n", pm_api_ret[0]); + break; case PM_QUERY_DATA: qdata.qid = pm_api_arg[0]; qdata.arg1 = pm_api_arg[1]; @@ -150,7 +310,7 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file, char *kern_buff, *tmp_buff; char *pm_api_req; u32 pm_id = 0; - u64 pm_api_arg[4] = {0, 0, 0, 0}; + u64 pm_api_arg[5] = {0, 0, 0, 0, 0}; /* Return values from PM APIs calls */ u32 pm_api_ret[4] = {0, 0, 0, 0}; diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index d7d07afc0532..563382cf16f2 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -218,9 +218,13 @@ enum pm_ioctl_id { /* Runtime feature configuration */ IOCTL_SET_FEATURE_CONFIG = 26, IOCTL_GET_FEATURE_CONFIG = 27, + /* IOCTL for Secure Read/Write Interface */ + IOCTL_READ_REG = 28, /* Dynamic SD/GEM configuration */ IOCTL_SET_SD_CONFIG = 30, IOCTL_SET_GEM_CONFIG = 31, + /* IOCTL to get default/current QoS */ + IOCTL_GET_QOS = 34, }; enum pm_query_id { From f33d6099edf78e3c97900c0173fedbfecc025a9e Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Fri, 30 Aug 2024 03:00:42 -0700 Subject: [PATCH 019/116] firmware: xilinx: use u32 for reset ID in reset APIs Refactors the reset handling mechanisms by replacing the reset ID's enum type with a u32. This update improves flexibility, allowing the reset ID to accommodate a broader range of values, including those that may not fit into predefined enum values. The use of u32 for reset ID enhances extensibility, especially for hardware platforms or features where more granular control of reset operations is required. By shifting to a general integer type, this change reduces constraints and simplifies integration with other system components that rely on non-enum-based reset IDs. Signed-off-by: Ronak Jain Link: https://lore.kernel.org/r/20240830100042.3163511-1-ronak.jain@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 4 ++-- include/linux/firmware/xlnx-zynqmp.h | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index add8acf66a9c..c8be32d9c6af 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -920,7 +920,7 @@ int zynqmp_pm_set_boot_health_status(u32 value) * * Return: Returns status, either success or error+reason */ -int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, +int zynqmp_pm_reset_assert(const u32 reset, const enum zynqmp_pm_reset_action assert_flag) { return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, NULL, 2, reset, assert_flag); @@ -934,7 +934,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); * * Return: Returns status, either success or error+reason */ -int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) +int zynqmp_pm_reset_get_status(const u32 reset, u32 *status) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 563382cf16f2..5b938fc2adad 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -557,9 +557,9 @@ int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data); int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value); int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type); int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select); -int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, +int zynqmp_pm_reset_assert(const u32 reset, const enum zynqmp_pm_reset_action assert_flag); -int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status); +int zynqmp_pm_reset_get_status(const u32 reset, u32 *status); unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode); int zynqmp_pm_bootmode_write(u32 ps_mode); int zynqmp_pm_init_finalize(void); @@ -702,14 +702,13 @@ static inline int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select) return -ENODEV; } -static inline int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, +static inline int zynqmp_pm_reset_assert(const u32 reset, const enum zynqmp_pm_reset_action assert_flag) { return -ENODEV; } -static inline int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, - u32 *status) +static inline int zynqmp_pm_reset_get_status(const u32 reset, u32 *status) { return -ENODEV; } From e8415a8aecdb73cadfcfd1f1e1307d84413a5eb8 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Thu, 19 Sep 2024 22:54:10 -0700 Subject: [PATCH 020/116] firmware: xilinx: add a warning print for unsupported feature As per the current code base, feature check API is used to check the version in zynqmp_pm_pinctrl_set_config() before requesting the firmware, and if the expected version is not found then it will return an error. So now when the latest kernel tries to access the tri-state functionality with older firmware, observe failure prints during booting. The failure prints, [ 1.204850] zynqmp-pinctrl firmware:zynqmp-firmware:pinctrl: failed to set: pin 37 param 2 value 0 [ 2.699455] zynqmp-pinctrl firmware:zynqmp-firmware:pinctrl: failed to set: pin 44 param 2 value 0 [ 2.708424] zynqmp-pinctrl firmware:zynqmp-firmware:pinctrl: failed to set: pin 46 param 2 value 0 [ 2.717387] zynqmp-pinctrl firmware:zynqmp-firmware:pinctrl: failed to set: pin 48 param 2 value 0 Now, these error prints mislead the user whether it is an actual failure or the feature itself is not there in the firmware. So, just to avoid confusion around this, add some debug prints before returning an error code. With that, it is easier to know whether it is an actual failure or the feature is unsupported. Signed-off-by: Ronak Jain Link: https://lore.kernel.org/r/20240920055410.2658465-1-ronak.jain@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index c8be32d9c6af..920aba92feee 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -1118,8 +1118,11 @@ int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, if (pm_family_code == ZYNQMP_FAMILY_CODE && param == PM_PINCTRL_CONFIG_TRI_STATE) { ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET); - if (ret < PM_PINCTRL_PARAM_SET_VERSION) + if (ret < PM_PINCTRL_PARAM_SET_VERSION) { + pr_warn("The requested pinctrl feature is not supported in the current firmware.\n" + "Expected firmware version is 2023.1 and above for this feature to work.\r\n"); return -EOPNOTSUPP; + } } return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, NULL, 3, pin, param, value); From 92fb71333d5737d0296fb968a653dfda4b225175 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Thu, 19 Sep 2024 22:55:01 -0700 Subject: [PATCH 021/116] firmware: xilinx: add support for new SMC call format Added zynqmp_pm_invoke_fw_fn() to use new SMC format in which lower 12 bits of SMC id are fixed and firmware header is moved to subsequent SMC arguments. The new SMC format supports full request and response buffers. Added zynqmp_pm_get_sip_svc_version() to get SiP SVC version number to check if TF-A is newer or older and use the SMC format accordingly to handle backward compatibility. Used new SMC format for PM_QUERY_DATA API as more response values are required in it. Signed-off-by: Ronak Jain Signed-off-by: Jay Buddhabhatti Link: https://lore.kernel.org/r/20240920055501.2658642-1-ronak.jain@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 137 ++++++++++++++++++++++++++- include/linux/firmware/xlnx-zynqmp.h | 26 ++++- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 920aba92feee..5022bd717054 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -3,7 +3,7 @@ * Xilinx Zynq MPSoC Firmware layer * * Copyright (C) 2014-2022 Xilinx, Inc. - * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc. * * Michal Simek * Davorin Mista @@ -46,6 +46,7 @@ static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER); static u32 ioctl_features[FEATURE_PAYLOAD_SIZE]; static u32 query_features[FEATURE_PAYLOAD_SIZE]; +static u32 sip_svc_version; static struct platform_device *em_dev; /** @@ -151,6 +152,9 @@ static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...) ret_payload[1] = upper_32_bits(res.a0); ret_payload[2] = lower_32_bits(res.a1); ret_payload[3] = upper_32_bits(res.a1); + ret_payload[4] = lower_32_bits(res.a2); + ret_payload[5] = upper_32_bits(res.a2); + ret_payload[6] = lower_32_bits(res.a3); } return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); @@ -191,6 +195,9 @@ static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...) ret_payload[1] = upper_32_bits(res.a0); ret_payload[2] = lower_32_bits(res.a1); ret_payload[3] = upper_32_bits(res.a1); + ret_payload[4] = lower_32_bits(res.a2); + ret_payload[5] = upper_32_bits(res.a2); + ret_payload[6] = lower_32_bits(res.a3); } return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); @@ -331,6 +338,70 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) } EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported); +/** + * zynqmp_pm_invoke_fw_fn() - Invoke the system-level platform management layer + * caller function depending on the configuration + * @pm_api_id: Requested PM-API call + * @ret_payload: Returned value array + * @num_args: Number of arguments to requested PM-API call + * + * Invoke platform management function for SMC or HVC call, depending on + * configuration. + * Following SMC Calling Convention (SMCCC) for SMC64: + * Pm Function Identifier, + * PM_SIP_SVC + PASS_THROUGH_FW_CMD_ID = + * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) + * ((SMC_64) << FUNCID_CC_SHIFT) + * ((SIP_START) << FUNCID_OEN_SHIFT) + * (PASS_THROUGH_FW_CMD_ID)) + * + * PM_SIP_SVC - Registered ZynqMP SIP Service Call. + * PASS_THROUGH_FW_CMD_ID - Fixed SiP SVC call ID for FW specific calls. + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...) +{ + /* + * Added SIP service call Function Identifier + * Make sure to stay in x0 register + */ + u64 smc_arg[SMC_ARG_CNT_64]; + int ret, i; + va_list arg_list; + u32 args[SMC_ARG_CNT_32] = {0}; + u32 module_id; + + if (num_args > SMC_ARG_CNT_32) + return -EINVAL; + + va_start(arg_list, num_args); + + /* Check if feature is supported or not */ + ret = zynqmp_pm_feature(pm_api_id); + if (ret < 0) + return ret; + + for (i = 0; i < num_args; i++) + args[i] = va_arg(arg_list, u32); + + va_end(arg_list); + + module_id = FIELD_GET(PLM_MODULE_ID_MASK, pm_api_id); + + if (module_id == 0) + module_id = XPM_MODULE_ID; + + smc_arg[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID; + smc_arg[1] = ((u64)args[0] << 32U) | FIELD_PREP(PLM_MODULE_ID_MASK, module_id) | + (pm_api_id & API_ID_MASK); + for (i = 1; i < (SMC_ARG_CNT_64 - 1); i++) + smc_arg[i + 1] = ((u64)args[(i * 2)] << 32U) | args[(i * 2) - 1]; + + return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3], + smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]); +} + /** * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer * caller function depending on the configuration @@ -488,6 +559,35 @@ int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily) } EXPORT_SYMBOL_GPL(zynqmp_pm_get_family_info); +/** + * zynqmp_pm_get_sip_svc_version() - Get SiP service call version + * @version: Returned version value + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_get_sip_svc_version(u32 *version) +{ + struct arm_smccc_res res; + u64 args[SMC_ARG_CNT_64] = {0}; + + if (!version) + return -EINVAL; + + /* Check if SiP SVC version already verified */ + if (sip_svc_version > 0) { + *version = sip_svc_version; + return 0; + } + + args[0] = GET_SIP_SVC_VERSION; + + arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res); + + *version = ((lower_32_bits(res.a0) << 16U) | lower_32_bits(res.a1)); + + return zynqmp_pm_ret_code(XST_PM_SUCCESS); +} + /** * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version * @version: Returned version value @@ -552,10 +652,34 @@ static int get_set_conduit_method(struct device_node *np) */ int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) { - int ret; + int ret, i = 0; + u32 ret_payload[PAYLOAD_ARG_CNT] = {0}; - ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid, qdata.arg1, qdata.arg2, - qdata.arg3); + if (sip_svc_version >= SIP_SVC_PASSTHROUGH_VERSION) { + ret = zynqmp_pm_invoke_fw_fn(PM_QUERY_DATA, ret_payload, 4, + qdata.qid, qdata.arg1, + qdata.arg2, qdata.arg3); + /* To support backward compatibility */ + if (!ret && !ret_payload[0]) { + /* + * TF-A passes return status on 0th index but + * api to get clock name reads data from 0th + * index so pass data at 0th index instead of + * return status + */ + if (qdata.qid == PM_QID_CLOCK_GET_NAME || + qdata.qid == PM_QID_PINCTRL_GET_FUNCTION_NAME) + i = 1; + + for (; i < PAYLOAD_ARG_CNT; i++, out++) + *out = ret_payload[i]; + + return ret; + } + } + + ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid, + qdata.arg1, qdata.arg2, qdata.arg3); /* * For clock name query, all bytes in SMC response are clock name @@ -1890,6 +2014,11 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) if (ret) return ret; + /* Get SiP SVC version number */ + ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version); + if (ret) + return ret; + ret = do_feature_check_call(PM_FEATURE_CHECK); if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1)) feature_check_enabled = true; diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 5b938fc2adad..76d85ad82ec0 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -3,7 +3,7 @@ * Xilinx Zynq MPSoC Firmware layer * * Copyright (C) 2014-2021 Xilinx - * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc. + * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc. * * Michal Simek * Davorin Mista @@ -32,6 +32,19 @@ /* SMC SIP service Call Function Identifier Prefix */ #define PM_SIP_SVC 0xC2000000 +/* SMC function ID to get SiP SVC version */ +#define GET_SIP_SVC_VERSION (0x8200ff03U) + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR (0U) +#define SIP_SVC_VERSION_MINOR (2U) + +#define SIP_SVC_PASSTHROUGH_VERSION ((SIP_SVC_VERSION_MAJOR << 16) | \ + SIP_SVC_VERSION_MINOR) + +/* Fixed ID for FW specific APIs */ +#define PASS_THROUGH_FW_CMD_ID GENMASK(11, 0) + /* PM API versions */ #define PM_API_VERSION_1 1 #define PM_API_VERSION_2 2 @@ -51,6 +64,7 @@ #define API_ID_MASK GENMASK(7, 0) #define MODULE_ID_MASK GENMASK(11, 8) +#define PLM_MODULE_ID_MASK GENMASK(15, 8) /* Firmware feature check version mask */ #define FIRMWARE_VERSION_MASK 0xFFFFU @@ -62,7 +76,13 @@ #define GET_CALLBACK_DATA 0xa01 /* Number of 32bits values in payload */ -#define PAYLOAD_ARG_CNT 4U +#define PAYLOAD_ARG_CNT 7U + +/* Number of 64bits arguments for SMC call */ +#define SMC_ARG_CNT_64 8U + +/* Number of 32bits arguments for SMC call */ +#define SMC_ARG_CNT_32 13U /* Number of arguments for a callback */ #define CB_ARG_CNT 4 @@ -130,6 +150,7 @@ enum pm_module_id { PM_MODULE_ID = 0x0, + XPM_MODULE_ID = 0x2, XSEM_MODULE_ID = 0x3, TF_A_MODULE_ID = 0xa, }; @@ -537,6 +558,7 @@ struct zynqmp_pm_query_data { }; int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...); +int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...); #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE) int zynqmp_pm_get_api_version(u32 *version); From 55ed774d0130adaa4ef12aefeb8e0638011cbe43 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Thu, 19 Sep 2024 22:55:46 -0700 Subject: [PATCH 022/116] firmware: xilinx: fix feature check logic for TF-A specific APIs Currently, Linux is passing only API ID for feature of TF-A specific APIs but for feature check of TF-A specific APIs, TF-A is checking for Module ID + API ID as a result incorrect version is received for all TF-A specific APIs. So, fix feature check logic to pass valid arguments to get correct version. Signed-off-by: Ronak Jain Signed-off-by: Jay Buddhabhatti Link: https://lore.kernel.org/r/20240920055546.2658783-1-ronak.jain@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 5022bd717054..cdb565c41119 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -225,11 +225,14 @@ static int __do_feature_check_call(const u32 api_id, u32 *ret_payload) * Feature check of TF-A APIs is done in the TF-A layer and it expects for * MODULE_ID_MASK bits of SMC's arg[0] to be the same as PM_MODULE_ID. */ - if (module_id == TF_A_MODULE_ID) + if (module_id == TF_A_MODULE_ID) { module_id = PM_MODULE_ID; + smc_arg[1] = api_id; + } else { + smc_arg[1] = (api_id & API_ID_MASK); + } smc_arg[0] = PM_SIP_SVC | FIELD_PREP(MODULE_ID_MASK, module_id) | feature_check_api_id; - smc_arg[1] = (api_id & API_ID_MASK); ret = do_fw_call(ret_payload, 2, smc_arg[0], smc_arg[1]); if (ret) From 16a0a69244240cfa32c525c021c40f85e090557a Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Thu, 12 Sep 2024 11:41:47 +0800 Subject: [PATCH 023/116] soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq() If request_irq() fails in sr_late_init(), there is no need to enable the irq, and if it succeeds, disable_irq() after request_irq() still has a time gap in which interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable when request IRQ. Fixes: 1279ba5916f6 ("OMAP3+: SR: disable interrupt by default") Signed-off-by: Jinjie Ruan Link: https://lore.kernel.org/r/20240912034147.3014213-1-ruanjinjie@huawei.com Signed-off-by: Kevin Hilman --- drivers/soc/ti/smartreflex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index d6219060b616..38add2ab5613 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -202,10 +202,10 @@ static int sr_late_init(struct omap_sr *sr_info) if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq, - sr_interrupt, 0, sr_info->name, sr_info); + sr_interrupt, IRQF_NO_AUTOEN, + sr_info->name, sr_info); if (ret) goto error; - disable_irq(sr_info->irq); } return ret; From d8ee46b226ace0110f82233ba4c06ff1742ae443 Mon Sep 17 00:00:00 2001 From: Andrew Kreimer Date: Fri, 13 Sep 2024 12:37:05 +0300 Subject: [PATCH 024/116] thermal/ti-soc-thermal: Fix typos Fix typos in comments. Reported-by: Matthew Wilcox Signed-off-by: Andrew Kreimer Link: https://lore.kernel.org/r/20240913093713.12376-1-algonell@gmail.com Signed-off-by: Kevin Hilman --- drivers/thermal/ti-soc-thermal/dra752-bandgap.h | 4 ++-- drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h | 8 ++++---- drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h index d1b5b699cf23..1402b8c44c6b 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h @@ -74,7 +74,7 @@ /** * Register bitfields for DRA752 * - * All the macros bellow define the required bits for + * All the macros below define the required bits for * controlling temperature on DRA752. Bit defines are * grouped by register. */ @@ -125,7 +125,7 @@ /** * Temperature limits and thresholds for DRA752 * - * All the macros bellow are definitions for handling the + * All the macros below are definitions for handling the * ADC conversions and representation of temperature limits * and thresholds for DRA752. Definitions are grouped * by temperature domain. diff --git a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h index c63f439e01d6..3963f1badfc9 100644 --- a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h @@ -32,7 +32,7 @@ /** * Register and bit definitions for OMAP4430 * - * All the macros bellow define the required bits for + * All the macros below define the required bits for * controlling temperature on OMAP4430. Bit defines are * grouped by register. */ @@ -48,7 +48,7 @@ /** * Temperature limits and thresholds for OMAP4430 * - * All the macros bellow are definitions for handling the + * All the macros below are definitions for handling the * ADC conversions and representation of temperature limits * and thresholds for OMAP4430. */ @@ -102,7 +102,7 @@ /** * Register bitfields for OMAP4460 * - * All the macros bellow define the required bits for + * All the macros below define the required bits for * controlling temperature on OMAP4460. Bit defines are * grouped by register. */ @@ -135,7 +135,7 @@ /** * Temperature limits and thresholds for OMAP4460 * - * All the macros bellow are definitions for handling the + * All the macros below are definitions for handling the * ADC conversions and representation of temperature limits * and thresholds for OMAP4460. */ diff --git a/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h index 3880e667ea96..b70084b8013a 100644 --- a/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h @@ -56,7 +56,7 @@ /** * Register bitfields for OMAP5430 * - * All the macros bellow define the required bits for + * All the macros below define the required bits for * controlling temperature on OMAP5430. Bit defines are * grouped by register. */ @@ -101,7 +101,7 @@ /** * Temperature limits and thresholds for OMAP5430 * - * All the macros bellow are definitions for handling the + * All the macros below are definitions for handling the * ADC conversions and representation of temperature limits * and thresholds for OMAP5430. Definitions are grouped * by temperature domain. From c6fa2834afc6a6fe210415ec253a61e6eafdf651 Mon Sep 17 00:00:00 2001 From: Maya Matuszczyk Date: Thu, 19 Sep 2024 15:44:21 +0200 Subject: [PATCH 025/116] firmware: qcom: scm: Allow QSEECOM on Lenovo Yoga Slim 7x Allow QSEECOM on Lenovo Yoga Slim 7x, to enable accessing EFI variables. Signed-off-by: Maya Matuszczyk Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240919134421.112643-2-maccraft123mc@gmail.com [bjorn: Rewrote commit message] Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 10986cb11ec0..e11f3f325414 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1734,6 +1734,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "lenovo,flex-5g" }, { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, + { .compatible = "lenovo,yoga-slim7x" }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,sc8180x-primus" }, From 35791e5672a14a95cb45cb723566bae36de111c9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 21 Aug 2024 12:26:02 +0200 Subject: [PATCH 026/116] qcom: MAINTAINERS: add linux-msm IRC on OFTC Qualcomm SoC community gathers in #linux-msm channel on OFTC, so mention it in the maintainer entries. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240821102602.134216-1-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f..56bf6e5768a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2818,6 +2818,7 @@ F: arch/arm64/boot/dts/qcom/sdm845-cheza* ARM/QUALCOMM MAILING LIST L: linux-arm-msm@vger.kernel.org +C: irc://irc.oftc.net/linux-msm F: Documentation/devicetree/bindings/*/qcom* F: Documentation/devicetree/bindings/soc/qcom/ F: arch/arm/boot/dts/qcom/ @@ -2859,6 +2860,7 @@ M: Bjorn Andersson M: Konrad Dybcio L: linux-arm-msm@vger.kernel.org S: Maintained +C: irc://irc.oftc.net/linux-msm T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git F: Documentation/devicetree/bindings/arm/qcom-soc.yaml F: Documentation/devicetree/bindings/arm/qcom.yaml @@ -18308,6 +18310,7 @@ PIN CONTROLLER - QUALCOMM M: Bjorn Andersson L: linux-arm-msm@vger.kernel.org S: Maintained +C: irc://irc.oftc.net/linux-msm F: Documentation/devicetree/bindings/pinctrl/qcom,* F: drivers/pinctrl/qcom/ From 6187aaae71ec236163d96601b37216e110bf7554 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2024 18:48:52 +0200 Subject: [PATCH 027/116] soc: qcom: pbs: simplify locking with guard() Simplify error handling (less gotos) over locks with guard(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240822164853.231087-3-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-pbs.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/soc/qcom/qcom-pbs.c b/drivers/soc/qcom/qcom-pbs.c index 77a70d3d0d0b..1cc5d045f9dd 100644 --- a/drivers/soc/qcom/qcom-pbs.c +++ b/drivers/soc/qcom/qcom-pbs.c @@ -84,16 +84,16 @@ int qcom_pbs_trigger_event(struct pbs_dev *pbs, u8 bitmap) if (IS_ERR_OR_NULL(pbs)) return -EINVAL; - mutex_lock(&pbs->lock); + guard(mutex)(&pbs->lock); ret = regmap_read(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, &val); if (ret < 0) - goto out; + return ret; if (val == PBS_CLIENT_SCRATCH2_ERROR) { /* PBS error - clear SCRATCH2 register */ ret = regmap_write(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, 0); if (ret < 0) - goto out; + return ret; } for (bit_pos = 0; bit_pos < 8; bit_pos++) { @@ -104,37 +104,31 @@ int qcom_pbs_trigger_event(struct pbs_dev *pbs, u8 bitmap) ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, BIT(bit_pos), 0); if (ret < 0) - goto out_clear_scratch1; + break; /* Set the PBS sequence bit position */ ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, BIT(bit_pos), BIT(bit_pos)); if (ret < 0) - goto out_clear_scratch1; + break; /* Initiate the SW trigger */ ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_TRIG_CTL, PBS_CLIENT_SW_TRIG_BIT, PBS_CLIENT_SW_TRIG_BIT); if (ret < 0) - goto out_clear_scratch1; + break; ret = qcom_pbs_wait_for_ack(pbs, bit_pos); if (ret < 0) - goto out_clear_scratch1; + break; /* Clear the PBS sequence bit position */ regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, BIT(bit_pos), 0); regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, BIT(bit_pos), 0); } -out_clear_scratch1: /* Clear all the requested bitmap */ - ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, bitmap, 0); - -out: - mutex_unlock(&pbs->lock); - - return ret; + return regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, bitmap, 0); } EXPORT_SYMBOL_GPL(qcom_pbs_trigger_event); From cd3a3e60ebfe6f62ccf9d2164f6455e0b1ae1884 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2024 18:48:53 +0200 Subject: [PATCH 028/116] soc: qcom: smem_state: simplify locking with guard() Simplify error handling (less gotos) over locks with guard(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240822164853.231087-4-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem_state.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c index e848cc9a3cf8..d9bfac6c54fb 100644 --- a/drivers/soc/qcom/smem_state.c +++ b/drivers/soc/qcom/smem_state.c @@ -3,6 +3,7 @@ * Copyright (c) 2015, Sony Mobile Communications Inc. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -60,20 +61,15 @@ static struct qcom_smem_state *of_node_to_state(struct device_node *np) { struct qcom_smem_state *state; - mutex_lock(&list_lock); + guard(mutex)(&list_lock); list_for_each_entry(state, &smem_states, list) { if (state->of_node == np) { kref_get(&state->refcount); - goto unlock; + return state; } } - state = ERR_PTR(-EPROBE_DEFER); - -unlock: - mutex_unlock(&list_lock); - - return state; + return ERR_PTR(-EPROBE_DEFER); } /** From 99b2186b2c82c39b083de65c4c9598bcc0fc288c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20de=20Bretagne?= Date: Mon, 9 Sep 2024 00:35:02 +0200 Subject: [PATCH 029/116] firmware: qcom: scm: Allow QSEECOM on Microsoft Surface Pro 9 5G MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the SC8280XP-based Microsoft Surface Pro 9 5G to the allowlist. Reviewed-by: Konrad Dybcio Signed-off-by: Jérôme de Bretagne Reviewed-by: Maximilian Luz Link: https://lore.kernel.org/r/20240908223505.21011-3-jerome.debretagne@gmail.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index e11f3f325414..671b07ca04d2 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1735,6 +1735,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, { .compatible = "lenovo,yoga-slim7x" }, + { .compatible = "microsoft,arcata", }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,sc8180x-primus" }, From 78261cb08f06c93d362cab5c5034bf5899bc7552 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 30 Sep 2024 10:51:31 +0300 Subject: [PATCH 030/116] soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get() This loop is supposed to break if the frequency returned from clk_round_rate() is the same as on the previous iteration. However, that check doesn't make sense on the first iteration through the loop. It leads to reading before the start of these->clk_perf_tbl[] array. Fixes: eddac5af0654 ("soc: qcom: Add GENI based QUP Wrapper driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/8cd12678-f44a-4b16-a579-c8f11175ee8c@stanley.mountain Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 2e8f24d5da80..4cb959106efa 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -585,7 +585,8 @@ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl) for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) { freq = clk_round_rate(se->clk, freq + 1); - if (freq <= 0 || freq == se->clk_perf_tbl[i - 1]) + if (freq <= 0 || + (i > 0 && freq == se->clk_perf_tbl[i - 1])) break; se->clk_perf_tbl[i] = freq; } From 31a95fe0851afbbc697b6be96c8a81a01d65aa5f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 4 Oct 2024 20:47:29 -0700 Subject: [PATCH 031/116] soc: qcom: pd-mapper: Add QCM6490 PD maps The QCM6490 is a variant of SC7280, with the usual set of protection domains, and hence the need for a PD-mapper. In particular USB Type-C port management and battery management is pmic_glink based. Add an entry to the kernel, to avoid the need for userspace to provide this service. Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241004-qcm6490-pd-mapper-v1-1-d6f4bc3bffa3@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_pd_mapper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index c940f4da28ed..6e30f08761aa 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -540,6 +540,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,msm8996", .data = msm8996_domains, }, { .compatible = "qcom,msm8998", .data = msm8998_domains, }, { .compatible = "qcom,qcm2290", .data = qcm2290_domains, }, + { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, { .compatible = "qcom,sc7180", .data = sc7180_domains, }, { .compatible = "qcom,sc7280", .data = sc7280_domains, }, From 1cbe974f816cf40bc0437ebabe26b453331fb0d9 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:51 +0800 Subject: [PATCH 032/116] soc: hisilicon: kunpeng_hccs: Fix a PCC typo Fix a PCC typo. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index e882a61636ec..c4a57328f22a 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -144,7 +144,7 @@ static int hccs_register_pcc_channel(struct hccs_dev *hdev) pcc_chan = pcc_mbox_request_channel(cl, hdev->chan_id); if (IS_ERR(pcc_chan)) { - dev_err(dev, "PPC channel request failed.\n"); + dev_err(dev, "PCC channel request failed.\n"); rc = -ENODEV; goto out; } From 0c811bd2721d219bd104e0dc1fa76deee5e04ae4 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:52 +0800 Subject: [PATCH 033/116] soc: hisilicon: kunpeng_hccs: Return failure on having not die or port information Driver is unavailable if all die number or all port number obtained from firmware are zero. Although this is unlikely, just to harden the code. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index c4a57328f22a..6e88f597f267 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -451,6 +451,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev) struct device *dev = hdev->dev; struct hccs_chip_info *chip; struct hccs_die_info *die; + bool has_die_info = false; u8 i, j; int ret; @@ -459,6 +460,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev) if (!chip->die_num) continue; + has_die_info = true; chip->dies = devm_kzalloc(hdev->dev, chip->die_num * sizeof(struct hccs_die_info), GFP_KERNEL); @@ -480,7 +482,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev) } } - return 0; + return has_die_info ? 0 : -EINVAL; } static int hccs_get_bd_info(struct hccs_dev *hdev, u8 opcode, @@ -601,6 +603,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev) struct device *dev = hdev->dev; struct hccs_chip_info *chip; struct hccs_die_info *die; + bool has_port_info = false; u8 i, j; int ret; @@ -611,6 +614,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev) if (!die->port_num) continue; + has_port_info = true; die->ports = devm_kzalloc(dev, die->port_num * sizeof(struct hccs_port_info), GFP_KERNEL); @@ -629,7 +633,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev) } } - return 0; + return has_port_info ? 0 : -EINVAL; } static int hccs_get_hw_info(struct hccs_dev *hdev) From 3400c85f6400dc907d686d319faad25956ac4db1 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:53 +0800 Subject: [PATCH 034/116] soc: hisilicon: kunpeng_hccs: Add the check for base address and size of shared memory If the shmem_base_addr from PCCT is zero, hccs_register_pcc_channel will return success. And then driver will access to illegal address when send PCC command. In addition, the size of shared memory used for communication between driver and platform is fixed, namely 64 Bytes which is unchangeable. So add the verification for hardening code. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 6e88f597f267..6055e5091cbd 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -170,15 +170,21 @@ static int hccs_register_pcc_channel(struct hccs_dev *hdev) goto err_mbx_channel_free; } - if (pcc_chan->shmem_base_addr) { - cl_info->pcc_comm_addr = ioremap(pcc_chan->shmem_base_addr, - pcc_chan->shmem_size); - if (!cl_info->pcc_comm_addr) { - dev_err(dev, "Failed to ioremap PCC communication region for channel-%u.\n", - hdev->chan_id); - rc = -ENOMEM; - goto err_mbx_channel_free; - } + if (!pcc_chan->shmem_base_addr || + pcc_chan->shmem_size != HCCS_PCC_SHARE_MEM_BYTES) { + dev_err(dev, "The base address or size (%llu) of PCC communication region is invalid.\n", + pcc_chan->shmem_size); + rc = -EINVAL; + goto err_mbx_channel_free; + } + + cl_info->pcc_comm_addr = ioremap(pcc_chan->shmem_base_addr, + pcc_chan->shmem_size); + if (!cl_info->pcc_comm_addr) { + dev_err(dev, "Failed to ioremap PCC communication region for channel-%u.\n", + hdev->chan_id); + rc = -ENOMEM; + goto err_mbx_channel_free; } return 0; From b51878373a81bda3a790fd936507fd0643ef98b3 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:54 +0800 Subject: [PATCH 035/116] soc: hisilicon: kunpeng_hccs: Fix the 'lane_mode' field name in port info structure to 'max_lane_num' The lane mode of HCCS port is an information to user, and actually comes from the maximum lane number. But it is good and easy for driver to use the maximum lane number. So fix the 'lane_mode' field name in port info structure to 'max_lane_num'. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- drivers/soc/hisilicon/kunpeng_hccs.c | 4 ++-- drivers/soc/hisilicon/kunpeng_hccs.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 6055e5091cbd..418e4ee5d9e5 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -594,7 +594,7 @@ static int hccs_get_all_port_info_on_die(struct hccs_dev *hdev, port = &die->ports[i]; port->port_id = attrs[i].port_id; port->port_type = attrs[i].port_type; - port->lane_mode = attrs[i].lane_mode; + port->max_lane_num = attrs[i].max_lane_num; port->enable = attrs[i].enable; port->die = die; } @@ -839,7 +839,7 @@ static ssize_t lane_mode_show(struct kobject *kobj, struct kobj_attribute *attr, { const struct hccs_port_info *port = kobj_to_port_info(kobj); - return sysfs_emit(buf, "x%u\n", port->lane_mode); + return sysfs_emit(buf, "x%u\n", port->max_lane_num); } static struct kobj_attribute lane_mode_attr = __ATTR_RO(lane_mode); diff --git a/drivers/soc/hisilicon/kunpeng_hccs.h b/drivers/soc/hisilicon/kunpeng_hccs.h index c3adbc01b471..5e12a1e1474e 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.h +++ b/drivers/soc/hisilicon/kunpeng_hccs.h @@ -19,7 +19,7 @@ struct hccs_port_info { u8 port_id; u8 port_type; - u8 lane_mode; + u8 max_lane_num; bool enable; /* if the port is enabled */ struct kobject kobj; bool dir_created; @@ -113,7 +113,7 @@ struct hccs_die_info_rsp_data { struct hccs_port_attr { u8 port_id; u8 port_type; - u8 lane_mode; + u8 max_lane_num; u8 enable : 1; /* if the port is enabled */ u16 rsv[2]; }; From 23fe8112a23106e7dfc2b73fc52a60ea3eb64c20 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:55 +0800 Subject: [PATCH 036/116] soc: hisilicon: kunpeng_hccs: Add used HCCS types sysfs Kunpeng_hccs driver supports multiple HCCS types used on one platform at the same time. In this case, to find which HCCS types are used on the platform the user needs to scan the type attribute of all ports, which is unfriendly to the user. In addition, the aggregated information is also useful for global control like the low power feature. So add the sysfs to show all HCCS types used on the platform. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- .../sysfs-devices-platform-kunpeng_hccs | 8 ++ drivers/soc/hisilicon/kunpeng_hccs.c | 102 +++++++++++++++++- drivers/soc/hisilicon/kunpeng_hccs.h | 15 +++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs index 1666340820f7..d4c355e0e0bb 100644 --- a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs +++ b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs @@ -79,3 +79,11 @@ Description: indicates a lane. crc_err_cnt: (RO) CRC err count on this port. ============= ==== ============================================= + +What: /sys/devices/platform/HISI04Bx:00/used_types +Date: August 2024 +KernelVersion: 6.12 +Contact: Huisong Li +Description: + This interface is used to show all HCCS types used on the + platform, like, HCCS-v1, HCCS-v2 and so on. diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 418e4ee5d9e5..623e7b7ed39a 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -21,11 +21,14 @@ * - if all enabled ports are in linked * - if all linked ports are in full lane * - CRC error count sum + * + * - Retrieve all HCCS types used on the platform. */ #include #include #include #include +#include #include @@ -53,6 +56,15 @@ static struct hccs_chip_info *kobj_to_chip_info(struct kobject *k) return container_of(k, struct hccs_chip_info, kobj); } +static struct hccs_dev *device_kobj_to_hccs_dev(struct kobject *k) +{ + struct device *dev = container_of(k, struct device, kobj); + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + return platform_get_drvdata(pdev); +} + struct hccs_register_ctx { struct device *dev; u8 chan_id; @@ -670,6 +682,55 @@ static int hccs_get_hw_info(struct hccs_dev *hdev) return 0; } +static u16 hccs_calc_used_type_num(struct hccs_dev *hdev, + unsigned long *hccs_ver) +{ + struct hccs_chip_info *chip; + struct hccs_port_info *port; + struct hccs_die_info *die; + u16 used_type_num = 0; + u16 i, j, k; + + for (i = 0; i < hdev->chip_num; i++) { + chip = &hdev->chips[i]; + for (j = 0; j < chip->die_num; j++) { + die = &chip->dies[j]; + for (k = 0; k < die->port_num; k++) { + port = &die->ports[k]; + set_bit(port->port_type, hccs_ver); + } + } + } + + for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1) + used_type_num++; + + return used_type_num; +} + +static int hccs_init_type_name_maps(struct hccs_dev *hdev) +{ + DECLARE_BITMAP(hccs_ver, HCCS_IP_MAX + 1) = {}; + unsigned int i; + u16 idx = 0; + + hdev->used_type_num = hccs_calc_used_type_num(hdev, hccs_ver); + hdev->type_name_maps = devm_kcalloc(hdev->dev, hdev->used_type_num, + sizeof(struct hccs_type_name_map), + GFP_KERNEL); + if (!hdev->type_name_maps) + return -ENOMEM; + + for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1) { + hdev->type_name_maps[idx].type = i; + sprintf(hdev->type_name_maps[idx].name, + "%s%u", HCCS_IP_PREFIX, i); + idx++; + } + + return 0; +} + static int hccs_query_port_link_status(struct hccs_dev *hdev, const struct hccs_port_info *port, struct hccs_link_status *link_status) @@ -830,7 +891,7 @@ static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, { const struct hccs_port_info *port = kobj_to_port_info(kobj); - return sysfs_emit(buf, "HCCS-v%u\n", port->port_type); + return sysfs_emit(buf, "%s%u\n", HCCS_IP_PREFIX, port->port_type); } static struct kobj_attribute hccs_type_attr = __ATTR_RO(type); @@ -1134,6 +1195,33 @@ static const struct kobj_type hccs_chip_type = { .default_groups = hccs_chip_default_groups, }; + +static ssize_t used_types_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj); + int len = 0; + u16 i; + + for (i = 0; i < hdev->used_type_num - 1; i++) + len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name); + len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name); + + return len; +} +static struct kobj_attribute used_types_attr = + __ATTR(used_types, 0444, used_types_show, NULL); + +static void hccs_remove_misc_sysfs(struct hccs_dev *hdev) +{ + sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr); +} + +static int hccs_add_misc_sysfs(struct hccs_dev *hdev) +{ + return sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr); +} + static void hccs_remove_die_dir(struct hccs_die_info *die) { struct hccs_port_info *port; @@ -1168,6 +1256,8 @@ static void hccs_remove_topo_dirs(struct hccs_dev *hdev) for (i = 0; i < hdev->chip_num; i++) hccs_remove_chip_dir(&hdev->chips[i]); + + hccs_remove_misc_sysfs(hdev); } static int hccs_create_hccs_dir(struct hccs_dev *hdev, @@ -1263,6 +1353,12 @@ static int hccs_create_topo_dirs(struct hccs_dev *hdev) } } + ret = hccs_add_misc_sysfs(hdev); + if (ret) { + dev_err(hdev->dev, "create misc sysfs interface failed, ret = %d\n", ret); + goto err; + } + return 0; err: for (k = 0; k < id; k++) @@ -1313,6 +1409,10 @@ static int hccs_probe(struct platform_device *pdev) if (rc) goto unregister_pcc_chan; + rc = hccs_init_type_name_maps(hdev); + if (rc) + goto unregister_pcc_chan; + rc = hccs_create_topo_dirs(hdev); if (rc) goto unregister_pcc_chan; diff --git a/drivers/soc/hisilicon/kunpeng_hccs.h b/drivers/soc/hisilicon/kunpeng_hccs.h index 5e12a1e1474e..401df4694aec 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.h +++ b/drivers/soc/hisilicon/kunpeng_hccs.h @@ -10,6 +10,19 @@ * | P0 | P1 | P2 | P3 | P0 | P1 | P2 | P3 | P0 | P1 | P2 | P3 |P0 | P1 | P2 | P3 | */ +enum hccs_port_type { + HCCS_V1 = 1, + HCCS_V2, +}; + +#define HCCS_IP_PREFIX "HCCS-v" +#define HCCS_IP_MAX 255 +#define HCCS_NAME_MAX_LEN 9 +struct hccs_type_name_map { + u8 type; + char name[HCCS_NAME_MAX_LEN + 1]; +}; + /* * This value cannot be 255, otherwise the loop of the multi-BD communication * case cannot end. @@ -74,6 +87,8 @@ struct hccs_dev { u64 caps; u8 chip_num; struct hccs_chip_info *chips; + u16 used_type_num; + struct hccs_type_name_map *type_name_maps; u8 chan_id; struct mutex lock; struct hccs_mbox_client_info cl_info; From e3c289c0916e2a3d7859a0cf851ea242fa23ec1e Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Wed, 28 Aug 2024 18:49:56 +0800 Subject: [PATCH 037/116] soc: hisilicon: kunpeng_hccs: Support low power feature for the specified HCCS type Add the low power feature for the specified HCCS type by increasing and decreasing the used lane number of these HCCS ports on platform. Signed-off-by: Huisong Li Reviewed-by: Jonathan Cameron Signed-off-by: Wei Xu --- .../sysfs-devices-platform-kunpeng_hccs | 37 ++ drivers/soc/hisilicon/Kconfig | 7 +- drivers/soc/hisilicon/kunpeng_hccs.c | 376 +++++++++++++++++- drivers/soc/hisilicon/kunpeng_hccs.h | 14 + 4 files changed, 431 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs index d4c355e0e0bb..d1b3a95a5518 100644 --- a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs +++ b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs @@ -87,3 +87,40 @@ Contact: Huisong Li Description: This interface is used to show all HCCS types used on the platform, like, HCCS-v1, HCCS-v2 and so on. + +What: /sys/devices/platform/HISI04Bx:00/available_inc_dec_lane_types +What: /sys/devices/platform/HISI04Bx:00/dec_lane_of_type +What: /sys/devices/platform/HISI04Bx:00/inc_lane_of_type +Date: August 2024 +KernelVersion: 6.12 +Contact: Huisong Li +Description: + These interfaces under /sys/devices/platform/HISI04Bx/ are + used to support the low power consumption feature of some + HCCS types by changing the number of lanes used. The interfaces + changing the number of lanes used are 'dec_lane_of_type' and + 'inc_lane_of_type' which require root privileges. These + interfaces aren't exposed if no HCCS type on platform support + this feature. Please note that decreasing lane number is only + allowed if all the specified HCCS ports are not busy. + + The low power consumption interfaces are as follows: + + ============================= ==== ================================ + available_inc_dec_lane_types: (RO) available HCCS types (string) to + increase and decrease the number + of lane used, e.g. HCCS-v2. + dec_lane_of_type: (WO) input HCCS type supported + decreasing lane to decrease the + used lane number of all specified + HCCS type ports on platform to + the minimum. + You can query the 'cur_lane_num' + to get the minimum lane number + after executing successfully. + inc_lane_of_type: (WO) input HCCS type supported + increasing lane to increase the + used lane number of all specified + HCCS type ports on platform to + the full lane state. + ============================= ==== ================================ diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig index 4b0a099b28cc..6d7c244d2e78 100644 --- a/drivers/soc/hisilicon/Kconfig +++ b/drivers/soc/hisilicon/Kconfig @@ -13,9 +13,12 @@ config KUNPENG_HCCS interconnection bus protocol. The performance of application may be affected if some HCCS ports are not in full lane status, have a large number of CRC - errors and so on. + errors and so on. This may support for reducing system power + consumption if there are HCCS ports supported low power feature + on platform. Say M here if you want to include support for querying the - health status and port information of HCCS on Kunpeng SoC. + health status and port information of HCCS, or reducing system + power consumption on Kunpeng SoC. endmenu diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 623e7b7ed39a..0a45bbc8cb68 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -23,10 +23,18 @@ * - CRC error count sum * * - Retrieve all HCCS types used on the platform. + * + * - Support low power feature for all specified HCCS type ports, and + * provide the following interface: + * - query HCCS types supported increasing and decreasing lane number. + * - decrease lane number of all specified HCCS type ports on idle state. + * - increase lane number of all specified HCCS type ports. */ #include +#include #include #include +#include #include #include @@ -65,6 +73,33 @@ static struct hccs_dev *device_kobj_to_hccs_dev(struct kobject *k) return platform_get_drvdata(pdev); } +static char *hccs_port_type_to_name(struct hccs_dev *hdev, u8 type) +{ + u16 i; + + for (i = 0; i < hdev->used_type_num; i++) { + if (hdev->type_name_maps[i].type == type) + return hdev->type_name_maps[i].name; + } + + return NULL; +} + +static int hccs_name_to_port_type(struct hccs_dev *hdev, + const char *name, u8 *type) +{ + u16 i; + + for (i = 0; i < hdev->used_type_num; i++) { + if (strcmp(hdev->type_name_maps[i].name, name) == 0) { + *type = hdev->type_name_maps[i].type; + return 0; + } + } + + return -EINVAL; +} + struct hccs_register_ctx { struct device *dev; u8 chan_id; @@ -1195,6 +1230,306 @@ static const struct kobj_type hccs_chip_type = { .default_groups = hccs_chip_default_groups, }; +static int hccs_parse_pm_port_type(struct hccs_dev *hdev, const char *buf, + u8 *port_type) +{ + char hccs_name[HCCS_NAME_MAX_LEN + 1] = ""; + u8 type; + int ret; + + ret = sscanf(buf, "%" __stringify(HCCS_NAME_MAX_LEN) "s", hccs_name); + if (ret != 1) + return -EINVAL; + + ret = hccs_name_to_port_type(hdev, hccs_name, &type); + if (ret) { + dev_dbg(hdev->dev, "input invalid, please get the available types from 'used_types'.\n"); + return ret; + } + + if (type == HCCS_V2 && hdev->caps & HCCS_CAPS_HCCS_V2_PM) { + *port_type = type; + return 0; + } + + dev_dbg(hdev->dev, "%s doesn't support for increasing and decreasing lane.\n", + hccs_name); + + return -EOPNOTSUPP; +} + +static int hccs_query_port_idle_status(struct hccs_dev *hdev, + struct hccs_port_info *port, u8 *idle) +{ + const struct hccs_die_info *die = port->die; + const struct hccs_chip_info *chip = die->chip; + struct hccs_port_comm_req_param *req_param; + struct hccs_desc desc; + int ret; + + hccs_init_req_desc(&desc); + req_param = (struct hccs_port_comm_req_param *)desc.req.data; + req_param->chip_id = chip->chip_id; + req_param->die_id = die->die_id; + req_param->port_id = port->port_id; + ret = hccs_pcc_cmd_send(hdev, HCCS_GET_PORT_IDLE_STATUS, &desc); + if (ret) { + dev_err(hdev->dev, + "get port idle status failed, ret = %d.\n", ret); + return ret; + } + + *idle = *((u8 *)desc.rsp.data); + return 0; +} + +static int hccs_get_all_spec_port_idle_sta(struct hccs_dev *hdev, u8 port_type, + bool *all_idle) +{ + struct hccs_chip_info *chip; + struct hccs_port_info *port; + struct hccs_die_info *die; + int ret = 0; + u8 i, j, k; + u8 idle; + + *all_idle = false; + for (i = 0; i < hdev->chip_num; i++) { + chip = &hdev->chips[i]; + for (j = 0; j < chip->die_num; j++) { + die = &chip->dies[j]; + for (k = 0; k < die->port_num; k++) { + port = &die->ports[k]; + if (port->port_type != port_type) + continue; + ret = hccs_query_port_idle_status(hdev, port, + &idle); + if (ret) { + dev_err(hdev->dev, + "hccs%u on chip%u/die%u get idle status failed, ret = %d.\n", + k, i, j, ret); + return ret; + } else if (idle == 0) { + dev_info(hdev->dev, "hccs%u on chip%u/die%u is busy.\n", + k, i, j); + return 0; + } + } + } + } + *all_idle = true; + + return 0; +} + +static int hccs_get_all_spec_port_full_lane_sta(struct hccs_dev *hdev, + u8 port_type, bool *full_lane) +{ + struct hccs_link_status status = {0}; + struct hccs_chip_info *chip; + struct hccs_port_info *port; + struct hccs_die_info *die; + u8 i, j, k; + int ret; + + *full_lane = false; + for (i = 0; i < hdev->chip_num; i++) { + chip = &hdev->chips[i]; + for (j = 0; j < chip->die_num; j++) { + die = &chip->dies[j]; + for (k = 0; k < die->port_num; k++) { + port = &die->ports[k]; + if (port->port_type != port_type) + continue; + ret = hccs_query_port_link_status(hdev, port, + &status); + if (ret) + return ret; + if (status.lane_num != port->max_lane_num) + return 0; + } + } + } + *full_lane = true; + + return 0; +} + +static int hccs_prepare_inc_lane(struct hccs_dev *hdev, u8 type) +{ + struct hccs_inc_lane_req_param *req_param; + struct hccs_desc desc; + int ret; + + hccs_init_req_desc(&desc); + req_param = (struct hccs_inc_lane_req_param *)desc.req.data; + req_param->port_type = type; + req_param->opt_type = HCCS_PREPARE_INC_LANE; + ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc); + if (ret) + dev_err(hdev->dev, "prepare for increasing lane failed, ret = %d.\n", + ret); + + return ret; +} + +static int hccs_wait_serdes_adapt_completed(struct hccs_dev *hdev, u8 type) +{ +#define HCCS_MAX_WAIT_CNT_FOR_ADAPT 10 +#define HCCS_QUERY_ADAPT_RES_DELAY_MS 100 +#define HCCS_SERDES_ADAPT_OK 0 + + struct hccs_inc_lane_req_param *req_param; + u8 wait_cnt = HCCS_MAX_WAIT_CNT_FOR_ADAPT; + struct hccs_desc desc; + u8 adapt_res; + int ret; + + do { + hccs_init_req_desc(&desc); + req_param = (struct hccs_inc_lane_req_param *)desc.req.data; + req_param->port_type = type; + req_param->opt_type = HCCS_GET_ADAPT_RES; + ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc); + if (ret) { + dev_err(hdev->dev, "query adapting result failed, ret = %d.\n", + ret); + return ret; + } + adapt_res = *((u8 *)&desc.rsp.data); + if (adapt_res == HCCS_SERDES_ADAPT_OK) + return 0; + + msleep(HCCS_QUERY_ADAPT_RES_DELAY_MS); + } while (--wait_cnt); + + dev_err(hdev->dev, "wait for adapting completed timeout.\n"); + + return -ETIMEDOUT; +} + +static int hccs_start_hpcs_retraining(struct hccs_dev *hdev, u8 type) +{ + struct hccs_inc_lane_req_param *req_param; + struct hccs_desc desc; + int ret; + + hccs_init_req_desc(&desc); + req_param = (struct hccs_inc_lane_req_param *)desc.req.data; + req_param->port_type = type; + req_param->opt_type = HCCS_START_RETRAINING; + ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc); + if (ret) + dev_err(hdev->dev, "start hpcs retraining failed, ret = %d.\n", + ret); + + return ret; +} + +static int hccs_start_inc_lane(struct hccs_dev *hdev, u8 type) +{ + int ret; + + ret = hccs_prepare_inc_lane(hdev, type); + if (ret) + return ret; + + ret = hccs_wait_serdes_adapt_completed(hdev, type); + if (ret) + return ret; + + return hccs_start_hpcs_retraining(hdev, type); +} + +static int hccs_start_dec_lane(struct hccs_dev *hdev, u8 type) +{ + struct hccs_desc desc; + u8 *port_type; + int ret; + + hccs_init_req_desc(&desc); + port_type = (u8 *)desc.req.data; + *port_type = type; + ret = hccs_pcc_cmd_send(hdev, HCCS_PM_DEC_LANE, &desc); + if (ret) + dev_err(hdev->dev, "start to decrease lane failed, ret = %d.\n", + ret); + + return ret; +} + +static ssize_t dec_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj); + bool all_in_idle; + u8 port_type; + int ret; + + ret = hccs_parse_pm_port_type(hdev, buf, &port_type); + if (ret) + return ret; + + mutex_lock(&hdev->lock); + ret = hccs_get_all_spec_port_idle_sta(hdev, port_type, &all_in_idle); + if (ret) + goto out; + if (!all_in_idle) { + ret = -EBUSY; + dev_err(hdev->dev, "please don't decrese lanes on high load with %s, ret = %d.\n", + hccs_port_type_to_name(hdev, port_type), ret); + goto out; + } + + ret = hccs_start_dec_lane(hdev, port_type); +out: + mutex_unlock(&hdev->lock); + + return ret == 0 ? count : ret; +} +static struct kobj_attribute dec_lane_of_type_attr = + __ATTR(dec_lane_of_type, 0200, NULL, dec_lane_of_type_store); + +static ssize_t inc_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj); + bool full_lane; + u8 port_type; + int ret; + + ret = hccs_parse_pm_port_type(hdev, buf, &port_type); + if (ret) + return ret; + + mutex_lock(&hdev->lock); + ret = hccs_get_all_spec_port_full_lane_sta(hdev, port_type, &full_lane); + if (ret || full_lane) + goto out; + + ret = hccs_start_inc_lane(hdev, port_type); +out: + mutex_unlock(&hdev->lock); + return ret == 0 ? count : ret; +} +static struct kobj_attribute inc_lane_of_type_attr = + __ATTR(inc_lane_of_type, 0200, NULL, inc_lane_of_type_store); + +static ssize_t available_inc_dec_lane_types_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj); + + if (hdev->caps & HCCS_CAPS_HCCS_V2_PM) + return sysfs_emit(buf, "%s\n", + hccs_port_type_to_name(hdev, HCCS_V2)); + + return -EINVAL; +} +static struct kobj_attribute available_inc_dec_lane_types_attr = + __ATTR(available_inc_dec_lane_types, 0444, + available_inc_dec_lane_types_show, NULL); static ssize_t used_types_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -1215,11 +1550,50 @@ static struct kobj_attribute used_types_attr = static void hccs_remove_misc_sysfs(struct hccs_dev *hdev) { sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr); + + if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM)) + return; + + sysfs_remove_file(&hdev->dev->kobj, + &available_inc_dec_lane_types_attr.attr); + sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr); + sysfs_remove_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr); } static int hccs_add_misc_sysfs(struct hccs_dev *hdev) { - return sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr); + int ret; + + ret = sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr); + if (ret) + return ret; + + if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM)) + return 0; + + ret = sysfs_create_file(&hdev->dev->kobj, + &available_inc_dec_lane_types_attr.attr); + if (ret) + goto used_types_remove; + + ret = sysfs_create_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr); + if (ret) + goto inc_dec_lane_types_remove; + + ret = sysfs_create_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr); + if (ret) + goto dec_lane_of_type_remove; + + return 0; + +dec_lane_of_type_remove: + sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr); +inc_dec_lane_types_remove: + sysfs_remove_file(&hdev->dev->kobj, + &available_inc_dec_lane_types_attr.attr); +used_types_remove: + sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr); + return ret; } static void hccs_remove_die_dir(struct hccs_die_info *die) diff --git a/drivers/soc/hisilicon/kunpeng_hccs.h b/drivers/soc/hisilicon/kunpeng_hccs.h index 401df4694aec..dc267136919b 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.h +++ b/drivers/soc/hisilicon/kunpeng_hccs.h @@ -80,10 +80,13 @@ struct hccs_verspecific_data { bool has_txdone_irq; }; +#define HCCS_CAPS_HCCS_V2_PM BIT_ULL(0) + struct hccs_dev { struct device *dev; struct acpi_device *acpi_dev; const struct hccs_verspecific_data *verspec_data; + /* device capabilities from firmware, like HCCS_CAPS_xxx. */ u64 caps; u8 chip_num; struct hccs_chip_info *chips; @@ -106,6 +109,9 @@ enum hccs_subcmd_type { HCCS_GET_DIE_PORTS_LANE_STA, HCCS_GET_DIE_PORTS_LINK_STA, HCCS_GET_DIE_PORTS_CRC_ERR_CNT, + HCCS_GET_PORT_IDLE_STATUS, + HCCS_PM_DEC_LANE, + HCCS_PM_INC_LANE, HCCS_SUB_CMD_MAX = 255, }; @@ -149,6 +155,14 @@ struct hccs_port_comm_req_param { u8 port_id; }; +#define HCCS_PREPARE_INC_LANE 1 +#define HCCS_GET_ADAPT_RES 2 +#define HCCS_START_RETRAINING 3 +struct hccs_inc_lane_req_param { + u8 port_type; + u8 opt_type; +}; + #define HCCS_PORT_RESET 1 #define HCCS_PORT_SETUP 2 #define HCCS_PORT_CONFIG 3 From 1f1d847a657523e182df87f88158b607afe7d559 Mon Sep 17 00:00:00 2001 From: Esben Haabendal Date: Fri, 13 Sep 2024 10:13:12 +0200 Subject: [PATCH 038/116] arm64: defconfig: Update defconfig with now user-visible CONFIG_FSL_IFC With CONFIG_FSL_IFC now being user-visible, and thus changed from a select to depends in CONFIG_MTD_NAND_FSL_IFC, the dependencies needs to be selected in defconfig. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Esben Haabendal Link: https://lore.kernel.org/r/20240913-fsl-ifc-config-v4-1-ae4b012fc402@geanix.com Signed-off-by: Krzysztof Kozlowski --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5fdbfea7a5b2..730f303350c3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1472,6 +1472,7 @@ CONFIG_ARM_MEDIATEK_CCI_DEVFREQ=m CONFIG_EXTCON_PTN5150=m CONFIG_EXTCON_USB_GPIO=y CONFIG_EXTCON_USBC_CROS_EC=y +CONFIG_FSL_IFC=y CONFIG_RENESAS_RPCIF=m CONFIG_IIO=y CONFIG_EXYNOS_ADC=y From 304c250ba121f5c505be3fc13dec984016f3c032 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Thu, 3 Oct 2024 23:10:08 +0200 Subject: [PATCH 039/116] firmware: qcom: scm: Allow QSEECOM on Dell XPS 13 9345 Allow particular machine accessing eg. efivars. Signed-off-by: Aleksandrs Vinarskis Reviewed-by: Dmitry Baryshkov Tested-by: Stefan Schmidt Link: https://lore.kernel.org/r/20241003211139.9296-3-alex.vinarskis@gmail.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 671b07ca04d2..bf86df2a0639 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1731,6 +1731,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send); + any potential issues with this, only allow validated machines for now. */ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { + { .compatible = "dell,xps13-9345" }, { .compatible = "lenovo,flex-5g" }, { .compatible = "lenovo,thinkpad-t14s" }, { .compatible = "lenovo,thinkpad-x13s", }, From 9cc832d37799dbea950c4c8a34721b02b8b5a8ff Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 29 Sep 2024 20:49:16 +0200 Subject: [PATCH 040/116] soc: imx8m: Probe the SoC driver as platform driver With driver_async_probe=* on kernel command line, the following trace is produced because on i.MX8M Plus hardware because the soc-imx8m.c driver calls of_clk_get_by_name() which returns -EPROBE_DEFER because the clock driver is not yet probed. This was not detected during regular testing without driver_async_probe. Convert the SoC code to platform driver and instantiate a platform device in its current device_initcall() to probe the platform driver. Rework .soc_revision callback to always return valid error code and return SoC revision via parameter. This way, if anything in the .soc_revision callback return -EPROBE_DEFER, it gets propagated to .probe and the .probe will get retried later. " ------------[ cut here ]------------ WARNING: CPU: 1 PID: 1 at drivers/soc/imx/soc-imx8m.c:115 imx8mm_soc_revision+0xdc/0x180 CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.11.0-next-20240924-00002-g2062bb554dea #603 Hardware name: DH electronics i.MX8M Plus DHCOM Premium Developer Kit (3) (DT) pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : imx8mm_soc_revision+0xdc/0x180 lr : imx8mm_soc_revision+0xd0/0x180 sp : ffff8000821fbcc0 x29: ffff8000821fbce0 x28: 0000000000000000 x27: ffff800081810120 x26: ffff8000818a9970 x25: 0000000000000006 x24: 0000000000824311 x23: ffff8000817f42c8 x22: ffff0000df8be210 x21: fffffffffffffdfb x20: ffff800082780000 x19: 0000000000000001 x18: ffffffffffffffff x17: ffff800081fff418 x16: ffff8000823e1000 x15: ffff0000c03b65e8 x14: ffff0000c00051b0 x13: ffff800082790000 x12: 0000000000000801 x11: ffff80008278ffff x10: ffff80008209d3a6 x9 : ffff80008062e95c x8 : ffff8000821fb9a0 x7 : 0000000000000000 x6 : 00000000000080e3 x5 : ffff0000df8c03d8 x4 : 0000000000000000 x3 : 0000000000000000 x2 : 0000000000000000 x1 : fffffffffffffdfb x0 : fffffffffffffdfb Call trace: imx8mm_soc_revision+0xdc/0x180 imx8_soc_init+0xb0/0x1e0 do_one_initcall+0x94/0x1a8 kernel_init_freeable+0x240/0x2a8 kernel_init+0x28/0x140 ret_from_fork+0x10/0x20 ---[ end trace 0000000000000000 ]--- SoC: i.MX8MP revision 1.1 " Signed-off-by: Marek Vasut Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8m.c | 107 ++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 22 deletions(-) diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index fe111bae38c8..5ea8887828c0 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -30,7 +30,7 @@ struct imx8_soc_data { char *name; - u32 (*soc_revision)(void); + int (*soc_revision)(u32 *socrev); }; static u64 soc_uid; @@ -51,24 +51,29 @@ static u32 imx8mq_soc_revision_from_atf(void) static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; #endif -static u32 __init imx8mq_soc_revision(void) +static int imx8mq_soc_revision(u32 *socrev) { struct device_node *np; void __iomem *ocotp_base; u32 magic; u32 rev; struct clk *clk; + int ret; np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); if (!np) - return 0; + return -EINVAL; ocotp_base = of_iomap(np, 0); - WARN_ON(!ocotp_base); + if (!ocotp_base) { + ret = -EINVAL; + goto err_iomap; + } + clk = of_clk_get_by_name(np, NULL); if (IS_ERR(clk)) { - WARN_ON(IS_ERR(clk)); - return 0; + ret = PTR_ERR(clk); + goto err_clk; } clk_prepare_enable(clk); @@ -88,32 +93,45 @@ static u32 __init imx8mq_soc_revision(void) soc_uid <<= 32; soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + *socrev = rev; + clk_disable_unprepare(clk); clk_put(clk); iounmap(ocotp_base); of_node_put(np); - return rev; + return 0; + +err_clk: + iounmap(ocotp_base); +err_iomap: + of_node_put(np); + return ret; } -static void __init imx8mm_soc_uid(void) +static int imx8mm_soc_uid(void) { void __iomem *ocotp_base; struct device_node *np; struct clk *clk; + int ret = 0; u32 offset = of_machine_is_compatible("fsl,imx8mp") ? IMX8MP_OCOTP_UID_OFFSET : 0; np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); if (!np) - return; + return -EINVAL; ocotp_base = of_iomap(np, 0); - WARN_ON(!ocotp_base); + if (!ocotp_base) { + ret = -EINVAL; + goto err_iomap; + } + clk = of_clk_get_by_name(np, NULL); if (IS_ERR(clk)) { - WARN_ON(IS_ERR(clk)); - return; + ret = PTR_ERR(clk); + goto err_clk; } clk_prepare_enable(clk); @@ -124,31 +142,41 @@ static void __init imx8mm_soc_uid(void) clk_disable_unprepare(clk); clk_put(clk); + +err_clk: iounmap(ocotp_base); +err_iomap: of_node_put(np); + + return ret; } -static u32 __init imx8mm_soc_revision(void) +static int imx8mm_soc_revision(u32 *socrev) { struct device_node *np; void __iomem *anatop_base; - u32 rev; + int ret; np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); if (!np) - return 0; + return -EINVAL; anatop_base = of_iomap(np, 0); - WARN_ON(!anatop_base); + if (!anatop_base) { + ret = -EINVAL; + goto err_iomap; + } - rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); + *socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); iounmap(anatop_base); of_node_put(np); - imx8mm_soc_uid(); + return imx8mm_soc_uid(); - return rev; +err_iomap: + of_node_put(np); + return ret; } static const struct imx8_soc_data imx8mq_soc_data = { @@ -184,7 +212,7 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = { kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ "unknown" -static int __init imx8_soc_init(void) +static int imx8m_soc_probe(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; @@ -212,8 +240,11 @@ static int __init imx8_soc_init(void) data = id->data; if (data) { soc_dev_attr->soc_id = data->name; - if (data->soc_revision) - soc_rev = data->soc_revision(); + if (data->soc_revision) { + ret = data->soc_revision(&soc_rev); + if (ret) + goto free_soc; + } } soc_dev_attr->revision = imx8_revision(soc_rev); @@ -251,6 +282,38 @@ static int __init imx8_soc_init(void) kfree(soc_dev_attr); return ret; } + +static struct platform_driver imx8m_soc_driver = { + .probe = imx8m_soc_probe, + .driver = { + .name = "imx8m-soc", + }, +}; + +static int __init imx8_soc_init(void) +{ + struct platform_device *pdev; + int ret; + + /* No match means this is non-i.MX8M hardware, do nothing. */ + if (!of_match_node(imx8_soc_match, of_root)) + return 0; + + ret = platform_driver_register(&imx8m_soc_driver); + if (ret) { + pr_err("Failed to register imx8m-soc platform driver: %d\n", ret); + return ret; + } + + pdev = platform_device_register_simple("imx8m-soc", -1, NULL, 0); + if (IS_ERR(pdev)) { + pr_err("Failed to register imx8m-soc platform device: %ld\n", PTR_ERR(pdev)); + platform_driver_unregister(&imx8m_soc_driver); + return PTR_ERR(pdev); + } + + return 0; +} device_initcall(imx8_soc_init); MODULE_DESCRIPTION("NXP i.MX8M SoC driver"); MODULE_LICENSE("GPL"); From 9c1c02fe8d7f33c18547b79c41f3fa41ef7bae8f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 29 Sep 2024 20:49:17 +0200 Subject: [PATCH 041/116] soc: imx8m: Remove global soc_uid The static global soc_uid is only ever used as kasprintf() parameter in imx8m_soc_probe(). Pass pointer to local u64 variable to .soc_revision() callback instead and let the .soc_revision() callback fill in the content. Remove the unnecessary static global variable. Signed-off-by: Marek Vasut Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8m.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index 5ea8887828c0..966593320e28 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -30,11 +30,9 @@ struct imx8_soc_data { char *name; - int (*soc_revision)(u32 *socrev); + int (*soc_revision)(u32 *socrev, u64 *socuid); }; -static u64 soc_uid; - #ifdef CONFIG_HAVE_ARM_SMCCC static u32 imx8mq_soc_revision_from_atf(void) { @@ -51,7 +49,7 @@ static u32 imx8mq_soc_revision_from_atf(void) static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; #endif -static int imx8mq_soc_revision(u32 *socrev) +static int imx8mq_soc_revision(u32 *socrev, u64 *socuid) { struct device_node *np; void __iomem *ocotp_base; @@ -89,9 +87,9 @@ static int imx8mq_soc_revision(u32 *socrev) rev = REV_B1; } - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + *socuid <<= 32; + *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); *socrev = rev; @@ -109,7 +107,7 @@ static int imx8mq_soc_revision(u32 *socrev) return ret; } -static int imx8mm_soc_uid(void) +static int imx8mm_soc_uid(u64 *socuid) { void __iomem *ocotp_base; struct device_node *np; @@ -136,9 +134,9 @@ static int imx8mm_soc_uid(void) clk_prepare_enable(clk); - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset); + *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset); + *socuid <<= 32; + *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset); clk_disable_unprepare(clk); clk_put(clk); @@ -151,7 +149,7 @@ static int imx8mm_soc_uid(void) return ret; } -static int imx8mm_soc_revision(u32 *socrev) +static int imx8mm_soc_revision(u32 *socrev, u64 *socuid) { struct device_node *np; void __iomem *anatop_base; @@ -172,7 +170,7 @@ static int imx8mm_soc_revision(u32 *socrev) iounmap(anatop_base); of_node_put(np); - return imx8mm_soc_uid(); + return imx8mm_soc_uid(socuid); err_iomap: of_node_put(np); @@ -215,10 +213,11 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = { static int imx8m_soc_probe(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; - struct soc_device *soc_dev; - const struct of_device_id *id; - u32 soc_rev = 0; const struct imx8_soc_data *data; + const struct of_device_id *id; + struct soc_device *soc_dev; + u32 soc_rev = 0; + u64 soc_uid = 0; int ret; soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); @@ -241,7 +240,7 @@ static int imx8m_soc_probe(struct platform_device *pdev) if (data) { soc_dev_attr->soc_id = data->name; if (data->soc_revision) { - ret = data->soc_revision(&soc_rev); + ret = data->soc_revision(&soc_rev, &soc_uid); if (ret) goto free_soc; } From 22b03a4e957e462b380a982759ccf0f6554735d3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 29 Sep 2024 20:49:18 +0200 Subject: [PATCH 042/116] soc: imx8m: Use devm_* to simplify probe failure handling Use device managed functions to simplify handling of failures during probe. Remove fail paths which are no longer necessary. Signed-off-by: Marek Vasut Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8m.c | 92 ++++++++++++------------------------- 1 file changed, 29 insertions(+), 63 deletions(-) diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index 966593320e28..8ac7658e3d52 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -51,22 +51,20 @@ static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; static int imx8mq_soc_revision(u32 *socrev, u64 *socuid) { - struct device_node *np; + struct device_node *np __free(device_node) = + of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); void __iomem *ocotp_base; u32 magic; u32 rev; struct clk *clk; int ret; - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); if (!np) return -EINVAL; ocotp_base = of_iomap(np, 0); - if (!ocotp_base) { - ret = -EINVAL; - goto err_iomap; - } + if (!ocotp_base) + return -EINVAL; clk = of_clk_get_by_name(np, NULL); if (IS_ERR(clk)) { @@ -96,35 +94,30 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid) clk_disable_unprepare(clk); clk_put(clk); iounmap(ocotp_base); - of_node_put(np); return 0; err_clk: iounmap(ocotp_base); -err_iomap: - of_node_put(np); return ret; } static int imx8mm_soc_uid(u64 *socuid) { + struct device_node *np __free(device_node) = + of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); void __iomem *ocotp_base; - struct device_node *np; struct clk *clk; int ret = 0; u32 offset = of_machine_is_compatible("fsl,imx8mp") ? IMX8MP_OCOTP_UID_OFFSET : 0; - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); if (!np) return -EINVAL; ocotp_base = of_iomap(np, 0); - if (!ocotp_base) { - ret = -EINVAL; - goto err_iomap; - } + if (!ocotp_base) + return -EINVAL; clk = of_clk_get_by_name(np, NULL); if (IS_ERR(clk)) { @@ -143,38 +136,27 @@ static int imx8mm_soc_uid(u64 *socuid) err_clk: iounmap(ocotp_base); -err_iomap: - of_node_put(np); - return ret; } static int imx8mm_soc_revision(u32 *socrev, u64 *socuid) { - struct device_node *np; + struct device_node *np __free(device_node) = + of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); void __iomem *anatop_base; - int ret; - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); if (!np) return -EINVAL; anatop_base = of_iomap(np, 0); - if (!anatop_base) { - ret = -EINVAL; - goto err_iomap; - } + if (!anatop_base) + return -EINVAL; *socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); iounmap(anatop_base); - of_node_put(np); return imx8mm_soc_uid(socuid); - -err_iomap: - of_node_put(np); - return ret; } static const struct imx8_soc_data imx8mq_soc_data = { @@ -205,22 +187,23 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = { { } }; -#define imx8_revision(soc_rev) \ - soc_rev ? \ - kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ +#define imx8_revision(dev, soc_rev) \ + (soc_rev) ? \ + devm_kasprintf((dev), GFP_KERNEL, "%d.%d", ((soc_rev) >> 4) & 0xf, (soc_rev) & 0xf) : \ "unknown" static int imx8m_soc_probe(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; const struct imx8_soc_data *data; + struct device *dev = &pdev->dev; const struct of_device_id *id; struct soc_device *soc_dev; u32 soc_rev = 0; u64 soc_uid = 0; int ret; - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) return -ENOMEM; @@ -228,13 +211,11 @@ static int imx8m_soc_probe(struct platform_device *pdev) ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine); if (ret) - goto free_soc; + return ret; id = of_match_node(imx8_soc_match, of_root); - if (!id) { - ret = -ENODEV; - goto free_soc; - } + if (!id) + return -ENODEV; data = id->data; if (data) { @@ -242,27 +223,21 @@ static int imx8m_soc_probe(struct platform_device *pdev) if (data->soc_revision) { ret = data->soc_revision(&soc_rev, &soc_uid); if (ret) - goto free_soc; + return ret; } } - soc_dev_attr->revision = imx8_revision(soc_rev); - if (!soc_dev_attr->revision) { - ret = -ENOMEM; - goto free_soc; - } + soc_dev_attr->revision = imx8_revision(dev, soc_rev); + if (!soc_dev_attr->revision) + return -ENOMEM; - soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); - if (!soc_dev_attr->serial_number) { - ret = -ENOMEM; - goto free_rev; - } + soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid); + if (!soc_dev_attr->serial_number) + return -ENOMEM; soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - ret = PTR_ERR(soc_dev); - goto free_serial_number; - } + if (IS_ERR(soc_dev)) + return PTR_ERR(soc_dev); pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id, soc_dev_attr->revision); @@ -271,15 +246,6 @@ static int imx8m_soc_probe(struct platform_device *pdev) platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); return 0; - -free_serial_number: - kfree(soc_dev_attr->serial_number); -free_rev: - if (strcmp(soc_dev_attr->revision, "unknown")) - kfree(soc_dev_attr->revision); -free_soc: - kfree(soc_dev_attr); - return ret; } static struct platform_driver imx8m_soc_driver = { From e8b259e3771bcf290f7229b1d45acd4d063a4815 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Mon, 10 Jun 2024 10:57:31 +0200 Subject: [PATCH 043/116] dt-bindings: soc: mediatek: Add DVFSRC bindings for MT8183 and MT8195 Add bindings for the MediaTek Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC), a hardware module used to collect all the requests from both software and the various remote processors embedded into the SoC and decide about a minimum operating voltage and a minimum DRAM frequency to fulfill those requests in an effort to provide the best achievable performance per watt. This hardware IP is capable of transparently performing direct register R/W on all of the DVFSRC-controlled regulators and SoC bandwidth knobs. Reviewed-by: Rob Herring (Arm) Signed-off-by: AngeloGioacchino Del Regno --- .../soc/mediatek/mediatek,mt8183-dvfsrc.yaml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml new file mode 100644 index 000000000000..1ad5b61b249f --- /dev/null +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/mediatek/mediatek,mt8183-dvfsrc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC) + +description: + The Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC) is a + Hardware module used to collect all the requests from both software and the + various remote processors embedded into the SoC and decide about a minimum + operating voltage and a minimum DRAM frequency to fulfill those requests in + an effort to provide the best achievable performance per watt. + This hardware IP is capable of transparently performing direct register R/W + on all of the DVFSRC-controlled regulators and SoC bandwidth knobs. + +maintainers: + - AngeloGioacchino Del Regno + - Henry Chen + +properties: + compatible: + oneOf: + - enum: + - mediatek,mt8183-dvfsrc + - mediatek,mt8195-dvfsrc + - items: + - const: mediatek,mt8192-dvfsrc + - const: mediatek,mt8195-dvfsrc + + reg: + maxItems: 1 + description: DVFSRC common register address and length. + + regulators: + type: object + $ref: /schemas/regulator/mediatek,mt6873-dvfsrc-regulator.yaml# + + interconnect: + type: object + $ref: /schemas/interconnect/mediatek,mt8183-emi.yaml# + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + system-controller@10012000 { + compatible = "mediatek,mt8195-dvfsrc"; + reg = <0 0x10012000 0 0x1000>; + + regulators { + compatible = "mediatek,mt8195-dvfsrc-regulator"; + + dvfsrc_vcore: dvfsrc-vcore { + regulator-name = "dvfsrc-vcore"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + }; + + dvfsrc_vscp: dvfsrc-vscp { + regulator-name = "dvfsrc-vscp"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + }; + }; + + emi_icc: interconnect { + compatible = "mediatek,mt8195-emi"; + #interconnect-cells = <1>; + }; + }; + }; From 192514ae05687a60ac230569b2a215fb2d3b8d90 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Mon, 10 Jun 2024 10:57:32 +0200 Subject: [PATCH 044/116] soc: mediatek: Add MediaTek DVFS Resource Collector (DVFSRC) driver The Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC) is a Hardware module used to collect all the requests from both software and the various remote processors embedded into the SoC and decide about a minimum operating voltage and a minimum DRAM frequency to fulfill those requests in an effort to provide the best achievable performance per watt. This hardware IP is capable of transparently performing direct register R/W on all of the DVFSRC-controlled regulators and SoC bandwidth knobs. This driver includes support for MT8183, MT8192 and MT8195. Co-Developed-by: Dawei Chien [Angelo: Partial refactoring and cleanups] Reviewed-by: Georgi Djakov Link: https://lore.kernel.org/r/20240610085735.147134-5-angelogioacchino.delregno@collabora.com Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/Kconfig | 11 + drivers/soc/mediatek/Makefile | 1 + drivers/soc/mediatek/mtk-dvfsrc.c | 545 +++++++++++++++++++++++ include/linux/soc/mediatek/dvfsrc.h | 36 ++ include/linux/soc/mediatek/mtk_sip_svc.h | 3 + 5 files changed, 596 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-dvfsrc.c create mode 100644 include/linux/soc/mediatek/dvfsrc.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index 1b7afb19ccd6..d7293977f06e 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -26,6 +26,17 @@ config MTK_DEVAPC The violation information is logged for further analysis or countermeasures. +config MTK_DVFSRC + tristate "MediaTek DVFSRC Support" + depends on ARCH_MEDIATEK + help + Say yes here to add support for the MediaTek Dynamic Voltage + and Frequency Scaling Resource Collector (DVFSRC): a HW + IP found on many MediaTek SoCs, which is responsible for + collecting DVFS requests from various SoC IPs, other than + software, and performing bandwidth scaling to provide the + best achievable performance-per-watt. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 6830512848fd..0665573e3c4b 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o +obj-$(CONFIG_MTK_DVFSRC) += mtk-dvfsrc.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_REGULATOR_COUPLER) += mtk-regulator-coupler.o diff --git a/drivers/soc/mediatek/mtk-dvfsrc.c b/drivers/soc/mediatek/mtk-dvfsrc.c new file mode 100644 index 000000000000..83bf46fdcf2d --- /dev/null +++ b/drivers/soc/mediatek/mtk-dvfsrc.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* DVFSRC_LEVEL */ +#define DVFSRC_V1_LEVEL_TARGET_LEVEL GENMASK(15, 0) +#define DVFSRC_TGT_LEVEL_IDLE 0x00 +#define DVFSRC_V1_LEVEL_CURRENT_LEVEL GENMASK(31, 16) + +/* DVFSRC_SW_REQ, DVFSRC_SW_REQ2 */ +#define DVFSRC_V1_SW_REQ2_DRAM_LEVEL GENMASK(1, 0) +#define DVFSRC_V1_SW_REQ2_VCORE_LEVEL GENMASK(3, 2) + +#define DVFSRC_V2_SW_REQ_DRAM_LEVEL GENMASK(3, 0) +#define DVFSRC_V2_SW_REQ_VCORE_LEVEL GENMASK(6, 4) + +/* DVFSRC_VCORE */ +#define DVFSRC_V2_VCORE_REQ_VSCP_LEVEL GENMASK(14, 12) + +#define DVFSRC_POLL_TIMEOUT_US 1000 +#define STARTUP_TIME_US 1 + +#define MTK_SIP_DVFSRC_INIT 0x0 +#define MTK_SIP_DVFSRC_START 0x1 + +struct dvfsrc_bw_constraints { + u16 max_dram_nom_bw; + u16 max_dram_peak_bw; + u16 max_dram_hrt_bw; +}; + +struct dvfsrc_opp { + u32 vcore_opp; + u32 dram_opp; +}; + +struct dvfsrc_opp_desc { + const struct dvfsrc_opp *opps; + u32 num_opp; +}; + +struct dvfsrc_soc_data; +struct mtk_dvfsrc { + struct device *dev; + struct platform_device *icc; + struct platform_device *regulator; + const struct dvfsrc_soc_data *dvd; + const struct dvfsrc_opp_desc *curr_opps; + void __iomem *regs; + int dram_type; +}; + +struct dvfsrc_soc_data { + const int *regs; + const struct dvfsrc_opp_desc *opps_desc; + u32 (*get_target_level)(struct mtk_dvfsrc *dvfsrc); + u32 (*get_current_level)(struct mtk_dvfsrc *dvfsrc); + u32 (*get_vcore_level)(struct mtk_dvfsrc *dvfsrc); + u32 (*get_vscp_level)(struct mtk_dvfsrc *dvfsrc); + void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); + void (*set_dram_peak_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); + void (*set_dram_hrt_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw); + void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); + void (*set_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level); + void (*set_vscp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); + int (*wait_for_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level); + int (*wait_for_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level); + const struct dvfsrc_bw_constraints *bw_constraints; +}; + +static u32 dvfsrc_readl(struct mtk_dvfsrc *dvfs, u32 offset) +{ + return readl(dvfs->regs + dvfs->dvd->regs[offset]); +} + +static void dvfsrc_writel(struct mtk_dvfsrc *dvfs, u32 offset, u32 val) +{ + writel(val, dvfs->regs + dvfs->dvd->regs[offset]); +} + +enum dvfsrc_regs { + DVFSRC_SW_REQ, + DVFSRC_SW_REQ2, + DVFSRC_LEVEL, + DVFSRC_TARGET_LEVEL, + DVFSRC_SW_BW, + DVFSRC_SW_PEAK_BW, + DVFSRC_SW_HRT_BW, + DVFSRC_VCORE, + DVFSRC_REGS_MAX, +}; + +static const int dvfsrc_mt8183_regs[] = { + [DVFSRC_SW_REQ] = 0x4, + [DVFSRC_SW_REQ2] = 0x8, + [DVFSRC_LEVEL] = 0xDC, + [DVFSRC_SW_BW] = 0x160, +}; + +static const int dvfsrc_mt8195_regs[] = { + [DVFSRC_SW_REQ] = 0xc, + [DVFSRC_VCORE] = 0x6c, + [DVFSRC_SW_PEAK_BW] = 0x278, + [DVFSRC_SW_BW] = 0x26c, + [DVFSRC_SW_HRT_BW] = 0x290, + [DVFSRC_LEVEL] = 0xd44, + [DVFSRC_TARGET_LEVEL] = 0xd48, +}; + +static const struct dvfsrc_opp *dvfsrc_get_current_opp(struct mtk_dvfsrc *dvfsrc) +{ + u32 level = dvfsrc->dvd->get_current_level(dvfsrc); + + return &dvfsrc->curr_opps->opps[level]; +} + +static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc) +{ + if (!dvfsrc->dvd->get_target_level) + return true; + + return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_TGT_LEVEL_IDLE; +} + +static int dvfsrc_wait_for_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + const struct dvfsrc_opp *curr; + + return readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, + curr->vcore_opp >= level, STARTUP_TIME_US, + DVFSRC_POLL_TIMEOUT_US); +} + +static int dvfsrc_wait_for_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + const struct dvfsrc_opp *target, *curr; + int ret; + + target = &dvfsrc->curr_opps->opps[level]; + ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, + curr->dram_opp >= target->dram_opp && + curr->vcore_opp >= target->vcore_opp, + STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); + if (ret < 0) { + dev_warn(dvfsrc->dev, + "timeout! target OPP: %u, dram: %d, vcore: %d\n", level, + curr->dram_opp, curr->vcore_opp); + return ret; + } + + return 0; +} + +static int dvfsrc_wait_for_opp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + const struct dvfsrc_opp *target, *curr; + int ret; + + target = &dvfsrc->curr_opps->opps[level]; + ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr, + curr->dram_opp >= target->dram_opp && + curr->vcore_opp >= target->vcore_opp, + STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); + if (ret < 0) { + dev_warn(dvfsrc->dev, + "timeout! target OPP: %u, dram: %d\n", level, curr->dram_opp); + return ret; + } + + return 0; +} + +static u32 dvfsrc_get_target_level_v1(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); + + return FIELD_GET(DVFSRC_V1_LEVEL_TARGET_LEVEL, val); +} + +static u32 dvfsrc_get_current_level_v1(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); + u32 current_level = FIELD_GET(DVFSRC_V1_LEVEL_CURRENT_LEVEL, val); + + return ffs(current_level) - 1; +} + +static u32 dvfsrc_get_target_level_v2(struct mtk_dvfsrc *dvfsrc) +{ + return dvfsrc_readl(dvfsrc, DVFSRC_TARGET_LEVEL); +} + +static u32 dvfsrc_get_current_level_v2(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL); + u32 level = ffs(val); + + /* Valid levels */ + if (level < dvfsrc->curr_opps->num_opp) + return dvfsrc->curr_opps->num_opp - level; + + /* Zero for level 0 or invalid level */ + return 0; +} + +static u32 dvfsrc_get_vcore_level_v1(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2); + + return FIELD_GET(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, val); +} + +static void dvfsrc_set_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2); + + val &= ~DVFSRC_V1_SW_REQ2_VCORE_LEVEL; + val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, level); + + dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ2, val); +} + +static u32 dvfsrc_get_vcore_level_v2(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ); + + return FIELD_GET(DVFSRC_V2_SW_REQ_VCORE_LEVEL, val); +} + +static void dvfsrc_set_vcore_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ); + + val &= ~DVFSRC_V2_SW_REQ_VCORE_LEVEL; + val |= FIELD_PREP(DVFSRC_V2_SW_REQ_VCORE_LEVEL, level); + + dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); +} + +static u32 dvfsrc_get_vscp_level_v2(struct mtk_dvfsrc *dvfsrc) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE); + + return FIELD_GET(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, val); +} + +static void dvfsrc_set_vscp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE); + + val &= ~DVFSRC_V2_VCORE_REQ_VSCP_LEVEL; + val |= FIELD_PREP(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, level); + + dvfsrc_writel(dvfsrc, DVFSRC_VCORE, val); +} + +static void __dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u32 reg, + u16 max_bw, u16 min_bw, u64 bw) +{ + u32 new_bw = (u32)div_u64(bw, 100 * 1000); + + /* If bw constraints (in mbps) are defined make sure to respect them */ + if (max_bw) + new_bw = min(new_bw, max_bw); + if (min_bw && new_bw > 0) + new_bw = max(new_bw, min_bw); + + dvfsrc_writel(dvfsrc, reg, new_bw); +} + +static void dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) +{ + u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_nom_bw; + + __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_BW, max_bw, 0, bw); +}; + +static void dvfsrc_set_dram_peak_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) +{ + u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_peak_bw; + + __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_PEAK_BW, max_bw, 0, bw); +} + +static void dvfsrc_set_dram_hrt_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw) +{ + u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_hrt_bw; + + __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_HRT_BW, max_bw, 0, bw); +} + +static void dvfsrc_set_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level) +{ + const struct dvfsrc_opp *opp = &dvfsrc->curr_opps->opps[level]; + u32 val; + + /* Translate Pstate to DVFSRC level and set it to DVFSRC HW */ + val = FIELD_PREP(DVFSRC_V1_SW_REQ2_DRAM_LEVEL, opp->dram_opp); + val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, opp->vcore_opp); + + dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n", opp->vcore_opp, opp->dram_opp); + dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val); +} + +int mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data) +{ + struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev); + bool state; + int ret; + + dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data); + + switch (cmd) { + case MTK_DVFSRC_CMD_BW: + dvfsrc->dvd->set_dram_bw(dvfsrc, data); + return 0; + case MTK_DVFSRC_CMD_HRT_BW: + if (dvfsrc->dvd->set_dram_hrt_bw) + dvfsrc->dvd->set_dram_hrt_bw(dvfsrc, data); + return 0; + case MTK_DVFSRC_CMD_PEAK_BW: + if (dvfsrc->dvd->set_dram_peak_bw) + dvfsrc->dvd->set_dram_peak_bw(dvfsrc, data); + return 0; + case MTK_DVFSRC_CMD_OPP: + if (!dvfsrc->dvd->set_opp_level) + return 0; + + dvfsrc->dvd->set_opp_level(dvfsrc, data); + break; + case MTK_DVFSRC_CMD_VCORE_LEVEL: + dvfsrc->dvd->set_vcore_level(dvfsrc, data); + break; + case MTK_DVFSRC_CMD_VSCP_LEVEL: + if (!dvfsrc->dvd->set_vscp_level) + return 0; + + dvfsrc->dvd->set_vscp_level(dvfsrc, data); + break; + default: + dev_err(dvfsrc->dev, "unknown command: %d\n", cmd); + return -EOPNOTSUPP; + } + + /* DVFSRC needs at least 2T(~196ns) to handle a request */ + udelay(STARTUP_TIME_US); + + ret = readx_poll_timeout_atomic(dvfsrc_is_idle, dvfsrc, state, state, + STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US); + if (ret < 0) { + dev_warn(dvfsrc->dev, + "%d: idle timeout, data: %llu, last: %d -> %d\n", cmd, data, + dvfsrc->dvd->get_current_level(dvfsrc), + dvfsrc->dvd->get_target_level(dvfsrc)); + return ret; + } + + if (cmd == MTK_DVFSRC_CMD_OPP) + ret = dvfsrc->dvd->wait_for_opp_level(dvfsrc, data); + else + ret = dvfsrc->dvd->wait_for_vcore_level(dvfsrc, data); + + if (ret < 0) { + dev_warn(dvfsrc->dev, + "%d: wait timeout, data: %llu, last: %d -> %d\n", + cmd, data, + dvfsrc->dvd->get_current_level(dvfsrc), + dvfsrc->dvd->get_target_level(dvfsrc)); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(mtk_dvfsrc_send_request); + +int mtk_dvfsrc_query_info(const struct device *dev, u32 cmd, int *data) +{ + struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev); + + switch (cmd) { + case MTK_DVFSRC_CMD_VCORE_LEVEL: + *data = dvfsrc->dvd->get_vcore_level(dvfsrc); + break; + case MTK_DVFSRC_CMD_VSCP_LEVEL: + *data = dvfsrc->dvd->get_vscp_level(dvfsrc); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} +EXPORT_SYMBOL(mtk_dvfsrc_query_info); + +static int mtk_dvfsrc_probe(struct platform_device *pdev) +{ + struct arm_smccc_res ares; + struct mtk_dvfsrc *dvfsrc; + int ret; + + dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL); + if (!dvfsrc) + return -ENOMEM; + + dvfsrc->dvd = of_device_get_match_data(&pdev->dev); + dvfsrc->dev = &pdev->dev; + + dvfsrc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(dvfsrc->regs)) + return PTR_ERR(dvfsrc->regs); + + arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_INIT, + 0, 0, 0, 0, 0, 0, &ares); + if (ares.a0) + return dev_err_probe(&pdev->dev, -EINVAL, "DVFSRC init failed: %lu\n", ares.a0); + + dvfsrc->dram_type = ares.a1; + dev_dbg(&pdev->dev, "DRAM Type: %d\n", dvfsrc->dram_type); + + dvfsrc->curr_opps = &dvfsrc->dvd->opps_desc[dvfsrc->dram_type]; + platform_set_drvdata(pdev, dvfsrc); + + ret = devm_of_platform_populate(&pdev->dev); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to populate child devices\n"); + + /* Everything is set up - make it run! */ + arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_START, + 0, 0, 0, 0, 0, 0, &ares); + if (ares.a0) + return dev_err_probe(&pdev->dev, -EINVAL, "Cannot start DVFSRC: %lu\n", ares.a0); + + return 0; +} + +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = { + { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 2 }, +}; + +static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = { + { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 }, +}; + +static const struct dvfsrc_opp_desc dvfsrc_opp_mt8183_desc[] = { + [0] = { + .opps = dvfsrc_opp_mt8183_lp4, + .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4), + }, + [1] = { + .opps = dvfsrc_opp_mt8183_lp3, + .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3), + }, + [2] = { + .opps = dvfsrc_opp_mt8183_lp3, + .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3), + } +}; + +static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8183 = { 0, 0, 0 }; + +static const struct dvfsrc_soc_data mt8183_data = { + .opps_desc = dvfsrc_opp_mt8183_desc, + .regs = dvfsrc_mt8183_regs, + .get_target_level = dvfsrc_get_target_level_v1, + .get_current_level = dvfsrc_get_current_level_v1, + .get_vcore_level = dvfsrc_get_vcore_level_v1, + .set_dram_bw = dvfsrc_set_dram_bw_v1, + .set_opp_level = dvfsrc_set_opp_level_v1, + .set_vcore_level = dvfsrc_set_vcore_level_v1, + .wait_for_opp_level = dvfsrc_wait_for_opp_level_v1, + .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, + .bw_constraints = &dvfsrc_bw_constr_mt8183, +}; + +static const struct dvfsrc_opp dvfsrc_opp_mt8195_lp4[] = { + { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, + { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, + { 1, 3 }, { 2, 3 }, { 3, 3 }, { 1, 4 }, + { 2, 4 }, { 3, 4 }, { 2, 5 }, { 3, 5 }, + { 3, 6 }, +}; + +static const struct dvfsrc_opp_desc dvfsrc_opp_mt8195_desc[] = { + [0] = { + .opps = dvfsrc_opp_mt8195_lp4, + .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8195_lp4), + } +}; + +static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_mt8195 = { + .max_dram_nom_bw = 255, + .max_dram_peak_bw = 255, + .max_dram_hrt_bw = 1023, +}; + +static const struct dvfsrc_soc_data mt8195_data = { + .opps_desc = dvfsrc_opp_mt8195_desc, + .regs = dvfsrc_mt8195_regs, + .get_target_level = dvfsrc_get_target_level_v2, + .get_current_level = dvfsrc_get_current_level_v2, + .get_vcore_level = dvfsrc_get_vcore_level_v2, + .get_vscp_level = dvfsrc_get_vscp_level_v2, + .set_dram_bw = dvfsrc_set_dram_bw_v1, + .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1, + .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1, + .set_vcore_level = dvfsrc_set_vcore_level_v2, + .set_vscp_level = dvfsrc_set_vscp_level_v2, + .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2, + .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1, + .bw_constraints = &dvfsrc_bw_constr_mt8195, +}; + +static const struct of_device_id mtk_dvfsrc_of_match[] = { + { .compatible = "mediatek,mt8183-dvfsrc", .data = &mt8183_data }, + { .compatible = "mediatek,mt8195-dvfsrc", .data = &mt8195_data }, + { /* sentinel */ } +}; + +static struct platform_driver mtk_dvfsrc_driver = { + .probe = mtk_dvfsrc_probe, + .driver = { + .name = "mtk-dvfsrc", + .of_match_table = mtk_dvfsrc_of_match, + }, +}; +module_platform_driver(mtk_dvfsrc_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_AUTHOR("Dawei Chien "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek DVFSRC driver"); diff --git a/include/linux/soc/mediatek/dvfsrc.h b/include/linux/soc/mediatek/dvfsrc.h new file mode 100644 index 000000000000..1498b3ed396b --- /dev/null +++ b/include/linux/soc/mediatek/dvfsrc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#ifndef __MEDIATEK_DVFSRC_H +#define __MEDIATEK_DVFSRC_H + +enum mtk_dvfsrc_cmd { + MTK_DVFSRC_CMD_BW, + MTK_DVFSRC_CMD_HRT_BW, + MTK_DVFSRC_CMD_PEAK_BW, + MTK_DVFSRC_CMD_OPP, + MTK_DVFSRC_CMD_VCORE_LEVEL, + MTK_DVFSRC_CMD_VSCP_LEVEL, + MTK_DVFSRC_CMD_MAX, +}; + +#if IS_ENABLED(CONFIG_MTK_DVFSRC) + +int mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data); +int mtk_dvfsrc_query_info(const struct device *dev, u32 cmd, int *data); + +#else + +static inline int mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data) +{ return -ENODEV; } + +static inline int mtk_dvfsrc_query_info(const struct device *dev, u32 cmd, int *data) +{ return -ENODEV; } + +#endif /* CONFIG_MTK_DVFSRC */ + +#endif diff --git a/include/linux/soc/mediatek/mtk_sip_svc.h b/include/linux/soc/mediatek/mtk_sip_svc.h index 0761128b4354..abe24a73ee19 100644 --- a/include/linux/soc/mediatek/mtk_sip_svc.h +++ b/include/linux/soc/mediatek/mtk_sip_svc.h @@ -22,6 +22,9 @@ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, MTK_SIP_SMC_CONVENTION, \ ARM_SMCCC_OWNER_SIP, fn_id) +/* DVFSRC SMC calls */ +#define MTK_SIP_DVFSRC_VCOREFS_CONTROL MTK_SIP_SMC_CMD(0x506) + /* IOMMU related SMC call */ #define MTK_SIP_KERNEL_IOMMU_CONTROL MTK_SIP_SMC_CMD(0x514) From 4b3347215f2600deb7d69c5d943c938b8d7daa58 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 8 Oct 2024 11:32:19 +0200 Subject: [PATCH 045/116] soc: mediatek: mtk-cmdq: Move mask build and append to function Move the CMDQ_CODE_MASK packet build and append logic to a new cmdq_pkt_mask() function; this reduces code duplication by 4x. Reviewed-by: Matthias Brugger Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-cmdq-helper.c | 31 ++++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index a8fccedba83f..620c371fd1fc 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -180,6 +180,15 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, return 0; } +static int cmdq_pkt_mask(struct cmdq_pkt *pkt, u32 mask) +{ + struct cmdq_instruction inst = { + .op = CMDQ_CODE_MASK, + .mask = ~mask + }; + return cmdq_pkt_append_command(pkt, inst); +} + int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) { struct cmdq_instruction inst; @@ -196,14 +205,11 @@ EXPORT_SYMBOL(cmdq_pkt_write); int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask) { - struct cmdq_instruction inst = { {0} }; u16 offset_mask = offset; int err; if (mask != 0xffffffff) { - inst.op = CMDQ_CODE_MASK; - inst.mask = ~mask; - err = cmdq_pkt_append_command(pkt, inst); + err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; @@ -251,9 +257,7 @@ int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, struct cmdq_instruction inst = {}; int err; - inst.op = CMDQ_CODE_MASK; - inst.mask = ~mask; - err = cmdq_pkt_append_command(pkt, inst); + err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; @@ -288,9 +292,7 @@ int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, struct cmdq_instruction inst = {}; int err; - inst.op = CMDQ_CODE_MASK; - inst.mask = ~mask; - err = cmdq_pkt_append_command(pkt, inst); + err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; @@ -409,12 +411,9 @@ EXPORT_SYMBOL(cmdq_pkt_poll); int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask) { - struct cmdq_instruction inst = { {0} }; int err; - inst.op = CMDQ_CODE_MASK; - inst.mask = ~mask; - err = cmdq_pkt_append_command(pkt, inst); + err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; @@ -436,9 +435,7 @@ int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mas * which enables use_mask bit. */ if (mask != GENMASK(31, 0)) { - inst.op = CMDQ_CODE_MASK; - inst.mask = ~mask; - ret = cmdq_pkt_append_command(pkt, inst); + ret = cmdq_pkt_mask(pkt, mask); if (ret < 0) return ret; use_mask = CMDQ_POLL_ENABLE_MASK; From 34771841a6a1e0bad73d955e9b26e60ae32545bb Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 8 Oct 2024 11:32:20 +0200 Subject: [PATCH 046/116] soc: mediatek: mtk-cmdq: Move cmdq_instruction init to declaration Move, where possible, the initialization of struct cmdq_instruction variables to their declaration to compress the code. While at it, also change an instance of open-coded mask to use the GENMASK() macro instead, and instances of `ret = func(); return ret;` to the equivalent (but shorter) `return func()`. Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-cmdq-helper.c | 199 ++++++++++++------------- 1 file changed, 92 insertions(+), 107 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 620c371fd1fc..0a05ee87a0fc 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -191,13 +191,12 @@ static int cmdq_pkt_mask(struct cmdq_pkt *pkt, u32 mask) int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) { - struct cmdq_instruction inst; - - inst.op = CMDQ_CODE_WRITE; - inst.value = value; - inst.offset = offset; - inst.subsys = subsys; - + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WRITE, + .value = value, + .offset = offset, + .subsys = subsys + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_write); @@ -208,30 +207,27 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset_mask = offset; int err; - if (mask != 0xffffffff) { + if (mask != GENMASK(31, 0)) { err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; offset_mask |= CMDQ_WRITE_ENABLE_MASK; } - err = cmdq_pkt_write(pkt, subsys, offset_mask, value); - - return err; + return cmdq_pkt_write(pkt, subsys, offset_mask, value); } EXPORT_SYMBOL(cmdq_pkt_write_mask); int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 reg_idx) { - struct cmdq_instruction inst = {}; - - inst.op = CMDQ_CODE_READ_S; - inst.dst_t = CMDQ_REG_TYPE; - inst.sop = high_addr_reg_idx; - inst.reg_dst = reg_idx; - inst.src_reg = addr_low; - + struct cmdq_instruction inst = { + .op = CMDQ_CODE_READ_S, + .dst_t = CMDQ_REG_TYPE, + .sop = high_addr_reg_idx, + .reg_dst = reg_idx, + .src_reg = addr_low + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_read_s); @@ -239,14 +235,13 @@ EXPORT_SYMBOL(cmdq_pkt_read_s); int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 src_reg_idx) { - struct cmdq_instruction inst = {}; - - inst.op = CMDQ_CODE_WRITE_S; - inst.src_t = CMDQ_REG_TYPE; - inst.sop = high_addr_reg_idx; - inst.offset = addr_low; - inst.src_reg = src_reg_idx; - + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WRITE_S, + .src_t = CMDQ_REG_TYPE, + .sop = high_addr_reg_idx, + .offset = addr_low, + .src_reg = src_reg_idx + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_write_s); @@ -254,20 +249,19 @@ EXPORT_SYMBOL(cmdq_pkt_write_s); int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 src_reg_idx, u32 mask) { - struct cmdq_instruction inst = {}; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WRITE_S_MASK, + .src_t = CMDQ_REG_TYPE, + .sop = high_addr_reg_idx, + .offset = addr_low, + .src_reg = src_reg_idx, + }; int err; err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; - inst.mask = 0; - inst.op = CMDQ_CODE_WRITE_S_MASK; - inst.src_t = CMDQ_REG_TYPE; - inst.sop = high_addr_reg_idx; - inst.offset = addr_low; - inst.src_reg = src_reg_idx; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_write_s_mask); @@ -275,13 +269,12 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_mask); int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, u16 addr_low, u32 value) { - struct cmdq_instruction inst = {}; - - inst.op = CMDQ_CODE_WRITE_S; - inst.sop = high_addr_reg_idx; - inst.offset = addr_low; - inst.value = value; - + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WRITE_S, + .sop = high_addr_reg_idx, + .offset = addr_low, + .value = value + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_write_s_value); @@ -289,18 +282,18 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_value); int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, u16 addr_low, u32 value, u32 mask) { - struct cmdq_instruction inst = {}; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WRITE_S_MASK, + .sop = high_addr_reg_idx, + .offset = addr_low, + .value = value + }; int err; err = cmdq_pkt_mask(pkt, mask); if (err < 0) return err; - inst.op = CMDQ_CODE_WRITE_S_MASK; - inst.sop = high_addr_reg_idx; - inst.offset = addr_low; - inst.value = value; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value); @@ -333,61 +326,61 @@ EXPORT_SYMBOL(cmdq_pkt_mem_move); int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) { - struct cmdq_instruction inst = { {0} }; u32 clear_option = clear ? CMDQ_WFE_UPDATE : 0; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WFE, + .value = CMDQ_WFE_OPTION | clear_option, + .event = event + }; if (event >= CMDQ_MAX_EVENT) return -EINVAL; - inst.op = CMDQ_CODE_WFE; - inst.value = CMDQ_WFE_OPTION | clear_option; - inst.event = event; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_wfe); int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event) { - struct cmdq_instruction inst = {}; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WFE, + .value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE | CMDQ_WFE_WAIT, + .event = event + }; if (event >= CMDQ_MAX_EVENT) return -EINVAL; - inst.op = CMDQ_CODE_WFE; - inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE | CMDQ_WFE_WAIT; - inst.event = event; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_acquire_event); int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) { - struct cmdq_instruction inst = { {0} }; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WFE, + .value = CMDQ_WFE_UPDATE, + .event = event + }; if (event >= CMDQ_MAX_EVENT) return -EINVAL; - inst.op = CMDQ_CODE_WFE; - inst.value = CMDQ_WFE_UPDATE; - inst.event = event; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_clear_event); int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event) { - struct cmdq_instruction inst = {}; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_WFE, + .value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE, + .event = event + }; if (event >= CMDQ_MAX_EVENT) return -EINVAL; - inst.op = CMDQ_CODE_WFE; - inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE; - inst.event = event; - return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_set_event); @@ -395,16 +388,13 @@ EXPORT_SYMBOL(cmdq_pkt_set_event); int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) { - struct cmdq_instruction inst = { {0} }; - int err; - - inst.op = CMDQ_CODE_POLL; - inst.value = value; - inst.offset = offset; - inst.subsys = subsys; - err = cmdq_pkt_append_command(pkt, inst); - - return err; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_POLL, + .value = value, + .offset = offset, + .subsys = subsys + }; + return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_poll); @@ -418,9 +408,7 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, return err; offset = offset | CMDQ_POLL_ENABLE_MASK; - err = cmdq_pkt_poll(pkt, subsys, offset, value); - - return err; + return cmdq_pkt_poll(pkt, subsys, offset, value); } EXPORT_SYMBOL(cmdq_pkt_poll_mask); @@ -474,11 +462,12 @@ int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, enum cmdq_logic_op s_op, struct cmdq_operand *right_operand) { - struct cmdq_instruction inst = { {0} }; + struct cmdq_instruction inst; if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX) return -EINVAL; + inst.value = 0; inst.op = CMDQ_CODE_LOGIC; inst.dst_t = CMDQ_REG_TYPE; inst.src_t = cmdq_operand_get_type(left_operand); @@ -494,43 +483,43 @@ EXPORT_SYMBOL(cmdq_pkt_logic_command); int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) { - struct cmdq_instruction inst = {}; - - inst.op = CMDQ_CODE_LOGIC; - inst.dst_t = CMDQ_REG_TYPE; - inst.reg_dst = reg_idx; - inst.value = value; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_LOGIC, + .dst_t = CMDQ_REG_TYPE, + .reg_dst = reg_idx, + .value = value + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_assign); int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) { - struct cmdq_instruction inst = {}; - - inst.op = CMDQ_CODE_JUMP; - inst.offset = CMDQ_JUMP_ABSOLUTE; - inst.value = addr >> shift_pa; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_JUMP, + .offset = CMDQ_JUMP_ABSOLUTE, + .value = addr >> shift_pa + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_jump_abs); int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa) { - struct cmdq_instruction inst = { {0} }; - - inst.op = CMDQ_CODE_JUMP; - inst.value = (u32)offset >> shift_pa; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_JUMP, + .value = (u32)offset >> shift_pa + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_jump_rel); int cmdq_pkt_eoc(struct cmdq_pkt *pkt) { - struct cmdq_instruction inst = { {0} }; - - inst.op = CMDQ_CODE_EOC; - inst.value = CMDQ_EOC_IRQ_EN; + struct cmdq_instruction inst = { + .op = CMDQ_CODE_EOC, + .value = CMDQ_EOC_IRQ_EN + }; return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_eoc); @@ -541,9 +530,7 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) int err; /* insert EOC and generate IRQ for each command iteration */ - inst.op = CMDQ_CODE_EOC; - inst.value = CMDQ_EOC_IRQ_EN; - err = cmdq_pkt_append_command(pkt, inst); + err = cmdq_pkt_eoc(pkt); if (err < 0) return err; @@ -551,9 +538,7 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) inst.op = CMDQ_CODE_JUMP; inst.value = CMDQ_JUMP_PASS >> cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); - err = cmdq_pkt_append_command(pkt, inst); - - return err; + return cmdq_pkt_append_command(pkt, inst); } EXPORT_SYMBOL(cmdq_pkt_finalize); From d0fa55cc987026b8ce421b5a93239526641c44f1 Mon Sep 17 00:00:00 2001 From: Pablo Sun Date: Wed, 2 Oct 2024 10:21:37 +0800 Subject: [PATCH 047/116] soc: mediatek: mediatek-regulator-coupler: Support mt8188 The Mali GPU in mt8188 also requires coupled power supplies, that is, the "vsram" voltage should follow the "vgpu" voltage. Therefore add the compatible to enable this coupling behavior. Signed-off-by: Pablo Sun Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20241002022138.29241-6-pablo.sun@mediatek.com Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-regulator-coupler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/mediatek/mtk-regulator-coupler.c b/drivers/soc/mediatek/mtk-regulator-coupler.c index ad2ed42aa697..0b6a2884145e 100644 --- a/drivers/soc/mediatek/mtk-regulator-coupler.c +++ b/drivers/soc/mediatek/mtk-regulator-coupler.c @@ -147,6 +147,7 @@ static int mediatek_regulator_coupler_init(void) { if (!of_machine_is_compatible("mediatek,mt8183") && !of_machine_is_compatible("mediatek,mt8186") && + !of_machine_is_compatible("mediatek,mt8188") && !of_machine_is_compatible("mediatek,mt8192")) return 0; From a1643ae9b3e3364edbb6cf285c5f2cf5d60336e6 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 24 Sep 2024 20:00:09 +0200 Subject: [PATCH 048/116] soc: mediatek: mtk-svs: Call of_node_put(np) only once in svs_get_subsys_device() An of_node_put(np) call was immediately used after a pointer check for a of_find_device_by_node() call in this function implementation. Thus call such a function only once instead directly before the check. This issue was transformed by using the Coccinelle software. Signed-off-by: Markus Elfring Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/884f0a5d-e6d3-47dc-8a9e-201bb86b271f@web.de Signed-off-by: AngeloGioacchino Del Regno --- drivers/soc/mediatek/mtk-svs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 9a91298c1253..7c349a94b45c 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2133,14 +2133,12 @@ static struct device *svs_get_subsys_device(struct svs_platform *svsp, } pdev = of_find_device_by_node(np); + of_node_put(np); if (!pdev) { - of_node_put(np); dev_err(svsp->dev, "cannot find pdev by %s\n", node_name); return ERR_PTR(-ENXIO); } - of_node_put(np); - return &pdev->dev; } From 11cf9a72bc0b31c16d0cca7487966710a452b6e2 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 21 Oct 2024 13:54:56 +0200 Subject: [PATCH 049/116] soc: qcom: smem: Fix up kerneldoc Fix warnings like: smem.c:504: warning: No description found for return value of 'qcom_smem_alloc' Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241021-topic-smem_kerneldoc-v1-1-4825904a7e25@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index e4411771f482..0d1ccf3ef108 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -499,6 +499,8 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem, * * Allocate space for a given smem item of size @size, given that the item is * not yet allocated. + * + * Return: 0 on success, negative errno on failure. */ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) { @@ -677,6 +679,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem, * * Looks up smem item and returns pointer to it. Size of smem * item is returned in @size. + * + * Return: a pointer to an SMEM item on success, ERR_PTR() on failure. */ void *qcom_smem_get(unsigned host, unsigned item, size_t *size) { @@ -709,6 +713,8 @@ EXPORT_SYMBOL_GPL(qcom_smem_get); * * To be used by smem clients as a quick way to determine if any new * allocations has been made. + * + * Return: number of available bytes on success, negative errno on failure. */ int qcom_smem_get_free_space(unsigned host) { @@ -758,7 +764,7 @@ static bool addr_in_range(void __iomem *base, size_t size, void *addr) * with an smem item pointer (previously returned by qcom_smem_get() * @p: the virtual address to convert * - * Returns 0 if the pointer provided is not within any smem region. + * Return: physical address of the SMEM item (if found), 0 otherwise */ phys_addr_t qcom_smem_virt_to_phys(void *p) { From dbc81e680a0f007cf062963c40f145074aacab2d Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Tue, 22 Oct 2024 16:54:30 +0800 Subject: [PATCH 050/116] dt-bindings: arm: qcom,ids: add SoC ID for QCS615 Add the ID for the Qualcomm QCS615 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lijuan Gao Link: https://lore.kernel.org/r/20241022-add_initial_support_for_qcs615-v4-2-0a551c6dd342@quicinc.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 8332f8d82f96..73a69fc535f6 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -278,6 +278,7 @@ #define QCOM_ID_IPQ5321 650 #define QCOM_ID_QCS8300 674 #define QCOM_ID_QCS8275 675 +#define QCOM_ID_QCS615 680 /* * The board type and revision information, used by Qualcomm bootloaders and From 8921bf54bfab240ea551b605c5c16c58f8777e97 Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Tue, 22 Oct 2024 16:54:32 +0800 Subject: [PATCH 051/116] soc: qcom: socinfo: Add QCS615 SoC ID table entry Add SoC Info support for the QCS615 platform. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lijuan Gao Link: https://lore.kernel.org/r/20241022-add_initial_support_for_qcs615-v4-4-0a551c6dd342@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 24c3971f2ef1..aed430f10eec 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -445,6 +445,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ5321) }, { qcom_board_id(QCS8300) }, { qcom_board_id(QCS8275) }, + { qcom_board_id(QCS615) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) From cb0d1c4e9b6b2b362ff41344157d33e2daf6ef7a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 22 Oct 2024 08:42:14 +0200 Subject: [PATCH 052/116] dt-bindings: soc: qcom: aoss-qmp: Add SM8750 Document compatible for Qualcomm SM8750 SoC Always-on SubSystem (AOSS), compatible with existing generic fallback. Signed-off-by: Krzysztof Kozlowski Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20241022064214.22868-1-krzysztof.kozlowski@linaro.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 7afdb60edb22..2b90cbef9600 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -40,6 +40,7 @@ properties: - qcom,sm8450-aoss-qmp - qcom,sm8550-aoss-qmp - qcom,sm8650-aoss-qmp + - qcom,sm8750-aoss-qmp - qcom,x1e80100-aoss-qmp - const: qcom,aoss-qmp From 3b3214acd7f2dd506924cd57ce6e380cdaede423 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Oct 2024 19:32:36 +0300 Subject: [PATCH 053/116] dt-bindings: arm: qcom,ids: add SoC ID for SAR2130P and SAR1130P Add the IDs for Qualcomm SAR2130P and SAR1130P platforms. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241018-sar2130p-socinfo-v1-1-b1e97ea963fe@linaro.org Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 73a69fc535f6..1a53ca2df523 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -255,6 +255,7 @@ #define QCOM_ID_IPQ9510 521 #define QCOM_ID_QRB4210 523 #define QCOM_ID_QRB2210 524 +#define QCOM_ID_SAR2130P 525 #define QCOM_ID_SM8475 530 #define QCOM_ID_SM8475P 531 #define QCOM_ID_SA8775P 534 @@ -264,6 +265,7 @@ #define QCOM_ID_X1E80100 555 #define QCOM_ID_SM8650 557 #define QCOM_ID_SM4450 568 +#define QCOM_ID_SAR1130P 579 #define QCOM_ID_QDU1010 587 #define QCOM_ID_QRU1032 588 #define QCOM_ID_QRU1052 589 From 3fa0104ed2f11e7f4b26bcdd82f9a45b983813c3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 18 Oct 2024 19:32:37 +0300 Subject: [PATCH 054/116] soc: qcom: socinfo: add SoC IDs for SAR1130P and SAR2130P Add SoC IDs for Qualcomm SAR1130P and SAR2130P platforms. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241018-sar2130p-socinfo-v1-2-b1e97ea963fe@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index aed430f10eec..37309c8a4591 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -422,6 +422,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ9510) }, { qcom_board_id(QRB4210) }, { qcom_board_id(QRB2210) }, + { qcom_board_id(SAR2130P) }, { qcom_board_id(SM8475) }, { qcom_board_id(SM8475P) }, { qcom_board_id(SA8775P) }, @@ -431,6 +432,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(X1E80100) }, { qcom_board_id(SM8650) }, { qcom_board_id(SM4450) }, + { qcom_board_id(SAR1130P) }, { qcom_board_id(QDU1010) }, { qcom_board_id(QRU1032) }, { qcom_board_id(QRU1052) }, From e19bc8b2249b13a34bb2db82755cee5a1dad0ef2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Oct 2024 21:20:16 +0300 Subject: [PATCH 055/116] dt-bindings: firmware: qcom,scm: Add SAR2130P compatible Document compatible for the SCM firmware interface on SAR2130P platform. Signed-off-by: Dmitry Baryshkov Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241017-sar2130p-scm-v1-1-cc74a6b75c94@linaro.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 2cc83771d8e7..1a6278e5571b 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -44,6 +44,7 @@ properties: - qcom,scm-qcm2290 - qcom,scm-qdu1000 - qcom,scm-sa8775p + - qcom,scm-sar2130p - qcom,scm-sc7180 - qcom,scm-sc7280 - qcom,scm-sc8180x From 25136f046b84dbbe3cb8945666a2ecae487ddf3f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 17 Oct 2024 21:19:47 +0300 Subject: [PATCH 056/116] dt-bindings: soc: qcom,aoss-qmp: Add SAR2130P compatible Document compatible for the Always-On Subsystem on SAR2130P platform. Signed-off-by: Dmitry Baryshkov Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241017-sar2130p-soc-v1-1-7f9c204710c3@linaro.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 2b90cbef9600..9bf4e0adc620 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -27,6 +27,7 @@ properties: - enum: - qcom,qdu1000-aoss-qmp - qcom,sa8775p-aoss-qmp + - qcom,sar2130p-aoss-qmp - qcom,sc7180-aoss-qmp - qcom,sc7280-aoss-qmp - qcom,sc8180x-aoss-qmp From 185686beb464996bc587e8ae1eee61f01bee080e Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 14 Oct 2024 14:46:30 +0200 Subject: [PATCH 057/116] misc: Add support for LAN966x PCI device Add a PCI driver that handles the LAN966x PCI device using a device-tree overlay. This overlay is applied to the PCI device DT node and allows to describe components that are present in the device. The memory from the device-tree is remapped to the BAR memory thanks to "ranges" properties computed at runtime by the PCI core during the PCI enumeration. The PCI device itself acts as an interrupt controller and is used as the parent of the internal LAN966x interrupt controller to route the interrupts to the assigned PCI INTx interrupt. Signed-off-by: Herve Codina Acked-by: Greg Kroah-Hartman Acked-by: Bjorn Helgaas # quirks.c Link: https://lore.kernel.org/r/20241014124636.24221-2-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/misc/Kconfig | 24 ++++ drivers/misc/Makefile | 3 + drivers/misc/lan966x_pci.c | 215 ++++++++++++++++++++++++++++++++++ drivers/misc/lan966x_pci.dtso | 167 ++++++++++++++++++++++++++ drivers/pci/quirks.c | 1 + 5 files changed, 410 insertions(+) create mode 100644 drivers/misc/lan966x_pci.c create mode 100644 drivers/misc/lan966x_pci.dtso diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3fe7e2a9bd29..902c306bc972 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -610,6 +610,30 @@ config MARVELL_CN10K_DPI To compile this driver as a module, choose M here: the module will be called mrvl_cn10k_dpi. +config MCHP_LAN966X_PCI + tristate "Microchip LAN966x PCIe Support" + depends on PCI + select OF + select OF_OVERLAY + select IRQ_DOMAIN + help + This enables the support for the LAN966x PCIe device. + + This is used to drive the LAN966x PCIe device from the host system + to which it is connected. The driver uses a device tree overlay to + load other drivers to support for LAN966x internal components. + + Even if this driver does not depend on those other drivers, in order + to have a fully functional board, the following drivers are needed: + - fixed-clock (COMMON_CLK) + - lan966x-oic (LAN966X_OIC) + - lan966x-cpu-syscon (MFD_SYSCON) + - lan966x-switch-reset (RESET_MCHP_SPARX5) + - lan966x-pinctrl (PINCTRL_OCELOT) + - lan966x-serdes (PHY_LAN966X_SERDES) + - lan966x-miim (MDIO_MSCC_MIIM) + - lan966x-switch (LAN966X_SWITCH) + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index a9f94525e181..885b22989580 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -71,4 +71,7 @@ obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o obj-$(CONFIG_NSM) += nsm.o obj-$(CONFIG_MARVELL_CN10K_DPI) += mrvl_cn10k_dpi.o +lan966x-pci-objs := lan966x_pci.o +lan966x-pci-objs += lan966x_pci.dtbo.o +obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ diff --git a/drivers/misc/lan966x_pci.c b/drivers/misc/lan966x_pci.c new file mode 100644 index 000000000000..9c79b58137e5 --- /dev/null +++ b/drivers/misc/lan966x_pci.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip LAN966x PCI driver + * + * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries. + * + * Authors: + * Clément Léger + * Hervé Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.lib */ +extern char __dtbo_lan966x_pci_begin[]; +extern char __dtbo_lan966x_pci_end[]; + +struct pci_dev_intr_ctrl { + struct pci_dev *pci_dev; + struct irq_domain *irq_domain; + int irq; +}; + +static int pci_dev_irq_domain_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) +{ + irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq); + return 0; +} + +static const struct irq_domain_ops pci_dev_irq_domain_ops = { + .map = pci_dev_irq_domain_map, + .xlate = irq_domain_xlate_onecell, +}; + +static irqreturn_t pci_dev_irq_handler(int irq, void *data) +{ + struct pci_dev_intr_ctrl *intr_ctrl = data; + int ret; + + ret = generic_handle_domain_irq(intr_ctrl->irq_domain, 0); + return ret ? IRQ_NONE : IRQ_HANDLED; +} + +static struct pci_dev_intr_ctrl *pci_dev_create_intr_ctrl(struct pci_dev *pdev) +{ + struct pci_dev_intr_ctrl *intr_ctrl __free(kfree) = NULL; + struct fwnode_handle *fwnode; + int ret; + + fwnode = dev_fwnode(&pdev->dev); + if (!fwnode) + return ERR_PTR(-ENODEV); + + intr_ctrl = kmalloc(sizeof(*intr_ctrl), GFP_KERNEL); + if (!intr_ctrl) + return ERR_PTR(-ENOMEM); + + intr_ctrl->pci_dev = pdev; + + intr_ctrl->irq_domain = irq_domain_create_linear(fwnode, 1, &pci_dev_irq_domain_ops, + intr_ctrl); + if (!intr_ctrl->irq_domain) { + pci_err(pdev, "Failed to create irqdomain\n"); + return ERR_PTR(-ENOMEM); + } + + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX); + if (ret < 0) { + pci_err(pdev, "Unable alloc irq vector (%d)\n", ret); + goto err_remove_domain; + } + intr_ctrl->irq = pci_irq_vector(pdev, 0); + ret = request_irq(intr_ctrl->irq, pci_dev_irq_handler, IRQF_SHARED, + pci_name(pdev), intr_ctrl); + if (ret) { + pci_err(pdev, "Unable to request irq %d (%d)\n", intr_ctrl->irq, ret); + goto err_free_irq_vector; + } + + return_ptr(intr_ctrl); + +err_free_irq_vector: + pci_free_irq_vectors(pdev); +err_remove_domain: + irq_domain_remove(intr_ctrl->irq_domain); + return ERR_PTR(ret); +} + +static void pci_dev_remove_intr_ctrl(struct pci_dev_intr_ctrl *intr_ctrl) +{ + free_irq(intr_ctrl->irq, intr_ctrl); + pci_free_irq_vectors(intr_ctrl->pci_dev); + irq_dispose_mapping(irq_find_mapping(intr_ctrl->irq_domain, 0)); + irq_domain_remove(intr_ctrl->irq_domain); + kfree(intr_ctrl); +} + +static void devm_pci_dev_remove_intr_ctrl(void *intr_ctrl) +{ + pci_dev_remove_intr_ctrl(intr_ctrl); +} + +static int devm_pci_dev_create_intr_ctrl(struct pci_dev *pdev) +{ + struct pci_dev_intr_ctrl *intr_ctrl; + + intr_ctrl = pci_dev_create_intr_ctrl(pdev); + if (IS_ERR(intr_ctrl)) + return PTR_ERR(intr_ctrl); + + return devm_add_action_or_reset(&pdev->dev, devm_pci_dev_remove_intr_ctrl, intr_ctrl); +} + +struct lan966x_pci { + struct device *dev; + int ovcs_id; +}; + +static int lan966x_pci_load_overlay(struct lan966x_pci *data) +{ + u32 dtbo_size = __dtbo_lan966x_pci_end - __dtbo_lan966x_pci_begin; + void *dtbo_start = __dtbo_lan966x_pci_begin; + + return of_overlay_fdt_apply(dtbo_start, dtbo_size, &data->ovcs_id, dev_of_node(data->dev)); +} + +static void lan966x_pci_unload_overlay(struct lan966x_pci *data) +{ + of_overlay_remove(&data->ovcs_id); +} + +static int lan966x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct device *dev = &pdev->dev; + struct lan966x_pci *data; + int ret; + + /* + * On ACPI system, fwnode can point to the ACPI node. + * This driver needs an of_node to be used as the device-tree overlay + * target. This of_node should be set by the PCI core if it succeeds in + * creating it (CONFIG_PCI_DYNAMIC_OF_NODES feature). + * Check here for the validity of this of_node. + */ + if (!dev_of_node(dev)) + return dev_err_probe(dev, -EINVAL, "Missing of_node for device\n"); + + /* Need to be done before devm_pci_dev_create_intr_ctrl. + * It allocates an IRQ and so pdev->irq is updated. + */ + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = devm_pci_dev_create_intr_ctrl(pdev); + if (ret) + return ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + pci_set_drvdata(pdev, data); + data->dev = dev; + + ret = lan966x_pci_load_overlay(data); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = of_platform_default_populate(dev_of_node(dev), NULL, dev); + if (ret) + goto err_unload_overlay; + + return 0; + +err_unload_overlay: + lan966x_pci_unload_overlay(data); + return ret; +} + +static void lan966x_pci_remove(struct pci_dev *pdev) +{ + struct lan966x_pci *data = pci_get_drvdata(pdev); + + of_platform_depopulate(data->dev); + + lan966x_pci_unload_overlay(data); +} + +static struct pci_device_id lan966x_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_EFAR, 0x9660) }, + { } +}; +MODULE_DEVICE_TABLE(pci, lan966x_pci_ids); + +static struct pci_driver lan966x_pci_driver = { + .name = "mchp_lan966x_pci", + .id_table = lan966x_pci_ids, + .probe = lan966x_pci_probe, + .remove = lan966x_pci_remove, +}; +module_pci_driver(lan966x_pci_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("Microchip LAN966x PCI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/lan966x_pci.dtso b/drivers/misc/lan966x_pci.dtso new file mode 100644 index 000000000000..7282687df25f --- /dev/null +++ b/drivers/misc/lan966x_pci.dtso @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Microchip UNG + */ + +#include +#include +#include +#include +#include + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = ""; + __overlay__ { + #address-cells = <3>; + #size-cells = <2>; + + pci-ep-bus@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * map @0xe2000000 (32MB) to BAR0 (CPU) + * map @0xe0000000 (16MB) to BAR1 (AMBA) + */ + ranges = <0xe2000000 0x00 0x00 0x00 0x2000000 + 0xe0000000 0x01 0x00 0x00 0x1000000>; + + oic: oic@e00c0120 { + compatible = "microchip,lan966x-oic"; + #interrupt-cells = <2>; + interrupt-controller; + interrupts = <0>; /* PCI INTx assigned interrupt */ + reg = <0xe00c0120 0x190>; + }; + + cpu_clk: cpu_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <600000000>; // CPU clock = 600MHz + }; + + ddr_clk: ddr_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; // Fabric clock = 30MHz + }; + + sys_clk: sys_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <15625000>; // System clock = 15.625MHz + }; + + cpu_ctrl: syscon@e00c0000 { + compatible = "microchip,lan966x-cpu-syscon", "syscon"; + reg = <0xe00c0000 0xa8>; + }; + + reset: reset@e200400c { + compatible = "microchip,lan966x-switch-reset"; + reg = <0xe200400c 0x4>, <0xe00c0000 0xa8>; + reg-names = "gcb","cpu"; + #reset-cells = <1>; + cpu-syscon = <&cpu_ctrl>; + }; + + gpio: pinctrl@e2004064 { + compatible = "microchip,lan966x-pinctrl"; + reg = <0xe2004064 0xb4>, + <0xe2010024 0x138>; + resets = <&reset 0>; + reset-names = "switch"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio 0 0 78>; + interrupt-parent = <&oic>; + interrupt-controller; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + + tod_pins: tod_pins { + pins = "GPIO_36"; + function = "ptpsync_1"; + }; + + fc0_a_pins: fcb4-i2c-pins { + /* RXD, TXD */ + pins = "GPIO_9", "GPIO_10"; + function = "fc0_a"; + }; + + }; + + serdes: serdes@e202c000 { + compatible = "microchip,lan966x-serdes"; + reg = <0xe202c000 0x9c>, + <0xe2004010 0x4>; + #phy-cells = <2>; + }; + + mdio1: mdio@e200413c { + #address-cells = <1>; + #size-cells = <0>; + compatible = "microchip,lan966x-miim"; + reg = <0xe200413c 0x24>, + <0xe2010020 0x4>; + + resets = <&reset 0>; + reset-names = "switch"; + + lan966x_phy0: ethernet-lan966x_phy@1 { + reg = <1>; + }; + + lan966x_phy1: ethernet-lan966x_phy@2 { + reg = <2>; + }; + }; + + switch: switch@e0000000 { + compatible = "microchip,lan966x-switch"; + reg = <0xe0000000 0x0100000>, + <0xe2000000 0x0800000>; + reg-names = "cpu", "gcb"; + + interrupt-parent = <&oic>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>, + <9 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "xtr", "ana"; + + resets = <&reset 0>; + reset-names = "switch"; + + pinctrl-names = "default"; + pinctrl-0 = <&tod_pins>; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + port0: port@0 { + phy-handle = <&lan966x_phy0>; + + reg = <0>; + phy-mode = "gmii"; + phys = <&serdes 0 CU(0)>; + }; + + port1: port@1 { + phy-handle = <&lan966x_phy1>; + + reg = <1>; + phy-mode = "gmii"; + phys = <&serdes 1 CU(1)>; + }; + }; + }; + }; + }; + }; +}; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dccb60c1d9cc..41dec625ed7b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6266,6 +6266,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node); /* * Devices known to require a longer delay before first config space access From 86f134941a4b74489ee7b3d057aa23f2afcb1e45 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 14 Oct 2024 14:46:31 +0200 Subject: [PATCH 058/116] MAINTAINERS: Add the Microchip LAN966x PCI driver entry After contributing the driver, add myself as the maintainer for the Microchip LAN966x PCI driver. Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20241014124636.24221-3-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f..79125b6f7814 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15184,6 +15184,12 @@ S: Maintained F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-oic.yaml F: drivers/irqchip/irq-lan966x-oic.c +MICROCHIP LAN966X PCI DRIVER +M: Herve Codina +S: Maintained +F: drivers/misc/lan966x_pci.c +F: drivers/misc/lan966x_pci.dtso + MICROCHIP LCDFB DRIVER M: Nicolas Ferre L: linux-fbdev@vger.kernel.org From 0426a920d6269cab3213f1f9eee1b5a91013441c Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 14 Oct 2024 14:46:32 +0200 Subject: [PATCH 059/116] reset: mchp: sparx5: Map cpu-syscon locally in case of LAN966x In the LAN966x PCI device use case, the syscon API cannot be used as it does not support device removal [1]. A syscon device is a core "system" device and not a device available in some addon boards and so, it is not supposed to be removed. The syscon API follows this assumption but this assumption is no longer valid in the LAN966x use case. In order to avoid the use of the syscon API and so, support for removal, use a local mapping of the syscon device. Link: https://lore.kernel.org/all/20240923100741.11277439@bootlin.com/ [1] Signed-off-by: Herve Codina Reviewed-by: Steen Hegelund Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20241014124636.24221-4-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-microchip-sparx5.c | 35 +++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/reset/reset-microchip-sparx5.c b/drivers/reset/reset-microchip-sparx5.c index 636e85c388b0..48a62d5da78d 100644 --- a/drivers/reset/reset-microchip-sparx5.c +++ b/drivers/reset/reset-microchip-sparx5.c @@ -62,6 +62,28 @@ static const struct reset_control_ops sparx5_reset_ops = { .reset = sparx5_reset_noop, }; +static const struct regmap_config mchp_lan966x_syscon_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static struct regmap *mchp_lan966x_syscon_to_regmap(struct device *dev, + struct device_node *syscon_np) +{ + struct regmap_config regmap_config = mchp_lan966x_syscon_regmap_config; + resource_size_t size; + void __iomem *base; + + base = devm_of_iomap(dev, syscon_np, 0, &size); + if (IS_ERR(base)) + return ERR_CAST(base); + + regmap_config.max_register = size - 4; + + return devm_regmap_init_mmio(dev, base, ®map_config); +} + static int mchp_sparx5_map_syscon(struct platform_device *pdev, char *name, struct regmap **target) { @@ -72,7 +94,18 @@ static int mchp_sparx5_map_syscon(struct platform_device *pdev, char *name, syscon_np = of_parse_phandle(pdev->dev.of_node, name, 0); if (!syscon_np) return -ENODEV; - regmap = syscon_node_to_regmap(syscon_np); + + /* + * The syscon API doesn't support syscon device removal. + * When used in LAN966x PCI device, the cpu-syscon device needs to be + * removed when the PCI device is removed. + * In case of LAN966x, map the syscon device locally to support the + * device removal. + */ + if (of_device_is_compatible(pdev->dev.of_node, "microchip,lan966x-switch-reset")) + regmap = mchp_lan966x_syscon_to_regmap(&pdev->dev, syscon_np); + else + regmap = syscon_node_to_regmap(syscon_np); of_node_put(syscon_np); if (IS_ERR(regmap)) { err = PTR_ERR(regmap); From eba0dedd27f9ad454deb580a1d09d63aa1766293 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 14 Oct 2024 14:46:33 +0200 Subject: [PATCH 060/116] reset: mchp: sparx5: Add MCHP_LAN966X_PCI dependency The sparx5 reset controller depends on the SPARX5 architecture or the LAN966x SoC. This reset controller can be used by the LAN966x PCI device and so it needs to be available when the LAN966x PCI device is enabled. Signed-off-by: Herve Codina Reviewed-by: Steen Hegelund Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20241014124636.24221-5-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index d28c4401a310..6337bcbd9b67 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -147,7 +147,7 @@ config RESET_LPC18XX config RESET_MCHP_SPARX5 bool "Microchip Sparx5 reset driver" - depends on ARCH_SPARX5 || SOC_LAN966 || COMPILE_TEST + depends on ARCH_SPARX5 || SOC_LAN966 || MCHP_LAN966X_PCI || COMPILE_TEST default y if SPARX5_SWITCH select MFD_SYSCON help From 996737ef676f5fea11a5e0a79a6e03ff13204490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20L=C3=A9ger?= Date: Mon, 14 Oct 2024 14:46:34 +0200 Subject: [PATCH 061/116] reset: mchp: sparx5: Allow building as a module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reset controller can be used by the LAN966x PCI device. The LAN966x PCI device driver can be built as a module and this reset controller driver has no reason to be a builtin driver in that case. Signed-off-by: Clément Léger Signed-off-by: Herve Codina Reviewed-by: Steen Hegelund Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20241014124636.24221-6-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 2 +- drivers/reset/reset-microchip-sparx5.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 6337bcbd9b67..18374555888d 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -146,7 +146,7 @@ config RESET_LPC18XX This enables the reset controller driver for NXP LPC18xx/43xx SoCs. config RESET_MCHP_SPARX5 - bool "Microchip Sparx5 reset driver" + tristate "Microchip Sparx5 reset driver" depends on ARCH_SPARX5 || SOC_LAN966 || MCHP_LAN966X_PCI || COMPILE_TEST default y if SPARX5_SWITCH select MFD_SYSCON diff --git a/drivers/reset/reset-microchip-sparx5.c b/drivers/reset/reset-microchip-sparx5.c index 48a62d5da78d..c4cc0edbb250 100644 --- a/drivers/reset/reset-microchip-sparx5.c +++ b/drivers/reset/reset-microchip-sparx5.c @@ -191,6 +191,7 @@ static const struct of_device_id mchp_sparx5_reset_of_match[] = { }, { } }; +MODULE_DEVICE_TABLE(of, mchp_sparx5_reset_of_match); static struct platform_driver mchp_sparx5_reset_driver = { .probe = mchp_sparx5_reset_probe, @@ -213,3 +214,4 @@ postcore_initcall(mchp_sparx5_reset_init); MODULE_DESCRIPTION("Microchip Sparx5 switch reset driver"); MODULE_AUTHOR("Steen Hegelund "); +MODULE_LICENSE("GPL"); From 37b395c2c489c1e031360f88a4be84a6fcc743a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20L=C3=A9ger?= Date: Mon, 14 Oct 2024 14:46:35 +0200 Subject: [PATCH 062/116] reset: mchp: sparx5: set the dev member of the reset controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to guarantee the device will not be deleted by the reset controller consumer, set the dev member of the reset controller. Signed-off-by: Clément Léger Signed-off-by: Herve Codina Reviewed-by: Steen Hegelund Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20241014124636.24221-7-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-microchip-sparx5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/reset/reset-microchip-sparx5.c b/drivers/reset/reset-microchip-sparx5.c index c4cc0edbb250..aa5464be7053 100644 --- a/drivers/reset/reset-microchip-sparx5.c +++ b/drivers/reset/reset-microchip-sparx5.c @@ -154,6 +154,7 @@ static int mchp_sparx5_reset_probe(struct platform_device *pdev) return err; ctx->rcdev.owner = THIS_MODULE; + ctx->rcdev.dev = &pdev->dev; ctx->rcdev.nr_resets = 1; ctx->rcdev.ops = &sparx5_reset_ops; ctx->rcdev.of_node = dn; From 61c6fe3d6f0e1606a2219ff8afbac7e5068a5795 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 1 Oct 2024 22:40:25 +0200 Subject: [PATCH 063/116] Revert "firmware: tegra: bpmp: Use scoped device node handling to simplify error paths" This reverts commit 8812b8689ee6 ("firmware: tegra: bpmp: Use scoped device node handling to simplify error paths") because it was silently modified by committer during commit process, by moving declaration of 'struct device_node *np' above the initializer/constructor. Such code was not intention of the author, is not conforming to cleanup.h code style and decreases the code readability. I did not write such code and I did not agree to put my name with such commit. Original patch: https://lore.kernel.org/all/20240816135722.105945-2-krzysztof.kozlowski@linaro.org/ Cc: Arnd Bergmann Signed-off-by: Krzysztof Kozlowski [treding@nvidia.com: shorten subject line] Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 2bee6e918f81..c3a1dc344961 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -3,7 +3,6 @@ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. */ -#include #include #include #include @@ -35,24 +34,29 @@ channel_to_ops(struct tegra_bpmp_channel *channel) struct tegra_bpmp *tegra_bpmp_get(struct device *dev) { - struct device_node *np __free(device_node); struct platform_device *pdev; struct tegra_bpmp *bpmp; + struct device_node *np; np = of_parse_phandle(dev->of_node, "nvidia,bpmp", 0); if (!np) return ERR_PTR(-ENOENT); pdev = of_find_device_by_node(np); - if (!pdev) - return ERR_PTR(-ENODEV); + if (!pdev) { + bpmp = ERR_PTR(-ENODEV); + goto put; + } bpmp = platform_get_drvdata(pdev); if (!bpmp) { + bpmp = ERR_PTR(-EPROBE_DEFER); put_device(&pdev->dev); - return ERR_PTR(-EPROBE_DEFER); + goto put; } +put: + of_node_put(np); return bpmp; } EXPORT_SYMBOL_GPL(tegra_bpmp_get); From 10b8a0cc84d28decb75bfc91f4395e176228a4ff Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Sat, 14 Sep 2024 16:25:32 +0800 Subject: [PATCH 064/116] soc: ti: knav_qmss_queue: Use IRQF_NO_AUTOEN flag in request_irq() As commit cbe16f35bee6 ("genirq: Add IRQF_NO_AUTOEN for request_irq/nmi()") said, reqeust_irq() and then disable_irq() is unsafe. In the small time gap between request_irq() and disable_irq(), interrupts can still come. IRQF_NO_AUTOEN flag can be used by drivers to request_irq(). It prevents the automatic enabling of the requested interrupt in the same safe way. With that the usage can be simplified and corrected. Compile-tested only. Signed-off-by: Jinjie Ruan Link: https://lore.kernel.org/r/20240914082532.344456-1-ruanjinjie@huawei.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/knav_qmss_queue.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 6c98738e548a..c099f9e7f8c6 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -119,11 +119,10 @@ static int knav_queue_setup_irq(struct knav_range_info *range, if (range->flags & RANGE_HAS_IRQ) { irq = range->irqs[queue].irq; - ret = request_irq(irq, knav_queue_int_handler, 0, - inst->irq_name, inst); + ret = request_irq(irq, knav_queue_int_handler, IRQF_NO_AUTOEN, + inst->irq_name, inst); if (ret) return ret; - disable_irq(irq); if (range->irqs[queue].cpu_mask) { ret = irq_set_affinity_hint(irq, range->irqs[queue].cpu_mask); if (ret) { From 74280c3d73143dcb976491fc085ccb0437cb5f0e Mon Sep 17 00:00:00 2001 From: Alessandro Zanni Date: Tue, 24 Sep 2024 23:46:10 +0200 Subject: [PATCH 065/116] soc: ti: knav_qmss_queue: Drop redundant continue statement Remove the statement "continue" at the end of the loop where it becomes useless. Problem found with Coccinelle static analysis tool, using continue.cocci script (coccinelle.gitlabpages.inria.fr/website/rules/continue.cocci) Signed-off-by: Alessandro Zanni Link: https://lore.kernel.org/r/20240924214612.38854-1-alessandro.zanni87@gmail.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/knav_qmss_queue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index c099f9e7f8c6..b4051cb932c4 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -722,7 +722,6 @@ static void kdesc_empty_pool(struct knav_pool *pool) if (!desc) { dev_dbg(pool->kdev->dev, "couldn't unmap desc, continuing\n"); - continue; } } WARN_ON(i != pool->num_desc); From 3e360703d0bff3bb5643b2a0bf9a670931ba8b71 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Mon, 7 Oct 2024 08:08:54 +0200 Subject: [PATCH 066/116] PM: QoS: Export dev_pm_qos_read_value Export the function dev_pm_qos_read_value(). Most other functions mentioned in Documentation/power/pm_qos_interface.rst are already exported, so export this one as well. This function will be used to read the resume latency in a driver that can also be compiled as a module. Signed-off-by: Markus Schneider-Pargmann Tested-by: Kevin Hilman Tested-by: Roger Quadros Reviewed-by: Dhruva Gole Reviewed-by: Kevin Hilman Acked-by: Rafael J. Wysocki Link: https://lore.kernel.org/lkml/CAJZ5v0g1Ri_wKYppomE6RXqcZXRnX7bLOPMtsQaao0uchSfE9A@mail.gmail.com/ Link: https://lore.kernel.org/r/20241007-tisci-syssuspendresume-v13-1-ed54cd659a49@baylibre.com Signed-off-by: Nishanth Menon --- drivers/base/power/qos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index bd77f6734f14..ff393cba7649 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -137,6 +137,7 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type) return ret; } +EXPORT_SYMBOL_GPL(dev_pm_qos_read_value); /** * apply_constraint - Add/modify/remove device PM QoS request. From 055b6cfb62f5a1ea811aa21b96f2e611329b12b8 Mon Sep 17 00:00:00 2001 From: Georgi Vlaev Date: Mon, 7 Oct 2024 08:08:55 +0200 Subject: [PATCH 067/116] firmware: ti_sci: Add support for querying the firmware caps Add support for the TISCI_MSG_QUERY_FW_CAPS message, used to retrieve the firmware capabilities of the currently running system firmware. The message belongs to the TISCI general core message API [1] and is available in SysFW version 08.04.03 and above. Currently, the message is supported on devices with split architecture of the system firmware (DM + TIFS) like AM62x. Old revisions or not yet supported platforms will NACK this request. We're using this message locally in ti_sci.c to get the low power features of the FW/SoC. As there's no other kernel consumers yet, this is not added to struct ti_sci_core_ops. Sysfw version >= 10.00.04 support LPM_DM_MANAGED capability [2], where Device Mgr firmware now manages which low power mode is chosen. Going forward, this is the default configuration supported for TI AM62 family of devices. The state chosen by the DM can be influenced by sending constraints using the new LPM constraint APIs. [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/general/core.html [2] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/general/core.html#tisci-msg-query-fw-caps Signed-off-by: Georgi Vlaev [vibhore@ti.com: Support for LPM_DM_MANAGED mode] Signed-off-by: Vibhore Vardhan Signed-off-by: Kevin Hilman Tested-by: Dhruva Gole Signed-off-by: Markus Schneider-Pargmann Tested-by: Kevin Hilman Tested-by: Roger Quadros Acked-by: Dhruva Gole Link: https://lore.kernel.org/r/20241007-tisci-syssuspendresume-v13-2-ed54cd659a49@baylibre.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 73 ++++++++++++++++++++++++++++++++++++++- drivers/firmware/ti_sci.h | 22 ++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 160968301b1f..d53192607709 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -2,7 +2,7 @@ /* * Texas Instruments System Control Interface Protocol Driver * - * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/ + * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/ * Nishanth Menon */ @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "ti_sci.h" @@ -98,6 +99,7 @@ struct ti_sci_desc { * @minfo: Message info * @node: list head * @host_id: Host ID + * @fw_caps: FW/SoC low power capabilities * @users: Number of users of this instance */ struct ti_sci_info { @@ -114,6 +116,7 @@ struct ti_sci_info { struct ti_sci_xfers_info minfo; struct list_head node; u8 host_id; + u64 fw_caps; /* protected by ti_sci_list_mutex */ int users; }; @@ -1651,6 +1654,67 @@ static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities + * @handle: Pointer to TI SCI handle + * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability + * + * Check if the firmware supports any optional low power modes. + * Old revisions of TIFS (< 08.04) will NACK the request which results in + * -ENODEV being returned. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle, + u64 *fw_caps) +{ + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct ti_sci_msg_resp_query_fw_caps *resp; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(struct ti_sci_msg_hdr), + sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_query_fw_caps *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to get capabilities\n"); + ret = -ENODEV; + goto fail; + } + + if (fw_caps) + *fw_caps = resp->fw_caps; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) { struct ti_sci_info *info; @@ -3390,6 +3454,13 @@ static int ti_sci_probe(struct platform_device *pdev) goto out; } + ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); + dev_dbg(dev, "Detected firmware capabilities: %s%s%s\n", + info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "" + ); + ti_sci_setup_ops(info); ret = devm_register_restart_handler(dev, tisci_reboot_handler, info); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 5846c60220f5..73ca9503606b 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -19,6 +19,7 @@ #define TI_SCI_MSG_WAKE_REASON 0x0003 #define TI_SCI_MSG_GOODBYE 0x0004 #define TI_SCI_MSG_SYS_RESET 0x0005 +#define TI_SCI_MSG_QUERY_FW_CAPS 0x0022 /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 @@ -132,6 +133,27 @@ struct ti_sci_msg_req_reboot { struct ti_sci_msg_hdr hdr; } __packed; +/** + * struct ti_sci_msg_resp_query_fw_caps - Response for query firmware caps + * @hdr: Generic header + * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability + * MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported) + * MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM + * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM + * + * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS + * providing currently available SOC/firmware capabilities. SoC that don't + * support low power modes return only MSG_FLAG_CAPS_GENERIC capability. + */ +struct ti_sci_msg_resp_query_fw_caps { + struct ti_sci_msg_hdr hdr; +#define MSG_FLAG_CAPS_GENERIC TI_SCI_MSG_FLAG(0) +#define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4) +#define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) +#define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) + u64 fw_caps; +} __packed; + /** * struct ti_sci_msg_req_set_device_state - Set the desired state of the device * @hdr: Generic header From ec24643bdd625971933451f22b8e33d364920f6e Mon Sep 17 00:00:00 2001 From: Vibhore Vardhan Date: Mon, 7 Oct 2024 08:08:56 +0200 Subject: [PATCH 068/116] firmware: ti_sci: Add system suspend and resume call Introduce system suspend call that enables the ti_sci driver to support low power mode when the user space issues a suspend to mem. The following power management operations defined in the TISCI Low Power Mode API [1] are implemented to support suspend and resume: 1) TISCI_MSG_PREPARE_SLEEP Prepare the SOC for entering into a low power mode and provide details to firmware about the state being entered. 2) TISCI_MSG_SET_IO_ISOLATION Control the IO isolation for Low Power Mode. Also, write a ti_sci_prepare_system_suspend call to be used in the driver suspend handler to allow the system to identify the low power mode being entered and if necessary, send TISCI_MSG_PREPARE_SLEEP with information about the mode being entered. Sysfw version >= 10.00.04 support LPM_DM_MANAGED capability [2], where Device Mgr firmware now manages which low power mode is chosen. Going forward, this is the default configuration supported for TI AM62 family of devices. The state chosen by the DM can be influenced by sending constraints using the new LPM constraint APIs. In case the firmware does not support LPM_DM_MANAGED mode, the mode selection logic can be extended as needed. If no suspend-to-RAM modes are supported, return without taking any action. We're using "pm_suspend_target_state" to map the kernel's target suspend state to SysFW low power mode. Make sure this is available only when CONFIG_SUSPEND is enabled. Suspend has to be split into two parts, ti_sci_suspend() will send the prepare sleep message to prepare suspend. ti_sci_suspend_noirq() sets IO isolation which needs to be done as late as possible to avoid any issues. On resume this has to be done as early as possible. [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html Co-developed-by: Dave Gerlach Signed-off-by: Dave Gerlach Signed-off-by: Georgi Vlaev Signed-off-by: Dhruva Gole Signed-off-by: Vibhore Vardhan Signed-off-by: Kevin Hilman Tested-by: Dhruva Gole Signed-off-by: Markus Schneider-Pargmann Tested-by: Roger Quadros Link: https://lore.kernel.org/r/20241007-tisci-syssuspendresume-v13-3-ed54cd659a49@baylibre.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 194 +++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 45 +++++- include/linux/soc/ti/ti_sci_protocol.h | 4 + 3 files changed, 242 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index d53192607709..ebf6c0756ba4 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -1654,6 +1655,68 @@ static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_cmd_prepare_sleep() - Prepare system for system suspend + * @handle: pointer to TI SCI handle + * @mode: Device identifier + * @ctx_lo: Low part of address for context save + * @ctx_hi: High part of address for context save + * @debug_flags: Debug flags to pass to firmware + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode, + u32 ctx_lo, u32 ctx_hi, u32 debug_flags) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_prepare_sleep *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + req = (struct ti_sci_msg_req_prepare_sleep *)xfer->xfer_buf; + req->mode = mode; + req->ctx_lo = ctx_lo; + req->ctx_hi = ctx_hi; + req->debug_flags = debug_flags; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to prepare sleep\n"); + ret = -ENODEV; + } + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + /** * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities * @handle: Pointer to TI SCI handle @@ -1715,6 +1778,61 @@ static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_cmd_set_io_isolation() - Enable IO isolation in LPM + * @handle: Pointer to TI SCI handle + * @state: The desired state of the IO isolation + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle, + u8 state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_set_io_isolation *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_IO_ISOLATION, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_io_isolation *)xfer->xfer_buf; + req->state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to set IO isolation\n"); + ret = -ENODEV; + } + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) { struct ti_sci_info *info; @@ -3326,6 +3444,81 @@ static int tisci_reboot_handler(struct sys_off_data *data) return NOTIFY_BAD; } +static int ti_sci_prepare_system_suspend(struct ti_sci_info *info) +{ + /* + * Map and validate the target Linux suspend state to TISCI LPM. + * Default is to let Device Manager select the low power mode. + */ + switch (pm_suspend_target_state) { + case PM_SUSPEND_MEM: + if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { + /* + * For the DM_MANAGED mode the context is reserved for + * internal use and can be 0 + */ + return ti_sci_cmd_prepare_sleep(&info->handle, + TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED, + 0, 0, 0); + } else { + /* DM Managed is not supported by the firmware. */ + dev_err(info->dev, "Suspend to memory is not supported by the firmware\n"); + return -EOPNOTSUPP; + } + break; + default: + /* + * Do not fail if we don't have action to take for a + * specific suspend mode. + */ + return 0; + } +} + +static int __maybe_unused ti_sci_suspend(struct device *dev) +{ + struct ti_sci_info *info = dev_get_drvdata(dev); + int ret; + + ret = ti_sci_prepare_system_suspend(info); + if (ret) + return ret; + + return 0; +} + +static int __maybe_unused ti_sci_suspend_noirq(struct device *dev) +{ + struct ti_sci_info *info = dev_get_drvdata(dev); + int ret = 0; + + ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE); + if (ret) + return ret; + + return 0; +} + +static int __maybe_unused ti_sci_resume_noirq(struct device *dev) +{ + struct ti_sci_info *info = dev_get_drvdata(dev); + int ret = 0; + + ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE); + if (ret) + return ret; + + return 0; +} + +static const struct dev_pm_ops ti_sci_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = ti_sci_suspend, + .suspend_noirq = ti_sci_suspend_noirq, + .resume_noirq = ti_sci_resume_noirq, +#endif +}; + /* Description for K2G */ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { .default_host_id = 2, @@ -3494,6 +3687,7 @@ static struct platform_driver ti_sci_driver = { .name = "ti-sci", .of_match_table = of_match_ptr(ti_sci_of_match), .suppress_bind_attrs = true, + .pm = &ti_sci_pm_ops, }, }; module_platform_driver(ti_sci_driver); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 73ca9503606b..8efe4d0e61fb 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -6,7 +6,7 @@ * The system works in a message response protocol * See: https://software-dl.ti.com/tisci/esd/latest/index.html for details * - * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/ + * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/ */ #ifndef __TI_SCI_H @@ -36,6 +36,10 @@ #define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d #define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e +/* Low Power Mode Requests */ +#define TI_SCI_MSG_PREPARE_SLEEP 0x0300 +#define TI_SCI_MSG_SET_IO_ISOLATION 0x0307 + /* Resource Management Requests */ #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 @@ -567,6 +571,45 @@ struct ti_sci_msg_resp_get_clock_freq { u64 freq_hz; } __packed; +/** + * struct tisci_msg_req_prepare_sleep - Request for TISCI_MSG_PREPARE_SLEEP. + * + * @hdr TISCI header to provide ACK/NAK flags to the host. + * @mode Low power mode to enter. + * @ctx_lo Low 32-bits of physical pointer to address to use for context save. + * @ctx_hi High 32-bits of physical pointer to address to use for context save. + * @debug_flags Flags that can be set to halt the sequence during suspend or + * resume to allow JTAG connection and debug. + * + * This message is used as the first step of entering a low power mode. It + * allows configurable information, including which state to enter to be + * easily shared from the application, as this is a non-secure message and + * therefore can be sent by anyone. + */ +struct ti_sci_msg_req_prepare_sleep { + struct ti_sci_msg_hdr hdr; + +#define TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED 0xfd + u8 mode; + u32 ctx_lo; + u32 ctx_hi; + u32 debug_flags; +} __packed; + +/** + * struct tisci_msg_set_io_isolation_req - Request for TI_SCI_MSG_SET_IO_ISOLATION. + * + * @hdr: Generic header + * @state: The deseared state of the IO isolation. + * + * This message is used to enable/disable IO isolation for low power modes. + * Response is generic ACK / NACK message. + */ +struct ti_sci_msg_req_set_io_isolation { + struct ti_sci_msg_hdr hdr; + u8 state; +} __packed; + #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff /** diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index bd0d11af76c5..1f1871e23f76 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -195,6 +195,10 @@ struct ti_sci_clk_ops { u64 *current_freq); }; +/* TISCI LPM IO isolation control values */ +#define TISCI_MSG_VALUE_IO_ENABLE 1 +#define TISCI_MSG_VALUE_IO_DISABLE 0 + /** * struct ti_sci_resource_desc - Description of TI SCI resource instance range. * @start: Start index of the first resource range. From 60357991f6b9d4bd4dc442a368da3f468cfa4903 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Mon, 7 Oct 2024 08:08:57 +0200 Subject: [PATCH 069/116] firmware: ti_sci: Introduce Power Management Ops Introduce power management ops supported by the TISCI Low Power Mode API [1]. 1) TISCI_MSG_LPM_WAKE_REASON Get which wake up source woke the SoC from Low Power Mode. The wake up source IDs will be common for all K3 platforms. 2) TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT Set LPM constraint on behalf of a device. By setting a constraint, the device ensures that it will not be powered off or reset in the selected mode. 3) TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT Set LPM resume latency constraint. By setting a constraint, the host ensures that the resume time from selected mode will be less than the constraint value. [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html Signed-off-by: Dave Gerlach [g-vlaev@ti.com: LPM_WAKE_REASON and IO_ISOLATION support] Signed-off-by: Georgi Vlaev [a-kaur@ti.com: SET_DEVICE_CONSTRAINT support] Signed-off-by: Akashdeep Kaur [vibhore@ti.com: SET_LATENCY_CONSTRAINT support] Signed-off-by: Vibhore Vardhan Signed-off-by: Kevin Hilman Reviewed-by: Akashdeep Kaur Tested-by: Dhruva Gole Signed-off-by: Markus Schneider-Pargmann Tested-by: Kevin Hilman Tested-by: Roger Quadros Acked-by: Dhruva Gole Link: https://lore.kernel.org/r/20241007-tisci-syssuspendresume-v13-4-ed54cd659a49@baylibre.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 198 +++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 76 ++++++++++ include/linux/soc/ti/ti_sci_protocol.h | 26 ++++ 3 files changed, 300 insertions(+) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index ebf6c0756ba4..b67c35c93802 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1833,6 +1833,186 @@ static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM + * @handle: Pointer to TI SCI handle + * @source: The wakeup source that woke the SoC from LPM + * @timestamp: Timestamp of the wakeup event + * @pin: The pin that has triggered wake up + * @mode: The last entered low power mode + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle, + u32 *source, u64 *timestamp, u8 *pin, u8 *mode) +{ + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct ti_sci_msg_resp_lpm_wake_reason *resp; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_WAKE_REASON, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(struct ti_sci_msg_hdr), + sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_lpm_wake_reason *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to get wake reason\n"); + ret = -ENODEV; + goto fail; + } + + if (source) + *source = resp->wake_source; + if (timestamp) + *timestamp = resp->wake_timestamp; + if (pin) + *pin = resp->wake_pin; + if (mode) + *mode = resp->mode; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_set_device_constraint() - Set LPM constraint on behalf of a device + * @handle: pointer to TI SCI handle + * @id: Device identifier + * @state: The desired state of device constraint: set or clear + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_device_constraint(const struct ti_sci_handle *handle, + u32 id, u8 state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_lpm_set_device_constraint *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_lpm_set_device_constraint *)xfer->xfer_buf; + req->id = id; + req->state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to set device constraint\n"); + ret = -ENODEV; + } + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_set_latency_constraint() - Set LPM resume latency constraint + * @handle: pointer to TI SCI handle + * @latency: maximum acceptable latency (in ms) to wake up from LPM + * @state: The desired state of latency constraint: set or clear + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_latency_constraint(const struct ti_sci_handle *handle, + u16 latency, u8 state) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_lpm_set_latency_constraint *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_lpm_set_latency_constraint *)xfer->xfer_buf; + req->latency = latency; + req->state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + dev_err(dev, "Failed to set device constraint\n"); + ret = -ENODEV; + } + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) { struct ti_sci_info *info; @@ -2975,6 +3155,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) struct ti_sci_core_ops *core_ops = &ops->core_ops; struct ti_sci_dev_ops *dops = &ops->dev_ops; struct ti_sci_clk_ops *cops = &ops->clk_ops; + struct ti_sci_pm_ops *pmops = &ops->pm_ops; struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; @@ -3014,6 +3195,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) cops->set_freq = ti_sci_cmd_clk_set_freq; cops->get_freq = ti_sci_cmd_clk_get_freq; + if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { + pr_debug("detected DM managed LPM in fw_caps\n"); + pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason; + pmops->set_device_constraint = ti_sci_cmd_set_device_constraint; + pmops->set_latency_constraint = ti_sci_cmd_set_latency_constraint; + } + rm_core_ops->get_range = ti_sci_cmd_get_resource_range; rm_core_ops->get_range_from_shost = ti_sci_cmd_get_resource_range_from_shost; @@ -3503,11 +3691,21 @@ static int __maybe_unused ti_sci_resume_noirq(struct device *dev) { struct ti_sci_info *info = dev_get_drvdata(dev); int ret = 0; + u32 source; + u64 time; + u8 pin; + u8 mode; ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE); if (ret) return ret; + ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode); + /* Do not fail to resume on error as the wake reason is not critical */ + if (!ret) + dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n", + source, pin, mode); + return 0; } diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 8efe4d0e61fb..053387d7baa0 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -38,7 +38,10 @@ /* Low Power Mode Requests */ #define TI_SCI_MSG_PREPARE_SLEEP 0x0300 +#define TI_SCI_MSG_LPM_WAKE_REASON 0x0306 #define TI_SCI_MSG_SET_IO_ISOLATION 0x0307 +#define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309 +#define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A /* Resource Management Requests */ #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 @@ -610,6 +613,79 @@ struct ti_sci_msg_req_set_io_isolation { u8 state; } __packed; +/** + * struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON. + * + * @hdr: Generic header. + * @wake_source: The wake up source that woke soc from LPM. + * @wake_timestamp: Timestamp at which soc woke. + * @wake_pin: The pin that has triggered wake up. + * @mode: The last entered low power mode. + * @rsvd: Reserved for future use. + * + * Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON, + * used to query the wake up source, pin and entered low power mode. + */ +struct ti_sci_msg_resp_lpm_wake_reason { + struct ti_sci_msg_hdr hdr; + u32 wake_source; + u64 wake_timestamp; + u8 wake_pin; + u8 mode; + u32 rsvd[2]; +} __packed; + +/** + * struct ti_sci_msg_req_lpm_set_device_constraint - Request for + * TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT. + * + * @hdr: TISCI header to provide ACK/NAK flags to the host. + * @id: Device ID of device whose constraint has to be modified. + * @state: The desired state of device constraint: set or clear. + * @rsvd: Reserved for future use. + * + * This message is used by host to set constraint on the device. This can be + * sent anytime after boot before prepare sleep message. Any device can set a + * constraint on the low power mode that the SoC can enter. It allows + * configurable information to be easily shared from the application, as this + * is a non-secure message and therefore can be sent by anyone. By setting a + * constraint, the device ensures that it will not be powered off or reset in + * the selected mode. Note: Access Restriction: Exclusivity flag of Device will + * be honored. If some other host already has constraint on this device ID, + * NACK will be returned. + */ +struct ti_sci_msg_req_lpm_set_device_constraint { + struct ti_sci_msg_hdr hdr; + u32 id; + u8 state; + u32 rsvd[2]; +} __packed; + +/** + * struct ti_sci_msg_req_lpm_set_latency_constraint - Request for + * TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT. + * + * @hdr: TISCI header to provide ACK/NAK flags to the host. + * @wkup_latency: The maximum acceptable latency to wake up from low power mode + * in milliseconds. The deeper the state, the higher the latency. + * @state: The desired state of wakeup latency constraint: set or clear. + * @rsvd: Reserved for future use. + * + * This message is used by host to set wakeup latency from low power mode. This can + * be sent anytime after boot before prepare sleep message, and can be sent after + * current low power mode is exited. Any device can set a constraint on the low power + * mode that the SoC can enter. It allows configurable information to be easily shared + * from the application, as this is a non-secure message and therefore can be sent by + * anyone. By setting a wakeup latency constraint, the host ensures that the resume time + * from selected low power mode will be less than the constraint value. + */ +struct ti_sci_msg_req_lpm_set_latency_constraint { + struct ti_sci_msg_hdr hdr; + u16 latency; + u8 state; + u32 rsvd; +} __packed; + #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff /** diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 1f1871e23f76..fd104b666836 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -199,6 +199,31 @@ struct ti_sci_clk_ops { #define TISCI_MSG_VALUE_IO_ENABLE 1 #define TISCI_MSG_VALUE_IO_DISABLE 0 +/* TISCI LPM constraint state values */ +#define TISCI_MSG_CONSTRAINT_SET 1 +#define TISCI_MSG_CONSTRAINT_CLR 0 + +/** + * struct ti_sci_pm_ops - Low Power Mode (LPM) control operations + * @lpm_wake_reason: Get the wake up source that woke the SoC from LPM + * - source: The wake up source that woke soc from LPM. + * - timestamp: Timestamp at which soc woke. + * @set_device_constraint: Set LPM constraint on behalf of a device + * - id: Device Identifier + * - state: The desired state of device constraint: set or clear. + * @set_latency_constraint: Set LPM resume latency constraint + * - latency: maximum acceptable latency to wake up from low power mode + * - state: The desired state of latency constraint: set or clear. + */ +struct ti_sci_pm_ops { + int (*lpm_wake_reason)(const struct ti_sci_handle *handle, + u32 *source, u64 *timestamp, u8 *pin, u8 *mode); + int (*set_device_constraint)(const struct ti_sci_handle *handle, + u32 id, u8 state); + int (*set_latency_constraint)(const struct ti_sci_handle *handle, + u16 latency, u8 state); +}; + /** * struct ti_sci_resource_desc - Description of TI SCI resource instance range. * @start: Start index of the first resource range. @@ -543,6 +568,7 @@ struct ti_sci_ops { struct ti_sci_core_ops core_ops; struct ti_sci_dev_ops dev_ops; struct ti_sci_clk_ops clk_ops; + struct ti_sci_pm_ops pm_ops; struct ti_sci_rm_core_ops rm_core_ops; struct ti_sci_rm_irq_ops rm_irq_ops; struct ti_sci_rm_ringacc_ops rm_ring_ops; From a7a15754c7f70a833ffeb9ad996b358924f10305 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 7 Oct 2024 08:08:58 +0200 Subject: [PATCH 070/116] firmware: ti_sci: add CPU latency constraint management During system-wide suspend, check if any of the CPUs have PM QoS resume latency constraints set. If so, set TI SCI constraint. TI SCI has a single system-wide latency constraint, so use the max of any of the CPU latencies as the system-wide value. Note: DM firmware clears all constraints at resume time, so constraints need to be checked/updated/sent at each system suspend. Co-developed-by: Vibhore Vardhan Signed-off-by: Vibhore Vardhan Reviewed-by: Dhruva Gole Signed-off-by: Dhruva Gole Signed-off-by: Kevin Hilman Tested-by: Dhruva Gole Signed-off-by: Markus Schneider-Pargmann Tested-by: Kevin Hilman Tested-by: Roger Quadros Link: https://lore.kernel.org/r/20241007-tisci-syssuspendresume-v13-5-ed54cd659a49@baylibre.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index b67c35c93802..555e41cc0808 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -3666,7 +3668,27 @@ static int ti_sci_prepare_system_suspend(struct ti_sci_info *info) static int __maybe_unused ti_sci_suspend(struct device *dev) { struct ti_sci_info *info = dev_get_drvdata(dev); - int ret; + struct device *cpu_dev, *cpu_dev_max = NULL; + s32 val, cpu_lat = 0; + int i, ret; + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { + for_each_possible_cpu(i) { + cpu_dev = get_cpu_device(i); + val = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_RESUME_LATENCY); + if (val != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) { + cpu_lat = max(cpu_lat, val); + cpu_dev_max = cpu_dev; + } + } + if (cpu_dev_max) { + dev_dbg(cpu_dev_max, "%s: sending max CPU latency=%u\n", __func__, cpu_lat); + ret = ti_sci_cmd_set_latency_constraint(&info->handle, + cpu_lat, TISCI_MSG_CONSTRAINT_SET); + if (ret) + return ret; + } + } ret = ti_sci_prepare_system_suspend(info); if (ret) From a4c14f509509a6a24f25edb7619f55f204a8433f Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Tue, 15 Oct 2024 16:33:20 -0500 Subject: [PATCH 071/116] firmware: ti_sci: Remove use of of_match_ptr() helper When OF support is disabled the of_device_id struct match table can be conditionally compiled out, this helper allows the assignment to also be turned into a NULL conditionally. When the of_device_id struct is not conditionally defined based on OF then the table will be unused causing a warning. The two options are to either set the table as _maybe_unused, or to just remove this helper since the table will always be defined. Do the latter here. Signed-off-by: Andrew Davis Link: https://lore.kernel.org/r/20241015213322.2649011-2-afd@ti.com Signed-off-by: Nishanth Menon --- drivers/firmware/ti_sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 555e41cc0808..806a975fff22 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -3905,7 +3905,7 @@ static struct platform_driver ti_sci_driver = { .probe = ti_sci_probe, .driver = { .name = "ti-sci", - .of_match_table = of_match_ptr(ti_sci_of_match), + .of_match_table = ti_sci_of_match, .suppress_bind_attrs = true, .pm = &ti_sci_pm_ops, }, From 14b2157a9c14481c3b967d8d1a95972bf885fb88 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 27 Aug 2024 11:24:49 -0700 Subject: [PATCH 072/116] dt-bindings: sram: Document reg-io-width property Some SRAMs need to be accessed with a specific access width, define the 'reg-io-width' property specifying such access sizes. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Florian Fainelli Message-Id: <20240827182450.3608307-2-florian.fainelli@broadcom.com> Signed-off-by: Sudeep Holla --- Documentation/devicetree/bindings/sram/sram.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index 0922d1f71ba8..7c1337e159f2 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -101,6 +101,12 @@ patternProperties: IO mem address range, relative to the SRAM range. maxItems: 1 + reg-io-width: + description: + The size (in bytes) of the IO accesses that should be performed on the + SRAM. + enum: [1, 2, 4, 8] + pool: description: Indicates that the particular reserved SRAM area is addressable From 2cd7f3db25feeb7c204e36df9f1bb13bea3a3a20 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 27 Aug 2024 11:24:50 -0700 Subject: [PATCH 073/116] firmware: arm_scmi: Support 'reg-io-width' property for shared memory Some shared memory areas might only support a certain access width, such as 32-bit, which memcpy_{from,to}_io() does not adhere to at least on ARM64 by making both 8-bit and 64-bit accesses to such memory. Update the shmem layer to support reading from and writing to such shared memory area using the specified I/O width in the Device Tree. The various transport layers making use of the shmem.c code are updated accordingly to pass the I/O accessors that they store. Signed-off-by: Florian Fainelli Message-Id: <20240827182450.3608307-3-florian.fainelli@broadcom.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 32 +++++++- drivers/firmware/arm_scmi/shmem.c | 78 +++++++++++++++++-- .../firmware/arm_scmi/transports/mailbox.c | 13 +++- drivers/firmware/arm_scmi/transports/optee.c | 11 ++- drivers/firmware/arm_scmi/transports/smc.c | 11 ++- 5 files changed, 124 insertions(+), 21 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c52ed6c64006..951254eda482 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -311,6 +311,26 @@ enum scmi_bad_msg { MSG_MBOX_SPURIOUS = -5, }; +/* Used for compactness and signature validation of the function pointers being + * passed. + */ +typedef void (*shmem_copy_toio_t)(void __iomem *to, const void *from, + size_t count); +typedef void (*shmem_copy_fromio_t)(void *to, const void __iomem *from, + size_t count); + +/** + * struct scmi_shmem_io_ops - I/O operations to read from/write to + * Shared Memory + * + * @toio: Copy data to the shared memory area + * @fromio: Copy data from the shared memory area + */ +struct scmi_shmem_io_ops { + shmem_copy_fromio_t fromio; + shmem_copy_toio_t toio; +}; + /* shmem related declarations */ struct scmi_shared_mem; @@ -331,13 +351,16 @@ struct scmi_shared_mem; struct scmi_shared_mem_operations { void (*tx_prepare)(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer, - struct scmi_chan_info *cinfo); + struct scmi_chan_info *cinfo, + shmem_copy_toio_t toio); u32 (*read_header)(struct scmi_shared_mem __iomem *shmem); void (*fetch_response)(struct scmi_shared_mem __iomem *shmem, - struct scmi_xfer *xfer); + struct scmi_xfer *xfer, + shmem_copy_fromio_t fromio); void (*fetch_notification)(struct scmi_shared_mem __iomem *shmem, - size_t max_len, struct scmi_xfer *xfer); + size_t max_len, struct scmi_xfer *xfer, + shmem_copy_fromio_t fromio); void (*clear_channel)(struct scmi_shared_mem __iomem *shmem); bool (*poll_done)(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); @@ -345,7 +368,8 @@ struct scmi_shared_mem_operations { bool (*channel_intr_enabled)(struct scmi_shared_mem __iomem *shmem); void __iomem *(*setup_iomap)(struct scmi_chan_info *cinfo, struct device *dev, - bool tx, struct resource *res); + bool tx, struct resource *res, + struct scmi_shmem_io_ops **ops); }; const struct scmi_shared_mem_operations *scmi_shared_mem_operations_get(void); diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index 01d8a9398fe8..e9f30ab671a8 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -34,9 +34,59 @@ struct scmi_shared_mem { u8 msg_payload[]; }; +static inline void shmem_memcpy_fromio32(void *to, + const void __iomem *from, + size_t count) +{ + WARN_ON(!IS_ALIGNED((unsigned long)from, 4) || + !IS_ALIGNED((unsigned long)to, 4) || + count % 4); + + __ioread32_copy(to, from, count / 4); +} + +static inline void shmem_memcpy_toio32(void __iomem *to, + const void *from, + size_t count) +{ + WARN_ON(!IS_ALIGNED((unsigned long)to, 4) || + !IS_ALIGNED((unsigned long)from, 4) || + count % 4); + + __iowrite32_copy(to, from, count / 4); +} + +static struct scmi_shmem_io_ops shmem_io_ops32 = { + .fromio = shmem_memcpy_fromio32, + .toio = shmem_memcpy_toio32, +}; + +/* Wrappers are needed for proper memcpy_{from,to}_io expansion by the + * pre-processor. + */ +static inline void shmem_memcpy_fromio(void *to, + const void __iomem *from, + size_t count) +{ + memcpy_fromio(to, from, count); +} + +static inline void shmem_memcpy_toio(void __iomem *to, + const void *from, + size_t count) +{ + memcpy_toio(to, from, count); +} + +static struct scmi_shmem_io_ops shmem_io_ops_default = { + .fromio = shmem_memcpy_fromio, + .toio = shmem_memcpy_toio, +}; + static void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer, - struct scmi_chan_info *cinfo) + struct scmi_chan_info *cinfo, + shmem_copy_toio_t copy_toio) { ktime_t stop; @@ -73,7 +123,7 @@ static void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length); iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header); if (xfer->tx.buf) - memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len); + copy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len); } static u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem) @@ -82,7 +132,8 @@ static u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem) } static void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, - struct scmi_xfer *xfer) + struct scmi_xfer *xfer, + shmem_copy_fromio_t copy_fromio) { size_t len = ioread32(&shmem->length); @@ -91,11 +142,12 @@ static void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, xfer->rx.len = min_t(size_t, xfer->rx.len, len > 8 ? len - 8 : 0); /* Take a copy to the rx buffer.. */ - memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); + copy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); } static void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, - size_t max_len, struct scmi_xfer *xfer) + size_t max_len, struct scmi_xfer *xfer, + shmem_copy_fromio_t copy_fromio) { size_t len = ioread32(&shmem->length); @@ -103,7 +155,7 @@ static void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, xfer->rx.len = min_t(size_t, max_len, len > 4 ? len - 4 : 0); /* Take a copy to the rx buffer.. */ - memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len); + copy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len); } static void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem) @@ -139,7 +191,8 @@ static bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem) static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo, struct device *dev, bool tx, - struct resource *res) + struct resource *res, + struct scmi_shmem_io_ops **ops) { struct device_node *shmem __free(device_node); const char *desc = tx ? "Tx" : "Rx"; @@ -148,6 +201,7 @@ static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo, struct resource lres = {}; resource_size_t size; void __iomem *addr; + u32 reg_io_width; shmem = of_parse_phandle(cdev->of_node, "shmem", idx); if (!shmem) @@ -173,6 +227,16 @@ static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo, return IOMEM_ERR_PTR(-EADDRNOTAVAIL); } + of_property_read_u32(shmem, "reg-io-width", ®_io_width); + switch (reg_io_width) { + case 4: + *ops = &shmem_io_ops32; + break; + default: + *ops = &shmem_io_ops_default; + break; + } + return addr; } diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c index e3d5f7560990..e7efa3376aae 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -26,6 +26,7 @@ * @cinfo: SCMI channel info * @shmem: Transmit/Receive shared memory area * @chan_lock: Lock that prevents multiple xfers from being queued + * @io_ops: Transport specific I/O operations */ struct scmi_mailbox { struct mbox_client cl; @@ -35,6 +36,7 @@ struct scmi_mailbox { struct scmi_chan_info *cinfo; struct scmi_shared_mem __iomem *shmem; struct mutex chan_lock; + struct scmi_shmem_io_ops *io_ops; }; #define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl) @@ -45,7 +47,8 @@ static void tx_prepare(struct mbox_client *cl, void *m) { struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); - core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo); + core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo, + smbox->io_ops->toio); } static void rx_callback(struct mbox_client *cl, void *m) @@ -197,7 +200,8 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (!smbox) return -ENOMEM; - smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL); + smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL, + &smbox->io_ops); if (IS_ERR(smbox->shmem)) return PTR_ERR(smbox->shmem); @@ -305,7 +309,7 @@ static void mailbox_fetch_response(struct scmi_chan_info *cinfo, { struct scmi_mailbox *smbox = cinfo->transport_info; - core->shmem->fetch_response(smbox->shmem, xfer); + core->shmem->fetch_response(smbox->shmem, xfer, smbox->io_ops->fromio); } static void mailbox_fetch_notification(struct scmi_chan_info *cinfo, @@ -313,7 +317,8 @@ static void mailbox_fetch_notification(struct scmi_chan_info *cinfo, { struct scmi_mailbox *smbox = cinfo->transport_info; - core->shmem->fetch_notification(smbox->shmem, max_len, xfer); + core->shmem->fetch_notification(smbox->shmem, max_len, xfer, + smbox->io_ops->fromio); } static void mailbox_clear_channel(struct scmi_chan_info *cinfo) diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c index 56fc63edf51e..663272879edf 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -114,6 +114,7 @@ enum scmi_optee_pta_cmd { * @req.shmem: Virtual base address of the shared memory * @req.msg: Shared memory protocol handle for SCMI request and * synchronous response + * @io_ops: Transport specific I/O operations * @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem * @link: Reference in agent's channel list */ @@ -128,6 +129,7 @@ struct scmi_optee_channel { struct scmi_shared_mem __iomem *shmem; struct scmi_msg_payld *msg; } req; + struct scmi_shmem_io_ops *io_ops; struct tee_shm *tee_shm; struct list_head link; }; @@ -350,7 +352,8 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo, struct scmi_optee_channel *channel) { - channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL); + channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL, + &channel->io_ops); if (IS_ERR(channel->req.shmem)) return PTR_ERR(channel->req.shmem); @@ -465,7 +468,8 @@ static int scmi_optee_send_message(struct scmi_chan_info *cinfo, ret = invoke_process_msg_channel(channel, core->msg->command_size(xfer)); } else { - core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo); + core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo, + channel->io_ops->toio); ret = invoke_process_smt_channel(channel); } @@ -484,7 +488,8 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo, core->msg->fetch_response(channel->req.msg, channel->rx_len, xfer); else - core->shmem->fetch_response(channel->req.shmem, xfer); + core->shmem->fetch_response(channel->req.shmem, xfer, + channel->io_ops->fromio); } static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret, diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c index f8dd108777f9..2f0e981e7599 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -45,6 +45,7 @@ * @irq: An optional IRQ for completion * @cinfo: SCMI channel info * @shmem: Transmit/Receive shared memory area + * @io_ops: Transport specific I/O operations * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. * Used when NOT operating in atomic mode. * @inflight: Atomic flag to protect access to Tx/Rx shared memory area. @@ -60,6 +61,7 @@ struct scmi_smc { int irq; struct scmi_chan_info *cinfo; struct scmi_shared_mem __iomem *shmem; + struct scmi_shmem_io_ops *io_ops; /* Protect access to shmem area */ struct mutex shmem_lock; #define INFLIGHT_NONE MSG_TOKEN_MAX @@ -144,7 +146,8 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (!scmi_info) return -ENOMEM; - scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res); + scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res, + &scmi_info->io_ops); if (IS_ERR(scmi_info->shmem)) return PTR_ERR(scmi_info->shmem); @@ -229,7 +232,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo, */ smc_channel_lock_acquire(scmi_info, xfer); - core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo); + core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo, + scmi_info->io_ops->toio); if (scmi_info->cap_id != ULONG_MAX) arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0, @@ -253,7 +257,8 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo, { struct scmi_smc *scmi_info = cinfo->transport_info; - core->shmem->fetch_response(scmi_info->shmem, xfer); + core->shmem->fetch_response(scmi_info->shmem, xfer, + scmi_info->io_ops->fromio); } static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret, From 5c14f38893d0b9daefc2c53b8ccd1692c7ced07c Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 28 Oct 2024 12:01:45 +0000 Subject: [PATCH 074/116] firmware: arm_scmi: Account for SHMEM memory overhead Transports using shared memory have to consider the overhead due to the layout area when determining the area effectively available for messages. Till now, such definitions were ambiguos across the SCMI stack and the overhead layout area was not considered at all. Add proper checks in the shmem layer to validate the provided max_msg_size against the effectively available memory area, less the layout. Signed-off-by: Cristian Marussi Message-Id: <20241028120151.1301177-2-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 6 +++++- drivers/firmware/arm_scmi/driver.c | 1 + drivers/firmware/arm_scmi/shmem.c | 7 +++++++ drivers/firmware/arm_scmi/transports/mailbox.c | 2 +- drivers/firmware/arm_scmi/transports/optee.c | 8 +++----- drivers/firmware/arm_scmi/transports/smc.c | 2 +- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 951254eda482..e2424e65066f 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -31,6 +31,8 @@ #define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) +#define SCMI_SHMEM_MAX_PAYLOAD_SIZE 104 + enum scmi_error_codes { SCMI_SUCCESS = 0, /* Success */ SCMI_ERR_SUPPORT = -1, /* Not supported */ @@ -165,6 +167,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); * channel * @is_p2a: A flag to identify a channel as P2A (RX) * @rx_timeout_ms: The configured RX timeout in milliseconds. + * @max_msg_size: Maximum size of message payload. * @handle: Pointer to SCMI entity handle * @no_completion_irq: Flag to indicate that this channel has no completion * interrupt mechanism for synchronous commands. @@ -177,6 +180,7 @@ struct scmi_chan_info { struct device *dev; bool is_p2a; unsigned int rx_timeout_ms; + unsigned int max_msg_size; struct scmi_handle *handle; bool no_completion_irq; void *transport_info; @@ -224,7 +228,7 @@ struct scmi_transport_ops { * @max_msg: Maximum number of messages for a channel type (tx or rx) that can * be pending simultaneously in the system. May be overridden by the * get_max_msg op. - * @max_msg_size: Maximum size of data per message that can be handled. + * @max_msg_size: Maximum size of data payload per message that can be handled. * @force_polling: Flag to force this whole transport to use SCMI core polling * mechanism instead of completion interrupts even if available. * @sync_cmds_completed_on_ret: Flag to indicate that the transport assures diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index f8934d049d68..7d5f0da975c7 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2645,6 +2645,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, cinfo->is_p2a = !tx; cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms; + cinfo->max_msg_size = info->desc->max_msg_size; /* Create a unique name for this transport device */ snprintf(name, 32, "__scmi_transport_device_%s_%02X", diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index e9f30ab671a8..11c347bff766 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -16,6 +16,8 @@ #include "common.h" +#define SCMI_SHMEM_LAYOUT_OVERHEAD 24 + /* * SCMI specification requires all parameters, message headers, return * arguments or any protocol data to be expressed in little endian @@ -221,6 +223,11 @@ static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo, } size = resource_size(res); + if (cinfo->max_msg_size + SCMI_SHMEM_LAYOUT_OVERHEAD > size) { + dev_err(dev, "misconfigured SCMI shared memory\n"); + return IOMEM_ERR_PTR(-ENOSPC); + } + addr = devm_ioremap(dev, res->start, size); if (!addr) { dev_err(dev, "failed to ioremap SCMI %s shared memory\n", desc); diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c index e7efa3376aae..b66df2981456 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -371,7 +371,7 @@ static struct scmi_desc scmi_mailbox_desc = { .ops = &scmi_mailbox_ops, .max_rx_timeout_ms = 30, /* We may increase this if required */ .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ - .max_msg_size = 128, + .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE, }; static const struct of_device_id scmi_of_match[] = { diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c index 663272879edf..3949a877e17d 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -17,8 +17,6 @@ #include "../common.h" -#define SCMI_OPTEE_MAX_MSG_SIZE 128 - enum scmi_optee_pta_cmd { /* * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities @@ -299,7 +297,7 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; param[2].u.memref.shm = channel->tee_shm; - param[2].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE; + param[2].u.memref.size = SCMI_SHMEM_MAX_PAYLOAD_SIZE; ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); if (ret < 0 || arg.ret) { @@ -332,7 +330,7 @@ static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo) static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel) { - const size_t msg_size = SCMI_OPTEE_MAX_MSG_SIZE; + const size_t msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE; void *shbuf; channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size); @@ -519,7 +517,7 @@ static struct scmi_desc scmi_optee_desc = { .ops = &scmi_optee_ops, .max_rx_timeout_ms = 30, .max_msg = 20, - .max_msg_size = SCMI_OPTEE_MAX_MSG_SIZE, + .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE, .sync_cmds_completed_on_ret = true, }; diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c index 2f0e981e7599..f632a62cfb3e 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -282,7 +282,7 @@ static struct scmi_desc scmi_smc_desc = { .ops = &scmi_smc_ops, .max_rx_timeout_ms = 30, .max_msg = 20, - .max_msg_size = 128, + .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE, /* * Setting .sync_cmds_atomic_replies to true for SMC assumes that, * once the SMC instruction has completed successfully, the issued From 3229e33311f86c3cbf3b0453ce242e74a5f11133 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 28 Oct 2024 12:01:46 +0000 Subject: [PATCH 075/116] firmware: arm_scmi: Calculate virtio PDU max size dynamically SCMI virtio transport maximum PDU size is currently hardcoded at build time; this will not play well with the possibile retrieval of a different size at run-time. Make the virtio transport derive the maximum PDU size from the max_msg_size provided by the SCMI core. No functional change. Reviewed-by: Florian Fainelli Signed-off-by: Cristian Marussi Message-Id: <20241028120151.1301177-3-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/transports/virtio.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c index d349766bc0b2..41aea33776a9 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -32,8 +32,8 @@ #define VIRTIO_MAX_RX_TIMEOUT_MS 60000 #define VIRTIO_SCMI_MAX_MSG_SIZE 128 /* Value may be increased. */ -#define VIRTIO_SCMI_MAX_PDU_SIZE \ - (VIRTIO_SCMI_MAX_MSG_SIZE + SCMI_MSG_MAX_PROT_OVERHEAD) +#define VIRTIO_SCMI_MAX_PDU_SIZE(ci) \ + ((ci)->max_msg_size + SCMI_MSG_MAX_PROT_OVERHEAD) #define DESCRIPTORS_PER_TX_MSG 2 /** @@ -90,6 +90,7 @@ enum poll_states { * @input: SDU used for (delayed) responses and notifications * @list: List which scmi_vio_msg may be part of * @rx_len: Input SDU size in bytes, once input has been received + * @max_len: Maximumm allowed SDU size in bytes * @poll_idx: Last used index registered for polling purposes if this message * transaction reply was configured for polling. * @poll_status: Polling state for this message. @@ -102,6 +103,7 @@ struct scmi_vio_msg { struct scmi_msg_payld *input; struct list_head list; unsigned int rx_len; + unsigned int max_len; unsigned int poll_idx; enum poll_states poll_status; /* Lock to protect access to poll_status */ @@ -234,7 +236,7 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, unsigned long flags; struct device *dev = &vioch->vqueue->vdev->dev; - sg_init_one(&sg_in, msg->input, VIRTIO_SCMI_MAX_PDU_SIZE); + sg_init_one(&sg_in, msg->input, msg->max_len); spin_lock_irqsave(&vioch->lock, flags); @@ -439,9 +441,9 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (!msg) return -ENOMEM; + msg->max_len = VIRTIO_SCMI_MAX_PDU_SIZE(cinfo); if (tx) { - msg->request = devm_kzalloc(dev, - VIRTIO_SCMI_MAX_PDU_SIZE, + msg->request = devm_kzalloc(dev, msg->max_len, GFP_KERNEL); if (!msg->request) return -ENOMEM; @@ -449,8 +451,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, refcount_set(&msg->users, 1); } - msg->input = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE, - GFP_KERNEL); + msg->input = devm_kzalloc(dev, msg->max_len, GFP_KERNEL); if (!msg->input) return -ENOMEM; From 5654d37268bcbae4727d693e35d8e55e13d96fee Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 28 Oct 2024 12:01:47 +0000 Subject: [PATCH 076/116] dt-bindings: firmware: arm,scmi: Introduce more transport properties Depending on specific hardware and firmware design choices, it may be possible for different platforms to end up having different requirements regarding the same transport characteristics. Introduce max-msg-size and max-msg properties to describe such platform specific transport constraints, since they cannot be discovered otherwise. Reviewed-by: Rob Herring (Arm) Signed-off-by: Cristian Marussi Message-Id: <20241028120151.1301177-4-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- .../devicetree/bindings/firmware/arm,scmi.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml index ff7a6f12cd00..abbd62f1fed0 100644 --- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml +++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml @@ -131,6 +131,21 @@ properties: be a non-zero value if set. minimum: 1 + arm,max-msg-size: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + An optional value, expressed in bytes, representing the maximum size + allowed for the payload of messages transmitted on this transport. + + arm,max-msg: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + An optional value representing the maximum number of concurrent in-flight + messages allowed by this transport; this number represents the maximum + number of concurrently outstanding messages that the server can handle on + this platform. If set, the value should be non-zero. + minimum: 1 + arm,smc-id: $ref: /schemas/types.yaml#/definitions/uint32 description: From c091de2d383a079bc996b8ebbc1d193732fa4897 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 28 Oct 2024 12:01:48 +0000 Subject: [PATCH 077/116] firmware: arm_scmi: Use max_msg and max_msg_size devicetree properties Override the default built-in max_msg and max_msg_size transport properties when the corresponding properties were found to be described in the devicetree. Signed-off-by: Cristian Marussi Message-Id: <20241028120151.1301177-5-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 7d5f0da975c7..ab9b05529339 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -3054,8 +3054,20 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) if (ret && ret != -EINVAL) dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n"); - dev_info(dev, "SCMI max-rx-timeout: %dms\n", - trans->desc->max_rx_timeout_ms); + ret = of_property_read_u32(dev->of_node, "arm,max-msg-size", + &trans->desc->max_msg_size); + if (ret && ret != -EINVAL) + dev_err(dev, "Malformed arm,max-msg-size DT property.\n"); + + ret = of_property_read_u32(dev->of_node, "arm,max-msg", + &trans->desc->max_msg); + if (ret && ret != -EINVAL) + dev_err(dev, "Malformed arm,max-msg DT property.\n"); + + dev_info(dev, + "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n", + trans->desc->max_rx_timeout_ms, trans->desc->max_msg_size, + trans->desc->max_msg); return trans->desc; } From 112ffc78dc8f4519b36853a415bd60fdf77edd1a Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 28 Oct 2024 12:01:49 +0000 Subject: [PATCH 078/116] firmware: arm_scmi: Relocate atomic_threshold to scmi_desc Relocate the atomic_threshold field to scmi_desc and move the related code to scmi_transport_setup. No functional change. Signed-off-by: Cristian Marussi Message-Id: <20241028120151.1301177-6-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 7 +++++++ drivers/firmware/arm_scmi/driver.c | 25 +++++++++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index e2424e65066f..9c7163f26878 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -229,6 +229,12 @@ struct scmi_transport_ops { * be pending simultaneously in the system. May be overridden by the * get_max_msg op. * @max_msg_size: Maximum size of data payload per message that can be handled. + * @atomic_threshold: Optional system wide DT-configured threshold, expressed + * in microseconds, for atomic operations. + * Only SCMI synchronous commands reported by the platform + * to have an execution latency lesser-equal to the threshold + * should be considered for atomic mode operation: such + * decision is finally left up to the SCMI drivers. * @force_polling: Flag to force this whole transport to use SCMI core polling * mechanism instead of completion interrupts even if available. * @sync_cmds_completed_on_ret: Flag to indicate that the transport assures @@ -247,6 +253,7 @@ struct scmi_desc { int max_rx_timeout_ms; int max_msg; int max_msg_size; + unsigned int atomic_threshold; const bool force_polling; const bool sync_cmds_completed_on_ret; const bool atomic_enabled; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index ab9b05529339..1f53ca1f87e3 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -149,12 +149,6 @@ struct scmi_debug_info { * base protocol * @active_protocols: IDR storing device_nodes for protocols actually defined * in the DT and confirmed as implemented by fw. - * @atomic_threshold: Optional system wide DT-configured threshold, expressed - * in microseconds, for atomic operations. - * Only SCMI synchronous commands reported by the platform - * to have an execution latency lesser-equal to the threshold - * should be considered for atomic mode operation: such - * decision is finally left up to the SCMI drivers. * @notify_priv: Pointer to private data structure specific to notifications. * @node: List head * @users: Number of users of this instance @@ -180,7 +174,6 @@ struct scmi_info { struct mutex protocols_mtx; u8 *protocols_imp; struct idr active_protocols; - unsigned int atomic_threshold; void *notify_priv; struct list_head node; int users; @@ -2445,7 +2438,7 @@ static bool scmi_is_transport_atomic(const struct scmi_handle *handle, ret = info->desc->atomic_enabled && is_transport_polling_capable(info->desc); if (ret && atomic_threshold) - *atomic_threshold = info->atomic_threshold; + *atomic_threshold = info->desc->atomic_threshold; return ret; } @@ -2959,7 +2952,7 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) (char **)&dbg->name); debugfs_create_u32("atomic_threshold_us", 0400, top_dentry, - &info->atomic_threshold); + (u32 *)&info->desc->atomic_threshold); debugfs_create_str("type", 0400, trans, (char **)&dbg->type); @@ -3069,6 +3062,13 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) trans->desc->max_rx_timeout_ms, trans->desc->max_msg_size, trans->desc->max_msg); + /* System wide atomic threshold for atomic ops .. if any */ + if (!of_property_read_u32(dev->of_node, "atomic-threshold-us", + &trans->desc->atomic_threshold)) + dev_info(dev, + "SCMI System wide atomic threshold set to %u us\n", + trans->desc->atomic_threshold); + return trans->desc; } @@ -3118,13 +3118,6 @@ static int scmi_probe(struct platform_device *pdev) handle->devm_protocol_acquire = scmi_devm_protocol_acquire; handle->devm_protocol_get = scmi_devm_protocol_get; handle->devm_protocol_put = scmi_devm_protocol_put; - - /* System wide atomic threshold for atomic ops .. if any */ - if (!of_property_read_u32(np, "atomic-threshold-us", - &info->atomic_threshold)) - dev_info(dev, - "SCMI System wide atomic threshold set to %d us\n", - info->atomic_threshold); handle->is_transport_atomic = scmi_is_transport_atomic; /* Setup all channels described in the DT at first */ From b4bd100500c0be2a9ac1655977f54806d1eb8195 Mon Sep 17 00:00:00 2001 From: Nikunj Kela Date: Thu, 5 Sep 2024 11:30:16 -0700 Subject: [PATCH 079/116] dt-bindings: firmware: qcom,scm: document support for SA8255p Add a compatible for the SA8255p platform's Secure Channel Manager firmware interface. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nikunj Kela Link: https://lore.kernel.org/r/20240905183016.3742735-1-quic_nkela@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 1a6278e5571b..4ef7c7114cdd 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -43,6 +43,7 @@ properties: - qcom,scm-msm8998 - qcom,scm-qcm2290 - qcom,scm-qdu1000 + - qcom,scm-sa8255p - qcom,scm-sa8775p - qcom,scm-sar2130p - qcom,scm-sc7180 @@ -205,6 +206,7 @@ allOf: compatible: contains: enum: + - qcom,scm-sa8255p - qcom,scm-sa8775p then: properties: From e81ee454d7650e971c9cf38cdfb3c20186ff505d Mon Sep 17 00:00:00 2001 From: Nikunj Kela Date: Thu, 5 Sep 2024 12:23:28 -0700 Subject: [PATCH 080/116] dt-bindings: soc: qcom: aoss-qmp: document support for SA8255p Add compatible for AOSS QMP representing support on SA8255p. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nikunj Kela Link: https://lore.kernel.org/r/20240905192328.3778542-1-quic_nkela@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 9bf4e0adc620..a6565de499af 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -26,6 +26,7 @@ properties: items: - enum: - qcom,qdu1000-aoss-qmp + - qcom,sa8255p-aoss-qmp - qcom,sa8775p-aoss-qmp - qcom,sar2130p-aoss-qmp - qcom,sc7180-aoss-qmp From 454381b5236c22ff5995aab5db4f640d34f9ea98 Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Mon, 9 Sep 2024 20:29:18 +0800 Subject: [PATCH 081/116] soc: qcom: rpmh-rsc: Simplify code with dev_err_probe() Use dev_err_probe() directly in the driver probe phase, and we don't need to judge if the error code is not equal to -EPROBE_DEFER. This can simplify the code a bit. Signed-off-by: Zhang Zekun Link: https://lore.kernel.org/r/20240909122921.12627-2-zhangzekun11@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index de86009ecd91..cb82e887b51d 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -1045,12 +1045,9 @@ static int rpmh_rsc_probe(struct platform_device *pdev) * do. To avoid adding this check to our children we'll do it now. */ ret = cmd_db_ready(); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Command DB not available (%d)\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Command DB not available\n"); drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); if (!drv) From 876b405004842b10a684f06f967502d20d64384f Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Mon, 9 Sep 2024 20:29:20 +0800 Subject: [PATCH 082/116] soc: qcom: smem: Simplify code with dev_err_probe() Use dev_err_probe() directly in the driver probe phase, and we don't need to judge if the error code is not equal to -EPROBE_DEFER. This can simplify the code a bit. Signed-off-by: Zhang Zekun Link: https://lore.kernel.org/r/20240909122921.12627-4-zhangzekun11@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 0d1ccf3ef108..cfe358a94471 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -1186,11 +1186,9 @@ static int qcom_smem_probe(struct platform_device *pdev) } hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); - if (hwlock_id < 0) { - if (hwlock_id != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to retrieve hwlock\n"); - return hwlock_id; - } + if (hwlock_id < 0) + return dev_err_probe(&pdev->dev, hwlock_id, + "failed to retrieve hwlock\n"); smem->hwlock = hwspin_lock_request_specific(hwlock_id); if (!smem->hwlock) From cd8ec43758a5ca91c5503d1cde2df95e05b968ca Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Mon, 9 Sep 2024 20:29:21 +0800 Subject: [PATCH 083/116] soc: qcom: smp2p: Simplify code with dev_err_probe() Use dev_err_probe() directly in the driver probe phase, and we don't need to judge if the error code is not equal to -EPROBE_DEFER. This can simplify the code a bit. Signed-off-by: Zhang Zekun Link: https://lore.kernel.org/r/20240909122921.12627-5-zhangzekun11@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smp2p.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index cefcbd61c628..2731449e2201 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -467,12 +467,9 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p) int ret; ret = qcom_smem_alloc(pid, smem_id, sizeof(*out)); - if (ret < 0 && ret != -EEXIST) { - if (ret != -EPROBE_DEFER) - dev_err(smp2p->dev, - "unable to allocate local smp2p item\n"); - return ret; - } + if (ret < 0 && ret != -EEXIST) + return dev_err_probe(smp2p->dev, ret, + "unable to allocate local smp2p item\n"); out = qcom_smem_get(pid, smem_id, NULL); if (IS_ERR(out)) { From 729ee76561fd3d0766ab70de92076d7f12f465b9 Mon Sep 17 00:00:00 2001 From: Nikunj Kela Date: Tue, 10 Sep 2024 10:15:32 -0700 Subject: [PATCH 084/116] dt-bindings: arm: qcom: add the SoC ID for SA8255P Add the SoC ID entry for SA8255P. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nikunj Kela Link: https://lore.kernel.org/r/20240910171534.2412263-2-quic_nkela@quicinc.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 1a53ca2df523..f27c96603f91 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -258,6 +258,7 @@ #define QCOM_ID_SAR2130P 525 #define QCOM_ID_SM8475 530 #define QCOM_ID_SM8475P 531 +#define QCOM_ID_SA8255P 532 #define QCOM_ID_SA8775P 534 #define QCOM_ID_QRU1000 539 #define QCOM_ID_SM8475_2 540 From 558e8b82a52c5ca9f54f4470cc67d8ec0b9e9b1c Mon Sep 17 00:00:00 2001 From: Nikunj Kela Date: Tue, 10 Sep 2024 10:15:33 -0700 Subject: [PATCH 085/116] soc: qcom: socinfo: add support for SA8255P Add SocInfo support for SA8255P. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nikunj Kela Link: https://lore.kernel.org/r/20240910171534.2412263-3-quic_nkela@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 37309c8a4591..859d3806d04c 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -425,6 +425,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SAR2130P) }, { qcom_board_id(SM8475) }, { qcom_board_id(SM8475P) }, + { qcom_board_id(SA8255P) }, { qcom_board_id(SA8775P) }, { qcom_board_id(QRU1000) }, { qcom_board_id(SM8475_2) }, From fc0dead9b7ae33ad9266d4a8e43232f673ae8710 Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Wed, 11 Sep 2024 16:03:16 +0800 Subject: [PATCH 086/116] dt-bindings: firmware: qcom,scm: document SCM on QCS8300 SoCs Document scm compatible for the Qualcomm QCS8300 SoC. It is an interface to communicate to the secure firmware. Signed-off-by: Zhenhua Huang Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240911-qcs8300_binding-v2-2-de8641b3eaa1@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 4ef7c7114cdd..4c361789de5d 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -42,6 +42,7 @@ properties: - qcom,scm-msm8996 - qcom,scm-msm8998 - qcom,scm-qcm2290 + - qcom,scm-qcs8300 - qcom,scm-qdu1000 - qcom,scm-sa8255p - qcom,scm-sa8775p From f8b2f3813067733b33b96741167416db5aab9ef3 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Wed, 11 Sep 2024 16:03:17 +0800 Subject: [PATCH 087/116] dt-bindings: soc: qcom: add qcom,qcs8300-imem compatible Document qcom,qcs8300-imem compatible. It has child node for debug purpose. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240911-qcs8300_binding-v2-3-de8641b3eaa1@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/sram/qcom,imem.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index faef3d6e0a94..9b06bcd01957 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -21,6 +21,7 @@ properties: - qcom,msm8226-imem - qcom,msm8974-imem - qcom,qcs404-imem + - qcom,qcs8300-imem - qcom,qdu1000-imem - qcom,sa8775p-imem - qcom,sc7180-imem From 8534231e09b8c3349e1964604472c6b5dc67227c Mon Sep 17 00:00:00 2001 From: Kyle Deng Date: Wed, 11 Sep 2024 16:03:18 +0800 Subject: [PATCH 088/116] dt-bindings: soc: qcom,aoss-qmp: Document the QCS8300 AOSS channel Document the Always-On Subsystem side channel on the Qualcomm QCS8300 platform for communication with client found on the SoC such as remoteprocs. Signed-off-by: Kyle Deng Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240911-qcs8300_binding-v2-4-de8641b3eaa1@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index a6565de499af..e63f800c6caa 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -25,6 +25,7 @@ properties: compatible: items: - enum: + - qcom,qcs8300-aoss-qmp - qcom,qdu1000-aoss-qmp - qcom,sa8255p-aoss-qmp - qcom,sa8775p-aoss-qmp From 8cbebdfe3e794e5b4f3e08a7297a513bf14fec6e Mon Sep 17 00:00:00 2001 From: Tengfei Fan Date: Wed, 11 Sep 2024 19:10:55 +0800 Subject: [PATCH 089/116] dt-bindings: arm: qcom,ids: add SoC ID for QCS9100 Add the ID for the Qualcomm QCS9100 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Tengfei Fan Link: https://lore.kernel.org/r/20240911-add_qcs9100_support-v2-1-e43a71ceb017@quicinc.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index f27c96603f91..b66f8aeb9f47 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -279,6 +279,7 @@ #define QCOM_ID_QCM8550 604 #define QCOM_ID_IPQ5300 624 #define QCOM_ID_IPQ5321 650 +#define QCOM_ID_QCS9100 667 #define QCOM_ID_QCS8300 674 #define QCOM_ID_QCS8275 675 #define QCOM_ID_QCS615 680 From d088afa7de3cbe689954dad49e7058d2c4b8944c Mon Sep 17 00:00:00 2001 From: Tengfei Fan Date: Wed, 11 Sep 2024 19:10:56 +0800 Subject: [PATCH 090/116] soc: qcom: socinfo: add QCS9100 ID Add the ID for the Qualcomm QCS9100 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Tengfei Fan Link: https://lore.kernel.org/r/20240911-add_qcs9100_support-v2-2-e43a71ceb017@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 859d3806d04c..20fa1974824d 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -446,6 +446,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCM8550) }, { qcom_board_id(IPQ5300) }, { qcom_board_id(IPQ5321) }, + { qcom_board_id(QCS9100) }, { qcom_board_id(QCS8300) }, { qcom_board_id(QCS8275) }, { qcom_board_id(QCS615) }, From 511c06e3903563dba4472430e1b586745b6ae238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 29 Oct 2024 08:48:58 +0100 Subject: [PATCH 091/116] soc: Switch back to struct platform_driver::remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 0edb555a65d1 ("platform: Make platform_driver::remove() return void") .remove() is (again) the right callback to implement for platform drivers. Convert all platform drivers below drivers/soc to use .remove(), with the eventual goal to drop struct platform_driver::remove_new(). As .remove() and .remove_new() have the same prototypes, conversion is done by just changing the structure member name in the driver initializer. On the way do a few whitespace changes to make indention consistent. Signed-off-by: Uwe Kleine-König Acked-by: Heiko Stuebner Acked-by: Herve Codina # for fsl/qe/{qmc,tsa}.c Acked-by: Bjorn Andersson # qcom parts Acked-by: Gabriel Somlo Acked-by: Andrew Jeffery # aspeed Link: https://lore.kernel.org/r/20241029074859.509587-2-u.kleine-koenig@baylibre.com Signed-off-by: Arnd Bergmann --- drivers/soc/aspeed/aspeed-lpc-ctrl.c | 2 +- drivers/soc/aspeed/aspeed-lpc-snoop.c | 2 +- drivers/soc/aspeed/aspeed-p2a-ctrl.c | 2 +- drivers/soc/aspeed/aspeed-uart-routing.c | 2 +- drivers/soc/fsl/dpaa2-console.c | 2 +- drivers/soc/fsl/qe/qmc.c | 2 +- drivers/soc/fsl/qe/tsa.c | 2 +- drivers/soc/fujitsu/a64fx-diag.c | 2 +- drivers/soc/hisilicon/kunpeng_hccs.c | 2 +- drivers/soc/ixp4xx/ixp4xx-npe.c | 2 +- drivers/soc/ixp4xx/ixp4xx-qmgr.c | 2 +- drivers/soc/litex/litex_soc_ctrl.c | 2 +- drivers/soc/loongson/loongson2_guts.c | 2 +- drivers/soc/mediatek/mtk-devapc.c | 2 +- drivers/soc/mediatek/mtk-mmsys.c | 2 +- drivers/soc/mediatek/mtk-socinfo.c | 2 +- drivers/soc/microchip/mpfs-sys-controller.c | 2 +- drivers/soc/pxa/ssp.c | 2 +- drivers/soc/qcom/icc-bwmon.c | 2 +- drivers/soc/qcom/llcc-qcom.c | 2 +- drivers/soc/qcom/ocmem.c | 2 +- drivers/soc/qcom/pmic_glink.c | 2 +- drivers/soc/qcom/qcom_aoss.c | 2 +- drivers/soc/qcom/qcom_gsbi.c | 2 +- drivers/soc/qcom/qcom_stats.c | 2 +- drivers/soc/qcom/ramp_controller.c | 4 ++-- drivers/soc/qcom/rmtfs_mem.c | 2 +- drivers/soc/qcom/rpm-proc.c | 2 +- drivers/soc/qcom/rpm_master_stats.c | 2 +- drivers/soc/qcom/smem.c | 2 +- drivers/soc/qcom/smp2p.c | 2 +- drivers/soc/qcom/smsm.c | 6 +++--- drivers/soc/qcom/socinfo.c | 2 +- drivers/soc/rockchip/io-domain.c | 8 ++++---- drivers/soc/samsung/exynos-chipid.c | 4 ++-- drivers/soc/tegra/cbb/tegra194-cbb.c | 2 +- drivers/soc/ti/k3-ringacc.c | 2 +- drivers/soc/ti/knav_dma.c | 4 ++-- drivers/soc/ti/knav_qmss_queue.c | 2 +- drivers/soc/ti/pm33xx.c | 2 +- drivers/soc/ti/pruss.c | 4 ++-- drivers/soc/ti/smartreflex.c | 2 +- drivers/soc/ti/wkup_m3_ipc.c | 2 +- drivers/soc/xilinx/xlnx_event_manager.c | 2 +- drivers/soc/xilinx/zynqmp_power.c | 2 +- 45 files changed, 54 insertions(+), 54 deletions(-) diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c index e87038009d1b..ee58151bd69e 100644 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c @@ -353,7 +353,7 @@ static struct platform_driver aspeed_lpc_ctrl_driver = { .of_match_table = aspeed_lpc_ctrl_match, }, .probe = aspeed_lpc_ctrl_probe, - .remove_new = aspeed_lpc_ctrl_remove, + .remove = aspeed_lpc_ctrl_remove, }; module_platform_driver(aspeed_lpc_ctrl_driver); diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index 888b5840c015..9ab5ba9cf1d6 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -366,7 +366,7 @@ static struct platform_driver aspeed_lpc_snoop_driver = { .of_match_table = aspeed_lpc_snoop_match, }, .probe = aspeed_lpc_snoop_probe, - .remove_new = aspeed_lpc_snoop_remove, + .remove = aspeed_lpc_snoop_remove, }; module_platform_driver(aspeed_lpc_snoop_driver); diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c index 8610ddacc7bc..6cc943744e12 100644 --- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c +++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c @@ -431,7 +431,7 @@ static struct platform_driver aspeed_p2a_ctrl_driver = { .of_match_table = aspeed_p2a_ctrl_match, }, .probe = aspeed_p2a_ctrl_probe, - .remove_new = aspeed_p2a_ctrl_remove, + .remove = aspeed_p2a_ctrl_remove, }; module_platform_driver(aspeed_p2a_ctrl_driver); diff --git a/drivers/soc/aspeed/aspeed-uart-routing.c b/drivers/soc/aspeed/aspeed-uart-routing.c index a2195f062e01..0191e36e66e1 100644 --- a/drivers/soc/aspeed/aspeed-uart-routing.c +++ b/drivers/soc/aspeed/aspeed-uart-routing.c @@ -589,7 +589,7 @@ static struct platform_driver aspeed_uart_routing_driver = { .of_match_table = aspeed_uart_routing_table, }, .probe = aspeed_uart_routing_probe, - .remove_new = aspeed_uart_routing_remove, + .remove = aspeed_uart_routing_remove, }; module_platform_driver(aspeed_uart_routing_driver); diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c index 6dbc77db7718..6310f54e68a2 100644 --- a/drivers/soc/fsl/dpaa2-console.c +++ b/drivers/soc/fsl/dpaa2-console.c @@ -320,7 +320,7 @@ static struct platform_driver dpaa2_console_driver = { .of_match_table = dpaa2_console_match_table, }, .probe = dpaa2_console_probe, - .remove_new = dpaa2_console_remove, + .remove = dpaa2_console_remove, }; module_platform_driver(dpaa2_console_driver); diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 19cc581b06d0..29d7fd7d5b21 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -2092,7 +2092,7 @@ static struct platform_driver qmc_driver = { .of_match_table = of_match_ptr(qmc_id_table), }, .probe = qmc_probe, - .remove_new = qmc_remove, + .remove = qmc_remove, }; module_platform_driver(qmc_driver); diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c index f0889b3fcaf2..515da9b45c2c 100644 --- a/drivers/soc/fsl/qe/tsa.c +++ b/drivers/soc/fsl/qe/tsa.c @@ -1086,7 +1086,7 @@ static struct platform_driver tsa_driver = { .of_match_table = of_match_ptr(tsa_id_table), }, .probe = tsa_probe, - .remove_new = tsa_remove, + .remove = tsa_remove, }; module_platform_driver(tsa_driver); diff --git a/drivers/soc/fujitsu/a64fx-diag.c b/drivers/soc/fujitsu/a64fx-diag.c index 330901893577..76cb0b6a221c 100644 --- a/drivers/soc/fujitsu/a64fx-diag.c +++ b/drivers/soc/fujitsu/a64fx-diag.c @@ -142,7 +142,7 @@ static struct platform_driver a64fx_diag_driver = { .acpi_match_table = ACPI_PTR(a64fx_diag_acpi_match), }, .probe = a64fx_diag_probe, - .remove_new = a64fx_diag_remove, + .remove = a64fx_diag_remove, }; module_platform_driver(a64fx_diag_driver); diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index e882a61636ec..8f51e59c9bb1 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -1348,7 +1348,7 @@ MODULE_DEVICE_TABLE(acpi, hccs_acpi_match); static struct platform_driver hccs_driver = { .probe = hccs_probe, - .remove_new = hccs_remove, + .remove = hccs_remove, .driver = { .name = "kunpeng_hccs", .acpi_match_table = hccs_acpi_match, diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c index 34a6f187c220..33e2e0366f19 100644 --- a/drivers/soc/ixp4xx/ixp4xx-npe.c +++ b/drivers/soc/ixp4xx/ixp4xx-npe.c @@ -759,7 +759,7 @@ static struct platform_driver ixp4xx_npe_driver = { .of_match_table = ixp4xx_npe_of_match, }, .probe = ixp4xx_npe_probe, - .remove_new = ixp4xx_npe_remove, + .remove = ixp4xx_npe_remove, }; module_platform_driver(ixp4xx_npe_driver); diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c index cb112f3643e9..475e229039e3 100644 --- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c +++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c @@ -461,7 +461,7 @@ static struct platform_driver ixp4xx_qmgr_driver = { .of_match_table = ixp4xx_qmgr_of_match, }, .probe = ixp4xx_qmgr_probe, - .remove_new = ixp4xx_qmgr_remove, + .remove = ixp4xx_qmgr_remove, }; module_platform_driver(ixp4xx_qmgr_driver); diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c index 72c44119dd54..d08bfc8ef7be 100644 --- a/drivers/soc/litex/litex_soc_ctrl.c +++ b/drivers/soc/litex/litex_soc_ctrl.c @@ -131,7 +131,7 @@ static struct platform_driver litex_soc_ctrl_driver = { .of_match_table = litex_soc_ctrl_of_match, }, .probe = litex_soc_ctrl_probe, - .remove_new = litex_soc_ctrl_remove, + .remove = litex_soc_ctrl_remove, }; module_platform_driver(litex_soc_ctrl_driver); diff --git a/drivers/soc/loongson/loongson2_guts.c b/drivers/soc/loongson/loongson2_guts.c index ef352a0f5022..ae42e3a9127f 100644 --- a/drivers/soc/loongson/loongson2_guts.c +++ b/drivers/soc/loongson/loongson2_guts.c @@ -169,7 +169,7 @@ static struct platform_driver loongson2_guts_driver = { .of_match_table = loongson2_guts_of_match, }, .probe = loongson2_guts_probe, - .remove_new = loongson2_guts_remove, + .remove = loongson2_guts_remove, }; static int __init loongson2_guts_init(void) diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c index 56cc345552a4..2a1adcb87d4e 100644 --- a/drivers/soc/mediatek/mtk-devapc.c +++ b/drivers/soc/mediatek/mtk-devapc.c @@ -301,7 +301,7 @@ static void mtk_devapc_remove(struct platform_device *pdev) static struct platform_driver mtk_devapc_driver = { .probe = mtk_devapc_probe, - .remove_new = mtk_devapc_remove, + .remove = mtk_devapc_remove, .driver = { .name = "mtk-devapc", .of_match_table = mtk_devapc_dt_match, diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 938240714e54..bb4639ca0b8c 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -487,7 +487,7 @@ static struct platform_driver mtk_mmsys_drv = { .of_match_table = of_match_mtk_mmsys, }, .probe = mtk_mmsys_probe, - .remove_new = mtk_mmsys_remove, + .remove = mtk_mmsys_remove, }; module_platform_driver(mtk_mmsys_drv); diff --git a/drivers/soc/mediatek/mtk-socinfo.c b/drivers/soc/mediatek/mtk-socinfo.c index 74672a9d6d13..123b12cd2543 100644 --- a/drivers/soc/mediatek/mtk-socinfo.c +++ b/drivers/soc/mediatek/mtk-socinfo.c @@ -187,7 +187,7 @@ static void mtk_socinfo_remove(struct platform_device *pdev) static struct platform_driver mtk_socinfo = { .probe = mtk_socinfo_probe, - .remove_new = mtk_socinfo_remove, + .remove = mtk_socinfo_remove, .driver = { .name = "mtk-socinfo", }, diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c index 7a4936019329..30bc45d17d34 100644 --- a/drivers/soc/microchip/mpfs-sys-controller.c +++ b/drivers/soc/microchip/mpfs-sys-controller.c @@ -232,7 +232,7 @@ static struct platform_driver mpfs_sys_controller_driver = { .of_match_table = mpfs_sys_controller_of_match, }, .probe = mpfs_sys_controller_probe, - .remove_new = mpfs_sys_controller_remove, + .remove = mpfs_sys_controller_remove, }; module_platform_driver(mpfs_sys_controller_driver); diff --git a/drivers/soc/pxa/ssp.c b/drivers/soc/pxa/ssp.c index 854d32e04558..bb0062c165fe 100644 --- a/drivers/soc/pxa/ssp.c +++ b/drivers/soc/pxa/ssp.c @@ -197,7 +197,7 @@ static const struct platform_device_id ssp_id_table[] = { static struct platform_driver pxa_ssp_driver = { .probe = pxa_ssp_probe, - .remove_new = pxa_ssp_remove, + .remove = pxa_ssp_remove, .driver = { .name = "pxa2xx-ssp", .of_match_table = of_match_ptr(pxa_ssp_of_ids), diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index f9235bc3aa3b..3dfa448bf8cf 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -872,7 +872,7 @@ MODULE_DEVICE_TABLE(of, bwmon_of_match); static struct platform_driver bwmon_driver = { .probe = bwmon_probe, - .remove_new = bwmon_remove, + .remove = bwmon_remove, .driver = { .name = "qcom-bwmon", .of_match_table = bwmon_of_match, diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8fa4ffd3a9b5..aa90e156b49e 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -1401,7 +1401,7 @@ static struct platform_driver qcom_llcc_driver = { .of_match_table = qcom_llcc_of_match, }, .probe = qcom_llcc_probe, - .remove_new = qcom_llcc_remove, + .remove = qcom_llcc_remove, }; module_platform_driver(qcom_llcc_driver); diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index ff8df7d75d6b..9c3bd37b6579 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -439,7 +439,7 @@ MODULE_DEVICE_TABLE(of, ocmem_of_match); static struct platform_driver ocmem_driver = { .probe = ocmem_dev_probe, - .remove_new = ocmem_dev_remove, + .remove = ocmem_dev_remove, .driver = { .name = "ocmem", .of_match_table = ocmem_of_match, diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 9606222993fd..fa53633ccb4a 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -380,7 +380,7 @@ MODULE_DEVICE_TABLE(of, pmic_glink_of_match); static struct platform_driver pmic_glink_driver = { .probe = pmic_glink_probe, - .remove_new = pmic_glink_remove, + .remove = pmic_glink_remove, .driver = { .name = "qcom_pmic_glink", .of_match_table = pmic_glink_of_match, diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 60af26667bce..0320ad3b9148 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -664,7 +664,7 @@ static struct platform_driver qmp_driver = { .suppress_bind_attrs = true, }, .probe = qmp_probe, - .remove_new = qmp_remove, + .remove = qmp_remove, }; module_platform_driver(qmp_driver); diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c index f04b9a324ea9..8f1158e0c631 100644 --- a/drivers/soc/qcom/qcom_gsbi.c +++ b/drivers/soc/qcom/qcom_gsbi.c @@ -232,7 +232,7 @@ static struct platform_driver gsbi_driver = { .of_match_table = gsbi_dt_match, }, .probe = gsbi_probe, - .remove_new = gsbi_remove, + .remove = gsbi_remove, }; module_platform_driver(gsbi_driver); diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index c429d5154aae..5de99cf59b9f 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, qcom_stats_table); static struct platform_driver qcom_stats = { .probe = qcom_stats_probe, - .remove_new = qcom_stats_remove, + .remove = qcom_stats_remove, .driver = { .name = "qcom_stats", .of_match_table = qcom_stats_table, diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c index e9a0cca07189..349bdfbc61ef 100644 --- a/drivers/soc/qcom/ramp_controller.c +++ b/drivers/soc/qcom/ramp_controller.c @@ -331,8 +331,8 @@ static struct platform_driver qcom_ramp_controller_driver = { .of_match_table = qcom_ramp_controller_match_table, .suppress_bind_attrs = true, }, - .probe = qcom_ramp_controller_probe, - .remove_new = qcom_ramp_controller_remove, + .probe = qcom_ramp_controller_probe, + .remove = qcom_ramp_controller_remove, }; static int __init qcom_ramp_controller_init(void) diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c index df850d073102..33603b8fd8f3 100644 --- a/drivers/soc/qcom/rmtfs_mem.c +++ b/drivers/soc/qcom/rmtfs_mem.c @@ -315,7 +315,7 @@ MODULE_DEVICE_TABLE(of, qcom_rmtfs_mem_of_match); static struct platform_driver qcom_rmtfs_mem_driver = { .probe = qcom_rmtfs_mem_probe, - .remove_new = qcom_rmtfs_mem_remove, + .remove = qcom_rmtfs_mem_remove, .driver = { .name = "qcom_rmtfs_mem", .of_match_table = qcom_rmtfs_mem_of_match, diff --git a/drivers/soc/qcom/rpm-proc.c b/drivers/soc/qcom/rpm-proc.c index 2995d9b90190..2466d0400c2e 100644 --- a/drivers/soc/qcom/rpm-proc.c +++ b/drivers/soc/qcom/rpm-proc.c @@ -53,7 +53,7 @@ MODULE_DEVICE_TABLE(of, rpm_proc_of_match); static struct platform_driver rpm_proc_driver = { .probe = rpm_proc_probe, - .remove_new = rpm_proc_remove, + .remove = rpm_proc_remove, .driver = { .name = "qcom-rpm-proc", .of_match_table = rpm_proc_of_match, diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c index 086fe4ba6707..49e4f9457279 100644 --- a/drivers/soc/qcom/rpm_master_stats.c +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -155,7 +155,7 @@ static const struct of_device_id rpm_master_table[] = { static struct platform_driver master_stats_driver = { .probe = master_stats_probe, - .remove_new = master_stats_remove, + .remove = master_stats_remove, .driver = { .name = "qcom_rpm_master_stats", .of_match_table = rpm_master_table, diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index e4411771f482..e9c690d58d0f 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -1251,7 +1251,7 @@ MODULE_DEVICE_TABLE(of, qcom_smem_of_match); static struct platform_driver qcom_smem_driver = { .probe = qcom_smem_probe, - .remove_new = qcom_smem_remove, + .remove = qcom_smem_remove, .driver = { .name = "qcom-smem", .of_match_table = qcom_smem_of_match, diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index cefcbd61c628..9295a13ae996 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -698,7 +698,7 @@ MODULE_DEVICE_TABLE(of, qcom_smp2p_of_match); static struct platform_driver qcom_smp2p_driver = { .probe = qcom_smp2p_probe, - .remove_new = qcom_smp2p_remove, + .remove = qcom_smp2p_remove, .driver = { .name = "qcom_smp2p", .of_match_table = qcom_smp2p_of_match, diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index ffe78ae34386..e803ea342c97 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -682,9 +682,9 @@ MODULE_DEVICE_TABLE(of, qcom_smsm_of_match); static struct platform_driver qcom_smsm_driver = { .probe = qcom_smsm_probe, - .remove_new = qcom_smsm_remove, - .driver = { - .name = "qcom-smsm", + .remove = qcom_smsm_remove, + .driver = { + .name = "qcom-smsm", .of_match_table = qcom_smsm_of_match, }, }; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 64fc4f41da77..6fa4d103ebbe 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -816,7 +816,7 @@ static void qcom_socinfo_remove(struct platform_device *pdev) static struct platform_driver qcom_socinfo_driver = { .probe = qcom_socinfo_probe, - .remove_new = qcom_socinfo_remove, + .remove = qcom_socinfo_remove, .driver = { .name = "qcom-socinfo", }, diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c index fd9fd31f71c2..f94985a905c2 100644 --- a/drivers/soc/rockchip/io-domain.c +++ b/drivers/soc/rockchip/io-domain.c @@ -742,10 +742,10 @@ static void rockchip_iodomain_remove(struct platform_device *pdev) } static struct platform_driver rockchip_iodomain_driver = { - .probe = rockchip_iodomain_probe, - .remove_new = rockchip_iodomain_remove, - .driver = { - .name = "rockchip-iodomain", + .probe = rockchip_iodomain_probe, + .remove = rockchip_iodomain_remove, + .driver = { + .name = "rockchip-iodomain", .of_match_table = rockchip_iodomain_match, }, }; diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index b1118d37779e..169f94df74bb 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -195,8 +195,8 @@ static struct platform_driver exynos_chipid_driver = { .name = "exynos-chipid", .of_match_table = exynos_chipid_of_device_ids, }, - .probe = exynos_chipid_probe, - .remove_new = exynos_chipid_remove, + .probe = exynos_chipid_probe, + .remove = exynos_chipid_remove, }; module_platform_driver(exynos_chipid_driver); diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c index 9cbc562ae7d3..846b17ffc2f9 100644 --- a/drivers/soc/tegra/cbb/tegra194-cbb.c +++ b/drivers/soc/tegra/cbb/tegra194-cbb.c @@ -2330,7 +2330,7 @@ static const struct dev_pm_ops tegra194_cbb_pm = { static struct platform_driver tegra194_cbb_driver = { .probe = tegra194_cbb_probe, - .remove_new = tegra194_cbb_remove, + .remove = tegra194_cbb_remove, .driver = { .name = "tegra194-cbb", .of_match_table = of_match_ptr(tegra194_cbb_match), diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index 8c0102968351..82a15cad1c6c 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -1562,7 +1562,7 @@ static void k3_ringacc_remove(struct platform_device *pdev) static struct platform_driver k3_ringacc_driver = { .probe = k3_ringacc_probe, - .remove_new = k3_ringacc_remove, + .remove = k3_ringacc_remove, .driver = { .name = "k3-ringacc", .of_match_table = k3_ringacc_of_match, diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index fb0746d8caad..a25ebe6cd503 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -783,8 +783,8 @@ MODULE_DEVICE_TABLE(of, of_match); static struct platform_driver knav_dma_driver = { .probe = knav_dma_probe, - .remove_new = knav_dma_remove, - .driver = { + .remove = knav_dma_remove, + .driver = { .name = "keystone-navigator-dma", .of_match_table = of_match, }, diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 6c98738e548a..c2ad1863048f 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -1894,7 +1894,7 @@ static void knav_queue_remove(struct platform_device *pdev) static struct platform_driver keystone_qmss_driver = { .probe = knav_queue_probe, - .remove_new = knav_queue_remove, + .remove = knav_queue_remove, .driver = { .name = "keystone-navigator-qmss", .of_match_table = keystone_qmss_of_match, diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index 8169885ab1e0..dfdff186c805 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -591,7 +591,7 @@ static struct platform_driver am33xx_pm_driver = { .name = "pm33xx", }, .probe = am33xx_pm_probe, - .remove_new = am33xx_pm_remove, + .remove = am33xx_pm_remove, }; module_platform_driver(am33xx_pm_driver); diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 3ec758f50e24..d7634bf5413a 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -593,8 +593,8 @@ static struct platform_driver pruss_driver = { .name = "pruss", .of_match_table = pruss_of_match, }, - .probe = pruss_probe, - .remove_new = pruss_remove, + .probe = pruss_probe, + .remove = pruss_remove, }; module_platform_driver(pruss_driver); diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index d6219060b616..8b197448e81c 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -969,7 +969,7 @@ MODULE_DEVICE_TABLE(of, omap_sr_match); static struct platform_driver smartreflex_driver = { .probe = omap_sr_probe, - .remove_new = omap_sr_remove, + .remove = omap_sr_remove, .shutdown = omap_sr_shutdown, .driver = { .name = DRIVER_NAME, diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c index 88f774db9208..79dde9a7ec63 100644 --- a/drivers/soc/ti/wkup_m3_ipc.c +++ b/drivers/soc/ti/wkup_m3_ipc.c @@ -755,7 +755,7 @@ MODULE_DEVICE_TABLE(of, wkup_m3_ipc_of_match); static struct platform_driver wkup_m3_ipc_driver = { .probe = wkup_m3_ipc_probe, - .remove_new = wkup_m3_ipc_remove, + .remove = wkup_m3_ipc_remove, .driver = { .name = "wkup_m3_ipc", .of_match_table = wkup_m3_ipc_of_match, diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c index f529e1346247..626b354d79a5 100644 --- a/drivers/soc/xilinx/xlnx_event_manager.c +++ b/drivers/soc/xilinx/xlnx_event_manager.c @@ -709,7 +709,7 @@ static void xlnx_event_manager_remove(struct platform_device *pdev) static struct platform_driver xlnx_event_manager_driver = { .probe = xlnx_event_manager_probe, - .remove_new = xlnx_event_manager_remove, + .remove = xlnx_event_manager_remove, .driver = { .name = "xlnx_event_manager", }, diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c index 411d33f2fb05..ae59bf16659a 100644 --- a/drivers/soc/xilinx/zynqmp_power.c +++ b/drivers/soc/xilinx/zynqmp_power.c @@ -408,7 +408,7 @@ MODULE_DEVICE_TABLE(of, pm_of_match); static struct platform_driver zynqmp_pm_platform_driver = { .probe = zynqmp_pm_probe, - .remove_new = zynqmp_pm_remove, + .remove = zynqmp_pm_remove, .driver = { .name = "zynqmp_power", .of_match_table = pm_of_match, From 53b3e2e0c9a36263be6874203c68bd7bd104663f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 26 Oct 2024 18:43:31 +0300 Subject: [PATCH 092/116] dt-bindings: cache: qcom,llcc: document SAR2130P and SAR1130P Describe the last level cache controller on the SAR2130P and SAR1130P platforms. They have 2 banks and also a separate register set to control scratchpad slice. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241026-sar2130p-llcc-v3-1-2a58fa1b4d12@linaro.org Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/cache/qcom,llcc.yaml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 68ea5f70b75f..2edacf28944c 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -22,6 +22,8 @@ properties: enum: - qcom,qdu1000-llcc - qcom,sa8775p-llcc + - qcom,sar1130p-llcc + - qcom,sar2130p-llcc - qcom,sc7180-llcc - qcom,sc7280-llcc - qcom,sc8180x-llcc @@ -62,6 +64,32 @@ required: - reg-names allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,sar1130p-llcc + - qcom,sar2130p-llcc + then: + properties: + reg: + items: + - description: LLCC0 base register region + - description: LLCC1 base register region + - description: LLCC broadcast OR register region + - description: LLCC broadcast AND register region + - description: LLCC scratchpad broadcast OR register region + - description: LLCC scratchpad broadcast AND register region + reg-names: + items: + - const: llcc0_base + - const: llcc1_base + - const: llcc_broadcast_base + - const: llcc_broadcast_and_base + - const: llcc_scratchpad_broadcast_base + - const: llcc_scratchpad_broadcast_and_base + - if: properties: compatible: From 6dd3f08c72d607372db9b96df95fc6f462981ee2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 26 Oct 2024 18:43:32 +0300 Subject: [PATCH 093/116] soc: qcom: llcc: use deciman integers for bit shift values As pointed out by Konrad Dybcio, we generally should be using decimal numbers to represent bit positions / bit shifts rather than hex numbers. Use decimals for consistency. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241026-sar2130p-llcc-v3-2-2a58fa1b4d12@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 5ac79baab73f..e69bcaf8bffd 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -27,14 +27,14 @@ #define ACT_CTRL_OPCODE_ACTIVATE BIT(0) #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1) #define ACT_CTRL_ACT_TRIG BIT(0) -#define ACT_CTRL_OPCODE_SHIFT 0x01 -#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x02 -#define ATTR1_FIXED_SIZE_SHIFT 0x03 -#define ATTR1_PRIORITY_SHIFT 0x04 -#define ATTR1_MAX_CAP_SHIFT 0x10 +#define ACT_CTRL_OPCODE_SHIFT 1 +#define ATTR1_PROBE_TARGET_WAYS_SHIFT 2 +#define ATTR1_FIXED_SIZE_SHIFT 3 +#define ATTR1_PRIORITY_SHIFT 4 +#define ATTR1_MAX_CAP_SHIFT 16 #define ATTR0_RES_WAYS_MASK GENMASK(15, 0) #define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16) -#define ATTR0_BONUS_WAYS_SHIFT 0x10 +#define ATTR0_BONUS_WAYS_SHIFT 16 #define LLCC_STATUS_READ_DELAY 100 #define CACHE_LINE_SIZE_SHIFT 6 From 1685f685ff8036c74c3b5e9006ec7ceda5bafefa Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 26 Oct 2024 18:43:33 +0300 Subject: [PATCH 094/116] soc: qcom: llcc: add support for SAR2130P and SAR1130P Implement necessary support for the LLCC control on the SAR1130P and SAR2130P platforms. These two platforms use different ATTR1_MAX_CAP shift and also require manual override for num_banks. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241026-sar2130p-llcc-v3-3-2a58fa1b4d12@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 460 ++++++++++++++++++++++++++++- include/linux/soc/qcom/llcc-qcom.h | 12 + 2 files changed, 466 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index e69bcaf8bffd..c0a01904ae4c 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -136,6 +136,8 @@ struct qcom_llcc_config { const struct llcc_slice_config *sct_data; const u32 *reg_offset; const struct llcc_edac_reg_offset *edac_reg_offset; + u32 max_cap_shift; /* instead of ATTR1_MAX_CAP_SHIFT */ + u32 num_banks; int size; bool need_llcc_cfg; bool no_edac; @@ -297,6 +299,408 @@ static const struct llcc_slice_config sa8775p_data[] = { }, }; +static const struct llcc_slice_config sar1130p_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 4096, + .priority = 1, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 3072, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 12800, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 28, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 26, + .max_cap = 2048, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x3, + .cache_mode = true, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 30, + .max_cap = 3072, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x1fff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP_LEFT, + .slice_id = 17, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP_RIGHT, + .slice_id = 18, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVCS_LEFT, + .slice_id = 22, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVCS_RIGHT, + .slice_id = 23, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, +}; + +static const struct llcc_slice_config sar2130p_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 6144, + .priority = 1, + .fixed_size = 0, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 128, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 6, + .max_cap = 1024, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 10, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 1536, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_APTCM, + .slice_id = 26, + .max_cap = 2048, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x3, + .cache_mode = true, + .dis_cap_alloc = true, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_VIEYE, + .slice_id = 7, + .max_cap = 7168, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIDPTH, + .slice_id = 8, + .max_cap = 7168, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPUMV, + .slice_id = 9, + .max_cap = 2048, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVA_LEFT, + .slice_id = 20, + .max_cap = 7168, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0x3ffffffc, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVA_RIGHT, + .slice_id = 21, + .max_cap = 7168, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0x3ffffffc, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVAGAIN, + .slice_id = 25, + .max_cap = 1024, + .priority = 2, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_AENPU, + .slice_id = 30, + .max_cap = 3072, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_VIPTH, + .slice_id = 29, + .max_cap = 1024, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0x3fffffff, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP_LEFT, + .slice_id = 17, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_DISP_RIGHT, + .slice_id = 18, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVCS_LEFT, + .slice_id = 22, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_EVCS_RIGHT, + .slice_id = 23, + .max_cap = 0, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_SPAD, + .slice_id = 24, + .max_cap = 7168, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0x0, + .res_ways = 0x0, + .cache_mode = 0, + .retain_on_pc = true, + }, +}; + static const struct llcc_slice_config sc7180_data[] = { { .usecase_id = LLCC_CPUSS, @@ -2686,6 +3090,30 @@ static const struct qcom_llcc_config sa8775p_cfg[] = { }, }; +static const struct qcom_llcc_config sar1130p_cfg[] = { + { + .sct_data = sar1130p_data, + .size = ARRAY_SIZE(sar1130p_data), + .need_llcc_cfg = true, + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .max_cap_shift = 14, + .num_banks = 2, + }, +}; + +static const struct qcom_llcc_config sar2130p_cfg[] = { + { + .sct_data = sar2130p_data, + .size = ARRAY_SIZE(sar2130p_data), + .need_llcc_cfg = true, + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .max_cap_shift = 14, + .num_banks = 2, + }, +}; + static const struct qcom_llcc_config sc7180_cfg[] = { { .sct_data = sc7180_data, @@ -2837,6 +3265,16 @@ static const struct qcom_sct_config sa8775p_cfgs = { .num_config = ARRAY_SIZE(sa8775p_cfg), }; +static const struct qcom_sct_config sar1130p_cfgs = { + .llcc_config = sar1130p_cfg, + .num_config = ARRAY_SIZE(sar1130p_cfg), +}; + +static const struct qcom_sct_config sar2130p_cfgs = { + .llcc_config = sar2130p_cfg, + .num_config = ARRAY_SIZE(sar2130p_cfg), +}; + static const struct qcom_sct_config sc7180_cfgs = { .llcc_config = sc7180_cfg, .num_config = ARRAY_SIZE(sc7180_cfg), @@ -3144,7 +3582,10 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, */ max_cap_cacheline = max_cap_cacheline / drv_data->num_banks; max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT; - attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT; + if (cfg->max_cap_shift) + attr1_val |= max_cap_cacheline << cfg->max_cap_shift; + else + attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT; attr1_cfg = LLCC_TRP_ATTR1_CFGn(config->slice_id); @@ -3381,12 +3822,17 @@ static int qcom_llcc_probe(struct platform_device *pdev) goto err; cfg = &cfgs->llcc_config[cfg_index]; - ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks); - if (ret) - goto err; + if (cfg->num_banks) { + num_banks = cfg->num_banks; + } else { + ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks); + if (ret) + goto err; + + num_banks &= LLCC_LB_CNT_MASK; + num_banks >>= LLCC_LB_CNT_SHIFT; + } - num_banks &= LLCC_LB_CNT_MASK; - num_banks >>= LLCC_LB_CNT_SHIFT; drv_data->num_banks = num_banks; drv_data->regmaps = devm_kcalloc(dev, num_banks, sizeof(*drv_data->regmaps), GFP_KERNEL); @@ -3483,6 +3929,8 @@ 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_cfgs}, { .compatible = "qcom,sa8775p-llcc", .data = &sa8775p_cfgs }, + { .compatible = "qcom,sar1130p-llcc", .data = &sar1130p_cfgs }, + { .compatible = "qcom,sar2130p-llcc", .data = &sar2130p_cfgs }, { .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfgs }, { .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfgs }, { .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfgs }, diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 9e9f528b1370..a79bfac230c6 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -54,7 +54,19 @@ #define LLCC_CAMEXP4 52 #define LLCC_DISP_WB 53 #define LLCC_DISP_1 54 +#define LLCC_VIEYE 57 +#define LLCC_VIDPTH 58 +#define LLCC_GPUMV 59 +#define LLCC_EVA_LEFT 60 +#define LLCC_EVA_RIGHT 61 +#define LLCC_EVAGAIN 62 +#define LLCC_VIPTH 63 #define LLCC_VIDVSP 64 +#define LLCC_DISP_LEFT 65 +#define LLCC_DISP_RIGHT 66 +#define LLCC_EVCS_LEFT 67 +#define LLCC_EVCS_RIGHT 68 +#define LLCC_SPAD 69 /** * struct llcc_slice_desc - Cache slice descriptor From 08e2d7c64edddbc0b0885be901b3f752ea245587 Mon Sep 17 00:00:00 2001 From: Song Xue Date: Thu, 10 Oct 2024 14:38:39 +0800 Subject: [PATCH 095/116] dt-bindings: cache: qcom,llcc: Document the QCS615 LLCC Document the LLCC on the QCS615 platform. The QCS615 platform has LLCC as the system cache controller. It includes 1 LLCC instance and 1 broadcast interface. Signed-off-by: Song Xue Reviewed-by: Krzysztof Kozlowski Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241010-add_llcc_support_for_qcs615-v2-1-044432450a75@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/cache/qcom,llcc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 2edacf28944c..a79d6699eb07 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -20,6 +20,7 @@ description: | properties: compatible: enum: + - qcom,qcs615-llcc - qcom,qdu1000-llcc - qcom,sa8775p-llcc - qcom,sar1130p-llcc @@ -95,6 +96,7 @@ allOf: compatible: contains: enum: + - qcom,qcs615-llcc - qcom,sc7180-llcc - qcom,sm6350-llcc then: From 9f85ed1976bc7882a300aedb556148dbbb245b96 Mon Sep 17 00:00:00 2001 From: Song Xue Date: Thu, 10 Oct 2024 14:38:40 +0800 Subject: [PATCH 096/116] soc: qcom: llcc: Add configuration data for QCS615 Add LLCC configuration support for the QCS615 platform. Signed-off-by: Song Xue Link: https://lore.kernel.org/r/20241010-add_llcc_support_for_qcs615-v2-2-044432450a75@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index c0a01904ae4c..227e3112455f 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -2628,6 +2628,45 @@ static const struct llcc_slice_config sm8650_data[] = { }, }; +static const struct llcc_slice_config qcs615_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 128, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MDM, + .slice_id = 8, + .max_cap = 256, + .priority = 0, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 128, + .priority = 1, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, +}; + static const struct llcc_slice_config qdu1000_data_2ch[] = { { .usecase_id = LLCC_MDMHPGRW, @@ -3049,6 +3088,16 @@ static const u32 llcc_v2_1_reg_offset[] = { [LLCC_COMMON_STATUS0] = 0x0003400c, }; +static const struct qcom_llcc_config qcs615_cfg[] = { + { + .sct_data = qcs615_data, + .size = ARRAY_SIZE(qcs615_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 qdu1000_cfg[] = { { .sct_data = qdu1000_data_8ch, @@ -3255,6 +3304,11 @@ static const struct qcom_llcc_config x1e80100_cfg[] = { }, }; +static const struct qcom_sct_config qcs615_cfgs = { + .llcc_config = qcs615_cfg, + .num_config = ARRAY_SIZE(qcs615_cfg), +}; + static const struct qcom_sct_config qdu1000_cfgs = { .llcc_config = qdu1000_cfg, .num_config = ARRAY_SIZE(qdu1000_cfg), @@ -3927,6 +3981,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) } static const struct of_device_id qcom_llcc_of_match[] = { + { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, { .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, { .compatible = "qcom,sa8775p-llcc", .data = &sa8775p_cfgs }, { .compatible = "qcom,sar1130p-llcc", .data = &sar1130p_cfgs }, From a83e18ca83583ce191848ee73975894d43093cde Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 31 Oct 2024 15:14:36 +0800 Subject: [PATCH 097/116] dt-bindings: cache: qcom,llcc: Document the QCS8300 LLCC Document the Last Level Cache Controller on QCS8300 platform. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/r/20241031-qcs8300_llcc-v3-1-bb56952cb83b@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/cache/qcom,llcc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index a79d6699eb07..276c375c30b4 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -21,6 +21,7 @@ properties: compatible: enum: - qcom,qcs615-llcc + - qcom,qcs8300-llcc - qcom,qdu1000-llcc - qcom,sa8775p-llcc - qcom,sar1130p-llcc @@ -195,6 +196,7 @@ allOf: compatible: contains: enum: + - qcom,qcs8300-llcc - qcom,sdm845-llcc - qcom,sm8150-llcc - qcom,sm8250-llcc From 584e936feedfcf678510a749f407115bdc811fbd Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 31 Oct 2024 15:14:37 +0800 Subject: [PATCH 098/116] soc: qcom: llcc: Add LLCC configuration for the QCS8300 platform Add LLCC configuration for the QCS8300 platform. There is an errata on LB_CNT information on QCS8300 platform, hardcode num_banks to get the correct value. Signed-off-by: Jingyi Wang Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241031-qcs8300_llcc-v3-2-bb56952cb83b@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 227e3112455f..316645c0d26d 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -2667,6 +2667,56 @@ static const struct llcc_slice_config qcs615_data[] = { }, }; +static const struct llcc_slice_config qcs8300_data[] = { + { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 12, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .retain_on_pc = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MMUHWT, + .slice_id = 13, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 128, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf, + .cache_mode = 0, + .activate_on_init = true, + }, +}; + static const struct llcc_slice_config qdu1000_data_2ch[] = { { .usecase_id = LLCC_MDMHPGRW, @@ -3098,6 +3148,17 @@ static const struct qcom_llcc_config qcs615_cfg[] = { }, }; +static const struct qcom_llcc_config qcs8300_cfg[] = { + { + .sct_data = qcs8300_data, + .size = ARRAY_SIZE(qcs8300_data), + .need_llcc_cfg = true, + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .num_banks = 4, + }, +}; + static const struct qcom_llcc_config qdu1000_cfg[] = { { .sct_data = qdu1000_data_8ch, @@ -3309,6 +3370,11 @@ static const struct qcom_sct_config qcs615_cfgs = { .num_config = ARRAY_SIZE(qcs615_cfg), }; +static const struct qcom_sct_config qcs8300_cfgs = { + .llcc_config = qcs8300_cfg, + .num_config = ARRAY_SIZE(qcs8300_cfg), +}; + static const struct qcom_sct_config qdu1000_cfgs = { .llcc_config = qdu1000_cfg, .num_config = ARRAY_SIZE(qdu1000_cfg), @@ -3982,6 +4048,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, + { .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs}, { .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, { .compatible = "qcom,sa8775p-llcc", .data = &sa8775p_cfgs }, { .compatible = "qcom,sar1130p-llcc", .data = &sar1130p_cfgs }, From 344ea0d36b8c9cb7668b002570159efe78a922c1 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 29 Oct 2024 09:43:35 +0100 Subject: [PATCH 099/116] misc: lan966x_pci: Fix dtc warns 'missing or empty reg/ranges property' dtc generates the following warnings when building the LAN966x device tree overlay (lan966x_pci.dtso): Warning (simple_bus_reg): /fragment@0/__overlay__/pci-ep-bus@0/cpu_clk: missing or empty reg/ranges property Warning (simple_bus_reg): /fragment@0/__overlay__/pci-ep-bus@0/ddr_clk: missing or empty reg/ranges property Warning (simple_bus_reg): /fragment@0/__overlay__/pci-ep-bus@0/sys_clk: missing or empty reg/ranges property Indeed, related nodes are under the pci-ep-bus (simple-bus) which is not correct. Put them outside this node. Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/all/20241025110919.64b1cffb@canb.auug.org.au/ Fixes: 185686beb464 ("misc: Add support for LAN966x PCI device") Signed-off-by: Herve Codina Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241029084338.194942-2-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/misc/lan966x_pci.dtso | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/misc/lan966x_pci.dtso b/drivers/misc/lan966x_pci.dtso index 7282687df25f..e9b304c6ced3 100644 --- a/drivers/misc/lan966x_pci.dtso +++ b/drivers/misc/lan966x_pci.dtso @@ -19,6 +19,24 @@ __overlay__ { #address-cells = <3>; #size-cells = <2>; + cpu_clk: clock-600000000 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <600000000>; /* CPU clock = 600MHz */ + }; + + ddr_clk: clock-30000000 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; /* Fabric clock = 30MHz */ + }; + + sys_clk: clock-15625000 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <15625000>; /* System clock = 15.625MHz */ + }; + pci-ep-bus@0 { compatible = "simple-bus"; #address-cells = <1>; @@ -39,24 +57,6 @@ oic: oic@e00c0120 { reg = <0xe00c0120 0x190>; }; - cpu_clk: cpu_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <600000000>; // CPU clock = 600MHz - }; - - ddr_clk: ddr_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <30000000>; // Fabric clock = 30MHz - }; - - sys_clk: sys_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <15625000>; // System clock = 15.625MHz - }; - cpu_ctrl: syscon@e00c0000 { compatible = "microchip,lan966x-cpu-syscon", "syscon"; reg = <0xe00c0000 0xa8>; From cf3e10cc0e88bba51d330ef851bcffa0bce1070c Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 29 Oct 2024 09:43:36 +0100 Subject: [PATCH 100/116] misc: lan966x_pci: Fix dtc warn 'Missing interrupt-parent' dtc generates the following warning when building the LAN966x devicetree overlay (lan966x_pci.dtso): Warning (interrupts_property): /fragment@0/__overlay__/pci-ep-bus@0/oic@e00c0120: Missing interrupt-parent The oic interrupt parent is the PCI device itself. The PCI device node is the node on which the dtbo will be applied and this node already has properties needed. In order to remove the warning, add the missing properties in the overlay fragment node. Properties in this node will not be added when the overlay is applied (which is what we expect) but makes dtc happy. Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/all/20241025110919.64b1cffb@canb.auug.org.au/ Fixes: 185686beb464 ("misc: Add support for LAN966x PCI device") Signed-off-by: Herve Codina Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241029084338.194942-3-herve.codina@bootlin.com Signed-off-by: Philipp Zabel --- drivers/misc/lan966x_pci.dtso | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/misc/lan966x_pci.dtso b/drivers/misc/lan966x_pci.dtso index e9b304c6ced3..7b196b0a0eb6 100644 --- a/drivers/misc/lan966x_pci.dtso +++ b/drivers/misc/lan966x_pci.dtso @@ -15,6 +15,16 @@ / { fragment@0 { target-path = ""; + + /* + * These properties allow to avoid a dtc warnings. + * The real interrupt controller is the PCI device itself. It + * is the node on which the device tree overlay will be applied. + * This node has those properties. + */ + #interrupt-cells = <1>; + interrupt-controller; + __overlay__ { #address-cells = <3>; #size-cells = <2>; From 75837f0b2bc61c62c8326fe3a1eb9a100714cfd7 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Fri, 25 Oct 2024 18:02:26 +0530 Subject: [PATCH 101/116] firmware: qcom: uefisecapp: Allow X1E Devkit devices Add X1E Devkit to the allowlist. Signed-off-by: Sibi Sankar Acked-by: Marc Zyngier Tested-by: Marc Zyngier Tested-by: Jens Glathe Link: https://lore.kernel.org/r/20241025123227.3527720-3-quic_sibis@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index bf86df2a0639..bdb42eb2e1e8 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1740,6 +1740,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, { .compatible = "qcom,sc8180x-primus" }, + { .compatible = "qcom,x1e001de-devkit" }, { .compatible = "qcom,x1e80100-crd" }, { .compatible = "qcom,x1e80100-qcp" }, { } From 4cadd106208143a919c957171a0634e16fd32f82 Mon Sep 17 00:00:00 2001 From: Melody Olvera Date: Mon, 21 Oct 2024 16:04:27 -0700 Subject: [PATCH 102/116] dt-bindings: firmware: qcom,scm: Document sm8750 SCM Document the scm compatible for sm8750 SoC. Signed-off-by: Melody Olvera Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241021230427.2632466-1-quic_molvera@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 4c361789de5d..2ee030000007 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -67,6 +67,7 @@ properties: - qcom,scm-sm8450 - qcom,scm-sm8550 - qcom,scm-sm8650 + - qcom,scm-sm8750 - qcom,scm-qcs404 - qcom,scm-x1e80100 - const: qcom,scm @@ -198,6 +199,7 @@ allOf: - qcom,scm-sm8450 - qcom,scm-sm8550 - qcom,scm-sm8650 + - qcom,scm-sm8750 then: properties: interrupts: false From 92f3397c8c8d63fefe0d045425ad54c5ee5d57bb Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 4 Nov 2024 16:10:53 +0100 Subject: [PATCH 103/116] soc: qcom: llcc: Flip the manual slice configuration condition Commit c14e64b46944 ("soc: qcom: llcc: Support chipsets that can write to llcc") made the code not configure certain registers on SDM845 due to firmware security policies. That turned out only to concern SDM845, but the condition was chosen such that all other entries (for SoCs that didnot need it) were required to set .need_llcc_cfg = true. Flip the condition, so the default is "doesn't need the workaround". Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20241104-topic-llcc_flip-v1-1-3003c846d131@oss.qualcomm.com [bjorn: Dropped a few newly added need_llcc_cfg uses] Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 316645c0d26d..4cd6dacfed8f 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -139,7 +139,7 @@ struct qcom_llcc_config { u32 max_cap_shift; /* instead of ATTR1_MAX_CAP_SHIFT */ u32 num_banks; int size; - bool need_llcc_cfg; + bool skip_llcc_cfg; bool no_edac; }; @@ -3142,7 +3142,6 @@ static const struct qcom_llcc_config qcs615_cfg[] = { { .sct_data = qcs615_data, .size = ARRAY_SIZE(qcs615_data), - .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, .edac_reg_offset = &llcc_v1_edac_reg_offset, }, @@ -3152,7 +3151,6 @@ static const struct qcom_llcc_config qcs8300_cfg[] = { { .sct_data = qcs8300_data, .size = ARRAY_SIZE(qcs8300_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, .num_banks = 4, @@ -3163,28 +3161,24 @@ 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, }, @@ -3194,7 +3188,6 @@ static const struct qcom_llcc_config sa8775p_cfg[] = { { .sct_data = sa8775p_data, .size = ARRAY_SIZE(sa8775p_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }, @@ -3204,7 +3197,6 @@ static const struct qcom_llcc_config sar1130p_cfg[] = { { .sct_data = sar1130p_data, .size = ARRAY_SIZE(sar1130p_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, .max_cap_shift = 14, @@ -3216,7 +3208,6 @@ static const struct qcom_llcc_config sar2130p_cfg[] = { { .sct_data = sar2130p_data, .size = ARRAY_SIZE(sar2130p_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, .max_cap_shift = 14, @@ -3228,7 +3219,6 @@ 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, }, @@ -3238,7 +3228,6 @@ 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, }, @@ -3248,7 +3237,6 @@ 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, }, @@ -3258,7 +3246,6 @@ 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, }, @@ -3268,7 +3255,7 @@ static const struct qcom_llcc_config sdm845_cfg[] = { { .sct_data = sdm845_data, .size = ARRAY_SIZE(sdm845_data), - .need_llcc_cfg = false, + .skip_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, .edac_reg_offset = &llcc_v1_edac_reg_offset, .no_edac = true, @@ -3279,7 +3266,6 @@ 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, }, @@ -3289,7 +3275,6 @@ 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, }, @@ -3299,7 +3284,6 @@ 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, }, @@ -3309,7 +3293,6 @@ 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, }, @@ -3319,7 +3302,6 @@ 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, }, @@ -3329,7 +3311,6 @@ 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, }, @@ -3339,7 +3320,6 @@ 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, }, @@ -3349,7 +3329,6 @@ static const struct qcom_llcc_config sm8650_cfg[] = { { .sct_data = sm8650_data, .size = ARRAY_SIZE(sm8650_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }, @@ -3359,7 +3338,6 @@ static const struct qcom_llcc_config x1e80100_cfg[] = { { .sct_data = x1e80100_data, .size = ARRAY_SIZE(x1e80100_data), - .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }, @@ -3734,7 +3712,8 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } - if (cfg->need_llcc_cfg) { + /* At least SDM845 disallows non-secure writes to these registers */ + if (!cfg->skip_llcc_cfg) { u32 disable_cap_alloc, retain_pc; disable_cap_alloc = config->dis_cap_alloc << config->slice_id; From c9cfca98998eb1cd14bdeccd607982ae818711e7 Mon Sep 17 00:00:00 2001 From: Manikanta Mylavarapu Date: Wed, 16 Oct 2024 20:45:26 +0530 Subject: [PATCH 104/116] dt-bindings: arm: qcom,ids: add SoC ID for IPQ5424/IPQ5404 Add the ID for Qualcomm IPQ5424/IPQ5404 SoC. Signed-off-by: Manikanta Mylavarapu Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241016151528.2893599-2-quic_mmanikan@quicinc.com Signed-off-by: Bjorn Andersson --- include/dt-bindings/arm/qcom,ids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index b66f8aeb9f47..e850dc3a1ad3 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -279,6 +279,8 @@ #define QCOM_ID_QCM8550 604 #define QCOM_ID_IPQ5300 624 #define QCOM_ID_IPQ5321 650 +#define QCOM_ID_IPQ5424 651 +#define QCOM_ID_IPQ5404 671 #define QCOM_ID_QCS9100 667 #define QCOM_ID_QCS8300 674 #define QCOM_ID_QCS8275 675 From a8fc655e01b6ca3b596b41ad000c7fead6093ce4 Mon Sep 17 00:00:00 2001 From: Manikanta Mylavarapu Date: Wed, 16 Oct 2024 20:45:27 +0530 Subject: [PATCH 105/116] soc: qcom: socinfo: add IPQ5424/IPQ5404 SoC ID Add SoC ID for Qualcomm IPQ5424/IPQ5404. Signed-off-by: Manikanta Mylavarapu Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241016151528.2893599-3-quic_mmanikan@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 20fa1974824d..a78c263906c7 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -446,6 +446,8 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCM8550) }, { qcom_board_id(IPQ5300) }, { qcom_board_id(IPQ5321) }, + { qcom_board_id(IPQ5424) }, + { qcom_board_id(IPQ5404) }, { qcom_board_id(QCS9100) }, { qcom_board_id(QCS8300) }, { qcom_board_id(QCS8275) }, From 109aa654f85c5141e813b2cd1bd36d90be678407 Mon Sep 17 00:00:00 2001 From: Luo Qiu Date: Fri, 1 Nov 2024 11:21:15 +0800 Subject: [PATCH 106/116] firmware: arm_scpi: Check the DVFS OPP count returned by the firmware Fix a kernel crash with the below call trace when the SCPI firmware returns OPP count of zero. dvfs_info.opp_count may be zero on some platforms during the reboot test, and the kernel will crash after dereferencing the pointer to kcalloc(info->count, sizeof(*opp), GFP_KERNEL). | Unable to handle kernel NULL pointer dereference at virtual address 0000000000000028 | Mem abort info: | ESR = 0x96000004 | Exception class = DABT (current EL), IL = 32 bits | SET = 0, FnV = 0 | EA = 0, S1PTW = 0 | Data abort info: | ISV = 0, ISS = 0x00000004 | CM = 0, WnR = 0 | user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000faefa08c | [0000000000000028] pgd=0000000000000000 | Internal error: Oops: 96000004 [#1] SMP | scpi-hwmon: probe of PHYT000D:00 failed with error -110 | Process systemd-udevd (pid: 1701, stack limit = 0x00000000aaede86c) | CPU: 2 PID: 1701 Comm: systemd-udevd Not tainted 4.19.90+ #1 | Hardware name: PHYTIUM LTD Phytium FT2000/4/Phytium FT2000/4, BIOS | pstate: 60000005 (nZCv daif -PAN -UAO) | pc : scpi_dvfs_recalc_rate+0x40/0x58 [clk_scpi] | lr : clk_register+0x438/0x720 | Call trace: | scpi_dvfs_recalc_rate+0x40/0x58 [clk_scpi] | devm_clk_hw_register+0x50/0xa0 | scpi_clk_ops_init.isra.2+0xa0/0x138 [clk_scpi] | scpi_clocks_probe+0x528/0x70c [clk_scpi] | platform_drv_probe+0x58/0xa8 | really_probe+0x260/0x3d0 | driver_probe_device+0x12c/0x148 | device_driver_attach+0x74/0x98 | __driver_attach+0xb4/0xe8 | bus_for_each_dev+0x88/0xe0 | driver_attach+0x30/0x40 | bus_add_driver+0x178/0x2b0 | driver_register+0x64/0x118 | __platform_driver_register+0x54/0x60 | scpi_clocks_driver_init+0x24/0x1000 [clk_scpi] | do_one_initcall+0x54/0x220 | do_init_module+0x54/0x1c8 | load_module+0x14a4/0x1668 | __se_sys_finit_module+0xf8/0x110 | __arm64_sys_finit_module+0x24/0x30 | el0_svc_common+0x78/0x170 | el0_svc_handler+0x38/0x78 | el0_svc+0x8/0x340 | Code: 937d7c00 a94153f3 a8c27bfd f9400421 (b8606820) | ---[ end trace 06feb22469d89fa8 ]--- | Kernel panic - not syncing: Fatal exception | SMP: stopping secondary CPUs | Kernel Offset: disabled | CPU features: 0x10,a0002008 | Memory Limit: none Fixes: 8cb7cf56c9fe ("firmware: add support for ARM System Control and Power Interface(SCPI) protocol") Signed-off-by: Luo Qiu Message-Id: <55A2F7A784391686+20241101032115.275977-1-luoqiu@kylinsec.com.cn> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 94a6b4e667de..f4d47577f83e 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -630,6 +630,9 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) if (ret) return ERR_PTR(ret); + if (!buf.opp_count) + return ERR_PTR(-ENOENT); + info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return ERR_PTR(-ENOMEM); From 1af75b2ad08bd5977c51c2d0fc11741a4c0a48d9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 10 Nov 2024 09:33:40 -0800 Subject: [PATCH 107/116] firmware: qcom: scm: Introduce CP_SMMU_APERTURE_ID The QCOM_SCM_SVC_MP service provides QCOM_SCM_MP_CP_SMMU_APERTURE_ID, which is used to trigger the mapping of register banks into the SMMU context for per-processes page tables to function (in case this isn't statically setup by firmware). This is necessary on e.g. QCS6490 Rb3Gen2, in order to avoid "CP | AHB bus error"-errors from the GPU. Introduce a function to allow the msm driver to invoke this call. Signed-off-by: Bjorn Andersson Reviewed-by: Rob Clark Link: https://lore.kernel.org/r/20241110-adreno-smmu-aparture-v2-1-9b1fb2ee41d4@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.c | 26 ++++++++++++++++++++++++++ drivers/firmware/qcom/qcom_scm.h | 1 + include/linux/firmware/qcom/qcom_scm.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index bdb42eb2e1e8..596a8acf0899 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -903,6 +903,32 @@ int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) } EXPORT_SYMBOL_GPL(qcom_scm_restore_sec_cfg); +#define QCOM_SCM_CP_APERTURE_CONTEXT_MASK GENMASK(7, 0) + +bool qcom_scm_set_gpu_smmu_aperture_is_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP, + QCOM_SCM_MP_CP_SMMU_APERTURE_ID); +} +EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture_is_available); + +int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID, + .arginfo = QCOM_SCM_ARGS(4), + .args[0] = 0xffff0000 | FIELD_PREP(QCOM_SCM_CP_APERTURE_CONTEXT_MASK, context_bank), + .args[1] = 0xffffffff, + .args[2] = 0xffffffff, + .args[3] = 0xffffffff, + .owner = ARM_SMCCC_OWNER_SIP + }; + + return qcom_scm_call(__scm->dev, &desc, NULL); +} +EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture); + int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index 685b8f59e7a6..e36b2f67607f 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -116,6 +116,7 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void); #define QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE 0x05 #define QCOM_SCM_MP_VIDEO_VAR 0x08 #define QCOM_SCM_MP_ASSIGN 0x16 +#define QCOM_SCM_MP_CP_SMMU_APERTURE_ID 0x1b #define QCOM_SCM_MP_SHM_BRIDGE_ENABLE 0x1c #define QCOM_SCM_MP_SHM_BRIDGE_DELETE 0x1d #define QCOM_SCM_MP_SHM_BRIDGE_CREATE 0x1e diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 9f14976399ab..4621aec0328c 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -85,6 +85,8 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); bool qcom_scm_restore_sec_cfg_available(void); int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); +int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank); +bool qcom_scm_set_gpu_smmu_aperture_is_available(void); int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size); From 98e5b7f98356cef2f13b54862ca9ac016b71ff06 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 10 Nov 2024 09:33:41 -0800 Subject: [PATCH 108/116] drm/msm/adreno: Setup SMMU aparture for per-process page table Support for per-process page tables requires the SMMU aparture to be setup such that the GPU can make updates with the SMMU. On some targets this is done statically in firmware, on others it's expected to be requested in runtime by the driver, through a SCM call. One place where configuration is expected to be done dynamically is the QCS6490 rb3gen2. The downstream driver does this unconditioanlly on any A6xx and newer, so follow suite and make the call. Signed-off-by: Bjorn Andersson Reviewed-by: Rob Clark Link: https://lore.kernel.org/r/20241110-adreno-smmu-aparture-v2-2-9b1fb2ee41d4@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 465a4cd14a43..3a40b38f2467 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -572,8 +572,19 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu, int adreno_hw_init(struct msm_gpu *gpu) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + int ret; + VERB("%s", gpu->name); + if (adreno_gpu->info->family >= ADRENO_6XX_GEN1 && + qcom_scm_set_gpu_smmu_aperture_is_available()) { + /* We currently always use context bank 0, so hard code this */ + ret = qcom_scm_set_gpu_smmu_aperture(0); + if (ret) + DRM_DEV_ERROR(gpu->dev->dev, "unable to set SMMU aperture: %d\n", ret); + } + for (int i = 0; i < gpu->nr_rings; i++) { struct msm_ringbuffer *ring = gpu->rb[i]; From 54a8cd0f92068a3718092f68c8ae99e2078f44b6 Mon Sep 17 00:00:00 2001 From: Joe Hattori Date: Wed, 30 Oct 2024 11:50:46 +0900 Subject: [PATCH 109/116] soc: qcom: ice: Remove the device_link field in qcom_ice The struct device_link *link field in struct qcom_ice is only used to store the result of a device_link_add call with the DL_FLAG_AUTOREMOVE_SUPPLIER flag. With this flag, the resulting value can only be used to check whether the link is present or not, as per the device_link_add description, hence this commit removes the field. Signed-off-by: Joe Hattori Link: https://lore.kernel.org/r/20241030025046.303342-1-joe@pf.is.s.u-tokyo.ac.jp Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ice.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index 50be7a9274a1..393d2d1d275f 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -44,7 +44,6 @@ struct qcom_ice { struct device *dev; void __iomem *base; - struct device_link *link; struct clk *core_clk; }; @@ -268,6 +267,7 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev) struct qcom_ice *ice; struct resource *res; void __iomem *base; + struct device_link *link; if (!dev || !dev->of_node) return ERR_PTR(-ENODEV); @@ -311,8 +311,8 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev) return ERR_PTR(-EPROBE_DEFER); } - ice->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER); - if (!ice->link) { + link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER); + if (!link) { dev_err(&pdev->dev, "Failed to create device link to consumer %s\n", dev_name(dev)); From 1fac9f8b7d28402c5f29173f06a784cd3b561e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 12 Nov 2024 09:35:19 +0100 Subject: [PATCH 110/116] bus: Switch back to struct platform_driver::remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 0edb555a65d1 ("platform: Make platform_driver::remove() return void") .remove() is (again) the right callback to implement for platform drivers. Convert all platform drivers below drivers/bus to use .remove(), with the eventual goal to drop struct platform_driver::remove_new(). As .remove() and .remove_new() have the same prototypes, conversion is done by just changing the structure member name in the driver initializer. Signed-off-by: Uwe Kleine-König Signed-off-by: Arnd Bergmann --- drivers/bus/fsl-mc/fsl-mc-bus.c | 2 +- drivers/bus/hisi_lpc.c | 2 +- drivers/bus/omap-ocp2scp.c | 2 +- drivers/bus/omap_l3_smx.c | 2 +- drivers/bus/qcom-ssc-block-bus.c | 2 +- drivers/bus/simple-pm-bus.c | 2 +- drivers/bus/sun50i-de2.c | 2 +- drivers/bus/sunxi-rsb.c | 2 +- drivers/bus/tegra-aconnect.c | 2 +- drivers/bus/tegra-gmi.c | 2 +- drivers/bus/ti-pwmss.c | 2 +- drivers/bus/ti-sysc.c | 2 +- drivers/bus/ts-nbus.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 930d8a3ba722..2916d1333649 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -1210,7 +1210,7 @@ static struct platform_driver fsl_mc_bus_driver = { .acpi_match_table = fsl_mc_bus_acpi_match_table, }, .probe = fsl_mc_bus_probe, - .remove_new = fsl_mc_bus_remove, + .remove = fsl_mc_bus_remove, .shutdown = fsl_mc_bus_remove, }; diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 09340adbacc2..53dd1573e323 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -689,6 +689,6 @@ static struct platform_driver hisi_lpc_driver = { .acpi_match_table = hisi_lpc_acpi_match, }, .probe = hisi_lpc_probe, - .remove_new = hisi_lpc_remove, + .remove = hisi_lpc_remove, }; builtin_platform_driver(hisi_lpc_driver); diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c index 7d7479ba0a75..e4dfda7b3b10 100644 --- a/drivers/bus/omap-ocp2scp.c +++ b/drivers/bus/omap-ocp2scp.c @@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, omap_ocp2scp_id_table); static struct platform_driver omap_ocp2scp_driver = { .probe = omap_ocp2scp_probe, - .remove_new = omap_ocp2scp_remove, + .remove = omap_ocp2scp_remove, .driver = { .name = "omap-ocp2scp", .of_match_table = of_match_ptr(omap_ocp2scp_id_table), diff --git a/drivers/bus/omap_l3_smx.c b/drivers/bus/omap_l3_smx.c index ee6d29925e4d..7f0a8f8b3f4c 100644 --- a/drivers/bus/omap_l3_smx.c +++ b/drivers/bus/omap_l3_smx.c @@ -273,7 +273,7 @@ static void omap3_l3_remove(struct platform_device *pdev) static struct platform_driver omap3_l3_driver = { .probe = omap3_l3_probe, - .remove_new = omap3_l3_remove, + .remove = omap3_l3_remove, .driver = { .name = "omap_l3_smx", .of_match_table = of_match_ptr(omap3_l3_match), diff --git a/drivers/bus/qcom-ssc-block-bus.c b/drivers/bus/qcom-ssc-block-bus.c index 5931974a21fa..85d781a32df4 100644 --- a/drivers/bus/qcom-ssc-block-bus.c +++ b/drivers/bus/qcom-ssc-block-bus.c @@ -373,7 +373,7 @@ MODULE_DEVICE_TABLE(of, qcom_ssc_block_bus_of_match); static struct platform_driver qcom_ssc_block_bus_driver = { .probe = qcom_ssc_block_bus_probe, - .remove_new = qcom_ssc_block_bus_remove, + .remove = qcom_ssc_block_bus_remove, .driver = { .name = "qcom-ssc-block-bus", .of_match_table = qcom_ssc_block_bus_of_match, diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c index 50870c827889..5dea31769f9a 100644 --- a/drivers/bus/simple-pm-bus.c +++ b/drivers/bus/simple-pm-bus.c @@ -128,7 +128,7 @@ MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match); static struct platform_driver simple_pm_bus_driver = { .probe = simple_pm_bus_probe, - .remove_new = simple_pm_bus_remove, + .remove = simple_pm_bus_remove, .driver = { .name = "simple-pm-bus", .of_match_table = simple_pm_bus_of_match, diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c index 3339311ce068..dfe588179aca 100644 --- a/drivers/bus/sun50i-de2.c +++ b/drivers/bus/sun50i-de2.c @@ -36,7 +36,7 @@ static const struct of_device_id sun50i_de2_bus_of_match[] = { static struct platform_driver sun50i_de2_bus_driver = { .probe = sun50i_de2_bus_probe, - .remove_new = sun50i_de2_bus_remove, + .remove = sun50i_de2_bus_remove, .driver = { .name = "sun50i-de2-bus", .of_match_table = sun50i_de2_bus_of_match, diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index a89d78925637..7a33c3b31d1e 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -832,7 +832,7 @@ MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); static struct platform_driver sunxi_rsb_driver = { .probe = sunxi_rsb_probe, - .remove_new = sunxi_rsb_remove, + .remove = sunxi_rsb_remove, .driver = { .name = RSB_CTRL_NAME, .of_match_table = sunxi_rsb_of_match_table, diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c index de80008bff92..90e3b0a10816 100644 --- a/drivers/bus/tegra-aconnect.c +++ b/drivers/bus/tegra-aconnect.c @@ -104,7 +104,7 @@ MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match); static struct platform_driver tegra_aconnect_driver = { .probe = tegra_aconnect_probe, - .remove_new = tegra_aconnect_remove, + .remove = tegra_aconnect_remove, .driver = { .name = "tegra-aconnect", .of_match_table = tegra_aconnect_of_match, diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c index f5d6414df9f2..9c09141961d8 100644 --- a/drivers/bus/tegra-gmi.c +++ b/drivers/bus/tegra-gmi.c @@ -303,7 +303,7 @@ MODULE_DEVICE_TABLE(of, tegra_gmi_id_table); static struct platform_driver tegra_gmi_driver = { .probe = tegra_gmi_probe, - .remove_new = tegra_gmi_remove, + .remove = tegra_gmi_remove, .driver = { .name = "tegra-gmi", .of_match_table = tegra_gmi_id_table, diff --git a/drivers/bus/ti-pwmss.c b/drivers/bus/ti-pwmss.c index 4969c556e752..1f2cab91e438 100644 --- a/drivers/bus/ti-pwmss.c +++ b/drivers/bus/ti-pwmss.c @@ -44,7 +44,7 @@ static struct platform_driver pwmss_driver = { .of_match_table = pwmss_of_match, }, .probe = pwmss_probe, - .remove_new = pwmss_remove, + .remove = pwmss_remove, }; module_platform_driver(pwmss_driver); diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 270a94a06e05..f67b927ae4ca 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -3345,7 +3345,7 @@ MODULE_DEVICE_TABLE(of, sysc_match); static struct platform_driver sysc_driver = { .probe = sysc_probe, - .remove_new = sysc_remove, + .remove = sysc_remove, .driver = { .name = "ti-sysc", .of_match_table = sysc_match, diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c index b8af44c5cdbd..2328c48b9b12 100644 --- a/drivers/bus/ts-nbus.c +++ b/drivers/bus/ts-nbus.c @@ -336,7 +336,7 @@ MODULE_DEVICE_TABLE(of, ts_nbus_of_match); static struct platform_driver ts_nbus_driver = { .probe = ts_nbus_probe, - .remove_new = ts_nbus_remove, + .remove = ts_nbus_remove, .driver = { .name = "ts_nbus", .of_match_table = ts_nbus_of_match, From 0efa0fcfe613d2e5ba745b9cf6daa9ba337cd14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 11 Nov 2024 10:53:57 +0100 Subject: [PATCH 111/116] firmware: turris-mox-rwtm: Document the driver private data structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add more comprehensive documentation for the driver private data structure, `struct mox_rwtm`. Signed-off-by: Marek Behún Signed-off-by: Arnd Bergmann --- drivers/firmware/turris-mox-rwtm.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c index f3bc0d427825..47fe6261f5a3 100644 --- a/drivers/firmware/turris-mox-rwtm.c +++ b/drivers/firmware/turris-mox-rwtm.c @@ -61,6 +61,27 @@ enum mbox_cmd { MBOX_CMD_OTP_WRITE = 8, }; +/** + * struct mox_rwtm - driver private data structure + * @mbox_client: rWTM mailbox client + * @mbox: rWTM mailbox channel + * @hwrng: RNG driver structure + * @reply: last mailbox reply, filled in receive callback + * @buf: DMA buffer + * @buf_phys: physical address of the DMA buffer + * @busy: mutex to protect mailbox command execution + * @cmd_done: command done completion + * @has_board_info: whether board information is present + * @serial_number: serial number of the device + * @board_version: board version / revision of the device + * @ram_size: RAM size of the device + * @mac_address1: first MAC address of the device + * @mac_address2: second MAC address of the device + * @has_pubkey: whether board ECDSA public key is present + * @pubkey: board ECDSA public key + * @last_sig: last ECDSA signature generated with board ECDSA private key + * @last_sig_done: whether the last ECDSA signing is complete + */ struct mox_rwtm { struct mbox_client mbox_client; struct mbox_chan *mbox; @@ -74,13 +95,11 @@ struct mox_rwtm { struct mutex busy; struct completion cmd_done; - /* board information */ bool has_board_info; u64 serial_number; int board_version, ram_size; u8 mac_address1[ETH_ALEN], mac_address2[ETH_ALEN]; - /* public key burned in eFuse */ bool has_pubkey; u8 pubkey[135]; From 372eb09cd98555eca6d912db9c678fa509b1dba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 11 Nov 2024 11:39:57 +0100 Subject: [PATCH 112/116] platform: cznic: turris-omnia-mcu: Document the driver private data structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add more comprehensive documentation for the driver private data structure, `struct omnia_mcu`. Signed-off-by: Marek Behún Signed-off-by: Arnd Bergmann --- drivers/platform/cznic/turris-omnia-mcu.h | 42 +++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h index 57ef5d350043..2b13e28ee323 100644 --- a/drivers/platform/cznic/turris-omnia-mcu.h +++ b/drivers/platform/cznic/turris-omnia-mcu.h @@ -23,41 +23,71 @@ struct i2c_client; struct rtc_device; +/** + * struct omnia_mcu - driver private data structure + * @client: I2C client + * @type: MCU type (STM32, GD32, MKL, or unknown) + * @features: bitmap of features supported by the MCU firmware + * @board_serial_number: board serial number, if stored in MCU + * @board_first_mac: board first MAC address, if stored in MCU + * @board_revision: board revision, if stored in MCU + * @gc: GPIO chip + * @lock: mutex to protect internal GPIO chip state + * @mask: bitmap of masked IRQs + * @rising: bitmap of rising edge IRQs + * @falling: bitmap of falling edge IRQs + * @both: bitmap of both edges IRQs + * @cached: bitmap of cached IRQ line values (when an IRQ line is configured for + * both edges, we cache the corresponding GPIO values in the IRQ + * handler) + * @is_cached: bitmap of which IRQ line values are cached + * @button_release_emul_work: front button release emulation work, used with old MCU firmware + * versions which did not send button release events, only button press + * events + * @last_status: cached value of the status word, to be compared with new value to + * determine which interrupt events occurred, used with old MCU + * firmware versions which only informed that the status word changed, + * but not which bits of the status word changed + * @button_pressed_emul: the front button is still emulated to be pressed + * @rtcdev: RTC device, does not actually count real-time, the device is only + * used for the RTC alarm mechanism, so that the board can be + * configured to wake up from poweroff state at a specific time + * @rtc_alarm: RTC alarm that was set for the board to wake up on, in MCU time + * (seconds since last MCU reset) + * @front_button_poweron: the front button should power on the device after it is powered off + * @wdt: watchdog driver structure + * @trng: RNG driver structure + * @trng_entropy_ready: RNG entropy ready completion + */ struct omnia_mcu { struct i2c_client *client; const char *type; u32 features; - /* board information */ u64 board_serial_number; u8 board_first_mac[ETH_ALEN]; u8 board_revision; #ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO - /* GPIO chip */ struct gpio_chip gc; struct mutex lock; unsigned long mask, rising, falling, both, cached, is_cached; - /* Old MCU firmware handling needs the following */ struct delayed_work button_release_emul_work; unsigned long last_status; bool button_pressed_emul; #endif #ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP - /* RTC device for configuring wake-up */ struct rtc_device *rtcdev; u32 rtc_alarm; bool front_button_poweron; #endif #ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG - /* MCU watchdog */ struct watchdog_device wdt; #endif #ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG - /* true random number generator */ struct hwrng trng; struct completion trng_entropy_ready; #endif From f335e0157717490e99145313871db789e8f10bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 11 Nov 2024 13:19:45 +0100 Subject: [PATCH 113/116] platform: cznic: turris-omnia-mcu: Rename variable holding GPIO line names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the `omnia_mcu_gpio_templates` variable to `omnia_mcu_gpio_names`. The array contained templates for the names during the development of the driver, but the template prefix `gpio%u.` was dropped before the driver was merged, since this functionality was broken in gpiolib. Signed-off-by: Marek Behún Signed-off-by: Arnd Bergmann --- drivers/platform/cznic/turris-omnia-mcu-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/cznic/turris-omnia-mcu-gpio.c b/drivers/platform/cznic/turris-omnia-mcu-gpio.c index 88e208d45882..5f35f7c5d5d7 100644 --- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c +++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c @@ -28,7 +28,7 @@ #define OMNIA_CMD_INT_ARG_LEN 8 #define FRONT_BUTTON_RELEASE_DELAY_MS 50 -static const char * const omnia_mcu_gpio_templates[64] = { +static const char * const omnia_mcu_gpio_names[64] = { /* GPIOs with value read from the 16-bit wide status */ [4] = "MiniPCIe0 Card Detect", [5] = "MiniPCIe0 mSATA Indicator", @@ -1018,7 +1018,7 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) mcu->gc.set_multiple = omnia_gpio_set_multiple; mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask; mcu->gc.can_sleep = true; - mcu->gc.names = omnia_mcu_gpio_templates; + mcu->gc.names = omnia_mcu_gpio_names; mcu->gc.base = -1; mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios); mcu->gc.label = "Turris Omnia MCU GPIOs"; From 844d098b6f33666ff544f18d7a256a46fe19328d Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Wed, 2 Oct 2024 22:21:51 +0200 Subject: [PATCH 114/116] soc: fsl: cpm1: tsa: switch to for_each_available_child_of_node_scoped() The non-scoped variant of this macro turns error-prone as soon as error paths are included, because explicit calls to of_node_put() are required to avoid leaking memory. Using its scoped counterpart simplifies the code by removing the need of explicit calls to of_node_put(), as they are automatically triggered as soon as the child node goes out of scope. Moreover, it is more robust as it accounts for new error paths without having to worry about decrementing the object's refcount. Note that the device_node is declared within the macro, and its explicit declaration can be dropped as well if it is not used anywhere else. Signed-off-by: Javier Carrasco Acked-by: Herve Codina Link: https://lore.kernel.org/r/20241002-tsa-scoped-v1-1-ba6a6d657f82@gmail.com Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/tsa.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c index f0889b3fcaf2..a1140aadfd6c 100644 --- a/drivers/soc/fsl/qe/tsa.c +++ b/drivers/soc/fsl/qe/tsa.c @@ -680,7 +680,6 @@ static inline int tsa_of_parse_tdm_tx_route(struct tsa *tsa, static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) { - struct device_node *tdm_np; struct tsa_tdm *tdm; struct clk *clk; u32 tdm_id, val; @@ -691,11 +690,10 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) tsa->tdm[i].is_enable = false; - for_each_available_child_of_node(np, tdm_np) { + for_each_available_child_of_node_scoped(np, tdm_np) { ret = of_property_read_u32(tdm_np, "reg", &tdm_id); if (ret) { dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); - of_node_put(tdm_np); return ret; } switch (tdm_id) { @@ -719,16 +717,14 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) invalid_tdm: dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np, tdm_id); - of_node_put(tdm_np); return -EINVAL; } } - for_each_available_child_of_node(np, tdm_np) { + for_each_available_child_of_node_scoped(np, tdm_np) { ret = of_property_read_u32(tdm_np, "reg", &tdm_id); if (ret) { dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); - of_node_put(tdm_np); return ret; } @@ -742,14 +738,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) dev_err(tsa->dev, "%pOF: failed to read fsl,rx-frame-sync-delay-bits\n", tdm_np); - of_node_put(tdm_np); return ret; } if (val > 3) { dev_err(tsa->dev, "%pOF: Invalid fsl,rx-frame-sync-delay-bits (%u)\n", tdm_np, val); - of_node_put(tdm_np); return -EINVAL; } tdm->simode_tdm |= TSA_SIMODE_TDM_RFSD(val); @@ -761,14 +755,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) dev_err(tsa->dev, "%pOF: failed to read fsl,tx-frame-sync-delay-bits\n", tdm_np); - of_node_put(tdm_np); return ret; } if (val > 3) { dev_err(tsa->dev, "%pOF: Invalid fsl,tx-frame-sync-delay-bits (%u)\n", tdm_np, val); - of_node_put(tdm_np); return -EINVAL; } tdm->simode_tdm |= TSA_SIMODE_TDM_TFSD(val); @@ -792,13 +784,11 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rsync" : "l1rsync"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - of_node_put(tdm_np); goto err; } ret = clk_prepare_enable(clk); if (ret) { clk_put(clk); - of_node_put(tdm_np); goto err; } tdm->l1rsync_clk = clk; @@ -806,13 +796,11 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rclk" : "l1rclk"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - of_node_put(tdm_np); goto err; } ret = clk_prepare_enable(clk); if (ret) { clk_put(clk); - of_node_put(tdm_np); goto err; } tdm->l1rclk_clk = clk; @@ -821,13 +809,11 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tsync" : "l1tsync"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - of_node_put(tdm_np); goto err; } ret = clk_prepare_enable(clk); if (ret) { clk_put(clk); - of_node_put(tdm_np); goto err; } tdm->l1tsync_clk = clk; @@ -835,13 +821,11 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tclk" : "l1tclk"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - of_node_put(tdm_np); goto err; } ret = clk_prepare_enable(clk); if (ret) { clk_put(clk); - of_node_put(tdm_np); goto err; } tdm->l1tclk_clk = clk; @@ -859,16 +843,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np) } ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id); - if (ret) { - of_node_put(tdm_np); + if (ret) goto err; - } ret = tsa_of_parse_tdm_tx_route(tsa, tdm_np, tsa->tdms, tdm_id); - if (ret) { - of_node_put(tdm_np); + if (ret) goto err; - } tdm->is_enable = true; } From c9f1efabf8e3b3ff886a42669f7093789dbeca94 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Sun, 13 Oct 2024 15:29:17 +0200 Subject: [PATCH 115/116] soc: fsl: rcpm: fix missing of_node_put() in copy_ippdexpcr1_setting() of_find_compatible_node() requires a call to of_node_put() when the pointer to the node is not required anymore to decrement its refcount and avoid leaking memory. Add the missing call to of_node_put() after the node has been used. Cc: stable@vger.kernel.org Fixes: e95f287deed2 ("soc: fsl: handle RCPM errata A-008646 on SoC LS1021A") Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20241013-rcpm-of_node_put-v1-1-9a8e55a01eae@gmail.com Signed-off-by: Christophe Leroy --- drivers/soc/fsl/rcpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c index 3d0cae30c769..06bd94b29fb3 100644 --- a/drivers/soc/fsl/rcpm.c +++ b/drivers/soc/fsl/rcpm.c @@ -36,6 +36,7 @@ static void copy_ippdexpcr1_setting(u32 val) return; regs = of_iomap(np, 0); + of_node_put(np); if (!regs) return; From cb3daa51db819a172e9524e96e2ed96b4237e51a Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 5 Nov 2024 15:56:23 +0100 Subject: [PATCH 116/116] soc: fsl: cpm1: qmc: Set the ret error code on platform_get_irq() failure A kernel test robot detected a missing error code: qmc.c:1942 qmc_probe() warn: missing error code 'ret' Indeed, the error returned by platform_get_irq() is checked and the operation is aborted in case of failure but the ret error code is not set in that case. Set the ret error code. Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202411051350.KNy6ZIWA-lkp@intel.com/ Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC") Cc: stable@vger.kernel.org Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20241105145623.401528-1-herve.codina@bootlin.com Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 3dffebb48b0d..fa7dc7d4abf3 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -2005,8 +2005,10 @@ static int qmc_probe(struct platform_device *pdev) /* Set the irq handler */ irq = platform_get_irq(pdev, 0); - if (irq < 0) + if (irq < 0) { + ret = irq; goto err_exit_xcc; + } ret = devm_request_irq(qmc->dev, irq, qmc_irq_handler, 0, "qmc", qmc); if (ret < 0) goto err_exit_xcc;