2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-26 14:14:01 +08:00

gpio: tegra186: Force one interrupt per bank

Newer chips support up to 8 interrupts per bank, which can be useful to
balance the load and decrease latency. However, it also required a very
complicated interrupt routing to be set up. To keep things simple for
now, ensure that a single interrupt per bank is enforced, even if all
possible interrupts are described in device tree.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
This commit is contained in:
Thierry Reding 2021-09-17 12:54:11 +02:00 committed by Bartosz Golaszewski
parent dcfd2a2975
commit ca03874806

View File

@ -81,6 +81,8 @@ struct tegra_gpio {
unsigned int *irq;
const struct tegra_gpio_soc *soc;
unsigned int num_irqs_per_bank;
unsigned int num_banks;
void __iomem *secure;
void __iomem *base;
@ -594,6 +596,28 @@ static void tegra186_gpio_init_route_mapping(struct tegra_gpio *gpio)
}
}
static unsigned int tegra186_gpio_irqs_per_bank(struct tegra_gpio *gpio)
{
struct device *dev = gpio->gpio.parent;
if (gpio->num_irq > gpio->num_banks) {
if (gpio->num_irq % gpio->num_banks != 0)
goto error;
}
if (gpio->num_irq < gpio->num_banks)
goto error;
gpio->num_irqs_per_bank = gpio->num_irq / gpio->num_banks;
return 0;
error:
dev_err(dev, "invalid number of interrupts (%u) for %u banks\n",
gpio->num_irq, gpio->num_banks);
return -EINVAL;
}
static int tegra186_gpio_probe(struct platform_device *pdev)
{
unsigned int i, j, offset;
@ -608,7 +632,17 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
gpio->soc = device_get_match_data(&pdev->dev);
gpio->gpio.label = gpio->soc->name;
gpio->gpio.parent = &pdev->dev;
/* count the number of banks in the controller */
for (i = 0; i < gpio->soc->num_ports; i++)
if (gpio->soc->ports[i].bank > gpio->num_banks)
gpio->num_banks = gpio->soc->ports[i].bank;
gpio->num_banks++;
/* get register apertures */
gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
if (IS_ERR(gpio->secure)) {
gpio->secure = devm_platform_ioremap_resource(pdev, 0);
@ -629,6 +663,10 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->num_irq = err;
err = tegra186_gpio_irqs_per_bank(gpio);
if (err < 0)
return err;
gpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),
GFP_KERNEL);
if (!gpio->irq)
@ -642,9 +680,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->irq[i] = err;
}
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;
@ -708,7 +743,30 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
irq->parent_handler = tegra186_gpio_irq;
irq->parent_handler_data = gpio;
irq->num_parents = gpio->num_irq;
irq->parents = gpio->irq;
/*
* To simplify things, use a single interrupt per bank for now. Some
* chips support up to 8 interrupts per bank, which can be useful to
* distribute the load and decrease the processing latency for GPIOs
* but it also requires a more complicated interrupt routing than we
* currently program.
*/
if (gpio->num_irqs_per_bank > 1) {
irq->parents = devm_kcalloc(&pdev->dev, gpio->num_banks,
sizeof(*irq->parents), GFP_KERNEL);
if (!irq->parents)
return -ENOMEM;
for (i = 0; i < gpio->num_banks; i++)
irq->parents[i] = gpio->irq[i * gpio->num_irqs_per_bank];
irq->num_parents = gpio->num_banks;
} else {
irq->num_parents = gpio->num_irq;
irq->parents = gpio->irq;
}
tegra186_gpio_init_route_mapping(gpio);
np = of_find_matching_node(NULL, tegra186_pmc_of_match);
if (np) {
@ -719,8 +777,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
tegra186_gpio_init_route_mapping(gpio);
irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
sizeof(*irq->map), GFP_KERNEL);
if (!irq->map)