gpio: tegra186: Add support for pin ranges
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> Link: https://lore.kernel.org/r/20200319122737.3063291-3-thierry.reding@gmail.com Tested-by: Vidya Sagar <vidyas@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Родитель
2ab73c6d83
Коммит
b64d6c9a6a
|
@ -58,11 +58,20 @@ struct tegra_gpio_port {
|
||||||
unsigned int pins;
|
unsigned int pins;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tegra186_pin_range {
|
||||||
|
unsigned int offset;
|
||||||
|
const char *group;
|
||||||
|
};
|
||||||
|
|
||||||
struct tegra_gpio_soc {
|
struct tegra_gpio_soc {
|
||||||
const struct tegra_gpio_port *ports;
|
const struct tegra_gpio_port *ports;
|
||||||
unsigned int num_ports;
|
unsigned int num_ports;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int instance;
|
unsigned int instance;
|
||||||
|
|
||||||
|
const struct tegra186_pin_range *pin_ranges;
|
||||||
|
unsigned int num_pin_ranges;
|
||||||
|
const char *pinmux;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_gpio {
|
struct tegra_gpio {
|
||||||
|
@ -254,6 +263,50 @@ static int tegra186_gpio_set_config(struct gpio_chip *chip,
|
||||||
return 0;
|
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,
|
static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
|
||||||
const struct of_phandle_args *spec,
|
const struct of_phandle_args *spec,
|
||||||
u32 *flags)
|
u32 *flags)
|
||||||
|
@ -578,12 +631,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||||
gpio->gpio.label = gpio->soc->name;
|
gpio->gpio.label = gpio->soc->name;
|
||||||
gpio->gpio.parent = &pdev->dev;
|
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.get_direction = tegra186_gpio_get_direction;
|
||||||
gpio->gpio.direction_input = tegra186_gpio_direction_input;
|
gpio->gpio.direction_input = tegra186_gpio_direction_input;
|
||||||
gpio->gpio.direction_output = tegra186_gpio_direction_output;
|
gpio->gpio.direction_output = tegra186_gpio_direction_output;
|
||||||
gpio->gpio.get = tegra186_gpio_get,
|
gpio->gpio.get = tegra186_gpio_get,
|
||||||
gpio->gpio.set = tegra186_gpio_set;
|
gpio->gpio.set = tegra186_gpio_set;
|
||||||
gpio->gpio.set_config = tegra186_gpio_set_config;
|
gpio->gpio.set_config = tegra186_gpio_set_config;
|
||||||
|
gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges;
|
||||||
|
|
||||||
gpio->gpio.base = -1;
|
gpio->gpio.base = -1;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче