diff --git a/CREDITS b/CREDITS index f33a33fd2371..3468de97c668 100644 --- a/CREDITS +++ b/CREDITS @@ -1425,6 +1425,10 @@ S: University of Stellenbosch S: Stellenbosch, Western Cape S: South Africa +N: Andy Gross +E: agross@kernel.org +D: Qualcomm SoC subsystem and drivers + N: Grant Grundler E: grantgrundler@gmail.com W: http://obmouse.sourceforge.net/ diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 580f9a97ddf7..b9a9f2cf32a1 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -33,6 +33,8 @@ properties: - qcom,sm8350-llcc - qcom,sm8450-llcc - qcom,sm8550-llcc + - qcom,sm8650-llcc + - qcom,x1e80100-llcc reg: minItems: 2 @@ -104,6 +106,7 @@ allOf: - qcom,qdu1000-llcc - qcom,sc8180x-llcc - qcom,sc8280xp-llcc + - qcom,x1e80100-llcc then: properties: reg: diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 0613a37a851a..47d3d2d52acd 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -63,7 +63,9 @@ properties: - qcom,scm-sm8350 - qcom,scm-sm8450 - qcom,scm-sm8550 + - qcom,scm-sm8650 - qcom,scm-qcs404 + - qcom,scm-x1e80100 - const: qcom,scm clocks: @@ -178,21 +180,6 @@ allOf: minItems: 3 maxItems: 3 - # Interconnects - - if: - not: - properties: - compatible: - contains: - enum: - - qcom,scm-qdu1000 - - qcom,scm-sc8280xp - - qcom,scm-sm8450 - - qcom,scm-sm8550 - then: - properties: - interconnects: false - # Interrupts - if: not: @@ -202,6 +189,7 @@ allOf: enum: - qcom,scm-sm8450 - qcom,scm-sm8550 + - qcom,scm-sm8650 then: properties: interrupts: false diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index d1c7c2be865f..b4478f417edc 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -38,6 +38,8 @@ properties: - qcom,sm8350-aoss-qmp - qcom,sm8450-aoss-qmp - qcom,sm8550-aoss-qmp + - qcom,sm8650-aoss-qmp + - qcom,x1e80100-aoss-qmp - const: qcom,aoss-qmp reg: diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml index 422921cf1f82..61df97ffe1e4 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml @@ -20,14 +20,20 @@ description: properties: compatible: - items: - - enum: - - qcom,sc8180x-pmic-glink - - qcom,sc8280xp-pmic-glink - - qcom,sm8350-pmic-glink - - qcom,sm8450-pmic-glink - - qcom,sm8550-pmic-glink - - const: qcom,pmic-glink + oneOf: + - items: + - enum: + - qcom,sc8180x-pmic-glink + - qcom,sc8280xp-pmic-glink + - qcom,sm8350-pmic-glink + - qcom,sm8450-pmic-glink + - qcom,sm8550-pmic-glink + - const: qcom,pmic-glink + - items: + - enum: + - qcom,sm8650-pmic-glink + - const: qcom,sm8550-pmic-glink + - const: qcom,pmic-glink '#address-cells': const: 1 diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml index 96a7f1822022..686a7ef2f48a 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml @@ -31,10 +31,24 @@ properties: reg: maxItems: 1 + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM + required: - compatible - reg +allOf: + - if: + not: + properties: + compatible: + const: qcom,rpmh-stats + then: + properties: + qcom,qmp: false + additionalProperties: false examples: diff --git a/MAINTAINERS b/MAINTAINERS index 0b8af0840847..71315544f1d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2555,7 +2555,6 @@ F: arch/arm64/boot/dts/qcom/sc7280* F: arch/arm64/boot/dts/qcom/sdm845-cheza* ARM/QUALCOMM SUPPORT -M: Andy Gross M: Bjorn Andersson M: Konrad Dybcio L: linux-arm-msm@vger.kernel.org diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c index a33acdaf7b78..32188f098ef3 100644 --- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c +++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c @@ -325,8 +325,10 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e req_data->length = req_size; status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); - if (status < 0) - return EFI_INVALID_PARAMETER; + if (status < 0) { + efi_status = EFI_INVALID_PARAMETER; + goto out_free; + } memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); @@ -471,8 +473,10 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e req_data->length = req_size; status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); - if (status < 0) - return EFI_INVALID_PARAMETER; + if (status < 0) { + efi_status = EFI_INVALID_PARAMETER; + goto out_free; + } memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); @@ -563,8 +567,10 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, *name_size / sizeof(*name)); - if (status < 0) - return EFI_INVALID_PARAMETER; + if (status < 0) { + efi_status = EFI_INVALID_PARAMETER; + goto out_free; + } status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size); if (status) { @@ -635,7 +641,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, * have already been validated above, causing this function to * bail with EFI_BUFFER_TOO_SMALL. */ - return EFI_DEVICE_ERROR; + efi_status = EFI_DEVICE_ERROR; } out_free: diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b3634e10f6f5..aa5956246f60 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -77,6 +77,18 @@ config QCOM_PDR_HELPERS select QCOM_QMI_HELPERS depends on NET +config QCOM_PMIC_PDCHARGER_ULOG + tristate "Qualcomm PMIC PDCharger ULOG driver" + depends on RPMSG + depends on EVENT_TRACING + help + The Qualcomm PMIC PDCharger ULOG driver provides access to logs of + the ADSP firmware PDCharger module in charge of Battery and Power + Delivery on modern systems. + + Say yes here to support PDCharger ULOG event tracing on modern + Qualcomm platforms. + config QCOM_PMIC_GLINK tristate "Qualcomm PMIC GLINK driver" depends on RPMSG @@ -209,6 +221,7 @@ config QCOM_STATS tristate "Qualcomm Technologies, Inc. (QTI) Sleep stats driver" depends on (ARCH_QCOM && DEBUG_FS) || COMPILE_TEST depends on QCOM_SMEM + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n help Qualcomm Technologies, Inc. (QTI) Sleep stats driver to read the shared memory exported by the remote processor related to diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index bbca2e1e55bb..05b3d54e8dc9 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -9,6 +9,8 @@ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o +obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o +CFLAGS_pmic_pdcharger_ulog.o := -I$(src) obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 674abd0d6700..4ca88eaebf06 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -47,7 +47,7 @@ #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K) #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n) #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n) -#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_8 * n) +#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_4 * n) #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 @@ -92,6 +92,19 @@ * @write_scid_en: Bit enables write cache support for a given scid. * @write_scid_cacheable_en: Enables write cache cacheable support for a * given scid (not supported on v2 or older hardware). + * @stale_en: Bit enables stale. + * @stale_cap_en: Bit enables stale only if current scid is over-cap. + * @mru_uncap_en: Roll-over on reserved cache ways if current scid is + * under-cap. + * @mru_rollover: Roll-over on reserved cache ways. + * @alloc_oneway_en: Allways allocate one way on over-cap even if there's no + * same-scid lines for replacement. + * @ovcap_en: Once current scid is over-capacity, allocate other over-cap SCID. + * @ovcap_prio: Once current scid is over-capacity, allocate other low priority + * over-cap scid. Depends on corresponding bit being set in + * ovcap_en. + * @vict_prio: When current scid is under-capacity, allocate over other + * lower-than victim priority-line threshold scid. */ struct llcc_slice_config { u32 usecase_id; @@ -362,6 +375,33 @@ static const struct llcc_slice_config sm8550_data[] = { {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, }; +static const struct llcc_slice_config 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}, +}; + 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 }, @@ -392,6 +432,29 @@ static const struct llcc_slice_config qdu1000_data_8ch[] = { { LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 }, }; +static const struct llcc_slice_config x1e80100_data[] = { + {LLCC_CPUSS, 1, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_AUDIO, 6, 3072, 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, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_GPU, 9, 4096, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_MMUHWT, 18, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 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, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_CAMEXP1, 7, 3072, 2, 1, 0xFFF, 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, 0, 0, 0, 0, 0, 0, 0, 0, 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, 512, 7, 1, 0x1, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_ISLAND2, 13, 512, 7, 1, 0x2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_ISLAND3, 14, 512, 7, 1, 0x3, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_ISLAND4, 15, 512, 7, 1, 0x4, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_CAMEXP2, 19, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_CAMEXP3, 20, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {LLCC_CAMEXP4, 21, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { .trp_ecc_error_status0 = 0x20344, .trp_ecc_error_status1 = 0x20348, @@ -610,6 +673,26 @@ static const struct qcom_llcc_config sm8550_cfg[] = { }, }; +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, + }, +}; + +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, + }, +}; + static const struct qcom_sct_config qdu1000_cfgs = { .llcc_config = qdu1000_cfg, .num_config = ARRAY_SIZE(qdu1000_cfg), @@ -675,6 +758,16 @@ static const struct qcom_sct_config sm8550_cfgs = { .num_config = ARRAY_SIZE(sm8550_cfg), }; +static const struct qcom_sct_config sm8650_cfgs = { + .llcc_config = sm8650_cfg, + .num_config = ARRAY_SIZE(sm8650_cfg), +}; + +static const struct qcom_sct_config x1e80100_cfgs = { + .llcc_config = x1e80100_cfg, + .num_config = ARRAY_SIZE(x1e80100_cfg), +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -715,7 +808,7 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid) EXPORT_SYMBOL_GPL(llcc_slice_getd); /** - * llcc_slice_putd - llcc slice descritpor + * llcc_slice_putd - llcc slice descriptor * @desc: Pointer to llcc slice descriptor */ void llcc_slice_putd(struct llcc_slice_desc *desc) @@ -941,15 +1034,15 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, u32 disable_cap_alloc, retain_pc; disable_cap_alloc = config->dis_cap_alloc << config->slice_id; - ret = regmap_write(drv_data->bcast_regmap, - LLCC_TRP_SCID_DIS_CAP_ALLOC, disable_cap_alloc); + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_SCID_DIS_CAP_ALLOC, + BIT(config->slice_id), disable_cap_alloc); if (ret) return ret; if (drv_data->version < LLCC_VERSION_4_1_0_0) { retain_pc = config->retain_on_pc << config->slice_id; - ret = regmap_write(drv_data->bcast_regmap, - LLCC_TRP_PCB_ACT, retain_pc); + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_PCB_ACT, + BIT(config->slice_id), retain_pc); if (ret) return ret; } @@ -1249,6 +1342,8 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfgs }, { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfgs }, { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfgs }, + { .compatible = "qcom,sm8650-llcc", .data = &sm8650_cfgs }, + { .compatible = "qcom,x1e80100-llcc", .data = &x1e80100_cfgs }, { } }; MODULE_DEVICE_TABLE(of, qcom_llcc_of_match); diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 914057331afd..f4bfd24386f1 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -18,9 +18,6 @@ enum { PMIC_GLINK_CLIENT_UCSI, }; -#define PMIC_GLINK_CLIENT_DEFAULT (BIT(PMIC_GLINK_CLIENT_BATT) | \ - BIT(PMIC_GLINK_CLIENT_ALTMODE)) - struct pmic_glink { struct device *dev; struct pdr_handle *pdr; @@ -263,10 +260,10 @@ static int pmic_glink_probe(struct platform_device *pdev) mutex_init(&pg->state_lock); match_data = (unsigned long *)of_device_get_match_data(&pdev->dev); - if (match_data) - pg->client_mask = *match_data; - else - pg->client_mask = PMIC_GLINK_CLIENT_DEFAULT; + if (!match_data) + return -EINVAL; + + pg->client_mask = *match_data; if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi"); @@ -336,14 +333,17 @@ static void pmic_glink_remove(struct platform_device *pdev) mutex_unlock(&__pmic_glink_lock); } +static const unsigned long pmic_glink_sc8180x_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE); + static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | BIT(PMIC_GLINK_CLIENT_ALTMODE) | BIT(PMIC_GLINK_CLIENT_UCSI); static const struct of_device_id pmic_glink_of_match[] = { - { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, - { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, - { .compatible = "qcom,pmic-glink" }, + { .compatible = "qcom,sc8180x-pmic-glink", .data = &pmic_glink_sc8180x_client_mask }, + { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8180x_client_mask }, + { .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask }, {} }; MODULE_DEVICE_TABLE(of, pmic_glink_of_match); @@ -363,14 +363,14 @@ static int pmic_glink_init(void) register_rpmsg_driver(&pmic_glink_rpmsg_driver); return 0; -}; +} module_init(pmic_glink_init); static void pmic_glink_exit(void) { unregister_rpmsg_driver(&pmic_glink_rpmsg_driver); platform_driver_unregister(&pmic_glink_driver); -}; +} module_exit(pmic_glink_exit); MODULE_DESCRIPTION("Qualcomm PMIC GLINK driver"); diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index b78279e2f54c..ad922f0dca6b 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -236,7 +236,7 @@ static void pmic_glink_altmode_worker(struct work_struct *work) drm_bridge_hpd_notify(&alt_port->bridge, connector_status_disconnected); pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index); -}; +} static enum typec_orientation pmic_glink_altmode_orientation(unsigned int orientation) { @@ -285,7 +285,7 @@ static void pmic_glink_altmode_sc8180xp_notify(struct pmic_glink_altmode *altmod svid = mux == 2 ? USB_TYPEC_DP_SID : 0; - if (!altmode->ports[port].altmode) { + if (port >= ARRAY_SIZE(altmode->ports) || !altmode->ports[port].altmode) { dev_dbg(altmode->dev, "notification on undefined port %d\n", port); return; } @@ -328,7 +328,7 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod hpd_state = FIELD_GET(SC8280XP_HPD_STATE_MASK, notify->payload[8]); hpd_irq = FIELD_GET(SC8280XP_HPD_IRQ_MASK, notify->payload[8]); - if (!altmode->ports[port].altmode) { + if (port >= ARRAY_SIZE(altmode->ports) || !altmode->ports[port].altmode) { dev_dbg(altmode->dev, "notification on undefined port %d\n", port); return; } diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c new file mode 100644 index 000000000000..238cd38589dc --- /dev/null +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2022, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd + */ +#include +#include +#include +#include +#include +#include +#include + +#define CREATE_TRACE_POINTS +#include "pmic_pdcharger_ulog.h" + +#define MSG_OWNER_CHG_ULOG 32778 +#define MSG_TYPE_REQ_RESP 1 + +#define GET_CHG_ULOG_REQ 0x18 +#define SET_CHG_ULOG_PROP_REQ 0x19 + +#define LOG_DEFAULT_TIME_MS 1000 + +#define MAX_ULOG_SIZE 8192 + +struct pmic_pdcharger_ulog_hdr { + __le32 owner; + __le32 type; + __le32 opcode; +}; + +struct pmic_pdcharger_ulog { + struct rpmsg_device *rpdev; + struct delayed_work ulog_work; +}; + +struct get_ulog_req_msg { + struct pmic_pdcharger_ulog_hdr hdr; + u32 log_size; +}; + +struct get_ulog_resp_msg { + struct pmic_pdcharger_ulog_hdr hdr; + u8 buf[MAX_ULOG_SIZE]; +}; + +static int pmic_pdcharger_ulog_write_async(struct pmic_pdcharger_ulog *pg, void *data, size_t len) +{ + return rpmsg_send(pg->rpdev->ept, data, len); +} + +static int pmic_pdcharger_ulog_request(struct pmic_pdcharger_ulog *pg) +{ + struct get_ulog_req_msg req_msg = { + .hdr = { + .owner = cpu_to_le32(MSG_OWNER_CHG_ULOG), + .type = cpu_to_le32(MSG_TYPE_REQ_RESP), + .opcode = cpu_to_le32(GET_CHG_ULOG_REQ) + }, + .log_size = MAX_ULOG_SIZE + }; + + return pmic_pdcharger_ulog_write_async(pg, &req_msg, sizeof(req_msg)); +} + +static void pmic_pdcharger_ulog_work(struct work_struct *work) +{ + struct pmic_pdcharger_ulog *pg = container_of(work, struct pmic_pdcharger_ulog, + ulog_work.work); + int rc; + + rc = pmic_pdcharger_ulog_request(pg); + if (rc) { + dev_err(&pg->rpdev->dev, "Error requesting ulog, rc=%d\n", rc); + return; + } +} + +static void pmic_pdcharger_ulog_handle_message(struct pmic_pdcharger_ulog *pg, + struct get_ulog_resp_msg *resp_msg, + size_t len) +{ + char *token, *buf = resp_msg->buf; + + if (len != sizeof(*resp_msg)) { + dev_err(&pg->rpdev->dev, "Expected data length: %zu, received: %zu\n", + sizeof(*resp_msg), len); + return; + } + + buf[MAX_ULOG_SIZE - 1] = '\0'; + + do { + token = strsep((char **)&buf, "\n"); + if (token && strlen(token)) + trace_pmic_pdcharger_ulog_msg(token); + } while (token); +} + +static int pmic_pdcharger_ulog_rpmsg_callback(struct rpmsg_device *rpdev, void *data, + int len, void *priv, u32 addr) +{ + struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev); + struct pmic_pdcharger_ulog_hdr *hdr = data; + u32 opcode; + + opcode = le32_to_cpu(hdr->opcode); + + switch (opcode) { + case GET_CHG_ULOG_REQ: + schedule_delayed_work(&pg->ulog_work, msecs_to_jiffies(LOG_DEFAULT_TIME_MS)); + pmic_pdcharger_ulog_handle_message(pg, data, len); + break; + default: + dev_err(&pg->rpdev->dev, "Unknown opcode %u\n", opcode); + break; + } + + return 0; +} + +static int pmic_pdcharger_ulog_rpmsg_probe(struct rpmsg_device *rpdev) +{ + struct pmic_pdcharger_ulog *pg; + struct device *dev = &rpdev->dev; + + pg = devm_kzalloc(dev, sizeof(*pg), GFP_KERNEL); + if (!pg) + return -ENOMEM; + + pg->rpdev = rpdev; + INIT_DELAYED_WORK(&pg->ulog_work, pmic_pdcharger_ulog_work); + + dev_set_drvdata(dev, pg); + + pmic_pdcharger_ulog_request(pg); + + return 0; +} + +static void pmic_pdcharger_ulog_rpmsg_remove(struct rpmsg_device *rpdev) +{ + struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev); + + cancel_delayed_work_sync(&pg->ulog_work); +} + +static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = { + { "PMIC_LOGS_ADSP_APPS" }, + {} +}; + +static struct rpmsg_driver pmic_pdcharger_ulog_rpmsg_driver = { + .probe = pmic_pdcharger_ulog_rpmsg_probe, + .remove = pmic_pdcharger_ulog_rpmsg_remove, + .callback = pmic_pdcharger_ulog_rpmsg_callback, + .id_table = pmic_pdcharger_ulog_rpmsg_id_match, + .drv = { + .name = "qcom_pmic_pdcharger_ulog_rpmsg", + }, +}; + +module_rpmsg_driver(pmic_pdcharger_ulog_rpmsg_driver); +MODULE_DESCRIPTION("Qualcomm PMIC ChargerPD ULOG driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.h b/drivers/soc/qcom/pmic_pdcharger_ulog.h new file mode 100644 index 000000000000..152e3a6b5480 --- /dev/null +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023, Linaro Ltd + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM pmic_pdcharger_ulog + +#if !defined(_TRACE_PMIC_PDCHARGER_ULOG_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_PMIC_PDCHARGER_ULOG_H + +#include + +TRACE_EVENT(pmic_pdcharger_ulog_msg, + TP_PROTO(char *msg), + TP_ARGS(msg), + TP_STRUCT__entry( + __string(msg, msg) + ), + TP_fast_assign( + __assign_str(msg, msg); + ), + TP_printk("%s", __get_str(msg)) +); + +#endif /* _TRACE_PMIC_PDCHARGER_ULOG_H */ + +/* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE pmic_pdcharger_ulog + +#include diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 51e05bec5bfc..6349a0debeb5 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -51,6 +51,11 @@ #define SMEM_IMAGE_TABLE_ADSP_INDEX 12 #define SMEM_IMAGE_TABLE_CNSS_INDEX 13 #define SMEM_IMAGE_TABLE_VIDEO_INDEX 14 +#define SMEM_IMAGE_TABLE_DSPS_INDEX 15 +#define SMEM_IMAGE_TABLE_CDSP_INDEX 16 +#define SMEM_IMAGE_TABLE_CDSP1_INDEX 19 +#define SMEM_IMAGE_TABLE_GPDSP_INDEX 20 +#define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21 #define SMEM_IMAGE_VERSION_TABLE 469 /* @@ -65,6 +70,11 @@ static const char *const socinfo_image_names[] = { [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm", [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz", [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video", + [SMEM_IMAGE_TABLE_DSPS_INDEX] = "dsps", + [SMEM_IMAGE_TABLE_CDSP_INDEX] = "cdsp", + [SMEM_IMAGE_TABLE_CDSP1_INDEX] = "cdsp1", + [SMEM_IMAGE_TABLE_GPDSP_INDEX] = "gpdsp", + [SMEM_IMAGE_TABLE_GPDSP1_INDEX] = "gpdsp1", }; static const char *const pmic_models[] = { @@ -93,7 +103,7 @@ static const char *const pmic_models[] = { [22] = "PM8821", [23] = "PM8038", [24] = "PM8005/PM8922", - [25] = "PM8917", + [25] = "PM8917/PM8937", [26] = "PM660L", [27] = "PM660", [30] = "PM8150", @@ -417,6 +427,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SA8775P) }, { qcom_board_id(QRU1000) }, { qcom_board_id(QDU1000) }, + { qcom_board_id(SM8650) }, { qcom_board_id(SM4450) }, { qcom_board_id(QDU1010) }, { qcom_board_id(QRU1032) }, diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 61b64558f96c..5392ec698959 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -578,6 +578,9 @@ static int ucsi_read_pdos(struct ucsi_connector *con, u64 command; int ret; + if (ucsi->quirks & UCSI_NO_PARTNER_PDOS) + return 0; + command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num); command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); command |= UCSI_GET_PDOS_PDO_OFFSET(offset); diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 474315a72c77..6478016d5cb8 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -317,6 +317,9 @@ struct ucsi { #define EVENT_PENDING 0 #define COMMAND_PENDING 1 #define ACK_PENDING 2 + + unsigned long quirks; +#define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */ }; #define UCSI_MAX_SVID 5 diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index db6e248f8208..a94e2df6fd45 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -296,11 +297,19 @@ static void pmic_glink_ucsi_destroy(void *data) mutex_unlock(&ucsi->lock); } +static const struct of_device_id pmic_glink_ucsi_of_quirks[] = { + { .compatible = "qcom,sc8180x-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, }, + { .compatible = "qcom,sc8280xp-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, }, + { .compatible = "qcom,sm8350-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, }, + {} +}; + static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { struct pmic_glink_ucsi *ucsi; struct device *dev = &adev->dev; + const struct of_device_id *match; struct fwnode_handle *fwnode; int ret; @@ -327,6 +336,10 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, if (ret) return ret; + match = of_match_device(pmic_glink_ucsi_of_quirks, dev->parent); + if (match) + ucsi->ucsi->quirks = (unsigned long)match->data; + ucsi_set_drvdata(ucsi->ucsi, ucsi); device_for_each_child_node(dev, fwnode) { diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index f7248348a459..51e0f6059410 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -255,6 +255,7 @@ #define QCOM_ID_SA8775P 534 #define QCOM_ID_QRU1000 539 #define QCOM_ID_QDU1000 545 +#define QCOM_ID_SM8650 557 #define QCOM_ID_SM4450 568 #define QCOM_ID_QDU1010 587 #define QCOM_ID_QRU1032 588