diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/arm_scmi/driver.c | 2 | ||||
-rw-r--r-- | drivers/firmware/arm_scmi/mailbox.c | 95 | ||||
-rw-r--r-- | drivers/firmware/arm_scmi/optee.c | 2 | ||||
-rw-r--r-- | drivers/firmware/imx/imx-scu.c | 5 | ||||
-rw-r--r-- | drivers/firmware/imx/scu-pd.c | 4 | ||||
-rw-r--r-- | drivers/firmware/meson/meson_sm.c | 5 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm.c | 16 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp-debugfs.c | 12 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp.c | 6 |
9 files changed, 116 insertions, 31 deletions
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index dbc474ff62b7..e7d97b59963b 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) return ret; ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo); - if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE)) + if (!ret && !idr_is_empty(&sinfo->rx_idr)) ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo); return ret; diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 112c285deb97..1efa5e9392c4 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -19,13 +19,15 @@ * struct scmi_mailbox - Structure representing a SCMI mailbox transport * * @cl: Mailbox Client - * @chan: Transmit/Receive mailbox channel + * @chan: Transmit/Receive mailbox uni/bi-directional channel + * @chan_receiver: Optional Receiver mailbox unidirectional channel * @cinfo: SCMI channel info * @shmem: Transmit/Receive shared memory area */ struct scmi_mailbox { struct mbox_client cl; struct mbox_chan *chan; + struct mbox_chan *chan_receiver; struct scmi_chan_info *cinfo; struct scmi_shared_mem __iomem *shmem; }; @@ -48,30 +50,62 @@ static void rx_callback(struct mbox_client *cl, void *m) static bool mailbox_chan_available(struct device_node *of_node, int idx) { + int num_mb; + + /* + * Just check if bidirrectional channels are involved, and check the + * index accordingly; proper full validation will be made later + * in mailbox_chan_setup(). + */ + num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells"); + if (num_mb == 3 && idx == 1) + idx = 2; + return !of_parse_phandle_with_args(of_node, "mboxes", "#mbox-cells", idx, NULL); } -static int mailbox_chan_validate(struct device *cdev) +/** + * mailbox_chan_validate - Validate transport configuration and map channels + * + * @cdev: Reference to the underlying transport device carrying the + * of_node descriptor to analyze. + * @a2p_rx_chan: A reference to an optional unidirectional channel to use + * for replies on the a2p channel. Set as zero if not present. + * @p2a_chan: A reference to the optional p2a channel. + * Set as zero if not present. + * + * At first, validate the transport configuration as described in terms of + * 'mboxes' and 'shmem', then determin which mailbox channel indexes are + * appropriate to be use in the current configuration. + * + * Return: 0 on Success or error + */ +static int mailbox_chan_validate(struct device *cdev, + int *a2p_rx_chan, int *p2a_chan) { int num_mb, num_sh, ret = 0; struct device_node *np = cdev->of_node; num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); num_sh = of_count_phandle_with_args(np, "shmem", NULL); + dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh); + /* Bail out if mboxes and shmem descriptors are inconsistent */ - if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) { - dev_warn(cdev, "Invalid channel descriptor for '%s'\n", - of_node_full_name(np)); + if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 || + (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) { + dev_warn(cdev, + "Invalid channel descriptor for '%s' - mbs:%d shm:%d\n", + of_node_full_name(np), num_mb, num_sh); return -EINVAL; } + /* Bail out if provided shmem descriptors do not refer distinct areas */ if (num_sh > 1) { struct device_node *np_tx, *np_rx; np_tx = of_parse_phandle(np, "shmem", 0); np_rx = of_parse_phandle(np, "shmem", 1); - /* SCMI Tx and Rx shared mem areas have to be distinct */ if (!np_tx || !np_rx || np_tx == np_rx) { dev_warn(cdev, "Invalid shmem descriptor for '%s'\n", of_node_full_name(np)); @@ -82,6 +116,29 @@ static int mailbox_chan_validate(struct device *cdev) of_node_put(np_rx); } + /* Calculate channels IDs to use depending on mboxes/shmem layout */ + if (!ret) { + switch (num_mb) { + case 1: + *a2p_rx_chan = 0; + *p2a_chan = 0; + break; + case 2: + if (num_sh == 2) { + *a2p_rx_chan = 0; + *p2a_chan = 1; + } else { + *a2p_rx_chan = 1; + *p2a_chan = 0; + } + break; + case 3: + *a2p_rx_chan = 1; + *p2a_chan = 2; + break; + } + } + return ret; } @@ -92,15 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, struct device *cdev = cinfo->dev; struct scmi_mailbox *smbox; struct device_node *shmem; - int ret, idx = tx ? 0 : 1; + int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1; struct mbox_client *cl; resource_size_t size; struct resource res; - ret = mailbox_chan_validate(cdev); + ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan); if (ret) return ret; + if (!tx && !p2a_chan) + return -ENODEV; + smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL); if (!smbox) return -ENOMEM; @@ -130,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, cl->tx_block = false; cl->knows_txdone = tx; - smbox->chan = mbox_request_channel(cl, tx ? 0 : 1); + smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan); if (IS_ERR(smbox->chan)) { ret = PTR_ERR(smbox->chan); if (ret != -EPROBE_DEFER) - dev_err(cdev, "failed to request SCMI %s mailbox\n", - tx ? "Tx" : "Rx"); + dev_err(cdev, + "failed to request SCMI %s mailbox\n", desc); return ret; } + /* Additional unidirectional channel for TX if needed */ + if (tx && a2p_rx_chan) { + smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan); + if (IS_ERR(smbox->chan_receiver)) { + ret = PTR_ERR(smbox->chan_receiver); + if (ret != -EPROBE_DEFER) + dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n"); + return ret; + } + } + cinfo->transport_info = smbox; smbox->cinfo = cinfo; @@ -152,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data) if (smbox && !IS_ERR(smbox->chan)) { mbox_free_channel(smbox->chan); + mbox_free_channel(smbox->chan_receiver); cinfo->transport_info = NULL; smbox->chan = NULL; + smbox->chan_receiver = NULL; smbox->cinfo = NULL; } diff --git a/drivers/firmware/arm_scmi/optee.c b/drivers/firmware/arm_scmi/optee.c index 929720387102..e123de6e8c67 100644 --- a/drivers/firmware/arm_scmi/optee.c +++ b/drivers/firmware/arm_scmi/optee.c @@ -403,7 +403,7 @@ out: static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo, struct scmi_optee_channel *channel) { - if (of_find_property(cinfo->dev->of_node, "shmem", NULL)) + if (of_property_present(cinfo->dev->of_node, "shmem")) return setup_static_shmem(dev, cinfo, channel); else return setup_dynamic_shmem(dev, channel); diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c index dca79caccd01..47db49911e7b 100644 --- a/drivers/firmware/imx/imx-scu.c +++ b/drivers/firmware/imx/imx-scu.c @@ -310,9 +310,8 @@ static int imx_scu_probe(struct platform_device *pdev) sc_chan->ch = mbox_request_channel_byname(cl, chan_name); if (IS_ERR(sc_chan->ch)) { ret = PTR_ERR(sc_chan->ch); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to request mbox chan %s ret %d\n", - chan_name, ret); + dev_err_probe(dev, ret, "Failed to request mbox chan %s\n", + chan_name); kfree(chan_name); return ret; } diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 2a4f07423365..84b673427073 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -180,7 +180,11 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { /* LVDS SS */ { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 }, + { "lvds0-pwm", IMX_SC_R_LVDS_0_PWM_0, 1, false, 0 }, + { "lvds0-lpi2c", IMX_SC_R_LVDS_0_I2C_0, 2, true, 0 }, { "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 }, + { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 }, + { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 }, /* DC SS */ { "dc0", IMX_SC_R_DC_0, 1, false, 0 }, diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c index 3f5ff9ed668e..798bcdb05d84 100644 --- a/drivers/firmware/meson/meson_sm.c +++ b/drivers/firmware/meson/meson_sm.c @@ -311,11 +311,14 @@ static int __init meson_sm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fw); - pr_info("secure-monitor enabled\n"); + if (devm_of_platform_populate(dev)) + goto out_in_base; if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group)) goto out_in_base; + pr_info("secure-monitor enabled\n"); + return 0; out_in_base: diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index b1e11f85b805..fde33acd46b7 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -905,7 +905,7 @@ static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, * Return negative errno on failure or 0 on success with @srcvm updated. */ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *srcvm, + u64 *srcvm, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt) { @@ -922,9 +922,9 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, __le32 *src; void *ptr; int ret, i, b; - unsigned long srcvm_bits = *srcvm; + u64 srcvm_bits = *srcvm; - src_sz = hweight_long(srcvm_bits) * sizeof(*src); + src_sz = hweight64(srcvm_bits) * sizeof(*src); mem_to_map_sz = sizeof(*mem_to_map); dest_sz = dest_cnt * sizeof(*destvm); ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) + @@ -937,8 +937,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, /* Fill source vmid detail */ src = ptr; i = 0; - for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG) - src[i++] = cpu_to_le32(b); + for (b = 0; b < BITS_PER_TYPE(u64); b++) { + if (srcvm_bits & BIT(b)) + src[i++] = cpu_to_le32(b); + } /* Fill details of mem buff to map */ mem_to_map = ptr + ALIGN(src_sz, SZ_64); @@ -1506,8 +1508,7 @@ static int qcom_scm_probe(struct platform_device *pdev) static void qcom_scm_shutdown(struct platform_device *pdev) { /* Clean shutdown, disable download mode to allow normal restart */ - if (download_mode) - qcom_scm_set_download_mode(false); + qcom_scm_set_download_mode(false); } static const struct of_device_id qcom_scm_dt_match[] = { @@ -1542,6 +1543,7 @@ static const struct of_device_id qcom_scm_dt_match[] = { }, { .compatible = "qcom,scm-msm8994" }, { .compatible = "qcom,scm-msm8996" }, + { .compatible = "qcom,scm-sm6375", .data = (void *)SCM_HAS_CORE_CLK }, { .compatible = "qcom,scm" }, {} }; diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 3ca2b5d9e66f..6dfe3d34109e 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -193,7 +193,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name, }, }; u32 fd = 0, len = 0; - int remaining, err; + int remaining, err, close_err; mutex_lock(&bpmp_debug_lock); err = mrq_debug_open(bpmp, name, &fd, &len, 0); @@ -231,7 +231,9 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name, *nbytes = len; close: - err = mrq_debug_close(bpmp, fd); + close_err = mrq_debug_close(bpmp, fd); + if (!err) + err = close_err; out: mutex_unlock(&bpmp_debug_lock); return err; @@ -319,7 +321,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p) }, }; u32 fd = 0, len = 0; - int remaining, err; + int remaining, err, close_err; filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf)); if (!filename) @@ -353,7 +355,9 @@ static int bpmp_debug_show(struct seq_file *m, void *p) } close: - err = mrq_debug_close(bpmp, fd); + close_err = mrq_debug_close(bpmp, fd); + if (!err) + err = close_err; out: mutex_unlock(&bpmp_debug_lock); return err; diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 042c2043929d..8b5e5daa9fae 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -764,19 +764,19 @@ static int tegra_bpmp_probe(struct platform_device *pdev) if (err < 0) goto free_mrq; - if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) { + if (of_property_present(pdev->dev.of_node, "#clock-cells")) { err = tegra_bpmp_init_clocks(bpmp); if (err < 0) goto free_mrq; } - if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) { + if (of_property_present(pdev->dev.of_node, "#reset-cells")) { err = tegra_bpmp_init_resets(bpmp); if (err < 0) goto free_mrq; } - if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) { + if (of_property_present(pdev->dev.of_node, "#power-domain-cells")) { err = tegra_bpmp_init_powergates(bpmp); if (err < 0) goto free_mrq; |