CS47L63 configuration error in nRF Connect SDK

There is a serious configuration error in Nordic's downstream Cirrus Logic HAL that's likely causing elusive problems for many of your Audio DK customers, particularly those writing their own code instead of relying on the nrf5340_audio example application.

Line 33 in cs47l63_syscfg_regs.c sets the following register value:

{ 0x1c00, 0x0006 }
/* which equals */
{ CS47L63_FLL1_CONTROL1,	FLL1_CTRL_UPD=1 | FLL1_HOLD=1 | FLL1_EN=0 }

This register not only enables/disables FLL1, but also allows its other control fields to be updated on the fly without first stopping the clock. The settings above, however, are ruinously incorrect, and actually prevent unsuspecting programmers from later changing any FLL1 control fields at all.

Section 4.10.7 Frequency-Locked Loop in the CS47L63 datasheet documents this peripheral, and I've included an excerpt below that explains the pertinent fields and details why the above register value is so problematic.

When changing FLL settings, it is recommended to disable the FLL by clearing FLLn_EN before updating the other register fields. If the FLL settings or input reference are changed without disabling the FLL, the FLL Hold Mode must be selected before writing to any other FLL control fields. FLL Hold Mode is selected by setting FLLn_HOLD.

If the FLL control fields are written while the FLL is enabled (FLLn_EN=1), the new values are only effective when a 1 is written to FLLn_CTRL_UPD. This makes it possible to update the FLL configuration fields simultaneously, without disabling the FLL.

To change FLL settings without disabling the FLL, the recommended control sequence is:

  • Select FLL Hold Mode (FLLn_HOLD=1)
  • Write to the FLL control fields
  • Update the FLL control registers (FLLn_CTRL_UPD=1)
  • Disable FLL Hold Mode (FLLn_HOLD=0)

Note that, if the FLL is disabled, the FLL control fields can be updated without writing to FLLn_CTRL_UPD.

Nordic's nrf5340_audio settings for the other FLL1 control fields are already configured before this erroneous register value is set, so under normal conditions the error is unlikely to even be noticed. But for anyone attempting to write their own code or reconfigure this clock (e.g. for undivided HFCLKAUDIO), the results are disastrous and nearly impossible to debug, especially since the source file is so illegibly cryptic and deeply hidden.

To allow FLL1 to be reconfigured without issue, the initial setting should be:

{ 0x1c00, 0x0000 }
/* which equals */
{ CS47L63_FLL1_CONTROL1,	FLL1_CTRL_UPD=0 | FLL1_HOLD=0 | FLL1_EN=0 }

This is exactly the kind of keyboard-smashing bug that eventually drove me to a different vendor from exhausted frustration, and Nordic would be well advised to fix it.

  • (updated)

    From the team:

    The file you are referring to comes directly from Cirrus, and this is indeed hidden a bit. Since this file comes from Cirrus Logic, we could have questioned the contents of this file more, but when a vendor tells us to apply a file of hex values after boot, we tend not to second-guess the contents. 

    Are you using WISCE to debug? There it will be visible what bitfields are set. 

    --

    Hi, 

    Thanks for the report. I have forwarded it to the team.

    Regards,
    Amanda H.

Related