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