From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 131D8C433F5 for ; Mon, 4 Apr 2022 12:51:38 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8FE5781DDF; Mon, 4 Apr 2022 14:51:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="UBDoPZ+9"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 321B180E94; Mon, 4 Apr 2022 14:51:32 +0200 (CEST) Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [IPv6:2a00:1450:4864:20::62f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 513DF801B0 for ; Mon, 4 Apr 2022 14:51:27 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=aford173@gmail.com Received: by mail-ej1-x62f.google.com with SMTP id i27so12568237ejd.9 for ; Mon, 04 Apr 2022 05:51:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=8vPVhwYqZI31+Dwo0SAOC2g3hKnw/5LhlNapz69D6Ew=; b=UBDoPZ+9xcVzO7BmKmC2RYSEEmVMDqAdfeLHtnZ/w3S9lnPKqsa31eFdSGDJkVxRLn ZVNYO2PU6CNg0aXzJDYUErs5dzViDYnQzGL3MBZS0SGkKnAqKSQLHqfPeuffY1/BfDUX 58OwnaHzYOmz1kvgcRYS0VfnMAUJvKoa+rhekifyo89ABhnaOlu/d8WNHXGAbakBw7Px desMtnU8WZ+dfr2AioEIALMivUTSAsx4XwmUX/LJEFdjOigCWCQFmxdt/kJp70ECnIBy bC4lDkwFORUUkseGLZlzDh5CRvsZ8EQHp7d97EmDkM6p5AgvwDMlV5R/jT5NknSSSjRz 9G7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=8vPVhwYqZI31+Dwo0SAOC2g3hKnw/5LhlNapz69D6Ew=; b=vcZreVMovOISU5NQjPnGcqaEA4e943O6zW6GD1YvdVUk/TB7POB6GdSbZs4/QcO2CR SlLvDSJaBEx/dDpzXM1lq1rUvM4YyYl5DgEBzv7xuGmd/74SUYW4TCTn8Syqf5tc4ka6 3qFA48EQLT1AEClGliZnTv0Q9KJBWGnvW+zZTvo8w4O//3mQkWW9wXTDAviK6N/V9I/A LsvoY291Dy0CwjaS/Mi2lr/U4ix/hTYumYfV19NJzEbADumFVb+FMnr59q1DTr5CLksb WUznmYX6CNb3xUrpK5Krn0/ksbSkvUtC8n0nM5WTuE2Vx1HuRX6zTOhqF9HPTxdOnryk LODQ== X-Gm-Message-State: AOAM530v/w5Qex4XWBAApIwNt2HuzbucSUDm13FMzXTvkB10P2N5V++1 K6DeX+/cK4YBGzkrNPPnYq3XPVcEBy79JfbbGlE= X-Google-Smtp-Source: ABdhPJze+Q1TxlRAuUyQGkrCcimUq99yMVxfFYEveT5Ff7fiFz/HOFk0AgHtm2ExmgGd6JaHixqikfKIW+3JNHB4PsY= X-Received: by 2002:a17:906:7714:b0:6ba:8a6a:b464 with SMTP id q20-20020a170906771400b006ba8a6ab464mr10618824ejm.613.1649076686650; Mon, 04 Apr 2022 05:51:26 -0700 (PDT) MIME-Version: 1.0 References: <20220331030349.482922-1-marex@denx.de> <20220331030349.482922-3-marex@denx.de> In-Reply-To: <20220331030349.482922-3-marex@denx.de> From: Adam Ford Date: Mon, 4 Apr 2022 07:51:15 -0500 Message-ID: Subject: Re: [PATCH 3/3] imx: power-domain: Get rid of SMCCC dependency To: Marek Vasut Cc: U-Boot Mailing List , Fabio Estevam , Peng Fan , Stefano Babic Content-Type: text/plain; charset="UTF-8" X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean On Wed, Mar 30, 2022 at 10:04 PM Marek Vasut wrote: > > This driver is the only SMCCC dependency in iMX8M U-Boot port. Rework > the driver based on Linux GPCv2 driver to directly control the GPCv2 > block instead of using SMCCC calls. This way, U-Boot can operate the > i.MX8M power domains without depending on anything else. > > This is losely based on Linux GPCv2 driver. The GPU, VPU, MIPI power > domains are not supported to save space, since they are not useful in > the bootloader. The only domains kept are ones for HSIO, PCIe, USB. I thought there were people who were using video in U-Boot, but maybe I am wrong. I was looking into doing something like this, but I was reluctant, because I wasn't sure if people were using video and/or what might break. I think this a good idea, but If people are using video for some reason, this patch series would break that since ATF would no longer be handling the blk control stuff. I did a quick check of defconfigs and board files and found none, we're probably safe, but I wonder if expanding the CC list to include more imx8mm/imx8mn users would be in order. adam > > Signed-off-by: Marek Vasut > Cc: Fabio Estevam > Cc: Peng Fan > Cc: Stefano Babic > --- > NOTE: So far this is tested on MX8MM and MX8MN. MX8MQ is not tested. > --- > drivers/power/domain/Kconfig | 1 + > drivers/power/domain/imx8m-power-domain.c | 379 ++++++++++++++++++++-- > 2 files changed, 361 insertions(+), 19 deletions(-) > > diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig > index 93d2599d83c..04fc0054323 100644 > --- a/drivers/power/domain/Kconfig > +++ b/drivers/power/domain/Kconfig > @@ -35,6 +35,7 @@ config IMX8_POWER_DOMAIN > config IMX8M_POWER_DOMAIN > bool "Enable i.MX8M power domain driver" > depends on POWER_DOMAIN && ARCH_IMX8M > + select CLK > help > Enable support for manipulating NXP i.MX8M on-SoC power domains via > requests to the ATF. > diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c > index c32dbcc31ae..e2e41cf5fee 100644 > --- a/drivers/power/domain/imx8m-power-domain.c > +++ b/drivers/power/domain/imx8m-power-domain.c > @@ -4,6 +4,7 @@ > */ > > #include > +#include > #include > #include > #include > @@ -12,52 +13,361 @@ > #include > #include > #include > +#include > #include > -#include > +#include > +#include > + > +#include > +#include > +#include > > DECLARE_GLOBAL_DATA_PTR; > > +#define GPC_PGC_CPU_MAPPING 0x0ec > + > +#define IMX8M_PCIE2_A53_DOMAIN BIT(15) > +#define IMX8M_OTG2_A53_DOMAIN BIT(5) > +#define IMX8M_OTG1_A53_DOMAIN BIT(4) > +#define IMX8M_PCIE1_A53_DOMAIN BIT(3) > + > +#define IMX8MM_OTG2_A53_DOMAIN BIT(5) > +#define IMX8MM_OTG1_A53_DOMAIN BIT(4) > +#define IMX8MM_PCIE_A53_DOMAIN BIT(3) > + > +#define IMX8MN_OTG1_A53_DOMAIN BIT(4) > +#define IMX8MN_MIPI_A53_DOMAIN BIT(2) > + > +#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 > +#define GPC_PU_PGC_SW_PDN_REQ 0x104 > + > +#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) > +#define IMX8M_OTG2_SW_Pxx_REQ BIT(3) > +#define IMX8M_OTG1_SW_Pxx_REQ BIT(2) > +#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) > + > +#define IMX8MM_OTG2_SW_Pxx_REQ BIT(3) > +#define IMX8MM_OTG1_SW_Pxx_REQ BIT(2) > +#define IMX8MM_PCIE_SW_Pxx_REQ BIT(1) > + > +#define IMX8MN_OTG1_SW_Pxx_REQ BIT(2) > +#define IMX8MN_MIPI_SW_Pxx_REQ BIT(0) > + > +#define GPC_M4_PU_PDN_FLG 0x1bc > + > +#define GPC_PU_PWRHSK 0x1fc > + > +#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) > +#define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6)) > + > +#define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23) > +#define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5) > + > +/* > + * The PGC offset values in Reference Manual > + * (Rev. 1, 01/2018 and the older ones) GPC chapter's > + * GPC_PGC memory map are incorrect, below offset > + * values are from design RTL. > + */ > +#define IMX8M_PGC_PCIE1 17 > +#define IMX8M_PGC_OTG1 18 > +#define IMX8M_PGC_OTG2 19 > +#define IMX8M_PGC_PCIE2 29 > + > +#define IMX8MM_PGC_PCIE 17 > +#define IMX8MM_PGC_OTG1 18 > +#define IMX8MM_PGC_OTG2 19 > + > +#define IMX8MN_PGC_OTG1 18 > + > +#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) > +#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) > + > +#define GPC_PGC_CTRL_PCR BIT(0) > + > +struct imx_pgc_regs { > + u16 map; > + u16 pup; > + u16 pdn; > + u16 hsk; > +}; > + > +struct imx_pgc_domain { > + unsigned long pgc; > + > + const struct { > + u32 pxx; > + u32 map; > + u32 hskreq; > + u32 hskack; > + } bits; > + > + const bool keep_clocks; > +}; > + > +struct imx_pgc_domain_data { > + const struct imx_pgc_domain *domains; > + size_t domains_num; > + const struct imx_pgc_regs *pgc_regs; > +}; > + > struct imx8m_power_domain_plat { > + struct power_domain pd; > + const struct imx_pgc_domain *domain; > + const struct imx_pgc_regs *regs; > + struct clk_bulk clk; > + void __iomem *base; > int resource_id; > int has_pd; > - struct power_domain pd; > }; > > +#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MQ) > +static const struct imx_pgc_regs imx7_pgc_regs = { > + .map = GPC_PGC_CPU_MAPPING, > + .pup = GPC_PU_PGC_SW_PUP_REQ, > + .pdn = GPC_PU_PGC_SW_PDN_REQ, > + .hsk = GPC_PU_PWRHSK, > +}; > +#endif > + > +#ifdef CONFIG_IMX8MQ > +static const struct imx_pgc_domain imx8m_pgc_domains[] = { > + [IMX8M_POWER_DOMAIN_PCIE1] = { > + .bits = { > + .pxx = IMX8M_PCIE1_SW_Pxx_REQ, > + .map = IMX8M_PCIE1_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8M_PGC_PCIE1), > + }, > + > + [IMX8M_POWER_DOMAIN_USB_OTG1] = { > + .bits = { > + .pxx = IMX8M_OTG1_SW_Pxx_REQ, > + .map = IMX8M_OTG1_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8M_PGC_OTG1), > + }, > + > + [IMX8M_POWER_DOMAIN_USB_OTG2] = { > + .bits = { > + .pxx = IMX8M_OTG2_SW_Pxx_REQ, > + .map = IMX8M_OTG2_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8M_PGC_OTG2), > + }, > + > + [IMX8M_POWER_DOMAIN_PCIE2] = { > + .bits = { > + .pxx = IMX8M_PCIE2_SW_Pxx_REQ, > + .map = IMX8M_PCIE2_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8M_PGC_PCIE2), > + }, > +}; > + > +static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { > + .domains = imx8m_pgc_domains, > + .domains_num = ARRAY_SIZE(imx8m_pgc_domains), > + .pgc_regs = &imx7_pgc_regs, > +}; > +#endif > + > +#ifdef CONFIG_IMX8MM > +static const struct imx_pgc_domain imx8mm_pgc_domains[] = { > + [IMX8MM_POWER_DOMAIN_HSIOMIX] = { > + .bits = { > + .pxx = 0, /* no power sequence control */ > + .map = 0, /* no power sequence control */ > + .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN, > + .hskack = IMX8MM_HSIO_HSK_PWRDNACKN, > + }, > + .keep_clocks = true, > + }, > + > + [IMX8MM_POWER_DOMAIN_PCIE] = { > + .bits = { > + .pxx = IMX8MM_PCIE_SW_Pxx_REQ, > + .map = IMX8MM_PCIE_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8MM_PGC_PCIE), > + }, > + > + [IMX8MM_POWER_DOMAIN_OTG1] = { > + .bits = { > + .pxx = IMX8MM_OTG1_SW_Pxx_REQ, > + .map = IMX8MM_OTG1_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8MM_PGC_OTG1), > + }, > + > + [IMX8MM_POWER_DOMAIN_OTG2] = { > + .bits = { > + .pxx = IMX8MM_OTG2_SW_Pxx_REQ, > + .map = IMX8MM_OTG2_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8MM_PGC_OTG2), > + }, > +}; > + > +static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = { > + .domains = imx8mm_pgc_domains, > + .domains_num = ARRAY_SIZE(imx8mm_pgc_domains), > + .pgc_regs = &imx7_pgc_regs, > +}; > +#endif > + > +#ifdef CONFIG_IMX8MN > +static const struct imx_pgc_domain imx8mn_pgc_domains[] = { > + [IMX8MN_POWER_DOMAIN_HSIOMIX] = { > + .bits = { > + .pxx = 0, /* no power sequence control */ > + .map = 0, /* no power sequence control */ > + .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN, > + .hskack = IMX8MN_HSIO_HSK_PWRDNACKN, > + }, > + .keep_clocks = true, > + }, > + > + [IMX8MN_POWER_DOMAIN_OTG1] = { > + .bits = { > + .pxx = IMX8MN_OTG1_SW_Pxx_REQ, > + .map = IMX8MN_OTG1_A53_DOMAIN, > + }, > + .pgc = BIT(IMX8MN_PGC_OTG1), > + }, > +}; > + > +static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = { > + .domains = imx8mn_pgc_domains, > + .domains_num = ARRAY_SIZE(imx8mn_pgc_domains), > + .pgc_regs = &imx7_pgc_regs, > +}; > +#endif > + > static int imx8m_power_domain_on(struct power_domain *power_domain) > { > struct udevice *dev = power_domain->dev; > - struct imx8m_power_domain_plat *pdata; > + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); > + const struct imx_pgc_domain *domain = pdata->domain; > + const struct imx_pgc_regs *regs = pdata->regs; > + void __iomem *base = pdata->base; > + u32 pgc; > + int ret; > + > + if (pdata->clk.count) { > + ret = clk_enable_bulk(&pdata->clk); > + if (ret) { > + dev_err(dev, "failed to enable reset clocks\n"); > + return ret; > + } > + } > > - pdata = dev_get_plat(dev); > + if (domain->bits.pxx) { > + /* request the domain to power up */ > + setbits_le32(base + regs->pup, domain->bits.pxx); > > - if (pdata->resource_id < 0) > - return -EINVAL; > + /* > + * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait > + * for PUP_REQ/PDN_REQ bit to be cleared > + */ > + ret = wait_for_bit_le32(base + regs->pup, domain->bits.pxx, > + false, 1000, false); > + if (ret) { > + dev_err(dev, "failed to command PGC\n"); > + goto out_clk_disable; > + } > > - if (pdata->has_pd) > - power_domain_on(&pdata->pd); > + /* disable power control */ > + for_each_set_bit(pgc, &domain->pgc, 32) { > + clrbits_le32(base + GPC_PGC_CTRL(pgc), > + GPC_PGC_CTRL_PCR); > + } > + } > + > + /* delay for reset to propagate */ > + udelay(5); > > - arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, > - pdata->resource_id, 1, 0, 0, 0, 0, NULL); > + /* request the ADB400 to power up */ > + if (domain->bits.hskreq) > + setbits_le32(base + regs->hsk, domain->bits.hskreq); > + > + /* Disable reset clocks for all devices in the domain */ > + if (!domain->keep_clocks && pdata->clk.count) > + clk_disable_bulk(&pdata->clk); > > return 0; > + > +out_clk_disable: > + if (pdata->clk.count) > + clk_disable_bulk(&pdata->clk); > + return ret; > } > > static int imx8m_power_domain_off(struct power_domain *power_domain) > { > struct udevice *dev = power_domain->dev; > - struct imx8m_power_domain_plat *pdata; > - pdata = dev_get_plat(dev); > + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); > + const struct imx_pgc_domain *domain = pdata->domain; > + const struct imx_pgc_regs *regs = pdata->regs; > + void __iomem *base = pdata->base; > + u32 pgc; > + int ret; > > - if (pdata->resource_id < 0) > - return -EINVAL; > + /* Enable reset clocks for all devices in the domain */ > + if (!domain->keep_clocks && pdata->clk.count) { > + ret = clk_enable_bulk(&pdata->clk); > + if (ret) > + return ret; > + } > > - arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, > - pdata->resource_id, 0, 0, 0, 0, 0, NULL); > + /* request the ADB400 to power down */ > + if (domain->bits.hskreq) { > + clrbits_le32(base + regs->hsk, domain->bits.hskreq); > + > + ret = wait_for_bit_le32(base + regs->hsk, domain->bits.hskack, > + false, 1000, false); > + if (ret) { > + dev_err(dev, "failed to power down ADB400\n"); > + goto out_clk_disable; > + } > + } > + > + if (domain->bits.pxx) { > + /* enable power control */ > + for_each_set_bit(pgc, &domain->pgc, 32) { > + setbits_le32(base + GPC_PGC_CTRL(pgc), > + GPC_PGC_CTRL_PCR); > + } > + > + /* request the domain to power down */ > + setbits_le32(base + regs->pdn, domain->bits.pxx); > + > + /* > + * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait > + * for PUP_REQ/PDN_REQ bit to be cleared > + */ > + ret = wait_for_bit_le32(base + regs->pdn, domain->bits.pxx, > + false, 1000, false); > + if (ret) { > + dev_err(dev, "failed to command PGC\n"); > + goto out_clk_disable; > + } > + } > + > + /* Disable reset clocks for all devices in the domain */ > + if (pdata->clk.count) > + clk_disable_bulk(&pdata->clk); > > if (pdata->has_pd) > power_domain_off(&pdata->pd); > > return 0; > + > +out_clk_disable: > + if (!domain->keep_clocks && pdata->clk.count) > + clk_disable_bulk(&pdata->clk); > + > + return ret; > } > > static int imx8m_power_domain_of_xlate(struct power_domain *power_domain, > @@ -101,12 +411,36 @@ static int imx8m_power_domain_bind(struct udevice *dev) > return 0; > } > > +static int imx8m_power_domain_probe(struct udevice *dev) > +{ > + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); > + int ret; > + > + /* Nothing to do for non-"power-domain" driver instances. */ > + if (!strstr(dev->name, "power-domain")) > + return 0; > + > + /* Grab optional power domain clock. */ > + ret = clk_get_bulk(dev, &pdata->clk); > + if (ret && ret != -ENOENT) { > + dev_err(dev, "Failed to get domain clock (%d)\n", ret); > + return ret; > + } > + > + return 0; > +} > + > static int imx8m_power_domain_of_to_plat(struct udevice *dev) > { > struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); > + struct imx_pgc_domain_data *domain_data = > + (struct imx_pgc_domain_data *)dev_get_driver_data(dev); > > pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), > "reg", -1); > + pdata->domain = &domain_data->domains[pdata->resource_id]; > + pdata->regs = domain_data->pgc_regs; > + pdata->base = dev_read_addr_ptr(dev->parent); > > if (!power_domain_get(dev, &pdata->pd)) > pdata->has_pd = 1; > @@ -115,9 +449,15 @@ static int imx8m_power_domain_of_to_plat(struct udevice *dev) > } > > static const struct udevice_id imx8m_power_domain_ids[] = { > - { .compatible = "fsl,imx8mq-gpc" }, > - { .compatible = "fsl,imx8mm-gpc" }, > - { .compatible = "fsl,imx8mn-gpc" }, > +#ifdef CONFIG_IMX8MQ > + { .compatible = "fsl,imx8mq-gpc", .data = (long)&imx8m_pgc_domain_data }, > +#endif > +#ifdef CONFIG_IMX8MM > + { .compatible = "fsl,imx8mm-gpc", .data = (long)&imx8mm_pgc_domain_data }, > +#endif > +#ifdef CONFIG_IMX8MN > + { .compatible = "fsl,imx8mn-gpc", .data = (long)&imx8mn_pgc_domain_data }, > +#endif > { } > }; > > @@ -132,6 +472,7 @@ U_BOOT_DRIVER(imx8m_power_domain) = { > .id = UCLASS_POWER_DOMAIN, > .of_match = imx8m_power_domain_ids, > .bind = imx8m_power_domain_bind, > + .probe = imx8m_power_domain_probe, > .of_to_plat = imx8m_power_domain_of_to_plat, > .plat_auto = sizeof(struct imx8m_power_domain_plat), > .ops = &imx8m_power_domain_ops, > -- > 2.35.1 >