[PATCH] board: purism: Add support for the Librem5 devkit

Guido Günther agx at sigxcpu.org
Fri Jun 12 16:29:23 CEST 2026


Hi Fabio,

On Tue, Jun 09, 2026 at 09:53:08AM -0300, Fabio Estevam wrote:
> Hi Guido,
> 
> On Mon, May 25, 2026 at 12:57 PM Guido Günther <agx at sigxcpu.org> wrote:
> 
> > +#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
> > +
> > +#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
> > +
> > +#define UART1_TX IMX_GPIO_NR(5, 23)
> > +#define UART1_RX IMX_GPIO_NR(5, 22)
> > +
> > +static const iomux_v3_cfg_t wdog_pads[] = {
> > +       IMX8MQ_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
> > +};
> > +
> > +static const iomux_v3_cfg_t uart_pads[] = {
> > +       IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +       IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +};
> > +
> > +int board_early_init_f(void)
> > +{
> > +       struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
> > +
> > +       imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
> > +       set_wdog_reset(wdog);
> > +
> > +       imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
> > +
> > +       return 0;
> > +}
> > +
> > +#if IS_ENABLED(CONFIG_FEC_MXC)
> > +#define FEC_RST_PAD IMX_GPIO_NR(1, 9)
> > +static const iomux_v3_cfg_t fec1_rst_pads[] = {
> > +       IMX8MQ_PAD_GPIO1_IO09__GPIO1_IO9 | MUX_PAD_CTRL(NO_PAD_CTRL),
> > +       IMX8MQ_PAD_GPIO1_IO15__CCM_CLKO2 | MUX_PAD_CTRL(0x1F),
> > +};
> > +
> > +static void setup_iomux_fec(void)
> > +{
> > +       imx_iomux_v3_setup_multiple_pads(fec1_rst_pads,
> > +                                        ARRAY_SIZE(fec1_rst_pads));
> > +
> > +       gpio_request(FEC_RST_PAD, "fec1_rst");
> > +       gpio_direction_output(FEC_RST_PAD, 0);
> > +       udelay(500);
> > +       gpio_direction_output(FEC_RST_PAD, 1);
> > +}
> > +
> > +static int setup_fec(void)
> > +{
> > +       setup_iomux_fec();
> > +
> > +       /* Use 125M anatop REF_CLK1 for ENET1, not from external */
> > +       clrsetbits_le32(IOMUXC_GPR_BASE_ADDR + 0x04, BIT(13) | BIT(17), 0);
> > +       return set_clk_enet(ENET_125MHZ);
> > +}
> > +
> > +int board_phy_config(struct phy_device *phydev)
> > +{
> > +       /* enable rgmii rxc skew and phy mode select to RGMII copper */
> > +       phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
> > +       phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
> > +
> > +       phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
> > +       phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
> > +
> > +       if (phydev->drv->config)
> > +               phydev->drv->config(phydev);
> > +       return 0;
> > +}
> > +#endif
> 
> The UART, watchdog, and Ethernet PHY C code above could be removed,
> since we're using DM, right?

Dropped most of it. I needed to keep the board_phy_config to keep
ethernet working. I'm still fuzzy what exactly is needed with DT
and what not so happy to fix up things where needed.

> 
> > +int board_init(void)
> > +{
> > +       if (IS_ENABLED(CONFIG_USB_DWC3) || IS_ENABLED(CONFIG_USB_XHCI_DWC3))
> > +               init_usb_clk();
> > +
> > +       if (IS_ENABLED(CONFIG_FEC_MXC))
> > +               setup_fec();
> > +
> > +       return 0;
> 
> Can board_init() be removed?

It's an empty function now.

> 
> > --- /dev/null
> > +++ b/board/purism/librem5-devkit/librem5-devkit.env
> > @@ -0,0 +1,20 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> > +
> > +boot_fdt=try
> 
> boot_fdt was used long ago, when we supported both DT and non-DT cases.
> 
> boot_fdt is no longer needed, as we always boot DT, so it can be
> removed.

Dropped.

> 
> > +boot_targets=mmc0 dhcp
> > +bootm_size=0x10000000
> > +console=ttymxc0,115200
> > +fdt_addr_r=0x43000000
> > +fdtfile=DEFAULT_FDT_FILE
> > +initrd_addr=0x43800000
> > +image=Image
> > +kernel_addr_r=CONFIG_SYS_LOAD_ADDR
> > +loadaddr=CONFIG_SYS_LOAD_ADDR
> > +mmcautodetect=yes
> > +mmcdev=CONFIG_ENV_MMC_DEVICE_INDEX
> > +mmcpart=1
> > +mmcroot=/dev/mmcblk0p1
> > +scriptaddr=CONFIG_SYS_LOAD_ADDR
> > +mmcargs=setenv bootargs console=${console} root=${mmcroot} rootwait rw
> > +loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
> > +loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile}
> 
> Use the generic load command instead of fatload.

Changed and also switched to standard bootflow as mostly we want to use
efibootmgr anyway.

> 
> > diff --git a/doc/board/purism/index.rst b/doc/board/purism/index.rst
> > index a9cdc312d46..0225aa7f3aa 100644
> > --- a/doc/board/purism/index.rst
> > +++ b/doc/board/purism/index.rst
> 
> > +Get and Build the ARM Trusted firmware
> > +--------------------------------------
> > +
> > +Note: srctree is U-Boot source directory
> > +Get ATF from: https://source.puri.sm/Librem5/arm-trusted-firmware
> 
> Can't the mainline ATF be used instead?

I believe so. The devkit has the B0 revision which wasn't handled in ATF
back then but that seems to be there now. I wanted to switch to manline
ATF later (and we want to add OP-TEE too) once I'm sure things are
stable. So maybe that can be updated in a follow up?

Thanks for the review
 -- Guido


More information about the U-Boot mailing list