Message ID | 20200319122737.3063291-3-thierry.reding@gmail.com |
---|---|
State | Deferred |
Headers | show |
Series | pinctrl: tegra: Support SFIO/GPIO programming | expand |
On 3/19/2020 5:57 PM, Thierry Reding wrote: > External email: Use caution opening links or attachments > > > From: Thierry Reding <treding@nvidia.com> > > Add support for Tegra SoC generations to specify a list of pin ranges > that map GPIOs to ranges of pins in the pin controller. > > Signed-off-by: Thierry Reding <treding@nvidia.com> > --- > drivers/gpio/gpio-tegra186.c | 56 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 56 insertions(+) > > diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c > index de241263d4be..1086c1fcaf49 100644 > --- a/drivers/gpio/gpio-tegra186.c > +++ b/drivers/gpio/gpio-tegra186.c > @@ -58,11 +58,20 @@ struct tegra_gpio_port { > unsigned int pins; > }; > > +struct tegra186_pin_range { > + unsigned int offset; > + const char *group; > +}; > + > struct tegra_gpio_soc { > const struct tegra_gpio_port *ports; > unsigned int num_ports; > const char *name; > unsigned int instance; > + > + const struct tegra186_pin_range *pin_ranges; > + unsigned int num_pin_ranges; > + const char *pinmux; > }; > > struct tegra_gpio { > @@ -254,6 +263,50 @@ static int tegra186_gpio_set_config(struct gpio_chip *chip, > return 0; > } > > +static int tegra186_gpio_add_pin_ranges(struct gpio_chip *chip) > +{ > + struct tegra_gpio *gpio = gpiochip_get_data(chip); > + struct pinctrl_dev *pctldev; > + struct device_node *np; > + unsigned int i, j; > + int err; > + > + if (!gpio->soc->pinmux || gpio->soc->num_pin_ranges == 0) > + return 0; > + > + np = of_find_compatible_node(NULL, NULL, gpio->soc->pinmux); > + if (!np) > + return -ENODEV; > + > + pctldev = of_pinctrl_get(np); > + of_node_put(np); > + if (!pctldev) > + return -EPROBE_DEFER; > + > + for (i = 0; i < gpio->soc->num_pin_ranges; i++) { > + unsigned int pin = gpio->soc->pin_ranges[i].offset, port; > + const char *group = gpio->soc->pin_ranges[i].group; > + > + port = pin / 8; > + pin = pin % 8; > + > + if (port >= gpio->soc->num_ports) { > + dev_warn(chip->parent, "invalid port %u for %s\n", > + port, group); > + continue; > + } > + > + for (j = 0; j < port; j++) > + pin += gpio->soc->ports[j].pins; > + > + err = gpiochip_add_pingroup_range(chip, pctldev, pin, group); > + if (err < 0) > + return err; > + } > + > + return 0; > +} > + > static int tegra186_gpio_of_xlate(struct gpio_chip *chip, > const struct of_phandle_args *spec, > u32 *flags) > @@ -578,12 +631,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev) > gpio->gpio.label = gpio->soc->name; > gpio->gpio.parent = &pdev->dev; > > + gpio->gpio.request = gpiochip_generic_request; > + gpio->gpio.free = gpiochip_generic_free; > gpio->gpio.get_direction = tegra186_gpio_get_direction; > gpio->gpio.direction_input = tegra186_gpio_direction_input; > gpio->gpio.direction_output = tegra186_gpio_direction_output; > gpio->gpio.get = tegra186_gpio_get, > gpio->gpio.set = tegra186_gpio_set; > gpio->gpio.set_config = tegra186_gpio_set_config; > + gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; > > gpio->gpio.base = -1; > > -- > 2.24.1 > Tested-by: Vidya Sagar <vidyas@nvidia.com>
On Thu, Mar 19, 2020 at 1:27 PM Thierry Reding <thierry.reding@gmail.com> wrote: > From: Thierry Reding <treding@nvidia.com> > > Add support for Tegra SoC generations to specify a list of pin ranges > that map GPIOs to ranges of pins in the pin controller. > > Signed-off-by: Thierry Reding <treding@nvidia.com> Patch applied! Yours, Linus Walleij
On Fri, Mar 27, 2020 at 11:39:35AM +0100, Linus Walleij wrote: > On Thu, Mar 19, 2020 at 1:27 PM Thierry Reding <thierry.reding@gmail.com> wrote: > > > From: Thierry Reding <treding@nvidia.com> > > > > Add support for Tegra SoC generations to specify a list of pin ranges > > that map GPIOs to ranges of pins in the pin controller. > > > > Signed-off-by: Thierry Reding <treding@nvidia.com> > > Patch applied! Hi Linus, I see patch 1 applied to gpio/for-next, but patches 2 and 3 don't seem to be in linux-next yet. Did anything go wrong with those? Thierry
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index de241263d4be..1086c1fcaf49 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -58,11 +58,20 @@ struct tegra_gpio_port { unsigned int pins; }; +struct tegra186_pin_range { + unsigned int offset; + const char *group; +}; + struct tegra_gpio_soc { const struct tegra_gpio_port *ports; unsigned int num_ports; const char *name; unsigned int instance; + + const struct tegra186_pin_range *pin_ranges; + unsigned int num_pin_ranges; + const char *pinmux; }; struct tegra_gpio { @@ -254,6 +263,50 @@ static int tegra186_gpio_set_config(struct gpio_chip *chip, return 0; } +static int tegra186_gpio_add_pin_ranges(struct gpio_chip *chip) +{ + struct tegra_gpio *gpio = gpiochip_get_data(chip); + struct pinctrl_dev *pctldev; + struct device_node *np; + unsigned int i, j; + int err; + + if (!gpio->soc->pinmux || gpio->soc->num_pin_ranges == 0) + return 0; + + np = of_find_compatible_node(NULL, NULL, gpio->soc->pinmux); + if (!np) + return -ENODEV; + + pctldev = of_pinctrl_get(np); + of_node_put(np); + if (!pctldev) + return -EPROBE_DEFER; + + for (i = 0; i < gpio->soc->num_pin_ranges; i++) { + unsigned int pin = gpio->soc->pin_ranges[i].offset, port; + const char *group = gpio->soc->pin_ranges[i].group; + + port = pin / 8; + pin = pin % 8; + + if (port >= gpio->soc->num_ports) { + dev_warn(chip->parent, "invalid port %u for %s\n", + port, group); + continue; + } + + for (j = 0; j < port; j++) + pin += gpio->soc->ports[j].pins; + + err = gpiochip_add_pingroup_range(chip, pctldev, pin, group); + if (err < 0) + return err; + } + + return 0; +} + static int tegra186_gpio_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *spec, u32 *flags) @@ -578,12 +631,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->gpio.label = gpio->soc->name; gpio->gpio.parent = &pdev->dev; + gpio->gpio.request = gpiochip_generic_request; + gpio->gpio.free = gpiochip_generic_free; gpio->gpio.get_direction = tegra186_gpio_get_direction; gpio->gpio.direction_input = tegra186_gpio_direction_input; gpio->gpio.direction_output = tegra186_gpio_direction_output; gpio->gpio.get = tegra186_gpio_get, gpio->gpio.set = tegra186_gpio_set; gpio->gpio.set_config = tegra186_gpio_set_config; + gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; gpio->gpio.base = -1;