Skip to content

soc: nordic: nrf53: assign pin xl1,xl2 to app core if lfxo disabled #92664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ivynya
Copy link

@ivynya ivynya commented Jul 3, 2025

I opened an issue #92663 where disabling LFXO for the nRF53 via devicetree or kconfig does not properly allow the pins from the LFXO (0.00 and 0.01) to be used as GPIO. This adds a few guards against those devicetree and kconfig properties, and if LFXO is disabled by the build configuration, will assign those pins to the nRF53 app core instead.

Copy link

github-actions bot commented Jul 3, 2025

Hello @ivynya, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe a better option than riding on the LFXO_CAP, would be to just use DT_NODE_HAS_STATUS_OKAY(LFXO_NODE), and if it is, then BUILD_ASSERT(DT_NODE_HAS_PROP(LFXO_NODE), load_capacitors) and lastly, clean up the#ifdef like

#ifdef CONFIG_SOC_NRF5340_CPUAPP
#if DT_NODE_HAS_STATUS_OKAY(LFXO_NODE)
	nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, LFXO_CAP);
#if !defined(CONFIG_BUILD_WITH_TFM)
	/* This can only be done from secure code.
	 * This is handled by the TF-M platform so we skip it when TF-M is
	 * enabled.
	 */
	nrf_gpio_pin_control_select(PIN_XL1, NRF_GPIO_PIN_SEL_PERIPHERAL);
	nrf_gpio_pin_control_select(PIN_XL2, NRF_GPIO_PIN_SEL_PERIPHERAL);
#endif /* !defined(CONFIG_BUILD_WITH_TFM) */
#elif !defined(CONFIG_BUILD_WITH_TFM)
	nrf_gpio_pin_control_select(PIN_XL1, NRF_GPIO_PIN_SEL_APP);
	nrf_gpio_pin_control_select(PIN_XL2, NRF_GPIO_PIN_SEL_APP);
#endif

This aligns everything to use the devicetree, and is is clearer as DT_NODE_HAS_STATUS_OKAY(LFXO_NODE) means what it says, where LFXO_CAP is being used to mean the same, but IMO does not read the same :)

If maintaining the HWM1 module is of interest, then a bespoke PR for it based on the deprecated Kconfig symbol would be needed.

@@ -54,11 +54,13 @@
#define HFXO_NODE DT_NODELABEL(hfxo)

/* LFXO config from DT */
#if DT_NODE_HAS_STATUS_OKAY(LFXO_NODE) && defined(CONFIG_SOC_ENABLE_LFXO)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONFIG_SOC_ENABLE_LFXO is deprecated, and is not used upstream. It is only used in the nordic specific HWM1 module, which defines it itself anyway, so really the config should just be removed from upstream entirely :)

With this change as is, the new and correct behavior added in this PR when LFXO is disabled in devicetree is only applied if the deprecated CONFIG_SOC_ENABLE_LFXO is also selected, which is an unnecessary additional constraint, especially given the downstream HWM1 module entirely ignores the contents of this file so its not making the change any more backwards compatible.

@ivynya ivynya force-pushed the nrf53-lfxo-config branch from 877bc15 to 1b70a1c Compare July 7, 2025 16:37
@ivynya
Copy link
Author

ivynya commented Jul 7, 2025

Thank you for the feedback! I believe I applied the suggestions correctly, checking directly and exclusively for the devicetree node instead. I also removed the legacy LFXO Kconfig if block (L62-72) as it sounds like after these changes it will not affect anything anymore. I tested quickly with my project and it seems to work. Please let me know if I might have misinterpreted anything or further changes are needed.

@ivynya ivynya requested a review from bjarki-andreasen July 7, 2025 16:48
Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks just about perfect :) Nice work!

masz-nordic
masz-nordic previously approved these changes Jul 8, 2025
@bjarki-andreasen
Copy link
Contributor

The Signed-off-by: entry must use the full name of your github profile, so Signed-off-by: Ivynya Lu <[email protected]>

@ivynya ivynya force-pushed the nrf53-lfxo-config branch from 1b70a1c to 31edb33 Compare July 9, 2025 03:05
Comment on lines 61 to 72
#else
/* LFXO config from legacy Kconfig */
#if defined(CONFIG_SOC_LFXO_CAP_INT_6PF)
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_6PF
#elif defined(CONFIG_SOC_LFXO_CAP_INT_7PF)
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_7PF
#elif defined(CONFIG_SOC_LFXO_CAP_INT_9PF)
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_9PF
#else
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_EXTERNAL
#endif
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part cannot be removed yet. These options are deprecated but they are still present in Kconfig, so they still need to be supported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then remove them in Kconfig? The have been deprecated for a year now

Copy link
Member

@anangl anangl Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they were deprecated in 4.0, so they can be removed now.

@@ -54,22 +54,14 @@
#define HFXO_NODE DT_NODELABEL(hfxo)

/* LFXO config from DT */
#if DT_NODE_HAS_STATUS_OKAY(LFXO_NODE)
BUILD_ASSERT(DT_NODE_HAS_PROP(LFXO_NODE, load_capacitors));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably better to mark this property as required in the devicetree binding. But anyway, as long as the legacy Kconfig options are available, we cannot require this property to be present.

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking it as required is an issue since the lfxo is not neccesarily present, which I believe is noted by the lfxo node having status = "disabled". In this case, if the prop is required, some random value has to be set even though it can not be correct given there is no lfxo on the board :) The same issue is present for the comparator where some properties are required only if the comp is actually enabled :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand the issue. Properties with required: true are required by dtc only for nodes with status "okay", so for disabled nodes you don't need to provide any value for them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I though they where always required, given what "disabled" means according to devicetree spec, seems we have our own rule which matches zephyrs bindings better :)

#elif !defined(CONFIG_BUILD_WITH_TFM)
nrf_gpio_pin_control_select(PIN_XL1, NRF_GPIO_PIN_SEL_APP);
nrf_gpio_pin_control_select(PIN_XL2, NRF_GPIO_PIN_SEL_APP);
#endif /* DT_NODE_HAS_STATUS_OKAY(LFXO_NODE) */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about defining something like LFXO_PIN_SEL depending on the lfxo node status and using here just:

#if defined(LFXO_CAP)
	nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS, LFXO_CAP);
#endif
#if !defined(CONFIG_BUILD_WITH_TFM)
	/* This can only be done from secure code.
	 * This is handled by the TF-M platform so we skip it when TF-M is
	 * enabled.
	 */
	nrf_gpio_pin_control_select(PIN_XL1, LFXO_PIN_SEL);
	nrf_gpio_pin_control_select(PIN_XL2, LFXO_PIN_SEL);
#endif /* !defined(CONFIG_BUILD_WITH_TFM) */

Wouldn't that be clearer?

Fixes zephyrproject-rtos#92663

Disabled LFXO via devicetree allows pin 0.00 and 0.01 to work correctly
as gpio by assigning it to the app core instead of peripheral. Removed
deprecated Kconfig options so DT is the only config path now.

Signed-off-by: Ivynya Lu <[email protected]>
@ivynya ivynya dismissed stale reviews from masz-nordic and bjarki-andreasen via 21ea969 July 14, 2025 16:37
@ivynya ivynya force-pushed the nrf53-lfxo-config branch from 31edb33 to 21ea969 Compare July 14, 2025 16:37
@ivynya
Copy link
Author

ivynya commented Jul 14, 2025

Sorry for the delay in update. I added a define LFXO_PIN_SEL and used it in the CPUAPP ifdef, as suggested, and also removed the Kconfig options for SOC_LFXO_ENABLE and related as it sounds like this would be acceptable due to them being deprecated.

However, I'm a little confused regarding the conversation about marking the DT property for load capacitors as required - would this be a preferred change or is it okay as-is? Again, for these changes I ran a quick test on my project and it seems to be working as intended, but please let me know if there are further changes needed. Thanks!

@ivynya ivynya requested a review from anangl July 14, 2025 16:46
Copy link

Copy link
Contributor

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into the build failure, some boards depend on the previous default behavior, which automatically sets load capacitors to "external" if load-capacitors is not specified in the devicetree.

To avoid having to look through and update all boards to check if they set load-capacitors to manually set them to external, let's keep the default behavior. That is, don't assert

BUILD_ASSERT(DT_NODE_HAS_PROP(LFXO_NODE, load_capacitors))

and instead default to external if the prop does not exist:

#if DT_NODE_HAS_PROP(LFXO_NODE, load_capacitors)
#if DT_ENUM_HAS_VALUE(LFXO_NODE, load_capacitors, external)
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_EXTERNAL
#elif DT_ENUM_HAS_VALUE(LFXO_NODE, load_capacitors, internal)
#define LFXO_CAP (DT_ENUM_IDX(LFXO_NODE, load_capacitance_picofarad) + 1U)
#endif
#else
#define LFXO_CAP NRF_OSCILLATORS_LFXO_CAP_EXTERNAL
#endif

and leave the binding, so load-capacitors stays not required :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: nRF Nordic nRFx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants