Qualcomm driver updates for v6.14

The Qualcomm SCM drivers gains a number of fixes and improvements
 related to race conditions during initialization. QSEECOM and the EFI
 variable service therein is enabled for a few 8cx Gen 3 and X Elite
 boards.
 
 LLCC driver gains configuration for IPQ5424 and WRCACHE is enabled on X
 Elite.
 
 The BCM_TCS_CMD() macro is corrected and is cleaned up.
 
 Support for SM7225 and X 1 Plus are added to the pd-mapper.
 
 pmic_glink and the associated altmode driver are simplied using guards.
 
 socinfo is added for QCS9075 and serial number readout on MSM8916
 devices is corrected.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmeCqjkVHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3FsPkQAI7TS8UeurQR0HFw+O+D4kwWNAKX
 6xHevX36jdd39HpLBGjoFbgNL3vrj6eblgKXIt6QD8hjexCAftoTJ5MPLF6uWm2M
 AJR4wVlt5Hu0ABcCZxYTEmEGQi27I5RQpfOH3rX3G1b7xi2gLb3zkG5EEIfdc27h
 je6O1BEFLJ5Y9TO0cBkGlTXG6HQ4NPSf24yBrVKm00Az6k/vJKZ7xu9bguOkz5yh
 lst7XuLfcnJUpwbUYVLKeFS+RBoP3JvDWNc470DR3khtvEQJ1NFFF3yifcztt6qG
 3SV8nahmqRHrob0r7dt2eCAbTFCGYKXnNM8d4Bigk5HLX2ph6lkHA9eGspC418uK
 da6HCNFQJXuB8VI2fl2ObAsfahYho1/SytRBqQYfkJB1GJtBGjZVeBb3X5VW411I
 8VhMosqBqqaIpgIzVB4YefKBG17NsEYab6/Rp6v3AjC4a4j7/bKcdnQshHbzGauU
 h/zsKK4UliU6cvPBvgF2w49QX/zjoQbebGpX2MV9xGbT+4sN88SS0hFlJGU1q2HD
 V+uTZzluiCggQe929ECmFGOb2vAQ7LWunkWYMACNuYQx0I0DfoqktBiXPxS+79qw
 NcugNifv3Q0Qfkqt3p/dLK9FQXFh5bmFViCCUuSfXd1um3kNcMuRLOuSVr94H3HJ
 2F5n854HebhJo8hQ
 =ra/f
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmeHzPkACgkQYKtH/8kJ
 UifViRAAtU2gDWABZCItsT5K5D6aXmGO/d5oN7AWvaJmBmPLTs7r8qQX5Ik+cwpR
 uOOgs929GNzXFfxtQhXpS1prmqHgeGtOg+LJm4/+vgre2LQlvt3erhe7pg3g2N5p
 xuS3hY+l5rbKJQ2y0T1WXmC12Bx+xsuH7Cu6WfboOa/UKW+VfpNGqvElZfW2B7EF
 e83Q8HeQ+lFfYjQ+9MjN+RpLIGy5UQiurangoWyYUkgNIxP0vj33FggAUbA371po
 H1SdKefnqvVrlEeyOoAZ9LA34OV0nBr/xW7Jx768BFrR+/k9bjjlkIDi3iHOxhId
 OBdQEytg5Fnu1dWmPIJn4M+lpu39fP5YFWdsc1STtjj57DF1TDZZ+UXNYkJnYHI9
 FN4p8l3d7l6Ae+jjxYCtE7F9IYujIAwediPWJc/ci9V2e7blTVA7PuSMfw7wbKFz
 CL6q+6pGTkYRJ033AqaOKE+WiTQgZEoRQGfDdJ9o+4U63XCEtOSas/BdCSgYv0zW
 qtgvXvlFOxrZ7L3OR+sleyUfNHTj3/OfiiQ0Bh8G0rF2cOMkkrIzrUFOFOOM/6wI
 4Fl2Zaomjcs5KFI6C+h1xJfYAOy/bhVRC1ceAWkkkk6iKViQbUottLN5wTvTlqVy
 QtGJ0saiuxEXBRohwIHI7KK4Dv/UerdOiKma83QiU230V/0X2Qk=
 =cVEn
 -----END PGP SIGNATURE-----

Merge tag 'qcom-drivers-for-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

Qualcomm driver updates for v6.14

The Qualcomm SCM drivers gains a number of fixes and improvements
related to race conditions during initialization. QSEECOM and the EFI
variable service therein is enabled for a few 8cx Gen 3 and X Elite
boards.

LLCC driver gains configuration for IPQ5424 and WRCACHE is enabled on X
Elite.

The BCM_TCS_CMD() macro is corrected and is cleaned up.

Support for SM7225 and X 1 Plus are added to the pd-mapper.

pmic_glink and the associated altmode driver are simplied using guards.

socinfo is added for QCS9075 and serial number readout on MSM8916
devices is corrected.

* tag 'qcom-drivers-for-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (29 commits)
  firmware: qcom: scm: add calls for wrapped key support
  soc: qcom: pd_mapper: Add SM7225 compatible
  dt-bindings: firmware: qcom,scm: Document ipq5424 SCM
  soc: qcom: llcc: Update configuration data for IPQ5424
  dt-bindings: cache: qcom,llcc: Add IPQ5424 compatible
  firmware: qcom: scm: smc: Narrow 'mempool' variable scope
  firmware: qcom: scm: smc: Handle missing SCM device
  firmware: qcom: scm: Cleanup global '__scm' on probe failures
  firmware: qcom: scm: Fix missing read barrier in qcom_scm_get_tzmem_pool()
  firmware: qcom: scm: Fix missing read barrier in qcom_scm_is_available()
  soc: qcom: socinfo: add QCS9075 SoC ID
  dt-bindings: arm: qcom,ids: add SoC ID for QCS9075
  soc: qcom: socinfo: Avoid out of bounds read of serial number
  firmware: qcom: scm: Allow QSEECOM on Huawei Matebook E Go (sc8280xp)
  firmware: qcom: scm: Allow QSEECOM for Windows Dev Kit 2023
  firmware: qcom: scm: Allow QSEECOM for HP Omnibook X14
  soc: qcom: rmtfs: constify rmtfs_class
  soc: qcom: rmtfs: allow building the module with COMPILE_TEST=y
  soc: qcom: pmic_glink_altmode: simplify locking with guard()
  soc: qcom: Rework BCM_TCS_CMD macro
  ...

Link: https://lore.kernel.org/r/20250111172901.391774-1-andersson@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2025-01-15 15:58:01 +01:00
commit 97d139585a
18 changed files with 407 additions and 87 deletions

View File

@ -20,6 +20,7 @@ description: |
properties:
compatible:
enum:
- qcom,ipq5424-llcc
- qcom,qcs615-llcc
- qcom,qcs8300-llcc
- qcom,qdu1000-llcc
@ -42,11 +43,11 @@ properties:
- qcom,x1e80100-llcc
reg:
minItems: 2
minItems: 1
maxItems: 10
reg-names:
minItems: 2
minItems: 1
maxItems: 10
interrupts:
@ -66,6 +67,21 @@ required:
- reg-names
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,ipq5424-llcc
then:
properties:
reg:
items:
- description: LLCC0 base register region
reg-names:
items:
- const: llcc0_base
- if:
properties:
compatible:

View File

@ -26,6 +26,7 @@ properties:
- qcom,scm-ipq4019
- qcom,scm-ipq5018
- qcom,scm-ipq5332
- qcom,scm-ipq5424
- qcom,scm-ipq6018
- qcom,scm-ipq806x
- qcom,scm-ipq8074
@ -42,6 +43,7 @@ properties:
- qcom,scm-msm8996
- qcom,scm-msm8998
- qcom,scm-qcm2290
- qcom,scm-qcs615
- qcom,scm-qcs8300
- qcom,scm-qdu1000
- qcom,scm-sa8255p

View File

@ -26,6 +26,7 @@ properties:
- items:
- enum:
- qcom,qcm2290-cpu-bwmon
- qcom,qcs615-cpu-bwmon
- qcom,qcs8300-cpu-bwmon
- qcom,sa8775p-cpu-bwmon
- qcom,sc7180-cpu-bwmon
@ -41,6 +42,7 @@ properties:
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
- items:
- enum:
- qcom,qcs615-llcc-bwmon
- qcom,qcs8300-llcc-bwmon
- qcom,sa8775p-llcc-bwmon
- qcom,sc7180-llcc-bwmon

View File

@ -25,6 +25,7 @@ properties:
compatible:
items:
- enum:
- qcom,qcs615-aoss-qmp
- qcom,qcs8300-aoss-qmp
- qcom,qdu1000-aoss-qmp
- qcom,sa8255p-aoss-qmp

View File

@ -152,7 +152,6 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
enum qcom_scm_convention qcom_convention,
struct qcom_scm_res *res, bool atomic)
{
struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool();
int arglen = desc->arginfo & 0xf;
int i, ret;
void *args_virt __free(qcom_tzmem) = NULL;
@ -173,6 +172,11 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool();
if (!mempool)
return -EINVAL;
args_virt = qcom_tzmem_alloc(mempool,
SCM_SMC_N_EXT_ARGS * sizeof(u64),
flag);

View File

@ -217,7 +217,10 @@ static DEFINE_SPINLOCK(scm_query_lock);
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void)
{
return __scm ? __scm->mempool : NULL;
if (!qcom_scm_is_available())
return NULL;
return __scm->mempool;
}
static enum qcom_scm_convention __get_convention(void)
@ -1279,6 +1282,220 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
}
EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
bool qcom_scm_has_wrapped_key_support(void)
{
return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_DERIVE_SW_SECRET) &&
__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_GENERATE_ICE_KEY) &&
__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_PREPARE_ICE_KEY) &&
__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_IMPORT_ICE_KEY);
}
EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
/**
* qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
* @eph_key: an ephemerally-wrapped key
* @eph_key_size: size of @eph_key in bytes
* @sw_secret: output buffer for the software secret
* @sw_secret_size: size of the software secret to derive in bytes
*
* Derive a software secret from an ephemerally-wrapped key for software crypto
* operations. This is done by calling into the secure execution environment,
* which then calls into the hardware to unwrap and derive the secret.
*
* For more information on sw_secret, see the "Hardware-wrapped keys" section of
* Documentation/block/inline-encryption.rst.
*
* Return: 0 on success; -errno on failure.
*/
int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
u8 *sw_secret, size_t sw_secret_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
.cmd = QCOM_SCM_ES_DERIVE_SW_SECRET,
.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL,
QCOM_SCM_RW, QCOM_SCM_VAL),
.owner = ARM_SMCCC_OWNER_SIP,
};
int ret;
void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
eph_key_size,
GFP_KERNEL);
if (!eph_key_buf)
return -ENOMEM;
void *sw_secret_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
sw_secret_size,
GFP_KERNEL);
if (!sw_secret_buf)
return -ENOMEM;
memcpy(eph_key_buf, eph_key, eph_key_size);
desc.args[0] = qcom_tzmem_to_phys(eph_key_buf);
desc.args[1] = eph_key_size;
desc.args[2] = qcom_tzmem_to_phys(sw_secret_buf);
desc.args[3] = sw_secret_size;
ret = qcom_scm_call(__scm->dev, &desc, NULL);
if (!ret)
memcpy(sw_secret, sw_secret_buf, sw_secret_size);
memzero_explicit(eph_key_buf, eph_key_size);
memzero_explicit(sw_secret_buf, sw_secret_size);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
/**
* qcom_scm_generate_ice_key() - Generate a wrapped key for storage encryption
* @lt_key: output buffer for the long-term wrapped key
* @lt_key_size: size of @lt_key in bytes. Must be the exact wrapped key size
* used by the SoC.
*
* Generate a key using the built-in HW module in the SoC. The resulting key is
* returned wrapped with the platform-specific Key Encryption Key.
*
* Return: 0 on success; -errno on failure.
*/
int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
.cmd = QCOM_SCM_ES_GENERATE_ICE_KEY,
.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL),
.owner = ARM_SMCCC_OWNER_SIP,
};
int ret;
void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
lt_key_size,
GFP_KERNEL);
if (!lt_key_buf)
return -ENOMEM;
desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[1] = lt_key_size;
ret = qcom_scm_call(__scm->dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);
memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
/**
* qcom_scm_prepare_ice_key() - Re-wrap a key with the per-boot ephemeral key
* @lt_key: a long-term wrapped key
* @lt_key_size: size of @lt_key in bytes
* @eph_key: output buffer for the ephemerally-wrapped key
* @eph_key_size: size of @eph_key in bytes. Must be the exact wrapped key size
* used by the SoC.
*
* Given a long-term wrapped key, re-wrap it with the per-boot ephemeral key for
* added protection. The resulting key will only be valid for the current boot.
*
* Return: 0 on success; -errno on failure.
*/
int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
u8 *eph_key, size_t eph_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
.cmd = QCOM_SCM_ES_PREPARE_ICE_KEY,
.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL,
QCOM_SCM_RW, QCOM_SCM_VAL),
.owner = ARM_SMCCC_OWNER_SIP,
};
int ret;
void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
lt_key_size,
GFP_KERNEL);
if (!lt_key_buf)
return -ENOMEM;
void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
eph_key_size,
GFP_KERNEL);
if (!eph_key_buf)
return -ENOMEM;
memcpy(lt_key_buf, lt_key, lt_key_size);
desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[1] = lt_key_size;
desc.args[2] = qcom_tzmem_to_phys(eph_key_buf);
desc.args[3] = eph_key_size;
ret = qcom_scm_call(__scm->dev, &desc, NULL);
if (!ret)
memcpy(eph_key, eph_key_buf, eph_key_size);
memzero_explicit(lt_key_buf, lt_key_size);
memzero_explicit(eph_key_buf, eph_key_size);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
/**
* qcom_scm_import_ice_key() - Import key for storage encryption
* @raw_key: the raw key to import
* @raw_key_size: size of @raw_key in bytes
* @lt_key: output buffer for the long-term wrapped key
* @lt_key_size: size of @lt_key in bytes. Must be the exact wrapped key size
* used by the SoC.
*
* Import a raw key and return a long-term wrapped key. Uses the SoC's HWKM to
* wrap the raw key using the platform-specific Key Encryption Key.
*
* Return: 0 on success; -errno on failure.
*/
int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
.cmd = QCOM_SCM_ES_IMPORT_ICE_KEY,
.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL,
QCOM_SCM_RW, QCOM_SCM_VAL),
.owner = ARM_SMCCC_OWNER_SIP,
};
int ret;
void *raw_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
raw_key_size,
GFP_KERNEL);
if (!raw_key_buf)
return -ENOMEM;
void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
lt_key_size,
GFP_KERNEL);
if (!lt_key_buf)
return -ENOMEM;
memcpy(raw_key_buf, raw_key, raw_key_size);
desc.args[0] = qcom_tzmem_to_phys(raw_key_buf);
desc.args[1] = raw_key_size;
desc.args[2] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[3] = lt_key_size;
ret = qcom_scm_call(__scm->dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);
memzero_explicit(raw_key_buf, raw_key_size);
memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);
/**
* qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
*
@ -1768,18 +1985,23 @@ 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 = "asus,vivobook-s15" },
{ .compatible = "dell,xps13-9345" },
{ .compatible = "hp,omnibook-x14" },
{ .compatible = "huawei,gaokun3" },
{ .compatible = "lenovo,flex-5g" },
{ .compatible = "lenovo,thinkpad-t14s" },
{ .compatible = "lenovo,thinkpad-x13s", },
{ .compatible = "lenovo,yoga-slim7x" },
{ .compatible = "microsoft,arcata", },
{ .compatible = "microsoft,blackrock" },
{ .compatible = "microsoft,romulus13", },
{ .compatible = "microsoft,romulus15", },
{ .compatible = "qcom,sc8180x-primus" },
{ .compatible = "qcom,x1e001de-devkit" },
{ .compatible = "qcom,x1e80100-crd" },
{ .compatible = "qcom,x1e80100-qcp" },
{ .compatible = "qcom,x1p42100-crd" },
{ }
};
@ -1867,7 +2089,8 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm)
*/
bool qcom_scm_is_available(void)
{
return !!READ_ONCE(__scm);
/* Paired with smp_store_release() in qcom_scm_probe */
return !!smp_load_acquire(&__scm);
}
EXPORT_SYMBOL_GPL(qcom_scm_is_available);
@ -2024,18 +2247,22 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (ret)
return ret;
/* Let all above stores be available after this */
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
smp_store_release(&__scm, scm);
irq = platform_get_irq_optional(pdev, 0);
if (irq < 0) {
if (irq != -ENXIO)
return irq;
if (irq != -ENXIO) {
ret = irq;
goto err;
}
} else {
ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler,
IRQF_ONESHOT, "qcom-scm", __scm);
if (ret < 0)
return dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
if (ret < 0) {
dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
goto err;
}
}
__get_convention();
@ -2054,14 +2281,18 @@ static int qcom_scm_probe(struct platform_device *pdev)
qcom_scm_disable_sdi();
ret = of_reserved_mem_device_init(__scm->dev);
if (ret && ret != -ENODEV)
return dev_err_probe(__scm->dev, ret,
"Failed to setup the reserved memory region for TZ mem\n");
if (ret && ret != -ENODEV) {
dev_err_probe(__scm->dev, ret,
"Failed to setup the reserved memory region for TZ mem\n");
goto err;
}
ret = qcom_tzmem_enable(__scm->dev);
if (ret)
return dev_err_probe(__scm->dev, ret,
"Failed to enable the TrustZone memory allocator\n");
if (ret) {
dev_err_probe(__scm->dev, ret,
"Failed to enable the TrustZone memory allocator\n");
goto err;
}
memset(&pool_config, 0, sizeof(pool_config));
pool_config.initial_size = 0;
@ -2069,9 +2300,11 @@ static int qcom_scm_probe(struct platform_device *pdev)
pool_config.max_size = SZ_256K;
__scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config);
if (IS_ERR(__scm->mempool))
return dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
"Failed to create the SCM memory pool\n");
if (IS_ERR(__scm->mempool)) {
dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
"Failed to create the SCM memory pool\n");
goto err;
}
/*
* Initialize the QSEECOM interface.
@ -2087,6 +2320,12 @@ static int qcom_scm_probe(struct platform_device *pdev)
WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);
return 0;
err:
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
smp_store_release(&__scm, NULL);
return ret;
}
static void qcom_scm_shutdown(struct platform_device *pdev)

View File

@ -128,6 +128,10 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
#define QCOM_SCM_SVC_ES 0x10 /* Enterprise Security */
#define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03
#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04
#define QCOM_SCM_ES_DERIVE_SW_SECRET 0x07
#define QCOM_SCM_ES_GENERATE_ICE_KEY 0x08
#define QCOM_SCM_ES_PREPARE_ICE_KEY 0x09
#define QCOM_SCM_ES_IMPORT_ICE_KEY 0x0a
#define QCOM_SCM_SVC_HDCP 0x11
#define QCOM_SCM_HDCP_INVOKE 0x01

View File

@ -139,7 +139,7 @@ config QCOM_RAMP_CTRL
config QCOM_RMTFS_MEM
tristate "Qualcomm Remote Filesystem memory driver"
depends on ARCH_QCOM
depends on ARCH_QCOM || COMPILE_TEST
select QCOM_SCM
help
The Qualcomm remote filesystem memory driver is used for allocating

View File

@ -142,6 +142,7 @@ struct qcom_llcc_config {
bool skip_llcc_cfg;
bool no_edac;
bool irq_configured;
bool no_broadcast_register;
};
struct qcom_sct_config {
@ -154,6 +155,38 @@ enum llcc_reg_offset {
LLCC_COMMON_STATUS0,
};
static const struct llcc_slice_config ipq5424_data[] = {
{
.usecase_id = LLCC_CPUSS,
.slice_id = 1,
.max_cap = 768,
.priority = 1,
.bonus_ways = 0xFFFF,
.retain_on_pc = true,
.activate_on_init = true,
.write_scid_cacheable_en = true,
.stale_en = true,
.stale_cap_en = true,
.alloc_oneway_en = true,
.ovcap_en = true,
.ovcap_prio = true,
.vict_prio = true,
},
{
.usecase_id = LLCC_VIDSC0,
.slice_id = 2,
.max_cap = 256,
.priority = 2,
.fixed_size = true,
.bonus_ways = 0xF000,
.retain_on_pc = true,
.activate_on_init = true,
.write_scid_cacheable_en = true,
.stale_en = true,
.stale_cap_en = true,
},
};
static const struct llcc_slice_config sa8775p_data[] = {
{
.usecase_id = LLCC_CPUSS,
@ -3004,6 +3037,7 @@ static const struct llcc_slice_config x1e80100_data[] = {
.fixed_size = true,
.bonus_ways = 0xfff,
.cache_mode = 0,
.activate_on_init = true,
}, {
.usecase_id = LLCC_CAMEXP0,
.slice_id = 4,
@ -3185,6 +3219,16 @@ static const struct qcom_llcc_config qdu1000_cfg[] = {
},
};
static const struct qcom_llcc_config ipq5424_cfg[] = {
{
.sct_data = ipq5424_data,
.size = ARRAY_SIZE(ipq5424_data),
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
.no_broadcast_register = true,
},
};
static const struct qcom_llcc_config sa8775p_cfg[] = {
{
.sct_data = sa8775p_data,
@ -3360,6 +3404,11 @@ static const struct qcom_sct_config qdu1000_cfgs = {
.num_config = ARRAY_SIZE(qdu1000_cfg),
};
static const struct qcom_sct_config ipq5424_cfgs = {
.llcc_config = ipq5424_cfg,
.num_config = ARRAY_SIZE(ipq5424_cfg),
};
static const struct qcom_sct_config sa8775p_cfgs = {
.llcc_config = sa8775p_cfg,
.num_config = ARRAY_SIZE(sa8775p_cfg),
@ -3957,8 +4006,12 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
if (IS_ERR(drv_data->bcast_regmap)) {
ret = PTR_ERR(drv_data->bcast_regmap);
goto err;
if (cfg->no_broadcast_register) {
drv_data->bcast_regmap = regmap;
} else {
ret = PTR_ERR(drv_data->bcast_regmap);
goto err;
}
}
/* Extract version of the IP */
@ -4029,6 +4082,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs},
{ .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs},
{ .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs},
{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs},

View File

@ -4,6 +4,7 @@
* Copyright (c) 2022, Linaro Ltd
*/
#include <linux/auxiliary_bus.h>
#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
@ -100,15 +101,13 @@ void pmic_glink_client_register(struct pmic_glink_client *client)
struct pmic_glink *pg = client->pg;
unsigned long flags;
mutex_lock(&pg->state_lock);
guard(mutex)(&pg->state_lock);
spin_lock_irqsave(&pg->client_lock, flags);
list_add(&client->node, &pg->clients);
client->pdr_notify(client->priv, pg->client_state);
spin_unlock_irqrestore(&pg->client_lock, flags);
mutex_unlock(&pg->state_lock);
}
EXPORT_SYMBOL_GPL(pmic_glink_client_register);
@ -119,26 +118,25 @@ int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
unsigned long start;
int ret;
mutex_lock(&pg->state_lock);
guard(mutex)(&pg->state_lock);
if (!pg->ept) {
ret = -ECONNRESET;
} else {
start = jiffies;
for (;;) {
ret = rpmsg_send(pg->ept, data, len);
if (ret != -EAGAIN)
break;
if (timeout_reached) {
ret = -ETIMEDOUT;
break;
}
usleep_range(1000, 5000);
timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT);
}
return -ECONNRESET;
}
start = jiffies;
for (;;) {
ret = rpmsg_send(pg->ept, data, len);
if (ret != -EAGAIN)
break;
if (timeout_reached) {
ret = -ETIMEDOUT;
break;
}
usleep_range(1000, 5000);
timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT);
}
mutex_unlock(&pg->state_lock);
return ret;
}
@ -227,51 +225,42 @@ static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv)
{
struct pmic_glink *pg = priv;
mutex_lock(&pg->state_lock);
guard(mutex)(&pg->state_lock);
pg->pdr_state = state;
pmic_glink_state_notify_clients(pg);
mutex_unlock(&pg->state_lock);
}
static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev)
{
struct pmic_glink *pg = __pmic_glink;
int ret = 0;
mutex_lock(&__pmic_glink_lock);
if (!pg) {
ret = dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n");
goto out_unlock;
}
guard(mutex)(&__pmic_glink_lock);
pg = __pmic_glink;
if (!pg)
return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n");
dev_set_drvdata(&rpdev->dev, pg);
mutex_lock(&pg->state_lock);
guard(mutex)(&pg->state_lock);
pg->ept = rpdev->ept;
pmic_glink_state_notify_clients(pg);
mutex_unlock(&pg->state_lock);
out_unlock:
mutex_unlock(&__pmic_glink_lock);
return ret;
return 0;
}
static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev)
{
struct pmic_glink *pg;
mutex_lock(&__pmic_glink_lock);
guard(mutex)(&__pmic_glink_lock);
pg = __pmic_glink;
if (!pg)
goto out_unlock;
return;
mutex_lock(&pg->state_lock);
guard(mutex)(&pg->state_lock);
pg->ept = NULL;
pmic_glink_state_notify_clients(pg);
mutex_unlock(&pg->state_lock);
out_unlock:
mutex_unlock(&__pmic_glink_lock);
}
static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = {
@ -378,9 +367,8 @@ static void pmic_glink_remove(struct platform_device *pdev)
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
mutex_lock(&__pmic_glink_lock);
guard(mutex)(&__pmic_glink_lock);
__pmic_glink = NULL;
mutex_unlock(&__pmic_glink_lock);
}
static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |

View File

@ -5,6 +5,7 @@
*/
#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@ -114,7 +115,7 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm
* The USBC_CMD_WRITE_REQ ack doesn't identify the request, so wait for
* one ack at a time.
*/
mutex_lock(&altmode->lock);
guard(mutex)(&altmode->lock);
req.hdr.owner = cpu_to_le32(altmode->owner_id);
req.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP);
@ -125,18 +126,16 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm
ret = pmic_glink_send(altmode->client, &req, sizeof(req));
if (ret) {
dev_err(altmode->dev, "failed to send altmode request: %#x (%d)\n", cmd, ret);
goto out_unlock;
return ret;
}
left = wait_for_completion_timeout(&altmode->pan_ack, 5 * HZ);
if (!left) {
dev_err(altmode->dev, "timeout waiting for altmode request ack for: %#x\n", cmd);
ret = -ETIMEDOUT;
return -ETIMEDOUT;
}
out_unlock:
mutex_unlock(&altmode->lock);
return ret;
return 0;
}
static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode,

View File

@ -553,6 +553,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
{ .compatible = "qcom,sm4250", .data = sm6115_domains, },
{ .compatible = "qcom,sm6115", .data = sm6115_domains, },
{ .compatible = "qcom,sm6350", .data = sm6350_domains, },
{ .compatible = "qcom,sm7225", .data = sm6350_domains, },
{ .compatible = "qcom,sm7325", .data = sc7280_domains, },
{ .compatible = "qcom,sm8150", .data = sm8150_domains, },
{ .compatible = "qcom,sm8250", .data = sm8250_domains, },
@ -561,6 +562,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
{ .compatible = "qcom,sm8550", .data = sm8550_domains, },
{ .compatible = "qcom,sm8650", .data = sm8550_domains, },
{ .compatible = "qcom,x1e80100", .data = x1e80100_domains, },
{ .compatible = "qcom,x1p42100", .data = x1e80100_domains, },
{},
};

View File

@ -125,7 +125,7 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp)
return 0;
}
static struct class rmtfs_class = {
static const struct class rmtfs_class = {
.name = "rmtfs",
};

View File

@ -112,7 +112,8 @@ struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
if (args.args_count != 1) {
dev_err(dev, "invalid #qcom,smem-state-cells\n");
return ERR_PTR(-EINVAL);
state = ERR_PTR(-EINVAL);
goto put;
}
state = of_node_to_state(args.np);

View File

@ -451,6 +451,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QCS9100) },
{ qcom_board_id(QCS8300) },
{ qcom_board_id(QCS8275) },
{ qcom_board_id(QCS9075) },
{ qcom_board_id(QCS615) },
};
@ -796,7 +797,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
if (!qs->attr.soc_id || !qs->attr.revision)
return -ENOMEM;
if (offsetof(struct socinfo, serial_num) <= item_size) {
if (offsetofend(struct socinfo, serial_num) <= item_size) {
qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%u",
le32_to_cpu(info->serial_num));

View File

@ -284,6 +284,7 @@
#define QCOM_ID_QCS9100 667
#define QCOM_ID_QCS8300 674
#define QCOM_ID_QCS8275 675
#define QCOM_ID_QCS9075 676
#define QCOM_ID_QCS615 680
/*

View File

@ -105,6 +105,14 @@ bool qcom_scm_ice_available(void);
int qcom_scm_ice_invalidate_key(u32 index);
int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
enum qcom_scm_ice_cipher cipher, u32 data_unit_size);
bool qcom_scm_has_wrapped_key_support(void);
int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
u8 *sw_secret, size_t sw_secret_size);
int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size);
int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
u8 *eph_key, size_t eph_key_size);
int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
u8 *lt_key, size_t lt_key_size);
bool qcom_scm_hdcp_available(void);
int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);

View File

@ -6,6 +6,9 @@
#ifndef __SOC_QCOM_TCS_H__
#define __SOC_QCOM_TCS_H__
#include <linux/bitfield.h>
#include <linux/bits.h>
#define MAX_RPMH_PAYLOAD 16
/**
@ -60,22 +63,17 @@ struct tcs_request {
struct tcs_cmd *cmds;
};
#define BCM_TCS_CMD_COMMIT_SHFT 30
#define BCM_TCS_CMD_COMMIT_MASK 0x40000000
#define BCM_TCS_CMD_VALID_SHFT 29
#define BCM_TCS_CMD_VALID_MASK 0x20000000
#define BCM_TCS_CMD_VOTE_X_SHFT 14
#define BCM_TCS_CMD_VOTE_MASK 0x3fff
#define BCM_TCS_CMD_VOTE_Y_SHFT 0
#define BCM_TCS_CMD_VOTE_Y_MASK 0xfffc000
#define BCM_TCS_CMD_COMMIT_MASK BIT(30)
#define BCM_TCS_CMD_VALID_MASK BIT(29)
#define BCM_TCS_CMD_VOTE_MASK GENMASK(13, 0)
#define BCM_TCS_CMD_VOTE_Y_MASK GENMASK(13, 0)
#define BCM_TCS_CMD_VOTE_X_MASK GENMASK(27, 14)
/* Construct a Bus Clock Manager (BCM) specific TCS command */
#define BCM_TCS_CMD(commit, valid, vote_x, vote_y) \
(((commit) << BCM_TCS_CMD_COMMIT_SHFT) | \
((valid) << BCM_TCS_CMD_VALID_SHFT) | \
((cpu_to_le32(vote_x) & \
BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) | \
((cpu_to_le32(vote_y) & \
BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT))
(u32_encode_bits(commit, BCM_TCS_CMD_COMMIT_MASK) | \
u32_encode_bits(valid, BCM_TCS_CMD_VALID_MASK) | \
u32_encode_bits(vote_x, BCM_TCS_CMD_VOTE_X_MASK) | \
u32_encode_bits(vote_y, BCM_TCS_CMD_VOTE_Y_MASK))
#endif /* __SOC_QCOM_TCS_H__ */