diff options
Diffstat (limited to 'drivers/gpio/gpio-zynq.c')
| -rw-r--r-- | drivers/gpio/gpio-zynq.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 0a7264aabe48..97780c57ab56 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -265,8 +265,8 @@ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin) * upper 16 bits) based on the given pin number and sets the state of a * gpio pin to the specified value. The state is either 0 or non-zero. */ -static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin, - int state) +static int zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin, + int state) { unsigned int reg_offset, bank_num, bank_pin_num; struct zynq_gpio *gpio = gpiochip_get_data(chip); @@ -290,6 +290,8 @@ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin, ((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK); writel_relaxed(state, gpio->base_addr + reg_offset); + + return 0; } /** @@ -575,6 +577,26 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) return 0; } +static int zynq_gpio_irq_reqres(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + int ret; + + ret = pm_runtime_resume_and_get(chip->parent); + if (ret < 0) + return ret; + + return gpiochip_reqres_irq(chip, d->hwirq); +} + +static void zynq_gpio_irq_relres(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + gpiochip_relres_irq(chip, d->hwirq); + pm_runtime_put(chip->parent); +} + /* irq chip descriptor */ static const struct irq_chip zynq_gpio_level_irqchip = { .name = DRIVER_NAME, @@ -584,9 +606,10 @@ static const struct irq_chip zynq_gpio_level_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, + .irq_request_resources = zynq_gpio_irq_reqres, + .irq_release_resources = zynq_gpio_irq_relres, .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static const struct irq_chip zynq_gpio_edge_irqchip = { @@ -597,8 +620,9 @@ static const struct irq_chip zynq_gpio_edge_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, + .irq_request_resources = zynq_gpio_irq_reqres, + .irq_release_resources = zynq_gpio_irq_relres, .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, @@ -711,7 +735,7 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) } } -static int __maybe_unused zynq_gpio_suspend(struct device *dev) +static int zynq_gpio_suspend(struct device *dev) { struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); @@ -732,7 +756,7 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) return 0; } -static int __maybe_unused zynq_gpio_resume(struct device *dev) +static int zynq_gpio_resume(struct device *dev) { struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); @@ -755,7 +779,7 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) return 0; } -static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev) +static int zynq_gpio_runtime_suspend(struct device *dev) { struct zynq_gpio *gpio = dev_get_drvdata(dev); @@ -764,7 +788,7 @@ static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev) +static int zynq_gpio_runtime_resume(struct device *dev) { struct zynq_gpio *gpio = dev_get_drvdata(dev); @@ -790,9 +814,8 @@ static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset) } static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) - SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, - zynq_gpio_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) + RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, zynq_gpio_runtime_resume, NULL) }; static const struct zynq_platform_data versal_gpio_def = { @@ -918,16 +941,10 @@ static int zynq_gpio_probe(struct platform_device *pdev) chip->ngpio = gpio->p_data->ngpio; /* Retrieve GPIO clock */ - gpio->clk = devm_clk_get(&pdev->dev, NULL); + gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(gpio->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found.\n"); - ret = clk_prepare_enable(gpio->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock.\n"); - return ret; - } - spin_lock_init(&gpio->dirlock); pm_runtime_set_active(&pdev->dev); @@ -977,7 +994,6 @@ err_pm_put: pm_runtime_put(&pdev->dev); err_pm_dis: pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(gpio->clk); return ret; } @@ -988,7 +1004,7 @@ err_pm_dis: * * Return: 0 always */ -static int zynq_gpio_remove(struct platform_device *pdev) +static void zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); int ret; @@ -996,17 +1012,16 @@ static int zynq_gpio_remove(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); + device_init_wakeup(&pdev->dev, 0); gpiochip_remove(&gpio->chip); - clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver zynq_gpio_driver = { .driver = { .name = DRIVER_NAME, - .pm = &zynq_gpio_dev_pm_ops, + .pm = pm_ptr(&zynq_gpio_dev_pm_ops), .of_match_table = zynq_gpio_of_match, }, .probe = zynq_gpio_probe, |
