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