arm: mvebu: set 38x and 39x AVS on lower frequency
authorBaruch Siach <baruch@tkos.co.il>
Wed, 10 Jul 2019 15:23:04 +0000 (18:23 +0300)
committerStefan Roese <sr@denx.de>
Thu, 11 Jul 2019 08:58:03 +0000 (10:58 +0200)
Reduce Auto Voltage Scaling VDD limit when core frequency is lower than
1600MHz. This reduces core voltage level from 1.25V to 1.15V, which
saves power.

The code is taken from Marvell's U-Boot 2013.01 revision 18.06.

Reviewed-by: Chris Packham <judge.packham@gmail.com>
Tested-by: Chris Packham <judge.packham@gmail.com>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Stefan Roese <sr@denx.de>
arch/arm/mach-mvebu/include/mach/cpu.h
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
arch/arm/mach-mvebu/spl.c

index e6140d67293ec60a3379073b0a3a47b3028ca0cc..2e2d72aac892f4a5e6df81ee087d25d75349d904 100644 (file)
@@ -163,6 +163,13 @@ int serdes_phy_config(void);
  */
 int ddr3_init(void);
 
+/* Auto Voltage Scaling */
+#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X)
+void mv_avs_init(void);
+#else
+static inline void mv_avs_init(void) {}
+#endif
+
 /*
  * get_ref_clk
  *
index d387893af37d10f794b45ddcb57f22d4de7f7260..e9dd096ad0f538facd9532fcc71900bda9aaaa6f 100644 (file)
@@ -256,3 +256,29 @@ u8 sys_env_device_rev_get(void)
        value = reg_read(DEV_VERSION_ID_REG);
        return (value & (REVISON_ID_MASK)) >> REVISON_ID_OFFS;
 }
+
+void mv_avs_init(void)
+{
+       u32 sar_freq;
+
+       if (!(IS_ENABLED(CONFIG_ARMADA_38X) || IS_ENABLED(CONFIG_ARMADA_39X)))
+               return;
+
+       reg_write(AVS_DEBUG_CNTR_REG, AVS_DEBUG_CNTR_DEFAULT_VALUE);
+       reg_write(AVS_DEBUG_CNTR_REG, AVS_DEBUG_CNTR_DEFAULT_VALUE);
+
+       sar_freq = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
+       sar_freq = sar_freq >> SAR_FREQ_OFFSET & SAR_FREQ_MASK;
+
+       /* Set AVS value only for core frequency of 1600MHz or less.
+        * For higher frequency leave the default value.
+        */
+       if (sar_freq <= 0xd) {
+               u32 avs_reg_data = reg_read(AVS_ENABLED_CONTROL);
+
+               avs_reg_data &= ~(AVS_LOW_VDD_LIMIT_MASK
+                               | AVS_HIGH_VDD_LIMIT_MASK);
+               avs_reg_data |= AVS_LOW_VDD_SLOW_VAL | AVS_HIGH_VDD_SLOW_VAL;
+               reg_write(AVS_ENABLED_CONTROL, avs_reg_data);
+       }
+}
index 365332d2b048eda37614fb9228a230446b39045c..1774a5b780cafa5052ea93dff184b377bfa63c32 100644 (file)
@@ -33,6 +33,8 @@
 #define DEV_ID_REG_DEVICE_ID_OFFS      16
 #define DEV_ID_REG_DEVICE_ID_MASK      0xffff0000
 
+#define SAR_FREQ_OFFSET                        10
+#define SAR_FREQ_MASK                  0x1f
 #define SAR_DEV_ID_OFFS                        27
 #define SAR_DEV_ID_MASK                        0x7
 
 #define AVS_LOW_VDD_LIMIT_OFFS         4
 #define AVS_LOW_VDD_LIMIT_MASK         (0xff << AVS_LOW_VDD_LIMIT_OFFS)
 #define AVS_LOW_VDD_LIMIT_VAL          (0x27 << AVS_LOW_VDD_LIMIT_OFFS)
+#define AVS_LOW_VDD_SLOW_VAL           (0x23 << AVS_LOW_VDD_LIMIT_OFFS)
 
 #define AVS_HIGH_VDD_LIMIT_OFFS                12
 #define AVS_HIGH_VDD_LIMIT_MASK                (0xff << AVS_HIGH_VDD_LIMIT_OFFS)
 #define AVS_HIGH_VDD_LIMIT_VAL         (0x27 << AVS_HIGH_VDD_LIMIT_OFFS)
+#define AVS_HIGH_VDD_SLOW_VAL          (0x23 << AVS_HIGH_VDD_LIMIT_OFFS)
 
 /* Board ID numbers */
 #define MARVELL_BOARD_ID_MASK          0x10
index d54de5195624be7915c5c181dfcff4d6410e52ef..3cb27b7f4b208aca7a6e8e2282197c2ca40d1d74 100644 (file)
@@ -126,6 +126,9 @@ void board_init_f(ulong dummy)
        ddr3_init();
 #endif
 
+       /* Initialize Auto Voltage Scaling */
+       mv_avs_init();
+
        /*
         * Return to the BootROM to continue the Marvell xmodem
         * UART boot protocol. As initiated by the kwboot tool.