xref: /linux/drivers/gpio/gpio-xilinx.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
16e75fc04SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c103de24SGrant Likely /*
374600ee0SMichal Simek  * Xilinx gpio driver for xps/axi_gpio IP.
4c103de24SGrant Likely  *
574600ee0SMichal Simek  * Copyright 2008 - 2013 Xilinx, Inc.
6c103de24SGrant Likely  */
7c103de24SGrant Likely 
802b3f84dSAndy Shevchenko #include <linux/bitmap.h>
974600ee0SMichal Simek #include <linux/bitops.h>
1065bbe531SSrinivas Neeli #include <linux/clk.h>
11c103de24SGrant Likely #include <linux/errno.h>
128c669fe6SSrinivas Neeli #include <linux/gpio/driver.h>
138c669fe6SSrinivas Neeli #include <linux/init.h>
14a32c7caeSSrinivas Neeli #include <linux/interrupt.h>
158c669fe6SSrinivas Neeli #include <linux/io.h>
16a32c7caeSSrinivas Neeli #include <linux/irq.h>
17bb207ef1SPaul Gortmaker #include <linux/module.h>
18e91d0f05SRob Herring #include <linux/of.h>
19e91d0f05SRob Herring #include <linux/platform_device.h>
2026b04774SSrinivas Neeli #include <linux/pm_runtime.h>
21c103de24SGrant Likely #include <linux/slab.h>
22c103de24SGrant Likely 
23c103de24SGrant Likely /* Register Offset Definitions */
24c103de24SGrant Likely #define XGPIO_DATA_OFFSET   (0x0)	/* Data register  */
25c103de24SGrant Likely #define XGPIO_TRI_OFFSET    (0x4)	/* I/O direction register  */
26c103de24SGrant Likely 
27043aa3dbSAndy Shevchenko #define XGPIO_CHANNEL0_OFFSET	0x0
28043aa3dbSAndy Shevchenko #define XGPIO_CHANNEL1_OFFSET	0x8
2974600ee0SMichal Simek 
30a32c7caeSSrinivas Neeli #define XGPIO_GIER_OFFSET	0x11c /* Global Interrupt Enable */
31a32c7caeSSrinivas Neeli #define XGPIO_GIER_IE		BIT(31)
32a32c7caeSSrinivas Neeli #define XGPIO_IPISR_OFFSET	0x120 /* IP Interrupt Status */
33a32c7caeSSrinivas Neeli #define XGPIO_IPIER_OFFSET	0x128 /* IP Interrupt Enable */
34a32c7caeSSrinivas Neeli 
3574600ee0SMichal Simek /* Read/Write access to the GPIO registers */
36c54c58baSRicardo Ribalda Delgado #if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86)
37cc090d61SMichal Simek # define xgpio_readreg(offset)		readl(offset)
38cc090d61SMichal Simek # define xgpio_writereg(offset, val)	writel(val, offset)
39cc090d61SMichal Simek #else
40cc090d61SMichal Simek # define xgpio_readreg(offset)		__raw_readl(offset)
41cc090d61SMichal Simek # define xgpio_writereg(offset, val)	__raw_writel(val, offset)
42cc090d61SMichal Simek #endif
4374600ee0SMichal Simek 
4474600ee0SMichal Simek /**
4574600ee0SMichal Simek  * struct xgpio_instance - Stores information about GPIO device
461ebd0687SRobert Hancock  * @gc: GPIO chip
471ebd0687SRobert Hancock  * @regs: register block
4802b3f84dSAndy Shevchenko  * @hw_map: GPIO pin mapping on hardware side
4902b3f84dSAndy Shevchenko  * @sw_map: GPIO pin mapping on software side
5002b3f84dSAndy Shevchenko  * @state: GPIO write state shadow register
5102b3f84dSAndy Shevchenko  * @last_irq_read: GPIO read state register from last interrupt
5202b3f84dSAndy Shevchenko  * @dir: GPIO direction shadow register
534ae798faSRicardo Ribalda Delgado  * @gpio_lock: Lock used for synchronization
54a32c7caeSSrinivas Neeli  * @irq: IRQ used by GPIO device
5502b3f84dSAndy Shevchenko  * @enable: GPIO IRQ enable/disable bitfield
5602b3f84dSAndy Shevchenko  * @rising_edge: GPIO IRQ rising edge enable/disable bitfield
5702b3f84dSAndy Shevchenko  * @falling_edge: GPIO IRQ falling edge enable/disable bitfield
5865bbe531SSrinivas Neeli  * @clk: clock resource for this driver
5974600ee0SMichal Simek  */
60c103de24SGrant Likely struct xgpio_instance {
611ebd0687SRobert Hancock 	struct gpio_chip gc;
621ebd0687SRobert Hancock 	void __iomem *regs;
6302b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_map, 64);
6402b3f84dSAndy Shevchenko 	DECLARE_BITMAP(sw_map, 64);
6502b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
6602b3f84dSAndy Shevchenko 	DECLARE_BITMAP(last_irq_read, 64);
6702b3f84dSAndy Shevchenko 	DECLARE_BITMAP(dir, 64);
6837ef3346SSrinivas Neeli 	spinlock_t gpio_lock;	/* For serializing operations */
69a32c7caeSSrinivas Neeli 	int irq;
7002b3f84dSAndy Shevchenko 	DECLARE_BITMAP(enable, 64);
7102b3f84dSAndy Shevchenko 	DECLARE_BITMAP(rising_edge, 64);
7202b3f84dSAndy Shevchenko 	DECLARE_BITMAP(falling_edge, 64);
7365bbe531SSrinivas Neeli 	struct clk *clk;
74749564ffSRicardo Ribalda Delgado };
75749564ffSRicardo Ribalda Delgado 
xgpio_from_bit(struct xgpio_instance * chip,int bit)7602b3f84dSAndy Shevchenko static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit)
771d6902d3SRicardo Ribalda Delgado {
7802b3f84dSAndy Shevchenko 	return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64);
791d6902d3SRicardo Ribalda Delgado }
801d6902d3SRicardo Ribalda Delgado 
xgpio_to_bit(struct xgpio_instance * chip,int gpio)8102b3f84dSAndy Shevchenko static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio)
821d6902d3SRicardo Ribalda Delgado {
8302b3f84dSAndy Shevchenko 	return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64);
841d6902d3SRicardo Ribalda Delgado }
851d6902d3SRicardo Ribalda Delgado 
xgpio_get_value32(const unsigned long * map,int bit)8602b3f84dSAndy Shevchenko static inline u32 xgpio_get_value32(const unsigned long *map, int bit)
871d6902d3SRicardo Ribalda Delgado {
8802b3f84dSAndy Shevchenko 	const size_t index = BIT_WORD(bit);
8902b3f84dSAndy Shevchenko 	const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5);
901d6902d3SRicardo Ribalda Delgado 
9102b3f84dSAndy Shevchenko 	return (map[index] >> offset) & 0xFFFFFFFFul;
9202b3f84dSAndy Shevchenko }
9302b3f84dSAndy Shevchenko 
xgpio_set_value32(unsigned long * map,int bit,u32 v)9402b3f84dSAndy Shevchenko static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v)
9502b3f84dSAndy Shevchenko {
9602b3f84dSAndy Shevchenko 	const size_t index = BIT_WORD(bit);
9702b3f84dSAndy Shevchenko 	const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5);
9802b3f84dSAndy Shevchenko 
9902b3f84dSAndy Shevchenko 	map[index] &= ~(0xFFFFFFFFul << offset);
10032c094a0SSrinivas Neeli 	map[index] |= (unsigned long)v << offset;
1011d6902d3SRicardo Ribalda Delgado }
1021d6902d3SRicardo Ribalda Delgado 
xgpio_regoffset(struct xgpio_instance * chip,int ch)103043aa3dbSAndy Shevchenko static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch)
1041d6902d3SRicardo Ribalda Delgado {
105043aa3dbSAndy Shevchenko 	switch (ch) {
106043aa3dbSAndy Shevchenko 	case 0:
107043aa3dbSAndy Shevchenko 		return XGPIO_CHANNEL0_OFFSET;
108043aa3dbSAndy Shevchenko 	case 1:
109043aa3dbSAndy Shevchenko 		return XGPIO_CHANNEL1_OFFSET;
110043aa3dbSAndy Shevchenko 	default:
111043aa3dbSAndy Shevchenko 		return -EINVAL;
112043aa3dbSAndy Shevchenko 	}
113043aa3dbSAndy Shevchenko }
1141d6902d3SRicardo Ribalda Delgado 
xgpio_read_ch(struct xgpio_instance * chip,int reg,int bit,unsigned long * a)11502b3f84dSAndy Shevchenko static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a)
116043aa3dbSAndy Shevchenko {
11702b3f84dSAndy Shevchenko 	void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32);
118f2a2f2c9SShubhrajyoti Datta 
11902b3f84dSAndy Shevchenko 	xgpio_set_value32(a, bit, xgpio_readreg(addr));
120043aa3dbSAndy Shevchenko }
121043aa3dbSAndy Shevchenko 
xgpio_write_ch(struct xgpio_instance * chip,int reg,int bit,unsigned long * a)12202b3f84dSAndy Shevchenko static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a)
123043aa3dbSAndy Shevchenko {
12402b3f84dSAndy Shevchenko 	void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32);
125f2a2f2c9SShubhrajyoti Datta 
12602b3f84dSAndy Shevchenko 	xgpio_writereg(addr, xgpio_get_value32(a, bit));
1271d6902d3SRicardo Ribalda Delgado }
1281d6902d3SRicardo Ribalda Delgado 
xgpio_read_ch_all(struct xgpio_instance * chip,int reg,unsigned long * a)12902b3f84dSAndy Shevchenko static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
1301d6902d3SRicardo Ribalda Delgado {
13102b3f84dSAndy Shevchenko 	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
1321d6902d3SRicardo Ribalda Delgado 
13302b3f84dSAndy Shevchenko 	for (bit = 0; bit <= lastbit ; bit += 32)
13402b3f84dSAndy Shevchenko 		xgpio_read_ch(chip, reg, bit, a);
13502b3f84dSAndy Shevchenko }
13602b3f84dSAndy Shevchenko 
xgpio_write_ch_all(struct xgpio_instance * chip,int reg,unsigned long * a)13702b3f84dSAndy Shevchenko static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
13802b3f84dSAndy Shevchenko {
13902b3f84dSAndy Shevchenko 	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
14002b3f84dSAndy Shevchenko 
14102b3f84dSAndy Shevchenko 	for (bit = 0; bit <= lastbit ; bit += 32)
14202b3f84dSAndy Shevchenko 		xgpio_write_ch(chip, reg, bit, a);
1431d6902d3SRicardo Ribalda Delgado }
144c103de24SGrant Likely 
145c103de24SGrant Likely /**
146c103de24SGrant Likely  * xgpio_get - Read the specified signal of the GPIO device.
147c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
148c103de24SGrant Likely  * @gpio:   GPIO signal number.
149c103de24SGrant Likely  *
1504ae798faSRicardo Ribalda Delgado  * This function reads the specified signal of the GPIO device.
1514ae798faSRicardo Ribalda Delgado  *
1524ae798faSRicardo Ribalda Delgado  * Return:
1534ae798faSRicardo Ribalda Delgado  * 0 if direction of GPIO signals is set as input otherwise it
1544ae798faSRicardo Ribalda Delgado  * returns negative error value.
155c103de24SGrant Likely  */
xgpio_get(struct gpio_chip * gc,unsigned int gpio)156c103de24SGrant Likely static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
157c103de24SGrant Likely {
158097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
15902b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
16002b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
161c103de24SGrant Likely 
16202b3f84dSAndy Shevchenko 	xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state);
1631d6902d3SRicardo Ribalda Delgado 
16402b3f84dSAndy Shevchenko 	return test_bit(bit, state);
165c103de24SGrant Likely }
166c103de24SGrant Likely 
167c103de24SGrant Likely /**
168c103de24SGrant Likely  * xgpio_set - Write the specified signal of the GPIO device.
169c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
170c103de24SGrant Likely  * @gpio:   GPIO signal number.
171c103de24SGrant Likely  * @val:    Value to be written to specified signal.
172c103de24SGrant Likely  *
173c103de24SGrant Likely  * This function writes the specified value in to the specified signal of the
174c103de24SGrant Likely  * GPIO device.
175c103de24SGrant Likely  */
xgpio_set(struct gpio_chip * gc,unsigned int gpio,int val)176c103de24SGrant Likely static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
177c103de24SGrant Likely {
178c103de24SGrant Likely 	unsigned long flags;
179097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
18002b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
181c103de24SGrant Likely 
18237ef3346SSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
183c103de24SGrant Likely 
184c103de24SGrant Likely 	/* Write to GPIO signal and set its direction to output */
18502b3f84dSAndy Shevchenko 	__assign_bit(bit, chip->state, val);
18674600ee0SMichal Simek 
18702b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state);
188c103de24SGrant Likely 
18937ef3346SSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
190c103de24SGrant Likely }
191c103de24SGrant Likely 
192c103de24SGrant Likely /**
1938e7c1b80SIban Rodriguez  * xgpio_set_multiple - Write the specified signals of the GPIO device.
1948e7c1b80SIban Rodriguez  * @gc:     Pointer to gpio_chip device structure.
1958e7c1b80SIban Rodriguez  * @mask:   Mask of the GPIOS to modify.
1968e7c1b80SIban Rodriguez  * @bits:   Value to be wrote on each GPIO
1978e7c1b80SIban Rodriguez  *
1988e7c1b80SIban Rodriguez  * This function writes the specified values into the specified signals of the
1998e7c1b80SIban Rodriguez  * GPIO devices.
2008e7c1b80SIban Rodriguez  */
xgpio_set_multiple(struct gpio_chip * gc,unsigned long * mask,unsigned long * bits)2018e7c1b80SIban Rodriguez static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
2028e7c1b80SIban Rodriguez 			       unsigned long *bits)
2038e7c1b80SIban Rodriguez {
20402b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_mask, 64);
20502b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_bits, 64);
20602b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
2078e7c1b80SIban Rodriguez 	unsigned long flags;
2088e7c1b80SIban Rodriguez 	struct xgpio_instance *chip = gpiochip_get_data(gc);
20902b3f84dSAndy Shevchenko 
21002b3f84dSAndy Shevchenko 	bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64);
21102b3f84dSAndy Shevchenko 	bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64);
2128e7c1b80SIban Rodriguez 
21337ef3346SSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
2148e7c1b80SIban Rodriguez 
21502b3f84dSAndy Shevchenko 	bitmap_replace(state, chip->state, hw_bits, hw_mask, 64);
2168e7c1b80SIban Rodriguez 
21702b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state);
21802b3f84dSAndy Shevchenko 
21902b3f84dSAndy Shevchenko 	bitmap_copy(chip->state, state, 64);
2208e7c1b80SIban Rodriguez 
22137ef3346SSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
2228e7c1b80SIban Rodriguez }
2238e7c1b80SIban Rodriguez 
2248e7c1b80SIban Rodriguez /**
225c103de24SGrant Likely  * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
226c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
227c103de24SGrant Likely  * @gpio:   GPIO signal number.
228c103de24SGrant Likely  *
2294ae798faSRicardo Ribalda Delgado  * Return:
2304ae798faSRicardo Ribalda Delgado  * 0 - if direction of GPIO signals is set as input
2314ae798faSRicardo Ribalda Delgado  * otherwise it returns negative error value.
232c103de24SGrant Likely  */
xgpio_dir_in(struct gpio_chip * gc,unsigned int gpio)233c103de24SGrant Likely static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
234c103de24SGrant Likely {
235c103de24SGrant Likely 	unsigned long flags;
236097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
23702b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
238c103de24SGrant Likely 
23937ef3346SSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
240c103de24SGrant Likely 
241c103de24SGrant Likely 	/* Set the GPIO bit in shadow register and set direction as input */
24202b3f84dSAndy Shevchenko 	__set_bit(bit, chip->dir);
24302b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir);
244c103de24SGrant Likely 
24537ef3346SSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
246c103de24SGrant Likely 
247c103de24SGrant Likely 	return 0;
248c103de24SGrant Likely }
249c103de24SGrant Likely 
250c103de24SGrant Likely /**
251c103de24SGrant Likely  * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
252c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
253c103de24SGrant Likely  * @gpio:   GPIO signal number.
254c103de24SGrant Likely  * @val:    Value to be written to specified signal.
255c103de24SGrant Likely  *
2564ae798faSRicardo Ribalda Delgado  * This function sets the direction of specified GPIO signal as output.
2574ae798faSRicardo Ribalda Delgado  *
2584ae798faSRicardo Ribalda Delgado  * Return:
2594ae798faSRicardo Ribalda Delgado  * If all GPIO signals of GPIO chip is configured as input then it returns
260c103de24SGrant Likely  * error otherwise it returns 0.
261c103de24SGrant Likely  */
xgpio_dir_out(struct gpio_chip * gc,unsigned int gpio,int val)262c103de24SGrant Likely static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
263c103de24SGrant Likely {
264c103de24SGrant Likely 	unsigned long flags;
265097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
26602b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
267c103de24SGrant Likely 
26837ef3346SSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
269c103de24SGrant Likely 
270c103de24SGrant Likely 	/* Write state of GPIO signal */
27102b3f84dSAndy Shevchenko 	__assign_bit(bit, chip->state, val);
27202b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state);
273c103de24SGrant Likely 
274c103de24SGrant Likely 	/* Clear the GPIO bit in shadow register and set direction as output */
27502b3f84dSAndy Shevchenko 	__clear_bit(bit, chip->dir);
27602b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir);
277c103de24SGrant Likely 
27837ef3346SSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
279c103de24SGrant Likely 
280c103de24SGrant Likely 	return 0;
281c103de24SGrant Likely }
282c103de24SGrant Likely 
283c103de24SGrant Likely /**
284c103de24SGrant Likely  * xgpio_save_regs - Set initial values of GPIO pins
2851ebd0687SRobert Hancock  * @chip: Pointer to GPIO instance
286c103de24SGrant Likely  */
xgpio_save_regs(struct xgpio_instance * chip)2871ebd0687SRobert Hancock static void xgpio_save_regs(struct xgpio_instance *chip)
288c103de24SGrant Likely {
28902b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state);
29002b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir);
291c103de24SGrant Likely }
292c103de24SGrant Likely 
xgpio_request(struct gpio_chip * chip,unsigned int offset)29326b04774SSrinivas Neeli static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
29426b04774SSrinivas Neeli {
29526b04774SSrinivas Neeli 	int ret;
29626b04774SSrinivas Neeli 
29726b04774SSrinivas Neeli 	ret = pm_runtime_get_sync(chip->parent);
29826b04774SSrinivas Neeli 	/*
29926b04774SSrinivas Neeli 	 * If the device is already active pm_runtime_get() will return 1 on
30026b04774SSrinivas Neeli 	 * success, but gpio_request still needs to return 0.
30126b04774SSrinivas Neeli 	 */
30226b04774SSrinivas Neeli 	return ret < 0 ? ret : 0;
30326b04774SSrinivas Neeli }
30426b04774SSrinivas Neeli 
xgpio_free(struct gpio_chip * chip,unsigned int offset)30526b04774SSrinivas Neeli static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
30626b04774SSrinivas Neeli {
30726b04774SSrinivas Neeli 	pm_runtime_put(chip->parent);
30826b04774SSrinivas Neeli }
30926b04774SSrinivas Neeli 
xgpio_suspend(struct device * dev)31026b04774SSrinivas Neeli static int __maybe_unused xgpio_suspend(struct device *dev)
31126b04774SSrinivas Neeli {
31226b04774SSrinivas Neeli 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
31326b04774SSrinivas Neeli 	struct irq_data *data = irq_get_irq_data(gpio->irq);
31426b04774SSrinivas Neeli 
31526b04774SSrinivas Neeli 	if (!data) {
316be4dc321SSrinivas Neeli 		dev_dbg(dev, "IRQ not connected\n");
317be4dc321SSrinivas Neeli 		return pm_runtime_force_suspend(dev);
31826b04774SSrinivas Neeli 	}
31926b04774SSrinivas Neeli 
32026b04774SSrinivas Neeli 	if (!irqd_is_wakeup_set(data))
32126b04774SSrinivas Neeli 		return pm_runtime_force_suspend(dev);
32226b04774SSrinivas Neeli 
32326b04774SSrinivas Neeli 	return 0;
32426b04774SSrinivas Neeli }
32526b04774SSrinivas Neeli 
326c103de24SGrant Likely /**
3270230a41eSSrinivas Neeli  * xgpio_remove - Remove method for the GPIO device.
3280230a41eSSrinivas Neeli  * @pdev: pointer to the platform device
3290230a41eSSrinivas Neeli  *
3300230a41eSSrinivas Neeli  * This function remove gpiochips and frees all the allocated resources.
3310230a41eSSrinivas Neeli  *
3320230a41eSSrinivas Neeli  * Return: 0 always
3330230a41eSSrinivas Neeli  */
xgpio_remove(struct platform_device * pdev)3344f7b5eedSUwe Kleine-König static void xgpio_remove(struct platform_device *pdev)
3350230a41eSSrinivas Neeli {
33626b04774SSrinivas Neeli 	pm_runtime_get_sync(&pdev->dev);
33726b04774SSrinivas Neeli 	pm_runtime_put_noidle(&pdev->dev);
33826b04774SSrinivas Neeli 	pm_runtime_disable(&pdev->dev);
3390230a41eSSrinivas Neeli }
3400230a41eSSrinivas Neeli 
3410230a41eSSrinivas Neeli /**
342a32c7caeSSrinivas Neeli  * xgpio_irq_ack - Acknowledge a child GPIO interrupt.
343a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
344a32c7caeSSrinivas Neeli  * This currently does nothing, but irq_ack is unconditionally called by
345a32c7caeSSrinivas Neeli  * handle_edge_irq and therefore must be defined.
346a32c7caeSSrinivas Neeli  */
xgpio_irq_ack(struct irq_data * irq_data)347a32c7caeSSrinivas Neeli static void xgpio_irq_ack(struct irq_data *irq_data)
348a32c7caeSSrinivas Neeli {
349a32c7caeSSrinivas Neeli }
350a32c7caeSSrinivas Neeli 
xgpio_resume(struct device * dev)35126b04774SSrinivas Neeli static int __maybe_unused xgpio_resume(struct device *dev)
35226b04774SSrinivas Neeli {
35326b04774SSrinivas Neeli 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
35426b04774SSrinivas Neeli 	struct irq_data *data = irq_get_irq_data(gpio->irq);
35526b04774SSrinivas Neeli 
35626b04774SSrinivas Neeli 	if (!data) {
357be4dc321SSrinivas Neeli 		dev_dbg(dev, "IRQ not connected\n");
358be4dc321SSrinivas Neeli 		return pm_runtime_force_resume(dev);
35926b04774SSrinivas Neeli 	}
36026b04774SSrinivas Neeli 
36126b04774SSrinivas Neeli 	if (!irqd_is_wakeup_set(data))
36226b04774SSrinivas Neeli 		return pm_runtime_force_resume(dev);
36326b04774SSrinivas Neeli 
36426b04774SSrinivas Neeli 	return 0;
36526b04774SSrinivas Neeli }
36626b04774SSrinivas Neeli 
xgpio_runtime_suspend(struct device * dev)36726b04774SSrinivas Neeli static int __maybe_unused xgpio_runtime_suspend(struct device *dev)
36826b04774SSrinivas Neeli {
369e24b9fc1SWolfram Sang 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
37026b04774SSrinivas Neeli 
37126b04774SSrinivas Neeli 	clk_disable(gpio->clk);
37226b04774SSrinivas Neeli 
37326b04774SSrinivas Neeli 	return 0;
37426b04774SSrinivas Neeli }
37526b04774SSrinivas Neeli 
xgpio_runtime_resume(struct device * dev)37626b04774SSrinivas Neeli static int __maybe_unused xgpio_runtime_resume(struct device *dev)
37726b04774SSrinivas Neeli {
378e24b9fc1SWolfram Sang 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
37926b04774SSrinivas Neeli 
38026b04774SSrinivas Neeli 	return clk_enable(gpio->clk);
38126b04774SSrinivas Neeli }
38226b04774SSrinivas Neeli 
38326b04774SSrinivas Neeli static const struct dev_pm_ops xgpio_dev_pm_ops = {
38426b04774SSrinivas Neeli 	SET_SYSTEM_SLEEP_PM_OPS(xgpio_suspend, xgpio_resume)
38526b04774SSrinivas Neeli 	SET_RUNTIME_PM_OPS(xgpio_runtime_suspend,
38626b04774SSrinivas Neeli 			   xgpio_runtime_resume, NULL)
38726b04774SSrinivas Neeli };
38826b04774SSrinivas Neeli 
389a32c7caeSSrinivas Neeli /**
390a32c7caeSSrinivas Neeli  * xgpio_irq_mask - Write the specified signal of the GPIO device.
391a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
392a32c7caeSSrinivas Neeli  */
xgpio_irq_mask(struct irq_data * irq_data)393a32c7caeSSrinivas Neeli static void xgpio_irq_mask(struct irq_data *irq_data)
394a32c7caeSSrinivas Neeli {
395a32c7caeSSrinivas Neeli 	unsigned long flags;
396a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
397a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
39802b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
39902b3f84dSAndy Shevchenko 	u32 mask = BIT(bit / 32), temp;
400a32c7caeSSrinivas Neeli 
401a32c7caeSSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
402a32c7caeSSrinivas Neeli 
40302b3f84dSAndy Shevchenko 	__clear_bit(bit, chip->enable);
404a32c7caeSSrinivas Neeli 
40502b3f84dSAndy Shevchenko 	if (xgpio_get_value32(chip->enable, bit) == 0) {
406a32c7caeSSrinivas Neeli 		/* Disable per channel interrupt */
40702b3f84dSAndy Shevchenko 		temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
40802b3f84dSAndy Shevchenko 		temp &= ~mask;
409a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp);
410a32c7caeSSrinivas Neeli 	}
411a32c7caeSSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
412b4510f8fSLinus Walleij 
413b4510f8fSLinus Walleij 	gpiochip_disable_irq(&chip->gc, irq_offset);
414a32c7caeSSrinivas Neeli }
415a32c7caeSSrinivas Neeli 
416a32c7caeSSrinivas Neeli /**
417a32c7caeSSrinivas Neeli  * xgpio_irq_unmask - Write the specified signal of the GPIO device.
418a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
419a32c7caeSSrinivas Neeli  */
xgpio_irq_unmask(struct irq_data * irq_data)420a32c7caeSSrinivas Neeli static void xgpio_irq_unmask(struct irq_data *irq_data)
421a32c7caeSSrinivas Neeli {
422a32c7caeSSrinivas Neeli 	unsigned long flags;
423a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
424a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
42502b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
42602b3f84dSAndy Shevchenko 	u32 old_enable = xgpio_get_value32(chip->enable, bit);
42702b3f84dSAndy Shevchenko 	u32 mask = BIT(bit / 32), val;
428a32c7caeSSrinivas Neeli 
429b4510f8fSLinus Walleij 	gpiochip_enable_irq(&chip->gc, irq_offset);
430b4510f8fSLinus Walleij 
431a32c7caeSSrinivas Neeli 	spin_lock_irqsave(&chip->gpio_lock, flags);
432a32c7caeSSrinivas Neeli 
43302b3f84dSAndy Shevchenko 	__set_bit(bit, chip->enable);
434a32c7caeSSrinivas Neeli 
43502b3f84dSAndy Shevchenko 	if (old_enable == 0) {
436a32c7caeSSrinivas Neeli 		/* Clear any existing per-channel interrupts */
43702b3f84dSAndy Shevchenko 		val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
43802b3f84dSAndy Shevchenko 		val &= mask;
439a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val);
440a32c7caeSSrinivas Neeli 
441a32c7caeSSrinivas Neeli 		/* Update GPIO IRQ read data before enabling interrupt*/
44202b3f84dSAndy Shevchenko 		xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read);
443a32c7caeSSrinivas Neeli 
444a32c7caeSSrinivas Neeli 		/* Enable per channel interrupt */
445a32c7caeSSrinivas Neeli 		val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
44602b3f84dSAndy Shevchenko 		val |= mask;
447a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val);
448a32c7caeSSrinivas Neeli 	}
449a32c7caeSSrinivas Neeli 
450a32c7caeSSrinivas Neeli 	spin_unlock_irqrestore(&chip->gpio_lock, flags);
451a32c7caeSSrinivas Neeli }
452a32c7caeSSrinivas Neeli 
453a32c7caeSSrinivas Neeli /**
454a32c7caeSSrinivas Neeli  * xgpio_set_irq_type - Write the specified signal of the GPIO device.
455a32c7caeSSrinivas Neeli  * @irq_data: Per IRQ and chip data passed down to chip functions
456a32c7caeSSrinivas Neeli  * @type: Interrupt type that is to be set for the gpio pin
457a32c7caeSSrinivas Neeli  *
458a32c7caeSSrinivas Neeli  * Return:
459a32c7caeSSrinivas Neeli  * 0 if interrupt type is supported otherwise -EINVAL
460a32c7caeSSrinivas Neeli  */
xgpio_set_irq_type(struct irq_data * irq_data,unsigned int type)461a32c7caeSSrinivas Neeli static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
462a32c7caeSSrinivas Neeli {
463a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
464a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
46502b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
466a32c7caeSSrinivas Neeli 
467a32c7caeSSrinivas Neeli 	/*
468a32c7caeSSrinivas Neeli 	 * The Xilinx GPIO hardware provides a single interrupt status
469a32c7caeSSrinivas Neeli 	 * indication for any state change in a given GPIO channel (bank).
470a32c7caeSSrinivas Neeli 	 * Therefore, only rising edge or falling edge triggers are
471a32c7caeSSrinivas Neeli 	 * supported.
472a32c7caeSSrinivas Neeli 	 */
473a32c7caeSSrinivas Neeli 	switch (type & IRQ_TYPE_SENSE_MASK) {
474a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_BOTH:
47502b3f84dSAndy Shevchenko 		__set_bit(bit, chip->rising_edge);
47602b3f84dSAndy Shevchenko 		__set_bit(bit, chip->falling_edge);
477a32c7caeSSrinivas Neeli 		break;
478a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_RISING:
47902b3f84dSAndy Shevchenko 		__set_bit(bit, chip->rising_edge);
48002b3f84dSAndy Shevchenko 		__clear_bit(bit, chip->falling_edge);
481a32c7caeSSrinivas Neeli 		break;
482a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_FALLING:
48302b3f84dSAndy Shevchenko 		__clear_bit(bit, chip->rising_edge);
48402b3f84dSAndy Shevchenko 		__set_bit(bit, chip->falling_edge);
485a32c7caeSSrinivas Neeli 		break;
486a32c7caeSSrinivas Neeli 	default:
487a32c7caeSSrinivas Neeli 		return -EINVAL;
488a32c7caeSSrinivas Neeli 	}
489a32c7caeSSrinivas Neeli 
490a32c7caeSSrinivas Neeli 	irq_set_handler_locked(irq_data, handle_edge_irq);
491a32c7caeSSrinivas Neeli 	return 0;
492a32c7caeSSrinivas Neeli }
493a32c7caeSSrinivas Neeli 
494a32c7caeSSrinivas Neeli /**
495a32c7caeSSrinivas Neeli  * xgpio_irqhandler - Gpio interrupt service routine
496a32c7caeSSrinivas Neeli  * @desc: Pointer to interrupt description
497a32c7caeSSrinivas Neeli  */
xgpio_irqhandler(struct irq_desc * desc)498a32c7caeSSrinivas Neeli static void xgpio_irqhandler(struct irq_desc *desc)
499a32c7caeSSrinivas Neeli {
500a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_desc_get_handler_data(desc);
50102b3f84dSAndy Shevchenko 	struct gpio_chip *gc = &chip->gc;
502a32c7caeSSrinivas Neeli 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
50302b3f84dSAndy Shevchenko 	DECLARE_BITMAP(rising, 64);
50402b3f84dSAndy Shevchenko 	DECLARE_BITMAP(falling, 64);
50502b3f84dSAndy Shevchenko 	DECLARE_BITMAP(all, 64);
50602b3f84dSAndy Shevchenko 	int irq_offset;
50702b3f84dSAndy Shevchenko 	u32 status;
50802b3f84dSAndy Shevchenko 	u32 bit;
509a32c7caeSSrinivas Neeli 
51002b3f84dSAndy Shevchenko 	status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
511a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status);
512a32c7caeSSrinivas Neeli 
513a32c7caeSSrinivas Neeli 	chained_irq_enter(irqchip, desc);
514a32c7caeSSrinivas Neeli 
5156453b953SAndy Shevchenko 	spin_lock(&chip->gpio_lock);
516a32c7caeSSrinivas Neeli 
51702b3f84dSAndy Shevchenko 	xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all);
51802b3f84dSAndy Shevchenko 
51902b3f84dSAndy Shevchenko 	bitmap_complement(rising, chip->last_irq_read, 64);
52002b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, all, 64);
52102b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, chip->enable, 64);
52202b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, chip->rising_edge, 64);
52302b3f84dSAndy Shevchenko 
52402b3f84dSAndy Shevchenko 	bitmap_complement(falling, all, 64);
52502b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->last_irq_read, 64);
52602b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->enable, 64);
52702b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->falling_edge, 64);
52802b3f84dSAndy Shevchenko 
52902b3f84dSAndy Shevchenko 	bitmap_copy(chip->last_irq_read, all, 64);
53002b3f84dSAndy Shevchenko 	bitmap_or(all, rising, falling, 64);
53102b3f84dSAndy Shevchenko 
5326453b953SAndy Shevchenko 	spin_unlock(&chip->gpio_lock);
533a32c7caeSSrinivas Neeli 
53402b3f84dSAndy Shevchenko 	dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling);
53502b3f84dSAndy Shevchenko 
53602b3f84dSAndy Shevchenko 	for_each_set_bit(bit, all, 64) {
53702b3f84dSAndy Shevchenko 		irq_offset = xgpio_from_bit(chip, bit);
538dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(gc->irq.domain, irq_offset);
539a32c7caeSSrinivas Neeli 	}
540a32c7caeSSrinivas Neeli 
541a32c7caeSSrinivas Neeli 	chained_irq_exit(irqchip, desc);
542a32c7caeSSrinivas Neeli }
543a32c7caeSSrinivas Neeli 
544b4510f8fSLinus Walleij static const struct irq_chip xgpio_irq_chip = {
545b4510f8fSLinus Walleij 	.name = "gpio-xilinx",
546b4510f8fSLinus Walleij 	.irq_ack = xgpio_irq_ack,
547b4510f8fSLinus Walleij 	.irq_mask = xgpio_irq_mask,
548b4510f8fSLinus Walleij 	.irq_unmask = xgpio_irq_unmask,
549b4510f8fSLinus Walleij 	.irq_set_type = xgpio_set_irq_type,
550b4510f8fSLinus Walleij 	.flags = IRQCHIP_IMMUTABLE,
551b4510f8fSLinus Walleij 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
552b4510f8fSLinus Walleij };
553b4510f8fSLinus Walleij 
554a32c7caeSSrinivas Neeli /**
555a0579474SAndy Shevchenko  * xgpio_probe - Probe method for the GPIO device.
556749564ffSRicardo Ribalda Delgado  * @pdev: pointer to the platform device
557c103de24SGrant Likely  *
5584ae798faSRicardo Ribalda Delgado  * Return:
5594ae798faSRicardo Ribalda Delgado  * It returns 0, if the driver is bound to the GPIO device, or
5604ae798faSRicardo Ribalda Delgado  * a negative value if there is an error.
561c103de24SGrant Likely  */
xgpio_probe(struct platform_device * pdev)562749564ffSRicardo Ribalda Delgado static int xgpio_probe(struct platform_device *pdev)
563c103de24SGrant Likely {
564c103de24SGrant Likely 	struct xgpio_instance *chip;
565c103de24SGrant Likely 	int status = 0;
566749564ffSRicardo Ribalda Delgado 	struct device_node *np = pdev->dev.of_node;
567a32c7caeSSrinivas Neeli 	u32 is_dual = 0;
56802b3f84dSAndy Shevchenko 	u32 width[2];
56902b3f84dSAndy Shevchenko 	u32 state[2];
57002b3f84dSAndy Shevchenko 	u32 dir[2];
571a32c7caeSSrinivas Neeli 	struct gpio_irq_chip *girq;
572a32c7caeSSrinivas Neeli 	u32 temp;
573c103de24SGrant Likely 
5741d6902d3SRicardo Ribalda Delgado 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
5751d6902d3SRicardo Ribalda Delgado 	if (!chip)
576c103de24SGrant Likely 		return -ENOMEM;
577c103de24SGrant Likely 
5781d6902d3SRicardo Ribalda Delgado 	platform_set_drvdata(pdev, chip);
579749564ffSRicardo Ribalda Delgado 
58002b3f84dSAndy Shevchenko 	/* First, check if the device is dual-channel */
58102b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,is-dual", &is_dual);
58202b3f84dSAndy Shevchenko 
58302b3f84dSAndy Shevchenko 	/* Setup defaults */
58402b3f84dSAndy Shevchenko 	memset32(width, 0, ARRAY_SIZE(width));
58502b3f84dSAndy Shevchenko 	memset32(state, 0, ARRAY_SIZE(state));
58602b3f84dSAndy Shevchenko 	memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir));
58702b3f84dSAndy Shevchenko 
588c103de24SGrant Likely 	/* Update GPIO state shadow register with default value */
58902b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,dout-default", &state[0]);
59002b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,dout-default-2", &state[1]);
59102b3f84dSAndy Shevchenko 
59202b3f84dSAndy Shevchenko 	bitmap_from_arr32(chip->state, state, 64);
593c103de24SGrant Likely 
594c103de24SGrant Likely 	/* Update GPIO direction shadow register with default value */
59502b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,tri-default", &dir[0]);
59602b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]);
59702b3f84dSAndy Shevchenko 
59802b3f84dSAndy Shevchenko 	bitmap_from_arr32(chip->dir, dir, 64);
5996f8bf500SMichal Simek 
6001b4c5a6eSGernot Vormayr 	/*
6011b4c5a6eSGernot Vormayr 	 * Check device node and parent device node for device width
6021b4c5a6eSGernot Vormayr 	 * and assume default width of 32
6031b4c5a6eSGernot Vormayr 	 */
60402b3f84dSAndy Shevchenko 	if (of_property_read_u32(np, "xlnx,gpio-width", &width[0]))
60502b3f84dSAndy Shevchenko 		width[0] = 32;
606c103de24SGrant Likely 
60702b3f84dSAndy Shevchenko 	if (width[0] > 32)
6086e551bfaSSrinivas Neeli 		return -EINVAL;
6096e551bfaSSrinivas Neeli 
61002b3f84dSAndy Shevchenko 	if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1]))
61102b3f84dSAndy Shevchenko 		width[1] = 32;
61202b3f84dSAndy Shevchenko 
61302b3f84dSAndy Shevchenko 	if (width[1] > 32)
61402b3f84dSAndy Shevchenko 		return -EINVAL;
61502b3f84dSAndy Shevchenko 
61602b3f84dSAndy Shevchenko 	/* Setup software pin mapping */
61702b3f84dSAndy Shevchenko 	bitmap_set(chip->sw_map, 0, width[0] + width[1]);
61802b3f84dSAndy Shevchenko 
61902b3f84dSAndy Shevchenko 	/* Setup hardware pin mapping */
62002b3f84dSAndy Shevchenko 	bitmap_set(chip->hw_map,  0, width[0]);
62102b3f84dSAndy Shevchenko 	bitmap_set(chip->hw_map, 32, width[1]);
62202b3f84dSAndy Shevchenko 
62337ef3346SSrinivas Neeli 	spin_lock_init(&chip->gpio_lock);
624c103de24SGrant Likely 
6251ebd0687SRobert Hancock 	chip->gc.base = -1;
62602b3f84dSAndy Shevchenko 	chip->gc.ngpio = bitmap_weight(chip->hw_map, 64);
6271ebd0687SRobert Hancock 	chip->gc.parent = &pdev->dev;
6281ebd0687SRobert Hancock 	chip->gc.direction_input = xgpio_dir_in;
6291ebd0687SRobert Hancock 	chip->gc.direction_output = xgpio_dir_out;
6301ebd0687SRobert Hancock 	chip->gc.get = xgpio_get;
6311ebd0687SRobert Hancock 	chip->gc.set = xgpio_set;
63226b04774SSrinivas Neeli 	chip->gc.request = xgpio_request;
63326b04774SSrinivas Neeli 	chip->gc.free = xgpio_free;
6341ebd0687SRobert Hancock 	chip->gc.set_multiple = xgpio_set_multiple;
635c103de24SGrant Likely 
6361ebd0687SRobert Hancock 	chip->gc.label = dev_name(&pdev->dev);
637c103de24SGrant Likely 
6381ebd0687SRobert Hancock 	chip->regs = devm_platform_ioremap_resource(pdev, 0);
6391ebd0687SRobert Hancock 	if (IS_ERR(chip->regs)) {
6401ebd0687SRobert Hancock 		dev_err(&pdev->dev, "failed to ioremap memory resource\n");
6411ebd0687SRobert Hancock 		return PTR_ERR(chip->regs);
6421ebd0687SRobert Hancock 	}
6431ebd0687SRobert Hancock 
644*4e26ddabSZhang Zekun 	chip->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
64545c5277fSSrinivas Neeli 	if (IS_ERR(chip->clk))
64645c5277fSSrinivas Neeli 		return dev_err_probe(&pdev->dev, PTR_ERR(chip->clk), "input clock not found.\n");
64765bbe531SSrinivas Neeli 
64826b04774SSrinivas Neeli 	pm_runtime_get_noresume(&pdev->dev);
64926b04774SSrinivas Neeli 	pm_runtime_set_active(&pdev->dev);
65026b04774SSrinivas Neeli 	pm_runtime_enable(&pdev->dev);
65165bbe531SSrinivas Neeli 
6521ebd0687SRobert Hancock 	xgpio_save_regs(chip);
6531ebd0687SRobert Hancock 
654a32c7caeSSrinivas Neeli 	chip->irq = platform_get_irq_optional(pdev, 0);
655a32c7caeSSrinivas Neeli 	if (chip->irq <= 0)
656a32c7caeSSrinivas Neeli 		goto skip_irq;
657a32c7caeSSrinivas Neeli 
658a32c7caeSSrinivas Neeli 	/* Disable per-channel interrupts */
659a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, 0);
660a32c7caeSSrinivas Neeli 	/* Clear any existing per-channel interrupts */
661a32c7caeSSrinivas Neeli 	temp = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
662a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, temp);
663a32c7caeSSrinivas Neeli 	/* Enable global interrupts */
664a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE);
665a32c7caeSSrinivas Neeli 
666a32c7caeSSrinivas Neeli 	girq = &chip->gc.irq;
667b4510f8fSLinus Walleij 	gpio_irq_chip_set_chip(girq, &xgpio_irq_chip);
668a32c7caeSSrinivas Neeli 	girq->parent_handler = xgpio_irqhandler;
669a32c7caeSSrinivas Neeli 	girq->num_parents = 1;
670a32c7caeSSrinivas Neeli 	girq->parents = devm_kcalloc(&pdev->dev, 1,
671a32c7caeSSrinivas Neeli 				     sizeof(*girq->parents),
672a32c7caeSSrinivas Neeli 				     GFP_KERNEL);
673a32c7caeSSrinivas Neeli 	if (!girq->parents) {
674a32c7caeSSrinivas Neeli 		status = -ENOMEM;
67526b04774SSrinivas Neeli 		goto err_pm_put;
676a32c7caeSSrinivas Neeli 	}
677a32c7caeSSrinivas Neeli 	girq->parents[0] = chip->irq;
678a32c7caeSSrinivas Neeli 	girq->default_type = IRQ_TYPE_NONE;
679a32c7caeSSrinivas Neeli 	girq->handler = handle_bad_irq;
680a32c7caeSSrinivas Neeli 
681a32c7caeSSrinivas Neeli skip_irq:
6821ebd0687SRobert Hancock 	status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
683c103de24SGrant Likely 	if (status) {
6841ebd0687SRobert Hancock 		dev_err(&pdev->dev, "failed to add GPIO chip\n");
68526b04774SSrinivas Neeli 		goto err_pm_put;
686c103de24SGrant Likely 	}
68774600ee0SMichal Simek 
68826b04774SSrinivas Neeli 	pm_runtime_put(&pdev->dev);
689c103de24SGrant Likely 	return 0;
690a32c7caeSSrinivas Neeli 
69126b04774SSrinivas Neeli err_pm_put:
69226b04774SSrinivas Neeli 	pm_runtime_disable(&pdev->dev);
69326b04774SSrinivas Neeli 	pm_runtime_put_noidle(&pdev->dev);
694a32c7caeSSrinivas Neeli 	return status;
695c103de24SGrant Likely }
696c103de24SGrant Likely 
6979992bc95SJingoo Han static const struct of_device_id xgpio_of_match[] = {
698c103de24SGrant Likely 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
699c103de24SGrant Likely 	{ /* end of list */ },
700c103de24SGrant Likely };
701c103de24SGrant Likely 
702749564ffSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(of, xgpio_of_match);
703749564ffSRicardo Ribalda Delgado 
704749564ffSRicardo Ribalda Delgado static struct platform_driver xgpio_plat_driver = {
705749564ffSRicardo Ribalda Delgado 	.probe		= xgpio_probe,
7064f7b5eedSUwe Kleine-König 	.remove_new	= xgpio_remove,
707749564ffSRicardo Ribalda Delgado 	.driver		= {
708749564ffSRicardo Ribalda Delgado 			.name = "gpio-xilinx",
709749564ffSRicardo Ribalda Delgado 			.of_match_table	= xgpio_of_match,
71026b04774SSrinivas Neeli 			.pm = &xgpio_dev_pm_ops,
711749564ffSRicardo Ribalda Delgado 	},
712749564ffSRicardo Ribalda Delgado };
713749564ffSRicardo Ribalda Delgado 
xgpio_init(void)714c103de24SGrant Likely static int __init xgpio_init(void)
715c103de24SGrant Likely {
716749564ffSRicardo Ribalda Delgado 	return platform_driver_register(&xgpio_plat_driver);
717c103de24SGrant Likely }
718c103de24SGrant Likely 
719c103de24SGrant Likely subsys_initcall(xgpio_init);
720749564ffSRicardo Ribalda Delgado 
xgpio_exit(void)721749564ffSRicardo Ribalda Delgado static void __exit xgpio_exit(void)
722749564ffSRicardo Ribalda Delgado {
723749564ffSRicardo Ribalda Delgado 	platform_driver_unregister(&xgpio_plat_driver);
724749564ffSRicardo Ribalda Delgado }
725749564ffSRicardo Ribalda Delgado module_exit(xgpio_exit);
726c103de24SGrant Likely 
727c103de24SGrant Likely MODULE_AUTHOR("Xilinx, Inc.");
728c103de24SGrant Likely MODULE_DESCRIPTION("Xilinx GPIO driver");
729c103de24SGrant Likely MODULE_LICENSE("GPL");
730