-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
Introduce pinctrl API to support pinctrl dts nodes #22748
Comments
Things to consider
The Linux pinctrl interface has a lot of functionality to query pinctrl configuration data. This functionality should be guarded by a config option (e.g. CONFIG_PINCTRL_RUNTIME_DTS), if implemented at all, to enable pinctrl for very memory constraint devices.
The way to generate the pinctrl configuration data for pin controller devices is key in the implementation of such a driver. Currently there is no adequate support in Zephyr. The tooling shall be clarified (gen_defines.py, another python script, ...). |
Steps to implement Steps to implement and candidate PRs for the different aspects of implementation.
|
@b0661 , out of curiosity, from what I understand you've already implemented pinctrl driver oot, could you share with us the solution you chose regarding gpio/pinctrl responsibilities partitioning? |
The solution is already in #6760. Gpio is using pinctrl as a backend for pin configuration and muxing. The OOT pinctrl driver/gpio_pinctrl drivers are currently not adapted to the new GPIO API. I may provide this after adaptations are done. The drivers are based on inline code generation - so maybe not of interest to Zephyr. |
API meeting 6th October 2020: @erwango describes the current state of the pinctrl API and bindings today. Usecases:
What do we want to achieve?
|
API meeting 13th October 2020:
@mnkp asks:
|
For reference, an overview of pinctrl: https://wiki.st.com/stm32mpu/wiki/Pinctrl_overview |
A few topics for thought:
|
I think it will be confusing if both pinctrl and gpio API allow for us to configure the same information (e.g. pull up/down, drive strength, open-drain). We should pick one of them to do it (I would lean towards GPIO). Should pinctrl focus more on the alternate mode and grouping aspects of pins? Pinctrl could be thought of as the controller for the pinmux device/operations. On a related but different note, I noticed that the gpio API does not have a way to get the current gpio flags. It would be really useful to have a getter function to determine if the gpio was currently an input/output or push-pull/open-drain. (I can create a separate issue for this, but it does seem related to this overall discussion) |
@jettr Please open an issue for fetching GPIO flags. I've considered this before but because information can be lost in translating from the |
The #28645 is an example that shows how to do it using pinctrl only. There is a variable length {0 - N} list for params. Users can complement that on board DTSI files or create their own. That shows how drivers can directly configure using pinctrl-0. Of course it is possible elaborate more and have a centralized entity to initialize all at same time. I think it is not so difficult to create a struct to store the data using DT_FOREACH like function, once params are bitfields and example shows how to handle it. It is possible inclusive store all pinctrl+flags (enabled and not at DT) that can be useful at runtime to change configurations. |
I think we need to support pull up/down, drive strength, etc. via pinctrl. If we do not, how would one specify e.g. the drive strength for a non-GPIO pin? |
Dev-Review (Nov 5):
|
API meeting 27.04.2021 @mnkp describes the options available to us a) Closer to the Linux approach a) The pinctrl driver owns an array of b) |
I was having audio problems when this was discussed, but I still cannot see how this can be made to work for Nordic devices in a space-efficient way. If we require a full array of possibilities, then it will contain NPINS * NFUNCTIONS elements, which is simply impractical even if stored in flash, and anyway most of the data will never be used by 99% of applications, even the ones that want to dynamically switch between a few possibilities. What am I missing? |
I'm also concerned about "with all the possible configurations that the application may need". Is that all existing pinmux configurations (which could include all potential tx/rx combinatory) or only the ones configured in device tree by enabled nodes? |
I think storing all possible combinations is definitely a no-go. In SoC like ST we'd be wasting a lot of ROM for nothing. I think we definitely should avoid something like https://elixir.bootlin.com/linux/latest/source/drivers/pinctrl/stm32/pinctrl-stm32mp157.c here. If I'm not wrong, what was discussed was to store all combinations listed in a board |
I rephrased it with "all the possible configurations that the application has defined in its Devicetree, which correspond to the actual physical connections on the board". So that means that you have to know at build time which pins are connected where, in some cases to more than one peripheral, or a peripheral to more than one set of pins, on the board, and that's the only set of combinations that will be encoded and stored in the pinctrl driver. For example: Pins 10 and 11 are physically wired to an FTDI chip that converts the UART signals to USB. But it turns out that there's also direct terminal access via raw UART provided in a port connector, to which pins 21 and 22 are wired. The software can, at runtime, decide when to route UART0 to either FTDI/USB or the UART connector.
Now, UART0 can probably be connected to 100s of different other pins, but we don't care because this board only cares about these 2 sets of pins, and that's the only thing we encode and store. |
@carlescufi that sounds more reasonable to me, but I think it is not compatible with "the Linux approach" option proposed by @mnkp . Or did I misunderstand? Anyway, I guess we'll see when we have a real API proposal, but it seems like we all agree that the Zephyr API needs to give the user (i.e. the board or application maintainer) full control over how much ROM to allocate to pin configuration data. If so, that addresses my concern. |
That is, to my understanding, exactly the Linux approach. Except Linux doesn't really have "boards" so they define more combos than strictly required. We can narrow it down better than them because we know exactly for which physical PCB we are building for. |
Just to reconfirm what @carlescufi has already stated. In case of option a) described here as "Closer to the Linux approach" the pinctrl would only store those combinations of pin configuration data that the application developer defined in the DTS for the given board they are developing their application for. As it was already noted here, with modern hardware, it's not feasible to store all the possible combinations of different pin configurations that are supported by the hardware. Option a) is actually more optimal regarding storage requirement since all the data are kept in one central place and made available to any interested party: driver or user application alike. In case of option b) if two different compilation modules switch pins between the same two peripherals each of the modules will keep local copies of the const struct that they will pass to |
@erwango refering to the discussion on stm32l0 power management (#35183) and regarding the pinctrl related stuff for low power mode, what do you think of putting it into the stm32 pinmux driver (drivers/pinmux/stm32/pinmux_stm32.c)? Currently the driver doesn't define an instance of device with all the callback functions but perhaps it should? Then I'm thinking we could experiment with the idea of using pm callback to put individual port instances to sleep and use gpio pinmux dts nodes for configuring what to do with different pins. This would involve a config option for PM_GPIO that will enable GPIO power save functionality. When enabled, by default it would disconnect all GPIOs upon entering powersave - but the programmer can then set specific gpio pinmux modes for certain pins or set them to be ignored when entering power saving mode. I can see that nxp has for example these nodes:
But I don't seem to find anything relevant for stm32. I think low power pin configurations are something that is closely related to gpio ports as they are configured on a specific board. It makes sense to put all configuration for low power deep sleep modes in one place. Perhaps even in power-states section in the board dts file. I think it would be way too complex to go through every single device driver and try to figure out how to configure low power modes for all the pins that it is using. |
That could be studied indeed and added if helps in pinctrl design.
Well, that's a bit different indeed on NXP and STM32 as on NXP (at least kxx) they have specific/distinct hw blocks for pinmux and gpio (please someone correct me if I'm wrong) and this is not the case on STM32 as "gpio" blocks are in charge both of pinmux and gpio.
I'm concerned this would no fit well with Device Power Management distributed method (PM_DEVICE_RUNTIME). |
@erwango interesting. I just thought of something. What about having pinctrl-[power-state] properties for all device nodes where [power-state] corresponds to the power state as specified in power-state-name. So for example: pinctrl-suspend-to-ram. The idea being that if these properties are present, then they would be automatically used. If not, then it is up to the device driver to manage power. This way the user has the choice to either use pinctrl or let the driver manage it - which works kindof like it does today with the pinctrl-0 property. |
I'd like to mention a problem with approach (b) I faced a few days ago. Let me detail the example so that the problem can be better understood. I have a custom driver called The question now: can I use Zephyr shields? Let's see what happens. In the current approach, a board is defined with the shield included, as if it was a single board:
But we can't easily use different shields because we have this:
If we had pinmux groups, as Linux, the board would be able to define the following groups:
and then the shield could finish the device definition like this:
There may be other solutions to this problem, but I thought it was worth mentioning it. |
Another option could be to use a board-specific shield overlay. |
I think @gmarull is a valid proposal and can usefull.
In this case, using approach [B], will Zephyr have only pinctrl-0 ? I mean, there is no necessity to have pinctrl-1...N, right? |
Definitely an option, even though it means duplicating the shield for every board. |
|
do we have any plan to support boot-time gpio direction setting capability? Possible benefits :
while doing some google-ing found that linux might have such a feature covered, the term called https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio.txt
|
I guess it would be a matter of adding
|
Not sure if this is the most relevant place to ask but with this can I use something like libgpiod library to list a microcontroller running zephyr via usb as a |
Introduction
In order to be able to use dts defined pin configurations, zephyr needs to propose a pinctrl API allowing to configure pins based on dts dt-bindings. This API will have to co-exist with newly introduced gpio API.
This issue is the follow up of #15611. It does not suggest solution, but is meant to launch discussions.
The Devicetree side of things is here: #29369.
Problem description
Following Linux description: "modules that control pin multiplexing or configuration parameters
such as pull-up/down, tri-state, drive-strength etc are designated as pin controllers".
A pinctrl API should allow device drivers to configure pins based on data available from dts pinctrl nodes, using pinctrl bindings (cf Linux pinctrl-bindings).
Pinctrl operation may be done by pinctrl client at boot time (initial device pin configuration), but also at run time (set pins to a power saving state).
Use cases
Considerations
Impacts of following points may vary across architectures, this list intends to be exhaustive (update if needed).
Considering dt-bindings, pinctrl operations will have a certain overlap with gpio operations:
gpio: direction(i/o/disconnect), value, bias(pull_up/down), drive(push-pull, open-drain, ..), active level(active low/high), interrupts
pinctrl: muxing, bias, drive, input, slew rate (cf Linux pincfg dt-binding)
gpio and pinctrl driver may require access to same pinctrl/gpio modules.
Aside from the pure conflict of access, impact on low power operations (controller clock switch off) should also be considered.
The Linux pinctrl interface has a lot of functionality to query pinctrl configuration data. This functionality should be guarded by a config option (e.g. CONFIG_PINCTRL_RUNTIME_DTS), if implemented at all, to enable pinctrl for very memory constraint devices.
The way to generate the pinctrl configuration data for pin controller devices is key in the implementation of such a driver. Currently there is no adequate support in Zephyr. The tooling shall be clarified (gen_defines.py, another python script, ...).
Impact on implementation
Aside from the pure API perspective (what services to offer), on the architectures impacted by some of the above points, pinctrl API implementation will raise dilemmas to resolve ahead of implementations.
Implementing pinctrl driver fully separately from gpio driver will have impact on memory footprint and make the resource sharing complex.
Other solutions could be considered (with potential impact on performance)
Steps to implement
Steps to implement and candidate PRs for the different aspects of implementation.
Pin controller API (aka. include/drivers/pinctrl.h)
Device tree pin configuration data encoding (aka. include/dts-bindings/pinctrl.h)
Pin controller device struct data format (struct config, struct data)
Device tree pin configuration data extraction (tooling)
Pin controller device struct data generation (tooling)
Pin controller device implementation for all SoCs
EDIT:
20-02-12: Added "Runtime pinctrl data access" and "Pin controller device struct data" (@b0661)
20-02-13: Added "Steps to implement" section (@b0661)
20-10-14: Added "Runtime pin configuration" following dev-review meeting.
20-10-27: Added "usecases" section following dev-review meeting
The text was updated successfully, but these errors were encountered: