zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.17k stars 6.23k forks source link

Possibility to define pinmux item for Pin Control as a plain input/output #42530

Closed r2r0 closed 2 years ago

r2r0 commented 2 years ago

Is your enhancement proposal related to a problem? Please describe. My device driver uses pins which need to switch between different pin functions which seems to be perfectly suited job for Pin Control API, but I cannot find a way to switch pin between special function (i.e., UART TX ) and "simple" GPIO function (i.e., input with pull-up). Unfortunately, it looks that Pin Control API allows only to switch between special pin functions which make it usable only in a very limited way for the cases like described above.

Describe the solution you'd like pinmux nodes used to define pinctrl-N nodes should also accept configuration as normal GPIO pins i.e., GPIO_INPUT | GPIO_PULL_UP.

Describe alternatives you've considered GPIO API does not offer configuration options for special pin functions, so this kind of function change can be only achieved using SOC specific low-level functions.

Additional context My platform is STM32WB.

gmarull commented 2 years ago

How are you planning to control the pins when in "GPIO mode"? pinctrl API only allows to set states, but doesn't offer gpio-like access. I'd also like to understand the use-case.

r2r0 commented 2 years ago

The idea is to switch between different pin control states (pinmux setups) to achive functionality required for specific device driver mode. I.e. in one of modes device driver needs pin TX functionality associated with SOC HW but in the another mode it requires just to keep polarization of the pin (using pull-up). If it would be possible by the meaning of Pin Control API then SOC HW cell registers not need to be touched during device driver mode switching and only pinmux access will be required (in a portable way without using a low level library). Also it will be sometimes quite usefull to be able to use Pin Control to disconnect pin (Hi-Z) in some modes (i.e sleep).

gmarull commented 2 years ago

The idea is to switch between different pin control states (pinmux setups) to achive functionality required for specific device driver mode.

This is already possible, and one can implement arbitrary custom states.

I.e. in one of modes device driver needs pin TX functionality associated with SOC HW but in the another mode it requires just to keep polarization of the pin (using pull-up).

Note that states are self-contained, so each state contains all pin configuration parameters. You can't define a state that just configures pull-up.

If it would be possible by the meaning of Pin Control API then SOC HW cell registers not need to be touched during device driver mode switching and only pinmux access will be required (in a portable way without using a low level library).

Also it will be sometimes quite usefull to be able to use Pin Control to disconnect pin (Hi-Z) in some modes (i.e sleep).

This is already possible, maybe some platforms haven't enabled the capability yet, though. https://github.com/zephyrproject-rtos/hal_stm32/pull/126

r2r0 commented 2 years ago

Note that states are self-contained, so each state contains all pin configuration parameters. You can't define a state that just configures pull-up.

In fact I need not only add pull-up but I need to reconfigure pinmux for pin - from alternate (special) function to I/O function. These are separate pin modes in pinmux register and maybe I am wrong but it seems natural and consistent to use Pin Control API for such switching. In one mode I would like to define HW RX pinmux setup and in other mode I would like to define "plain" I/O pinmux setup - there are different pinmux (as in registers) contents.

This is already possible, maybe some platforms haven't enabled the capability yet, though. zephyrproject-rtos/hal_stm32#126

For my platform I found only ANALOG function, which is not necessary the same like Hi-Z but of course I will dig into it as a sidequest.

gmarull commented 2 years ago

Note that states are self-contained, so each state contains all pin configuration parameters. You can't define a state that just configures pull-up.

In fact I need not only add pull-up but I need to reconfigure pinmux for pin - from alternate (special) function to I/O function.

Then, what is the purpose of moving to I/O if pin can't be controlled with pinctrl API? I still fail to see the use case here. One case could be I2C recover, but you'd still need to define *-gpios properties and use GPIO API to manually control the pins while in such "gpio" state.

For my platform I found only ANALOG function, which is not necessary the same like Hi-Z but of course I will dig into it as a sidequest.

Available pin configuration parameters is really vendor-specific, the pinctrl bindings are the best source of truth right now.

r2r0 commented 2 years ago

Supposing that I will use GPIO API flow for described case can be like this:

It looks to be not a big deal, but I need do define each pin in two separate places in DT using different syntax and in case of change in module logic I need to synchronize code changes for 2 different APIs. This apply for each pin and for each new HW versions of board - this means that the possibility of making mistake is pretty high.

I understand that some design principles limits functions scope for single module for a good reason but in this case Pin Control is supposed not to drive pin level or something like that but just change pin mode. In mentioned case change of pin polarization (level) is just a result of changing pin mode i.e., like changing mode to I2C with automatic pull-up.

BTW> Thanks for you quick and patient responses.

gmarull commented 2 years ago

Supposing that I will use GPIO API flow for described case can be like this:

  • initialize device pin(s) using default state (Pin Control API)
  • do something related to core device functionality which changes device state (pin is driven by SOC HW)
  • reinitialize pin(s) to GPIO mode (GPIO API)
  • do something related to core device functionality which changes device state not touching initialized GPIO pin(s) at all
  • reinitialize device using default state (Pin Control API)
  • ....

For this workflow, you don't need GPIO API, you can use pinctrl. The only thing you'll need is support from your vendor so that their pinctrl driver allows configuring a pin as regular GPIO IN/OUT (for STM32 you're now allowed to use AF/ANALOG modes only). I'm still curious on why you require > * do something related to core device functionality which changes device state not touching initialized GPIO pin(s) at all though.

r2r0 commented 2 years ago

Hmm... I am a little confused now. I asked recently about this feature on Zephyr users group and I got (private reply from ST) that it is not possible and: "... this was requested before and pushed back by GPIO maintainer ..." Does it mean that you do not see any problem with adding to (vendor specific) pinctrl driver relgular GPIO modes?

gmarull commented 2 years ago

Hmm... I am a little confused now. I asked recently about this feature on Zephyr users group and I got (private reply from ST) that it is not possible and: "... this was requested before and pushed back by GPIO maintainer ..." Does it mean that you do not see any problem with add to (vendor specific) pinctrl driver relgular GPIO modes?

I guess the first step is to define the use-case, I still haven't been able to understand why this is required. A concrete example would help.

r2r0 commented 2 years ago

My use case: USART is configured in ISO 7816 mode (smart card communication protocol). To allow user to connect more than one card there is used smart card multiplexer ASIC. This chip consumes relatively big amount of power, so it is desirable to enable it only after card insertion is detected (it is achieved using simple microswitch and GPIO level detection). Unfortunately, to achieve low power consumption when card multiplexer is disabled, this ASIC requires (ISO 7816) pins with specific polarization. Of course, this can be done using additional HW but it will increase BOM. So, there are two (in reality more) states of device: card(s) inserted, and no cards are present and they correspond to two different setup/modes for ISO 7816 pins: USART (ISO7816 communication) and plain GPIO (signals polarization).

gmarull commented 2 years ago

First I'd check if enabling pull-ups/downs is sufficient while still holding the AF mode (you'll need to replicate nodes since default ones can't be re-used for other states). If not, then you'll need to ask STM32 maintainers if they are willing to support GPIO IN/OUT modes via pinctrl. In the end, this is something not related to the pinctrl API really, since it just applies states.

erwango commented 2 years ago

@r2r0 I had a look to what was supported on STM32 Linux pinctrl bindings and could likely be implemented in Zephyr as well (I still need to confirm this), something as follow:

            {
                     pinmux = <STM32_PINMUX('A', 9, GPIO)>;
            };

By default, state would be input. To drive the line, additional boolean properties output-low and output-high would be available. If doable, would it solve your case ?

r2r0 commented 2 years ago

@erwango Yes, it looks that it will solve my case(s). GPIO combined with already available ANALOG binding will be everything what I need. BTW> Will I still be able to use bias-pull-[up|down]?

myst729 commented 1 month ago

Is this possible for analog mux on nRF52 chips? (e.g. CD74HC4067 /w nRF52840)