Message ID | bb68d2360314158cd8ccb9c6794877c3bb45d72e.1411492954.git.stefan@agner.ch (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: > Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. > This is needed since direction configuration is not part of the > GPIO module in Vybrid. > > Signed-off-by: Stefan Agner <stefan@agner.ch> > --- > drivers/pinctrl/pinctrl-imx.c | 54 +++++++++++++++++++++++++++++++++++++++++ > drivers/pinctrl/pinctrl-imx.h | 1 + > drivers/pinctrl/pinctrl-vf610.c | 2 +- > 3 files changed, 56 insertions(+), 1 deletion(-) > > diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c > index 0d4558b..64d1b59 100644 > --- a/drivers/pinctrl/pinctrl-imx.c > +++ b/drivers/pinctrl/pinctrl-imx.c > @@ -294,10 +294,59 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, > return 0; > } > > +static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, > + struct pinctrl_gpio_range *range, unsigned offset) > +{ > + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); > + const struct imx_pinctrl_soc_info *info = ipctl->info; > + const struct imx_pin_reg *pin_reg; > + u32 reg; > + > + if (!(info->flags & GPIO_CONTROL)) > + return -EINVAL; > + > + pin_reg = &info->pin_regs[offset]; > + if (pin_reg->mux_reg == -1) > + return -EINVAL; > + > + reg = readl(ipctl->base + pin_reg->mux_reg); > + reg &= ~(0x7 << 20); > + writel(reg, ipctl->base + pin_reg->mux_reg); Isn't this setup redundant at all, since imx_pmx_enable() already takes care of setting mux register including GPIO mode? > + > + return 0; > +} > + > +static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, > + struct pinctrl_gpio_range *range, unsigned offset, bool input) > +{ > + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); > + const struct imx_pinctrl_soc_info *info = ipctl->info; > + const struct imx_pin_reg *pin_reg; > + u32 reg; > + > + if (!(info->flags & GPIO_CONTROL)) > + return -EINVAL; > + > + pin_reg = &info->pin_regs[offset]; > + if (pin_reg->mux_reg == -1) > + return -EINVAL; > + > + reg = readl(ipctl->base + pin_reg->mux_reg); > + if (input) > + reg &= ~0x2; > + else > + reg |= 0x2; This is all about Output Buffer Enable (OBE) bit. What about Input Buffer Enable (IBE) bit? Don't we need to set or clear it as per GPIO direction as well? > + writel(reg, ipctl->base + pin_reg->mux_reg); > + > + return 0; > +} > + > static const struct pinmux_ops imx_pmx_ops = { > .get_functions_count = imx_pmx_get_funcs_count, > .get_function_name = imx_pmx_get_func_name, > .get_function_groups = imx_pmx_get_groups, > + .gpio_request_enable = imx_pmx_gpio_request_enable, > + .gpio_set_direction = imx_pmx_gpio_set_direction, > .enable = imx_pmx_enable, > }; > > @@ -579,6 +628,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, > dev_err(&pdev->dev, "wrong pinctrl info\n"); > return -EINVAL; > } > + > + /* GPIO control functions only intended for shared mux/conf register */ > + if (info->flags & GPIO_CONTROL) > + BUG_ON(!(info->flags & SHARE_MUX_CONF_REG)); > + If this is always true, why don't we just use flag SHARE_MUX_CONF_REG and save GPIO_CONTROL? This check doesn't make too much sense to me if we choose to have a new flag for GPIO setup. IMO, we should probably either drop the GPIO_CONTROL flag or the check. Shawn > info->dev = &pdev->dev; > > /* Create state holders etc for this driver */ > diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/pinctrl-imx.h > index 49e55d3..8f37ca4 100644 > --- a/drivers/pinctrl/pinctrl-imx.h > +++ b/drivers/pinctrl/pinctrl-imx.h > @@ -84,6 +84,7 @@ struct imx_pinctrl_soc_info { > }; > > #define SHARE_MUX_CONF_REG 0x1 > +#define GPIO_CONTROL 0x2 > > #define NO_MUX 0x0 > #define NO_PAD 0x0 > diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c > index b788e15..fdf5661 100644 > --- a/drivers/pinctrl/pinctrl-vf610.c > +++ b/drivers/pinctrl/pinctrl-vf610.c > @@ -299,7 +299,7 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = { > static struct imx_pinctrl_soc_info vf610_pinctrl_info = { > .pins = vf610_pinctrl_pads, > .npins = ARRAY_SIZE(vf610_pinctrl_pads), > - .flags = SHARE_MUX_CONF_REG, > + .flags = SHARE_MUX_CONF_REG | GPIO_CONTROL, > }; > > static struct of_device_id vf610_pinctrl_of_match[] = { > -- > 2.1.0 >
Am 2014-09-25 04:47, schrieb Shawn Guo: > On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: >> Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. >> This is needed since direction configuration is not part of the >> GPIO module in Vybrid. >> >> Signed-off-by: Stefan Agner <stefan@agner.ch> >> --- >> drivers/pinctrl/pinctrl-imx.c | 54 +++++++++++++++++++++++++++++++++++++++++ >> drivers/pinctrl/pinctrl-imx.h | 1 + >> drivers/pinctrl/pinctrl-vf610.c | 2 +- >> 3 files changed, 56 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c >> index 0d4558b..64d1b59 100644 >> --- a/drivers/pinctrl/pinctrl-imx.c >> +++ b/drivers/pinctrl/pinctrl-imx.c >> @@ -294,10 +294,59 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, >> return 0; >> } >> >> +static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, >> + struct pinctrl_gpio_range *range, unsigned offset) >> +{ >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); >> + const struct imx_pinctrl_soc_info *info = ipctl->info; >> + const struct imx_pin_reg *pin_reg; >> + u32 reg; >> + >> + if (!(info->flags & GPIO_CONTROL)) >> + return -EINVAL; >> + >> + pin_reg = &info->pin_regs[offset]; >> + if (pin_reg->mux_reg == -1) >> + return -EINVAL; >> + >> + reg = readl(ipctl->base + pin_reg->mux_reg); >> + reg &= ~(0x7 << 20); >> + writel(reg, ipctl->base + pin_reg->mux_reg); > > Isn't this setup redundant at all, since imx_pmx_enable() already takes > care of setting mux register including GPIO mode? > Yes currently this is redundant, when a pinmux is actually applied. What is the expected behaviour? Is a explicit pinmux necessary before we can use GPIO? If not, maybe it would make more sense to use imx_pmx_enable here to write all pinctrl settings? >> + >> + return 0; >> +} >> + >> +static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, >> + struct pinctrl_gpio_range *range, unsigned offset, bool input) >> +{ >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); >> + const struct imx_pinctrl_soc_info *info = ipctl->info; >> + const struct imx_pin_reg *pin_reg; >> + u32 reg; >> + >> + if (!(info->flags & GPIO_CONTROL)) >> + return -EINVAL; >> + >> + pin_reg = &info->pin_regs[offset]; >> + if (pin_reg->mux_reg == -1) >> + return -EINVAL; >> + >> + reg = readl(ipctl->base + pin_reg->mux_reg); >> + if (input) >> + reg &= ~0x2; >> + else >> + reg |= 0x2; > > This is all about Output Buffer Enable (OBE) bit. What about Input > Buffer Enable (IBE) bit? Don't we need to set or clear it as per GPIO > direction as well? > The leave the input buffer doesn't hurt, it allows to read back the value which is actually "on the wire". If a pin is hard on GND, one can actually see that. >> + writel(reg, ipctl->base + pin_reg->mux_reg); >> + >> + return 0; >> +} >> + >> static const struct pinmux_ops imx_pmx_ops = { >> .get_functions_count = imx_pmx_get_funcs_count, >> .get_function_name = imx_pmx_get_func_name, >> .get_function_groups = imx_pmx_get_groups, >> + .gpio_request_enable = imx_pmx_gpio_request_enable, >> + .gpio_set_direction = imx_pmx_gpio_set_direction, >> .enable = imx_pmx_enable, >> }; >> >> @@ -579,6 +628,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, >> dev_err(&pdev->dev, "wrong pinctrl info\n"); >> return -EINVAL; >> } >> + >> + /* GPIO control functions only intended for shared mux/conf register */ >> + if (info->flags & GPIO_CONTROL) >> + BUG_ON(!(info->flags & SHARE_MUX_CONF_REG)); >> + > > If this is always true, why don't we just use flag SHARE_MUX_CONF_REG > and save GPIO_CONTROL? This check doesn't make too much sense to me if > we choose to have a new flag for GPIO setup. IMO, we should probably > either drop the GPIO_CONTROL flag or the check. > Well, this is always true because the vf610 driver configures both configs. But when somebody accidentally enables GPIO_CONFIG without understanding the implications... This was more meant like "don't try to use the GPIO_CONTROL just like that, its Vybird specific". But I'm ok to remove this runtime check, maybe a comment describing the flags is more appropriate..? > Shawn > >> info->dev = &pdev->dev; >> >> /* Create state holders etc for this driver */ >> diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/pinctrl-imx.h >> index 49e55d3..8f37ca4 100644 >> --- a/drivers/pinctrl/pinctrl-imx.h >> +++ b/drivers/pinctrl/pinctrl-imx.h >> @@ -84,6 +84,7 @@ struct imx_pinctrl_soc_info { >> }; >> >> #define SHARE_MUX_CONF_REG 0x1 >> +#define GPIO_CONTROL 0x2 >> >> #define NO_MUX 0x0 >> #define NO_PAD 0x0 >> diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c >> index b788e15..fdf5661 100644 >> --- a/drivers/pinctrl/pinctrl-vf610.c >> +++ b/drivers/pinctrl/pinctrl-vf610.c >> @@ -299,7 +299,7 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = { >> static struct imx_pinctrl_soc_info vf610_pinctrl_info = { >> .pins = vf610_pinctrl_pads, >> .npins = ARRAY_SIZE(vf610_pinctrl_pads), >> - .flags = SHARE_MUX_CONF_REG, >> + .flags = SHARE_MUX_CONF_REG | GPIO_CONTROL, >> }; >> >> static struct of_device_id vf610_pinctrl_of_match[] = { >> -- >> 2.1.0 >>
On Thu, Sep 25, 2014 at 09:00:41AM +0200, Stefan Agner wrote: > Am 2014-09-25 04:47, schrieb Shawn Guo: > > On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: > >> Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. > >> This is needed since direction configuration is not part of the > >> GPIO module in Vybrid. > >> > >> Signed-off-by: Stefan Agner <stefan@agner.ch> > >> --- > >> drivers/pinctrl/pinctrl-imx.c | 54 +++++++++++++++++++++++++++++++++++++++++ > >> drivers/pinctrl/pinctrl-imx.h | 1 + > >> drivers/pinctrl/pinctrl-vf610.c | 2 +- > >> 3 files changed, 56 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c > >> index 0d4558b..64d1b59 100644 > >> --- a/drivers/pinctrl/pinctrl-imx.c > >> +++ b/drivers/pinctrl/pinctrl-imx.c > >> @@ -294,10 +294,59 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, > >> return 0; > >> } > >> > >> +static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, > >> + struct pinctrl_gpio_range *range, unsigned offset) > >> +{ > >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); > >> + const struct imx_pinctrl_soc_info *info = ipctl->info; > >> + const struct imx_pin_reg *pin_reg; > >> + u32 reg; > >> + > >> + if (!(info->flags & GPIO_CONTROL)) > >> + return -EINVAL; > >> + > >> + pin_reg = &info->pin_regs[offset]; > >> + if (pin_reg->mux_reg == -1) > >> + return -EINVAL; > >> + > >> + reg = readl(ipctl->base + pin_reg->mux_reg); > >> + reg &= ~(0x7 << 20); > >> + writel(reg, ipctl->base + pin_reg->mux_reg); > > > > Isn't this setup redundant at all, since imx_pmx_enable() already takes > > care of setting mux register including GPIO mode? > > > > Yes currently this is redundant, when a pinmux is actually applied. What > is the expected behaviour? Is a explicit pinmux necessary before we can > use GPIO? If not, maybe it would make more sense to use imx_pmx_enable > here to write all pinctrl settings? Okay, as per Documentation/pinctrl.txt, it's required that GPIO and PINCTRL can be used as orthogonal. That said, your code does the right thing. Sorry for the noisy comment. > > >> + > >> + return 0; > >> +} > >> + > >> +static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, > >> + struct pinctrl_gpio_range *range, unsigned offset, bool input) > >> +{ > >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); > >> + const struct imx_pinctrl_soc_info *info = ipctl->info; > >> + const struct imx_pin_reg *pin_reg; > >> + u32 reg; > >> + > >> + if (!(info->flags & GPIO_CONTROL)) > >> + return -EINVAL; > >> + > >> + pin_reg = &info->pin_regs[offset]; > >> + if (pin_reg->mux_reg == -1) > >> + return -EINVAL; > >> + > >> + reg = readl(ipctl->base + pin_reg->mux_reg); > >> + if (input) > >> + reg &= ~0x2; > >> + else > >> + reg |= 0x2; > > > > This is all about Output Buffer Enable (OBE) bit. What about Input > > Buffer Enable (IBE) bit? Don't we need to set or clear it as per GPIO > > direction as well? > > > > The leave the input buffer doesn't hurt, it allows to read back the > value which is actually "on the wire". If a pin is hard on GND, one can > actually see that. Okay. > > >> + writel(reg, ipctl->base + pin_reg->mux_reg); > >> + > >> + return 0; > >> +} > >> + > >> static const struct pinmux_ops imx_pmx_ops = { > >> .get_functions_count = imx_pmx_get_funcs_count, > >> .get_function_name = imx_pmx_get_func_name, > >> .get_function_groups = imx_pmx_get_groups, > >> + .gpio_request_enable = imx_pmx_gpio_request_enable, > >> + .gpio_set_direction = imx_pmx_gpio_set_direction, > >> .enable = imx_pmx_enable, > >> }; > >> > >> @@ -579,6 +628,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, > >> dev_err(&pdev->dev, "wrong pinctrl info\n"); > >> return -EINVAL; > >> } > >> + > >> + /* GPIO control functions only intended for shared mux/conf register */ > >> + if (info->flags & GPIO_CONTROL) > >> + BUG_ON(!(info->flags & SHARE_MUX_CONF_REG)); > >> + > > > > If this is always true, why don't we just use flag SHARE_MUX_CONF_REG > > and save GPIO_CONTROL? This check doesn't make too much sense to me if > > we choose to have a new flag for GPIO setup. IMO, we should probably > > either drop the GPIO_CONTROL flag or the check. > > > > Well, this is always true because the vf610 driver configures both > configs. But when somebody accidentally enables GPIO_CONFIG without > understanding the implications... This was more meant like "don't try to > use the GPIO_CONTROL just like that, its Vybird specific". But it will become a blocker if some day an i.MX controller (no flag SHARE_MUX_CONF_REG) needs to use GPIO_CONFIG. > But I'm ok to remove this runtime check, maybe a comment describing the > flags is more appropriate..? Sounds good. Shawn
Am 2014-09-25 11:07, schrieb Shawn Guo: > On Thu, Sep 25, 2014 at 09:00:41AM +0200, Stefan Agner wrote: >> Am 2014-09-25 04:47, schrieb Shawn Guo: >> > On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: >> >> Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. >> >> This is needed since direction configuration is not part of the >> >> GPIO module in Vybrid. >> >> >> >> Signed-off-by: Stefan Agner <stefan@agner.ch> >> >> --- >> >> drivers/pinctrl/pinctrl-imx.c | 54 +++++++++++++++++++++++++++++++++++++++++ >> >> drivers/pinctrl/pinctrl-imx.h | 1 + >> >> drivers/pinctrl/pinctrl-vf610.c | 2 +- >> >> 3 files changed, 56 insertions(+), 1 deletion(-) >> >> >> >> diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c >> >> index 0d4558b..64d1b59 100644 >> >> --- a/drivers/pinctrl/pinctrl-imx.c >> >> +++ b/drivers/pinctrl/pinctrl-imx.c >> >> @@ -294,10 +294,59 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, >> >> return 0; >> >> } >> >> >> >> +static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, >> >> + struct pinctrl_gpio_range *range, unsigned offset) >> >> +{ >> >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); >> >> + const struct imx_pinctrl_soc_info *info = ipctl->info; >> >> + const struct imx_pin_reg *pin_reg; >> >> + u32 reg; >> >> + >> >> + if (!(info->flags & GPIO_CONTROL)) >> >> + return -EINVAL; >> >> + >> >> + pin_reg = &info->pin_regs[offset]; >> >> + if (pin_reg->mux_reg == -1) >> >> + return -EINVAL; >> >> + >> >> + reg = readl(ipctl->base + pin_reg->mux_reg); >> >> + reg &= ~(0x7 << 20); >> >> + writel(reg, ipctl->base + pin_reg->mux_reg); >> > >> > Isn't this setup redundant at all, since imx_pmx_enable() already takes >> > care of setting mux register including GPIO mode? >> > >> >> Yes currently this is redundant, when a pinmux is actually applied. What >> is the expected behaviour? Is a explicit pinmux necessary before we can >> use GPIO? If not, maybe it would make more sense to use imx_pmx_enable >> here to write all pinctrl settings? > > Okay, as per Documentation/pinctrl.txt, it's required that GPIO and > PINCTRL can be used as orthogonal. That said, your code does the right > thing. Sorry for the noisy comment. > I'm happy you came up with this, since its the thing which I'm must unsure whether this is right. Right now, if you just export a random pin (which has no pinmux configured in dt), you get an error since this function fails (mux_reg == -1). But I guess we can't avoid it, we need the pinctrl framework to have a valid setting before we fiddle around with the pad. But now, if there is a pinmux configuration in dt, but its not applied (using pinctrl-0 = ...), the export will succeed, however the GPIO will not really be usable since no sane pad configuration is not applied (input/output buffer disabled, no drive-strength)... So we might well just don't change the mux here too. IMHO, fully orthogonal is not possible, since on Vybrid those two depend on each other. But in order to make it "more orthogonal", we maybe should force applying the full configuration in imx_pmx_gpio_request_enable (e.g. drive strenght etc), rather then only mux the pad to to GPIO... What do you think? >> >> >> + >> >> + return 0; >> >> +} >> >> + >> >> +static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, >> >> + struct pinctrl_gpio_range *range, unsigned offset, bool input) >> >> +{ >> >> + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); >> >> + const struct imx_pinctrl_soc_info *info = ipctl->info; >> >> + const struct imx_pin_reg *pin_reg; >> >> + u32 reg; >> >> + >> >> + if (!(info->flags & GPIO_CONTROL)) >> >> + return -EINVAL; >> >> + >> >> + pin_reg = &info->pin_regs[offset]; >> >> + if (pin_reg->mux_reg == -1) >> >> + return -EINVAL; >> >> + >> >> + reg = readl(ipctl->base + pin_reg->mux_reg); >> >> + if (input) >> >> + reg &= ~0x2; >> >> + else >> >> + reg |= 0x2; >> > >> > This is all about Output Buffer Enable (OBE) bit. What about Input >> > Buffer Enable (IBE) bit? Don't we need to set or clear it as per GPIO >> > direction as well? >> > >> >> The leave the input buffer doesn't hurt, it allows to read back the >> value which is actually "on the wire". If a pin is hard on GND, one can >> actually see that. > > Okay. > >> >> >> + writel(reg, ipctl->base + pin_reg->mux_reg); >> >> + >> >> + return 0; >> >> +} >> >> + >> >> static const struct pinmux_ops imx_pmx_ops = { >> >> .get_functions_count = imx_pmx_get_funcs_count, >> >> .get_function_name = imx_pmx_get_func_name, >> >> .get_function_groups = imx_pmx_get_groups, >> >> + .gpio_request_enable = imx_pmx_gpio_request_enable, >> >> + .gpio_set_direction = imx_pmx_gpio_set_direction, >> >> .enable = imx_pmx_enable, >> >> }; >> >> >> >> @@ -579,6 +628,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, >> >> dev_err(&pdev->dev, "wrong pinctrl info\n"); >> >> return -EINVAL; >> >> } >> >> + >> >> + /* GPIO control functions only intended for shared mux/conf register */ >> >> + if (info->flags & GPIO_CONTROL) >> >> + BUG_ON(!(info->flags & SHARE_MUX_CONF_REG)); >> >> + >> > >> > If this is always true, why don't we just use flag SHARE_MUX_CONF_REG >> > and save GPIO_CONTROL? This check doesn't make too much sense to me if >> > we choose to have a new flag for GPIO setup. IMO, we should probably >> > either drop the GPIO_CONTROL flag or the check. >> > >> >> Well, this is always true because the vf610 driver configures both >> configs. But when somebody accidentally enables GPIO_CONFIG without >> understanding the implications... This was more meant like "don't try to >> use the GPIO_CONTROL just like that, its Vybird specific". > > But it will become a blocker if some day an i.MX controller (no flag > SHARE_MUX_CONF_REG) needs to use GPIO_CONFIG. > >> But I'm ok to remove this runtime check, maybe a comment describing the >> flags is more appropriate..? > > Sounds good. > > Shawn
On 25 Sep 2014, stefan@agner.ch wrote: > Am 2014-09-25 11:07, schrieb Shawn Guo: >> On Thu, Sep 25, 2014 at 09:00:41AM +0200, Stefan Agner wrote: >>> Am 2014-09-25 04:47, schrieb Shawn Guo: >>>> On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: >>>>> Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. >>>>> This is needed since direction configuration is not part of the >>>>> GPIO module in Vybrid. >>>>> >>>>> Signed-off-by: Stefan Agner <stefan@agner.ch> >>>>> --- [snip] >>>>> + reg = readl(ipctl->base + pin_reg->mux_reg); >>>>> + reg &= ~(0x7 << 20); >>>>> + writel(reg, ipctl->base + pin_reg->mux_reg); >>>> Isn't this setup redundant at all, since imx_pmx_enable() already >>>> takes care of setting mux register including GPIO mode? >>> Yes currently this is redundant, when a pinmux is actually >>> applied. What is the expected behaviour? Is a explicit pinmux >>> necessary before we can use GPIO? If not, maybe it would make more >>> sense to use imx_pmx_enable here to write all pinctrl settings? >> Okay, as per Documentation/pinctrl.txt, it's required that GPIO and >> PINCTRL can be used as orthogonal. That said, your code does the >> right thing. Sorry for the noisy comment. > I'm happy you came up with this, since its the thing which I'm must > unsure whether this is right. > Right now, if you just export a random pin (which has no pinmux > configured in dt), you get an error since this function fails (mux_reg > == -1). But I guess we can't avoid it, we need the pinctrl framework > to have a valid setting before we fiddle around with the pad. > But now, if there is a pinmux configuration in dt, but its not applied > (using pinctrl-0 = ...), the export will succeed, however the GPIO > will not really be usable since no sane pad configuration is not > applied (input/output buffer disabled, no drive-strength)... So we > might well just don't change the mux here too. > IMHO, fully orthogonal is not possible, since on Vybrid those two > depend on each other. But in order to make it "more orthogonal", we > maybe should force applying the full configuration in > imx_pmx_gpio_request_enable (e.g. drive strenght etc), rather then > only mux the pad to to GPIO... > What do you think? The muxing must have been done, that is correct. However, this could be by a boot loader, by some other API, etc. People maybe concerned about Linux affecting 'CAN' (or some 'mission critical' pins) muxing for instance, but want the A5 to handle GPIO. If somewhere, somehow the pin was muxed properly and the GPIO code still works, I believe this is a win. I see that this flexibility makes it more difficult to get something that just works. I think the device trees take care of this for normal users. It might be appropriate to add a DT node that sets 'GPIO_CONTROL' and put a note in the DT-GPIO document, that pinctrl is needed for a normal case or if some external muxing is used or not needed, then 'control=false' can be set (or whatever good DT terminology)? Then the 'GPIO_CONTROL' check would be in the 'vf610_gpio_direction_input()' functions. The 'pinctrl' functions are currently compiled to stubs if that is configured out. Then there is 'multi-machine' support with DT and compile time selects with CONFIG_PINCTRL and I don't think there is a lot of additional code or confusion? Fwiw, Bill Pringlemeir.
Am 2014-09-25 18:43, schrieb Bill Pringlemeir: > On 25 Sep 2014, stefan@agner.ch wrote: > >> Am 2014-09-25 11:07, schrieb Shawn Guo: >>> On Thu, Sep 25, 2014 at 09:00:41AM +0200, Stefan Agner wrote: >>>> Am 2014-09-25 04:47, schrieb Shawn Guo: >>>>> On Tue, Sep 23, 2014 at 07:37:54PM +0200, Stefan Agner wrote: > >>>>>> Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. >>>>>> This is needed since direction configuration is not part of the >>>>>> GPIO module in Vybrid. >>>>>> >>>>>> Signed-off-by: Stefan Agner <stefan@agner.ch> >>>>>> --- > > [snip] > >>>>>> + reg = readl(ipctl->base + pin_reg->mux_reg); >>>>>> + reg &= ~(0x7 << 20); >>>>>> + writel(reg, ipctl->base + pin_reg->mux_reg); > >>>>> Isn't this setup redundant at all, since imx_pmx_enable() already >>>>> takes care of setting mux register including GPIO mode? > >>>> Yes currently this is redundant, when a pinmux is actually >>>> applied. What is the expected behaviour? Is a explicit pinmux >>>> necessary before we can use GPIO? If not, maybe it would make more >>>> sense to use imx_pmx_enable here to write all pinctrl settings? > >>> Okay, as per Documentation/pinctrl.txt, it's required that GPIO and >>> PINCTRL can be used as orthogonal. That said, your code does the >>> right thing. Sorry for the noisy comment. > >> I'm happy you came up with this, since its the thing which I'm must >> unsure whether this is right. > >> Right now, if you just export a random pin (which has no pinmux >> configured in dt), you get an error since this function fails (mux_reg >> == -1). But I guess we can't avoid it, we need the pinctrl framework >> to have a valid setting before we fiddle around with the pad. > >> But now, if there is a pinmux configuration in dt, but its not applied >> (using pinctrl-0 = ...), the export will succeed, however the GPIO >> will not really be usable since no sane pad configuration is not >> applied (input/output buffer disabled, no drive-strength)... So we >> might well just don't change the mux here too. > >> IMHO, fully orthogonal is not possible, since on Vybrid those two >> depend on each other. But in order to make it "more orthogonal", we >> maybe should force applying the full configuration in >> imx_pmx_gpio_request_enable (e.g. drive strenght etc), rather then >> only mux the pad to to GPIO... > >> What do you think? > > The muxing must have been done, that is correct. However, this could be > by a boot loader, by some other API, etc. People maybe concerned about > Linux affecting 'CAN' (or some 'mission critical' pins) muxing for > instance, but want the A5 to handle GPIO. > > If somewhere, somehow the pin was muxed properly and the GPIO code still > works, I believe this is a win. I see that this flexibility makes it > more difficult to get something that just works. I think the device > trees take care of this for normal users. It might be appropriate to > add a DT node that sets 'GPIO_CONTROL' and put a note in the DT-GPIO > document, that pinctrl is needed for a normal case or if some external > muxing is used or not needed, then 'control=false' can be set (or > whatever good DT terminology)? Then the 'GPIO_CONTROL' check would be > in the 'vf610_gpio_direction_input()' functions. The 'pinctrl' > functions are currently compiled to stubs if that is configured out. Currently pinctrl is not optional for Vybrid (Kconfig mandates pinctrl by "select PINCTRL_VF610"). IMHO there is no real value having a way to mark a pin as "muxed externally" (control=false). If we use a pin, we should configure and mux that properly in Linux, and if we don't have valid configuration/mux information, we should not touch that pin. In v2 of this patchset, the GPIO code only worked when there _is_ a pinctrl entry for that GPIO pin in the DT. This is because I need the register offset, which is provided by the entry itself. But the pad configuration is another point, which I did not consider in v2. But in v3, the GPIO code also writes the pad control. So it was never possible to just use the GPIO driver for any pin, even that pin was correctly muxed and configured externally. And, especially on Vybrid, I think this is a good thing, since the pin could be used by the M4 core. One has to have at least a proper entry in the device tree. And in v3, I also check that this entry represents a valid GPIO mux (VF610_PAD_*GPIO*). IMHO with v3 we have a quite good and safe solution: - Using pins as GPIO needs a valid DT entry - Using that pin only requires exporting the pin, all configuration/muxing get applied by imx_pmx_gpio_request_enable > Then there is 'multi-machine' support with DT and compile time selects > with CONFIG_PINCTRL and I don't think there is a lot of additional code > or confusion? I don't understand that. -- Stefan
>> On 25 Sep 2014, stefan@agner.ch wrote: >>> IMHO, fully orthogonal is not possible, since on Vybrid those two >>> depend on each other. But in order to make it "more orthogonal", we >>> maybe should force applying the full configuration in >>> imx_pmx_gpio_request_enable (e.g. drive strenght etc), rather then >>> only mux the pad to to GPIO... >>> What do you think? > Am 2014-09-25 18:43, schrieb Bill Pringlemeir: >> The muxing must have been done, that is correct. However, this could >> be by a boot loader, by some other API, etc. People maybe concerned >> about Linux affecting 'CAN' (or some 'mission critical' pins) muxing >> for instance, but want the A5 to handle GPIO. >> >> If somewhere, somehow the pin was muxed properly and the GPIO code >> still works, I believe this is a win. I see that this flexibility >> makes it more difficult to get something that just works. I think >> the device trees take care of this for normal users. It might be >> appropriate to add a DT node that sets 'GPIO_CONTROL' and put a note >> in the DT-GPIO document, that pinctrl is needed for a normal case or >> if some external muxing is used or not needed, then 'control=false' >> can be set (or whatever good DT terminology)? Then the >> 'GPIO_CONTROL' check would be in the 'vf610_gpio_direction_input()' >> functions. The 'pinctrl' functions are currently compiled to stubs >> if that is configured out. On 26 Sep 2014, stefan@agner.ch wrote: > Currently pinctrl is not optional for Vybrid (Kconfig mandates pinctrl > by "select PINCTRL_VF610"). > IMHO there is no real value having a way to mark a pin as "muxed > externally" (control=false). If we use a pin, we should configure and > mux that properly in Linux, and if we don't have valid > configuration/mux information, we should not touch that pin. I didn't mean per-pin, I meant for the GPIO controller as a whole. I was also looking at a IOMUX controlled by the M4 and/or a boot loader. I agree it is not possible with the mainline. This just makes it even less possible. This is great if we know we are going that route. > In v2 of this patchset, the GPIO code only worked when there _is_ a > pinctrl entry for that GPIO pin in the DT. This is because I need the > register offset, which is provided by the entry itself. But the pad > configuration is another point, which I did not consider in v2. But in > v3, the GPIO code also writes the pad control. I was a little concerned about this as the pin may have pull-ups and pull-downs. We would not want to dynamically change this. However, I don't fully understand this path. [snip] >> Then there is 'multi-machine' support with DT and compile time >> selects with CONFIG_PINCTRL and I don't think there is a lot of >> additional code or confusion? > I don't understand that. I was thinking of a modified Vybrid which would allow us to not select PINCTRL. As per Shawn's comment, it is suppose to be optional/orthogonal to the GPIO controller. If someone made the change to not select PINCTRL_VF610, then the GPIO code calls would currently compile to stubs. To get the same things with a multi-machine (Vybrid/Imx with/without pinctrl), then you could use the DT property which would avoid the pinctrl calls. The more required modules we require for each feature, the harder it is to partition the AIPS peripherals between cores. It sort of makes the mainline Linux only useful for the VF5xx non-secure parts. I guess another option is to make another pinctrl module for the Vybrid which uses some inter-core communications to alter the MUX configuration. This makes sense for the pinctrl and the CCM/clock modules. Each and every driver depends on them, so it is probably good for sanity to require that Linux has some version of these modules. If the 'M4' was to control the pins and/or clock, then some other modules could be written that makes some calls to that CPU (or world). For other AIPS peripherals, it would be nice if they could be either configured out and/or set to disabled by the device tree. Regards, Bill Pringlemeir.
Am 2014-09-29 17:05, schrieb Bill Pringlemeir: >>> On 25 Sep 2014, stefan@agner.ch wrote: > >>>> IMHO, fully orthogonal is not possible, since on Vybrid those two >>>> depend on each other. But in order to make it "more orthogonal", we >>>> maybe should force applying the full configuration in >>>> imx_pmx_gpio_request_enable (e.g. drive strenght etc), rather then >>>> only mux the pad to to GPIO... >>>> What do you think? > >> Am 2014-09-25 18:43, schrieb Bill Pringlemeir: > >>> The muxing must have been done, that is correct. However, this could >>> be by a boot loader, by some other API, etc. People maybe concerned >>> about Linux affecting 'CAN' (or some 'mission critical' pins) muxing >>> for instance, but want the A5 to handle GPIO. >>> >>> If somewhere, somehow the pin was muxed properly and the GPIO code >>> still works, I believe this is a win. I see that this flexibility >>> makes it more difficult to get something that just works. I think >>> the device trees take care of this for normal users. It might be >>> appropriate to add a DT node that sets 'GPIO_CONTROL' and put a note >>> in the DT-GPIO document, that pinctrl is needed for a normal case or >>> if some external muxing is used or not needed, then 'control=false' >>> can be set (or whatever good DT terminology)? Then the >>> 'GPIO_CONTROL' check would be in the 'vf610_gpio_direction_input()' >>> functions. The 'pinctrl' functions are currently compiled to stubs >>> if that is configured out. > > On 26 Sep 2014, stefan@agner.ch wrote: > >> Currently pinctrl is not optional for Vybrid (Kconfig mandates pinctrl >> by "select PINCTRL_VF610"). > >> IMHO there is no real value having a way to mark a pin as "muxed >> externally" (control=false). If we use a pin, we should configure and >> mux that properly in Linux, and if we don't have valid >> configuration/mux information, we should not touch that pin. > > I didn't mean per-pin, I meant for the GPIO controller as a whole. I > was also looking at a IOMUX controlled by the M4 and/or a boot loader. > I agree it is not possible with the mainline. This just makes it even > less possible. This is great if we know we are going that route. Ok, but this patch doesn't make it less possible then before: You can disable the GPIO driver or disable all gpio device tree entries. > >> In v2 of this patchset, the GPIO code only worked when there _is_ a >> pinctrl entry for that GPIO pin in the DT. This is because I need the >> register offset, which is provided by the entry itself. But the pad >> configuration is another point, which I did not consider in v2. But in >> v3, the GPIO code also writes the pad control. > > I was a little concerned about this as the pin may have pull-ups and > pull-downs. We would not want to dynamically change this. However, I > don't fully understand this path. > > [snip] > >>> Then there is 'multi-machine' support with DT and compile time >>> selects with CONFIG_PINCTRL and I don't think there is a lot of >>> additional code or confusion? > >> I don't understand that. > > I was thinking of a modified Vybrid which would allow us to not select > PINCTRL. As per Shawn's comment, it is suppose to be > optional/orthogonal to the GPIO controller. If someone made the change > to not select PINCTRL_VF610, then the GPIO code calls would currently > compile to stubs. To get the same things with a multi-machine > (Vybrid/Imx with/without pinctrl), then you could use the DT property > which would avoid the pinctrl calls. Now I understand, you mean a kernel with PINCTRL support but having an option to still disable the pinctrl functionality for Vybrids GPIOs. I think if you descide to use a pin as GPIO from Linux on A5, you also want that pin to be "pinctrl"ed by Linux. I don't see a reason why you want a pin configured by something else (bootloader or firmware on M4), but then use that same pin as GPIO from Linux. IMHO, it's good to get this as a package (GPIO which does pinctrl). In the IOMUXC module each pin has its own register, so here it's ok to have multiple sytems fiddling with it, as long as the systems are not touching the same pins at the same time. > The more required modules we require for each feature, the harder it is > to partition the AIPS peripherals between cores. It sort of makes the > mainline Linux only useful for the VF5xx non-secure parts. I agree, having the option to partition AIPS peripherals is useful, especially on Vybrid (and i.MX6SX). And this is perfectly possible with device tree. Just disable the gpio device tree sections (which are compatible = "fsl,vf610-gpio") which you don't plan to use on Linux. Linux creates 5 instances of the driver when all 5 gpio device tree entries are active. However, you can create a board file with only one gpio section, and you get only one instance of the driver which takes care of the associated 32 pins. Or even no gpio device tree sections at all, and you have the same situation before this driver was merged... However, sub GPIO/PORT bank partitioning is not possible... The PORT and GPIO module have shared register for 32 pins, and some operation might not be atomic, so locking would be required. Having two system accessing the same PORT/GPIO bank would certainly impose problems, for instance when handling a PORT interrupt. > I guess another option is to make another pinctrl module for the Vybrid > which uses some inter-core communications to alter the MUX > configuration. This makes sense for the pinctrl and the CCM/clock > modules. Each and every driver depends on them, so it is probably good > for sanity to require that Linux has some version of these modules. If > the 'M4' was to control the pins and/or clock, then some other modules > could be written that makes some calls to that CPU (or world). I also have some M4 firmwares running (eCos, bare-metal), and usually we just let them access the CCM in a "read-only" mode. It works fairly well, however I agree this solution is not perfect. The hardware designers gave us hardware semaphores and CPU to CPU interrupts, so we could build a configuration interface (and maybe a resource allocation as well) around this. This would then implicate an ABI, and this certainly would need some time and discussion to make it good enough for mainline, if possible at all. > For other AIPS peripherals, it would be nice if they could be either > configured out and/or set to disabled by the device tree. Agreed, we should do this as much as possible for Vybrid. -- Stefan
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 0d4558b..64d1b59 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -294,10 +294,59 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, return 0; } +static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset) +{ + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); + const struct imx_pinctrl_soc_info *info = ipctl->info; + const struct imx_pin_reg *pin_reg; + u32 reg; + + if (!(info->flags & GPIO_CONTROL)) + return -EINVAL; + + pin_reg = &info->pin_regs[offset]; + if (pin_reg->mux_reg == -1) + return -EINVAL; + + reg = readl(ipctl->base + pin_reg->mux_reg); + reg &= ~(0x7 << 20); + writel(reg, ipctl->base + pin_reg->mux_reg); + + return 0; +} + +static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset, bool input) +{ + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); + const struct imx_pinctrl_soc_info *info = ipctl->info; + const struct imx_pin_reg *pin_reg; + u32 reg; + + if (!(info->flags & GPIO_CONTROL)) + return -EINVAL; + + pin_reg = &info->pin_regs[offset]; + if (pin_reg->mux_reg == -1) + return -EINVAL; + + reg = readl(ipctl->base + pin_reg->mux_reg); + if (input) + reg &= ~0x2; + else + reg |= 0x2; + writel(reg, ipctl->base + pin_reg->mux_reg); + + return 0; +} + static const struct pinmux_ops imx_pmx_ops = { .get_functions_count = imx_pmx_get_funcs_count, .get_function_name = imx_pmx_get_func_name, .get_function_groups = imx_pmx_get_groups, + .gpio_request_enable = imx_pmx_gpio_request_enable, + .gpio_set_direction = imx_pmx_gpio_set_direction, .enable = imx_pmx_enable, }; @@ -579,6 +628,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, dev_err(&pdev->dev, "wrong pinctrl info\n"); return -EINVAL; } + + /* GPIO control functions only intended for shared mux/conf register */ + if (info->flags & GPIO_CONTROL) + BUG_ON(!(info->flags & SHARE_MUX_CONF_REG)); + info->dev = &pdev->dev; /* Create state holders etc for this driver */ diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/pinctrl-imx.h index 49e55d3..8f37ca4 100644 --- a/drivers/pinctrl/pinctrl-imx.h +++ b/drivers/pinctrl/pinctrl-imx.h @@ -84,6 +84,7 @@ struct imx_pinctrl_soc_info { }; #define SHARE_MUX_CONF_REG 0x1 +#define GPIO_CONTROL 0x2 #define NO_MUX 0x0 #define NO_PAD 0x0 diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c index b788e15..fdf5661 100644 --- a/drivers/pinctrl/pinctrl-vf610.c +++ b/drivers/pinctrl/pinctrl-vf610.c @@ -299,7 +299,7 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = { static struct imx_pinctrl_soc_info vf610_pinctrl_info = { .pins = vf610_pinctrl_pads, .npins = ARRAY_SIZE(vf610_pinctrl_pads), - .flags = SHARE_MUX_CONF_REG, + .flags = SHARE_MUX_CONF_REG | GPIO_CONTROL, }; static struct of_device_id vf610_pinctrl_of_match[] = {
Add pinmux support for GPIO for Vybrid (vf610) IOMUX controller. This is needed since direction configuration is not part of the GPIO module in Vybrid. Signed-off-by: Stefan Agner <stefan@agner.ch> --- drivers/pinctrl/pinctrl-imx.c | 54 +++++++++++++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-imx.h | 1 + drivers/pinctrl/pinctrl-vf610.c | 2 +- 3 files changed, 56 insertions(+), 1 deletion(-)