FanWu,
Questions about the Linux kernel should be sent to the public mailing
lists so that anyone can see the discussion, join in, and/or see the
result of the discussion in the list archives. Also, please use
plain-text email, since that makes it easier to read and reply.
The problem with simply calling pinmux_disable_setting() in all cases as
you propose is that (at least on some HW), calling
pinmux_disable_setting() may cause the HW to be programmed, and that may
glitch the pin. In other words, the current code does this:
old mux function -> new mux function
Presumably the board/SoC HW designers have validated that such
transitions don't cause invalid signals to be emitted.
However, your proposal might do:
old mux function -> disabled state -> new mux function
That introduces a potential extra HW state (whatever
pinmux_disable_state() programs) which could cause glitches on the pin,
which could cause problems.
So, I think what we need is your option (1), although some care will be
needed to avoid too much nested iteration.
On 05/04/2014 08:12 PM, FanWu wrote:
On 04/17/2014 04:05 PM, Will Wu wrote:
On 04/14/2014 11:27 AM, FanWu wrote:Dear Linus,
Dear, Linus Walleij
Dear, Linus Walleij
Sorry to bother you. I am a Linux Kernel developer in Marvell.
Recently, I am focusing on the Pinctrl related driver development and
found there seems a possible issue lying in Pinctrl related framework.
I will try to make myself clear and please help to review the
following statement.
In the following I will listed what I found and the suggested code
change in the mentioned part.
If there is a DTS node is similar to the following one(only the
pinctrl related part is listed in the node content), in current
Kernel Pinctrl solution, it is possible that the "desc->mux_usecount"
for each physical pin is kept being added without any chance to be
decreased, when the Pin's owner wants to do Pin's state switching in
their user scenario.
component a {
...
pinctrl-names = "default", "sleep";
pinctrl-0 = <&a_grp_setting_a &*c_grp_setting*>;
pinctrl-1 = <&a_grp_setting_b &*c_grp_setting*>;
...
}
The "c_grp_setting" config node is totally same in two pinctrl state.
The only difference b/t the two Pinctrl states is the
"a_group_setting". Pinctrl-0 uses "a_grp_setting_a" setting while
pinctrl-1 uses "a_grp_setting_b" setting.
If the pins' owner wants to switch the pins' state in some cases, he
needs to do the following sequence:
pin = pinctrl_get();
state = pinctrl_lookup_state(wanted_state);
pinctrl_select_state(state);
pinctrl_put();
In pinctrl_select_state function, with current code logic, the
setting, existing in old state but not in new state, will be
disabled(put to safe state) ahead of enabling it.
However, for the state, existing in both old state and new state,
will not be disabled ahead of enabling it, i.e, the pins' owner only
wants to change part of the related pins state.
So the Physical Pin's "desc->mux_usecount" will be increased without
any chance to be decreased.
Thus, there seems two ways to solve the issue I mentioned above:
1. Avoid "enable"(calling pinmux_enable_setting) the Same Pins
setting repeatedly
2. "Disable"(calling pinmux_disable_setting) the Same Pins setting
ahead of enable them in any case.
I think the 2nd way is easy for code change, shown as the following
one. Please help to review this.
If there is anything wrong, feel free to correct me and share your
suggestion for this topic.
Great thanks for this !
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index
2f4edfa..c9b97ae 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -944,30 +944,10 @@ int pinctrl_select_state(struct pinctrl *p,
struct pinctrl_state *state)
return 0;
if (p->state) {
- /*
- * The set of groups with a mux configuration in the
old state
- * may not be identical to the set of groups with a
mux setting
- * in the new state. While this might be unusual,
it's entirely
- * possible for the "user"-supplied mapping table to
be written
- * that way. For each group that was configured in
the old state
- * but not in the new state, this code puts that
group into a
- * safe/disabled state.
- */
list_for_each_entry(setting, &p->state->settings,
node) {
- bool found = false;
if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
continue;
- list_for_each_entry(setting2,
&state->settings, node) {
- if (setting2->type !=
PIN_MAP_TYPE_MUX_GROUP)
- continue;
- if (setting2->data.mux.group ==
-
setting->data.mux.group) {
- found = true;
- break;
- }
- }
- if (!found)
- pinmux_disable_setting(setting);
+ pinmux_disable_setting(setting);
}
}
Do you think what I said above is OK for the possible code change ?
Looking forward your reply.
Great thanks !
Great thanks for your reply and your suggestion.
Just add Stephen Warren to review what mentioned before
Dear Stephen,
I am Will, from Marvell, BSP developer, focusing on Pinctrl part recently.
I just filed patch to do some code changes in the file of
drivers/pinctrl/core.c.
The reason why I did this and some possible issue are described in the
early mail.
Could you please help to review the mail and previous mail.
Great thanks for this !
Looking forward your reply !