162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Xilinx Zynq GPIO device driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2009 - 2014 Xilinx, Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bitops.h>
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/interrupt.h>
1362306a36Sopenharmony_ci#include <linux/spinlock.h>
1462306a36Sopenharmony_ci#include <linux/io.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/platform_device.h>
1762306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1862306a36Sopenharmony_ci#include <linux/of.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define DRIVER_NAME "zynq-gpio"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* Maximum banks */
2362306a36Sopenharmony_ci#define ZYNQ_GPIO_MAX_BANK	4
2462306a36Sopenharmony_ci#define ZYNQMP_GPIO_MAX_BANK	6
2562306a36Sopenharmony_ci#define VERSAL_GPIO_MAX_BANK	4
2662306a36Sopenharmony_ci#define PMC_GPIO_MAX_BANK	5
2762306a36Sopenharmony_ci#define VERSAL_UNUSED_BANKS	2
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK0_NGPIO	32
3062306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK1_NGPIO	22
3162306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK2_NGPIO	32
3262306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK3_NGPIO	32
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK0_NGPIO 26
3562306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK1_NGPIO 26
3662306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK2_NGPIO 26
3762306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK3_NGPIO 32
3862306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK4_NGPIO 32
3962306a36Sopenharmony_ci#define ZYNQMP_GPIO_BANK5_NGPIO 32
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define	ZYNQ_GPIO_NR_GPIOS	118
4262306a36Sopenharmony_ci#define	ZYNQMP_GPIO_NR_GPIOS	174
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK0_PIN_MIN(str)	0
4562306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK0_PIN_MAX(str)	(ZYNQ_GPIO_BANK0_PIN_MIN(str) + \
4662306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK0_NGPIO - 1)
4762306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK1_PIN_MIN(str)	(ZYNQ_GPIO_BANK0_PIN_MAX(str) + 1)
4862306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK1_PIN_MAX(str)	(ZYNQ_GPIO_BANK1_PIN_MIN(str) + \
4962306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK1_NGPIO - 1)
5062306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK2_PIN_MIN(str)	(ZYNQ_GPIO_BANK1_PIN_MAX(str) + 1)
5162306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK2_PIN_MAX(str)	(ZYNQ_GPIO_BANK2_PIN_MIN(str) + \
5262306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK2_NGPIO - 1)
5362306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK3_PIN_MIN(str)	(ZYNQ_GPIO_BANK2_PIN_MAX(str) + 1)
5462306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK3_PIN_MAX(str)	(ZYNQ_GPIO_BANK3_PIN_MIN(str) + \
5562306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK3_NGPIO - 1)
5662306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK4_PIN_MIN(str)	(ZYNQ_GPIO_BANK3_PIN_MAX(str) + 1)
5762306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK4_PIN_MAX(str)	(ZYNQ_GPIO_BANK4_PIN_MIN(str) + \
5862306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK4_NGPIO - 1)
5962306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK5_PIN_MIN(str)	(ZYNQ_GPIO_BANK4_PIN_MAX(str) + 1)
6062306a36Sopenharmony_ci#define ZYNQ_GPIO_BANK5_PIN_MAX(str)	(ZYNQ_GPIO_BANK5_PIN_MIN(str) + \
6162306a36Sopenharmony_ci					ZYNQ##str##_GPIO_BANK5_NGPIO - 1)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* Register offsets for the GPIO device */
6462306a36Sopenharmony_ci/* LSW Mask & Data -WO */
6562306a36Sopenharmony_ci#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK)	(0x000 + (8 * BANK))
6662306a36Sopenharmony_ci/* MSW Mask & Data -WO */
6762306a36Sopenharmony_ci#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK)	(0x004 + (8 * BANK))
6862306a36Sopenharmony_ci/* Data Register-RW */
6962306a36Sopenharmony_ci#define ZYNQ_GPIO_DATA_OFFSET(BANK)	(0x040 + (4 * BANK))
7062306a36Sopenharmony_ci#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK)	(0x060 + (4 * BANK))
7162306a36Sopenharmony_ci/* Direction mode reg-RW */
7262306a36Sopenharmony_ci#define ZYNQ_GPIO_DIRM_OFFSET(BANK)	(0x204 + (0x40 * BANK))
7362306a36Sopenharmony_ci/* Output enable reg-RW */
7462306a36Sopenharmony_ci#define ZYNQ_GPIO_OUTEN_OFFSET(BANK)	(0x208 + (0x40 * BANK))
7562306a36Sopenharmony_ci/* Interrupt mask reg-RO */
7662306a36Sopenharmony_ci#define ZYNQ_GPIO_INTMASK_OFFSET(BANK)	(0x20C + (0x40 * BANK))
7762306a36Sopenharmony_ci/* Interrupt enable reg-WO */
7862306a36Sopenharmony_ci#define ZYNQ_GPIO_INTEN_OFFSET(BANK)	(0x210 + (0x40 * BANK))
7962306a36Sopenharmony_ci/* Interrupt disable reg-WO */
8062306a36Sopenharmony_ci#define ZYNQ_GPIO_INTDIS_OFFSET(BANK)	(0x214 + (0x40 * BANK))
8162306a36Sopenharmony_ci/* Interrupt status reg-RO */
8262306a36Sopenharmony_ci#define ZYNQ_GPIO_INTSTS_OFFSET(BANK)	(0x218 + (0x40 * BANK))
8362306a36Sopenharmony_ci/* Interrupt type reg-RW */
8462306a36Sopenharmony_ci#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK)	(0x21C + (0x40 * BANK))
8562306a36Sopenharmony_ci/* Interrupt polarity reg-RW */
8662306a36Sopenharmony_ci#define ZYNQ_GPIO_INTPOL_OFFSET(BANK)	(0x220 + (0x40 * BANK))
8762306a36Sopenharmony_ci/* Interrupt on any, reg-RW */
8862306a36Sopenharmony_ci#define ZYNQ_GPIO_INTANY_OFFSET(BANK)	(0x224 + (0x40 * BANK))
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/* Disable all interrupts mask */
9162306a36Sopenharmony_ci#define ZYNQ_GPIO_IXR_DISABLE_ALL	0xFFFFFFFF
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* Mid pin number of a bank */
9462306a36Sopenharmony_ci#define ZYNQ_GPIO_MID_PIN_NUM 16
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* GPIO upper 16 bit mask */
9762306a36Sopenharmony_ci#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
10062306a36Sopenharmony_ci#define ZYNQ_GPIO_QUIRK_IS_ZYNQ	BIT(0)
10162306a36Sopenharmony_ci#define GPIO_QUIRK_DATA_RO_BUG	BIT(1)
10262306a36Sopenharmony_ci#define GPIO_QUIRK_VERSAL	BIT(2)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistruct gpio_regs {
10562306a36Sopenharmony_ci	u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
10662306a36Sopenharmony_ci	u32 datalsw[ZYNQMP_GPIO_MAX_BANK];
10762306a36Sopenharmony_ci	u32 dirm[ZYNQMP_GPIO_MAX_BANK];
10862306a36Sopenharmony_ci	u32 outen[ZYNQMP_GPIO_MAX_BANK];
10962306a36Sopenharmony_ci	u32 int_en[ZYNQMP_GPIO_MAX_BANK];
11062306a36Sopenharmony_ci	u32 int_dis[ZYNQMP_GPIO_MAX_BANK];
11162306a36Sopenharmony_ci	u32 int_type[ZYNQMP_GPIO_MAX_BANK];
11262306a36Sopenharmony_ci	u32 int_polarity[ZYNQMP_GPIO_MAX_BANK];
11362306a36Sopenharmony_ci	u32 int_any[ZYNQMP_GPIO_MAX_BANK];
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/**
11762306a36Sopenharmony_ci * struct zynq_gpio - gpio device private data structure
11862306a36Sopenharmony_ci * @chip:	instance of the gpio_chip
11962306a36Sopenharmony_ci * @base_addr:	base address of the GPIO device
12062306a36Sopenharmony_ci * @clk:	clock resource for this controller
12162306a36Sopenharmony_ci * @irq:	interrupt for the GPIO device
12262306a36Sopenharmony_ci * @p_data:	pointer to platform data
12362306a36Sopenharmony_ci * @context:	context registers
12462306a36Sopenharmony_ci * @dirlock:	lock used for direction in/out synchronization
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_cistruct zynq_gpio {
12762306a36Sopenharmony_ci	struct gpio_chip chip;
12862306a36Sopenharmony_ci	void __iomem *base_addr;
12962306a36Sopenharmony_ci	struct clk *clk;
13062306a36Sopenharmony_ci	int irq;
13162306a36Sopenharmony_ci	const struct zynq_platform_data *p_data;
13262306a36Sopenharmony_ci	struct gpio_regs context;
13362306a36Sopenharmony_ci	spinlock_t dirlock; /* lock */
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/**
13762306a36Sopenharmony_ci * struct zynq_platform_data -  zynq gpio platform data structure
13862306a36Sopenharmony_ci * @label:	string to store in gpio->label
13962306a36Sopenharmony_ci * @quirks:	Flags is used to identify the platform
14062306a36Sopenharmony_ci * @ngpio:	max number of gpio pins
14162306a36Sopenharmony_ci * @max_bank:	maximum number of gpio banks
14262306a36Sopenharmony_ci * @bank_min:	this array represents bank's min pin
14362306a36Sopenharmony_ci * @bank_max:	this array represents bank's max pin
14462306a36Sopenharmony_ci */
14562306a36Sopenharmony_cistruct zynq_platform_data {
14662306a36Sopenharmony_ci	const char *label;
14762306a36Sopenharmony_ci	u32 quirks;
14862306a36Sopenharmony_ci	u16 ngpio;
14962306a36Sopenharmony_ci	int max_bank;
15062306a36Sopenharmony_ci	int bank_min[ZYNQMP_GPIO_MAX_BANK];
15162306a36Sopenharmony_ci	int bank_max[ZYNQMP_GPIO_MAX_BANK];
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic const struct irq_chip zynq_gpio_level_irqchip;
15562306a36Sopenharmony_cistatic const struct irq_chip zynq_gpio_edge_irqchip;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/**
15862306a36Sopenharmony_ci * zynq_gpio_is_zynq - test if HW is zynq or zynqmp
15962306a36Sopenharmony_ci * @gpio:	Pointer to driver data struct
16062306a36Sopenharmony_ci *
16162306a36Sopenharmony_ci * Return: 0 if zynqmp, 1 if zynq.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_cistatic int zynq_gpio_is_zynq(struct zynq_gpio *gpio)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	return !!(gpio->p_data->quirks & ZYNQ_GPIO_QUIRK_IS_ZYNQ);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/**
16962306a36Sopenharmony_ci * gpio_data_ro_bug - test if HW bug exists or not
17062306a36Sopenharmony_ci * @gpio:       Pointer to driver data struct
17162306a36Sopenharmony_ci *
17262306a36Sopenharmony_ci * Return: 0 if bug doesnot exist, 1 if bug exists.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_cistatic int gpio_data_ro_bug(struct zynq_gpio *gpio)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	return !!(gpio->p_data->quirks & GPIO_QUIRK_DATA_RO_BUG);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/**
18062306a36Sopenharmony_ci * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
18162306a36Sopenharmony_ci * for a given pin in the GPIO device
18262306a36Sopenharmony_ci * @pin_num:	gpio pin number within the device
18362306a36Sopenharmony_ci * @bank_num:	an output parameter used to return the bank number of the gpio
18462306a36Sopenharmony_ci *		pin
18562306a36Sopenharmony_ci * @bank_pin_num: an output parameter used to return pin number within a bank
18662306a36Sopenharmony_ci *		  for the given gpio pin
18762306a36Sopenharmony_ci * @gpio:	gpio device data structure
18862306a36Sopenharmony_ci *
18962306a36Sopenharmony_ci * Returns the bank number and pin offset within the bank.
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_cistatic inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
19262306a36Sopenharmony_ci					  unsigned int *bank_num,
19362306a36Sopenharmony_ci					  unsigned int *bank_pin_num,
19462306a36Sopenharmony_ci					  struct zynq_gpio *gpio)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	int bank;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	for (bank = 0; bank < gpio->p_data->max_bank; bank++) {
19962306a36Sopenharmony_ci		if ((pin_num >= gpio->p_data->bank_min[bank]) &&
20062306a36Sopenharmony_ci		    (pin_num <= gpio->p_data->bank_max[bank])) {
20162306a36Sopenharmony_ci			*bank_num = bank;
20262306a36Sopenharmony_ci			*bank_pin_num = pin_num -
20362306a36Sopenharmony_ci					gpio->p_data->bank_min[bank];
20462306a36Sopenharmony_ci			return;
20562306a36Sopenharmony_ci		}
20662306a36Sopenharmony_ci		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
20762306a36Sopenharmony_ci			bank = bank + VERSAL_UNUSED_BANKS;
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* default */
21162306a36Sopenharmony_ci	WARN(true, "invalid GPIO pin number: %u", pin_num);
21262306a36Sopenharmony_ci	*bank_num = 0;
21362306a36Sopenharmony_ci	*bank_pin_num = 0;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/**
21762306a36Sopenharmony_ci * zynq_gpio_get_value - Get the state of the specified pin of GPIO device
21862306a36Sopenharmony_ci * @chip:	gpio_chip instance to be worked on
21962306a36Sopenharmony_ci * @pin:	gpio pin number within the device
22062306a36Sopenharmony_ci *
22162306a36Sopenharmony_ci * This function reads the state of the specified pin of the GPIO device.
22262306a36Sopenharmony_ci *
22362306a36Sopenharmony_ci * Return: 0 if the pin is low, 1 if pin is high.
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_cistatic int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	u32 data;
22862306a36Sopenharmony_ci	unsigned int bank_num, bank_pin_num;
22962306a36Sopenharmony_ci	struct zynq_gpio *gpio = gpiochip_get_data(chip);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (gpio_data_ro_bug(gpio)) {
23462306a36Sopenharmony_ci		if (zynq_gpio_is_zynq(gpio)) {
23562306a36Sopenharmony_ci			if (bank_num <= 1) {
23662306a36Sopenharmony_ci				data = readl_relaxed(gpio->base_addr +
23762306a36Sopenharmony_ci					ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
23862306a36Sopenharmony_ci			} else {
23962306a36Sopenharmony_ci				data = readl_relaxed(gpio->base_addr +
24062306a36Sopenharmony_ci					ZYNQ_GPIO_DATA_OFFSET(bank_num));
24162306a36Sopenharmony_ci			}
24262306a36Sopenharmony_ci		} else {
24362306a36Sopenharmony_ci			if (bank_num <= 2) {
24462306a36Sopenharmony_ci				data = readl_relaxed(gpio->base_addr +
24562306a36Sopenharmony_ci					ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
24662306a36Sopenharmony_ci			} else {
24762306a36Sopenharmony_ci				data = readl_relaxed(gpio->base_addr +
24862306a36Sopenharmony_ci					ZYNQ_GPIO_DATA_OFFSET(bank_num));
24962306a36Sopenharmony_ci			}
25062306a36Sopenharmony_ci		}
25162306a36Sopenharmony_ci	} else {
25262306a36Sopenharmony_ci		data = readl_relaxed(gpio->base_addr +
25362306a36Sopenharmony_ci			ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci	return (data >> bank_pin_num) & 1;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/**
25962306a36Sopenharmony_ci * zynq_gpio_set_value - Modify the state of the pin with specified value
26062306a36Sopenharmony_ci * @chip:	gpio_chip instance to be worked on
26162306a36Sopenharmony_ci * @pin:	gpio pin number within the device
26262306a36Sopenharmony_ci * @state:	value used to modify the state of the specified pin
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci * This function calculates the register offset (i.e to lower 16 bits or
26562306a36Sopenharmony_ci * upper 16 bits) based on the given pin number and sets the state of a
26662306a36Sopenharmony_ci * gpio pin to the specified value. The state is either 0 or non-zero.
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistatic void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
26962306a36Sopenharmony_ci				int state)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	unsigned int reg_offset, bank_num, bank_pin_num;
27262306a36Sopenharmony_ci	struct zynq_gpio *gpio = gpiochip_get_data(chip);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
27762306a36Sopenharmony_ci		/* only 16 data bits in bit maskable reg */
27862306a36Sopenharmony_ci		bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
27962306a36Sopenharmony_ci		reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
28062306a36Sopenharmony_ci	} else {
28162306a36Sopenharmony_ci		reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/*
28562306a36Sopenharmony_ci	 * get the 32 bit value to be written to the mask/data register where
28662306a36Sopenharmony_ci	 * the upper 16 bits is the mask and lower 16 bits is the data
28762306a36Sopenharmony_ci	 */
28862306a36Sopenharmony_ci	state = !!state;
28962306a36Sopenharmony_ci	state = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
29062306a36Sopenharmony_ci		((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	writel_relaxed(state, gpio->base_addr + reg_offset);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/**
29662306a36Sopenharmony_ci * zynq_gpio_dir_in - Set the direction of the specified GPIO pin as input
29762306a36Sopenharmony_ci * @chip:	gpio_chip instance to be worked on
29862306a36Sopenharmony_ci * @pin:	gpio pin number within the device
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * This function uses the read-modify-write sequence to set the direction of
30162306a36Sopenharmony_ci * the gpio pin as input.
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci * Return: 0 always
30462306a36Sopenharmony_ci */
30562306a36Sopenharmony_cistatic int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	u32 reg;
30862306a36Sopenharmony_ci	unsigned int bank_num, bank_pin_num;
30962306a36Sopenharmony_ci	unsigned long flags;
31062306a36Sopenharmony_ci	struct zynq_gpio *gpio = gpiochip_get_data(chip);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/*
31562306a36Sopenharmony_ci	 * On zynq bank 0 pins 7 and 8 are special and cannot be used
31662306a36Sopenharmony_ci	 * as inputs.
31762306a36Sopenharmony_ci	 */
31862306a36Sopenharmony_ci	if (zynq_gpio_is_zynq(gpio) && bank_num == 0 &&
31962306a36Sopenharmony_ci	    (bank_pin_num == 7 || bank_pin_num == 8))
32062306a36Sopenharmony_ci		return -EINVAL;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	/* clear the bit in direction mode reg to set the pin as input */
32362306a36Sopenharmony_ci	spin_lock_irqsave(&gpio->dirlock, flags);
32462306a36Sopenharmony_ci	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
32562306a36Sopenharmony_ci	reg &= ~BIT(bank_pin_num);
32662306a36Sopenharmony_ci	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
32762306a36Sopenharmony_ci	spin_unlock_irqrestore(&gpio->dirlock, flags);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	return 0;
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci/**
33362306a36Sopenharmony_ci * zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output
33462306a36Sopenharmony_ci * @chip:	gpio_chip instance to be worked on
33562306a36Sopenharmony_ci * @pin:	gpio pin number within the device
33662306a36Sopenharmony_ci * @state:	value to be written to specified pin
33762306a36Sopenharmony_ci *
33862306a36Sopenharmony_ci * This function sets the direction of specified GPIO pin as output, configures
33962306a36Sopenharmony_ci * the Output Enable register for the pin and uses zynq_gpio_set to set
34062306a36Sopenharmony_ci * the state of the pin to the value specified.
34162306a36Sopenharmony_ci *
34262306a36Sopenharmony_ci * Return: 0 always
34362306a36Sopenharmony_ci */
34462306a36Sopenharmony_cistatic int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
34562306a36Sopenharmony_ci			     int state)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	u32 reg;
34862306a36Sopenharmony_ci	unsigned int bank_num, bank_pin_num;
34962306a36Sopenharmony_ci	unsigned long flags;
35062306a36Sopenharmony_ci	struct zynq_gpio *gpio = gpiochip_get_data(chip);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* set the GPIO pin as output */
35562306a36Sopenharmony_ci	spin_lock_irqsave(&gpio->dirlock, flags);
35662306a36Sopenharmony_ci	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
35762306a36Sopenharmony_ci	reg |= BIT(bank_pin_num);
35862306a36Sopenharmony_ci	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	/* configure the output enable reg for the pin */
36162306a36Sopenharmony_ci	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
36262306a36Sopenharmony_ci	reg |= BIT(bank_pin_num);
36362306a36Sopenharmony_ci	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
36462306a36Sopenharmony_ci	spin_unlock_irqrestore(&gpio->dirlock, flags);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	/* set the state of the pin */
36762306a36Sopenharmony_ci	zynq_gpio_set_value(chip, pin, state);
36862306a36Sopenharmony_ci	return 0;
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci/**
37262306a36Sopenharmony_ci * zynq_gpio_get_direction - Read the direction of the specified GPIO pin
37362306a36Sopenharmony_ci * @chip:	gpio_chip instance to be worked on
37462306a36Sopenharmony_ci * @pin:	gpio pin number within the device
37562306a36Sopenharmony_ci *
37662306a36Sopenharmony_ci * This function returns the direction of the specified GPIO.
37762306a36Sopenharmony_ci *
37862306a36Sopenharmony_ci * Return: GPIO_LINE_DIRECTION_OUT or GPIO_LINE_DIRECTION_IN
37962306a36Sopenharmony_ci */
38062306a36Sopenharmony_cistatic int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	u32 reg;
38362306a36Sopenharmony_ci	unsigned int bank_num, bank_pin_num;
38462306a36Sopenharmony_ci	struct zynq_gpio *gpio = gpiochip_get_data(chip);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (reg & BIT(bank_pin_num))
39162306a36Sopenharmony_ci		return GPIO_LINE_DIRECTION_OUT;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_IN;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci/**
39762306a36Sopenharmony_ci * zynq_gpio_irq_mask - Disable the interrupts for a gpio pin
39862306a36Sopenharmony_ci * @irq_data:	per irq and chip data passed down to chip functions
39962306a36Sopenharmony_ci *
40062306a36Sopenharmony_ci * This function calculates gpio pin number from irq number and sets the
40162306a36Sopenharmony_ci * bit in the Interrupt Disable register of the corresponding bank to disable
40262306a36Sopenharmony_ci * interrupts for that pin.
40362306a36Sopenharmony_ci */
40462306a36Sopenharmony_cistatic void zynq_gpio_irq_mask(struct irq_data *irq_data)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	unsigned int device_pin_num, bank_num, bank_pin_num;
40762306a36Sopenharmony_ci	const unsigned long offset = irqd_to_hwirq(irq_data);
40862306a36Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data);
40962306a36Sopenharmony_ci	struct zynq_gpio *gpio =
41062306a36Sopenharmony_ci		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	gpiochip_disable_irq(chip, offset);
41362306a36Sopenharmony_ci	device_pin_num = irq_data->hwirq;
41462306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
41562306a36Sopenharmony_ci	writel_relaxed(BIT(bank_pin_num),
41662306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci/**
42062306a36Sopenharmony_ci * zynq_gpio_irq_unmask - Enable the interrupts for a gpio pin
42162306a36Sopenharmony_ci * @irq_data:	irq data containing irq number of gpio pin for the interrupt
42262306a36Sopenharmony_ci *		to enable
42362306a36Sopenharmony_ci *
42462306a36Sopenharmony_ci * This function calculates the gpio pin number from irq number and sets the
42562306a36Sopenharmony_ci * bit in the Interrupt Enable register of the corresponding bank to enable
42662306a36Sopenharmony_ci * interrupts for that pin.
42762306a36Sopenharmony_ci */
42862306a36Sopenharmony_cistatic void zynq_gpio_irq_unmask(struct irq_data *irq_data)
42962306a36Sopenharmony_ci{
43062306a36Sopenharmony_ci	unsigned int device_pin_num, bank_num, bank_pin_num;
43162306a36Sopenharmony_ci	const unsigned long offset = irqd_to_hwirq(irq_data);
43262306a36Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data);
43362306a36Sopenharmony_ci	struct zynq_gpio *gpio =
43462306a36Sopenharmony_ci		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	gpiochip_enable_irq(chip, offset);
43762306a36Sopenharmony_ci	device_pin_num = irq_data->hwirq;
43862306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
43962306a36Sopenharmony_ci	writel_relaxed(BIT(bank_pin_num),
44062306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/**
44462306a36Sopenharmony_ci * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
44562306a36Sopenharmony_ci * @irq_data:	irq data containing irq number of gpio pin for the interrupt
44662306a36Sopenharmony_ci *		to ack
44762306a36Sopenharmony_ci *
44862306a36Sopenharmony_ci * This function calculates gpio pin number from irq number and sets the bit
44962306a36Sopenharmony_ci * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
45062306a36Sopenharmony_ci */
45162306a36Sopenharmony_cistatic void zynq_gpio_irq_ack(struct irq_data *irq_data)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	unsigned int device_pin_num, bank_num, bank_pin_num;
45462306a36Sopenharmony_ci	struct zynq_gpio *gpio =
45562306a36Sopenharmony_ci		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	device_pin_num = irq_data->hwirq;
45862306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
45962306a36Sopenharmony_ci	writel_relaxed(BIT(bank_pin_num),
46062306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
46162306a36Sopenharmony_ci}
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci/**
46462306a36Sopenharmony_ci * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
46562306a36Sopenharmony_ci * @irq_data:	irq data containing irq number of gpio pin for the interrupt
46662306a36Sopenharmony_ci *		to enable
46762306a36Sopenharmony_ci *
46862306a36Sopenharmony_ci * Clears the INTSTS bit and unmasks the given interrupt.
46962306a36Sopenharmony_ci */
47062306a36Sopenharmony_cistatic void zynq_gpio_irq_enable(struct irq_data *irq_data)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	/*
47362306a36Sopenharmony_ci	 * The Zynq GPIO controller does not disable interrupt detection when
47462306a36Sopenharmony_ci	 * the interrupt is masked and only disables the propagation of the
47562306a36Sopenharmony_ci	 * interrupt. This means when the controller detects an interrupt
47662306a36Sopenharmony_ci	 * condition while the interrupt is logically disabled it will propagate
47762306a36Sopenharmony_ci	 * that interrupt event once the interrupt is enabled. This will cause
47862306a36Sopenharmony_ci	 * the interrupt consumer to see spurious interrupts to prevent this
47962306a36Sopenharmony_ci	 * first make sure that the interrupt is not asserted and then enable
48062306a36Sopenharmony_ci	 * it.
48162306a36Sopenharmony_ci	 */
48262306a36Sopenharmony_ci	zynq_gpio_irq_ack(irq_data);
48362306a36Sopenharmony_ci	zynq_gpio_irq_unmask(irq_data);
48462306a36Sopenharmony_ci}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci/**
48762306a36Sopenharmony_ci * zynq_gpio_set_irq_type - Set the irq type for a gpio pin
48862306a36Sopenharmony_ci * @irq_data:	irq data containing irq number of gpio pin
48962306a36Sopenharmony_ci * @type:	interrupt type that is to be set for the gpio pin
49062306a36Sopenharmony_ci *
49162306a36Sopenharmony_ci * This function gets the gpio pin number and its bank from the gpio pin number
49262306a36Sopenharmony_ci * and configures the INT_TYPE, INT_POLARITY and INT_ANY registers.
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * Return: 0, negative error otherwise.
49562306a36Sopenharmony_ci * TYPE-EDGE_RISING,  INT_TYPE - 1, INT_POLARITY - 1,  INT_ANY - 0;
49662306a36Sopenharmony_ci * TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0,  INT_ANY - 0;
49762306a36Sopenharmony_ci * TYPE-EDGE_BOTH,    INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1;
49862306a36Sopenharmony_ci * TYPE-LEVEL_HIGH,   INT_TYPE - 0, INT_POLARITY - 1,  INT_ANY - NA;
49962306a36Sopenharmony_ci * TYPE-LEVEL_LOW,    INT_TYPE - 0, INT_POLARITY - 0,  INT_ANY - NA
50062306a36Sopenharmony_ci */
50162306a36Sopenharmony_cistatic int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	u32 int_type, int_pol, int_any;
50462306a36Sopenharmony_ci	unsigned int device_pin_num, bank_num, bank_pin_num;
50562306a36Sopenharmony_ci	struct zynq_gpio *gpio =
50662306a36Sopenharmony_ci		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	device_pin_num = irq_data->hwirq;
50962306a36Sopenharmony_ci	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	int_type = readl_relaxed(gpio->base_addr +
51262306a36Sopenharmony_ci				 ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
51362306a36Sopenharmony_ci	int_pol = readl_relaxed(gpio->base_addr +
51462306a36Sopenharmony_ci				ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
51562306a36Sopenharmony_ci	int_any = readl_relaxed(gpio->base_addr +
51662306a36Sopenharmony_ci				ZYNQ_GPIO_INTANY_OFFSET(bank_num));
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/*
51962306a36Sopenharmony_ci	 * based on the type requested, configure the INT_TYPE, INT_POLARITY
52062306a36Sopenharmony_ci	 * and INT_ANY registers
52162306a36Sopenharmony_ci	 */
52262306a36Sopenharmony_ci	switch (type) {
52362306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_RISING:
52462306a36Sopenharmony_ci		int_type |= BIT(bank_pin_num);
52562306a36Sopenharmony_ci		int_pol |= BIT(bank_pin_num);
52662306a36Sopenharmony_ci		int_any &= ~BIT(bank_pin_num);
52762306a36Sopenharmony_ci		break;
52862306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_FALLING:
52962306a36Sopenharmony_ci		int_type |= BIT(bank_pin_num);
53062306a36Sopenharmony_ci		int_pol &= ~BIT(bank_pin_num);
53162306a36Sopenharmony_ci		int_any &= ~BIT(bank_pin_num);
53262306a36Sopenharmony_ci		break;
53362306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_BOTH:
53462306a36Sopenharmony_ci		int_type |= BIT(bank_pin_num);
53562306a36Sopenharmony_ci		int_any |= BIT(bank_pin_num);
53662306a36Sopenharmony_ci		break;
53762306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_HIGH:
53862306a36Sopenharmony_ci		int_type &= ~BIT(bank_pin_num);
53962306a36Sopenharmony_ci		int_pol |= BIT(bank_pin_num);
54062306a36Sopenharmony_ci		break;
54162306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_LOW:
54262306a36Sopenharmony_ci		int_type &= ~BIT(bank_pin_num);
54362306a36Sopenharmony_ci		int_pol &= ~BIT(bank_pin_num);
54462306a36Sopenharmony_ci		break;
54562306a36Sopenharmony_ci	default:
54662306a36Sopenharmony_ci		return -EINVAL;
54762306a36Sopenharmony_ci	}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	writel_relaxed(int_type,
55062306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
55162306a36Sopenharmony_ci	writel_relaxed(int_pol,
55262306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
55362306a36Sopenharmony_ci	writel_relaxed(int_any,
55462306a36Sopenharmony_ci		       gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (type & IRQ_TYPE_LEVEL_MASK)
55762306a36Sopenharmony_ci		irq_set_chip_handler_name_locked(irq_data,
55862306a36Sopenharmony_ci						 &zynq_gpio_level_irqchip,
55962306a36Sopenharmony_ci						 handle_fasteoi_irq, NULL);
56062306a36Sopenharmony_ci	else
56162306a36Sopenharmony_ci		irq_set_chip_handler_name_locked(irq_data,
56262306a36Sopenharmony_ci						 &zynq_gpio_edge_irqchip,
56362306a36Sopenharmony_ci						 handle_level_irq, NULL);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	return 0;
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	struct zynq_gpio *gpio =
57162306a36Sopenharmony_ci		gpiochip_get_data(irq_data_get_irq_chip_data(data));
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	irq_set_irq_wake(gpio->irq, on);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	return 0;
57662306a36Sopenharmony_ci}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_cistatic int zynq_gpio_irq_reqres(struct irq_data *d)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
58162306a36Sopenharmony_ci	int ret;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(chip->parent);
58462306a36Sopenharmony_ci	if (ret < 0)
58562306a36Sopenharmony_ci		return ret;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	return gpiochip_reqres_irq(chip, d->hwirq);
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic void zynq_gpio_irq_relres(struct irq_data *d)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	gpiochip_relres_irq(chip, d->hwirq);
59562306a36Sopenharmony_ci	pm_runtime_put(chip->parent);
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/* irq chip descriptor */
59962306a36Sopenharmony_cistatic const struct irq_chip zynq_gpio_level_irqchip = {
60062306a36Sopenharmony_ci	.name		= DRIVER_NAME,
60162306a36Sopenharmony_ci	.irq_enable	= zynq_gpio_irq_enable,
60262306a36Sopenharmony_ci	.irq_eoi	= zynq_gpio_irq_ack,
60362306a36Sopenharmony_ci	.irq_mask	= zynq_gpio_irq_mask,
60462306a36Sopenharmony_ci	.irq_unmask	= zynq_gpio_irq_unmask,
60562306a36Sopenharmony_ci	.irq_set_type	= zynq_gpio_set_irq_type,
60662306a36Sopenharmony_ci	.irq_set_wake	= zynq_gpio_set_wake,
60762306a36Sopenharmony_ci	.irq_request_resources = zynq_gpio_irq_reqres,
60862306a36Sopenharmony_ci	.irq_release_resources = zynq_gpio_irq_relres,
60962306a36Sopenharmony_ci	.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
61062306a36Sopenharmony_ci			  IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
61162306a36Sopenharmony_ci};
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic const struct irq_chip zynq_gpio_edge_irqchip = {
61462306a36Sopenharmony_ci	.name		= DRIVER_NAME,
61562306a36Sopenharmony_ci	.irq_enable	= zynq_gpio_irq_enable,
61662306a36Sopenharmony_ci	.irq_ack	= zynq_gpio_irq_ack,
61762306a36Sopenharmony_ci	.irq_mask	= zynq_gpio_irq_mask,
61862306a36Sopenharmony_ci	.irq_unmask	= zynq_gpio_irq_unmask,
61962306a36Sopenharmony_ci	.irq_set_type	= zynq_gpio_set_irq_type,
62062306a36Sopenharmony_ci	.irq_set_wake	= zynq_gpio_set_wake,
62162306a36Sopenharmony_ci	.irq_request_resources = zynq_gpio_irq_reqres,
62262306a36Sopenharmony_ci	.irq_release_resources = zynq_gpio_irq_relres,
62362306a36Sopenharmony_ci	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
62462306a36Sopenharmony_ci};
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistatic void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
62762306a36Sopenharmony_ci				      unsigned int bank_num,
62862306a36Sopenharmony_ci				      unsigned long pending)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	unsigned int bank_offset = gpio->p_data->bank_min[bank_num];
63162306a36Sopenharmony_ci	struct irq_domain *irqdomain = gpio->chip.irq.domain;
63262306a36Sopenharmony_ci	int offset;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	if (!pending)
63562306a36Sopenharmony_ci		return;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	for_each_set_bit(offset, &pending, 32)
63862306a36Sopenharmony_ci		generic_handle_domain_irq(irqdomain, offset + bank_offset);
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci/**
64262306a36Sopenharmony_ci * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
64362306a36Sopenharmony_ci * @desc:	irq descriptor instance of the 'irq'
64462306a36Sopenharmony_ci *
64562306a36Sopenharmony_ci * This function reads the Interrupt Status Register of each bank to get the
64662306a36Sopenharmony_ci * gpio pin number which has triggered an interrupt. It then acks the triggered
64762306a36Sopenharmony_ci * interrupt and calls the pin specific handler set by the higher layer
64862306a36Sopenharmony_ci * application for that pin.
64962306a36Sopenharmony_ci * Note: A bug is reported if no handler is set for the gpio pin.
65062306a36Sopenharmony_ci */
65162306a36Sopenharmony_cistatic void zynq_gpio_irqhandler(struct irq_desc *desc)
65262306a36Sopenharmony_ci{
65362306a36Sopenharmony_ci	u32 int_sts, int_enb;
65462306a36Sopenharmony_ci	unsigned int bank_num;
65562306a36Sopenharmony_ci	struct zynq_gpio *gpio =
65662306a36Sopenharmony_ci		gpiochip_get_data(irq_desc_get_handler_data(desc));
65762306a36Sopenharmony_ci	struct irq_chip *irqchip = irq_desc_get_chip(desc);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	chained_irq_enter(irqchip, desc);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
66262306a36Sopenharmony_ci		int_sts = readl_relaxed(gpio->base_addr +
66362306a36Sopenharmony_ci					ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
66462306a36Sopenharmony_ci		int_enb = readl_relaxed(gpio->base_addr +
66562306a36Sopenharmony_ci					ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
66662306a36Sopenharmony_ci		zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
66762306a36Sopenharmony_ci		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
66862306a36Sopenharmony_ci			bank_num = bank_num + VERSAL_UNUSED_BANKS;
66962306a36Sopenharmony_ci	}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	chained_irq_exit(irqchip, desc);
67262306a36Sopenharmony_ci}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic void zynq_gpio_save_context(struct zynq_gpio *gpio)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	unsigned int bank_num;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
67962306a36Sopenharmony_ci		gpio->context.datalsw[bank_num] =
68062306a36Sopenharmony_ci				readl_relaxed(gpio->base_addr +
68162306a36Sopenharmony_ci				ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
68262306a36Sopenharmony_ci		gpio->context.datamsw[bank_num] =
68362306a36Sopenharmony_ci				readl_relaxed(gpio->base_addr +
68462306a36Sopenharmony_ci				ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num));
68562306a36Sopenharmony_ci		gpio->context.dirm[bank_num] = readl_relaxed(gpio->base_addr +
68662306a36Sopenharmony_ci				ZYNQ_GPIO_DIRM_OFFSET(bank_num));
68762306a36Sopenharmony_ci		gpio->context.int_en[bank_num] = readl_relaxed(gpio->base_addr +
68862306a36Sopenharmony_ci				ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
68962306a36Sopenharmony_ci		gpio->context.int_type[bank_num] =
69062306a36Sopenharmony_ci				readl_relaxed(gpio->base_addr +
69162306a36Sopenharmony_ci				ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
69262306a36Sopenharmony_ci		gpio->context.int_polarity[bank_num] =
69362306a36Sopenharmony_ci				readl_relaxed(gpio->base_addr +
69462306a36Sopenharmony_ci				ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
69562306a36Sopenharmony_ci		gpio->context.int_any[bank_num] =
69662306a36Sopenharmony_ci				readl_relaxed(gpio->base_addr +
69762306a36Sopenharmony_ci				ZYNQ_GPIO_INTANY_OFFSET(bank_num));
69862306a36Sopenharmony_ci		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
69962306a36Sopenharmony_ci			bank_num = bank_num + VERSAL_UNUSED_BANKS;
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_cistatic void zynq_gpio_restore_context(struct zynq_gpio *gpio)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	unsigned int bank_num;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
70862306a36Sopenharmony_ci		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
70962306a36Sopenharmony_ci				ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
71062306a36Sopenharmony_ci		writel_relaxed(gpio->context.datalsw[bank_num],
71162306a36Sopenharmony_ci			       gpio->base_addr +
71262306a36Sopenharmony_ci			       ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
71362306a36Sopenharmony_ci		writel_relaxed(gpio->context.datamsw[bank_num],
71462306a36Sopenharmony_ci			       gpio->base_addr +
71562306a36Sopenharmony_ci			       ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num));
71662306a36Sopenharmony_ci		writel_relaxed(gpio->context.dirm[bank_num],
71762306a36Sopenharmony_ci			       gpio->base_addr +
71862306a36Sopenharmony_ci			       ZYNQ_GPIO_DIRM_OFFSET(bank_num));
71962306a36Sopenharmony_ci		writel_relaxed(gpio->context.int_type[bank_num],
72062306a36Sopenharmony_ci			       gpio->base_addr +
72162306a36Sopenharmony_ci			       ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
72262306a36Sopenharmony_ci		writel_relaxed(gpio->context.int_polarity[bank_num],
72362306a36Sopenharmony_ci			       gpio->base_addr +
72462306a36Sopenharmony_ci			       ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
72562306a36Sopenharmony_ci		writel_relaxed(gpio->context.int_any[bank_num],
72662306a36Sopenharmony_ci			       gpio->base_addr +
72762306a36Sopenharmony_ci			       ZYNQ_GPIO_INTANY_OFFSET(bank_num));
72862306a36Sopenharmony_ci		writel_relaxed(~(gpio->context.int_en[bank_num]),
72962306a36Sopenharmony_ci			       gpio->base_addr +
73062306a36Sopenharmony_ci			       ZYNQ_GPIO_INTEN_OFFSET(bank_num));
73162306a36Sopenharmony_ci		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
73262306a36Sopenharmony_ci			bank_num = bank_num + VERSAL_UNUSED_BANKS;
73362306a36Sopenharmony_ci	}
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_cistatic int __maybe_unused zynq_gpio_suspend(struct device *dev)
73762306a36Sopenharmony_ci{
73862306a36Sopenharmony_ci	struct zynq_gpio *gpio = dev_get_drvdata(dev);
73962306a36Sopenharmony_ci	struct irq_data *data = irq_get_irq_data(gpio->irq);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	if (!data) {
74262306a36Sopenharmony_ci		dev_err(dev, "irq_get_irq_data() failed\n");
74362306a36Sopenharmony_ci		return -EINVAL;
74462306a36Sopenharmony_ci	}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	if (!device_may_wakeup(dev))
74762306a36Sopenharmony_ci		disable_irq(gpio->irq);
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	if (!irqd_is_wakeup_set(data)) {
75062306a36Sopenharmony_ci		zynq_gpio_save_context(gpio);
75162306a36Sopenharmony_ci		return pm_runtime_force_suspend(dev);
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	return 0;
75562306a36Sopenharmony_ci}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_cistatic int __maybe_unused zynq_gpio_resume(struct device *dev)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	struct zynq_gpio *gpio = dev_get_drvdata(dev);
76062306a36Sopenharmony_ci	struct irq_data *data = irq_get_irq_data(gpio->irq);
76162306a36Sopenharmony_ci	int ret;
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	if (!data) {
76462306a36Sopenharmony_ci		dev_err(dev, "irq_get_irq_data() failed\n");
76562306a36Sopenharmony_ci		return -EINVAL;
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	if (!device_may_wakeup(dev))
76962306a36Sopenharmony_ci		enable_irq(gpio->irq);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	if (!irqd_is_wakeup_set(data)) {
77262306a36Sopenharmony_ci		ret = pm_runtime_force_resume(dev);
77362306a36Sopenharmony_ci		zynq_gpio_restore_context(gpio);
77462306a36Sopenharmony_ci		return ret;
77562306a36Sopenharmony_ci	}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	return 0;
77862306a36Sopenharmony_ci}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_cistatic int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci	struct zynq_gpio *gpio = dev_get_drvdata(dev);
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	clk_disable_unprepare(gpio->clk);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	return 0;
78762306a36Sopenharmony_ci}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistatic int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	struct zynq_gpio *gpio = dev_get_drvdata(dev);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	return clk_prepare_enable(gpio->clk);
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	int ret;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	ret = pm_runtime_get_sync(chip->parent);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	/*
80362306a36Sopenharmony_ci	 * If the device is already active pm_runtime_get() will return 1 on
80462306a36Sopenharmony_ci	 * success, but gpio_request still needs to return 0.
80562306a36Sopenharmony_ci	 */
80662306a36Sopenharmony_ci	return ret < 0 ? ret : 0;
80762306a36Sopenharmony_ci}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	pm_runtime_put(chip->parent);
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_cistatic const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
81562306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume)
81662306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
81762306a36Sopenharmony_ci			   zynq_gpio_runtime_resume, NULL)
81862306a36Sopenharmony_ci};
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_cistatic const struct zynq_platform_data versal_gpio_def = {
82162306a36Sopenharmony_ci	.label = "versal_gpio",
82262306a36Sopenharmony_ci	.quirks = GPIO_QUIRK_VERSAL,
82362306a36Sopenharmony_ci	.ngpio = 58,
82462306a36Sopenharmony_ci	.max_bank = VERSAL_GPIO_MAX_BANK,
82562306a36Sopenharmony_ci	.bank_min[0] = 0,
82662306a36Sopenharmony_ci	.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
82762306a36Sopenharmony_ci	.bank_min[3] = 26,
82862306a36Sopenharmony_ci	.bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */
82962306a36Sopenharmony_ci};
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_cistatic const struct zynq_platform_data pmc_gpio_def = {
83262306a36Sopenharmony_ci	.label = "pmc_gpio",
83362306a36Sopenharmony_ci	.ngpio = 116,
83462306a36Sopenharmony_ci	.max_bank = PMC_GPIO_MAX_BANK,
83562306a36Sopenharmony_ci	.bank_min[0] = 0,
83662306a36Sopenharmony_ci	.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
83762306a36Sopenharmony_ci	.bank_min[1] = 26,
83862306a36Sopenharmony_ci	.bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */
83962306a36Sopenharmony_ci	.bank_min[3] = 52,
84062306a36Sopenharmony_ci	.bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */
84162306a36Sopenharmony_ci	.bank_min[4] = 84,
84262306a36Sopenharmony_ci	.bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */
84362306a36Sopenharmony_ci};
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_cistatic const struct zynq_platform_data zynqmp_gpio_def = {
84662306a36Sopenharmony_ci	.label = "zynqmp_gpio",
84762306a36Sopenharmony_ci	.quirks = GPIO_QUIRK_DATA_RO_BUG,
84862306a36Sopenharmony_ci	.ngpio = ZYNQMP_GPIO_NR_GPIOS,
84962306a36Sopenharmony_ci	.max_bank = ZYNQMP_GPIO_MAX_BANK,
85062306a36Sopenharmony_ci	.bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(MP),
85162306a36Sopenharmony_ci	.bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(MP),
85262306a36Sopenharmony_ci	.bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(MP),
85362306a36Sopenharmony_ci	.bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(MP),
85462306a36Sopenharmony_ci	.bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(MP),
85562306a36Sopenharmony_ci	.bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(MP),
85662306a36Sopenharmony_ci	.bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(MP),
85762306a36Sopenharmony_ci	.bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(MP),
85862306a36Sopenharmony_ci	.bank_min[4] = ZYNQ_GPIO_BANK4_PIN_MIN(MP),
85962306a36Sopenharmony_ci	.bank_max[4] = ZYNQ_GPIO_BANK4_PIN_MAX(MP),
86062306a36Sopenharmony_ci	.bank_min[5] = ZYNQ_GPIO_BANK5_PIN_MIN(MP),
86162306a36Sopenharmony_ci	.bank_max[5] = ZYNQ_GPIO_BANK5_PIN_MAX(MP),
86262306a36Sopenharmony_ci};
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_cistatic const struct zynq_platform_data zynq_gpio_def = {
86562306a36Sopenharmony_ci	.label = "zynq_gpio",
86662306a36Sopenharmony_ci	.quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ | GPIO_QUIRK_DATA_RO_BUG,
86762306a36Sopenharmony_ci	.ngpio = ZYNQ_GPIO_NR_GPIOS,
86862306a36Sopenharmony_ci	.max_bank = ZYNQ_GPIO_MAX_BANK,
86962306a36Sopenharmony_ci	.bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(),
87062306a36Sopenharmony_ci	.bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(),
87162306a36Sopenharmony_ci	.bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(),
87262306a36Sopenharmony_ci	.bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(),
87362306a36Sopenharmony_ci	.bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(),
87462306a36Sopenharmony_ci	.bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(),
87562306a36Sopenharmony_ci	.bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(),
87662306a36Sopenharmony_ci	.bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(),
87762306a36Sopenharmony_ci};
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic const struct of_device_id zynq_gpio_of_match[] = {
88062306a36Sopenharmony_ci	{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
88162306a36Sopenharmony_ci	{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
88262306a36Sopenharmony_ci	{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
88362306a36Sopenharmony_ci	{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
88462306a36Sopenharmony_ci	{ /* end of table */ }
88562306a36Sopenharmony_ci};
88662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci/**
88962306a36Sopenharmony_ci * zynq_gpio_probe - Initialization method for a zynq_gpio device
89062306a36Sopenharmony_ci * @pdev:	platform device instance
89162306a36Sopenharmony_ci *
89262306a36Sopenharmony_ci * This function allocates memory resources for the gpio device and registers
89362306a36Sopenharmony_ci * all the banks of the device. It will also set up interrupts for the gpio
89462306a36Sopenharmony_ci * pins.
89562306a36Sopenharmony_ci * Note: Interrupts are disabled for all the banks during initialization.
89662306a36Sopenharmony_ci *
89762306a36Sopenharmony_ci * Return: 0 on success, negative error otherwise.
89862306a36Sopenharmony_ci */
89962306a36Sopenharmony_cistatic int zynq_gpio_probe(struct platform_device *pdev)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	int ret, bank_num;
90262306a36Sopenharmony_ci	struct zynq_gpio *gpio;
90362306a36Sopenharmony_ci	struct gpio_chip *chip;
90462306a36Sopenharmony_ci	struct gpio_irq_chip *girq;
90562306a36Sopenharmony_ci	const struct of_device_id *match;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
90862306a36Sopenharmony_ci	if (!gpio)
90962306a36Sopenharmony_ci		return -ENOMEM;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	match = of_match_node(zynq_gpio_of_match, pdev->dev.of_node);
91262306a36Sopenharmony_ci	if (!match) {
91362306a36Sopenharmony_ci		dev_err(&pdev->dev, "of_match_node() failed\n");
91462306a36Sopenharmony_ci		return -EINVAL;
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci	gpio->p_data = match->data;
91762306a36Sopenharmony_ci	platform_set_drvdata(pdev, gpio);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	gpio->base_addr = devm_platform_ioremap_resource(pdev, 0);
92062306a36Sopenharmony_ci	if (IS_ERR(gpio->base_addr))
92162306a36Sopenharmony_ci		return PTR_ERR(gpio->base_addr);
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	gpio->irq = platform_get_irq(pdev, 0);
92462306a36Sopenharmony_ci	if (gpio->irq < 0)
92562306a36Sopenharmony_ci		return gpio->irq;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	/* configure the gpio chip */
92862306a36Sopenharmony_ci	chip = &gpio->chip;
92962306a36Sopenharmony_ci	chip->label = gpio->p_data->label;
93062306a36Sopenharmony_ci	chip->owner = THIS_MODULE;
93162306a36Sopenharmony_ci	chip->parent = &pdev->dev;
93262306a36Sopenharmony_ci	chip->get = zynq_gpio_get_value;
93362306a36Sopenharmony_ci	chip->set = zynq_gpio_set_value;
93462306a36Sopenharmony_ci	chip->request = zynq_gpio_request;
93562306a36Sopenharmony_ci	chip->free = zynq_gpio_free;
93662306a36Sopenharmony_ci	chip->direction_input = zynq_gpio_dir_in;
93762306a36Sopenharmony_ci	chip->direction_output = zynq_gpio_dir_out;
93862306a36Sopenharmony_ci	chip->get_direction = zynq_gpio_get_direction;
93962306a36Sopenharmony_ci	chip->base = of_alias_get_id(pdev->dev.of_node, "gpio");
94062306a36Sopenharmony_ci	chip->ngpio = gpio->p_data->ngpio;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/* Retrieve GPIO clock */
94362306a36Sopenharmony_ci	gpio->clk = devm_clk_get(&pdev->dev, NULL);
94462306a36Sopenharmony_ci	if (IS_ERR(gpio->clk))
94562306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found.\n");
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	ret = clk_prepare_enable(gpio->clk);
94862306a36Sopenharmony_ci	if (ret) {
94962306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unable to enable clock.\n");
95062306a36Sopenharmony_ci		return ret;
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	spin_lock_init(&gpio->dirlock);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
95662306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
95762306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(&pdev->dev);
95862306a36Sopenharmony_ci	if (ret < 0)
95962306a36Sopenharmony_ci		goto err_pm_dis;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	/* disable interrupts for all banks */
96262306a36Sopenharmony_ci	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
96362306a36Sopenharmony_ci		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
96462306a36Sopenharmony_ci			       ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
96562306a36Sopenharmony_ci		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
96662306a36Sopenharmony_ci			bank_num = bank_num + VERSAL_UNUSED_BANKS;
96762306a36Sopenharmony_ci	}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	/* Set up the GPIO irqchip */
97062306a36Sopenharmony_ci	girq = &chip->irq;
97162306a36Sopenharmony_ci	gpio_irq_chip_set_chip(girq, &zynq_gpio_edge_irqchip);
97262306a36Sopenharmony_ci	girq->parent_handler = zynq_gpio_irqhandler;
97362306a36Sopenharmony_ci	girq->num_parents = 1;
97462306a36Sopenharmony_ci	girq->parents = devm_kcalloc(&pdev->dev, 1,
97562306a36Sopenharmony_ci				     sizeof(*girq->parents),
97662306a36Sopenharmony_ci				     GFP_KERNEL);
97762306a36Sopenharmony_ci	if (!girq->parents) {
97862306a36Sopenharmony_ci		ret = -ENOMEM;
97962306a36Sopenharmony_ci		goto err_pm_put;
98062306a36Sopenharmony_ci	}
98162306a36Sopenharmony_ci	girq->parents[0] = gpio->irq;
98262306a36Sopenharmony_ci	girq->default_type = IRQ_TYPE_NONE;
98362306a36Sopenharmony_ci	girq->handler = handle_level_irq;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	/* report a bug if gpio chip registration fails */
98662306a36Sopenharmony_ci	ret = gpiochip_add_data(chip, gpio);
98762306a36Sopenharmony_ci	if (ret) {
98862306a36Sopenharmony_ci		dev_err(&pdev->dev, "Failed to add gpio chip\n");
98962306a36Sopenharmony_ci		goto err_pm_put;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY);
99362306a36Sopenharmony_ci	device_init_wakeup(&pdev->dev, 1);
99462306a36Sopenharmony_ci	pm_runtime_put(&pdev->dev);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	return 0;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_cierr_pm_put:
99962306a36Sopenharmony_ci	pm_runtime_put(&pdev->dev);
100062306a36Sopenharmony_cierr_pm_dis:
100162306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
100262306a36Sopenharmony_ci	clk_disable_unprepare(gpio->clk);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	return ret;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci/**
100862306a36Sopenharmony_ci * zynq_gpio_remove - Driver removal function
100962306a36Sopenharmony_ci * @pdev:	platform device instance
101062306a36Sopenharmony_ci *
101162306a36Sopenharmony_ci * Return: 0 always
101262306a36Sopenharmony_ci */
101362306a36Sopenharmony_cistatic int zynq_gpio_remove(struct platform_device *pdev)
101462306a36Sopenharmony_ci{
101562306a36Sopenharmony_ci	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
101662306a36Sopenharmony_ci	int ret;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	ret = pm_runtime_get_sync(&pdev->dev);
101962306a36Sopenharmony_ci	if (ret < 0)
102062306a36Sopenharmony_ci		dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n");
102162306a36Sopenharmony_ci	gpiochip_remove(&gpio->chip);
102262306a36Sopenharmony_ci	clk_disable_unprepare(gpio->clk);
102362306a36Sopenharmony_ci	device_set_wakeup_capable(&pdev->dev, 0);
102462306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
102562306a36Sopenharmony_ci	return 0;
102662306a36Sopenharmony_ci}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_cistatic struct platform_driver zynq_gpio_driver = {
102962306a36Sopenharmony_ci	.driver	= {
103062306a36Sopenharmony_ci		.name = DRIVER_NAME,
103162306a36Sopenharmony_ci		.pm = &zynq_gpio_dev_pm_ops,
103262306a36Sopenharmony_ci		.of_match_table = zynq_gpio_of_match,
103362306a36Sopenharmony_ci	},
103462306a36Sopenharmony_ci	.probe = zynq_gpio_probe,
103562306a36Sopenharmony_ci	.remove = zynq_gpio_remove,
103662306a36Sopenharmony_ci};
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_cimodule_platform_driver(zynq_gpio_driver);
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ciMODULE_AUTHOR("Xilinx Inc.");
104162306a36Sopenharmony_ciMODULE_DESCRIPTION("Zynq GPIO driver");
104262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1043