[PATCH 2/2] board: apalis-imx8: add new 8gb product variant

Marcel Ziswiler marcel.ziswiler at toradex.com
Tue May 10 17:39:21 CEST 2022


On Mon, 2022-05-09 at 18:58 +0200, Philippe Schenker wrote:
> From: Philippe Schenker <philippe.schenker at toradex.com>
> 
> Add the new Apalis iMX8 product variant
> 
> 0067: Apalis iMX8 QuadMax 8GB Wi-Fi / BT IT
> 
> the only difference to the product
> 
> 0037 Apalis iMX8 QuadMax 4GB Wi-Fi / BT IT
> 
> is the 8gb of RAM. Toradex strategy to choose the correct RAM timing in
> SCFW is by fuses in the user area telling which RAM timing to load.
> 
> This commit makes use of this information to set the correct size of
> the RAM and therefore distinguish between the new 0067 and 0037 product
> 
> Signed-off-by: Philippe Schenker <philippe.schenker at toradex.com>
> Reviewed-by: Francesco Dolcini <francesco.dolcini at toradex.com>

Acked-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>

> ---
> 
>  board/toradex/apalis-imx8/apalis-imx8.c | 81 +++++++++++++++++++++++--
>  1 file changed, 77 insertions(+), 4 deletions(-)
> 
> diff --git a/board/toradex/apalis-imx8/apalis-imx8.c b/board/toradex/apalis-imx8/apalis-imx8.c
> index 04877fcd94..408198843f 100644
> --- a/board/toradex/apalis-imx8/apalis-imx8.c
> +++ b/board/toradex/apalis-imx8/apalis-imx8.c
> @@ -18,6 +18,7 @@
>  #include <env.h>
>  #include <errno.h>
>  #include <linux/libfdt.h>
> +#include <linux/bitops.h>
>  
>  #include "../common/tdx-cfg-block.h"
>  
> @@ -28,22 +29,75 @@ DECLARE_GLOBAL_DATA_PTR;
>                          (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT) | \
>                          (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
>  
> +#define TDX_USER_FUSE_BLOCK1_A 276
> +#define TDX_USER_FUSE_BLOCK1_B 277
> +#define TDX_USER_FUSE_BLOCK2_A 278
> +#define TDX_USER_FUSE_BLOCK2_B 279
> +
>  static iomux_cfg_t uart1_pads[] = {
>         SC_P_UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
>         SC_P_UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
>  };
>  
> +struct tdx_user_fuses {
> +       u16 pid4;
> +       u16 vers;
> +       u8 ramid;
> +};
> +
>  static void setup_iomux_uart(void)
>  {
>         imx8_iomux_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
>  }
>  
> +static uint32_t do_get_tdx_user_fuse(int a, int b)
> +{
> +       sc_err_t sciErr;
> +       u32 val_a = 0;
> +       u32 val_b = 0;
> +
> +       sciErr = sc_misc_otp_fuse_read(-1, a, &val_a);
> +       if (sciErr != SC_ERR_NONE) {
> +               printf("Error reading out user fuse %d\n", a);
> +               return 0;
> +       }
> +
> +       sciErr = sc_misc_otp_fuse_read(-1, b, &val_b);
> +       if (sciErr != SC_ERR_NONE) {
> +               printf("Error reading out user fuse %d\n", b);
> +               return 0;
> +       }
> +
> +       return ((val_a & 0xffff) << 16) | (val_b & 0xffff);
> +}
> +
> +static void get_tdx_user_fuse(struct tdx_user_fuses *tdxuserfuse)
> +{
> +       u32 fuse_block;
> +
> +       fuse_block = do_get_tdx_user_fuse(TDX_USER_FUSE_BLOCK2_A,
> +                                         TDX_USER_FUSE_BLOCK2_B);
> +
> +       /*
> +        * Fuse block 2 acts as a backup area, if this reads 0 we want to
> +        * use fuse block 1
> +        */
> +       if (fuse_block == 0)
> +               fuse_block = do_get_tdx_user_fuse(TDX_USER_FUSE_BLOCK1_A,
> +                                                 TDX_USER_FUSE_BLOCK1_B);
> +
> +       tdxuserfuse->pid4 = (fuse_block >> 18) & GENMASK(13, 0);
> +       tdxuserfuse->vers = (fuse_block >> 4) & GENMASK(13, 0);
> +       tdxuserfuse->ramid = fuse_block & GENMASK(3, 0);
> +}
> +
>  void board_mem_get_layout(u64 *phys_sdram_1_start,
>                           u64 *phys_sdram_1_size,
>                           u64 *phys_sdram_2_start,
>                           u64 *phys_sdram_2_size)
>  {
>         u32 is_quadplus = 0, val = 0;
> +       struct tdx_user_fuses tdxramfuses;
>         sc_err_t scierr = sc_misc_otp_fuse_read(-1, 6, &val);
>  
>         if (scierr == SC_ERR_NONE) {
> @@ -51,14 +105,33 @@ void board_mem_get_layout(u64 *phys_sdram_1_start,
>                 is_quadplus = ((val >> 4) & 0x3) != 0x0;
>         }
>  
> +       get_tdx_user_fuse(&tdxramfuses);
> +
>         *phys_sdram_1_start = PHYS_SDRAM_1;
>         *phys_sdram_1_size = PHYS_SDRAM_1_SIZE;
>         *phys_sdram_2_start = PHYS_SDRAM_2;
> -       if (is_quadplus)
> -               /* Our QP based SKUs only have 2 GB RAM (PHYS_SDRAM_1_SIZE) */
> +
> +       switch (tdxramfuses.ramid) {
> +       case 1:
> +               *phys_sdram_2_size = SZ_2G;
> +               break;
> +       case 2:
>                 *phys_sdram_2_size = 0x0UL;
> -       else
> -               *phys_sdram_2_size = PHYS_SDRAM_2_SIZE;
> +               break;
> +       case 3:
> +               *phys_sdram_2_size = SZ_2G;
> +               break;
> +       case 4:
> +               *phys_sdram_2_size = SZ_4G + SZ_2G;
> +               break;
> +       default:
> +               if (is_quadplus)
> +                       /* Our QP based SKUs only have 2 GB RAM (PHYS_SDRAM_1_SIZE) */
> +                       *phys_sdram_2_size = 0x0UL;
> +               else
> +                       *phys_sdram_2_size = PHYS_SDRAM_2_SIZE;
> +               break;
> +       }
>  }
>  
>  int board_early_init_f(void)


More information about the U-Boot mailing list