diff mbox

[U-Boot] tegra: implement pinmux_avoid_func()

Message ID 1358871699-31964-1-git-send-email-swarren@wwwdotorg.org
State Deferred
Delegated to: Tom Warren
Headers show

Commit Message

Stephen Warren Jan. 22, 2013, 4:21 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

This selects the "safe" (non-conflicting) mux function for a pin group
if the current setting matches the specified function.

Many signals can be routed to or from multiple different groups. Each
signal must be routed to or from only a single group at a given time.
Hence, if we program a particular group for a function, we must ensure
no other group is programmed to that same function first. This API
makes this easy.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
This patch will need updating due to the recently added Tegra30 support.
However, I'm posting it for Lucas, since his NAND patches can probably
benefit from this.

 arch/arm/cpu/tegra20-common/pinmux.c       |   23 +++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra20/pinmux.h |    6 ++++++
 2 files changed, 29 insertions(+)

Comments

Simon Glass Jan. 22, 2013, 9:13 p.m. UTC | #1
Hi Stephen,

On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> This selects the "safe" (non-conflicting) mux function for a pin group
> if the current setting matches the specified function.
>
> Many signals can be routed to or from multiple different groups. Each
> signal must be routed to or from only a single group at a given time.
> Hence, if we program a particular group for a function, we must ensure
> no other group is programmed to that same function first. This API
> makes this easy.

What is the intended use of this function? (sorry, yes, I am confused :-)

>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> This patch will need updating due to the recently added Tegra30 support.
> However, I'm posting it for Lucas, since his NAND patches can probably
> benefit from this.
>
>  arch/arm/cpu/tegra20-common/pinmux.c       |   23 +++++++++++++++++++++++
>  arch/arm/include/asm/arch-tegra20/pinmux.h |    6 ++++++
>  2 files changed, 29 insertions(+)
>
> diff --git a/arch/arm/cpu/tegra20-common/pinmux.c b/arch/arm/cpu/tegra20-common/pinmux.c
> index 5ad2121..47179f3 100644
> --- a/arch/arm/cpu/tegra20-common/pinmux.c
> +++ b/arch/arm/cpu/tegra20-common/pinmux.c
> @@ -554,6 +554,29 @@ void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
>         writel(reg, muxctl);
>  }
>
> +static enum pmux_func pinmux_get_func(enum pmux_pingrp pin)
> +{
> +       struct pmux_tri_ctlr *pmt =
> +                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
> +       enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
> +       u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
> +       u32 reg;
> +
> +       reg = readl(muxctl);
> +       reg >>= MUXCTL_SHIFT(mux_id);
> +       reg &= 3;
> +
> +       return tegra_soc_pingroups[pin].funcs[reg];
> +}
> +
> +void pinmux_avoid_func(enum pmux_pingrp pin, enum pmux_func avoid)
> +{
> +       if (pinmux_get_func(pin) != avoid)
> +               return;

Is this an error - does the caller need to know?

> +
> +       pinmux_set_func(pin, tegra_soc_pingroups[pin].func_safe);
> +}
> +
>  void pinmux_config_pingroup(const struct pingroup_config *config)
>  {
>         enum pmux_pingrp pin = config->pingroup;
> diff --git a/arch/arm/include/asm/arch-tegra20/pinmux.h b/arch/arm/include/asm/arch-tegra20/pinmux.h
> index a9b4eda..d36e18e 100644
> --- a/arch/arm/include/asm/arch-tegra20/pinmux.h
> +++ b/arch/arm/include/asm/arch-tegra20/pinmux.h
> @@ -337,6 +337,12 @@ void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd);
>  /* Set the mux function for a pin group */
>  void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func);
>
> +/*
> + * Select the "safe" (non-conflicting) mux function for a pin group if the
> + * current setting matches the specified function.
> + */

What does it do when it doesn't match, and perhaps comment when you
might find this function useful?

> +void pinmux_avoid_func(enum pmux_pingrp pin, enum pmux_func func);
> +
>  /* Set the complete configuration for a pin group */
>  void pinmux_config_pingroup(const struct pingroup_config *config);
>
> --
> 1.7.10.4
>

Regards,
Simon
Stephen Warren Jan. 22, 2013, 9:26 p.m. UTC | #2
On 01/22/2013 02:13 PM, Simon Glass wrote:
> Hi Stephen,
> 
> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> This selects the "safe" (non-conflicting) mux function for a pin group
>> if the current setting matches the specified function.
>>
>> Many signals can be routed to or from multiple different groups. Each
>> signal must be routed to or from only a single group at a given time.
>> Hence, if we program a particular group for a function, we must ensure
>> no other group is programmed to that same function first. This API
>> makes this easy.
> 
> What is the intended use of this function? (sorry, yes, I am confused :-)

It's a safer way of doing this:
"tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
http://lists.denx.de/pipermail/u-boot/2013-January/144612.html

i.e. it address the concerns I raised here:
http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
Simon Glass Jan. 22, 2013, 9:42 p.m. UTC | #3
Hi Stephen,

On Tue, Jan 22, 2013 at 1:26 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 01/22/2013 02:13 PM, Simon Glass wrote:
>> Hi Stephen,
>>
>> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> From: Stephen Warren <swarren@nvidia.com>
>>>
>>> This selects the "safe" (non-conflicting) mux function for a pin group
>>> if the current setting matches the specified function.
>>>
>>> Many signals can be routed to or from multiple different groups. Each
>>> signal must be routed to or from only a single group at a given time.
>>> Hence, if we program a particular group for a function, we must ensure
>>> no other group is programmed to that same function first. This API
>>> makes this easy.
>>
>> What is the intended use of this function? (sorry, yes, I am confused :-)
>
> It's a safer way of doing this:
> "tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
> http://lists.denx.de/pipermail/u-boot/2013-January/144612.html
>
> i.e. it address the concerns I raised here:
> http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
>

OK thank you. So is your function only intended for use with T20?

Regards,
Simon
Stephen Warren Jan. 22, 2013, 10:14 p.m. UTC | #4
On 01/22/2013 02:42 PM, Simon Glass wrote:
> Hi Stephen,
> 
> On Tue, Jan 22, 2013 at 1:26 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 01/22/2013 02:13 PM, Simon Glass wrote:
>>> Hi Stephen,
>>>
>>> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>
>>>> This selects the "safe" (non-conflicting) mux function for a pin group
>>>> if the current setting matches the specified function.
>>>>
>>>> Many signals can be routed to or from multiple different groups. Each
>>>> signal must be routed to or from only a single group at a given time.
>>>> Hence, if we program a particular group for a function, we must ensure
>>>> no other group is programmed to that same function first. This API
>>>> makes this easy.
>>>
>>> What is the intended use of this function? (sorry, yes, I am confused :-)
>>
>> It's a safer way of doing this:
>> "tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
>> http://lists.denx.de/pipermail/u-boot/2013-January/144612.html
>>
>> i.e. it address the concerns I raised here:
>> http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
>>
> 
> OK thank you. So is your function only intended for use with T20?

No, I imagine that it should be used for all Tegras; I just wrote it
long enough ago that there was only Tegra20 at the time. I assume that
if Lucas wants to use this function as a pre-cursor to his NAND pinmux
change, he'll update it for whatever Tegra versions are checked in at
the time first.

Sorry, I'm being lazy/over-worked.
Simon Glass Jan. 23, 2013, 12:03 a.m. UTC | #5
Hi Stephen,

On Tue, Jan 22, 2013 at 2:14 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 01/22/2013 02:42 PM, Simon Glass wrote:
>> Hi Stephen,
>>
>> On Tue, Jan 22, 2013 at 1:26 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 01/22/2013 02:13 PM, Simon Glass wrote:
>>>> Hi Stephen,
>>>>
>>>> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>
>>>>> This selects the "safe" (non-conflicting) mux function for a pin group
>>>>> if the current setting matches the specified function.
>>>>>
>>>>> Many signals can be routed to or from multiple different groups. Each
>>>>> signal must be routed to or from only a single group at a given time.
>>>>> Hence, if we program a particular group for a function, we must ensure
>>>>> no other group is programmed to that same function first. This API
>>>>> makes this easy.
>>>>
>>>> What is the intended use of this function? (sorry, yes, I am confused :-)
>>>
>>> It's a safer way of doing this:
>>> "tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
>>> http://lists.denx.de/pipermail/u-boot/2013-January/144612.html
>>>
>>> i.e. it address the concerns I raised here:
>>> http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
>>>
>>
>> OK thank you. So is your function only intended for use with T20?
>
> No, I imagine that it should be used for all Tegras; I just wrote it
> long enough ago that there was only Tegra20 at the time. I assume that
> if Lucas wants to use this function as a pre-cursor to his NAND pinmux
> change, he'll update it for whatever Tegra versions are checked in at
> the time first.
>
Thanks, I get it.

Should Lucas consider adding a warning or some sort of indication that
the function did nothing?

> Sorry, I'm being lazy/over-worked.
>
:-)

Regards,
Simon
Stephen Warren Jan. 23, 2013, 12:21 a.m. UTC | #6
On 01/22/2013 05:03 PM, Simon Glass wrote:
> Hi Stephen,
> 
> On Tue, Jan 22, 2013 at 2:14 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 01/22/2013 02:42 PM, Simon Glass wrote:
>>> Hi Stephen,
>>>
>>> On Tue, Jan 22, 2013 at 1:26 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 01/22/2013 02:13 PM, Simon Glass wrote:
>>>>> Hi Stephen,
>>>>>
>>>>> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>
>>>>>> This selects the "safe" (non-conflicting) mux function for a pin group
>>>>>> if the current setting matches the specified function.
>>>>>>
>>>>>> Many signals can be routed to or from multiple different groups. Each
>>>>>> signal must be routed to or from only a single group at a given time.
>>>>>> Hence, if we program a particular group for a function, we must ensure
>>>>>> no other group is programmed to that same function first. This API
>>>>>> makes this easy.
>>>>>
>>>>> What is the intended use of this function? (sorry, yes, I am confused :-)
>>>>
>>>> It's a safer way of doing this:
>>>> "tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
>>>> http://lists.denx.de/pipermail/u-boot/2013-January/144612.html
>>>>
>>>> i.e. it address the concerns I raised here:
>>>> http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
>>>>
>>>
>>> OK thank you. So is your function only intended for use with T20?
>>
>> No, I imagine that it should be used for all Tegras; I just wrote it
>> long enough ago that there was only Tegra20 at the time. I assume that
>> if Lucas wants to use this function as a pre-cursor to his NAND pinmux
>> change, he'll update it for whatever Tegra versions are checked in at
>> the time first.
>>
> Thanks, I get it.
> 
> Should Lucas consider adding a warning or some sort of indication that
> the function did nothing?

Do you mean on Tegra30 where it isn't implemented yet (no - I'd expect
to see this implemented instead) or when the current function programmed
into HW already doesn't match the value one is trying to avoid (no - I'd
expect this to be quite common).
Simon Glass Jan. 23, 2013, 12:26 a.m. UTC | #7
Hi Stephen,

On Tue, Jan 22, 2013 at 4:21 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 01/22/2013 05:03 PM, Simon Glass wrote:
>> Hi Stephen,
>>
>> On Tue, Jan 22, 2013 at 2:14 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 01/22/2013 02:42 PM, Simon Glass wrote:
>>>> Hi Stephen,
>>>>
>>>> On Tue, Jan 22, 2013 at 1:26 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>> On 01/22/2013 02:13 PM, Simon Glass wrote:
>>>>>> Hi Stephen,
>>>>>>
>>>>>> On Tue, Jan 22, 2013 at 8:21 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>
>>>>>>> This selects the "safe" (non-conflicting) mux function for a pin group
>>>>>>> if the current setting matches the specified function.
>>>>>>>
>>>>>>> Many signals can be routed to or from multiple different groups. Each
>>>>>>> signal must be routed to or from only a single group at a given time.
>>>>>>> Hence, if we program a particular group for a function, we must ensure
>>>>>>> no other group is programmed to that same function first. This API
>>>>>>> makes this easy.
>>>>>>
>>>>>> What is the intended use of this function? (sorry, yes, I am confused :-)
>>>>>
>>>>> It's a safer way of doing this:
>>>>> "tegra: pinmux: fix FUNCMUX_NDFLASH_KBC_8_BIT"
>>>>> http://lists.denx.de/pipermail/u-boot/2013-January/144612.html
>>>>>
>>>>> i.e. it address the concerns I raised here:
>>>>> http://lists.denx.de/pipermail/u-boot/2013-January/144713.html
>>>>>
>>>>
>>>> OK thank you. So is your function only intended for use with T20?
>>>
>>> No, I imagine that it should be used for all Tegras; I just wrote it
>>> long enough ago that there was only Tegra20 at the time. I assume that
>>> if Lucas wants to use this function as a pre-cursor to his NAND pinmux
>>> change, he'll update it for whatever Tegra versions are checked in at
>>> the time first.
>>>
>> Thanks, I get it.
>>
>> Should Lucas consider adding a warning or some sort of indication that
>> the function did nothing?
>
> Do you mean on Tegra30 where it isn't implemented yet (no - I'd expect
> to see this implemented instead) or when the current function programmed
> into HW already doesn't match the value one is trying to avoid (no - I'd
> expect this to be quite common).
>

The latter - ok that's fine.

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/cpu/tegra20-common/pinmux.c b/arch/arm/cpu/tegra20-common/pinmux.c
index 5ad2121..47179f3 100644
--- a/arch/arm/cpu/tegra20-common/pinmux.c
+++ b/arch/arm/cpu/tegra20-common/pinmux.c
@@ -554,6 +554,29 @@  void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
 	writel(reg, muxctl);
 }
 
+static enum pmux_func pinmux_get_func(enum pmux_pingrp pin)
+{
+	struct pmux_tri_ctlr *pmt =
+			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
+	u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
+	u32 reg;
+
+	reg = readl(muxctl);
+	reg >>= MUXCTL_SHIFT(mux_id);
+	reg &= 3;
+
+	return tegra_soc_pingroups[pin].funcs[reg];
+}
+
+void pinmux_avoid_func(enum pmux_pingrp pin, enum pmux_func avoid)
+{
+	if (pinmux_get_func(pin) != avoid)
+		return;
+
+	pinmux_set_func(pin, tegra_soc_pingroups[pin].func_safe);
+}
+
 void pinmux_config_pingroup(const struct pingroup_config *config)
 {
 	enum pmux_pingrp pin = config->pingroup;
diff --git a/arch/arm/include/asm/arch-tegra20/pinmux.h b/arch/arm/include/asm/arch-tegra20/pinmux.h
index a9b4eda..d36e18e 100644
--- a/arch/arm/include/asm/arch-tegra20/pinmux.h
+++ b/arch/arm/include/asm/arch-tegra20/pinmux.h
@@ -337,6 +337,12 @@  void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd);
 /* Set the mux function for a pin group */
 void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func);
 
+/*
+ * Select the "safe" (non-conflicting) mux function for a pin group if the
+ * current setting matches the specified function.
+ */
+void pinmux_avoid_func(enum pmux_pingrp pin, enum pmux_func func);
+
 /* Set the complete configuration for a pin group */
 void pinmux_config_pingroup(const struct pingroup_config *config);