xref: /openbmc/linux/drivers/gpio/gpio-tangier.c (revision 37e20428)
1d2c19e89SPandith N // SPDX-License-Identifier: GPL-2.0-only
2d2c19e89SPandith N /*
3d2c19e89SPandith N  * Intel Tangier GPIO driver
4d2c19e89SPandith N  *
5d2c19e89SPandith N  * Copyright (c) 2016, 2021, 2023 Intel Corporation.
6d2c19e89SPandith N  *
7d2c19e89SPandith N  * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8d2c19e89SPandith N  *          Pandith N <pandith.n@intel.com>
9d2c19e89SPandith N  *          Raag Jadav <raag.jadav@intel.com>
10d2c19e89SPandith N  */
11d2c19e89SPandith N 
12d2c19e89SPandith N #include <linux/bitops.h>
13d2c19e89SPandith N #include <linux/device.h>
14d2c19e89SPandith N #include <linux/errno.h>
15d2c19e89SPandith N #include <linux/export.h>
16d2c19e89SPandith N #include <linux/interrupt.h>
17d2c19e89SPandith N #include <linux/io.h>
18d2c19e89SPandith N #include <linux/irq.h>
193b8d8cccSRaag Jadav #include <linux/math.h>
20d2c19e89SPandith N #include <linux/module.h>
21d2c19e89SPandith N #include <linux/pinctrl/pinconf-generic.h>
22d2c19e89SPandith N #include <linux/spinlock.h>
23d2c19e89SPandith N #include <linux/string_helpers.h>
24d2c19e89SPandith N #include <linux/types.h>
25d2c19e89SPandith N 
26d2c19e89SPandith N #include <linux/gpio/driver.h>
27d2c19e89SPandith N 
28d2c19e89SPandith N #include "gpio-tangier.h"
29d2c19e89SPandith N 
30d2c19e89SPandith N #define GCCR		0x000	/* Controller configuration */
31d2c19e89SPandith N #define GPLR		0x004	/* Pin level r/o */
32d2c19e89SPandith N #define GPDR		0x01c	/* Pin direction */
33d2c19e89SPandith N #define GPSR		0x034	/* Pin set w/o */
34d2c19e89SPandith N #define GPCR		0x04c	/* Pin clear w/o */
35d2c19e89SPandith N #define GRER		0x064	/* Rising edge detect */
36d2c19e89SPandith N #define GFER		0x07c	/* Falling edge detect */
37d2c19e89SPandith N #define GFBR		0x094	/* Glitch filter bypass */
38d2c19e89SPandith N #define GIMR		0x0ac	/* Interrupt mask */
39d2c19e89SPandith N #define GISR		0x0c4	/* Interrupt source */
40d2c19e89SPandith N #define GITR		0x300	/* Input type */
41d2c19e89SPandith N #define GLPR		0x318	/* Level input polarity */
42d2c19e89SPandith N 
43d2c19e89SPandith N /**
44d2c19e89SPandith N  * struct tng_gpio_context - Context to be saved during suspend-resume
45d2c19e89SPandith N  * @level: Pin level
46d2c19e89SPandith N  * @gpdr: Pin direction
47d2c19e89SPandith N  * @grer: Rising edge detect enable
48d2c19e89SPandith N  * @gfer: Falling edge detect enable
49d2c19e89SPandith N  * @gimr: Interrupt mask
50d2c19e89SPandith N  * @gwmr: Wake mask
51d2c19e89SPandith N  */
52d2c19e89SPandith N struct tng_gpio_context {
53d2c19e89SPandith N 	u32 level;
54d2c19e89SPandith N 	u32 gpdr;
55d2c19e89SPandith N 	u32 grer;
56d2c19e89SPandith N 	u32 gfer;
57d2c19e89SPandith N 	u32 gimr;
58d2c19e89SPandith N 	u32 gwmr;
59d2c19e89SPandith N };
60d2c19e89SPandith N 
gpio_reg(struct gpio_chip * chip,unsigned int offset,unsigned int reg)61d2c19e89SPandith N static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset,
62d2c19e89SPandith N 			      unsigned int reg)
63d2c19e89SPandith N {
64d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
65d2c19e89SPandith N 	u8 reg_offset = offset / 32;
66d2c19e89SPandith N 
67d2c19e89SPandith N 	return priv->reg_base + reg + reg_offset * 4;
68d2c19e89SPandith N }
69d2c19e89SPandith N 
gpio_reg_and_bit(struct gpio_chip * chip,unsigned int offset,unsigned int reg,u8 * bit)70d2c19e89SPandith N static void __iomem *gpio_reg_and_bit(struct gpio_chip *chip, unsigned int offset,
71d2c19e89SPandith N 				      unsigned int reg, u8 *bit)
72d2c19e89SPandith N {
73d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
74d2c19e89SPandith N 	u8 reg_offset = offset / 32;
75d2c19e89SPandith N 	u8 shift = offset % 32;
76d2c19e89SPandith N 
77d2c19e89SPandith N 	*bit = shift;
78d2c19e89SPandith N 	return priv->reg_base + reg + reg_offset * 4;
79d2c19e89SPandith N }
80d2c19e89SPandith N 
tng_gpio_get(struct gpio_chip * chip,unsigned int offset)81d2c19e89SPandith N static int tng_gpio_get(struct gpio_chip *chip, unsigned int offset)
82d2c19e89SPandith N {
83d2c19e89SPandith N 	void __iomem *gplr;
84d2c19e89SPandith N 	u8 shift;
85d2c19e89SPandith N 
86d2c19e89SPandith N 	gplr = gpio_reg_and_bit(chip, offset, GPLR, &shift);
87d2c19e89SPandith N 
88d2c19e89SPandith N 	return !!(readl(gplr) & BIT(shift));
89d2c19e89SPandith N }
90d2c19e89SPandith N 
tng_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)91d2c19e89SPandith N static void tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
92d2c19e89SPandith N {
93d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
94d2c19e89SPandith N 	unsigned long flags;
95d2c19e89SPandith N 	void __iomem *reg;
96d2c19e89SPandith N 	u8 shift;
97d2c19e89SPandith N 
98d2c19e89SPandith N 	reg = gpio_reg_and_bit(chip, offset, value ? GPSR : GPCR, &shift);
99d2c19e89SPandith N 
100d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
101d2c19e89SPandith N 
102d2c19e89SPandith N 	writel(BIT(shift), reg);
103d2c19e89SPandith N 
104d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
105d2c19e89SPandith N }
106d2c19e89SPandith N 
tng_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)107d2c19e89SPandith N static int tng_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
108d2c19e89SPandith N {
109d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
110d2c19e89SPandith N 	unsigned long flags;
111d2c19e89SPandith N 	void __iomem *gpdr;
112d2c19e89SPandith N 	u32 value;
113d2c19e89SPandith N 	u8 shift;
114d2c19e89SPandith N 
115d2c19e89SPandith N 	gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
116d2c19e89SPandith N 
117d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
118d2c19e89SPandith N 
119d2c19e89SPandith N 	value = readl(gpdr);
120d2c19e89SPandith N 	value &= ~BIT(shift);
121d2c19e89SPandith N 	writel(value, gpdr);
122d2c19e89SPandith N 
123d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
124d2c19e89SPandith N 
125d2c19e89SPandith N 	return 0;
126d2c19e89SPandith N }
127d2c19e89SPandith N 
tng_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)128d2c19e89SPandith N static int tng_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
129d2c19e89SPandith N 				     int value)
130d2c19e89SPandith N {
131d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
132d2c19e89SPandith N 	unsigned long flags;
133d2c19e89SPandith N 	void __iomem *gpdr;
134d2c19e89SPandith N 	u8 shift;
135d2c19e89SPandith N 
136d2c19e89SPandith N 	gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
137d2c19e89SPandith N 	tng_gpio_set(chip, offset, value);
138d2c19e89SPandith N 
139d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
140d2c19e89SPandith N 
141d2c19e89SPandith N 	value = readl(gpdr);
142d2c19e89SPandith N 	value |= BIT(shift);
143d2c19e89SPandith N 	writel(value, gpdr);
144d2c19e89SPandith N 
145d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
146d2c19e89SPandith N 
147d2c19e89SPandith N 	return 0;
148d2c19e89SPandith N }
149d2c19e89SPandith N 
tng_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)150d2c19e89SPandith N static int tng_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
151d2c19e89SPandith N {
152d2c19e89SPandith N 	void __iomem *gpdr;
153d2c19e89SPandith N 	u8 shift;
154d2c19e89SPandith N 
155d2c19e89SPandith N 	gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
156d2c19e89SPandith N 
157d2c19e89SPandith N 	if (readl(gpdr) & BIT(shift))
158d2c19e89SPandith N 		return GPIO_LINE_DIRECTION_OUT;
159d2c19e89SPandith N 
160d2c19e89SPandith N 	return GPIO_LINE_DIRECTION_IN;
161d2c19e89SPandith N }
162d2c19e89SPandith N 
tng_gpio_set_debounce(struct gpio_chip * chip,unsigned int offset,unsigned int debounce)163d2c19e89SPandith N static int tng_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
164d2c19e89SPandith N 				 unsigned int debounce)
165d2c19e89SPandith N {
166d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
167d2c19e89SPandith N 	unsigned long flags;
168d2c19e89SPandith N 	void __iomem *gfbr;
169d2c19e89SPandith N 	u32 value;
170d2c19e89SPandith N 	u8 shift;
171d2c19e89SPandith N 
172d2c19e89SPandith N 	gfbr = gpio_reg_and_bit(chip, offset, GFBR, &shift);
173d2c19e89SPandith N 
174d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
175d2c19e89SPandith N 
176d2c19e89SPandith N 	value = readl(gfbr);
177d2c19e89SPandith N 	if (debounce)
178d2c19e89SPandith N 		value &= ~BIT(shift);
179d2c19e89SPandith N 	else
180d2c19e89SPandith N 		value |= BIT(shift);
181d2c19e89SPandith N 	writel(value, gfbr);
182d2c19e89SPandith N 
183d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
184d2c19e89SPandith N 
185d2c19e89SPandith N 	return 0;
186d2c19e89SPandith N }
187d2c19e89SPandith N 
tng_gpio_set_config(struct gpio_chip * chip,unsigned int offset,unsigned long config)188d2c19e89SPandith N static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
189d2c19e89SPandith N 			       unsigned long config)
190d2c19e89SPandith N {
191d2c19e89SPandith N 	u32 debounce;
192d2c19e89SPandith N 
193d2c19e89SPandith N 	switch (pinconf_to_config_param(config)) {
194d2c19e89SPandith N 	case PIN_CONFIG_BIAS_DISABLE:
195d2c19e89SPandith N 	case PIN_CONFIG_BIAS_PULL_UP:
196d2c19e89SPandith N 	case PIN_CONFIG_BIAS_PULL_DOWN:
197d2c19e89SPandith N 		return gpiochip_generic_config(chip, offset, config);
198d2c19e89SPandith N 	case PIN_CONFIG_INPUT_DEBOUNCE:
199d2c19e89SPandith N 		debounce = pinconf_to_config_argument(config);
200d2c19e89SPandith N 		return tng_gpio_set_debounce(chip, offset, debounce);
201d2c19e89SPandith N 	default:
202d2c19e89SPandith N 		return -ENOTSUPP;
203d2c19e89SPandith N 	}
204d2c19e89SPandith N }
205d2c19e89SPandith N 
tng_irq_ack(struct irq_data * d)206d2c19e89SPandith N static void tng_irq_ack(struct irq_data *d)
207d2c19e89SPandith N {
20837e20428SAndy Shevchenko 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
20937e20428SAndy Shevchenko 	struct tng_gpio *priv = gpiochip_get_data(gc);
210d2c19e89SPandith N 	irq_hw_number_t gpio = irqd_to_hwirq(d);
211d2c19e89SPandith N 	unsigned long flags;
212d2c19e89SPandith N 	void __iomem *gisr;
213d2c19e89SPandith N 	u8 shift;
214d2c19e89SPandith N 
215d2c19e89SPandith N 	gisr = gpio_reg_and_bit(&priv->chip, gpio, GISR, &shift);
216d2c19e89SPandith N 
217d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
218d2c19e89SPandith N 	writel(BIT(shift), gisr);
219d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
220d2c19e89SPandith N }
221d2c19e89SPandith N 
tng_irq_unmask_mask(struct tng_gpio * priv,u32 gpio,bool unmask)222d2c19e89SPandith N static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
223d2c19e89SPandith N {
224d2c19e89SPandith N 	unsigned long flags;
225d2c19e89SPandith N 	void __iomem *gimr;
226d2c19e89SPandith N 	u32 value;
227d2c19e89SPandith N 	u8 shift;
228d2c19e89SPandith N 
229d2c19e89SPandith N 	gimr = gpio_reg_and_bit(&priv->chip, gpio, GIMR, &shift);
230d2c19e89SPandith N 
231d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
232d2c19e89SPandith N 
233d2c19e89SPandith N 	value = readl(gimr);
234d2c19e89SPandith N 	if (unmask)
235d2c19e89SPandith N 		value |= BIT(shift);
236d2c19e89SPandith N 	else
237d2c19e89SPandith N 		value &= ~BIT(shift);
238d2c19e89SPandith N 	writel(value, gimr);
239d2c19e89SPandith N 
240d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
241d2c19e89SPandith N }
242d2c19e89SPandith N 
tng_irq_mask(struct irq_data * d)243d2c19e89SPandith N static void tng_irq_mask(struct irq_data *d)
244d2c19e89SPandith N {
24537e20428SAndy Shevchenko 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
24637e20428SAndy Shevchenko 	struct tng_gpio *priv = gpiochip_get_data(gc);
247d2c19e89SPandith N 	irq_hw_number_t gpio = irqd_to_hwirq(d);
248d2c19e89SPandith N 
249d2c19e89SPandith N 	tng_irq_unmask_mask(priv, gpio, false);
250d2c19e89SPandith N 	gpiochip_disable_irq(&priv->chip, gpio);
251d2c19e89SPandith N }
252d2c19e89SPandith N 
tng_irq_unmask(struct irq_data * d)253d2c19e89SPandith N static void tng_irq_unmask(struct irq_data *d)
254d2c19e89SPandith N {
25537e20428SAndy Shevchenko 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
25637e20428SAndy Shevchenko 	struct tng_gpio *priv = gpiochip_get_data(gc);
257d2c19e89SPandith N 	irq_hw_number_t gpio = irqd_to_hwirq(d);
258d2c19e89SPandith N 
259d2c19e89SPandith N 	gpiochip_enable_irq(&priv->chip, gpio);
260d2c19e89SPandith N 	tng_irq_unmask_mask(priv, gpio, true);
261d2c19e89SPandith N }
262d2c19e89SPandith N 
tng_irq_set_type(struct irq_data * d,unsigned int type)263d2c19e89SPandith N static int tng_irq_set_type(struct irq_data *d, unsigned int type)
264d2c19e89SPandith N {
265d2c19e89SPandith N 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
266d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(gc);
267d2c19e89SPandith N 	irq_hw_number_t gpio = irqd_to_hwirq(d);
268d2c19e89SPandith N 	void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
269d2c19e89SPandith N 	void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
270d2c19e89SPandith N 	void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR);
271d2c19e89SPandith N 	void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR);
272d2c19e89SPandith N 	u8 shift = gpio % 32;
273d2c19e89SPandith N 	unsigned long flags;
274d2c19e89SPandith N 	u32 value;
275d2c19e89SPandith N 
276d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
277d2c19e89SPandith N 
278d2c19e89SPandith N 	value = readl(grer);
279d2c19e89SPandith N 	if (type & IRQ_TYPE_EDGE_RISING)
280d2c19e89SPandith N 		value |= BIT(shift);
281d2c19e89SPandith N 	else
282d2c19e89SPandith N 		value &= ~BIT(shift);
283d2c19e89SPandith N 	writel(value, grer);
284d2c19e89SPandith N 
285d2c19e89SPandith N 	value = readl(gfer);
286d2c19e89SPandith N 	if (type & IRQ_TYPE_EDGE_FALLING)
287d2c19e89SPandith N 		value |= BIT(shift);
288d2c19e89SPandith N 	else
289d2c19e89SPandith N 		value &= ~BIT(shift);
290d2c19e89SPandith N 	writel(value, gfer);
291d2c19e89SPandith N 
292d2c19e89SPandith N 	/*
293d2c19e89SPandith N 	 * To prevent glitches from triggering an unintended level interrupt,
294d2c19e89SPandith N 	 * configure GLPR register first and then configure GITR.
295d2c19e89SPandith N 	 */
296d2c19e89SPandith N 	value = readl(glpr);
297d2c19e89SPandith N 	if (type & IRQ_TYPE_LEVEL_LOW)
298d2c19e89SPandith N 		value |= BIT(shift);
299d2c19e89SPandith N 	else
300d2c19e89SPandith N 		value &= ~BIT(shift);
301d2c19e89SPandith N 	writel(value, glpr);
302d2c19e89SPandith N 
303d2c19e89SPandith N 	if (type & IRQ_TYPE_LEVEL_MASK) {
304d2c19e89SPandith N 		value = readl(gitr);
305d2c19e89SPandith N 		value |= BIT(shift);
306d2c19e89SPandith N 		writel(value, gitr);
307d2c19e89SPandith N 
308d2c19e89SPandith N 		irq_set_handler_locked(d, handle_level_irq);
309d2c19e89SPandith N 	} else if (type & IRQ_TYPE_EDGE_BOTH) {
310d2c19e89SPandith N 		value = readl(gitr);
311d2c19e89SPandith N 		value &= ~BIT(shift);
312d2c19e89SPandith N 		writel(value, gitr);
313d2c19e89SPandith N 
314d2c19e89SPandith N 		irq_set_handler_locked(d, handle_edge_irq);
315d2c19e89SPandith N 	}
316d2c19e89SPandith N 
317d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
318d2c19e89SPandith N 
319d2c19e89SPandith N 	return 0;
320d2c19e89SPandith N }
321d2c19e89SPandith N 
tng_irq_set_wake(struct irq_data * d,unsigned int on)322d2c19e89SPandith N static int tng_irq_set_wake(struct irq_data *d, unsigned int on)
323d2c19e89SPandith N {
324d2c19e89SPandith N 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
325d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(gc);
326d2c19e89SPandith N 	irq_hw_number_t gpio = irqd_to_hwirq(d);
327d2c19e89SPandith N 	void __iomem *gwmr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwmr);
328d2c19e89SPandith N 	void __iomem *gwsr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwsr);
329d2c19e89SPandith N 	u8 shift = gpio % 32;
330d2c19e89SPandith N 	unsigned long flags;
331d2c19e89SPandith N 	u32 value;
332d2c19e89SPandith N 
333d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
334d2c19e89SPandith N 
335d2c19e89SPandith N 	/* Clear the existing wake status */
336d2c19e89SPandith N 	writel(BIT(shift), gwsr);
337d2c19e89SPandith N 
338d2c19e89SPandith N 	value = readl(gwmr);
339d2c19e89SPandith N 	if (on)
340d2c19e89SPandith N 		value |= BIT(shift);
341d2c19e89SPandith N 	else
342d2c19e89SPandith N 		value &= ~BIT(shift);
343d2c19e89SPandith N 	writel(value, gwmr);
344d2c19e89SPandith N 
345d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
346d2c19e89SPandith N 
347d2c19e89SPandith N 	dev_dbg(priv->dev, "%s wake for gpio %lu\n", str_enable_disable(on), gpio);
348d2c19e89SPandith N 	return 0;
349d2c19e89SPandith N }
350d2c19e89SPandith N 
351d2c19e89SPandith N static const struct irq_chip tng_irqchip = {
352d2c19e89SPandith N 	.name		= "gpio-tangier",
353d2c19e89SPandith N 	.irq_ack	= tng_irq_ack,
354d2c19e89SPandith N 	.irq_mask	= tng_irq_mask,
355d2c19e89SPandith N 	.irq_unmask	= tng_irq_unmask,
356d2c19e89SPandith N 	.irq_set_type	= tng_irq_set_type,
357d2c19e89SPandith N 	.irq_set_wake	= tng_irq_set_wake,
358d2c19e89SPandith N 	.flags          = IRQCHIP_IMMUTABLE,
359d2c19e89SPandith N 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
360d2c19e89SPandith N };
361d2c19e89SPandith N 
tng_irq_handler(struct irq_desc * desc)362d2c19e89SPandith N static void tng_irq_handler(struct irq_desc *desc)
363d2c19e89SPandith N {
364d2c19e89SPandith N 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
365d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(gc);
366d2c19e89SPandith N 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
367d2c19e89SPandith N 	unsigned long base, gpio;
368d2c19e89SPandith N 
369d2c19e89SPandith N 	chained_irq_enter(irqchip, desc);
370d2c19e89SPandith N 
371d2c19e89SPandith N 	/* Check GPIO controller to check which pin triggered the interrupt */
372d2c19e89SPandith N 	for (base = 0; base < priv->chip.ngpio; base += 32) {
373d2c19e89SPandith N 		void __iomem *gisr = gpio_reg(&priv->chip, base, GISR);
374d2c19e89SPandith N 		void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR);
375d2c19e89SPandith N 		unsigned long pending, enabled;
376d2c19e89SPandith N 
377d2c19e89SPandith N 		pending = readl(gisr);
378d2c19e89SPandith N 		enabled = readl(gimr);
379d2c19e89SPandith N 
380d2c19e89SPandith N 		/* Only interrupts that are enabled */
381d2c19e89SPandith N 		pending &= enabled;
382d2c19e89SPandith N 
383d2c19e89SPandith N 		for_each_set_bit(gpio, &pending, 32)
384d2c19e89SPandith N 			generic_handle_domain_irq(gc->irq.domain, base + gpio);
385d2c19e89SPandith N 	}
386d2c19e89SPandith N 
387d2c19e89SPandith N 	chained_irq_exit(irqchip, desc);
388d2c19e89SPandith N }
389d2c19e89SPandith N 
tng_irq_init_hw(struct gpio_chip * chip)390d2c19e89SPandith N static int tng_irq_init_hw(struct gpio_chip *chip)
391d2c19e89SPandith N {
392d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
393d2c19e89SPandith N 	void __iomem *reg;
394d2c19e89SPandith N 	unsigned int base;
395d2c19e89SPandith N 
396d2c19e89SPandith N 	for (base = 0; base < priv->chip.ngpio; base += 32) {
397d2c19e89SPandith N 		/* Clear the rising-edge detect register */
398d2c19e89SPandith N 		reg = gpio_reg(&priv->chip, base, GRER);
399d2c19e89SPandith N 		writel(0, reg);
400d2c19e89SPandith N 
401d2c19e89SPandith N 		/* Clear the falling-edge detect register */
402d2c19e89SPandith N 		reg = gpio_reg(&priv->chip, base, GFER);
403d2c19e89SPandith N 		writel(0, reg);
404d2c19e89SPandith N 	}
405d2c19e89SPandith N 
406d2c19e89SPandith N 	return 0;
407d2c19e89SPandith N }
408d2c19e89SPandith N 
tng_gpio_add_pin_ranges(struct gpio_chip * chip)409d2c19e89SPandith N static int tng_gpio_add_pin_ranges(struct gpio_chip *chip)
410d2c19e89SPandith N {
411d2c19e89SPandith N 	struct tng_gpio *priv = gpiochip_get_data(chip);
412d2c19e89SPandith N 	const struct tng_gpio_pinrange *range;
413d2c19e89SPandith N 	unsigned int i;
414d2c19e89SPandith N 	int ret;
415d2c19e89SPandith N 
416d2c19e89SPandith N 	for (i = 0; i < priv->pin_info.nranges; i++) {
417d2c19e89SPandith N 		range = &priv->pin_info.pin_ranges[i];
418d2c19e89SPandith N 		ret = gpiochip_add_pin_range(&priv->chip,
419d2c19e89SPandith N 					     priv->pin_info.name,
420d2c19e89SPandith N 					     range->gpio_base,
421d2c19e89SPandith N 					     range->pin_base,
422d2c19e89SPandith N 					     range->npins);
423d2c19e89SPandith N 		if (ret) {
424d2c19e89SPandith N 			dev_err(priv->dev, "failed to add GPIO pin range\n");
425d2c19e89SPandith N 			return ret;
426d2c19e89SPandith N 		}
427d2c19e89SPandith N 	}
428d2c19e89SPandith N 
429d2c19e89SPandith N 	return 0;
430d2c19e89SPandith N }
431d2c19e89SPandith N 
devm_tng_gpio_probe(struct device * dev,struct tng_gpio * gpio)432d2c19e89SPandith N int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio)
433d2c19e89SPandith N {
434d2c19e89SPandith N 	const struct tng_gpio_info *info = &gpio->info;
4353b8d8cccSRaag Jadav 	size_t nctx = DIV_ROUND_UP(info->ngpio, 32);
436d2c19e89SPandith N 	struct gpio_irq_chip *girq;
437d2c19e89SPandith N 	int ret;
438d2c19e89SPandith N 
4393b8d8cccSRaag Jadav 	gpio->ctx = devm_kcalloc(dev, nctx, sizeof(*gpio->ctx), GFP_KERNEL);
440d2c19e89SPandith N 	if (!gpio->ctx)
441d2c19e89SPandith N 		return -ENOMEM;
442d2c19e89SPandith N 
443d2c19e89SPandith N 	gpio->chip.label = dev_name(dev);
444d2c19e89SPandith N 	gpio->chip.parent = dev;
445d2c19e89SPandith N 	gpio->chip.request = gpiochip_generic_request;
446d2c19e89SPandith N 	gpio->chip.free = gpiochip_generic_free;
447d2c19e89SPandith N 	gpio->chip.direction_input = tng_gpio_direction_input;
448d2c19e89SPandith N 	gpio->chip.direction_output = tng_gpio_direction_output;
449d2c19e89SPandith N 	gpio->chip.get = tng_gpio_get;
450d2c19e89SPandith N 	gpio->chip.set = tng_gpio_set;
451d2c19e89SPandith N 	gpio->chip.get_direction = tng_gpio_get_direction;
452d2c19e89SPandith N 	gpio->chip.set_config = tng_gpio_set_config;
453d2c19e89SPandith N 	gpio->chip.base = info->base;
454d2c19e89SPandith N 	gpio->chip.ngpio = info->ngpio;
455d2c19e89SPandith N 	gpio->chip.can_sleep = false;
456d2c19e89SPandith N 	gpio->chip.add_pin_ranges = tng_gpio_add_pin_ranges;
457d2c19e89SPandith N 
458d2c19e89SPandith N 	raw_spin_lock_init(&gpio->lock);
459d2c19e89SPandith N 
460d2c19e89SPandith N 	girq = &gpio->chip.irq;
461d2c19e89SPandith N 	gpio_irq_chip_set_chip(girq, &tng_irqchip);
462d2c19e89SPandith N 	girq->init_hw = tng_irq_init_hw;
463d2c19e89SPandith N 	girq->parent_handler = tng_irq_handler;
464d2c19e89SPandith N 	girq->num_parents = 1;
465d2c19e89SPandith N 	girq->parents = devm_kcalloc(dev, girq->num_parents,
466d2c19e89SPandith N 				     sizeof(*girq->parents), GFP_KERNEL);
467d2c19e89SPandith N 	if (!girq->parents)
468d2c19e89SPandith N 		return -ENOMEM;
469d2c19e89SPandith N 
470d2c19e89SPandith N 	girq->parents[0] = gpio->irq;
471d2c19e89SPandith N 	girq->first = info->first;
472d2c19e89SPandith N 	girq->default_type = IRQ_TYPE_NONE;
473d2c19e89SPandith N 	girq->handler = handle_bad_irq;
474d2c19e89SPandith N 
475d2c19e89SPandith N 	ret = devm_gpiochip_add_data(dev, &gpio->chip, gpio);
476d2c19e89SPandith N 	if (ret)
477d2c19e89SPandith N 		return dev_err_probe(dev, ret, "gpiochip_add error\n");
478d2c19e89SPandith N 
479d2c19e89SPandith N 	return 0;
480d2c19e89SPandith N }
481d2c19e89SPandith N EXPORT_SYMBOL_NS_GPL(devm_tng_gpio_probe, GPIO_TANGIER);
482d2c19e89SPandith N 
tng_gpio_suspend(struct device * dev)483d2c19e89SPandith N int tng_gpio_suspend(struct device *dev)
484d2c19e89SPandith N {
485d2c19e89SPandith N 	struct tng_gpio *priv = dev_get_drvdata(dev);
486d2c19e89SPandith N 	struct tng_gpio_context *ctx = priv->ctx;
487d2c19e89SPandith N 	unsigned long flags;
488d2c19e89SPandith N 	unsigned int base;
489d2c19e89SPandith N 
490d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
491d2c19e89SPandith N 
492d2c19e89SPandith N 	for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) {
493d2c19e89SPandith N 		/* GPLR is RO, values read will be restored using GPSR */
494d2c19e89SPandith N 		ctx->level = readl(gpio_reg(&priv->chip, base, GPLR));
495d2c19e89SPandith N 
496d2c19e89SPandith N 		ctx->gpdr = readl(gpio_reg(&priv->chip, base, GPDR));
497d2c19e89SPandith N 		ctx->grer = readl(gpio_reg(&priv->chip, base, GRER));
498d2c19e89SPandith N 		ctx->gfer = readl(gpio_reg(&priv->chip, base, GFER));
499d2c19e89SPandith N 		ctx->gimr = readl(gpio_reg(&priv->chip, base, GIMR));
500d2c19e89SPandith N 
501d2c19e89SPandith N 		ctx->gwmr = readl(gpio_reg(&priv->chip, base, priv->wake_regs.gwmr));
502d2c19e89SPandith N 	}
503d2c19e89SPandith N 
504d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
505d2c19e89SPandith N 
506d2c19e89SPandith N 	return 0;
507d2c19e89SPandith N }
508d2c19e89SPandith N EXPORT_SYMBOL_NS_GPL(tng_gpio_suspend, GPIO_TANGIER);
509d2c19e89SPandith N 
tng_gpio_resume(struct device * dev)510d2c19e89SPandith N int tng_gpio_resume(struct device *dev)
511d2c19e89SPandith N {
512d2c19e89SPandith N 	struct tng_gpio *priv = dev_get_drvdata(dev);
513d2c19e89SPandith N 	struct tng_gpio_context *ctx = priv->ctx;
514d2c19e89SPandith N 	unsigned long flags;
515d2c19e89SPandith N 	unsigned int base;
516d2c19e89SPandith N 
517d2c19e89SPandith N 	raw_spin_lock_irqsave(&priv->lock, flags);
518d2c19e89SPandith N 
519d2c19e89SPandith N 	for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) {
520d2c19e89SPandith N 		/* GPLR is RO, values read will be restored using GPSR */
521d2c19e89SPandith N 		writel(ctx->level, gpio_reg(&priv->chip, base, GPSR));
522d2c19e89SPandith N 
523d2c19e89SPandith N 		writel(ctx->gpdr, gpio_reg(&priv->chip, base, GPDR));
524d2c19e89SPandith N 		writel(ctx->grer, gpio_reg(&priv->chip, base, GRER));
525d2c19e89SPandith N 		writel(ctx->gfer, gpio_reg(&priv->chip, base, GFER));
526d2c19e89SPandith N 		writel(ctx->gimr, gpio_reg(&priv->chip, base, GIMR));
527d2c19e89SPandith N 
528d2c19e89SPandith N 		writel(ctx->gwmr, gpio_reg(&priv->chip, base, priv->wake_regs.gwmr));
529d2c19e89SPandith N 	}
530d2c19e89SPandith N 
531d2c19e89SPandith N 	raw_spin_unlock_irqrestore(&priv->lock, flags);
532d2c19e89SPandith N 
533d2c19e89SPandith N 	return 0;
534d2c19e89SPandith N }
535d2c19e89SPandith N EXPORT_SYMBOL_NS_GPL(tng_gpio_resume, GPIO_TANGIER);
536d2c19e89SPandith N 
537d2c19e89SPandith N MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
538d2c19e89SPandith N MODULE_AUTHOR("Pandith N <pandith.n@intel.com>");
539d2c19e89SPandith N MODULE_AUTHOR("Raag Jadav <raag.jadav@intel.com>");
540d2c19e89SPandith N MODULE_DESCRIPTION("Intel Tangier GPIO driver");
541d2c19e89SPandith N MODULE_LICENSE("GPL");
542