soc: nrf54l15: Fix LFXO INTCAP code calculations

There were two errors in calculations of LFXO INTCAP code:
- The value provided by DTS files is internal desired capacitance.
  The value from DTS has to be "encoded" before use in INTCAP
  calculations formula. The formula for encoding is:
  CAPACITANCE_CODE = (<desired_value> - 4pF) / 0.5
  Subtract of 4 is related with lowest value in the allowed range.
  Division by 0.5 is related with change to steps size.
  In former code the subtration of 4pF was missing.

- The mid_val calcuation was wrong due offset_k left shift by 4.
  It should be left shift by 3 to get total left shift of 9.
  That matches the left shift of former part of the equation.
  Final integer value was calculated by right shift 10, it should
  be right shift 9. Then rounding was done by use of mod by (1 << 10)
  It should be mod by (1 << 9) and compared with (1 << 8), that is
  half of 0-512 range.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2024-06-12 18:10:55 +02:00 committed by Anas Nashif
commit f0f5f28f99

View file

@ -65,16 +65,34 @@ static int nordicsemi_nrf54l_init(void)
* where CAPACITANCE is the desired capacitor value in pF, holding any
* value between 4 pF and 18 pF in 0.5 pF steps.
*/
uint32_t mid_val =
(((DT_PROP(LFXO_NODE, load_capacitance_femtofarad) * 2UL) / 1000UL - 8UL) *
(uint32_t)(slope_k + 392)) + (offset_k << 4UL);
uint32_t capvalue_k = mid_val >> 10UL;
/* Round. */
if ((mid_val % 1024UL) >= 512UL) {
capvalue_k++;
/* Encoding of desired capacitance (single ended) to value required for INTCAP core
* calculation: (CAP_VAL - 4 pF)* 0.5
* That translate to ((CAP_VAL_FEMTO_F - 4000fF) * 2UL) / 1000UL
*
* NOTE: The desired capacitance value is used in encoded from in INTCAP calculation formula
* That is different than in case of HFXO.
*/
uint32_t cap_val_encoded = (((DT_PROP(LFXO_NODE, load_capacitance_femtofarad) - 4000UL)
* 2UL) / 1000UL);
/* Calculation of INTCAP code before rounding. Min that calculations here are done on
* values multiplied by 2^9, e.g. 0.765625 * 2^9 = 392.
* offset_k should be divided by 2^6, but to add it to value shifted by 2^9 we have to
* multiply it be 2^3.
*/
uint32_t mid_val = (cap_val_encoded - 4UL) * (uint32_t)(slope_k + 392UL)
+ (offset_k << 3UL);
/* Get integer part of the INTCAP code */
uint32_t lfxo_intcap = mid_val >> 9UL;
/* Round based on fractional part */
if ((mid_val & BIT_MASK(9)) > (BIT_MASK(9) / 2)) {
lfxo_intcap++;
}
nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, (nrf_oscillators_lfxo_cap_t)capvalue_k);
nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, lfxo_intcap);
#elif DT_ENUM_HAS_VALUE(LFXO_NODE, load_capacitors, external)
nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, (nrf_oscillators_lfxo_cap_t)0);
#endif