diff options
Diffstat (limited to '')
30 files changed, 285 insertions, 96 deletions
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index ba8f5b5460..fb2bd31387 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -7,7 +7,7 @@ obj-y += apple/ obj-y += aspeed/ obj-$(CONFIG_ARCH_AT91) += atmel/ obj-y += bcm/ -obj-$(CONFIG_SOC_CANAAN) += canaan/ +obj-$(CONFIG_ARCH_CANAAN) += canaan/ obj-$(CONFIG_ARCH_DOVE) += dove/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-y += fsl/ diff --git a/drivers/soc/canaan/Kconfig b/drivers/soc/canaan/Kconfig index 43ced2bf84..3121d351fe 100644 --- a/drivers/soc/canaan/Kconfig +++ b/drivers/soc/canaan/Kconfig @@ -2,9 +2,9 @@ config SOC_K210_SYSCTL bool "Canaan Kendryte K210 SoC system controller" - depends on RISCV && SOC_CANAAN && OF + depends on RISCV && SOC_CANAAN_K210 && OF depends on COMMON_CLK_K210 - default SOC_CANAAN + default SOC_CANAAN_K210 select PM select MFD_SYSCON help diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig index 0ab688af30..4b0a099b28 100644 --- a/drivers/soc/hisilicon/Kconfig +++ b/drivers/soc/hisilicon/Kconfig @@ -6,7 +6,7 @@ menu "Hisilicon SoC drivers" config KUNPENG_HCCS tristate "HCCS driver on Kunpeng SoC" depends on ACPI - depends on MAILBOX + depends on PCC depends on ARM64 || COMPILE_TEST help The Huawei Cache Coherence System (HCCS) is a multi-chip diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 9ff70b38e5..e882a61636 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -556,6 +556,12 @@ static int hccs_get_all_port_attr(struct hccs_dev *hdev, start_id = rsp_head.next_id; } + if (left_buf_len != 0) { + dev_err(hdev->dev, "failed to get the expected port number(%u) attribute.\n", + size); + return -EINVAL; + } + return 0; } diff --git a/drivers/soc/litex/Kconfig b/drivers/soc/litex/Kconfig index e6ba3573a7..f3f8696395 100644 --- a/drivers/soc/litex/Kconfig +++ b/drivers/soc/litex/Kconfig @@ -7,7 +7,7 @@ config LITEX config LITEX_SOC_CONTROLLER tristate "Enable LiteX SoC Controller driver" - depends on OF || COMPILE_TEST + depends on OF depends on HAS_IOMEM select LITEX help diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c index 10813299aa..72c44119dd 100644 --- a/drivers/soc/litex/litex_soc_ctrl.c +++ b/drivers/soc/litex/litex_soc_ctrl.c @@ -82,13 +82,11 @@ static int litex_reset_handler(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -#ifdef CONFIG_OF static const struct of_device_id litex_soc_ctrl_of_match[] = { {.compatible = "litex,soc-controller"}, {}, }; MODULE_DEVICE_TABLE(of, litex_soc_ctrl_of_match); -#endif /* CONFIG_OF */ static int litex_soc_ctrl_probe(struct platform_device *pdev) { @@ -130,7 +128,7 @@ static void litex_soc_ctrl_remove(struct platform_device *pdev) static struct platform_driver litex_soc_ctrl_driver = { .driver = { .name = "litex-soc-controller", - .of_match_table = of_match_ptr(litex_soc_ctrl_of_match) + .of_match_table = litex_soc_ctrl_of_match, }, .probe = litex_soc_ctrl_probe, .remove_new = litex_soc_ctrl_remove, diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 0b2e5690da..046522664d 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -12,6 +12,8 @@ #define CMDQ_WRITE_ENABLE_MASK BIT(0) #define CMDQ_POLL_ENABLE_MASK BIT(0) +/* dedicate the last GPR_R15 to assign the register address to be poll */ +#define CMDQ_POLL_ADDR_GPR (15) #define CMDQ_EOC_IRQ_EN BIT(0) #define CMDQ_REG_TYPE 1 #define CMDQ_JUMP_RELATIVE 0 @@ -56,7 +58,7 @@ int cmdq_dev_get_client_reg(struct device *dev, "mediatek,gce-client-reg", 3, idx, &spec); if (err < 0) { - dev_err(dev, + dev_warn(dev, "error %d can't parse gce-client-reg property (%d)", err, idx); @@ -106,22 +108,16 @@ void cmdq_mbox_destroy(struct cmdq_client *client) } EXPORT_SYMBOL(cmdq_mbox_destroy); -struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size) { - struct cmdq_pkt *pkt; struct device *dev; dma_addr_t dma_addr; - pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); - if (!pkt) - return ERR_PTR(-ENOMEM); pkt->va_base = kzalloc(size, GFP_KERNEL); - if (!pkt->va_base) { - kfree(pkt); - return ERR_PTR(-ENOMEM); - } + if (!pkt->va_base) + return -ENOMEM; + pkt->buf_size = size; - pkt->cl = (void *)client; dev = client->chan->mbox->dev; dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, @@ -129,24 +125,20 @@ struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); kfree(pkt->va_base); - kfree(pkt); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } pkt->pa_base = dma_addr; - return pkt; + return 0; } EXPORT_SYMBOL(cmdq_pkt_create); -void cmdq_pkt_destroy(struct cmdq_pkt *pkt) +void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt) { - struct cmdq_client *client = (struct cmdq_client *)pkt->cl; - dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size, DMA_TO_DEVICE); kfree(pkt->va_base); - kfree(pkt); } EXPORT_SYMBOL(cmdq_pkt_destroy); @@ -300,6 +292,32 @@ int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, } EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value); +int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr) +{ + const u16 high_addr_reg_idx = CMDQ_THR_SPR_IDX0; + const u16 value_reg_idx = CMDQ_THR_SPR_IDX1; + int ret; + + /* read the value of src_addr into high_addr_reg_idx */ + ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(src_addr)); + if (ret < 0) + return ret; + ret = cmdq_pkt_read_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(src_addr), value_reg_idx); + if (ret < 0) + return ret; + + /* write the value of value_reg_idx into dst_addr */ + ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(dst_addr)); + if (ret < 0) + return ret; + ret = cmdq_pkt_write_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(dst_addr), value_reg_idx); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_mem_move); + int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) { struct cmdq_instruction inst = { {0} }; @@ -316,6 +334,21 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) } EXPORT_SYMBOL(cmdq_pkt_wfe); +int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event) +{ + struct cmdq_instruction inst = {}; + + if (event >= CMDQ_MAX_EVENT) + return -EINVAL; + + inst.op = CMDQ_CODE_WFE; + inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE | CMDQ_WFE_WAIT; + inst.event = event; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_acquire_event); + int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) { struct cmdq_instruction inst = { {0} }; @@ -381,6 +414,53 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, } EXPORT_SYMBOL(cmdq_pkt_poll_mask); +int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask) +{ + struct cmdq_instruction inst = { {0} }; + u8 use_mask = 0; + int ret; + + /* + * Append an MASK instruction to set the mask for following POLL instruction + * which enables use_mask bit. + */ + if (mask != GENMASK(31, 0)) { + inst.op = CMDQ_CODE_MASK; + inst.mask = ~mask; + ret = cmdq_pkt_append_command(pkt, inst); + if (ret < 0) + return ret; + use_mask = CMDQ_POLL_ENABLE_MASK; + } + + /* + * POLL is an legacy operation in GCE and it does not support SPR and CMDQ_CODE_LOGIC, + * so it can not use cmdq_pkt_assign to keep polling register address to SPR. + * If user wants to poll a register address which doesn't have a subsys id, + * user needs to use GPR and CMDQ_CODE_MASK to move polling register address to GPR. + */ + inst.op = CMDQ_CODE_MASK; + inst.dst_t = CMDQ_REG_TYPE; + inst.sop = CMDQ_POLL_ADDR_GPR; + inst.value = addr; + ret = cmdq_pkt_append_command(pkt, inst); + if (ret < 0) + return ret; + + /* Append POLL instruction to poll the register address assign to GPR previously. */ + inst.op = CMDQ_CODE_POLL; + inst.dst_t = CMDQ_REG_TYPE; + inst.sop = CMDQ_POLL_ADDR_GPR; + inst.offset = use_mask; + inst.value = value; + ret = cmdq_pkt_append_command(pkt, inst); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_poll_addr); + int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) { struct cmdq_instruction inst = {}; @@ -393,17 +473,36 @@ int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) } EXPORT_SYMBOL(cmdq_pkt_assign); -int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) +int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) { struct cmdq_instruction inst = {}; inst.op = CMDQ_CODE_JUMP; inst.offset = CMDQ_JUMP_ABSOLUTE; - inst.value = addr >> - cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); + inst.value = addr >> shift_pa; + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_jump_abs); + +int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa) +{ + struct cmdq_instruction inst = { {0} }; + + inst.op = CMDQ_CODE_JUMP; + inst.value = (u32)offset >> shift_pa; + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_jump_rel); + +int cmdq_pkt_eoc(struct cmdq_pkt *pkt) +{ + struct cmdq_instruction inst = { {0} }; + + inst.op = CMDQ_CODE_EOC; + inst.value = CMDQ_EOC_IRQ_EN; return cmdq_pkt_append_command(pkt, inst); } -EXPORT_SYMBOL(cmdq_pkt_jump); +EXPORT_SYMBOL(cmdq_pkt_eoc); int cmdq_pkt_finalize(struct cmdq_pkt *pkt) { @@ -427,19 +526,4 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) } EXPORT_SYMBOL(cmdq_pkt_finalize); -int cmdq_pkt_flush_async(struct cmdq_pkt *pkt) -{ - int err; - struct cmdq_client *client = (struct cmdq_client *)pkt->cl; - - err = mbox_send_message(client->chan, pkt); - if (err < 0) - return err; - /* We can send next packet immediately, so just call txdone. */ - mbox_client_txdone(client->chan, 0); - - return 0; -} -EXPORT_SYMBOL(cmdq_pkt_flush_async); - MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 73c256d395..01b129caf1 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -496,6 +496,40 @@ static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_MERGE5] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE4, }; +static const unsigned int mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = { + [MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0, + [MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2, + [MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3, + [MUTEX_MOD_IDX_MDP_FG0] = MT8195_MUTEX_MOD_MDP_FG0, + [MUTEX_MOD_IDX_MDP_FG2] = MT8195_MUTEX_MOD_MDP_FG2, + [MUTEX_MOD_IDX_MDP_FG3] = MT8195_MUTEX_MOD_MDP_FG3, + [MUTEX_MOD_IDX_MDP_HDR0] = MT8195_MUTEX_MOD_MDP_HDR0, + [MUTEX_MOD_IDX_MDP_HDR2] = MT8195_MUTEX_MOD_MDP_HDR2, + [MUTEX_MOD_IDX_MDP_HDR3] = MT8195_MUTEX_MOD_MDP_HDR3, + [MUTEX_MOD_IDX_MDP_AAL0] = MT8195_MUTEX_MOD_MDP_AAL0, + [MUTEX_MOD_IDX_MDP_AAL2] = MT8195_MUTEX_MOD_MDP_AAL2, + [MUTEX_MOD_IDX_MDP_AAL3] = MT8195_MUTEX_MOD_MDP_AAL3, + [MUTEX_MOD_IDX_MDP_RSZ0] = MT8195_MUTEX_MOD_MDP_RSZ0, + [MUTEX_MOD_IDX_MDP_RSZ2] = MT8195_MUTEX_MOD_MDP_RSZ2, + [MUTEX_MOD_IDX_MDP_RSZ3] = MT8195_MUTEX_MOD_MDP_RSZ3, + [MUTEX_MOD_IDX_MDP_MERGE2] = MT8195_MUTEX_MOD_MDP_MERGE2, + [MUTEX_MOD_IDX_MDP_MERGE3] = MT8195_MUTEX_MOD_MDP_MERGE3, + [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8195_MUTEX_MOD_MDP_TDSHP0, + [MUTEX_MOD_IDX_MDP_TDSHP2] = MT8195_MUTEX_MOD_MDP_TDSHP2, + [MUTEX_MOD_IDX_MDP_TDSHP3] = MT8195_MUTEX_MOD_MDP_TDSHP3, + [MUTEX_MOD_IDX_MDP_COLOR0] = MT8195_MUTEX_MOD_MDP_COLOR0, + [MUTEX_MOD_IDX_MDP_COLOR2] = MT8195_MUTEX_MOD_MDP_COLOR2, + [MUTEX_MOD_IDX_MDP_COLOR3] = MT8195_MUTEX_MOD_MDP_COLOR3, + [MUTEX_MOD_IDX_MDP_OVL0] = MT8195_MUTEX_MOD_MDP_OVL0, + [MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0, + [MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2, + [MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3, + [MUTEX_MOD_IDX_MDP_TCC0] = MT8195_MUTEX_MOD_MDP_TCC0, + [MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0, + [MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2, + [MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3, +}; + static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0, [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0, @@ -735,6 +769,13 @@ static const struct mtk_mutex_data mt8188_mutex_driver_data = { .mutex_sof_reg = MT8183_MUTEX0_SOF0, }; +static const struct mtk_mutex_data mt8188_vpp_mutex_driver_data = { + .mutex_sof = mt8188_mutex_sof, + .mutex_mod_reg = MT8183_MUTEX0_MOD0, + .mutex_sof_reg = MT8183_MUTEX0_SOF0, + .mutex_table_mod = mt8188_mdp_mutex_table_mod, +}; + static const struct mtk_mutex_data mt8192_mutex_driver_data = { .mutex_mod = mt8192_mutex_mod, .mutex_sof = mt8183_mutex_sof, @@ -1089,6 +1130,7 @@ static const struct of_device_id mutex_driver_dt_match[] = { { .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data }, { .compatible = "mediatek,mt8186-mdp3-mutex", .data = &mt8186_mdp_mutex_driver_data }, { .compatible = "mediatek,mt8188-disp-mutex", .data = &mt8188_mutex_driver_data }, + { .compatible = "mediatek,mt8188-vpp-mutex", .data = &mt8188_vpp_mutex_driver_data }, { .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data }, { .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data }, { .compatible = "mediatek,mt8195-vpp-mutex", .data = &mt8195_vpp_mutex_driver_data }, diff --git a/drivers/soc/mediatek/mtk-socinfo.c b/drivers/soc/mediatek/mtk-socinfo.c index 42572e8c15..74672a9d6d 100644 --- a/drivers/soc/mediatek/mtk-socinfo.c +++ b/drivers/soc/mediatek/mtk-socinfo.c @@ -48,14 +48,15 @@ static struct socinfo_data socinfo_data_table[] = { MTK_SOCINFO_ENTRY("MT8183", "MT8183V/AZA", "Kompanio 500", 0x00010043, 0x00000940), MTK_SOCINFO_ENTRY("MT8186", "MT8186GV/AZA", "Kompanio 520", 0x81861001, CELL_NOT_USED), MTK_SOCINFO_ENTRY("MT8186T", "MT8186TV/AZA", "Kompanio 528", 0x81862001, CELL_NOT_USED), - MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 830", 0x81880000, 0x00000010), - MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 830", 0x81880000, 0x00000011), + MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 838", 0x81880000, 0x00000010), + MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 838", 0x81880000, 0x00000011), MTK_SOCINFO_ENTRY("MT8192", "MT8192V/AZA", "Kompanio 820", 0x00001100, 0x00040080), MTK_SOCINFO_ENTRY("MT8192T", "MT8192V/ATZA", "Kompanio 828", 0x00000100, 0x000400C0), MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EZA", "Kompanio 1200", 0x81950300, CELL_NOT_USED), MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EHZA", "Kompanio 1200", 0x81950304, CELL_NOT_USED), MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EZA", "Kompanio 1380", 0x81950400, CELL_NOT_USED), MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EHZA", "Kompanio 1380", 0x81950404, CELL_NOT_USED), + MTK_SOCINFO_ENTRY("MT8395", "MT8395AV/ZA", "Genio 1200", 0x83950100, CELL_NOT_USED), }; static int mtk_socinfo_create_socinfo_node(struct mtk_socinfo *mtk_socinfop) @@ -144,7 +145,14 @@ static int mtk_socinfo_get_socinfo_data(struct mtk_socinfo *mtk_socinfop) } } - return match_socinfo_index >= 0 ? match_socinfo_index : -ENOENT; + if (match_socinfo_index < 0) { + dev_warn(mtk_socinfop->dev, + "Unknown MediaTek SoC with ID 0x%08x 0x%08x\n", + cell_data[0], cell_data[1]); + return -ENOENT; + } + + return match_socinfo_index; } static int mtk_socinfo_probe(struct platform_device *pdev) diff --git a/drivers/soc/pxa/ssp.c b/drivers/soc/pxa/ssp.c index 7af04e8b81..854d32e045 100644 --- a/drivers/soc/pxa/ssp.c +++ b/drivers/soc/pxa/ssp.c @@ -25,7 +25,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/platform_device.h> -#include <linux/spi/pxa2xx_spi.h> +#include <linux/pxa2xx_ssp.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_device.h> diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 86fb2cd4f4..d845726620 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -153,12 +153,7 @@ static int cmd_db_get_header(const char *id, const struct entry_header **eh, if (ret) return ret; - /* - * Pad out query string to same length as in DB. NOTE: the output - * query string is not necessarily '\0' terminated if it bumps up - * against the max size. That's OK and expected. - */ - strncpy(query, id, sizeof(query)); + strtomem_pad(query, id, 0); for (i = 0; i < MAX_SLV_ID; i++) { rsc_hdr = &cmd_db_header->header[i]; @@ -392,7 +387,7 @@ static int __init cmd_db_device_init(void) { return platform_driver_register(&cmd_db_dev_driver); } -arch_initcall(cmd_db_device_init); +core_initcall(cmd_db_device_init); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 6567062593..ecddb60bd6 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -282,7 +282,7 @@ static const struct regmap_config msm8998_bwmon_regmap_cfg = { * Cache is necessary for using regmap fields with non-readable * registers. */ - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config msm8998_bwmon_global_regmap_cfg = { @@ -301,7 +301,7 @@ static const struct regmap_config msm8998_bwmon_global_regmap_cfg = { * Cache is necessary for using regmap fields with non-readable * registers. */ - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct reg_field sdm845_cpu_bwmon_reg_fields[] = { @@ -369,7 +369,7 @@ static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = { * Cache is necessary for using regmap fields with non-readable * registers. */ - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* BWMON v5 */ @@ -446,7 +446,7 @@ static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = { * Cache is necessary for using regmap fields with non-readable * registers. */ - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) @@ -565,7 +565,7 @@ static void bwmon_start(struct icc_bwmon *bwmon) int window; /* No need to check for errors, as this must have succeeded before. */ - dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0); + dev_pm_opp_put(dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0)); bwmon_clear_counters(bwmon, true); @@ -772,11 +772,13 @@ static int bwmon_probe(struct platform_device *pdev) opp = dev_pm_opp_find_bw_floor(dev, &bwmon->max_bw_kbps, 0); if (IS_ERR(opp)) return dev_err_probe(dev, PTR_ERR(opp), "failed to find max peak bandwidth\n"); + dev_pm_opp_put(opp); bwmon->min_bw_kbps = 0; opp = dev_pm_opp_find_bw_ceil(dev, &bwmon->min_bw_kbps, 0); if (IS_ERR(opp)) return dev_err_probe(dev, PTR_ERR(opp), "failed to find min peak bandwidth\n"); + dev_pm_opp_put(opp); bwmon->dev = dev; diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c index a1b6a4081d..216166e98f 100644 --- a/drivers/soc/qcom/pdr_interface.c +++ b/drivers/soc/qcom/pdr_interface.c @@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi, locator_hdl); struct pdr_service *pds; + mutex_lock(&pdr->lock); /* Create a local client port for QMI communication */ pdr->locator_addr.sq_family = AF_QIPCRTR; pdr->locator_addr.sq_node = svc->node; pdr->locator_addr.sq_port = svc->port; - mutex_lock(&pdr->lock); pdr->locator_init_complete = true; mutex_unlock(&pdr->lock); @@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi, mutex_lock(&pdr->lock); pdr->locator_init_complete = false; - mutex_unlock(&pdr->lock); pdr->locator_addr.sq_node = 0; pdr->locator_addr.sq_port = 0; + mutex_unlock(&pdr->lock); } static const struct qmi_ops pdr_locator_ops = { @@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req, if (ret < 0) return ret; + mutex_lock(&pdr->lock); ret = qmi_send_request(&pdr->locator_hdl, &pdr->locator_addr, &txn, SERVREG_GET_DOMAIN_LIST_REQ, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN, servreg_get_domain_list_req_ei, req); + mutex_unlock(&pdr->lock); if (ret < 0) { qmi_txn_cancel(&txn); return ret; @@ -415,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds) if (ret < 0) goto out; - for (i = domains_read; i < resp->domain_list_len; i++) { + for (i = 0; i < resp->domain_list_len; i++) { entry = &resp->domain_list[i]; if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name)) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 823fd108fa..9ebc0ba359 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -348,16 +348,15 @@ 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_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,sc8180x-pmic-glink", .data = &pmic_glink_sc8180x_client_mask }, - { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8180x_client_mask }, + { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8280xp_client_mask }, { .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask }, {} }; @@ -374,8 +373,17 @@ static struct platform_driver pmic_glink_driver = { static int pmic_glink_init(void) { - platform_driver_register(&pmic_glink_driver); - register_rpmsg_driver(&pmic_glink_rpmsg_driver); + int ret; + + ret = platform_driver_register(&pmic_glink_driver); + if (ret < 0) + return ret; + + ret = register_rpmsg_driver(&pmic_glink_rpmsg_driver); + if (ret < 0) { + platform_driver_unregister(&pmic_glink_driver); + return ret; + } return 0; } diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c index 238cd38589..39f412bbf2 100644 --- a/drivers/soc/qcom/pmic_pdcharger_ulog.c +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c @@ -150,6 +150,10 @@ static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = { { "PMIC_LOGS_ADSP_APPS" }, {} }; +/* + * No MODULE_DEVICE_TABLE intentionally: that's a debugging module, to be + * loaded manually only. + */ static struct rpmsg_driver pmic_pdcharger_ulog_rpmsg_driver = { .probe = pmic_pdcharger_ulog_rpmsg_probe, diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.h b/drivers/soc/qcom/pmic_pdcharger_ulog.h index 152e3a6b54..1cfa58f0e3 100644 --- a/drivers/soc/qcom/pmic_pdcharger_ulog.h +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.h @@ -18,7 +18,7 @@ TRACE_EVENT(pmic_pdcharger_ulog_msg, __string(msg, msg) ), TP_fast_assign( - __assign_str(msg, msg); + __assign_str(msg); ), TP_printk("%s", __get_str(msg)) ); diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 0216fc24f2..c429d5154a 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -35,11 +35,15 @@ static const struct subsystem_data subsystems[] = { { "wpss", 605, 13 }, { "adsp", 606, 2 }, { "cdsp", 607, 5 }, + { "cdsp1", 607, 12 }, + { "gpdsp0", 607, 17 }, + { "gpdsp1", 607, 18 }, { "slpi", 608, 3 }, { "gpu", 609, 0 }, { "display", 610, 0 }, { "adsp_island", 613, 2 }, { "slpi_island", 613, 3 }, + { "apss", 631, QCOM_SMEM_HOST_ANY }, }; struct stats_config { diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c index 9ca13bcf67..086fe4ba67 100644 --- a/drivers/soc/qcom/rpm_master_stats.c +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -148,6 +148,10 @@ static const struct of_device_id rpm_master_table[] = { { .compatible = "qcom,rpm-master-stats" }, { }, }; +/* + * No MODULE_DEVICE_TABLE intentionally: that's a debugging module, to be + * loaded manually only. + */ static struct platform_driver master_stats_driver = { .probe = master_stats_probe, diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index daf64be966..de86009ecd 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -646,13 +646,14 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) { struct tcs_group *tcs; int tcs_id; - unsigned long flags; + + might_sleep(); tcs = get_tcs_for_msg(drv, msg); if (IS_ERR(tcs)) return PTR_ERR(tcs); - spin_lock_irqsave(&drv->lock, flags); + spin_lock_irq(&drv->lock); /* Wait forever for a free tcs. It better be there eventually! */ wait_event_lock_irq(drv->tcs_wait, @@ -670,7 +671,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); enable_tcs_irq(drv, tcs_id, true); } - spin_unlock_irqrestore(&drv->lock, flags); + spin_unlock_irq(&drv->lock); /* * These two can be done after the lock is released because: @@ -1155,7 +1156,7 @@ static int __init rpmh_driver_init(void) { return platform_driver_register(&rpmh_driver); } -arch_initcall(rpmh_driver_init); +core_initcall(rpmh_driver_init); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 9f26d7f9b9..8903ed9563 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -183,7 +183,6 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, } if (state == RPMH_ACTIVE_ONLY_STATE) { - WARN_ON(irqs_disabled()); ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg); } else { /* Clean up our call by spoofing tx_done */ diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index e8ff9819ac..41342c3791 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -133,6 +133,8 @@ static const char *const pmic_models[] = { [72] = "PMR735D", [73] = "PM8550", [74] = "PMK8550", + [82] = "PMC8380", + [83] = "SMB2360", }; struct socinfo_params { @@ -430,6 +432,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QRU1000) }, { qcom_board_id(SM8475_2) }, { qcom_board_id(QDU1000) }, + { qcom_board_id(X1E80100) }, { qcom_board_id(SM8650) }, { qcom_board_id(SM4450) }, { qcom_board_id(QDU1010) }, diff --git a/drivers/soc/qcom/trace-aoss.h b/drivers/soc/qcom/trace-aoss.h index 554029b33b..fb5b0470c4 100644 --- a/drivers/soc/qcom/trace-aoss.h +++ b/drivers/soc/qcom/trace-aoss.h @@ -18,7 +18,7 @@ TRACE_EVENT(aoss_send, __string(msg, msg) ), TP_fast_assign( - __assign_str(msg, msg); + __assign_str(msg); ), TP_printk("%s", __get_str(msg)) ); @@ -31,7 +31,7 @@ TRACE_EVENT(aoss_send_done, __field(int, ret) ), TP_fast_assign( - __assign_str(msg, msg); + __assign_str(msg); __entry->ret = ret; ), TP_printk("%s: %d", __get_str(msg), __entry->ret) diff --git a/drivers/soc/qcom/trace-rpmh.h b/drivers/soc/qcom/trace-rpmh.h index be6b42ecc1..593ec1d4e0 100644 --- a/drivers/soc/qcom/trace-rpmh.h +++ b/drivers/soc/qcom/trace-rpmh.h @@ -26,7 +26,7 @@ TRACE_EVENT(rpmh_tx_done, ), TP_fast_assign( - __assign_str(name, d->name); + __assign_str(name); __entry->m = m; __entry->addr = r->cmds[0].addr; __entry->data = r->cmds[0].data; @@ -55,7 +55,7 @@ TRACE_EVENT(rpmh_send_msg, ), TP_fast_assign( - __assign_str(name, d->name); + __assign_str(name); __entry->m = m; __entry->state = state; __entry->n = n; diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 5deca747fb..5d94c3f314 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -24,6 +24,7 @@ config ARCH_RCAR_GEN2 select RENESAS_IRQC select RST_RCAR select SYS_SUPPORTS_SH_CMT + select SYS_SUPPORTS_SH_TMU config ARCH_RCAR_GEN3 bool @@ -344,6 +345,11 @@ config ARCH_R9A09G011 help This enables support for the Renesas RZ/V2M SoC. +config ARCH_R9A09G057 + bool "ARM64 Platform support for RZ/V2H(P)" + help + This enables support for the Renesas RZ/V2H(P) SoC variants. + endif # ARM64 if RISCV diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 8f9b8d3736..172d59e6fb 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -75,6 +75,10 @@ static const struct renesas_family fam_rzg3s __initconst __maybe_unused = { .name = "RZ/G3S", }; +static const struct renesas_family fam_rzv2h __initconst __maybe_unused = { + .name = "RZ/V2H", +}; + static const struct renesas_family fam_rzv2l __initconst __maybe_unused = { .name = "RZ/V2L", }; @@ -177,6 +181,11 @@ static const struct renesas_soc soc_rz_g3s __initconst __maybe_unused = { .id = 0x85e0447, }; +static const struct renesas_soc soc_rz_v2h __initconst __maybe_unused = { + .family = &fam_rzv2h, + .id = 0x847a447, +}; + static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = { .family = &fam_rzv2l, .id = 0x8447447, @@ -407,6 +416,9 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = { #ifdef CONFIG_ARCH_R9A09G011 { .compatible = "renesas,r9a09g011", .data = &soc_rz_v2m }, #endif +#ifdef CONFIG_ARCH_R9A09G057 + { .compatible = "renesas,r9a09g057", .data = &soc_rz_v2h }, +#endif #ifdef CONFIG_ARCH_SH73A0 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, #endif @@ -432,6 +444,11 @@ static const struct renesas_id id_rzg2l __initconst = { .mask = 0xfffffff, }; +static const struct renesas_id id_rzv2h __initconst = { + .offset = 0x304, + .mask = 0xfffffff, +}; + static const struct renesas_id id_rzv2m __initconst = { .offset = 0x104, .mask = 0xff, @@ -449,6 +466,7 @@ static const struct of_device_id renesas_ids[] __initconst = { { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a08g045-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a09g011-sys", .data = &id_rzv2m }, + { .compatible = "renesas,r9a09g057-sys", .data = &id_rzv2h }, { .compatible = "renesas,prr", .data = &id_prr }, { /* sentinel */ } }; @@ -513,7 +531,7 @@ static int __init renesas_soc_init(void) eslo = product & 0xf; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi, eslo); - } else if (id == &id_rzg2l) { + } else if (id == &id_rzg2l || id == &id_rzv2h) { eshi = ((product >> 28) & 0x0f); soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u", eshi); diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c index d60af8acc3..97006cc3b9 100644 --- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -11,6 +11,7 @@ #include <linux/cpu.h> #include <linux/device.h> +#include <linux/energy_model.h> #include <linux/errno.h> #include <linux/of.h> #include <linux/pm_opp.h> @@ -97,9 +98,16 @@ static int exynos_asv_update_opps(struct exynos_asv *asv) last_opp_table = opp_table; ret = exynos_asv_update_cpu_opps(asv, cpu); - if (ret < 0) + if (!ret) { + /* + * Update EM power values since OPP + * voltage values may have changed. + */ + em_dev_update_chip_binning(cpu); + } else { dev_err(asv->dev, "Couldn't udate OPPs for cpu%d\n", cpuid); + } } dev_pm_opp_put_opp_table(opp_table); diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index b6bfd6729d..d276672838 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -127,8 +127,8 @@ static void tegra_fuse_print_sku_info(struct tegra_sku_info *tegra_sku_info) static int tegra_fuse_add_lookups(struct tegra_fuse *fuse) { - fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups), - fuse->soc->num_lookups, GFP_KERNEL); + fuse->lookups = kmemdup_array(fuse->soc->lookups, fuse->soc->num_lookups, + sizeof(*fuse->lookups), GFP_KERNEL); if (!fuse->lookups) return -ENOMEM; diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index d6bfcea5ee..91d0ad6dde 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -4074,6 +4074,7 @@ static const char * const tegra194_reset_sources[] = { }; static const struct tegra_wake_event tegra194_wake_events[] = { + TEGRA_WAKE_GPIO("eqos", 20, 0, TEGRA194_MAIN_GPIO(G, 4)), TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)), TEGRA_WAKE_IRQ("rtc", 73, 10), @@ -4210,6 +4211,7 @@ static const char * const tegra234_reset_sources[] = { static const struct tegra_wake_event tegra234_wake_events[] = { TEGRA_WAKE_GPIO("sd-wake", 8, 0, TEGRA234_MAIN_GPIO(G, 7)), + TEGRA_WAKE_GPIO("eqos", 20, 0, TEGRA234_MAIN_GPIO(G, 4)), TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)), TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)), diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c index 253299e421..366018f6a0 100644 --- a/drivers/soc/xilinx/xlnx_event_manager.c +++ b/drivers/soc/xilinx/xlnx_event_manager.c @@ -3,6 +3,7 @@ * Xilinx Event Management Driver * * Copyright (C) 2021 Xilinx, Inc. + * Copyright (C) 2024 Advanced Micro Devices, Inc. * * Abhyuday Godhasara <abhyuday.godhasara@xilinx.com> */ @@ -19,7 +20,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> -static DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number1); +static DEFINE_PER_CPU_READ_MOSTLY(int, dummy_cpu_number); static int virq_sgi; static int event_manager_availability = -EACCES; @@ -570,7 +571,6 @@ static void xlnx_disable_percpu_irq(void *data) static int xlnx_event_init_sgi(struct platform_device *pdev) { int ret = 0; - int cpu; /* * IRQ related structures are used for the following: * for each SGI interrupt ensure its mapped by GIC IRQ domain @@ -607,11 +607,8 @@ static int xlnx_event_init_sgi(struct platform_device *pdev) sgi_fwspec.param[0] = sgi_num; virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec); - cpu = get_cpu(); - per_cpu(cpu_number1, cpu) = cpu; ret = request_percpu_irq(virq_sgi, xlnx_event_handler, "xlnx_event_mgmt", - &cpu_number1); - put_cpu(); + &dummy_cpu_number); WARN_ON(ret); if (ret) { @@ -627,16 +624,12 @@ static int xlnx_event_init_sgi(struct platform_device *pdev) static void xlnx_event_cleanup_sgi(struct platform_device *pdev) { - int cpu = smp_processor_id(); - - per_cpu(cpu_number1, cpu) = cpu; - cpuhp_remove_state(CPUHP_AP_ONLINE_DYN); on_each_cpu(xlnx_disable_percpu_irq, NULL, 1); irq_clear_status_flags(virq_sgi, IRQ_PER_CPU); - free_percpu_irq(virq_sgi, &cpu_number1); + free_percpu_irq(virq_sgi, &dummy_cpu_number); irq_dispose_mapping(virq_sgi); } diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c index 965b114393..b82c01373f 100644 --- a/drivers/soc/xilinx/zynqmp_power.c +++ b/drivers/soc/xilinx/zynqmp_power.c @@ -190,7 +190,9 @@ static int zynqmp_pm_probe(struct platform_device *pdev) u32 pm_api_version; struct mbox_client *client; - zynqmp_pm_get_api_version(&pm_api_version); + ret = zynqmp_pm_get_api_version(&pm_api_version); + if (ret) + return ret; /* Check PM API version number */ if (pm_api_version < ZYNQMP_PM_VERSION) |