[PATCH] mmc: sunxi: support DM MMC in SPL

James Hilliard james.hilliard1 at gmail.com
Sun Jun 28 23:27:48 CEST 2026


On Sun, Jun 28, 2026 at 10:16 AM Andre Przywara <andre.przywara at arm.com> wrote:
>
> On Fri, 26 Jun 2026 14:51:50 -0600
> James Hilliard <james.hilliard1 at gmail.com> wrote:
>
> Hi James,
>
> > sunxi SPL normally uses the legacy MMC interface while U-Boot
> > proper uses the DM driver. Boards which enable SPL_DM_MMC need
>
> I think I mentioned this before: enabling the device model in the SPL
> (or not) is not a *device* decision, but a platform one.

I'm a bit confused here, uboot's configuration system from what I can tell
is designed to allow enabling device model for specific devices and even
for specific drivers.

Why would this need to be a platform level decision? Given that boards
that don't have enough SRAM for SPL DM support tend to be older, we
will presumably want to migrate newer boards to SPL DM at some point
in the future anyways.

> And for
> technical reasons, mostly to support older devices, which have no other
> choice, but also to keep it simple and the SPL small, we do not use DM
> in the SPL on Allwinner boards.

I mean, this seems to me to be justification for continuing to support
legacy drivers, not justification for not supporting DM as well since there
are also many sunxi boards that don't have that limitation.

> I see the SPL as the continuation of the
> BootROM, which is completely board agnostic.

At a minimum SPL is still fairly SoC specific. Although in practice it seems
to not be all that board agnostic, I think if anything DM support makes it
more agnostic by allowing better factoring of the device specific stuff.

> The SPL can mimic this
> behaviour, to follow the decisions that the BootROM made, for instance
> about the boot device. The only difference here is the DRAM
> initialisation, which requires some board specific data, but so far we
> got away with just hardcoding it.

This is one of a few reasons I wanted to get SPL DM functional on sunxi.

> If that is not good anymore, I think
> we can find other solutions than pulling in the whole world of SPL_DM
> support.
>
> So what is the purpose of this exercise, why do you want DM_SPL
> supported?

Some cryptoengine uboot drivers I was working on adding seemed to
need DM_SPL, also I think handling DRAM profiles becomes easier with
it somewhat.

> Keep in mind that there are 178 Allwinner boards supported in
> U-Boot, so there better would be good reasons to change something
> fundamental like this for all of them. It changing it for a number of
> them is not better, because this doubles the test matrix, so we have to
> test now that it works on both legacy and DM_SPL boards - which frankly
> nobody will do.

Well it doesn't actually double the test matrix since presumably boards
that are not SPL DM compatible will continue to use non-DM drivers only.

Wouldn't we typically just pick either DM or non-DM configs for upstream
uboot testing/configs for any particular board to avoid maintaining more
configurations than necessary in the test matrix?

> And aside from that, please do NOT add any more #ifdef's to the U-Boot
> code.

This seemed to be how other subsystems handled both DM and non-DM
driver support, is there a better way?

> Also just posting single patches that do not do anything on their
> own is not a good idea.

I'm not sure what you mean here, the change here is fixing SPL DM
support in the driver, it's already possible to select SPL DM MMC
support in kconfig for the sunxi MMC driver.

> Cheers,
> Andre
>
> > the DM driver to perform the same early pinmux, resource and clock
> > setup as the legacy path.
> >
> > For SPL without OF_CONTROL, create controllers from static platform
> > data matching the controllers selected by the legacy SPL board code.
> > Reuse the legacy host capability, resource and clock setup helpers for
> > that no-devicetree probe path.
> >
> > For SPL with OF_CONTROL but without SPL_CLK or SPL_PINCTRL, keep
> > using the devicetree for the controller address and clock register
> > layout, then fall back to the legacy CCU base, clock init and pinmux
> > setup. This allows SPL to use DM_MMC without pulling the full clock
> > and pinctrl drivers into SRAM-constrained builds.
> >
> > Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
> > ---
> >  arch/arm/include/asm/arch-sunxi/mmc.h |   1 +
> >  board/sunxi/board.c                   |   6 +-
> >  drivers/mmc/sunxi_mmc.c               | 252 +++++++++++++++++---------
> >  3 files changed, 175 insertions(+), 84 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
> > index b8d91b5c64b..e6c19bf08fb 100644
> > --- a/arch/arm/include/asm/arch-sunxi/mmc.h
> > +++ b/arch/arm/include/asm/arch-sunxi/mmc.h
> > @@ -3,6 +3,7 @@
> >  #ifndef _ASM_ARCH_MMC_H_
> >  #define _ASM_ARCH_MMC_H_
> >
> > +void sunxi_mmc_pinmux_setup(int sdc_no);
> >  struct mmc *sunxi_mmc_init(int sdc_no);
> >
> >  #endif /* _ASM_ARCH_MMC_H_ */
> > diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> > index 3d1afec7c66..4311f38737c 100644
> > --- a/board/sunxi/board.c
> > +++ b/board/sunxi/board.c
> > @@ -334,7 +334,7 @@ void board_nand_init(void)
> >  #endif /* CONFIG_NAND_SUNXI */
> >
> >  #ifdef CONFIG_MMC
> > -static void mmc_pinmux_setup(int sdc)
> > +void sunxi_mmc_pinmux_setup(int sdc)
> >  {
> >       unsigned int pin;
> >
> > @@ -515,13 +515,13 @@ int board_mmc_init(struct bd_info *bis)
> >        * any problem with unconditionally enabling this in the SPL.
> >        */
> >       if (!IS_ENABLED(CONFIG_UART0_PORT_F)) {
> > -             mmc_pinmux_setup(0);
> > +             sunxi_mmc_pinmux_setup(0);
> >               if (!sunxi_mmc_init(0))
> >                       return -1;
> >       }
> >
> >       if (CONFIG_MMC_SUNXI_SLOT_EXTRA != -1) {
> > -             mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
> > +             sunxi_mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
> >               if (!sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA))
> >                       return -1;
> >       }
> > diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
> > index e28c81afffe..7816dac3423 100644
> > --- a/drivers/mmc/sunxi_mmc.c
> > +++ b/drivers/mmc/sunxi_mmc.c
> > @@ -6,11 +6,11 @@
> >   *
> >   * MMC driver for allwinner sunxi platform.
> >   *
> > - * This driver is used by the (ARM) SPL with the legacy MMC interface, and
> > - * by U-Boot proper using the full DM interface. The actual hardware access
> > - * code is common, and comes first in this file.
> > - * The legacy MMC interface implementation comes next, followed by the
> > - * proper DM_MMC implementation at the end.
> > + * This driver is used by the (ARM) SPL with the legacy MMC interface or the
> > + * full DM interface, and by U-Boot proper using the full DM interface. The
> > + * actual hardware access code is common, and comes first in this file.
> > + * The legacy MMC interface implementation comes next, followed by the DM_MMC
> > + * implementation at the end.
> >   */
> >
> >  #include <dm.h>
> > @@ -24,9 +24,7 @@
> >  #include <asm/io.h>
> >  #include <asm/arch/clock.h>
> >  #include <asm/arch/cpu.h>
> > -#if !CONFIG_IS_ENABLED(DM_MMC)
> >  #include <asm/arch/mmc.h>
> > -#endif
> >  #include <linux/delay.h>
> >  #include <sunxi_gpio.h>
> >
> > @@ -36,7 +34,12 @@
> >  #define CCM_MMC_CTRL_MODE_SEL_NEW    0
> >  #endif
> >
> > +#define SUNXI_MMC_NAME                       "SUNXI SD/MMC"
> > +
> >  struct sunxi_mmc_plat {
> > +#if !CONFIG_IS_ENABLED(OF_REAL)
> > +     unsigned int mmc_no;
> > +#endif
> >       struct mmc_config cfg;
> >       struct mmc mmc;
> >  };
> > @@ -64,6 +67,83 @@ static bool sunxi_mmc_can_calibrate(void)
> >              IS_ENABLED(CONFIG_MACH_SUN8I_R40);
> >  }
> >
> > +#if !CONFIG_IS_ENABLED(DM_MMC) || !CONFIG_IS_ENABLED(OF_REAL)
> > +static uint sunxi_mmc_get_host_caps(unsigned int mmc_no)
> > +{
> > +     uint host_caps = MMC_MODE_4BIT;
> > +
> > +     if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
> > +          IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
> > +          IS_ENABLED(CONFIG_MACH_SUN55I_A523)) && mmc_no == 2)
> > +             host_caps = MMC_MODE_8BIT;
> > +
> > +     return host_caps | MMC_MODE_HS_52MHz | MMC_MODE_HS;
> > +}
> > +
> > +static int mmc_resource_init(struct sunxi_mmc_priv *priv, int sdc_no)
> > +{
> > +     void *ccm = (void *)SUNXI_CCM_BASE;
> > +
> > +     debug("init mmc %d resource\n", sdc_no);
> > +
> > +     switch (sdc_no) {
> > +     case 0:
> > +             priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
> > +             priv->mclkreg = ccm + CCU_MMC0_CLK_CFG;
> > +             break;
> > +     case 1:
> > +             priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
> > +             priv->mclkreg = ccm + CCU_MMC1_CLK_CFG;
> > +             break;
> > +#ifdef SUNXI_MMC2_BASE
> > +     case 2:
> > +             priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
> > +             priv->mclkreg = ccm + CCU_MMC2_CLK_CFG;
> > +             break;
> > +#endif
> > +#ifdef SUNXI_MMC3_BASE
> > +     case 3:
> > +             priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
> > +             priv->mclkreg = ccm + CCU_MMC3_CLK_CFG;
> > +             break;
> > +#endif
> > +     default:
> > +             printf("Wrong mmc number %d\n", sdc_no);
> > +             return -1;
> > +     }
> > +     priv->mmc_no = sdc_no;
> > +
> > +     return 0;
> > +}
> > +#endif
> > +
> > +#if !CONFIG_IS_ENABLED(DM_MMC) || !CONFIG_IS_ENABLED(OF_REAL) || \
> > +     !CONFIG_IS_ENABLED(CLK)
> > +static void sunxi_mmc_clock_init(int sdc_no)
> > +{
> > +     void *ccm = (void *)SUNXI_CCM_BASE;
> > +
> > +     debug("init mmc %d clock and io\n", sdc_no);
> > +#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
> > +     setbits_le32(ccm + CCU_AHB_GATE0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
> > +
> > +#ifdef CONFIG_SUNXI_GEN_SUN6I
> > +     /* unassert reset */
> > +     setbits_le32(ccm + CCU_AHB_RESET0_CFG, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
> > +#endif
> > +#if defined(CONFIG_MACH_SUN9I)
> > +     /* sun9i has a mmc-common module, also set the gate and reset there */
> > +     writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
> > +            SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
> > +#endif
> > +#else /* CONFIG_SUN50I_GEN_H6 */
> > +     setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << sdc_no);
> > +     /* unassert reset */
> > +     setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << (RESET_SHIFT + sdc_no));
> > +#endif
> > +}
> > +#endif
> > +
> >  static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
> >  {
> >       unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly;
> > @@ -492,43 +572,6 @@ static void sunxi_mmc_reset(void *regs)
> >  /* support 4 mmc hosts */
> >  struct sunxi_mmc_priv mmc_host[4];
> >
> > -static int mmc_resource_init(int sdc_no)
> > -{
> > -     struct sunxi_mmc_priv *priv = &mmc_host[sdc_no];
> > -     void *ccm = (void *)SUNXI_CCM_BASE;
> > -
> > -     debug("init mmc %d resource\n", sdc_no);
> > -
> > -     switch (sdc_no) {
> > -     case 0:
> > -             priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
> > -             priv->mclkreg = ccm + CCU_MMC0_CLK_CFG;
> > -             break;
> > -     case 1:
> > -             priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
> > -             priv->mclkreg = ccm + CCU_MMC1_CLK_CFG;
> > -             break;
> > -#ifdef SUNXI_MMC2_BASE
> > -     case 2:
> > -             priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
> > -             priv->mclkreg = ccm + CCU_MMC2_CLK_CFG;
> > -             break;
> > -#endif
> > -#ifdef SUNXI_MMC3_BASE
> > -     case 3:
> > -             priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
> > -             priv->mclkreg = ccm + CCU_MMC3_CLK_CFG;
> > -             break;
> > -#endif
> > -     default:
> > -             printf("Wrong mmc number %d\n", sdc_no);
> > -             return -1;
> > -     }
> > -     priv->mmc_no = sdc_no;
> > -
> > -     return 0;
> > -}
> > -
> >  static int sunxi_mmc_core_init(struct mmc *mmc)
> >  {
> >       struct sunxi_mmc_priv *priv = mmc->priv;
> > @@ -562,52 +605,27 @@ static const struct mmc_ops sunxi_mmc_ops = {
> >
> >  struct mmc *sunxi_mmc_init(int sdc_no)
> >  {
> > -     void *ccm = (void *)SUNXI_CCM_BASE;
> >       struct sunxi_mmc_priv *priv = &mmc_host[sdc_no];
> >       struct mmc_config *cfg = &priv->cfg;
> >       int ret;
> >
> >       memset(priv, '\0', sizeof(struct sunxi_mmc_priv));
> >
> > -     cfg->name = "SUNXI SD/MMC";
> > +     cfg->name = SUNXI_MMC_NAME;
> >       cfg->ops  = &sunxi_mmc_ops;
> >
> >       cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
> > -     cfg->host_caps = MMC_MODE_4BIT;
> > -
> > -     if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
> > -         IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_MACH_SUN55I_A523)) &&
> > -         (sdc_no == 2))
> > -             cfg->host_caps = MMC_MODE_8BIT;
> > -
> > -     cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
> > +     cfg->host_caps = sunxi_mmc_get_host_caps(sdc_no);
> >       cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
> >
> >       cfg->f_min = 400000;
> >       cfg->f_max = 52000000;
> >
> > -     if (mmc_resource_init(sdc_no) != 0)
> > +     if (mmc_resource_init(priv, sdc_no) != 0)
> >               return NULL;
> >
> >       /* config ahb clock */
> > -     debug("init mmc %d clock and io\n", sdc_no);
> > -#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
> > -     setbits_le32(ccm + CCU_AHB_GATE0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
> > -
> > -#ifdef CONFIG_SUNXI_GEN_SUN6I
> > -     /* unassert reset */
> > -     setbits_le32(ccm + CCU_AHB_RESET0_CFG, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
> > -#endif
> > -#if defined(CONFIG_MACH_SUN9I)
> > -     /* sun9i has a mmc-common module, also set the gate and reset there */
> > -     writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
> > -            SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
> > -#endif
> > -#else /* CONFIG_SUN50I_GEN_H6 */
> > -     setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << sdc_no);
> > -     /* unassert reset */
> > -     setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << (RESET_SHIFT + sdc_no));
> > -#endif
> > +     sunxi_mmc_clock_init(sdc_no);
> >       ret = mmc_set_mod_clk(priv, 24000000);
> >       if (ret)
> >               return NULL;
> > @@ -644,7 +662,7 @@ static int sunxi_mmc_getcd(struct udevice *dev)
> >           (mmc->cfg->host_caps & MMC_CAP_NEEDS_POLL))
> >               return 1;
> >
> > -     if (dm_gpio_is_valid(&priv->cd_gpio)) {
> > +     if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&priv->cd_gpio)) {
> >               int cd_state = dm_gpio_get_value(&priv->cd_gpio);
> >
> >               if (mmc->cfg->host_caps & MMC_CAP_CD_ACTIVE_HIGH)
> > @@ -652,6 +670,7 @@ static int sunxi_mmc_getcd(struct udevice *dev)
> >               else
> >                       return cd_state;
> >       }
> > +
> >       return 1;
> >  }
> >
> > @@ -661,6 +680,7 @@ static const struct dm_mmc_ops sunxi_mmc_ops = {
> >       .get_cd         = sunxi_mmc_getcd,
> >  };
> >
> > +#if CONFIG_IS_ENABLED(OF_REAL)
> >  static unsigned get_mclk_offset(void)
> >  {
> >       if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
> > @@ -671,20 +691,26 @@ static unsigned get_mclk_offset(void)
> >
> >       return 0x88;
> >  };
> > +#endif
> >
> >  static int sunxi_mmc_probe(struct udevice *dev)
> >  {
> >       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> >       struct sunxi_mmc_plat *plat = dev_get_plat(dev);
> >       struct sunxi_mmc_priv *priv = dev_get_priv(dev);
> > +#if CONFIG_IS_ENABLED(OF_REAL)
> >       struct reset_ctl_bulk reset_bulk;
> > +#if CONFIG_IS_ENABLED(CLK)
> >       struct clk gate_clk;
> > -     struct mmc_config *cfg = &plat->cfg;
> > +#endif
> >       struct ofnode_phandle_args args;
> >       u32 *ccu_reg;
> > +#endif
> > +     struct mmc_config *cfg = &plat->cfg;
> >       int ret;
> >
> > -     cfg->name = dev->name;
> > +     if (!cfg->name)
> > +             cfg->name = dev->name;
> >
> >       cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
> >       cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
> > @@ -693,37 +719,58 @@ static int sunxi_mmc_probe(struct udevice *dev)
> >       cfg->f_min = 400000;
> >       cfg->f_max = 52000000;
> >
> > +#if CONFIG_IS_ENABLED(OF_REAL)
> >       ret = mmc_of_parse(dev, cfg);
> >       if (ret)
> >               return ret;
> >
> >       priv->reg = dev_read_addr_ptr(dev);
> > +     priv->mmc_no = ((uintptr_t)priv->reg - SUNXI_MMC0_BASE) / 0x1000;
> > +
> > +#if !CONFIG_IS_ENABLED(PINCTRL)
> > +     sunxi_mmc_pinmux_setup(priv->mmc_no);
> > +#endif
> >
> >       /* We don't have a sunxi clock driver so find the clock address here */
> >       ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
> >                                         1, &args);
> > -     if (ret)
> > +     if (!ret)
> > +             ccu_reg = (u32 *)(uintptr_t)ofnode_get_addr(args.node);
> > +     else if (!CONFIG_IS_ENABLED(CLK))
> > +             ccu_reg = (u32 *)SUNXI_CCM_BASE;
> > +     else
> >               return ret;
> > -     ccu_reg = (u32 *)(uintptr_t)ofnode_get_addr(args.node);
> >
> > -     priv->mmc_no = ((uintptr_t)priv->reg - SUNXI_MMC0_BASE) / 0x1000;
> >       priv->mclkreg = (void *)ccu_reg + get_mclk_offset() + priv->mmc_no * 4;
> >
> > +#if CONFIG_IS_ENABLED(CLK)
> >       ret = clk_get_by_name(dev, "ahb", &gate_clk);
> >       if (!ret)
> >               clk_enable(&gate_clk);
> > +#else
> > +     sunxi_mmc_clock_init(priv->mmc_no);
> > +#endif
> >
> >       ret = reset_get_bulk(dev, &reset_bulk);
> >       if (!ret)
> >               reset_deassert_bulk(&reset_bulk);
> > +#else
> > +     cfg->host_caps = sunxi_mmc_get_host_caps(plat->mmc_no);
> > +     sunxi_mmc_pinmux_setup(plat->mmc_no);
> > +     ret = mmc_resource_init(priv, plat->mmc_no);
> > +     if (ret)
> > +             return ret;
> > +     sunxi_mmc_clock_init(plat->mmc_no);
> > +#endif
> >
> >       ret = mmc_set_mod_clk(priv, 24000000);
> >       if (ret)
> >               return ret;
> >
> >       /* This GPIO is optional */
> > -     gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
> > -                          GPIOD_IS_IN | GPIOD_PULL_UP);
> > +     if (CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_REAL))
> > +             gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
> > +                                  GPIOD_IS_IN | GPIOD_PULL_UP);
> >
> >       upriv->mmc = &plat->mmc;
> >
> > @@ -739,6 +786,7 @@ static int sunxi_mmc_bind(struct udevice *dev)
> >       return mmc_bind(dev, &plat->mmc, &plat->cfg);
> >  }
> >
> > +#if CONFIG_IS_ENABLED(OF_REAL)
> >  static const struct udevice_id sunxi_mmc_ids[] = {
> >       { .compatible = "allwinner,sun4i-a10-mmc" },
> >       { .compatible = "allwinner,sun5i-a13-mmc" },
> > @@ -754,15 +802,57 @@ static const struct udevice_id sunxi_mmc_ids[] = {
> >       { .compatible = "allwinner,sun50i-a100-emmc" },
> >       { /* sentinel */ }
> >  };
> > +#endif
> >
> >  U_BOOT_DRIVER(sunxi_mmc_drv) = {
> >       .name           = "sunxi_mmc",
> >       .id             = UCLASS_MMC,
> > +#if CONFIG_IS_ENABLED(OF_REAL)
> >       .of_match       = sunxi_mmc_ids,
> > +#endif
> >       .bind           = sunxi_mmc_bind,
> >       .probe          = sunxi_mmc_probe,
> >       .ops            = &sunxi_mmc_ops,
> >       .plat_auto      = sizeof(struct sunxi_mmc_plat),
> >       .priv_auto      = sizeof(struct sunxi_mmc_priv),
> > +#if !CONFIG_IS_ENABLED(OF_CONTROL)
> > +     .flags          = DM_FLAG_PRE_RELOC,
> > +#endif
> >  };
> > +
> > +#if defined(CONFIG_XPL_BUILD) && CONFIG_IS_ENABLED(DM_MMC) && \
> > +     !CONFIG_IS_ENABLED(OF_CONTROL)
> > +/*
> > + * SPL runs DM binding before DRAM init, and sunxi SPL .bss is in DRAM.
> > + * Keep this static platform data non-zero so it stays in SRAM-backed .data.
> > + */
> > +#define SUNXI_MMC_PLAT(_mmc_no)      { \
> > +             .mmc_no = _mmc_no, \
> > +             .cfg.name = SUNXI_MMC_NAME, \
> > +     }
> > +
> > +#define SUNXI_MMC_DRVINFO(_mmc_no) \
> > +     static struct sunxi_mmc_plat sunxi_mmc##_mmc_no##_plat = \
> > +             SUNXI_MMC_PLAT(_mmc_no); \
> > +     U_BOOT_DRVINFO(sunxi_mmc##_mmc_no) = { \
> > +             .name = "sunxi_mmc", \
> > +             .plat = &sunxi_mmc##_mmc_no##_plat, \
> > +     }
> > +
> > +#if !IS_ENABLED(CONFIG_UART0_PORT_F)
> > +SUNXI_MMC_DRVINFO(0);
> > +#endif
> > +
> > +#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 1
> > +SUNXI_MMC_DRVINFO(1);
> > +#endif
> > +
> > +#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 2 && defined(SUNXI_MMC2_BASE)
> > +SUNXI_MMC_DRVINFO(2);
> > +#endif
> > +
> > +#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 3 && defined(SUNXI_MMC3_BASE)
> > +SUNXI_MMC_DRVINFO(3);
> > +#endif
> > +#endif
> >  #endif
>


More information about the U-Boot mailing list