You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by be...@apache.org on 2020/01/22 18:18:25 UTC

[mynewt-core] branch master updated: hw/mcu/dialog: Apply trim and preferred values

This is an automated email from the ASF dual-hosted git repository.

benmccrea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new f44ad5d  hw/mcu/dialog: Apply trim and preferred values
     new b275ac3  Merge pull request #2161 from andrzej-kaczmarek/dialog-trimv
f44ad5d is described below

commit f44ad5daf7ca9b939520f8c217f4db799e9f150c
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Tue Jan 21 15:11:54 2020 +0100

    hw/mcu/dialog: Apply trim and preferred values
    
    So far we assumed that 1st stage bootloader applied all trim values
    stored in CS and they are valid. However, since power domains can be
    disabled we need to make sure proper settings are reapplied once they
    are enabled.
    
    This patch automates this process:
    - read trim values for each applicable PD on init
    - apply trim values once PD is enabled (on 1st acquire)
    - apply preferred values on top of this
    
    This means that after waking up from extended sleep (where most of power
    domains are disabled) all settings are reapplied correctly.
---
 hw/mcu/dialog/da1469x/include/mcu/da1469x_pd.h |  13 ++-
 hw/mcu/dialog/da1469x/src/da1469x_pd.c         | 148 ++++++++++++++++++++++++-
 hw/mcu/dialog/da1469x/src/da1469x_sleep.c      |   9 +-
 hw/mcu/dialog/da1469x/src/hal_system.c         |   3 -
 hw/mcu/dialog/da1469x/src/system_da1469x.c     |  18 ++-
 5 files changed, 176 insertions(+), 15 deletions(-)

diff --git a/hw/mcu/dialog/da1469x/include/mcu/da1469x_pd.h b/hw/mcu/dialog/da1469x/include/mcu/da1469x_pd.h
index acc552b..5a9e3bd 100644
--- a/hw/mcu/dialog/da1469x/include/mcu/da1469x_pd.h
+++ b/hw/mcu/dialog/da1469x/include/mcu/da1469x_pd.h
@@ -29,14 +29,17 @@ extern "C" {
 #endif
 
 /* Available (controllable) power domains */
-#define MCU_PD_DOMAIN_PER           0
-#define MCU_PD_DOMAIN_RAD           1
-#define MCU_PD_DOMAIN_TIM           2
-#define MCU_PD_DOMAIN_COM           3
+#define MCU_PD_DOMAIN_SYS           0
+#define MCU_PD_DOMAIN_PER           1
+#define MCU_PD_DOMAIN_RAD           2
+#define MCU_PD_DOMAIN_TIM           3
+#define MCU_PD_DOMAIN_COM           4
 
-#define MCU_PD_DOMAIN_COUNT         4
+#define MCU_PD_DOMAIN_COUNT         5
 
+int da1469x_pd_init(void);
 int da1469x_pd_acquire(uint8_t pd);
+int da1469x_pd_acquire_noconf(uint8_t pd);
 int da1469x_pd_release(uint8_t pd);
 int da1469x_pd_release_nowait(uint8_t pd);
 
diff --git a/hw/mcu/dialog/da1469x/src/da1469x_pd.c b/hw/mcu/dialog/da1469x/src/da1469x_pd.c
index 1f95f90..20ac45c 100644
--- a/hw/mcu/dialog/da1469x/src/da1469x_pd.c
+++ b/hw/mcu/dialog/da1469x/src/da1469x_pd.c
@@ -18,9 +18,11 @@
  */
 
 #include <assert.h>
+#include <stdlib.h>
 #include "defs/error.h"
 #include "mcu/da1469x_hal.h"
 #include "mcu/da1469x_pd.h"
+#include "mcu/da1469x_trimv.h"
 #include "os/util.h"
 
 struct da1469x_pd_desc {
@@ -28,7 +30,14 @@ struct da1469x_pd_desc {
     uint8_t stat_down_bit; /* up is +1 */
 };
 
+struct da1469x_pd_trimv {
+    uint8_t count;
+    uint32_t *words;
+};
+
 static const struct da1469x_pd_desc g_da1469x_pd_desc[] = {
+    [MCU_PD_DOMAIN_SYS] = { CRG_TOP_PMU_CTRL_REG_SYS_SLEEP_Pos,
+                            CRG_TOP_SYS_STAT_REG_SYS_IS_DOWN_Pos },
     [MCU_PD_DOMAIN_PER] = { CRG_TOP_PMU_CTRL_REG_PERIPH_SLEEP_Pos,
                             CRG_TOP_SYS_STAT_REG_PER_IS_DOWN_Pos },
     [MCU_PD_DOMAIN_RAD] = { CRG_TOP_PMU_CTRL_REG_RADIO_SLEEP_Pos,
@@ -40,9 +49,129 @@ static const struct da1469x_pd_desc g_da1469x_pd_desc[] = {
 };
 
 static uint8_t g_da1469x_pd_refcnt[ ARRAY_SIZE(g_da1469x_pd_desc) ];
+static struct da1469x_pd_trimv g_da1469x_pd_trimv[ ARRAY_SIZE(g_da1469x_pd_desc) ];
+
+static void
+da1469x_pd_load_trimv(uint8_t pd, uint8_t group)
+{
+    struct da1469x_pd_trimv *tv;
+
+    assert(pd < ARRAY_SIZE(g_da1469x_pd_desc));
+
+    tv = &g_da1469x_pd_trimv[pd];
+    tv->count = da1469x_trimv_group_num_words_get(group);
+    if (tv->count == 0) {
+        return;
+    }
+
+    tv->words = calloc(tv->count, 4);
+    if (!tv->words) {
+        tv->count = 0;
+        assert(0);
+        return;
+    }
+
+    tv->count = da1469x_trimv_group_read(group, tv->words, tv->count);
+    tv->count /= 2;
+}
+
+static void
+da1469x_pd_apply_trimv(uint8_t pd)
+{
+    struct da1469x_pd_trimv *tv;
+    volatile uint32_t *reg;
+    uint32_t val;
+    int idx;
+
+    assert(pd < ARRAY_SIZE(g_da1469x_pd_desc));
+
+    tv = &g_da1469x_pd_trimv[pd];
+    if (tv->count == 0) {
+        return;
+    }
+
+    for (idx = 0; idx < tv->count; idx++) {
+        reg = (void *)tv->words[idx * 2];
+        val = tv->words[idx * 2 + 1];
+        *reg = val;
+    }
+}
+
+static inline uint32_t
+get_reg32(uint32_t addr)
+{
+    volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+    return *reg;
+}
+
+static inline void
+set_reg32(uint32_t addr, uint32_t val)
+{
+    volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+    *reg = val;
+}
+
+static inline void
+set_reg32_mask(uint32_t addr, uint32_t mask, uint32_t val)
+{
+    volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+    *reg = (*reg & (~mask)) | (val & mask);
+}
+
+static void
+da1469x_pd_apply_preferred(uint8_t pd)
+{
+    switch (pd) {
+    case MCU_PD_DOMAIN_SYS:
+        set_reg32_mask(0x50040400, 0x00000c00, 0x003f6a78);
+        set_reg32_mask(0x50040454, 0x000003ff, 0x00000002);
+        break;
+    case MCU_PD_DOMAIN_TIM:
+        set_reg32_mask(0x50010000, 0x3ff00000, 0x000afd70);
+        set_reg32_mask(0x50010010, 0x000000c0, 0x00000562);
+        set_reg32_mask(0x50010030, 0x43c38002, 0x4801e6b6);
+        set_reg32_mask(0x50010034, 0x007fff00, 0x7500a1a4);
+        set_reg32_mask(0x50010038, 0x00000fff, 0x001e45c4);
+        set_reg32_mask(0x5001003c, 0x40000000, 0x40096255);
+        set_reg32_mask(0x50010040, 0x00c00000, 0x00c00000);
+        set_reg32_mask(0x50010018, 0x000000ff, 0x00000180);
+        break;
+    }
+}
+
+static void
+apply_preferred_pd_aon(void)
+{
+    if (get_reg32(0x500000f8) == 0x00008800) {
+        set_reg32(0x500000f8, 0x00007700);
+    }
+    set_reg32_mask(0x50000050, 0x00001000, 0x00001020);
+    set_reg32(0x500000a4, 0x000000ca);
+    set_reg32_mask(0x50000064, 0x0003ffff, 0x041e6ef4);
+}
 
 int
-da1469x_pd_acquire(uint8_t pd)
+da1469x_pd_init(void)
+{
+    /*
+     * Apply now for always-on domain which, as name suggests, is always on so
+     * need to do this only once.
+     */
+    apply_preferred_pd_aon();
+
+    da1469x_pd_load_trimv(MCU_PD_DOMAIN_SYS, 1);
+    da1469x_pd_load_trimv(MCU_PD_DOMAIN_COM, 2);
+    da1469x_pd_load_trimv(MCU_PD_DOMAIN_TIM, 4);
+    da1469x_pd_load_trimv(MCU_PD_DOMAIN_PER, 5);
+
+    return 0;
+}
+
+static int
+da1469x_pd_acquire_internal(uint8_t pd, bool load)
 {
     uint8_t *refcnt;
     uint32_t primask;
@@ -62,6 +191,11 @@ da1469x_pd_acquire(uint8_t pd)
         bitmask = 1 << (g_da1469x_pd_desc[pd].stat_down_bit + 1);
         while ((CRG_TOP->SYS_STAT_REG & bitmask) == 0);
 
+        if (load) {
+            da1469x_pd_apply_trimv(pd);
+            da1469x_pd_apply_preferred(pd);
+        }
+
         ret = 1;
     }
 
@@ -71,6 +205,18 @@ da1469x_pd_acquire(uint8_t pd)
 }
 
 int
+da1469x_pd_acquire(uint8_t pd)
+{
+    return da1469x_pd_acquire_internal(pd, true);
+}
+
+int
+da1469x_pd_acquire_noconf(uint8_t pd)
+{
+    return da1469x_pd_acquire_internal(pd, false);
+}
+
+int
 da1469x_pd_release(uint8_t pd)
 {
     uint8_t *refcnt;
diff --git a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c
index e2662f5..a476e83 100644
--- a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c
+++ b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c
@@ -19,6 +19,7 @@
 
 #include <assert.h>
 #include "mcu/da1469x_clock.h"
+#include "mcu/da1469x_pd.h"
 #include "mcu/da1469x_pdc.h"
 #include "mcu/da1469x_prail.h"
 #include "mcu/mcu.h"
@@ -65,11 +66,15 @@ da1469x_sleep(os_time_t ticks)
         return;
     }
 
+    /* PD_SYS will not be disabled here until we enter deep sleep, so don't wait */
+    da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS);
+
     mcu_gpio_enter_sleep();
     ret = da1469x_m33_sleep();
     mcu_gpio_exit_sleep();
     if (!ret) {
-        /* We were not sleeping, just return */
+        /* We were not sleeping, no need to apply PD_SYS settings again */
+        da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS);
         return;
     }
 
@@ -77,6 +82,8 @@ da1469x_sleep(os_time_t ticks)
     da1469x_prail_dcdc_restore();
 #endif
 
+    da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
+
     /*
      * If PDC entry for "combo" wakeup is pending, but none of CMAC2SYS, WKUP
      * or VBUS is pending it means we were woken up from JTAG. We need to block
diff --git a/hw/mcu/dialog/da1469x/src/hal_system.c b/hw/mcu/dialog/da1469x/src/hal_system.c
index 53baf10..57a2ca2 100644
--- a/hw/mcu/dialog/da1469x/src/hal_system.c
+++ b/hw/mcu/dialog/da1469x/src/hal_system.c
@@ -23,7 +23,6 @@
 #include "mcu/da1469x_lpclk.h"
 #include "mcu/da1469x_pd.h"
 #include "mcu/da1469x_pdc.h"
-#include "mcu/da1469x_trimv.h"
 #include "hal/hal_system.h"
 #include "os/os_cputime.h"
 
@@ -59,8 +58,6 @@ hal_system_init(void)
         g_hal_reset_reason = 0;
     }
 #endif
-
-    da1469x_trimv_init_from_otp();
 }
 
 void
diff --git a/hw/mcu/dialog/da1469x/src/system_da1469x.c b/hw/mcu/dialog/da1469x/src/system_da1469x.c
index 938df82..1dfae27 100644
--- a/hw/mcu/dialog/da1469x/src/system_da1469x.c
+++ b/hw/mcu/dialog/da1469x/src/system_da1469x.c
@@ -22,6 +22,7 @@
 #include "mcu/da1469x_pdc.h"
 #include "mcu/da1469x_prail.h"
 #include "mcu/da1469x_clock.h"
+#include "mcu/da1469x_trimv.h"
 #include <mcu/da1469x_otp.h>
 #include "mcu/mcu.h"
 #include "da1469x_priv.h"
@@ -88,6 +89,18 @@ SystemInit(void)
     NVIC_DisableIRQ(PDC_IRQn);
     NVIC_ClearPendingIRQ(PDC_IRQn);
 
+    /*
+     * We need to parse trim values from CS to apply them when each power domain
+     * is enabled so need to do this before any PD is acquired. Need to initialize
+     * OTP before that.
+     */
+    da1469x_otp_init();
+    da1469x_trimv_init_from_otp();
+    da1469x_pd_init();
+
+    /* PD_SYS is already running so let's acquire it to apply preferred settings */
+    da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
+
 #if MYNEWT_VAL(OS_SCHEDULING) && MYNEWT_VAL(MCU_DEEP_SLEEP)
     /* Make sure PD_TIM domain is always up for Timer2 to be running */
     da1469x_pd_acquire(MCU_PD_DOMAIN_TIM);
@@ -107,15 +120,10 @@ SystemInit(void)
     da1469x_pdc_ack(idx);
     g_mcu_pdc_combo_idx = idx;
 
-    CRG_TOP->PMU_CTRL_REG |= CRG_TOP_PMU_CTRL_REG_SYS_SLEEP_Msk;
-
     /* Enable cache retainability */
     CRG_TOP->PMU_CTRL_REG |= CRG_TOP_PMU_CTRL_REG_RETAIN_CACHE_Msk;
 #endif
 
-    /* initialize OTP and place in deep standby */
-    da1469x_otp_init();
-
     /* Initialize and configure power rails */
     da1469x_prail_initialize();
 #if MYNEWT_VAL(MCU_DCDC_ENABLE)