[U-Boot] [PATCH] tegra: implement pinmux_avoid_func()

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(+)
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);

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

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

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

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.

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

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).

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
participants (2)
-
Simon Glass
-
Stephen Warren