-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
Move STM32 MCO configuration from Kconfig to dts #68846
Move STM32 MCO configuration from Kconfig to dts #68846
Conversation
This commit updates the STM32 HAL module to include the MCO pinctrl dtsi files. Signed-off-by: Benjamin Björnsson <[email protected]>
This commit adds a driver for the STM32 MCO clocks. The drivers contains a quirk to get around the problem of the GPIO being initialized after the clock control driver. Signed-off-by: Benjamin Björnsson <[email protected]>
This commit adds nodes for MCO clocks for the STM32C0 series. Also adds macros for selecting source and division of the MCO clocks. Adding the following to the nucleo_c031c6 board dts while running the hello_world sample gives an output clock of 6 MHz on PA9 from dividing the 48 MHz HSE with 8: &clk_mco { clocks = <&rcc 0 MCO_DIV(3)>, <&rcc 0 MCO_SEL(4)>; pinctrl-0 = <&rcc_mco_pa9>; pinctrl-names = "default"; status = "okay"; }; Signed-off-by: Benjamin Björnsson <[email protected]>
The following west manifest projects have been modified in this Pull Request:
Note: This message is automatically posted and updated by the Manifest GitHub Action. |
Great thanks @benjaminbjornsson for working on this. We'll try to provide feedback soon on the points raised. |
As a first shot, I'd propose apply pinctrl during boot and make it evolve later if required.
One possible way to workaround this could be to use this specific table zephyr/scripts/build/check_init_priorities.py Lines 49 to 53 in 4a72cb1
Same here, I propose to start w/o PM.
See my comments on this part. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note on the bindings:
clocks = <&rcc 0 MCO_DIV(3)>,
<&rcc 0 MCO_SEL(4)>;
If you're not actually using rcc as clock controller then you don't need to specify it, and you don't need to use same cells neither, so it can just be:
clocks = <MCO_DIV(3)>,
<MCO_SEL(4)>;
Or even :
clocks = <MCO_DIV(3) MCO_SEL(4)>;
or whatever finally. This would help to get rid of the initialization priority issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it more, it would be interesting to reusing the existing format and specifying the clock source:
clocks = <&rcc STM32_SRC_PLL_Q MCO_SEL(4)>,
This way, it is clearer for the user to know what the exact clock source is (or what value has been set 2 years ago w/o opening the RM). It would also prevent to set clocks source that don't exist.
Then for prescaler, 2 options:
- Use a dedicated property:
st,mco-prescaler = <MCO_DIV(3)>;
- Reuse existing rcc phandle array with a specificier:
<&rcc PRESCALER MCO_DIV(3)>;
static int clock_control_stm32_mco_init(const struct device *dev) | ||
{ | ||
const struct clock_control_stm32_mco_config *config = dev->config; | ||
|
||
for (int i = 0; i < config->pclk_len; i++) { | ||
sys_clear_bits(config->base + STM32_CLOCK_REG_GET(config->pclken->enr), | ||
STM32_CLOCK_MASK_GET(config->pclken[i].enr) | ||
<< STM32_CLOCK_SHIFT_GET(config->pclken[i].enr)); | ||
sys_set_bits(config->base + STM32_CLOCK_REG_GET(config->pclken->enr), | ||
STM32_CLOCK_VAL_GET(config->pclken[i].enr) | ||
<< STM32_CLOCK_SHIFT_GET(config->pclken[i].enr)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Altenatively, this could remain a routine of the clock_control diver (called before clock configuretion) and as such, reuse stm32_clock_control_on
internal calls.
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
@erwango @benjaminbjornsson I recently needed this functionality for a projects I was working on for the STM32G4 family (since that family doesnt have support in Zephyr for the MCO right now and wanted to do all the configuration (clock source, prescaler, pinmux) from devicetree only to find it wasnt there and that only this PR and a few other issues were addressing it. However, I think it might be nicer to take a slightly different approach wrt binding and devicetree structure which I was able to implement for the STM32G4 that should work for most STM32 (from what my quick skimming through a few reference manuals suggestions): First, very similar to this PR, I do think the MCO should sit alone in the devicetree clocks section:
Then, each board can set up its MCO has it sees fit using a style similar to the STM32 PLL (and can setup dependencies using linking it as the clock source):
As each MCO has its own set of prescalers depending on the family, the addition of the family-specific compatible is needed, the bindings for both looks like this:
To handle the setting up of the pin control, I think its best to split as was done in the PR since setting up the MCO clock source and prescaler are supposed to be done along with all the other clocks (I think some families recommend doing it before the PLL even but thats not currently happening, it could by just moving the call to
After that, its just needing to remove all the code handling the configuration from Kconfig and replacing it with code to take from the device tree instead. And restrictions on the source can be added to the code here if needed (not all familes support all sources so if we want to warn users about an invalid configuration, we would have to do what the PLLQ clock source does for all families). There are a few other hiccups here though that Ill mention below:
(Then just remove all the Kconfig variables, leaving just ones for enabling MCO and MCO2 defaulting to status okay in the devicetree) A significant problems I can see with the above is that the actual clock source for the MCO can be a few things not well represented in the device tree for some families (PLLQ, SYSCLK, PLLXDIV2). We could just do the approximate thing for all of these, but it might be a bit awkward:
Otherwise, this solution is just a bit cleaner and clearer IMO than what was done in this PR; just a bit more cleanup and trying to take a bit more advantage of the code that was there and moving everything to the device tree (would need to update all supported families to have the right MCO node(s) as well though). Minor other questions:
|
@mrrosen Thanks for digging into that. Your proposal looks globally fine but for the clock source selection, I was proposing to reuse existing clock-control API. See #68846 (comment) (which one point remaining to be settled about the presecaler). |
I think using a separate prescaler property would be the best way to handle it since it lets you limit it nicely in the binding as in my example above while being very human-reabable without macros in the device tree since it seems it can be converted nicely into STM LL macros as is done in the driver now. As for selecting the clock source, using Technically, it could do something more common to how the rcc cells would now by doing |
Sure, fine.
Ack on the complain about the syntax. Though, since it's there for other nodes, people have to deal with it anyway. Though, it'll just work and allow to provide the configuration w/o further implementation than adding the right MCO macros. It has no impact on clock control driver and all the system to check if the clock is enabled is already there. Hopefully, once #72102 is completed, we can get a more friendly syntax. Edit: Note: It is not technically possible to use LL headers in device tree such as |
This PR is intended to resolve the STM32 MCO clock issue discussed here #31912, #58443.
A couple of things come to mind while working on this so I decided to make this a draft before continuing: