From: "Niedermayr, BENEDIKT" <benedikt.niedermayr@siemens.com>
To: "tony@atomide.com" <tony@atomide.com>
Cc: "haojian.zhuang@linaro.org" <haojian.zhuang@linaro.org>,
"linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>,
"linux-omap@vger.kernel.org" <linux-omap@vger.kernel.org>,
"linus.walleij@linaro.org" <linus.walleij@linaro.org>
Subject: Re: Pinconf issues on AMxxx plattforms
Date: Fri, 5 May 2023 12:59:14 +0000 [thread overview]
Message-ID: <8208d823e9cddcb0e427e8feef43f7fa03067ff7.camel@siemens.com> (raw)
In-Reply-To: <20230504053509.GN14287@atomide.com>
On Thu, 2023-05-04 at 08:35 +0300, Tony Lindgren wrote:
> Hi,
>
> Adding linux-gpio and Linus W to Cc. Some questions and comments below
> towards the end.
>
> * Niedermayr, BENEDIKT <benedikt.niedermayr@siemens.com> [230503 08:38]:
> > Hello,
> >
> > We encountered some issues when accessing the gpiochardev interface on an
> > AM65xx plaform.
> >
> > The basic idea was to fully rely on all features the gpiochardev seems to
> > offer.
> > I got all relevant information from the Linux Kernel Documentation
> > (Documentation/driver-api/pin-control.rst) and saw
> > some presentations from Linus Walleij regarding the gpiochardev
> > capabilities.
> >
> > If I understand that correctly the gpiochardev interface should support the
> > following features:
> > * Requesting gpio pins from userspace
> > * Set input/output directions
> > * Set BIAS settings (pull-up, pull-down, etc.)
> > * Gpio function of that pin automatically gets muxed in if requested
> >
> > Requesting pins worked for me as expected after I added the required DTB
> > properties:
> > * pinctrl-single: Add each required pin to "pinctrl-single,gpio-range" in
> > the pincontroller node
> > * gpio: Add each required pin to gpio-range property in the gpio node
> >
> > I also added the required childnodes in the pinctrl node:
> >
> > &main_pmx0 {
> > ...
> > d6_gpio: d6-gpio {
> > pinctrl-single,pins = <
> > /* (AH16) GPIO0_38 */
> > AM65X_IOPAD(0x0098, PIN_INPUT, 7)
> > > ;
> > pinctrl-single,bias-pullup = <0x20000 0x20000 0x10000 0x30000>;
> > pinctrl-single,bias-pulldown = <0x00000 0x0 0x10000 0x30000>;
> > };
> > ...
> > }
> >
> > When I tried to set any BIAS settings nothing happened or some error occured
> > in the kernel logs (i'm not 100% sure anymore since almost 2 months have
> > past).
> > The first thing I had to do was to assign the gpiochip_generic_config
> > callback to the gpiochiop for that (gpio-davinci.c). This callback in turn
> > will finally call pcs_pinconf_set(), which
> > is the pinctrl drivers related callback for setting the pinconf.
> > But still no success...
> >
> > Then I went deeper into the rabbit whole and encountered that the error had
> > to do with pcs_get_function() (pinctrl-single.c).
> > I found out that this function requests the current function (or pinmux
> > state) from the pinctrl subsystem core.
> > The pinctrl driver needs this information for accessing the correct pinctrl
> > childnode bits.
> >
> > So what is the Problem here?
> > The pinctrl offers 3 different options for muxing:
> >
> > 1. Using the generic kernel APIs:
> > Call pinctrl_select_state() function as stated
> > in Documentation/driver-api/pin-control.rst (section "Pin control requests
> > from drivers").
> > This function will select a defined state which has been defined in DTB
> > with "pinctrl-0", "pinctrl-1", "pinctrl-x"
> > 2. Mux pins with debugfs:
> > Write the desired pingroup and pinfunction into the "pinmux-select"
> > file of the related pin controller.
> > 3. Mux the GPIO function of a requested GPIO pin by calling the pinctrl
> > drivers pcs_request_gpio() function.
> >
> > The problem now is that only option 1. will store the current mux
> > information in the pinctrl subsystems core.
> > The pinctrl-single driver highly depends on that information, which is not
> > available at all wenn muxing with options 2&3.
> >
> > I was able to fix that for option 2 but not for option 3. The problem here
> > is that the pcs_request_gpio() function just does not provide enough
> > parameters with sufficient information for achieving that task.
>
> Care to post what your fix for #2 above looks like?
Thanks for the reply.
Sure, I can post it. But that is just an example and not a final proposal.
It seems pretty complex but accessing "pdesc->mux_setting" directly was not possible, since
it is defined as const pointer.
So I created an internal shadow copy private data struct and stored the mux_settings there.
In pcs_set_mux() I can then update the mux_setting and query it in pcs_get_function().
Im sure that there are much better solutions but for now it's just a first shot.
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index cd314a5305a2..fa47fbf1534c 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -38,6 +38,16 @@
#define DRIVER_NAME "pinctrl-single"
#define PCS_OFF_DISABLED ~0U
+/**
+ * struct pcs_setting_mux - hold current mux settings per pin
+ * @func: selected pin function
+ * @group: selected pin group
+ */
+struct pcs_setting_mux {
+ unsigned func;
+ unsigned group;
+};
+
/**
* struct pcs_func_vals - mux function register offset and value pair
* @reg: register virtual address
@@ -340,12 +350,11 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
{
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
- const struct pinctrl_setting_mux *setting;
+ struct pcs_setting_mux *setting = pdesc->drv_data;
struct function_desc *function;
unsigned fselector;
/* If pin is not described in DTS & enabled, mux_setting is NULL. */
- setting = pdesc->mux_setting;
if (!setting)
return -ENOTSUPP;
fselector = setting->func;
@@ -365,7 +374,9 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
struct pcs_device *pcs;
struct function_desc *function;
struct pcs_function *func;
- int i;
+ int i, ret;
+ const unsigned *pins = NULL;
+ unsigned num_pins = 0;
pcs = pinctrl_dev_get_drvdata(pctldev);
/* If function mask is null, needn't enable it. */
@@ -376,8 +387,32 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
if (!func)
return -EINVAL;
- dev_dbg(pcs->dev, "enabling %s function%i\n",
- func->name, fselector);
+ /*
+ * Last mux setting must be stored here as well.
+ * Referring to proper pinconf requires the current pin function
+ * to be known
+ */
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &num_pins);
+ if (ret && PCS_HAS_PINCONF) {
+ dev_err(pcs->dev, "Cannot store mux settings\n");
+ return ret;
+ }
+
+ for (i = 0; i < num_pins; i++) {
+ struct pcs_setting_mux *setting;
+ struct pin_desc *desc;
+
+ desc = pin_desc_get(pctldev, pins[i]);
+ if (!desc) {
+ dev_err(pcs->dev, "Unable to request pindesc for PIN%d\n",
+ pins[i]);
+ continue;
+ }
+
+ setting = desc->drv_data;
+ setting->func = fselector;
+ setting->group = group;
+ }
for (i = 0; i < func->nvals; i++) {
struct pcs_func_vals *vals;
@@ -682,6 +717,7 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset)
{
struct pcs_soc_data *pcs_soc = &pcs->socdata;
struct pinctrl_pin_desc *pin;
+ struct pcs_setting_mux *setting;
int i;
i = pcs->pins.cur;
@@ -703,7 +739,14 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset)
}
}
+
+ setting = devm_kzalloc(pcs->dev, sizeof(*setting), GFP_KERNEL);
+ if (!setting)
+ return -ENOMEM;
+
+
pin = &pcs->pins.pa[i];
+ pin->drv_data = setting;
pin->number = i;
pcs->pins.cur++;
> pin_desc
> > I'm not sure if I miss something important here?
> > Are you aware of this issue?
>
> Sounds like something needs to be implemented for pinctrl-single.c.
Ok then I'm not completely wrong.
I will try to sent out a more complete patchseries for discussions during next two weeks.
>
> Regards,
>
> Tony
Cheers,
Benedikt
prev parent reply other threads:[~2023-05-05 12:59 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <aa493d62327f26e4c65d649a812346cdfb26771f.camel@siemens.com>
2023-05-04 5:35 ` Pinconf issues on AMxxx plattforms Tony Lindgren
2023-05-04 8:31 ` Linus Walleij
2023-05-05 8:54 ` Tony Lindgren
2023-05-05 13:28 ` Niedermayr, BENEDIKT
2023-05-05 12:59 ` Niedermayr, BENEDIKT [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8208d823e9cddcb0e427e8feef43f7fa03067ff7.camel@siemens.com \
--to=benedikt.niedermayr@siemens.com \
--cc=haojian.zhuang@linaro.org \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=tony@atomide.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).