]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
ARM: tegra: Relocate fuse code from warmboot file
authorIon Agorria <ion@agorria.com>
Thu, 26 Dec 2024 09:52:04 +0000 (10:52 +0100)
committerSvyatoslav Ryhel <clamor95@gmail.com>
Fri, 1 Aug 2025 05:43:41 +0000 (08:43 +0300)
Move a set of helpers used in warmboot code to more appropriate AP and FUSE
locations.

Signed-off-by: Ion Agorria <ion@agorria.com>
arch/arm/include/asm/arch-tegra/ap.h
arch/arm/include/asm/arch-tegra/fuse.h
arch/arm/include/asm/arch-tegra/warmboot.h
arch/arm/mach-tegra/ap.c
arch/arm/mach-tegra/cpu.h
arch/arm/mach-tegra/fuse.c
arch/arm/mach-tegra/tegra20/warmboot.c

index b922b2d30ea0f98bde84cf015bcdec33623585c8..295c32877376d4503e92b8217e560ffdf21b742a 100644 (file)
@@ -54,6 +54,13 @@ int tegra_get_chip_sku(void);
  */
 int tegra_get_chip(void);
 
+/**
+ * Returns the pure SOC major version from the HIDREV register
+ *
+ * Return:     SOC major version
+ */
+u32 tegra_get_major_version(void);
+
 /**
  * Returns the SKU ID from the sku_info register
  *
index f3f2ad8e3f2cc72f9102ec629327a7e1fccc9853..631ebbb283c6b6247ec1df7a57359765c06e56d6 100644 (file)
@@ -17,8 +17,22 @@ struct fuse_regs {
        u32 fa;                         /* 0x148: FUSE_FA */
        u32 reserved3[21];              /* 0x14C - 0x19C: */
        u32 security_mode;              /* 0x1A0: FUSE_SECURITY_MODE */
+       u32 sbk[4];                     /* 0x1A4 - 0x1B4 */
 };
 
+/* Defines the supported operating modes */
+enum fuse_operating_mode {
+       MODE_UNDEFINED = 0,
+       MODE_PRODUCTION = 3,
+       MODE_ODM_PRODUCTION_SECURE = 4,
+       MODE_ODM_PRODUCTION_OPEN = 5,
+};
+
+/**
+ * Initializes fuse hardware
+ */
+void tegra_fuse_init(void);
+
 /**
  * Calculate SoC UID
  *
@@ -26,4 +40,11 @@ struct fuse_regs {
  */
 unsigned long long tegra_chip_uid(void);
 
+/**
+ * Gives the current operating mode from fuses
+ *
+ * @return current operating mode
+ */
+enum fuse_operating_mode tegra_fuse_get_operation_mode(void);
+
 #endif /* ifndef _FUSE_H_ */
index 9a53456370f3b014340b9ed87913c6c9b766ad13..402f93aac486e9c7c55653581f73ca21788f3a10 100644 (file)
 #define STRAP_OPT_A_RAM_CODE_SHIFT     4
 #define STRAP_OPT_A_RAM_CODE_MASK      (0xf << STRAP_OPT_A_RAM_CODE_SHIFT)
 
-/* Defines the supported operating modes */
-enum fuse_operating_mode {
-       MODE_PRODUCTION = 3,
-       MODE_UNDEFINED,
-};
-
 /* Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) */
 enum {
        HASH_LENGTH = 4
index f35bdba4d48aade69cb8417365e22ec881161f6b..a7938ed79100844b6fcca6648e04c71b6f23d932 100644 (file)
@@ -37,6 +37,14 @@ int tegra_get_chip(void)
        return rev;
 }
 
+u32 tegra_get_major_version(void)
+{
+       struct apb_misc_gp_ctlr *gp =
+               (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+
+       return (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> HIDREV_MAJORPREV_SHIFT;
+}
+
 int tegra_get_sku_info(void)
 {
        int sku_id;
index 006aae3d07052cc8a646652e850487c434ea826b..5477423f4d0a14f572b6b8eb3cad9f7ea35a2e20 100644 (file)
@@ -71,6 +71,7 @@ void powerup_cpu(void);
 void reset_A9_cpu(int reset);
 void start_cpu(u32 reset_vector);
 int tegra_get_chip(void);
+u32 tegra_get_major_version(void);
 int tegra_get_sku_info(void);
 int tegra_get_chip_sku(void);
 void adjust_pllp_out_freqs(void);
index e9b5259ac7010126469c07e06eed3aac1f1e7b9e..abdf6504161965421824fa2f20e41e3235f685b8 100644 (file)
@@ -39,7 +39,7 @@ static u32 tegra_fuse_readl(unsigned long offset)
        return readl(NV_PA_FUSE_BASE + offset);
 }
 
-static void tegra_fuse_init(void)
+void tegra_fuse_init(void)
 {
        u32 reg;
 
@@ -49,8 +49,11 @@ static void tegra_fuse_init(void)
         * this bit fuse region will not work.
         */
        reg = readl_relaxed(NV_PA_CLK_RST_BASE + 0x48);
-       reg |= BIT(28);
-       writel(reg, NV_PA_CLK_RST_BASE + 0x48);
+
+       if (reg & BIT(28))
+               return;
+
+       writel(reg | BIT(28), NV_PA_CLK_RST_BASE + 0x48);
 
        clock_enable(PERIPH_ID_FUSE);
        udelay(2);
@@ -148,3 +151,57 @@ unsigned long long tegra_chip_uid(void)
 
        return uid;
 }
+
+static int tegra_is_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+       return readl(&fuse->production_mode);
+}
+
+static int tegra_is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+       return readl(&fuse->security_mode);
+}
+
+static int tegra_is_failure_analysis_mode(struct fuse_regs *fuse)
+{
+       return readl(&fuse->fa);
+}
+
+static int tegra_is_sbk_zeroes(struct fuse_regs *fuse)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               if (readl(&fuse->sbk[i]))
+                       return 0;
+
+       return 1;
+}
+
+static int tegra_is_production_mode(struct fuse_regs *fuse)
+{
+       if (!tegra_get_major_version())
+               return 1;
+
+       return !tegra_is_failure_analysis_mode(fuse) &&
+              tegra_is_production_mode_fuse_set(fuse);
+}
+
+enum fuse_operating_mode tegra_fuse_get_operation_mode(void)
+{
+       struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
+
+       tegra_fuse_init();
+
+       if (tegra_is_production_mode(fuse)) {
+               if (!tegra_is_odm_production_mode_fuse_set(fuse))
+                       return MODE_PRODUCTION;
+               else
+                       if (tegra_is_sbk_zeroes(fuse))
+                               return MODE_ODM_PRODUCTION_OPEN;
+                       else
+                               return MODE_ODM_PRODUCTION_SECURE;
+       }
+
+       return MODE_UNDEFINED;
+}
index 18034c83a1c216618555c04267b957c68ea30d9d..059388f723186ced60f8b713c84ef294549af739 100644 (file)
@@ -182,83 +182,10 @@ int warmboot_save_sdram_params(void)
        return 0;
 }
 
-static u32 get_major_version(void)
-{
-       u32 major_id;
-       struct apb_misc_gp_ctlr *gp =
-               (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
-
-       major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >>
-                       HIDREV_MAJORPREV_SHIFT;
-       return major_id;
-}
-
-static int is_production_mode_fuse_set(struct fuse_regs *fuse)
-{
-       return readl(&fuse->production_mode);
-}
-
-static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
-{
-       return readl(&fuse->security_mode);
-}
-
-static int is_failure_analysis_mode(struct fuse_regs *fuse)
-{
-       return readl(&fuse->fa);
-}
-
-static int ap20_is_odm_production_mode(void)
-{
-       struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
-
-       if (!is_failure_analysis_mode(fuse) &&
-           is_odm_production_mode_fuse_set(fuse))
-               return 1;
-       else
-               return 0;
-}
-
-static int ap20_is_production_mode(void)
-{
-       struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
-
-       if (get_major_version() == 0)
-               return 1;
-
-       if (!is_failure_analysis_mode(fuse) &&
-           is_production_mode_fuse_set(fuse) &&
-           !is_odm_production_mode_fuse_set(fuse))
-               return 1;
-       else
-               return 0;
-}
-
-static enum fuse_operating_mode fuse_get_operation_mode(void)
-{
-       u32 chip_id;
-       struct apb_misc_gp_ctlr *gp =
-               (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
-
-       chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
-                       HIDREV_CHIPID_SHIFT;
-       if (chip_id == CHIPID_TEGRA20) {
-               if (ap20_is_odm_production_mode()) {
-                       printf("!! odm_production_mode is not supported !!\n");
-                       return MODE_UNDEFINED;
-               } else
-                       if (ap20_is_production_mode())
-                               return MODE_PRODUCTION;
-                       else
-                               return MODE_UNDEFINED;
-       }
-       return MODE_UNDEFINED;
-}
-
 static void determine_crypto_options(int *is_encrypted, int *is_signed,
                                     int *use_zero_key)
 {
-       switch (fuse_get_operation_mode()) {
+       switch (tegra_fuse_get_operation_mode()) {
        case MODE_PRODUCTION:
                *is_encrypted = 0;
                *is_signed = 1;