Commit a5752075 authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Linus Walleij
Browse files

pinctrl: at91: move gpio suspend/resume calls to driver's context



Move gpio suspend/resume execution local to driver and let it execute as
close as possible to the moment the machine specific PM code is executed
(by setting it to .noirq member of dev_pm_ops). With this the
at91_pinctrl_gpio_suspend()/at91_pinctrl_gpio_resume() calls were removed
from arch/arm/mach-at91/pm.c and also a header has been removed.
The patch has been checked on sama5d3_xplained, sam9x60ek,
sama5d2_xplained, sama7g5ek boards.

Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Link: https://lore.kernel.org/r/20220831135636.3176406-3-claudiu.beznea@microchip.com


Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 7fec8c9c
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@
#include <linux/clk/at91_pmc.h>
#include <linux/platform_data/atmel.h>

#include <soc/at91/pm.h>

#include <asm/cacheflush.h>
#include <asm/fncpy.h>
#include <asm/system_misc.h>
@@ -624,16 +622,6 @@ static int at91_pm_enter(suspend_state_t state)
	if (ret)
		return ret;

#ifdef CONFIG_PINCTRL_AT91
	/*
	 * FIXME: this is needed to communicate between the pinctrl driver and
	 * the PM implementation in the machine. Possibly part of the PM
	 * implementation should be moved down into the pinctrl driver and get
	 * called as part of the generic suspend/resume path.
	 */
	at91_pinctrl_gpio_suspend();
#endif

	switch (state) {
	case PM_SUSPEND_MEM:
	case PM_SUSPEND_STANDBY:
@@ -658,9 +646,6 @@ static int at91_pm_enter(suspend_state_t state)
	}

error:
#ifdef CONFIG_PINCTRL_AT91
	at91_pinctrl_gpio_resume();
#endif
	at91_pm_config_quirks(false);
	return 0;
}
+36 −43
Original line number Diff line number Diff line
@@ -22,8 +22,7 @@
#include <linux/pinctrl/pinmux.h>
/* Since we request GPIOs from ourself */
#include <linux/pinctrl/consumer.h>

#include <soc/at91/pm.h>
#include <linux/pm.h>

#include "pinctrl-at91.h"
#include "core.h"
@@ -44,6 +43,9 @@ struct at91_pinctrl_mux_ops;
 * @regbase: PIO bank virtual address
 * @clock: associated clock
 * @ops: at91 pinctrl mux ops
 * @wakeups: wakeup interrupts
 * @backups: interrupts disabled in suspend
 * @id: gpio chip identifier
 */
struct at91_gpio_chip {
	struct gpio_chip	chip;
@@ -55,6 +57,9 @@ struct at91_gpio_chip {
	void __iomem		*regbase;
	struct clk		*clock;
	const struct at91_pinctrl_mux_ops *ops;
	u32			wakeups;
	u32			backups;
	u32			id;
};

static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
@@ -1627,70 +1632,51 @@ static void gpio_irq_ack(struct irq_data *d)
	/* the interrupt is already cleared before by reading ISR */
}

static u32 wakeups[MAX_GPIO_BANKS];
static u32 backups[MAX_GPIO_BANKS];

static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
{
	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
	unsigned	bank = at91_gpio->pioc_idx;
	unsigned mask = 1 << d->hwirq;

	if (unlikely(bank >= MAX_GPIO_BANKS))
		return -EINVAL;

	if (state)
		wakeups[bank] |= mask;
		at91_gpio->wakeups |= mask;
	else
		wakeups[bank] &= ~mask;
		at91_gpio->wakeups &= ~mask;

	irq_set_irq_wake(at91_gpio->pioc_virq, state);

	return 0;
}

void at91_pinctrl_gpio_suspend(void)
static int at91_gpio_suspend(struct device *dev)
{
	int i;
	struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev);
	void __iomem *pio = at91_chip->regbase;

	for (i = 0; i < gpio_banks; i++) {
		void __iomem  *pio;
	at91_chip->backups = readl_relaxed(pio + PIO_IMR);
	writel_relaxed(at91_chip->backups, pio + PIO_IDR);
	writel_relaxed(at91_chip->wakeups, pio + PIO_IER);

		if (!gpio_chips[i])
			continue;

		pio = gpio_chips[i]->regbase;

		backups[i] = readl_relaxed(pio + PIO_IMR);
		writel_relaxed(backups[i], pio + PIO_IDR);
		writel_relaxed(wakeups[i], pio + PIO_IER);

		if (!wakeups[i])
			clk_disable_unprepare(gpio_chips[i]->clock);
	if (!at91_chip->wakeups)
		clk_disable_unprepare(at91_chip->clock);
	else
		printk(KERN_DEBUG "GPIO-%c may wake for %08x\n",
			       'A'+i, wakeups[i]);
	}
		       'A' + at91_chip->id, at91_chip->wakeups);

	return 0;
}

void at91_pinctrl_gpio_resume(void)
static int at91_gpio_resume(struct device *dev)
{
	int i;

	for (i = 0; i < gpio_banks; i++) {
		void __iomem  *pio;
	struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev);
	void __iomem *pio = at91_chip->regbase;

		if (!gpio_chips[i])
			continue;

		pio = gpio_chips[i]->regbase;
	if (!at91_chip->wakeups)
		clk_prepare_enable(at91_chip->clock);

		if (!wakeups[i])
			clk_prepare_enable(gpio_chips[i]->clock);
	writel_relaxed(at91_chip->wakeups, pio + PIO_IDR);
	writel_relaxed(at91_chip->backups, pio + PIO_IER);

		writel_relaxed(wakeups[i], pio + PIO_IDR);
		writel_relaxed(backups[i], pio + PIO_IER);
	}
	return 0;
}

static void gpio_irq_handler(struct irq_desc *desc)
@@ -1872,6 +1858,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
	}

	at91_chip->chip = at91_gpio_template;
	at91_chip->id = alias_idx;

	chip = &at91_chip->chip;
	chip->label = dev_name(&pdev->dev);
@@ -1917,6 +1904,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
		goto gpiochip_add_err;

	gpio_chips[alias_idx] = at91_chip;
	platform_set_drvdata(pdev, at91_chip);
	gpio_banks = max(gpio_banks, alias_idx + 1);

	dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
@@ -1932,10 +1920,15 @@ static int at91_gpio_probe(struct platform_device *pdev)
	return ret;
}

static const struct dev_pm_ops at91_gpio_pm_ops = {
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(at91_gpio_suspend, at91_gpio_resume)
};

static struct platform_driver at91_gpio_driver = {
	.driver = {
		.name = "gpio-at91",
		.of_match_table = at91_gpio_of_match,
		.pm = pm_ptr(&at91_gpio_pm_ops),
	},
	.probe = at91_gpio_probe,
};

include/soc/at91/pm.h

deleted100644 → 0
+0 −16
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Atmel Power Management
 *
 * Copyright (C) 2020 Atmel
 *
 * Author: Lee Jones <lee.jones@linaro.org>
 */

#ifndef __SOC_ATMEL_PM_H
#define __SOC_ATMEL_PM_H

void at91_pinctrl_gpio_suspend(void);
void at91_pinctrl_gpio_resume(void);

#endif /* __SOC_ATMEL_PM_H */