xref: /openbmc/linux/drivers/gpio/gpio-xilinx.c (revision aad29a73199b7fbccfbabea3f1ee627ad1924f52)
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
55a32c7caeSSrinivas Neeli  * @irqchip: IRQ chip
5602b3f84dSAndy Shevchenko  * @enable: GPIO IRQ enable/disable bitfield
5702b3f84dSAndy Shevchenko  * @rising_edge: GPIO IRQ rising edge enable/disable bitfield
5802b3f84dSAndy Shevchenko  * @falling_edge: GPIO IRQ falling edge enable/disable bitfield
5965bbe531SSrinivas Neeli  * @clk: clock resource for this driver
6074600ee0SMichal Simek  */
61c103de24SGrant Likely struct xgpio_instance {
621ebd0687SRobert Hancock 	struct gpio_chip gc;
631ebd0687SRobert Hancock 	void __iomem *regs;
6402b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_map, 64);
6502b3f84dSAndy Shevchenko 	DECLARE_BITMAP(sw_map, 64);
6602b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
6702b3f84dSAndy Shevchenko 	DECLARE_BITMAP(last_irq_read, 64);
6802b3f84dSAndy Shevchenko 	DECLARE_BITMAP(dir, 64);
69*b0111650SSean Anderson 	raw_spinlock_t gpio_lock;	/* For serializing operations */
70a32c7caeSSrinivas Neeli 	int irq;
7102b3f84dSAndy Shevchenko 	DECLARE_BITMAP(enable, 64);
7202b3f84dSAndy Shevchenko 	DECLARE_BITMAP(rising_edge, 64);
7302b3f84dSAndy Shevchenko 	DECLARE_BITMAP(falling_edge, 64);
7465bbe531SSrinivas Neeli 	struct clk *clk;
75749564ffSRicardo Ribalda Delgado };
76749564ffSRicardo Ribalda Delgado 
xgpio_from_bit(struct xgpio_instance * chip,int bit)7702b3f84dSAndy Shevchenko static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit)
781d6902d3SRicardo Ribalda Delgado {
7902b3f84dSAndy Shevchenko 	return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64);
801d6902d3SRicardo Ribalda Delgado }
811d6902d3SRicardo Ribalda Delgado 
xgpio_to_bit(struct xgpio_instance * chip,int gpio)8202b3f84dSAndy Shevchenko static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio)
831d6902d3SRicardo Ribalda Delgado {
8402b3f84dSAndy Shevchenko 	return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64);
851d6902d3SRicardo Ribalda Delgado }
861d6902d3SRicardo Ribalda Delgado 
xgpio_get_value32(const unsigned long * map,int bit)8702b3f84dSAndy Shevchenko static inline u32 xgpio_get_value32(const unsigned long *map, int bit)
881d6902d3SRicardo Ribalda Delgado {
8902b3f84dSAndy Shevchenko 	const size_t index = BIT_WORD(bit);
9002b3f84dSAndy Shevchenko 	const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5);
911d6902d3SRicardo Ribalda Delgado 
9202b3f84dSAndy Shevchenko 	return (map[index] >> offset) & 0xFFFFFFFFul;
9302b3f84dSAndy Shevchenko }
9402b3f84dSAndy Shevchenko 
xgpio_set_value32(unsigned long * map,int bit,u32 v)9502b3f84dSAndy Shevchenko static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v)
9602b3f84dSAndy Shevchenko {
9702b3f84dSAndy Shevchenko 	const size_t index = BIT_WORD(bit);
9802b3f84dSAndy Shevchenko 	const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5);
9902b3f84dSAndy Shevchenko 
10002b3f84dSAndy Shevchenko 	map[index] &= ~(0xFFFFFFFFul << offset);
10132c094a0SSrinivas Neeli 	map[index] |= (unsigned long)v << offset;
1021d6902d3SRicardo Ribalda Delgado }
1031d6902d3SRicardo Ribalda Delgado 
xgpio_regoffset(struct xgpio_instance * chip,int ch)104043aa3dbSAndy Shevchenko static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch)
1051d6902d3SRicardo Ribalda Delgado {
106043aa3dbSAndy Shevchenko 	switch (ch) {
107043aa3dbSAndy Shevchenko 	case 0:
108043aa3dbSAndy Shevchenko 		return XGPIO_CHANNEL0_OFFSET;
109043aa3dbSAndy Shevchenko 	case 1:
110043aa3dbSAndy Shevchenko 		return XGPIO_CHANNEL1_OFFSET;
111043aa3dbSAndy Shevchenko 	default:
112043aa3dbSAndy Shevchenko 		return -EINVAL;
113043aa3dbSAndy Shevchenko 	}
114043aa3dbSAndy Shevchenko }
1151d6902d3SRicardo Ribalda Delgado 
xgpio_read_ch(struct xgpio_instance * chip,int reg,int bit,unsigned long * a)11602b3f84dSAndy Shevchenko static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a)
117043aa3dbSAndy Shevchenko {
11802b3f84dSAndy Shevchenko 	void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32);
119f2a2f2c9SShubhrajyoti Datta 
12002b3f84dSAndy Shevchenko 	xgpio_set_value32(a, bit, xgpio_readreg(addr));
121043aa3dbSAndy Shevchenko }
122043aa3dbSAndy Shevchenko 
xgpio_write_ch(struct xgpio_instance * chip,int reg,int bit,unsigned long * a)12302b3f84dSAndy Shevchenko static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a)
124043aa3dbSAndy Shevchenko {
12502b3f84dSAndy Shevchenko 	void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32);
126f2a2f2c9SShubhrajyoti Datta 
12702b3f84dSAndy Shevchenko 	xgpio_writereg(addr, xgpio_get_value32(a, bit));
1281d6902d3SRicardo Ribalda Delgado }
1291d6902d3SRicardo Ribalda Delgado 
xgpio_read_ch_all(struct xgpio_instance * chip,int reg,unsigned long * a)13002b3f84dSAndy Shevchenko static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
1311d6902d3SRicardo Ribalda Delgado {
13202b3f84dSAndy Shevchenko 	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
1331d6902d3SRicardo Ribalda Delgado 
13402b3f84dSAndy Shevchenko 	for (bit = 0; bit <= lastbit ; bit += 32)
13502b3f84dSAndy Shevchenko 		xgpio_read_ch(chip, reg, bit, a);
13602b3f84dSAndy Shevchenko }
13702b3f84dSAndy Shevchenko 
xgpio_write_ch_all(struct xgpio_instance * chip,int reg,unsigned long * a)13802b3f84dSAndy Shevchenko static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
13902b3f84dSAndy Shevchenko {
14002b3f84dSAndy Shevchenko 	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
14102b3f84dSAndy Shevchenko 
14202b3f84dSAndy Shevchenko 	for (bit = 0; bit <= lastbit ; bit += 32)
14302b3f84dSAndy Shevchenko 		xgpio_write_ch(chip, reg, bit, a);
1441d6902d3SRicardo Ribalda Delgado }
145c103de24SGrant Likely 
146c103de24SGrant Likely /**
147c103de24SGrant Likely  * xgpio_get - Read the specified signal of the GPIO device.
148c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
149c103de24SGrant Likely  * @gpio:   GPIO signal number.
150c103de24SGrant Likely  *
1514ae798faSRicardo Ribalda Delgado  * This function reads the specified signal of the GPIO device.
1524ae798faSRicardo Ribalda Delgado  *
1534ae798faSRicardo Ribalda Delgado  * Return:
1544ae798faSRicardo Ribalda Delgado  * 0 if direction of GPIO signals is set as input otherwise it
1554ae798faSRicardo Ribalda Delgado  * returns negative error value.
156c103de24SGrant Likely  */
xgpio_get(struct gpio_chip * gc,unsigned int gpio)157c103de24SGrant Likely static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
158c103de24SGrant Likely {
159097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
16002b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
16102b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
162c103de24SGrant Likely 
16302b3f84dSAndy Shevchenko 	xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state);
1641d6902d3SRicardo Ribalda Delgado 
16502b3f84dSAndy Shevchenko 	return test_bit(bit, state);
166c103de24SGrant Likely }
167c103de24SGrant Likely 
168c103de24SGrant Likely /**
169c103de24SGrant Likely  * xgpio_set - Write the specified signal of the GPIO device.
170c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
171c103de24SGrant Likely  * @gpio:   GPIO signal number.
172c103de24SGrant Likely  * @val:    Value to be written to specified signal.
173c103de24SGrant Likely  *
174c103de24SGrant Likely  * This function writes the specified value in to the specified signal of the
175c103de24SGrant Likely  * GPIO device.
176c103de24SGrant Likely  */
xgpio_set(struct gpio_chip * gc,unsigned int gpio,int val)177c103de24SGrant Likely static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
178c103de24SGrant Likely {
179c103de24SGrant Likely 	unsigned long flags;
180097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
18102b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
182c103de24SGrant Likely 
183*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
184c103de24SGrant Likely 
185c103de24SGrant Likely 	/* Write to GPIO signal and set its direction to output */
18602b3f84dSAndy Shevchenko 	__assign_bit(bit, chip->state, val);
18774600ee0SMichal Simek 
18802b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state);
189c103de24SGrant Likely 
190*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
191c103de24SGrant Likely }
192c103de24SGrant Likely 
193c103de24SGrant Likely /**
1948e7c1b80SIban Rodriguez  * xgpio_set_multiple - Write the specified signals of the GPIO device.
1958e7c1b80SIban Rodriguez  * @gc:     Pointer to gpio_chip device structure.
1968e7c1b80SIban Rodriguez  * @mask:   Mask of the GPIOS to modify.
1978e7c1b80SIban Rodriguez  * @bits:   Value to be wrote on each GPIO
1988e7c1b80SIban Rodriguez  *
1998e7c1b80SIban Rodriguez  * This function writes the specified values into the specified signals of the
2008e7c1b80SIban Rodriguez  * GPIO devices.
2018e7c1b80SIban Rodriguez  */
xgpio_set_multiple(struct gpio_chip * gc,unsigned long * mask,unsigned long * bits)2028e7c1b80SIban Rodriguez static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
2038e7c1b80SIban Rodriguez 			       unsigned long *bits)
2048e7c1b80SIban Rodriguez {
20502b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_mask, 64);
20602b3f84dSAndy Shevchenko 	DECLARE_BITMAP(hw_bits, 64);
20702b3f84dSAndy Shevchenko 	DECLARE_BITMAP(state, 64);
2088e7c1b80SIban Rodriguez 	unsigned long flags;
2098e7c1b80SIban Rodriguez 	struct xgpio_instance *chip = gpiochip_get_data(gc);
21002b3f84dSAndy Shevchenko 
21102b3f84dSAndy Shevchenko 	bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64);
21202b3f84dSAndy Shevchenko 	bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64);
2138e7c1b80SIban Rodriguez 
214*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
2158e7c1b80SIban Rodriguez 
21602b3f84dSAndy Shevchenko 	bitmap_replace(state, chip->state, hw_bits, hw_mask, 64);
2178e7c1b80SIban Rodriguez 
21802b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state);
21902b3f84dSAndy Shevchenko 
22002b3f84dSAndy Shevchenko 	bitmap_copy(chip->state, state, 64);
2218e7c1b80SIban Rodriguez 
222*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
2238e7c1b80SIban Rodriguez }
2248e7c1b80SIban Rodriguez 
2258e7c1b80SIban Rodriguez /**
226c103de24SGrant Likely  * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
227c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
228c103de24SGrant Likely  * @gpio:   GPIO signal number.
229c103de24SGrant Likely  *
2304ae798faSRicardo Ribalda Delgado  * Return:
2314ae798faSRicardo Ribalda Delgado  * 0 - if direction of GPIO signals is set as input
2324ae798faSRicardo Ribalda Delgado  * otherwise it returns negative error value.
233c103de24SGrant Likely  */
xgpio_dir_in(struct gpio_chip * gc,unsigned int gpio)234c103de24SGrant Likely static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
235c103de24SGrant Likely {
236c103de24SGrant Likely 	unsigned long flags;
237097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
23802b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
239c103de24SGrant Likely 
240*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
241c103de24SGrant Likely 
242c103de24SGrant Likely 	/* Set the GPIO bit in shadow register and set direction as input */
24302b3f84dSAndy Shevchenko 	__set_bit(bit, chip->dir);
24402b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir);
245c103de24SGrant Likely 
246*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
247c103de24SGrant Likely 
248c103de24SGrant Likely 	return 0;
249c103de24SGrant Likely }
250c103de24SGrant Likely 
251c103de24SGrant Likely /**
252c103de24SGrant Likely  * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
253c103de24SGrant Likely  * @gc:     Pointer to gpio_chip device structure.
254c103de24SGrant Likely  * @gpio:   GPIO signal number.
255c103de24SGrant Likely  * @val:    Value to be written to specified signal.
256c103de24SGrant Likely  *
2574ae798faSRicardo Ribalda Delgado  * This function sets the direction of specified GPIO signal as output.
2584ae798faSRicardo Ribalda Delgado  *
2594ae798faSRicardo Ribalda Delgado  * Return:
2604ae798faSRicardo Ribalda Delgado  * If all GPIO signals of GPIO chip is configured as input then it returns
261c103de24SGrant Likely  * error otherwise it returns 0.
262c103de24SGrant Likely  */
xgpio_dir_out(struct gpio_chip * gc,unsigned int gpio,int val)263c103de24SGrant Likely static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
264c103de24SGrant Likely {
265c103de24SGrant Likely 	unsigned long flags;
266097d88e9SLinus Walleij 	struct xgpio_instance *chip = gpiochip_get_data(gc);
26702b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, gpio);
268c103de24SGrant Likely 
269*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
270c103de24SGrant Likely 
271c103de24SGrant Likely 	/* Write state of GPIO signal */
27202b3f84dSAndy Shevchenko 	__assign_bit(bit, chip->state, val);
27302b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state);
274c103de24SGrant Likely 
275c103de24SGrant Likely 	/* Clear the GPIO bit in shadow register and set direction as output */
27602b3f84dSAndy Shevchenko 	__clear_bit(bit, chip->dir);
27702b3f84dSAndy Shevchenko 	xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir);
278c103de24SGrant Likely 
279*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
280c103de24SGrant Likely 
281c103de24SGrant Likely 	return 0;
282c103de24SGrant Likely }
283c103de24SGrant Likely 
284c103de24SGrant Likely /**
285c103de24SGrant Likely  * xgpio_save_regs - Set initial values of GPIO pins
2861ebd0687SRobert Hancock  * @chip: Pointer to GPIO instance
287c103de24SGrant Likely  */
xgpio_save_regs(struct xgpio_instance * chip)2881ebd0687SRobert Hancock static void xgpio_save_regs(struct xgpio_instance *chip)
289c103de24SGrant Likely {
29002b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state);
29102b3f84dSAndy Shevchenko 	xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir);
292c103de24SGrant Likely }
293c103de24SGrant Likely 
xgpio_request(struct gpio_chip * chip,unsigned int offset)29426b04774SSrinivas Neeli static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
29526b04774SSrinivas Neeli {
29626b04774SSrinivas Neeli 	int ret;
29726b04774SSrinivas Neeli 
29826b04774SSrinivas Neeli 	ret = pm_runtime_get_sync(chip->parent);
29926b04774SSrinivas Neeli 	/*
30026b04774SSrinivas Neeli 	 * If the device is already active pm_runtime_get() will return 1 on
30126b04774SSrinivas Neeli 	 * success, but gpio_request still needs to return 0.
30226b04774SSrinivas Neeli 	 */
30326b04774SSrinivas Neeli 	return ret < 0 ? ret : 0;
30426b04774SSrinivas Neeli }
30526b04774SSrinivas Neeli 
xgpio_free(struct gpio_chip * chip,unsigned int offset)30626b04774SSrinivas Neeli static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
30726b04774SSrinivas Neeli {
30826b04774SSrinivas Neeli 	pm_runtime_put(chip->parent);
30926b04774SSrinivas Neeli }
31026b04774SSrinivas Neeli 
xgpio_suspend(struct device * dev)31126b04774SSrinivas Neeli static int __maybe_unused xgpio_suspend(struct device *dev)
31226b04774SSrinivas Neeli {
31326b04774SSrinivas Neeli 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
31426b04774SSrinivas Neeli 	struct irq_data *data = irq_get_irq_data(gpio->irq);
31526b04774SSrinivas Neeli 
31626b04774SSrinivas Neeli 	if (!data) {
317be4dc321SSrinivas Neeli 		dev_dbg(dev, "IRQ not connected\n");
318be4dc321SSrinivas Neeli 		return pm_runtime_force_suspend(dev);
31926b04774SSrinivas Neeli 	}
32026b04774SSrinivas Neeli 
32126b04774SSrinivas Neeli 	if (!irqd_is_wakeup_set(data))
32226b04774SSrinivas Neeli 		return pm_runtime_force_suspend(dev);
32326b04774SSrinivas Neeli 
32426b04774SSrinivas Neeli 	return 0;
32526b04774SSrinivas Neeli }
32626b04774SSrinivas Neeli 
327c103de24SGrant Likely /**
3280230a41eSSrinivas Neeli  * xgpio_remove - Remove method for the GPIO device.
3290230a41eSSrinivas Neeli  * @pdev: pointer to the platform device
3300230a41eSSrinivas Neeli  *
3310230a41eSSrinivas Neeli  * This function remove gpiochips and frees all the allocated resources.
3320230a41eSSrinivas Neeli  *
3330230a41eSSrinivas Neeli  * Return: 0 always
3340230a41eSSrinivas Neeli  */
xgpio_remove(struct platform_device * pdev)3350230a41eSSrinivas Neeli static int xgpio_remove(struct platform_device *pdev)
3360230a41eSSrinivas Neeli {
3370230a41eSSrinivas Neeli 	struct xgpio_instance *gpio = platform_get_drvdata(pdev);
3380230a41eSSrinivas Neeli 
33926b04774SSrinivas Neeli 	pm_runtime_get_sync(&pdev->dev);
34026b04774SSrinivas Neeli 	pm_runtime_put_noidle(&pdev->dev);
34126b04774SSrinivas Neeli 	pm_runtime_disable(&pdev->dev);
3420230a41eSSrinivas Neeli 	clk_disable_unprepare(gpio->clk);
3430230a41eSSrinivas Neeli 
3440230a41eSSrinivas Neeli 	return 0;
3450230a41eSSrinivas Neeli }
3460230a41eSSrinivas Neeli 
3470230a41eSSrinivas Neeli /**
348a32c7caeSSrinivas Neeli  * xgpio_irq_ack - Acknowledge a child GPIO interrupt.
349a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
350a32c7caeSSrinivas Neeli  * This currently does nothing, but irq_ack is unconditionally called by
351a32c7caeSSrinivas Neeli  * handle_edge_irq and therefore must be defined.
352a32c7caeSSrinivas Neeli  */
xgpio_irq_ack(struct irq_data * irq_data)353a32c7caeSSrinivas Neeli static void xgpio_irq_ack(struct irq_data *irq_data)
354a32c7caeSSrinivas Neeli {
355a32c7caeSSrinivas Neeli }
356a32c7caeSSrinivas Neeli 
xgpio_resume(struct device * dev)35726b04774SSrinivas Neeli static int __maybe_unused xgpio_resume(struct device *dev)
35826b04774SSrinivas Neeli {
35926b04774SSrinivas Neeli 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
36026b04774SSrinivas Neeli 	struct irq_data *data = irq_get_irq_data(gpio->irq);
36126b04774SSrinivas Neeli 
36226b04774SSrinivas Neeli 	if (!data) {
363be4dc321SSrinivas Neeli 		dev_dbg(dev, "IRQ not connected\n");
364be4dc321SSrinivas Neeli 		return pm_runtime_force_resume(dev);
36526b04774SSrinivas Neeli 	}
36626b04774SSrinivas Neeli 
36726b04774SSrinivas Neeli 	if (!irqd_is_wakeup_set(data))
36826b04774SSrinivas Neeli 		return pm_runtime_force_resume(dev);
36926b04774SSrinivas Neeli 
37026b04774SSrinivas Neeli 	return 0;
37126b04774SSrinivas Neeli }
37226b04774SSrinivas Neeli 
xgpio_runtime_suspend(struct device * dev)37326b04774SSrinivas Neeli static int __maybe_unused xgpio_runtime_suspend(struct device *dev)
37426b04774SSrinivas Neeli {
375e24b9fc1SWolfram Sang 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
37626b04774SSrinivas Neeli 
37726b04774SSrinivas Neeli 	clk_disable(gpio->clk);
37826b04774SSrinivas Neeli 
37926b04774SSrinivas Neeli 	return 0;
38026b04774SSrinivas Neeli }
38126b04774SSrinivas Neeli 
xgpio_runtime_resume(struct device * dev)38226b04774SSrinivas Neeli static int __maybe_unused xgpio_runtime_resume(struct device *dev)
38326b04774SSrinivas Neeli {
384e24b9fc1SWolfram Sang 	struct xgpio_instance *gpio = dev_get_drvdata(dev);
38526b04774SSrinivas Neeli 
38626b04774SSrinivas Neeli 	return clk_enable(gpio->clk);
38726b04774SSrinivas Neeli }
38826b04774SSrinivas Neeli 
38926b04774SSrinivas Neeli static const struct dev_pm_ops xgpio_dev_pm_ops = {
39026b04774SSrinivas Neeli 	SET_SYSTEM_SLEEP_PM_OPS(xgpio_suspend, xgpio_resume)
39126b04774SSrinivas Neeli 	SET_RUNTIME_PM_OPS(xgpio_runtime_suspend,
39226b04774SSrinivas Neeli 			   xgpio_runtime_resume, NULL)
39326b04774SSrinivas Neeli };
39426b04774SSrinivas Neeli 
395a32c7caeSSrinivas Neeli /**
396a32c7caeSSrinivas Neeli  * xgpio_irq_mask - Write the specified signal of the GPIO device.
397a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
398a32c7caeSSrinivas Neeli  */
xgpio_irq_mask(struct irq_data * irq_data)399a32c7caeSSrinivas Neeli static void xgpio_irq_mask(struct irq_data *irq_data)
400a32c7caeSSrinivas Neeli {
401a32c7caeSSrinivas Neeli 	unsigned long flags;
402a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
403a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
40402b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
40502b3f84dSAndy Shevchenko 	u32 mask = BIT(bit / 32), temp;
406a32c7caeSSrinivas Neeli 
407*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
408a32c7caeSSrinivas Neeli 
40902b3f84dSAndy Shevchenko 	__clear_bit(bit, chip->enable);
410a32c7caeSSrinivas Neeli 
41102b3f84dSAndy Shevchenko 	if (xgpio_get_value32(chip->enable, bit) == 0) {
412a32c7caeSSrinivas Neeli 		/* Disable per channel interrupt */
41302b3f84dSAndy Shevchenko 		temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
41402b3f84dSAndy Shevchenko 		temp &= ~mask;
415a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp);
416a32c7caeSSrinivas Neeli 	}
417*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
418b4510f8fSLinus Walleij 
419b4510f8fSLinus Walleij 	gpiochip_disable_irq(&chip->gc, irq_offset);
420a32c7caeSSrinivas Neeli }
421a32c7caeSSrinivas Neeli 
422a32c7caeSSrinivas Neeli /**
423a32c7caeSSrinivas Neeli  * xgpio_irq_unmask - Write the specified signal of the GPIO device.
424a32c7caeSSrinivas Neeli  * @irq_data: per IRQ and chip data passed down to chip functions
425a32c7caeSSrinivas Neeli  */
xgpio_irq_unmask(struct irq_data * irq_data)426a32c7caeSSrinivas Neeli static void xgpio_irq_unmask(struct irq_data *irq_data)
427a32c7caeSSrinivas Neeli {
428a32c7caeSSrinivas Neeli 	unsigned long flags;
429a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
430a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
43102b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
43202b3f84dSAndy Shevchenko 	u32 old_enable = xgpio_get_value32(chip->enable, bit);
43302b3f84dSAndy Shevchenko 	u32 mask = BIT(bit / 32), val;
434a32c7caeSSrinivas Neeli 
435b4510f8fSLinus Walleij 	gpiochip_enable_irq(&chip->gc, irq_offset);
436b4510f8fSLinus Walleij 
437*b0111650SSean Anderson 	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
438a32c7caeSSrinivas Neeli 
43902b3f84dSAndy Shevchenko 	__set_bit(bit, chip->enable);
440a32c7caeSSrinivas Neeli 
44102b3f84dSAndy Shevchenko 	if (old_enable == 0) {
442a32c7caeSSrinivas Neeli 		/* Clear any existing per-channel interrupts */
44302b3f84dSAndy Shevchenko 		val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
44402b3f84dSAndy Shevchenko 		val &= mask;
445a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val);
446a32c7caeSSrinivas Neeli 
447a32c7caeSSrinivas Neeli 		/* Update GPIO IRQ read data before enabling interrupt*/
44802b3f84dSAndy Shevchenko 		xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read);
449a32c7caeSSrinivas Neeli 
450a32c7caeSSrinivas Neeli 		/* Enable per channel interrupt */
451a32c7caeSSrinivas Neeli 		val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
45202b3f84dSAndy Shevchenko 		val |= mask;
453a32c7caeSSrinivas Neeli 		xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val);
454a32c7caeSSrinivas Neeli 	}
455a32c7caeSSrinivas Neeli 
456*b0111650SSean Anderson 	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
457a32c7caeSSrinivas Neeli }
458a32c7caeSSrinivas Neeli 
459a32c7caeSSrinivas Neeli /**
460a32c7caeSSrinivas Neeli  * xgpio_set_irq_type - Write the specified signal of the GPIO device.
461a32c7caeSSrinivas Neeli  * @irq_data: Per IRQ and chip data passed down to chip functions
462a32c7caeSSrinivas Neeli  * @type: Interrupt type that is to be set for the gpio pin
463a32c7caeSSrinivas Neeli  *
464a32c7caeSSrinivas Neeli  * Return:
465a32c7caeSSrinivas Neeli  * 0 if interrupt type is supported otherwise -EINVAL
466a32c7caeSSrinivas Neeli  */
xgpio_set_irq_type(struct irq_data * irq_data,unsigned int type)467a32c7caeSSrinivas Neeli static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
468a32c7caeSSrinivas Neeli {
469a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
470a32c7caeSSrinivas Neeli 	int irq_offset = irqd_to_hwirq(irq_data);
47102b3f84dSAndy Shevchenko 	int bit = xgpio_to_bit(chip, irq_offset);
472a32c7caeSSrinivas Neeli 
473a32c7caeSSrinivas Neeli 	/*
474a32c7caeSSrinivas Neeli 	 * The Xilinx GPIO hardware provides a single interrupt status
475a32c7caeSSrinivas Neeli 	 * indication for any state change in a given GPIO channel (bank).
476a32c7caeSSrinivas Neeli 	 * Therefore, only rising edge or falling edge triggers are
477a32c7caeSSrinivas Neeli 	 * supported.
478a32c7caeSSrinivas Neeli 	 */
479a32c7caeSSrinivas Neeli 	switch (type & IRQ_TYPE_SENSE_MASK) {
480a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_BOTH:
48102b3f84dSAndy Shevchenko 		__set_bit(bit, chip->rising_edge);
48202b3f84dSAndy Shevchenko 		__set_bit(bit, chip->falling_edge);
483a32c7caeSSrinivas Neeli 		break;
484a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_RISING:
48502b3f84dSAndy Shevchenko 		__set_bit(bit, chip->rising_edge);
48602b3f84dSAndy Shevchenko 		__clear_bit(bit, chip->falling_edge);
487a32c7caeSSrinivas Neeli 		break;
488a32c7caeSSrinivas Neeli 	case IRQ_TYPE_EDGE_FALLING:
48902b3f84dSAndy Shevchenko 		__clear_bit(bit, chip->rising_edge);
49002b3f84dSAndy Shevchenko 		__set_bit(bit, chip->falling_edge);
491a32c7caeSSrinivas Neeli 		break;
492a32c7caeSSrinivas Neeli 	default:
493a32c7caeSSrinivas Neeli 		return -EINVAL;
494a32c7caeSSrinivas Neeli 	}
495a32c7caeSSrinivas Neeli 
496a32c7caeSSrinivas Neeli 	irq_set_handler_locked(irq_data, handle_edge_irq);
497a32c7caeSSrinivas Neeli 	return 0;
498a32c7caeSSrinivas Neeli }
499a32c7caeSSrinivas Neeli 
500a32c7caeSSrinivas Neeli /**
501a32c7caeSSrinivas Neeli  * xgpio_irqhandler - Gpio interrupt service routine
502a32c7caeSSrinivas Neeli  * @desc: Pointer to interrupt description
503a32c7caeSSrinivas Neeli  */
xgpio_irqhandler(struct irq_desc * desc)504a32c7caeSSrinivas Neeli static void xgpio_irqhandler(struct irq_desc *desc)
505a32c7caeSSrinivas Neeli {
506a32c7caeSSrinivas Neeli 	struct xgpio_instance *chip = irq_desc_get_handler_data(desc);
50702b3f84dSAndy Shevchenko 	struct gpio_chip *gc = &chip->gc;
508a32c7caeSSrinivas Neeli 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
50902b3f84dSAndy Shevchenko 	DECLARE_BITMAP(rising, 64);
51002b3f84dSAndy Shevchenko 	DECLARE_BITMAP(falling, 64);
51102b3f84dSAndy Shevchenko 	DECLARE_BITMAP(all, 64);
51202b3f84dSAndy Shevchenko 	int irq_offset;
51302b3f84dSAndy Shevchenko 	u32 status;
51402b3f84dSAndy Shevchenko 	u32 bit;
515a32c7caeSSrinivas Neeli 
51602b3f84dSAndy Shevchenko 	status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
517a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status);
518a32c7caeSSrinivas Neeli 
519a32c7caeSSrinivas Neeli 	chained_irq_enter(irqchip, desc);
520a32c7caeSSrinivas Neeli 
521*b0111650SSean Anderson 	raw_spin_lock(&chip->gpio_lock);
522a32c7caeSSrinivas Neeli 
52302b3f84dSAndy Shevchenko 	xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all);
52402b3f84dSAndy Shevchenko 
52502b3f84dSAndy Shevchenko 	bitmap_complement(rising, chip->last_irq_read, 64);
52602b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, all, 64);
52702b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, chip->enable, 64);
52802b3f84dSAndy Shevchenko 	bitmap_and(rising, rising, chip->rising_edge, 64);
52902b3f84dSAndy Shevchenko 
53002b3f84dSAndy Shevchenko 	bitmap_complement(falling, all, 64);
53102b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->last_irq_read, 64);
53202b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->enable, 64);
53302b3f84dSAndy Shevchenko 	bitmap_and(falling, falling, chip->falling_edge, 64);
53402b3f84dSAndy Shevchenko 
53502b3f84dSAndy Shevchenko 	bitmap_copy(chip->last_irq_read, all, 64);
53602b3f84dSAndy Shevchenko 	bitmap_or(all, rising, falling, 64);
53702b3f84dSAndy Shevchenko 
538*b0111650SSean Anderson 	raw_spin_unlock(&chip->gpio_lock);
539a32c7caeSSrinivas Neeli 
54002b3f84dSAndy Shevchenko 	dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling);
54102b3f84dSAndy Shevchenko 
54202b3f84dSAndy Shevchenko 	for_each_set_bit(bit, all, 64) {
54302b3f84dSAndy Shevchenko 		irq_offset = xgpio_from_bit(chip, bit);
544dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(gc->irq.domain, irq_offset);
545a32c7caeSSrinivas Neeli 	}
546a32c7caeSSrinivas Neeli 
547a32c7caeSSrinivas Neeli 	chained_irq_exit(irqchip, desc);
548a32c7caeSSrinivas Neeli }
549a32c7caeSSrinivas Neeli 
550b4510f8fSLinus Walleij static const struct irq_chip xgpio_irq_chip = {
551b4510f8fSLinus Walleij 	.name = "gpio-xilinx",
552b4510f8fSLinus Walleij 	.irq_ack = xgpio_irq_ack,
553b4510f8fSLinus Walleij 	.irq_mask = xgpio_irq_mask,
554b4510f8fSLinus Walleij 	.irq_unmask = xgpio_irq_unmask,
555b4510f8fSLinus Walleij 	.irq_set_type = xgpio_set_irq_type,
556b4510f8fSLinus Walleij 	.flags = IRQCHIP_IMMUTABLE,
557b4510f8fSLinus Walleij 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
558b4510f8fSLinus Walleij };
559b4510f8fSLinus Walleij 
560a32c7caeSSrinivas Neeli /**
561a0579474SAndy Shevchenko  * xgpio_probe - Probe method for the GPIO device.
562749564ffSRicardo Ribalda Delgado  * @pdev: pointer to the platform device
563c103de24SGrant Likely  *
5644ae798faSRicardo Ribalda Delgado  * Return:
5654ae798faSRicardo Ribalda Delgado  * It returns 0, if the driver is bound to the GPIO device, or
5664ae798faSRicardo Ribalda Delgado  * a negative value if there is an error.
567c103de24SGrant Likely  */
xgpio_probe(struct platform_device * pdev)568749564ffSRicardo Ribalda Delgado static int xgpio_probe(struct platform_device *pdev)
569c103de24SGrant Likely {
570c103de24SGrant Likely 	struct xgpio_instance *chip;
571c103de24SGrant Likely 	int status = 0;
572749564ffSRicardo Ribalda Delgado 	struct device_node *np = pdev->dev.of_node;
573a32c7caeSSrinivas Neeli 	u32 is_dual = 0;
57402b3f84dSAndy Shevchenko 	u32 width[2];
57502b3f84dSAndy Shevchenko 	u32 state[2];
57602b3f84dSAndy Shevchenko 	u32 dir[2];
577a32c7caeSSrinivas Neeli 	struct gpio_irq_chip *girq;
578a32c7caeSSrinivas Neeli 	u32 temp;
579c103de24SGrant Likely 
5801d6902d3SRicardo Ribalda Delgado 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
5811d6902d3SRicardo Ribalda Delgado 	if (!chip)
582c103de24SGrant Likely 		return -ENOMEM;
583c103de24SGrant Likely 
5841d6902d3SRicardo Ribalda Delgado 	platform_set_drvdata(pdev, chip);
585749564ffSRicardo Ribalda Delgado 
58602b3f84dSAndy Shevchenko 	/* First, check if the device is dual-channel */
58702b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,is-dual", &is_dual);
58802b3f84dSAndy Shevchenko 
58902b3f84dSAndy Shevchenko 	/* Setup defaults */
59002b3f84dSAndy Shevchenko 	memset32(width, 0, ARRAY_SIZE(width));
59102b3f84dSAndy Shevchenko 	memset32(state, 0, ARRAY_SIZE(state));
59202b3f84dSAndy Shevchenko 	memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir));
59302b3f84dSAndy Shevchenko 
594c103de24SGrant Likely 	/* Update GPIO state shadow register with default value */
59502b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,dout-default", &state[0]);
59602b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,dout-default-2", &state[1]);
59702b3f84dSAndy Shevchenko 
59802b3f84dSAndy Shevchenko 	bitmap_from_arr32(chip->state, state, 64);
599c103de24SGrant Likely 
600c103de24SGrant Likely 	/* Update GPIO direction shadow register with default value */
60102b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,tri-default", &dir[0]);
60202b3f84dSAndy Shevchenko 	of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]);
60302b3f84dSAndy Shevchenko 
60402b3f84dSAndy Shevchenko 	bitmap_from_arr32(chip->dir, dir, 64);
6056f8bf500SMichal Simek 
6061b4c5a6eSGernot Vormayr 	/*
6071b4c5a6eSGernot Vormayr 	 * Check device node and parent device node for device width
6081b4c5a6eSGernot Vormayr 	 * and assume default width of 32
6091b4c5a6eSGernot Vormayr 	 */
61002b3f84dSAndy Shevchenko 	if (of_property_read_u32(np, "xlnx,gpio-width", &width[0]))
61102b3f84dSAndy Shevchenko 		width[0] = 32;
612c103de24SGrant Likely 
61302b3f84dSAndy Shevchenko 	if (width[0] > 32)
6146e551bfaSSrinivas Neeli 		return -EINVAL;
6156e551bfaSSrinivas Neeli 
61602b3f84dSAndy Shevchenko 	if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1]))
61702b3f84dSAndy Shevchenko 		width[1] = 32;
61802b3f84dSAndy Shevchenko 
61902b3f84dSAndy Shevchenko 	if (width[1] > 32)
62002b3f84dSAndy Shevchenko 		return -EINVAL;
62102b3f84dSAndy Shevchenko 
62202b3f84dSAndy Shevchenko 	/* Setup software pin mapping */
62302b3f84dSAndy Shevchenko 	bitmap_set(chip->sw_map, 0, width[0] + width[1]);
62402b3f84dSAndy Shevchenko 
62502b3f84dSAndy Shevchenko 	/* Setup hardware pin mapping */
62602b3f84dSAndy Shevchenko 	bitmap_set(chip->hw_map,  0, width[0]);
62702b3f84dSAndy Shevchenko 	bitmap_set(chip->hw_map, 32, width[1]);
62802b3f84dSAndy Shevchenko 
629*b0111650SSean Anderson 	raw_spin_lock_init(&chip->gpio_lock);
630c103de24SGrant Likely 
6311ebd0687SRobert Hancock 	chip->gc.base = -1;
63202b3f84dSAndy Shevchenko 	chip->gc.ngpio = bitmap_weight(chip->hw_map, 64);
6331ebd0687SRobert Hancock 	chip->gc.parent = &pdev->dev;
6341ebd0687SRobert Hancock 	chip->gc.direction_input = xgpio_dir_in;
6351ebd0687SRobert Hancock 	chip->gc.direction_output = xgpio_dir_out;
6361ebd0687SRobert Hancock 	chip->gc.get = xgpio_get;
6371ebd0687SRobert Hancock 	chip->gc.set = xgpio_set;
63826b04774SSrinivas Neeli 	chip->gc.request = xgpio_request;
63926b04774SSrinivas Neeli 	chip->gc.free = xgpio_free;
6401ebd0687SRobert Hancock 	chip->gc.set_multiple = xgpio_set_multiple;
641c103de24SGrant Likely 
6421ebd0687SRobert Hancock 	chip->gc.label = dev_name(&pdev->dev);
643c103de24SGrant Likely 
6441ebd0687SRobert Hancock 	chip->regs = devm_platform_ioremap_resource(pdev, 0);
6451ebd0687SRobert Hancock 	if (IS_ERR(chip->regs)) {
6461ebd0687SRobert Hancock 		dev_err(&pdev->dev, "failed to ioremap memory resource\n");
6471ebd0687SRobert Hancock 		return PTR_ERR(chip->regs);
6481ebd0687SRobert Hancock 	}
6491ebd0687SRobert Hancock 
65065bbe531SSrinivas Neeli 	chip->clk = devm_clk_get_optional(&pdev->dev, NULL);
65145c5277fSSrinivas Neeli 	if (IS_ERR(chip->clk))
65245c5277fSSrinivas Neeli 		return dev_err_probe(&pdev->dev, PTR_ERR(chip->clk), "input clock not found.\n");
65365bbe531SSrinivas Neeli 
65465bbe531SSrinivas Neeli 	status = clk_prepare_enable(chip->clk);
65565bbe531SSrinivas Neeli 	if (status < 0) {
65665bbe531SSrinivas Neeli 		dev_err(&pdev->dev, "Failed to prepare clk\n");
65765bbe531SSrinivas Neeli 		return status;
65865bbe531SSrinivas Neeli 	}
65926b04774SSrinivas Neeli 	pm_runtime_get_noresume(&pdev->dev);
66026b04774SSrinivas Neeli 	pm_runtime_set_active(&pdev->dev);
66126b04774SSrinivas Neeli 	pm_runtime_enable(&pdev->dev);
66265bbe531SSrinivas Neeli 
6631ebd0687SRobert Hancock 	xgpio_save_regs(chip);
6641ebd0687SRobert Hancock 
665a32c7caeSSrinivas Neeli 	chip->irq = platform_get_irq_optional(pdev, 0);
666a32c7caeSSrinivas Neeli 	if (chip->irq <= 0)
667a32c7caeSSrinivas Neeli 		goto skip_irq;
668a32c7caeSSrinivas Neeli 
669a32c7caeSSrinivas Neeli 	/* Disable per-channel interrupts */
670a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, 0);
671a32c7caeSSrinivas Neeli 	/* Clear any existing per-channel interrupts */
672a32c7caeSSrinivas Neeli 	temp = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
673a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, temp);
674a32c7caeSSrinivas Neeli 	/* Enable global interrupts */
675a32c7caeSSrinivas Neeli 	xgpio_writereg(chip->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE);
676a32c7caeSSrinivas Neeli 
677a32c7caeSSrinivas Neeli 	girq = &chip->gc.irq;
678b4510f8fSLinus Walleij 	gpio_irq_chip_set_chip(girq, &xgpio_irq_chip);
679a32c7caeSSrinivas Neeli 	girq->parent_handler = xgpio_irqhandler;
680a32c7caeSSrinivas Neeli 	girq->num_parents = 1;
681a32c7caeSSrinivas Neeli 	girq->parents = devm_kcalloc(&pdev->dev, 1,
682a32c7caeSSrinivas Neeli 				     sizeof(*girq->parents),
683a32c7caeSSrinivas Neeli 				     GFP_KERNEL);
684a32c7caeSSrinivas Neeli 	if (!girq->parents) {
685a32c7caeSSrinivas Neeli 		status = -ENOMEM;
68626b04774SSrinivas Neeli 		goto err_pm_put;
687a32c7caeSSrinivas Neeli 	}
688a32c7caeSSrinivas Neeli 	girq->parents[0] = chip->irq;
689a32c7caeSSrinivas Neeli 	girq->default_type = IRQ_TYPE_NONE;
690a32c7caeSSrinivas Neeli 	girq->handler = handle_bad_irq;
691a32c7caeSSrinivas Neeli 
692a32c7caeSSrinivas Neeli skip_irq:
6931ebd0687SRobert Hancock 	status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
694c103de24SGrant Likely 	if (status) {
6951ebd0687SRobert Hancock 		dev_err(&pdev->dev, "failed to add GPIO chip\n");
69626b04774SSrinivas Neeli 		goto err_pm_put;
697c103de24SGrant Likely 	}
69874600ee0SMichal Simek 
69926b04774SSrinivas Neeli 	pm_runtime_put(&pdev->dev);
700c103de24SGrant Likely 	return 0;
701a32c7caeSSrinivas Neeli 
70226b04774SSrinivas Neeli err_pm_put:
70326b04774SSrinivas Neeli 	pm_runtime_disable(&pdev->dev);
70426b04774SSrinivas Neeli 	pm_runtime_put_noidle(&pdev->dev);
705a32c7caeSSrinivas Neeli 	clk_disable_unprepare(chip->clk);
706a32c7caeSSrinivas Neeli 	return status;
707c103de24SGrant Likely }
708c103de24SGrant Likely 
7099992bc95SJingoo Han static const struct of_device_id xgpio_of_match[] = {
710c103de24SGrant Likely 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
711c103de24SGrant Likely 	{ /* end of list */ },
712c103de24SGrant Likely };
713c103de24SGrant Likely 
714749564ffSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(of, xgpio_of_match);
715749564ffSRicardo Ribalda Delgado 
716749564ffSRicardo Ribalda Delgado static struct platform_driver xgpio_plat_driver = {
717749564ffSRicardo Ribalda Delgado 	.probe		= xgpio_probe,
7180230a41eSSrinivas Neeli 	.remove		= xgpio_remove,
719749564ffSRicardo Ribalda Delgado 	.driver		= {
720749564ffSRicardo Ribalda Delgado 			.name = "gpio-xilinx",
721749564ffSRicardo Ribalda Delgado 			.of_match_table	= xgpio_of_match,
72226b04774SSrinivas Neeli 			.pm = &xgpio_dev_pm_ops,
723749564ffSRicardo Ribalda Delgado 	},
724749564ffSRicardo Ribalda Delgado };
725749564ffSRicardo Ribalda Delgado 
xgpio_init(void)726c103de24SGrant Likely static int __init xgpio_init(void)
727c103de24SGrant Likely {
728749564ffSRicardo Ribalda Delgado 	return platform_driver_register(&xgpio_plat_driver);
729c103de24SGrant Likely }
730c103de24SGrant Likely 
731c103de24SGrant Likely subsys_initcall(xgpio_init);
732749564ffSRicardo Ribalda Delgado 
xgpio_exit(void)733749564ffSRicardo Ribalda Delgado static void __exit xgpio_exit(void)
734749564ffSRicardo Ribalda Delgado {
735749564ffSRicardo Ribalda Delgado 	platform_driver_unregister(&xgpio_plat_driver);
736749564ffSRicardo Ribalda Delgado }
737749564ffSRicardo Ribalda Delgado module_exit(xgpio_exit);
738c103de24SGrant Likely 
739c103de24SGrant Likely MODULE_AUTHOR("Xilinx, Inc.");
740c103de24SGrant Likely MODULE_DESCRIPTION("Xilinx GPIO driver");
741c103de24SGrant Likely MODULE_LICENSE("GPL");
742