[PATCH v5 1/3] mailbox: Introduce support for T-head TH1520 Mailbox driver
Christophe JAILLET
christophe.jaillet at wanadoo.fr
Thu Oct 31 14:05:53 PDT 2024
Le 31/10/2024 à 21:47, Michal Wilczynski a écrit :
> This driver was tested using the drm/imagination GPU driver. It was able
> to successfully power on the GPU, by passing a command through mailbox
> from E910 core to E902 that's responsible for powering up the GPU. The
> GPU driver was able to read the BVNC version from control registers,
> which confirms it was successfully powered on.
>
> [ 33.957467] powervr ffef400000.gpu: [drm] loaded firmware
> powervr/rogue_36.52.104.182_v1.fw
> [ 33.966008] powervr ffef400000.gpu: [drm] FW version v1.0 (build
> 6621747 OS)
> [ 38.978542] powervr ffef400000.gpu: [drm] *ERROR* Firmware failed to
> boot
>
> Though the driver still fails to boot the firmware, the mailbox driver
> works when used with the not-yet-upstreamed firmware AON driver. There
> is ongoing work to get the BXM-4-64 supported with the drm/imagination
> driver [1], though it's not completed yet.
>
> This work is based on the driver from the vendor kernel [2].
>
> Link: https://gitlab.freedesktop.org/imagination/linux-firmware/-/issues/2 [1]
> Link: https://github.com/revyos/thead-kernel.git [2]
>
> Signed-off-by: Michal Wilczynski <m.wilczynski at samsung.com>
> ---
Hi,
> +static int th1520_mbox_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct th1520_mbox_priv *priv;
> + unsigned int remote_idx = 0;
> + unsigned int i;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = dev;
> +
> + priv->clocks[0].id = "clk-local";
> + priv->clocks[1].id = "clk-remote-icu0";
> + priv->clocks[2].id = "clk-remote-icu1";
> + priv->clocks[3].id = "clk-remote-icu2";
> +
> + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks),
> + priv->clocks);
> + if (ret) {
> + dev_err(dev, "Failed to get clocks\n");
> + return ret;
> + }
> +
> + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks);
This should be undone if an error occurs later in the probe.
Using a devm_action_or_reset() would certainly be nicer and would avoid
the need for a .remove() function.
> + if (ret) {
> + dev_err(dev, "Failed to enable clocks\n");
> + return ret;
> + }
> +
> + /*
> + * The address mappings in the device tree align precisely with those
> + * outlined in the manual. However, register offsets within these
> + * mapped regions are irregular, particularly for remote-icu0.
> + * Consequently, th1520_map_mmio() requires an additional parameter to
> + * handle this quirk.
> + */
> + priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] =
> + th1520_map_mmio(pdev, "local", 0x0);
> + if (IS_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]))
> + return PTR_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]);
> +
> + priv->remote_icu[0] = th1520_map_mmio(pdev, "remote-icu0", 0x4000);
> + if (IS_ERR(priv->remote_icu[0]))
> + return PTR_ERR(priv->remote_icu[0]);
> +
> + priv->remote_icu[1] = th1520_map_mmio(pdev, "remote-icu1", 0x0);
> + if (IS_ERR(priv->remote_icu[1]))
> + return PTR_ERR(priv->remote_icu[1]);
> +
> + priv->remote_icu[2] = th1520_map_mmio(pdev, "remote-icu2", 0x0);
> + if (IS_ERR(priv->remote_icu[2]))
> + return PTR_ERR(priv->remote_icu[2]);
> +
> + priv->local_icu[TH_1520_MBOX_ICU_CPU1] =
> + priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] +
> + TH_1520_MBOX_CHAN_RES_SIZE;
> + priv->local_icu[TH_1520_MBOX_ICU_CPU2] =
> + priv->local_icu[TH_1520_MBOX_ICU_CPU1] +
> + TH_1520_MBOX_CHAN_RES_SIZE;
> + priv->local_icu[TH_1520_MBOX_ICU_CPU3] =
> + priv->local_icu[TH_1520_MBOX_ICU_CPU2] +
> + TH_1520_MBOX_CHAN_RES_SIZE;
> +
> + priv->cur_cpu_ch_base = priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0];
> +
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq < 0)
> + return priv->irq;
> +
> + /* init the chans */
> + for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
> + struct th1520_mbox_con_priv *cp = &priv->con_priv[i];
> +
> + cp->idx = i;
> + cp->chan = &priv->mbox_chans[i];
> + priv->mbox_chans[i].con_priv = cp;
> + snprintf(cp->irq_desc, sizeof(cp->irq_desc),
> + "th1520_mbox_chan[%i]", cp->idx);
> +
> + cp->comm_local_base = priv->local_icu[i];
> + if (i != TH_1520_MBOX_ICU_KERNEL_CPU0) {
> + cp->comm_remote_base = priv->remote_icu[remote_idx];
> + remote_idx++;
> + }
> + }
> +
> + spin_lock_init(&priv->mbox_lock);
> +
> + priv->mbox.dev = dev;
> + priv->mbox.ops = &th1520_mbox_ops;
> + priv->mbox.chans = priv->mbox_chans;
> + priv->mbox.num_chans = TH_1520_MBOX_CHANS;
> + priv->mbox.of_xlate = th1520_mbox_xlate;
> + priv->mbox.txdone_irq = true;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + ret = th1520_mbox_init_generic(priv);
> + if (ret) {
> + dev_err(dev, "Failed to init mailbox context\n");
> + return ret;
> + }
> +
> + return devm_mbox_controller_register(dev, &priv->mbox);
> +}
> +
> +static void th1520_mbox_remove(struct platform_device *pdev)
> +{
> + struct th1520_mbox_priv *priv = platform_get_drvdata(pdev);
> +
> + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
> +}
...
CJ
More information about the linux-riscv
mailing list