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:
parent
dcfd2a2975
commit
ca03874806
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user