diff options
Diffstat (limited to 'drivers/soc/qcom')
-rw-r--r-- | drivers/soc/qcom/Kconfig | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/ice.c | 401 | ||||
-rw-r--r-- | drivers/soc/qcom/llcc-qcom.c | 497 | ||||
-rw-r--r-- | drivers/soc/qcom/mdt_loader.c | 10 | ||||
-rw-r--r-- | drivers/soc/qcom/pdr_interface.c | 8 | ||||
-rw-r--r-- | drivers/soc/qcom/pdr_internal.h | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/pmic_glink.c | 85 | ||||
-rw-r--r-- | drivers/soc/qcom/pmic_glink_altmode.c | 41 | ||||
-rw-r--r-- | drivers/soc/qcom/qcom_aoss.c | 3 | ||||
-rw-r--r-- | drivers/soc/qcom/qcom_pd_mapper.c | 25 | ||||
-rw-r--r-- | drivers/soc/qcom/qcom_pdr_msg.c | 3 | ||||
-rw-r--r-- | drivers/soc/qcom/qmi_encdec.c | 52 | ||||
-rw-r--r-- | drivers/soc/qcom/qmi_interface.c | 6 | ||||
-rw-r--r-- | drivers/soc/qcom/rmtfs_mem.c | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmh-rsc.c | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/smem.c | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/smp2p.c | 4 | ||||
-rw-r--r-- | drivers/soc/qcom/smsm.c | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/socinfo.c | 2 |
19 files changed, 1019 insertions, 129 deletions
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 74b9121240f8..58e63cf0036b 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -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 diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index 393d2d1d275f..c467b55b4174 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -11,6 +11,7 @@ #include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/device.h> #include <linux/iopoll.h> #include <linux/of.h> #include <linux/of_platform.h> @@ -20,20 +21,63 @@ #include <soc/qcom/ice.h> -#define AES_256_XTS_KEY_SIZE 64 +#define AES_256_XTS_KEY_SIZE 64 /* for raw keys only */ +#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE 100 /* assuming HWKM v2 */ /* QCOM ICE registers */ + +#define QCOM_ICE_REG_CONTROL 0x0000 +#define QCOM_ICE_LEGACY_MODE_ENABLED BIT(0) + #define QCOM_ICE_REG_VERSION 0x0008 + #define QCOM_ICE_REG_FUSE_SETTING 0x0010 +#define QCOM_ICE_FUSE_SETTING_MASK BIT(0) +#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK BIT(1) +#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK BIT(2) + #define QCOM_ICE_REG_BIST_STATUS 0x0070 +#define QCOM_ICE_BIST_STATUS_MASK GENMASK(31, 28) + #define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 -/* BIST ("built-in self-test") status flags */ -#define QCOM_ICE_BIST_STATUS_MASK GENMASK(31, 28) +#define QCOM_ICE_REG_CRYPTOCFG_BASE 0x4040 +#define QCOM_ICE_REG_CRYPTOCFG_SIZE 0x80 +#define QCOM_ICE_REG_CRYPTOCFG(slot) (QCOM_ICE_REG_CRYPTOCFG_BASE + \ + QCOM_ICE_REG_CRYPTOCFG_SIZE * (slot)) +union crypto_cfg { + __le32 regval; + struct { + u8 dusize; + u8 capidx; + u8 reserved; +#define QCOM_ICE_HWKM_CFG_ENABLE_VAL BIT(7) + u8 cfge; + }; +}; + +/* QCOM ICE HWKM (Hardware Key Manager) registers */ -#define QCOM_ICE_FUSE_SETTING_MASK 0x1 -#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 -#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 +#define HWKM_OFFSET 0x8000 + +#define QCOM_ICE_REG_HWKM_TZ_KM_CTL (HWKM_OFFSET + 0x1000) +#define QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL (BIT(1) | BIT(2)) + +#define QCOM_ICE_REG_HWKM_TZ_KM_STATUS (HWKM_OFFSET + 0x1004) +#define QCOM_ICE_HWKM_KT_CLEAR_DONE BIT(0) +#define QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE BIT(1) +#define QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE BIT(2) +#define QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 BIT(7) +#define QCOM_ICE_HWKM_BIST_DONE_V2 BIT(9) + +#define QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS (HWKM_OFFSET + 0x2008) +#define QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL BIT(3) + +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_0 (HWKM_OFFSET + 0x5000) +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_1 (HWKM_OFFSET + 0x5004) +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_2 (HWKM_OFFSET + 0x5008) +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_3 (HWKM_OFFSET + 0x500C) +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_4 (HWKM_OFFSET + 0x5010) #define qcom_ice_writel(engine, val, reg) \ writel((val), (engine)->base + (reg)) @@ -41,11 +85,18 @@ #define qcom_ice_readl(engine, reg) \ readl((engine)->base + (reg)) +static bool qcom_ice_use_wrapped_keys; +module_param_named(use_wrapped_keys, qcom_ice_use_wrapped_keys, bool, 0660); +MODULE_PARM_DESC(use_wrapped_keys, + "Support wrapped keys instead of raw keys, if available on the platform"); + struct qcom_ice { struct device *dev; void __iomem *base; struct clk *core_clk; + bool use_hwkm; + bool hwkm_init_complete; }; static bool qcom_ice_check_supported(struct qcom_ice *ice) @@ -75,6 +126,35 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice) return false; } + /* + * Check for HWKM support and decide whether to use it or not. ICE + * v3.2.1 and later have HWKM v2. ICE v3.2.0 has HWKM v1. Earlier ICE + * versions don't have HWKM at all. However, for HWKM to be fully + * usable by Linux, the TrustZone software also needs to support certain + * SCM calls including the ones to generate and prepare keys. That + * effectively makes the earliest supported SoC be SM8650, which has + * HWKM v2. Therefore, this driver doesn't include support for HWKM v1, + * and it checks for the SCM call support before it decides to use HWKM. + * + * Also, since HWKM and legacy mode are mutually exclusive, and + * ICE-capable storage driver(s) need to know early on whether to + * advertise support for raw keys or wrapped keys, HWKM cannot be used + * unconditionally. A module parameter is used to opt into using it. + */ + if ((major >= 4 || + (major == 3 && (minor >= 3 || (minor == 2 && step >= 1)))) && + qcom_scm_has_wrapped_key_support()) { + if (qcom_ice_use_wrapped_keys) { + dev_info(dev, "Using HWKM. Supporting wrapped keys only.\n"); + ice->use_hwkm = true; + } else { + dev_info(dev, "Not using HWKM. Supporting raw keys only.\n"); + } + } else if (qcom_ice_use_wrapped_keys) { + dev_warn(dev, "A supported HWKM is not present. Ignoring qcom_ice.use_wrapped_keys=1.\n"); + } else { + dev_info(dev, "A supported HWKM is not present. Supporting raw keys only.\n"); + } return true; } @@ -122,17 +202,71 @@ static int qcom_ice_wait_bist_status(struct qcom_ice *ice) err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS, regval, !(regval & QCOM_ICE_BIST_STATUS_MASK), 50, 5000); - if (err) + if (err) { dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n"); + return err; + } - return err; + if (ice->use_hwkm && + qcom_ice_readl(ice, QCOM_ICE_REG_HWKM_TZ_KM_STATUS) != + (QCOM_ICE_HWKM_KT_CLEAR_DONE | + QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE | + QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE | + QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 | + QCOM_ICE_HWKM_BIST_DONE_V2)) { + dev_err(ice->dev, "HWKM self-test error!\n"); + /* + * Too late to revoke use_hwkm here, as it was already + * propagated up the stack into the crypto capabilities. + */ + } + return 0; +} + +static void qcom_ice_hwkm_init(struct qcom_ice *ice) +{ + u32 regval; + + if (!ice->use_hwkm) + return; + + BUILD_BUG_ON(QCOM_ICE_HWKM_WRAPPED_KEY_SIZE > + BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE); + /* + * When ICE is in HWKM mode, it only supports wrapped keys. + * When ICE is in legacy mode, it only supports raw keys. + * + * Put ICE in HWKM mode. ICE defaults to legacy mode. + */ + regval = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL); + regval &= ~QCOM_ICE_LEGACY_MODE_ENABLED; + qcom_ice_writel(ice, regval, QCOM_ICE_REG_CONTROL); + + /* Disable CRC checks. This HWKM feature is not used. */ + qcom_ice_writel(ice, QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL, + QCOM_ICE_REG_HWKM_TZ_KM_CTL); + + /* + * Allow the HWKM slave to read and write the keyslots in the ICE HWKM + * slave. Without this, TrustZone cannot program keys into ICE. + */ + qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_0); + qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_1); + qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_2); + qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_3); + qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_4); + + /* Clear the HWKM response FIFO. */ + qcom_ice_writel(ice, QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL, + QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS); + ice->hwkm_init_complete = true; } int qcom_ice_enable(struct qcom_ice *ice) { qcom_ice_low_power_mode_enable(ice); qcom_ice_optimization_enable(ice); - + qcom_ice_hwkm_init(ice); return qcom_ice_wait_bist_status(ice); } EXPORT_SYMBOL_GPL(qcom_ice_enable); @@ -148,7 +282,7 @@ int qcom_ice_resume(struct qcom_ice *ice) err); return err; } - + qcom_ice_hwkm_init(ice); return qcom_ice_wait_bist_status(ice); } EXPORT_SYMBOL_GPL(qcom_ice_resume); @@ -156,15 +290,58 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume); int qcom_ice_suspend(struct qcom_ice *ice) { clk_disable_unprepare(ice->core_clk); + ice->hwkm_init_complete = false; return 0; } EXPORT_SYMBOL_GPL(qcom_ice_suspend); -int qcom_ice_program_key(struct qcom_ice *ice, - u8 algorithm_id, u8 key_size, - const u8 crypto_key[], u8 data_unit_size, - int slot) +static unsigned int translate_hwkm_slot(struct qcom_ice *ice, unsigned int slot) +{ + return slot * 2; +} + +static int qcom_ice_program_wrapped_key(struct qcom_ice *ice, unsigned int slot, + const struct blk_crypto_key *bkey) +{ + struct device *dev = ice->dev; + union crypto_cfg cfg = { + .dusize = bkey->crypto_cfg.data_unit_size / 512, + .capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS, + .cfge = QCOM_ICE_HWKM_CFG_ENABLE_VAL, + }; + int err; + + if (!ice->use_hwkm) { + dev_err_ratelimited(dev, "Got wrapped key when not using HWKM\n"); + return -EINVAL; + } + if (!ice->hwkm_init_complete) { + dev_err_ratelimited(dev, "HWKM not yet initialized\n"); + return -EINVAL; + } + + /* Clear CFGE before programming the key. */ + qcom_ice_writel(ice, 0x0, QCOM_ICE_REG_CRYPTOCFG(slot)); + + /* Call into TrustZone to program the wrapped key using HWKM. */ + err = qcom_scm_ice_set_key(translate_hwkm_slot(ice, slot), bkey->bytes, + bkey->size, cfg.capidx, cfg.dusize); + if (err) { + dev_err_ratelimited(dev, + "qcom_scm_ice_set_key failed; err=%d, slot=%u\n", + err, slot); + return err; + } + + /* Set CFGE after programming the key. */ + qcom_ice_writel(ice, le32_to_cpu(cfg.regval), + QCOM_ICE_REG_CRYPTOCFG(slot)); + return 0; +} + +int qcom_ice_program_key(struct qcom_ice *ice, unsigned int slot, + const struct blk_crypto_key *blk_key) { struct device *dev = ice->dev; union { @@ -175,15 +352,26 @@ int qcom_ice_program_key(struct qcom_ice *ice, int err; /* Only AES-256-XTS has been tested so far. */ - if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS || - key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) { - dev_err_ratelimited(dev, - "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", - algorithm_id, key_size); + if (blk_key->crypto_cfg.crypto_mode != + BLK_ENCRYPTION_MODE_AES_256_XTS) { + dev_err_ratelimited(dev, "Unsupported crypto mode: %d\n", + blk_key->crypto_cfg.crypto_mode); + return -EINVAL; + } + + if (blk_key->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) + return qcom_ice_program_wrapped_key(ice, slot, blk_key); + + if (ice->use_hwkm) { + dev_err_ratelimited(dev, "Got raw key when using HWKM\n"); return -EINVAL; } - memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE); + if (blk_key->size != AES_256_XTS_KEY_SIZE) { + dev_err_ratelimited(dev, "Incorrect key size\n"); + return -EINVAL; + } + memcpy(key.bytes, blk_key->bytes, AES_256_XTS_KEY_SIZE); /* The SCM call requires that the key words are encoded in big endian */ for (i = 0; i < ARRAY_SIZE(key.words); i++) @@ -191,7 +379,7 @@ int qcom_ice_program_key(struct qcom_ice *ice, err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, QCOM_SCM_ICE_CIPHER_AES_256_XTS, - data_unit_size); + blk_key->crypto_cfg.data_unit_size / 512); memzero_explicit(&key, sizeof(key)); @@ -201,10 +389,131 @@ EXPORT_SYMBOL_GPL(qcom_ice_program_key); int qcom_ice_evict_key(struct qcom_ice *ice, int slot) { + if (ice->hwkm_init_complete) + slot = translate_hwkm_slot(ice, slot); return qcom_scm_ice_invalidate_key(slot); } EXPORT_SYMBOL_GPL(qcom_ice_evict_key); +/** + * qcom_ice_get_supported_key_type() - Get the supported key type + * @ice: ICE driver data + * + * Return: the blk-crypto key type that the ICE driver is configured to use. + * This is the key type that ICE-capable storage drivers should advertise as + * supported in the crypto capabilities of any disks they register. + */ +enum blk_crypto_key_type qcom_ice_get_supported_key_type(struct qcom_ice *ice) +{ + if (ice->use_hwkm) + return BLK_CRYPTO_KEY_TYPE_HW_WRAPPED; + return BLK_CRYPTO_KEY_TYPE_RAW; +} +EXPORT_SYMBOL_GPL(qcom_ice_get_supported_key_type); + +/** + * qcom_ice_derive_sw_secret() - Derive software secret from wrapped key + * @ice: ICE driver data + * @eph_key: an ephemerally-wrapped key + * @eph_key_size: size of @eph_key in bytes + * @sw_secret: output buffer for the software secret + * + * Use HWKM to derive the "software secret" from a hardware-wrapped key that is + * given in ephemerally-wrapped form. + * + * Return: 0 on success; -EBADMSG if the given ephemerally-wrapped key is + * invalid; or another -errno value. + */ +int qcom_ice_derive_sw_secret(struct qcom_ice *ice, + const u8 *eph_key, size_t eph_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) +{ + int err = qcom_scm_derive_sw_secret(eph_key, eph_key_size, + sw_secret, + BLK_CRYPTO_SW_SECRET_SIZE); + if (err == -EIO || err == -EINVAL) + err = -EBADMSG; /* probably invalid key */ + return err; +} +EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret); + +/** + * qcom_ice_generate_key() - Generate a wrapped key for inline encryption + * @ice: ICE driver data + * @lt_key: output buffer for the long-term wrapped key + * + * Use HWKM to generate a new key and return it as a long-term wrapped key. + * + * Return: the size of the resulting wrapped key on success; -errno on failure. + */ +int qcom_ice_generate_key(struct qcom_ice *ice, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + int err; + + err = qcom_scm_generate_ice_key(lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); + if (err) + return err; + + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; +} +EXPORT_SYMBOL_GPL(qcom_ice_generate_key); + +/** + * qcom_ice_prepare_key() - Prepare a wrapped key for inline encryption + * @ice: ICE driver data + * @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 + * + * Use HWKM to re-wrap a long-term wrapped key with the per-boot ephemeral key. + * + * Return: the size of the resulting wrapped key on success; -EBADMSG if the + * given long-term wrapped key is invalid; or another -errno value. + */ +int qcom_ice_prepare_key(struct qcom_ice *ice, + const u8 *lt_key, size_t lt_key_size, + u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + int err; + + err = qcom_scm_prepare_ice_key(lt_key, lt_key_size, + eph_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); + if (err == -EIO || err == -EINVAL) + err = -EBADMSG; /* probably invalid key */ + if (err) + return err; + + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; +} +EXPORT_SYMBOL_GPL(qcom_ice_prepare_key); + +/** + * qcom_ice_import_key() - Import a raw key for inline encryption + * @ice: ICE driver data + * @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 + * + * Use HWKM to import a raw key and return it as a long-term wrapped key. + * + * Return: the size of the resulting wrapped key on success; -errno on failure. + */ +int qcom_ice_import_key(struct qcom_ice *ice, + const u8 *raw_key, size_t raw_key_size, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + int err; + + err = qcom_scm_import_ice_key(raw_key, raw_key_size, + lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); + if (err) + return err; + + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; +} +EXPORT_SYMBOL_GPL(qcom_ice_import_key); + static struct qcom_ice *qcom_ice_create(struct device *dev, void __iomem *base) { @@ -261,7 +570,7 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, * Return: ICE pointer on success, NULL if there is no ICE data provided by the * consumer or ERR_PTR() on error. */ -struct qcom_ice *of_qcom_ice_get(struct device *dev) +static struct qcom_ice *of_qcom_ice_get(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct qcom_ice *ice; @@ -322,7 +631,53 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev) return ice; } -EXPORT_SYMBOL_GPL(of_qcom_ice_get); + +static void qcom_ice_put(const struct qcom_ice *ice) +{ + struct platform_device *pdev = to_platform_device(ice->dev); + + if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice")) + platform_device_put(pdev); +} + +static void devm_of_qcom_ice_put(struct device *dev, void *res) +{ + qcom_ice_put(*(struct qcom_ice **)res); +} + +/** + * devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from + * a DT node. + * @dev: device pointer for the consumer device. + * + * This function will provide an ICE instance either by creating one for the + * consumer device if its DT node provides the 'ice' reg range and the 'ice' + * clock (for legacy DT style). On the other hand, if consumer provides a + * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already + * be created and so this function will return that instead. + * + * Return: ICE pointer on success, NULL if there is no ICE data provided by the + * consumer or ERR_PTR() on error. + */ +struct qcom_ice *devm_of_qcom_ice_get(struct device *dev) +{ + struct qcom_ice *ice, **dr; + + dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + ice = of_qcom_ice_get(dev); + if (!IS_ERR_OR_NULL(ice)) { + *dr = ice; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return ice; +} +EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get); static int qcom_ice_probe(struct platform_device *pdev) { diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 56823b6a2fac..192edc3f64dc 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -35,6 +35,11 @@ #define ATTR0_RES_WAYS_MASK GENMASK(15, 0) #define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16) #define ATTR0_BONUS_WAYS_SHIFT 16 +#define ATTR2_PROBE_TARGET_WAYS_MASK BIT(4) +#define ATTR2_FIXED_SIZE_MASK BIT(8) +#define ATTR2_PRIORITY_MASK GENMASK(14, 12) +#define ATTR2_PARENT_SCID_MASK GENMASK(21, 16) +#define ATTR2_IN_A_GROUP_MASK BIT(24) #define LLCC_STATUS_READ_DELAY 100 #define CACHE_LINE_SIZE_SHIFT 6 @@ -49,6 +54,10 @@ #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_4 * n) +#define LLCC_V6_TRP_ATTR0_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR0_CFG] + SZ_64 * (n)) +#define LLCC_V6_TRP_ATTR1_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR1_CFG] + SZ_64 * (n)) +#define LLCC_V6_TRP_ATTR2_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR2_CFG] + SZ_64 * (n)) +#define LLCC_V6_TRP_ATTR3_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR3_CFG] + SZ_64 * (n)) #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 @@ -66,6 +75,7 @@ #define LLCC_VERSION_2_0_0_0 0x02000000 #define LLCC_VERSION_2_1_0_0 0x02010000 #define LLCC_VERSION_4_1_0_0 0x04010000 +#define LLCC_VERSION_6_0_0_0 0X06000000 /** * struct llcc_slice_config - Data associated with the llcc slice @@ -106,6 +116,7 @@ * ovcap_en. * @vict_prio: When current scid is under-capacity, allocate over other * lower-than victim priority-line threshold scid. + * @parent_slice_id: For grouped slices, specifies the slice id of the parent. */ struct llcc_slice_config { u32 usecase_id; @@ -130,6 +141,7 @@ struct llcc_slice_config { bool ovcap_en; bool ovcap_prio; bool vict_prio; + u32 parent_slice_id; }; struct qcom_llcc_config { @@ -153,6 +165,21 @@ struct qcom_sct_config { enum llcc_reg_offset { LLCC_COMMON_HW_INFO, LLCC_COMMON_STATUS0, + LLCC_TRP_ATTR0_CFG, + LLCC_TRP_ATTR1_CFG, + LLCC_TRP_ATTR2_CFG, + LLCC_TRP_ATTR3_CFG, + LLCC_TRP_SID_DIS_CAP_ALLOC, + LLCC_TRP_ALGO_STALE_EN, + LLCC_TRP_ALGO_STALE_CAP_EN, + LLCC_TRP_ALGO_MRU0, + LLCC_TRP_ALGO_MRU1, + LLCC_TRP_ALGO_ALLOC0, + LLCC_TRP_ALGO_ALLOC1, + LLCC_TRP_ALGO_ALLOC2, + LLCC_TRP_ALGO_ALLOC3, + LLCC_TRP_WRS_EN, + LLCC_TRP_WRS_CACHEABLE_EN, }; static const struct llcc_slice_config ipq5424_data[] = { @@ -2662,6 +2689,263 @@ static const struct llcc_slice_config sm8650_data[] = { }, }; +static const struct llcc_slice_config sm8750_data[] = { + { + .usecase_id = LLCC_CPUSS, + .slice_id = 1, + .max_cap = 5120, + .priority = 1, + .bonus_ways = 0xffffffff, + .activate_on_init = true, + .write_scid_en = true, + }, { + .usecase_id = LLCC_MDMHPFX, + .slice_id = 24, + .max_cap = 1024, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_VIDSC0, + .slice_id = 2, + .max_cap = 512, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_AUDIO, + .slice_id = 35, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_MDMHPGRW, + .slice_id = 25, + .max_cap = 1024, + .priority = 5, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_MODHW, + .slice_id = 26, + .max_cap = 1024, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_CMPT, + .slice_id = 34, + .max_cap = 4096, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_GPUHTW, + .slice_id = 11, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_GPU, + .slice_id = 9, + .max_cap = 5632, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .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 = 0xffffffff, + .activate_on_init = true, + }, { + .usecase_id = LLCC_DISP, + .slice_id = 16, + .max_cap = 7168, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .cache_mode = 2, + .stale_en = true, + }, { + .usecase_id = LLCC_VIDFW, + .slice_id = 17, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_CAMFW, + .slice_id = 20, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_MDMPNG, + .slice_id = 27, + .max_cap = 256, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0xf0000000, + }, { + .usecase_id = LLCC_AUDHW, + .slice_id = 22, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_CVP, + .slice_id = 8, + .max_cap = 800, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .vict_prio = true, + }, { + .usecase_id = LLCC_MODPE, + .slice_id = 29, + .max_cap = 256, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xf0000000, + .alloc_oneway_en = true, + }, { + .usecase_id = LLCC_WRCACHE, + .slice_id = 31, + .max_cap = 512, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .activate_on_init = true, + }, { + .usecase_id = LLCC_CVPFW, + .slice_id = 19, + .max_cap = 64, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_CMPTHCP, + .slice_id = 15, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_LCPDARE, + .slice_id = 30, + .max_cap = 128, + .priority = 5, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .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 = 0xffffffff, + .cache_mode = 2, + }, { + .usecase_id = LLCC_ISLAND1, + .slice_id = 12, + .max_cap = 7936, + .priority = 7, + .fixed_size = true, + .bonus_ways = 0x7fffffff, + }, { + .usecase_id = LLCC_DISP_WB, + .slice_id = 23, + .max_cap = 512, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_VIDVSP, + .slice_id = 4, + .max_cap = 256, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + }, { + .usecase_id = LLCC_VIDDEC, + .slice_id = 5, + .max_cap = 6144, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .cache_mode = 2, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CAMOFE, + .slice_id = 33, + .max_cap = 6144, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .stale_en = true, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CAMRTIP, + .slice_id = 13, + .max_cap = 1024, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .stale_en = true, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CAMSRTIP, + .slice_id = 14, + .max_cap = 6144, + .priority = 4, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .stale_en = true, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CAMRTRF, + .slice_id = 7, + .max_cap = 3584, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .stale_en = true, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CAMSRTRF, + .slice_id = 21, + .max_cap = 6144, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .stale_en = true, + .ovcap_prio = true, + .parent_slice_id = 33, + }, { + .usecase_id = LLCC_CPUSSMPAM, + .slice_id = 6, + .max_cap = 2048, + .priority = 1, + .fixed_size = true, + .bonus_ways = 0xffffffff, + .activate_on_init = true, + .write_scid_en = true, + }, +}; + static const struct llcc_slice_config qcs615_data[] = { { .usecase_id = LLCC_CPUSS, @@ -3161,6 +3445,33 @@ static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = { .drp_ecc_db_err_syn0 = 0x52120, }; +static const struct llcc_edac_reg_offset llcc_v6_edac_reg_offset = { + .trp_ecc_error_status0 = 0x47448, + .trp_ecc_error_status1 = 0x47450, + .trp_ecc_sb_err_syn0 = 0x47490, + .trp_ecc_db_err_syn0 = 0x474d0, + .trp_ecc_error_cntr_clear = 0x47444, + .trp_interrupt_0_status = 0x47600, + .trp_interrupt_0_clear = 0x47604, + .trp_interrupt_0_enable = 0x47608, + + /* LLCC Common registers */ + .cmn_status0 = 0x6400c, + .cmn_interrupt_0_enable = 0x6401c, + .cmn_interrupt_2_enable = 0x6403c, + + /* LLCC DRP registers */ + .drp_ecc_error_cfg = 0x80000, + .drp_ecc_error_cntr_clear = 0x80004, + .drp_interrupt_status = 0x80020, + .drp_interrupt_clear = 0x80028, + .drp_interrupt_enable = 0x8002c, + .drp_ecc_error_status0 = 0x820f4, + .drp_ecc_error_status1 = 0x820f8, + .drp_ecc_sb_err_syn0 = 0x820fc, + .drp_ecc_db_err_syn0 = 0x82120, +}; + /* LLCC register offset starting from v1.0.0 */ static const u32 llcc_v1_reg_offset[] = { [LLCC_COMMON_HW_INFO] = 0x00030000, @@ -3173,6 +3484,27 @@ static const u32 llcc_v2_1_reg_offset[] = { [LLCC_COMMON_STATUS0] = 0x0003400c, }; +/* LLCC register offset starting from v6.0.0 */ +static const u32 llcc_v6_reg_offset[] = { + [LLCC_COMMON_HW_INFO] = 0x00064000, + [LLCC_COMMON_STATUS0] = 0x0006400c, + [LLCC_TRP_ATTR0_CFG] = 0x00041000, + [LLCC_TRP_ATTR1_CFG] = 0x00041008, + [LLCC_TRP_ATTR2_CFG] = 0x00041010, + [LLCC_TRP_ATTR3_CFG] = 0x00041014, + [LLCC_TRP_SID_DIS_CAP_ALLOC] = 0x00042000, + [LLCC_TRP_ALGO_STALE_EN] = 0x00042008, + [LLCC_TRP_ALGO_STALE_CAP_EN] = 0x00042010, + [LLCC_TRP_ALGO_MRU0] = 0x00042018, + [LLCC_TRP_ALGO_MRU1] = 0x00042020, + [LLCC_TRP_ALGO_ALLOC0] = 0x00042028, + [LLCC_TRP_ALGO_ALLOC1] = 0x00042030, + [LLCC_TRP_ALGO_ALLOC2] = 0x00042038, + [LLCC_TRP_ALGO_ALLOC3] = 0x00042040, + [LLCC_TRP_WRS_EN] = 0x00042080, + [LLCC_TRP_WRS_CACHEABLE_EN] = 0x00042088, +}; + static const struct qcom_llcc_config qcs615_cfg[] = { { .sct_data = qcs615_data, @@ -3379,6 +3711,16 @@ static const struct qcom_llcc_config sm8650_cfg[] = { }, }; +static const struct qcom_llcc_config sm8750_cfg[] = { + { + .sct_data = sm8750_data, + .size = ARRAY_SIZE(sm8750_data), + .skip_llcc_cfg = false, + .reg_offset = llcc_v6_reg_offset, + .edac_reg_offset = &llcc_v6_edac_reg_offset, + }, +}; + static const struct qcom_llcc_config x1e80100_cfg[] = { { .sct_data = x1e80100_data, @@ -3489,6 +3831,11 @@ static const struct qcom_sct_config sm8650_cfgs = { .num_config = ARRAY_SIZE(sm8650_cfg), }; +static const struct qcom_sct_config sm8750_cfgs = { + .llcc_config = sm8750_cfg, + .num_config = ARRAY_SIZE(sm8750_cfg), +}; + static const struct qcom_sct_config x1e80100_cfgs = { .llcc_config = x1e80100_cfg, .num_config = ARRAY_SIZE(x1e80100_cfg), @@ -3869,6 +4216,139 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } +static int _qcom_llcc_cfg_program_v6(const struct llcc_slice_config *config, + const struct qcom_llcc_config *cfg) +{ + u32 stale_en, stale_cap_en, mru_uncap_en, mru_rollover; + u32 alloc_oneway_en, ovcap_en, ovcap_prio, vict_prio; + u32 attr0_cfg, attr1_cfg, attr2_cfg, attr3_cfg; + u32 attr0_val, attr1_val, attr2_val, attr3_val; + u32 slice_offset, reg_offset; + struct llcc_slice_desc *desc; + u32 wren, wr_cache_en; + int ret; + + attr0_cfg = LLCC_V6_TRP_ATTR0_CFGn(config->slice_id); + attr1_cfg = LLCC_V6_TRP_ATTR1_CFGn(config->slice_id); + attr2_cfg = LLCC_V6_TRP_ATTR2_CFGn(config->slice_id); + attr3_cfg = LLCC_V6_TRP_ATTR3_CFGn(config->slice_id); + + attr0_val = config->res_ways; + attr1_val = config->bonus_ways; + attr2_val = config->cache_mode; + attr2_val |= FIELD_PREP(ATTR2_PROBE_TARGET_WAYS_MASK, config->probe_target_ways); + attr2_val |= FIELD_PREP(ATTR2_FIXED_SIZE_MASK, config->fixed_size); + attr2_val |= FIELD_PREP(ATTR2_PRIORITY_MASK, config->priority); + + if (config->parent_slice_id && config->fixed_size) { + attr2_val |= FIELD_PREP(ATTR2_PARENT_SCID_MASK, config->parent_slice_id); + attr2_val |= ATTR2_IN_A_GROUP_MASK; + } + + attr3_val = MAX_CAP_TO_BYTES(config->max_cap); + attr3_val /= drv_data->num_banks; + attr3_val >>= CACHE_LINE_SIZE_SHIFT; + + ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, attr0_val); + if (ret) + return ret; + + ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, attr1_val); + if (ret) + return ret; + + ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val); + if (ret) + return ret; + + ret = regmap_write(drv_data->bcast_regmap, attr3_cfg, attr3_val); + if (ret) + return ret; + + slice_offset = config->slice_id % 32; + reg_offset = (config->slice_id / 32) * 4; + + wren = config->write_scid_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_WRS_EN] + reg_offset, + BIT(slice_offset), wren); + if (ret) + return ret; + + wr_cache_en = config->write_scid_cacheable_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_WRS_CACHEABLE_EN] + reg_offset, + BIT(slice_offset), wr_cache_en); + if (ret) + return ret; + + stale_en = config->stale_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_STALE_EN] + reg_offset, + BIT(slice_offset), stale_en); + if (ret) + return ret; + + stale_cap_en = config->stale_cap_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_STALE_CAP_EN] + reg_offset, + BIT(slice_offset), stale_cap_en); + if (ret) + return ret; + + mru_uncap_en = config->mru_uncap_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_MRU0] + reg_offset, + BIT(slice_offset), mru_uncap_en); + if (ret) + return ret; + + mru_rollover = config->mru_rollover << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_MRU1] + reg_offset, + BIT(slice_offset), mru_rollover); + if (ret) + return ret; + + alloc_oneway_en = config->alloc_oneway_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC0] + reg_offset, + BIT(slice_offset), alloc_oneway_en); + if (ret) + return ret; + + ovcap_en = config->ovcap_en << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC1] + reg_offset, + BIT(slice_offset), ovcap_en); + if (ret) + return ret; + + ovcap_prio = config->ovcap_prio << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC2] + reg_offset, + BIT(slice_offset), ovcap_prio); + if (ret) + return ret; + + vict_prio = config->vict_prio << slice_offset; + ret = regmap_update_bits(drv_data->bcast_regmap, + cfg->reg_offset[LLCC_TRP_ALGO_ALLOC3] + reg_offset, + BIT(slice_offset), vict_prio); + if (ret) + return ret; + + if (config->activate_on_init) { + desc = llcc_slice_getd(config->usecase_id); + if (PTR_ERR_OR_ZERO(desc)) + return -EINVAL; + + ret = llcc_slice_activate(desc); + } + + return ret; +} + static int qcom_llcc_cfg_program(struct platform_device *pdev, const struct qcom_llcc_config *cfg) { @@ -3880,10 +4360,18 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev, sz = drv_data->cfg_size; llcc_table = drv_data->cfg; - for (i = 0; i < sz; i++) { - ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg); - if (ret) - return ret; + if (drv_data->version >= LLCC_VERSION_6_0_0_0) { + for (i = 0; i < sz; i++) { + ret = _qcom_llcc_cfg_program_v6(&llcc_table[i], cfg); + if (ret) + return ret; + } + } else { + for (i = 0; i < sz; i++) { + ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg); + if (ret) + return ret; + } } return ret; @@ -4102,6 +4590,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfgs }, { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfgs }, { .compatible = "qcom,sm8650-llcc", .data = &sm8650_cfgs }, + { .compatible = "qcom,sm8750-llcc", .data = &sm8750_cfgs }, { .compatible = "qcom,x1e80100-llcc", .data = &x1e80100_cfgs }, { } }; diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index b2c0fb55d4ae..44589d10b15b 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -83,7 +83,7 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw) int i; ehdr = (struct elf32_hdr *)fw->data; - phdrs = (struct elf32_phdr *)(ehdr + 1); + phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; @@ -135,7 +135,7 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, void *data; ehdr = (struct elf32_hdr *)fw->data; - phdrs = (struct elf32_phdr *)(ehdr + 1); + phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); if (ehdr->e_phnum < 2) return ERR_PTR(-EINVAL); @@ -215,7 +215,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, int i; ehdr = (struct elf32_hdr *)fw->data; - phdrs = (struct elf32_phdr *)(ehdr + 1); + phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; @@ -270,7 +270,7 @@ static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_na int i; ehdr = (struct elf32_hdr *)fw->data; - phdrs = (struct elf32_phdr *)(ehdr + 1); + phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { /* @@ -312,7 +312,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, is_split = qcom_mdt_bins_are_split(fw, fw_name); ehdr = (struct elf32_hdr *)fw->data; - phdrs = (struct elf32_phdr *)(ehdr + 1); + phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c index 328b6153b2be..71be378d2e43 100644 --- a/drivers/soc/qcom/pdr_interface.c +++ b/drivers/soc/qcom/pdr_interface.c @@ -75,7 +75,6 @@ static int pdr_locator_new_server(struct qmi_handle *qmi, { struct pdr_handle *pdr = container_of(qmi, struct pdr_handle, locator_hdl); - struct pdr_service *pds; mutex_lock(&pdr->lock); /* Create a local client port for QMI communication */ @@ -87,12 +86,7 @@ static int pdr_locator_new_server(struct qmi_handle *qmi, mutex_unlock(&pdr->lock); /* Service pending lookup requests */ - mutex_lock(&pdr->list_lock); - list_for_each_entry(pds, &pdr->lookups, node) { - if (pds->need_locator_lookup) - schedule_work(&pdr->locator_work); - } - mutex_unlock(&pdr->list_lock); + schedule_work(&pdr->locator_work); return 0; } diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h index 8d17f7fb79e7..039508c1bbf7 100644 --- a/drivers/soc/qcom/pdr_internal.h +++ b/drivers/soc/qcom/pdr_internal.h @@ -91,7 +91,6 @@ struct servreg_loc_pfr_resp { struct qmi_response_type_v01 rsp; }; -extern const struct qmi_elem_info servreg_location_entry_ei[]; extern const struct qmi_elem_info servreg_get_domain_list_req_ei[]; extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[]; extern const struct qmi_elem_info servreg_register_listener_req_ei[]; diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index caf3f63d940e..c0a4be5df926 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -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; } @@ -169,7 +167,10 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data, return 0; } -static void pmic_glink_aux_release(struct device *dev) {} +static void pmic_glink_aux_release(struct device *dev) +{ + of_node_put(dev->of_node); +} static int pmic_glink_add_aux_device(struct pmic_glink *pg, struct auxiliary_device *aux, @@ -183,8 +184,10 @@ static int pmic_glink_add_aux_device(struct pmic_glink *pg, aux->dev.release = pmic_glink_aux_release; device_set_of_node_from_dev(&aux->dev, parent); ret = auxiliary_device_init(aux); - if (ret) + if (ret) { + of_node_put(aux->dev.of_node); return ret; + } ret = auxiliary_device_add(aux); if (ret) @@ -227,51 +230,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; + struct pmic_glink *pg; - 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,20 +372,15 @@ 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) | - 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,sc8280xp-pmic-glink", .data = &pmic_glink_sc8280xp_client_mask }, { .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask }, {} }; diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 463b1c528831..7f11acd33323 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -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, @@ -219,21 +218,29 @@ static void pmic_glink_altmode_worker(struct work_struct *work) { struct pmic_glink_altmode_port *alt_port = work_to_altmode_port(work); struct pmic_glink_altmode *altmode = alt_port->altmode; + enum drm_connector_status conn_status; typec_switch_set(alt_port->typec_switch, alt_port->orientation); - if (alt_port->svid == USB_TYPEC_DP_SID && alt_port->mode == 0xff) - pmic_glink_altmode_safe(altmode, alt_port); - else if (alt_port->svid == USB_TYPEC_DP_SID) - pmic_glink_altmode_enable_dp(altmode, alt_port, alt_port->mode, - alt_port->hpd_state, alt_port->hpd_irq); - else - pmic_glink_altmode_enable_usb(altmode, alt_port); + if (alt_port->svid == USB_TYPEC_DP_SID) { + if (alt_port->mode == 0xff) { + pmic_glink_altmode_safe(altmode, alt_port); + } else { + pmic_glink_altmode_enable_dp(altmode, alt_port, + alt_port->mode, + alt_port->hpd_state, + alt_port->hpd_irq); + } - drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, - alt_port->hpd_state ? - connector_status_connected : - connector_status_disconnected); + if (alt_port->hpd_state) + conn_status = connector_status_connected; + else + conn_status = connector_status_disconnected; + + drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status); + } else { + pmic_glink_altmode_enable_usb(altmode, alt_port); + } pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index); } diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 0320ad3b9148..a543ab9bee6c 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -12,6 +12,7 @@ #include <linux/platform_device.h> #include <linux/thermal.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/soc/qcom/qcom_aoss.h> #define CREATE_TRACE_POINTS @@ -358,7 +359,7 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, return 0; ret = qmp_send(qmp_cdev->qmp, "{class: volt_flr, event:zero_temp, res:%s, value:%s}", - qmp_cdev->name, cdev_state ? "on" : "off"); + qmp_cdev->name, str_on_off(cdev_state)); if (!ret) qmp_cdev->state = cdev_state; diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 6e30f08761aa..3abea241b1c4 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -429,6 +429,16 @@ static const struct qcom_pdm_domain_data *sc8280xp_domains[] = { NULL, }; +/* Unlike SDM660, SDM630/636 lack CDSP */ +static const struct qcom_pdm_domain_data *sdm630_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &adsp_sensor_pd, + &mpss_root_pd, + &mpss_wlan_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sdm660_domains[] = { &adsp_audio_pd, &adsp_root_pd, @@ -478,6 +488,16 @@ static const struct qcom_pdm_domain_data *sm6350_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *sm7150_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &adsp_sensor_pd, + &cdsp_root_pd, + &mpss_root_pd_gps, + &mpss_wlan_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sm8150_domains[] = { &adsp_audio_pd, &adsp_root_pd, @@ -546,6 +566,8 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, + { .compatible = "qcom,sdm630", .data = sdm630_domains, }, + { .compatible = "qcom,sdm636", .data = sdm630_domains, }, { .compatible = "qcom,sda660", .data = sdm660_domains, }, { .compatible = "qcom,sdm660", .data = sdm660_domains, }, { .compatible = "qcom,sdm670", .data = sdm670_domains, }, @@ -553,6 +575,8 @@ 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,sm7150", .data = sm7150_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 +585,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, }, {}, }; diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c index bf3e4a47165e..ca98932140d8 100644 --- a/drivers/soc/qcom/qcom_pdr_msg.c +++ b/drivers/soc/qcom/qcom_pdr_msg.c @@ -8,7 +8,7 @@ #include "pdr_internal.h" -const struct qmi_elem_info servreg_location_entry_ei[] = { +static const struct qmi_elem_info servreg_location_entry_ei[] = { { .data_type = QMI_STRING, .elem_len = SERVREG_NAME_LENGTH + 1, @@ -47,7 +47,6 @@ const struct qmi_elem_info servreg_location_entry_ei[] = { }, {} }; -EXPORT_SYMBOL_GPL(servreg_location_entry_ei); const struct qmi_elem_info servreg_get_domain_list_req_ei[] = { { diff --git a/drivers/soc/qcom/qmi_encdec.c b/drivers/soc/qcom/qmi_encdec.c index bb09eff85cff..7660a960fb45 100644 --- a/drivers/soc/qcom/qmi_encdec.c +++ b/drivers/soc/qcom/qmi_encdec.c @@ -304,6 +304,8 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf, const void *buf_src; int encode_tlv = 0; int rc; + u8 val8; + u16 val16; if (!ei_array) return 0; @@ -338,7 +340,6 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf, break; case QMI_DATA_LEN: - memcpy(&data_len_value, buf_src, temp_ei->elem_size); data_len_sz = temp_ei->elem_size == sizeof(u8) ? sizeof(u8) : sizeof(u16); /* Check to avoid out of range buffer access */ @@ -348,8 +349,17 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf, __func__); return -ETOOSMALL; } - rc = qmi_encode_basic_elem(buf_dst, &data_len_value, - 1, data_len_sz); + if (data_len_sz == sizeof(u8)) { + val8 = *(u8 *)buf_src; + data_len_value = (u32)val8; + rc = qmi_encode_basic_elem(buf_dst, &val8, + 1, data_len_sz); + } else { + val16 = *(u16 *)buf_src; + data_len_value = (u32)le16_to_cpu(val16); + rc = qmi_encode_basic_elem(buf_dst, &val16, + 1, data_len_sz); + } UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst, encoded_bytes, tlv_len, encode_tlv, rc); @@ -523,14 +533,23 @@ static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array, u32 string_len = 0; u32 string_len_sz = 0; const struct qmi_elem_info *temp_ei = ei_array; + u8 val8; + u16 val16; if (dec_level == 1) { string_len = tlv_len; } else { string_len_sz = temp_ei->elem_len <= U8_MAX ? sizeof(u8) : sizeof(u16); - rc = qmi_decode_basic_elem(&string_len, buf_src, - 1, string_len_sz); + if (string_len_sz == sizeof(u8)) { + rc = qmi_decode_basic_elem(&val8, buf_src, + 1, string_len_sz); + string_len = (u32)val8; + } else { + rc = qmi_decode_basic_elem(&val16, buf_src, + 1, string_len_sz); + string_len = (u32)val16; + } decoded_bytes += rc; } @@ -604,6 +623,9 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct, u32 decoded_bytes = 0; const void *buf_src = in_buf; int rc; + u8 val8; + u16 val16; + u32 val32; while (decoded_bytes < in_buf_len) { if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI) @@ -642,9 +664,17 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct, if (temp_ei->data_type == QMI_DATA_LEN) { data_len_sz = temp_ei->elem_size == sizeof(u8) ? sizeof(u8) : sizeof(u16); - rc = qmi_decode_basic_elem(&data_len_value, buf_src, - 1, data_len_sz); - memcpy(buf_dst, &data_len_value, sizeof(u32)); + if (data_len_sz == sizeof(u8)) { + rc = qmi_decode_basic_elem(&val8, buf_src, + 1, data_len_sz); + data_len_value = (u32)val8; + } else { + rc = qmi_decode_basic_elem(&val16, buf_src, + 1, data_len_sz); + data_len_value = (u32)val16; + } + val32 = cpu_to_le32(data_len_value); + memcpy(buf_dst, &val32, sizeof(u32)); temp_ei = temp_ei + 1; buf_dst = out_c_struct + temp_ei->offset; tlv_len -= data_len_sz; @@ -746,9 +776,9 @@ void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, hdr = msg; hdr->type = type; - hdr->txn_id = txn_id; - hdr->msg_id = msg_id; - hdr->msg_len = msglen; + hdr->txn_id = cpu_to_le16(txn_id); + hdr->msg_id = cpu_to_le16(msg_id); + hdr->msg_len = cpu_to_le16(msglen); *len = sizeof(*hdr) + msglen; diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index bc6d6379d8b1..6500f863aae5 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -400,7 +400,7 @@ static void qmi_invoke_handler(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, for (handler = qmi->handlers; handler->fn; handler++) { if (handler->type == hdr->type && - handler->msg_id == hdr->msg_id) + handler->msg_id == le16_to_cpu(hdr->msg_id)) break; } @@ -488,7 +488,7 @@ static void qmi_handle_message(struct qmi_handle *qmi, /* If this is a response, find the matching transaction handle */ if (hdr->type == QMI_RESPONSE) { mutex_lock(&qmi->txn_lock); - txn = idr_find(&qmi->txns, hdr->txn_id); + txn = idr_find(&qmi->txns, le16_to_cpu(hdr->txn_id)); /* Ignore unexpected responses */ if (!txn) { @@ -514,7 +514,7 @@ static void qmi_handle_message(struct qmi_handle *qmi, } else { /* Create a txn based on the txn_id of the incoming message */ memset(&tmp_txn, 0, sizeof(tmp_txn)); - tmp_txn.id = hdr->txn_id; + tmp_txn.id = le16_to_cpu(hdr->txn_id); qmi_invoke_handler(qmi, sq, &tmp_txn, buf, len); } diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c index 33603b8fd8f3..1b32469f2789 100644 --- a/drivers/soc/qcom/rmtfs_mem.c +++ b/drivers/soc/qcom/rmtfs_mem.c @@ -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", }; diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index cb82e887b51d..fdab2b1067db 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -1072,7 +1072,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT); drv->ver.minor >>= MINOR_VER_SHIFT; - if (drv->ver.major == 3) + if (drv->ver.major >= 3) drv->regs = rpmh_rsc_reg_offset_ver_3_0; else drv->regs = rpmh_rsc_reg_offset_ver_2_7; diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 592819701809..cf425930539e 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -86,7 +86,7 @@ #define SMEM_GLOBAL_HOST 0xfffe /* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 20 +#define SMEM_HOST_COUNT 25 /** * struct smem_proc_comm - proc_comm communication struct (legacy) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index a3e88ced328a..cb515c2340c1 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -399,7 +399,7 @@ static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p, struct smp2p_entry *entry, struct device_node *node) { - entry->domain = irq_domain_add_linear(node, 32, &smp2p_irq_ops, entry); + entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smp2p_irq_ops, entry); if (!entry->domain) { dev_err(smp2p->dev, "failed to add irq_domain\n"); return -ENOMEM; @@ -575,7 +575,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev) smp2p->mbox_client.knows_txdone = true; smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); if (IS_ERR(smp2p->mbox_chan)) { - if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) + if (PTR_ERR(smp2p->mbox_chan) != -ENOENT) return PTR_ERR(smp2p->mbox_chan); smp2p->mbox_chan = NULL; diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index e803ea342c97..021e9d1f61dc 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -456,7 +456,7 @@ static int smsm_inbound_entry(struct qcom_smsm *smsm, return ret; } - entry->domain = irq_domain_add_linear(node, 32, &smsm_irq_ops, entry); + entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smsm_irq_ops, entry); if (!entry->domain) { dev_err(smsm->dev, "failed to add irq_domain\n"); return -ENOMEM; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index d49c55979bb3..8c4147737c35 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -444,6 +444,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ5302) }, { qcom_board_id(QCS8550) }, { qcom_board_id(QCM8550) }, + { qcom_board_id(SM8750) }, { qcom_board_id(IPQ5300) }, { qcom_board_id(IPQ5321) }, { qcom_board_id(IPQ5424) }, @@ -451,6 +452,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) }, }; |