diff mbox series

[v2,1/2] pinctrl: qcom: Add egpio feature support

Message ID 1635250056-20274-1-git-send-email-rnayak@codeaurora.org (mailing list archive)
State Superseded
Headers show
Series [v2,1/2] pinctrl: qcom: Add egpio feature support | expand

Commit Message

Rajendra Nayak Oct. 26, 2021, 12:07 p.m. UTC
From: Prasad Sodagudi <psodagud@codeaurora.org>

egpio is a scheme which allows special power Island Domain IOs
(LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
TLMM functions with Island Domain functions.
With this scheme, an IO can be controlled both by the cpu running
linux and the Island processor. This provides great flexibility to
re-purpose the Island IOs for regular TLMM usecases.

2 new bits are added to ctl_reg, egpio_present is a read only bit
which shows if egpio feature is available or not on a given gpio.
egpio_enable is the read/write bit and only effective if egpio_present
is 1. Once its set, the Island IO is controlled from Chip TLMM.
egpio_enable when set to 0 means the GPIO is used as Island Domain IO.

To support this we add a new function 'egpio' which can be used to
set the egpio_enable to 0, for any other TLMM controlled functions
we set the egpio_enable to 1.

Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/pinctrl/qcom/pinctrl-msm.c | 17 +++++++++++++++--
 drivers/pinctrl/qcom/pinctrl-msm.h |  4 ++++
 2 files changed, 19 insertions(+), 2 deletions(-)

Comments

Bjorn Andersson Oct. 28, 2021, 11:01 p.m. UTC | #1
On Tue 26 Oct 05:07 PDT 2021, Rajendra Nayak wrote:

> From: Prasad Sodagudi <psodagud@codeaurora.org>
> 
> egpio is a scheme which allows special power Island Domain IOs
> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
> TLMM functions with Island Domain functions.
> With this scheme, an IO can be controlled both by the cpu running
> linux and the Island processor. This provides great flexibility to
> re-purpose the Island IOs for regular TLMM usecases.
> 
> 2 new bits are added to ctl_reg, egpio_present is a read only bit
> which shows if egpio feature is available or not on a given gpio.
> egpio_enable is the read/write bit and only effective if egpio_present
> is 1. Once its set, the Island IO is controlled from Chip TLMM.
> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
> 
> To support this we add a new function 'egpio' which can be used to
> set the egpio_enable to 0, for any other TLMM controlled functions
> we set the egpio_enable to 1.
> 
> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---
>  drivers/pinctrl/qcom/pinctrl-msm.c | 17 +++++++++++++++--
>  drivers/pinctrl/qcom/pinctrl-msm.h |  4 ++++
>  2 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
> index 8476a8a..bfdba3a 100644
> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
> @@ -185,6 +185,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>  	unsigned int irq = irq_find_mapping(gc->irq.domain, group);
>  	struct irq_data *d = irq_get_irq_data(irq);
>  	unsigned int gpio_func = pctrl->soc->gpio_func;
> +	unsigned int egpio_func = pctrl->soc->egpio_func;
>  	const struct msm_pingroup *g;
>  	unsigned long flags;
>  	u32 val, mask;
> @@ -218,8 +219,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>  	raw_spin_lock_irqsave(&pctrl->lock, flags);
>  
>  	val = msm_readl_ctl(pctrl, g);
> -	val &= ~mask;
> -	val |= i << g->mux_bit;
> +
> +	if (egpio_func && i == egpio_func) {
> +		if (val & BIT(g->egpio_present))
> +			val &= ~BIT(g->egpio_enable);
> +		else
> +			return -EINVAL;

You're returning here with pctrl->lock held and irqs disabled.

> +	} else {
> +		val &= ~mask;
> +		val |= i << g->mux_bit;
> +		/* Check if egpio present and enable that feature */

I never remember if egpio_enable means apss or lpass, so I think this
comment would be better as:

		/* Claim ownership of pin if egpio capable */

> +		if (egpio_func && (val & BIT(g->egpio_present)))

Can't you drop the parenthesis around the second expression?

Regards,
Bjorn

> +			val |= BIT(g->egpio_enable);
> +	}
> +
>  	msm_writel_ctl(val, pctrl, g);
>  
>  	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
> index e31a516..b7110ac 100644
> --- a/drivers/pinctrl/qcom/pinctrl-msm.h
> +++ b/drivers/pinctrl/qcom/pinctrl-msm.h
> @@ -77,6 +77,8 @@ struct msm_pingroup {
>  	unsigned drv_bit:5;
>  
>  	unsigned od_bit:5;
> +	unsigned egpio_enable:5;
> +	unsigned egpio_present:5;
>  	unsigned oe_bit:5;
>  	unsigned in_bit:5;
>  	unsigned out_bit:5;
> @@ -119,6 +121,7 @@ struct msm_gpio_wakeirq_map {
>   *                            to be aware that their parent can't handle dual
>   *                            edge interrupts.
>   * @gpio_func: Which function number is GPIO (usually 0).
> + * @egpio_func: Which function number is eGPIO
>   */
>  struct msm_pinctrl_soc_data {
>  	const struct pinctrl_pin_desc *pins;
> @@ -136,6 +139,7 @@ struct msm_pinctrl_soc_data {
>  	unsigned int nwakeirq_map;
>  	bool wakeirq_dual_edge_errata;
>  	unsigned int gpio_func;
> +	unsigned int egpio_func;
>  };
>  
>  extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>
Stephen Boyd Oct. 29, 2021, 6:54 a.m. UTC | #2
Quoting Rajendra Nayak (2021-10-26 05:07:35)
> From: Prasad Sodagudi <psodagud@codeaurora.org>
>
> egpio is a scheme which allows special power Island Domain IOs
> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
> TLMM functions with Island Domain functions.
> With this scheme, an IO can be controlled both by the cpu running
> linux and the Island processor. This provides great flexibility to
> re-purpose the Island IOs for regular TLMM usecases.
>
> 2 new bits are added to ctl_reg, egpio_present is a read only bit
> which shows if egpio feature is available or not on a given gpio.
> egpio_enable is the read/write bit and only effective if egpio_present
> is 1. Once its set, the Island IO is controlled from Chip TLMM.
> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>
> To support this we add a new function 'egpio' which can be used to
> set the egpio_enable to 0, for any other TLMM controlled functions
> we set the egpio_enable to 1.
>
> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---

Does this supersede adding support for lpass pinctrl in this series[1]?

[1] https://lore.kernel.org/r/1635342097-2726-1-git-send-email-srivasam@codeaurora.org
Rajendra Nayak Oct. 29, 2021, 9:58 a.m. UTC | #3
On 10/29/2021 4:31 AM, Bjorn Andersson wrote:
> On Tue 26 Oct 05:07 PDT 2021, Rajendra Nayak wrote:
> 
>> From: Prasad Sodagudi <psodagud@codeaurora.org>
>>
>> egpio is a scheme which allows special power Island Domain IOs
>> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
>> TLMM functions with Island Domain functions.
>> With this scheme, an IO can be controlled both by the cpu running
>> linux and the Island processor. This provides great flexibility to
>> re-purpose the Island IOs for regular TLMM usecases.
>>
>> 2 new bits are added to ctl_reg, egpio_present is a read only bit
>> which shows if egpio feature is available or not on a given gpio.
>> egpio_enable is the read/write bit and only effective if egpio_present
>> is 1. Once its set, the Island IO is controlled from Chip TLMM.
>> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>>
>> To support this we add a new function 'egpio' which can be used to
>> set the egpio_enable to 0, for any other TLMM controlled functions
>> we set the egpio_enable to 1.
>>
>> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>> ---
>>   drivers/pinctrl/qcom/pinctrl-msm.c | 17 +++++++++++++++--
>>   drivers/pinctrl/qcom/pinctrl-msm.h |  4 ++++
>>   2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
>> index 8476a8a..bfdba3a 100644
>> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
>> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
>> @@ -185,6 +185,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>>   	unsigned int irq = irq_find_mapping(gc->irq.domain, group);
>>   	struct irq_data *d = irq_get_irq_data(irq);
>>   	unsigned int gpio_func = pctrl->soc->gpio_func;
>> +	unsigned int egpio_func = pctrl->soc->egpio_func;
>>   	const struct msm_pingroup *g;
>>   	unsigned long flags;
>>   	u32 val, mask;
>> @@ -218,8 +219,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>>   	raw_spin_lock_irqsave(&pctrl->lock, flags);
>>   
>>   	val = msm_readl_ctl(pctrl, g);
>> -	val &= ~mask;
>> -	val |= i << g->mux_bit;
>> +
>> +	if (egpio_func && i == egpio_func) {
>> +		if (val & BIT(g->egpio_present))
>> +			val &= ~BIT(g->egpio_enable);
>> +		else
>> +			return -EINVAL;
> 
> You're returning here with pctrl->lock held and irqs disabled.

argh, right. I will fix that and repost.
I wonder if I should just drop that error handling completely,
we wouldn't end up here unless the platform driver wrongly populates
a pin which does not support egpio with a egpio function.

> 
>> +	} else {
>> +		val &= ~mask;
>> +		val |= i << g->mux_bit;
>> +		/* Check if egpio present and enable that feature */
> 
> I never remember if egpio_enable means apss or lpass, so I think this
> comment would be better as:
> 
> 		/* Claim ownership of pin if egpio capable */

:) makes sense

> 
>> +		if (egpio_func && (val & BIT(g->egpio_present)))
> 
> Can't you drop the parenthesis around the second expression?

yes, will do, thanks for the review.
Rajendra Nayak Oct. 29, 2021, 10:19 a.m. UTC | #4
On 10/29/2021 12:24 PM, Stephen Boyd wrote:
> Quoting Rajendra Nayak (2021-10-26 05:07:35)
>> From: Prasad Sodagudi <psodagud@codeaurora.org>
>>
>> egpio is a scheme which allows special power Island Domain IOs
>> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
>> TLMM functions with Island Domain functions.
>> With this scheme, an IO can be controlled both by the cpu running
>> linux and the Island processor. This provides great flexibility to
>> re-purpose the Island IOs for regular TLMM usecases.
>>
>> 2 new bits are added to ctl_reg, egpio_present is a read only bit
>> which shows if egpio feature is available or not on a given gpio.
>> egpio_enable is the read/write bit and only effective if egpio_present
>> is 1. Once its set, the Island IO is controlled from Chip TLMM.
>> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>>
>> To support this we add a new function 'egpio' which can be used to
>> set the egpio_enable to 0, for any other TLMM controlled functions
>> we set the egpio_enable to 1.
>>
>> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>> ---
> 
> Does this supersede adding support for lpass pinctrl in this series[1]?

No, the driver in [1] actually manages the LPASS TLMM instance, while this patch
makes it possible for the 'same' pins to be managed by the SoC TLMM instance.
On sc7280 SoC for instance GPIO144-158 maps to LPI-GPIO-0-14, and GPIO159-174
maps to SSC-GPIO-0-15.

> [1] https://lore.kernel.org/r/1635342097-2726-1-git-send-email-srivasam@codeaurora.org
>
Stephen Boyd Oct. 29, 2021, 7:05 p.m. UTC | #5
Quoting Rajendra Nayak (2021-10-29 03:19:04)
>
>
> On 10/29/2021 12:24 PM, Stephen Boyd wrote:
> > Quoting Rajendra Nayak (2021-10-26 05:07:35)
> >> From: Prasad Sodagudi <psodagud@codeaurora.org>
> >>
> >> egpio is a scheme which allows special power Island Domain IOs
> >> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
> >> TLMM functions with Island Domain functions.
> >> With this scheme, an IO can be controlled both by the cpu running
> >> linux and the Island processor. This provides great flexibility to
> >> re-purpose the Island IOs for regular TLMM usecases.
> >>
> >> 2 new bits are added to ctl_reg, egpio_present is a read only bit
> >> which shows if egpio feature is available or not on a given gpio.
> >> egpio_enable is the read/write bit and only effective if egpio_present
> >> is 1. Once its set, the Island IO is controlled from Chip TLMM.
> >> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
> >>
> >> To support this we add a new function 'egpio' which can be used to
> >> set the egpio_enable to 0, for any other TLMM controlled functions
> >> we set the egpio_enable to 1.
> >>
> >> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
> >> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> >> ---
> >
> > Does this supersede adding support for lpass pinctrl in this series[1]?
>
> No, the driver in [1] actually manages the LPASS TLMM instance, while this patch
> makes it possible for the 'same' pins to be managed by the SoC TLMM instance.
> On sc7280 SoC for instance GPIO144-158 maps to LPI-GPIO-0-14, and GPIO159-174
> maps to SSC-GPIO-0-15.

How do we make sure that the LPASS pins are actually muxed out of the
SoC and not blocked by eGPIO in this driver muxing out the pin as a
gpio? Do they avoid conflicting with each other somehow?
Doug Anderson Nov. 1, 2021, 9:04 p.m. UTC | #6
Hi,

On Tue, Oct 26, 2021 at 5:09 AM Rajendra Nayak <rnayak@codeaurora.org> wrote:
>
> From: Prasad Sodagudi <psodagud@codeaurora.org>
>
> egpio is a scheme which allows special power Island Domain IOs
> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
> TLMM functions with Island Domain functions.
> With this scheme, an IO can be controlled both by the cpu running
> linux and the Island processor. This provides great flexibility to
> re-purpose the Island IOs for regular TLMM usecases.
>
> 2 new bits are added to ctl_reg, egpio_present is a read only bit
> which shows if egpio feature is available or not on a given gpio.
> egpio_enable is the read/write bit and only effective if egpio_present
> is 1. Once its set, the Island IO is controlled from Chip TLMM.
> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>
> To support this we add a new function 'egpio' which can be used to
> set the egpio_enable to 0, for any other TLMM controlled functions
> we set the egpio_enable to 1.
>
> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---
>  drivers/pinctrl/qcom/pinctrl-msm.c | 17 +++++++++++++++--
>  drivers/pinctrl/qcom/pinctrl-msm.h |  4 ++++
>  2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
> index 8476a8a..bfdba3a 100644
> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
> @@ -185,6 +185,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>         unsigned int irq = irq_find_mapping(gc->irq.domain, group);
>         struct irq_data *d = irq_get_irq_data(irq);
>         unsigned int gpio_func = pctrl->soc->gpio_func;
> +       unsigned int egpio_func = pctrl->soc->egpio_func;
>         const struct msm_pingroup *g;
>         unsigned long flags;
>         u32 val, mask;
> @@ -218,8 +219,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>         raw_spin_lock_irqsave(&pctrl->lock, flags);
>
>         val = msm_readl_ctl(pctrl, g);
> -       val &= ~mask;
> -       val |= i << g->mux_bit;
> +
> +       if (egpio_func && i == egpio_func) {
> +               if (val & BIT(g->egpio_present))
> +                       val &= ~BIT(g->egpio_enable);
> +               else
> +                       return -EINVAL;
> +       } else {
> +               val &= ~mask;
> +               val |= i << g->mux_bit;
> +               /* Check if egpio present and enable that feature */
> +               if (egpio_func && (val & BIT(g->egpio_present)))
> +                       val |= BIT(g->egpio_enable);
> +       }
> +
>         msm_writel_ctl(val, pctrl, g);
>
>         raw_spin_unlock_irqrestore(&pctrl->lock, flags);
> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
> index e31a516..b7110ac 100644
> --- a/drivers/pinctrl/qcom/pinctrl-msm.h
> +++ b/drivers/pinctrl/qcom/pinctrl-msm.h
> @@ -77,6 +77,8 @@ struct msm_pingroup {
>         unsigned drv_bit:5;
>
>         unsigned od_bit:5;
> +       unsigned egpio_enable:5;
> +       unsigned egpio_present:5;
>         unsigned oe_bit:5;
>         unsigned in_bit:5;
>         unsigned out_bit:5;
> @@ -119,6 +121,7 @@ struct msm_gpio_wakeirq_map {
>   *                            to be aware that their parent can't handle dual
>   *                            edge interrupts.
>   * @gpio_func: Which function number is GPIO (usually 0).
> + * @egpio_func: Which function number is eGPIO

nit: in the above, document that this is actually a _virtual_ number.
In other words it doesn't actually map to any real hardware register
setting. Also maybe document 0 here means that eGPIO isn't supported
on this SoC. ...and lastly, all the other entries in this docstring
end with a ".". Something roughly like this:

 * @egpio_func: If non-zero then this SoC supports eGPIO. Even though in
                hardware this is a mux 1-level above the TLMM, we'll treat
                it as if this is just another mux state of the TLMM. Since
                it doesn't really map to hardware, we'll allocate a virtual
                function number for eGPIO and any time we see that function
                number used we'll treat it as a request to mux away from
                our TLMM towards another owner.

Thinking about this made me look a little closer at your virtual
function number, though. On sc7280 (in the next patch) you chose
function "9" as GPIO. Things smell a little strange, though.
Apparently sc7280 was already setup for a non-virtual "function 9"
since "nfuncs" was 10. Was this just a fortunate bug that kept you
from having to touch all the sc7280 PINGROUP definitions in the next
patch, or is there actually a true "function 9" somewhere in the
hardware that we might want to someday add to Linux? If so, should we
pick eGPIO as 10?

...and then, looking further, what would happen if we picked eGPIO 10?
Should "nfuncs" include this virtual number, or not? If "nfuncs"
_does_ include this number and it bumps you over to the next
"order_base_2" then the mask calculated by msm_pinmux_set_mux() will
be wrong. If "nfuncs" _doesn't_ include this number then we should
probably document that fact, and (I suppose) change sc7280's "nfuncs"
down to 9?


-Doug
Rajendra Nayak Nov. 2, 2021, 10:38 a.m. UTC | #7
On 10/30/2021 12:35 AM, Stephen Boyd wrote:
> Quoting Rajendra Nayak (2021-10-29 03:19:04)
>>
>>
>> On 10/29/2021 12:24 PM, Stephen Boyd wrote:
>>> Quoting Rajendra Nayak (2021-10-26 05:07:35)
>>>> From: Prasad Sodagudi <psodagud@codeaurora.org>
>>>>
>>>> egpio is a scheme which allows special power Island Domain IOs
>>>> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
>>>> TLMM functions with Island Domain functions.
>>>> With this scheme, an IO can be controlled both by the cpu running
>>>> linux and the Island processor. This provides great flexibility to
>>>> re-purpose the Island IOs for regular TLMM usecases.
>>>>
>>>> 2 new bits are added to ctl_reg, egpio_present is a read only bit
>>>> which shows if egpio feature is available or not on a given gpio.
>>>> egpio_enable is the read/write bit and only effective if egpio_present
>>>> is 1. Once its set, the Island IO is controlled from Chip TLMM.
>>>> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>>>>
>>>> To support this we add a new function 'egpio' which can be used to
>>>> set the egpio_enable to 0, for any other TLMM controlled functions
>>>> we set the egpio_enable to 1.
>>>>
>>>> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
>>>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>>>> ---
>>>
>>> Does this supersede adding support for lpass pinctrl in this series[1]?
>>
>> No, the driver in [1] actually manages the LPASS TLMM instance, while this patch
>> makes it possible for the 'same' pins to be managed by the SoC TLMM instance.
>> On sc7280 SoC for instance GPIO144-158 maps to LPI-GPIO-0-14, and GPIO159-174
>> maps to SSC-GPIO-0-15.
> 
> How do we make sure that the LPASS pins are actually muxed out of the
> SoC and not blocked by eGPIO in this driver muxing out the pin as a
> gpio? Do they avoid conflicting with each other somehow?

No, currently they don't. The default value of egpio_enable is 0, so
if SoC TLMM grabs it first and sets it to 1 and then the LPASS TLMM tries
to grab it, perhaps it can find out and throw and error, though I don;t
think it does that today.
I am not sure how this can be caught when its the other way round (LPASS grabs it first)
Rajendra Nayak Nov. 2, 2021, 11:02 a.m. UTC | #8
On 11/2/2021 2:34 AM, Doug Anderson wrote:
> Hi,
> 
> On Tue, Oct 26, 2021 at 5:09 AM Rajendra Nayak <rnayak@codeaurora.org> wrote:
>>
>> From: Prasad Sodagudi <psodagud@codeaurora.org>
>>
>> egpio is a scheme which allows special power Island Domain IOs
>> (LPASS,SSC) to be reused as regular chip GPIOs by muxing regular
>> TLMM functions with Island Domain functions.
>> With this scheme, an IO can be controlled both by the cpu running
>> linux and the Island processor. This provides great flexibility to
>> re-purpose the Island IOs for regular TLMM usecases.
>>
>> 2 new bits are added to ctl_reg, egpio_present is a read only bit
>> which shows if egpio feature is available or not on a given gpio.
>> egpio_enable is the read/write bit and only effective if egpio_present
>> is 1. Once its set, the Island IO is controlled from Chip TLMM.
>> egpio_enable when set to 0 means the GPIO is used as Island Domain IO.
>>
>> To support this we add a new function 'egpio' which can be used to
>> set the egpio_enable to 0, for any other TLMM controlled functions
>> we set the egpio_enable to 1.
>>
>> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
>> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>> ---
>>   drivers/pinctrl/qcom/pinctrl-msm.c | 17 +++++++++++++++--
>>   drivers/pinctrl/qcom/pinctrl-msm.h |  4 ++++
>>   2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
>> index 8476a8a..bfdba3a 100644
>> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
>> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
>> @@ -185,6 +185,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>>          unsigned int irq = irq_find_mapping(gc->irq.domain, group);
>>          struct irq_data *d = irq_get_irq_data(irq);
>>          unsigned int gpio_func = pctrl->soc->gpio_func;
>> +       unsigned int egpio_func = pctrl->soc->egpio_func;
>>          const struct msm_pingroup *g;
>>          unsigned long flags;
>>          u32 val, mask;
>> @@ -218,8 +219,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
>>          raw_spin_lock_irqsave(&pctrl->lock, flags);
>>
>>          val = msm_readl_ctl(pctrl, g);
>> -       val &= ~mask;
>> -       val |= i << g->mux_bit;
>> +
>> +       if (egpio_func && i == egpio_func) {
>> +               if (val & BIT(g->egpio_present))
>> +                       val &= ~BIT(g->egpio_enable);
>> +               else
>> +                       return -EINVAL;
>> +       } else {
>> +               val &= ~mask;
>> +               val |= i << g->mux_bit;
>> +               /* Check if egpio present and enable that feature */
>> +               if (egpio_func && (val & BIT(g->egpio_present)))
>> +                       val |= BIT(g->egpio_enable);
>> +       }
>> +
>>          msm_writel_ctl(val, pctrl, g);
>>
>>          raw_spin_unlock_irqrestore(&pctrl->lock, flags);
>> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
>> index e31a516..b7110ac 100644
>> --- a/drivers/pinctrl/qcom/pinctrl-msm.h
>> +++ b/drivers/pinctrl/qcom/pinctrl-msm.h
>> @@ -77,6 +77,8 @@ struct msm_pingroup {
>>          unsigned drv_bit:5;
>>
>>          unsigned od_bit:5;
>> +       unsigned egpio_enable:5;
>> +       unsigned egpio_present:5;
>>          unsigned oe_bit:5;
>>          unsigned in_bit:5;
>>          unsigned out_bit:5;
>> @@ -119,6 +121,7 @@ struct msm_gpio_wakeirq_map {
>>    *                            to be aware that their parent can't handle dual
>>    *                            edge interrupts.
>>    * @gpio_func: Which function number is GPIO (usually 0).
>> + * @egpio_func: Which function number is eGPIO
> 
> nit: in the above, document that this is actually a _virtual_ number.
> In other words it doesn't actually map to any real hardware register
> setting. Also maybe document 0 here means that eGPIO isn't supported
> on this SoC. ...and lastly, all the other entries in this docstring
> end with a ".". Something roughly like this:
> 
>   * @egpio_func: If non-zero then this SoC supports eGPIO. Even though in
>                  hardware this is a mux 1-level above the TLMM, we'll treat
>                  it as if this is just another mux state of the TLMM. Since
>                  it doesn't really map to hardware, we'll allocate a virtual
>                  function number for eGPIO and any time we see that function
>                  number used we'll treat it as a request to mux away from
>                  our TLMM towards another owner.

Thanks Doug, this sounds perfect, I'll copy-paste it :)

> Thinking about this made me look a little closer at your virtual
> function number, though. On sc7280 (in the next patch) you chose
> function "9" as GPIO. Things smell a little strange, though.
> Apparently sc7280 was already setup for a non-virtual "function 9"
> since "nfuncs" was 10. Was this just a fortunate bug that kept you
> from having to touch all the sc7280 PINGROUP definitions in the next
> patch, or is there actually a true "function 9" somewhere in the
> hardware that we might want to someday add to Linux? If so, should we
> pick eGPIO as 10?

Right, I did start off thinking I would need to add a new function, and
deal with changing all the PINGROUP definitions, and worry about all the
stuff that you mentioned below, but then I realized function 9 was actually
unused on all sc7280 pins (and I did look at the couple other SoCs usptream
which support egpio which also had the same pattern) so decided to just reuse
function 9 and avoid dealing with all the mess that would result
with adding a new virtual function ¯\_(ツ)_/¯

> ...and then, looking further, what would happen if we picked eGPIO 10?
> Should "nfuncs" include this virtual number, or not? If "nfuncs"
> _does_ include this number and it bumps you over to the next
> "order_base_2" then the mask calculated by msm_pinmux_set_mux() will
> be wrong. If "nfuncs" _doesn't_ include this number then we should
> probably document that fact, and (I suppose) change sc7280's "nfuncs"
> down to 9?
> 
> 
> -Doug
>
diff mbox series

Patch

diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 8476a8a..bfdba3a 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -185,6 +185,7 @@  static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
 	unsigned int irq = irq_find_mapping(gc->irq.domain, group);
 	struct irq_data *d = irq_get_irq_data(irq);
 	unsigned int gpio_func = pctrl->soc->gpio_func;
+	unsigned int egpio_func = pctrl->soc->egpio_func;
 	const struct msm_pingroup *g;
 	unsigned long flags;
 	u32 val, mask;
@@ -218,8 +219,20 @@  static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
 	raw_spin_lock_irqsave(&pctrl->lock, flags);
 
 	val = msm_readl_ctl(pctrl, g);
-	val &= ~mask;
-	val |= i << g->mux_bit;
+
+	if (egpio_func && i == egpio_func) {
+		if (val & BIT(g->egpio_present))
+			val &= ~BIT(g->egpio_enable);
+		else
+			return -EINVAL;
+	} else {
+		val &= ~mask;
+		val |= i << g->mux_bit;
+		/* Check if egpio present and enable that feature */
+		if (egpio_func && (val & BIT(g->egpio_present)))
+			val |= BIT(g->egpio_enable);
+	}
+
 	msm_writel_ctl(val, pctrl, g);
 
 	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index e31a516..b7110ac 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -77,6 +77,8 @@  struct msm_pingroup {
 	unsigned drv_bit:5;
 
 	unsigned od_bit:5;
+	unsigned egpio_enable:5;
+	unsigned egpio_present:5;
 	unsigned oe_bit:5;
 	unsigned in_bit:5;
 	unsigned out_bit:5;
@@ -119,6 +121,7 @@  struct msm_gpio_wakeirq_map {
  *                            to be aware that their parent can't handle dual
  *                            edge interrupts.
  * @gpio_func: Which function number is GPIO (usually 0).
+ * @egpio_func: Which function number is eGPIO
  */
 struct msm_pinctrl_soc_data {
 	const struct pinctrl_pin_desc *pins;
@@ -136,6 +139,7 @@  struct msm_pinctrl_soc_data {
 	unsigned int nwakeirq_map;
 	bool wakeirq_dual_edge_errata;
 	unsigned int gpio_func;
+	unsigned int egpio_func;
 };
 
 extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;