xref: /linux/drivers/gpio/gpio-merrifield.c (revision ccf6fd6dcc86143002dec6c392d8aa41a6a46353)
1*ccf6fd6dSAndy Shevchenko /*
2*ccf6fd6dSAndy Shevchenko  * Intel Merrifield SoC GPIO driver
3*ccf6fd6dSAndy Shevchenko  *
4*ccf6fd6dSAndy Shevchenko  * Copyright (c) 2016 Intel Corporation.
5*ccf6fd6dSAndy Shevchenko  * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
6*ccf6fd6dSAndy Shevchenko  *
7*ccf6fd6dSAndy Shevchenko  * This program is free software; you can redistribute it and/or modify
8*ccf6fd6dSAndy Shevchenko  * it under the terms of the GNU General Public License version 2 as
9*ccf6fd6dSAndy Shevchenko  * published by the Free Software Foundation.
10*ccf6fd6dSAndy Shevchenko  */
11*ccf6fd6dSAndy Shevchenko 
12*ccf6fd6dSAndy Shevchenko #include <linux/bitops.h>
13*ccf6fd6dSAndy Shevchenko #include <linux/gpio/driver.h>
14*ccf6fd6dSAndy Shevchenko #include <linux/init.h>
15*ccf6fd6dSAndy Shevchenko #include <linux/interrupt.h>
16*ccf6fd6dSAndy Shevchenko #include <linux/io.h>
17*ccf6fd6dSAndy Shevchenko #include <linux/module.h>
18*ccf6fd6dSAndy Shevchenko #include <linux/pci.h>
19*ccf6fd6dSAndy Shevchenko #include <linux/pinctrl/consumer.h>
20*ccf6fd6dSAndy Shevchenko 
21*ccf6fd6dSAndy Shevchenko #define GCCR		0x000	/* controller configuration */
22*ccf6fd6dSAndy Shevchenko #define GPLR		0x004	/* pin level r/o */
23*ccf6fd6dSAndy Shevchenko #define GPDR		0x01c	/* pin direction */
24*ccf6fd6dSAndy Shevchenko #define GPSR		0x034	/* pin set w/o */
25*ccf6fd6dSAndy Shevchenko #define GPCR		0x04c	/* pin clear w/o */
26*ccf6fd6dSAndy Shevchenko #define GRER		0x064	/* rising edge detect */
27*ccf6fd6dSAndy Shevchenko #define GFER		0x07c	/* falling edge detect */
28*ccf6fd6dSAndy Shevchenko #define GFBR		0x094	/* glitch filter bypass */
29*ccf6fd6dSAndy Shevchenko #define GIMR		0x0ac	/* interrupt mask */
30*ccf6fd6dSAndy Shevchenko #define GISR		0x0c4	/* interrupt source */
31*ccf6fd6dSAndy Shevchenko #define GITR		0x300	/* input type */
32*ccf6fd6dSAndy Shevchenko #define GLPR		0x318	/* level input polarity */
33*ccf6fd6dSAndy Shevchenko #define GWMR		0x400	/* wake mask */
34*ccf6fd6dSAndy Shevchenko #define GWSR		0x418	/* wake source */
35*ccf6fd6dSAndy Shevchenko #define GSIR		0xc00	/* secure input */
36*ccf6fd6dSAndy Shevchenko 
37*ccf6fd6dSAndy Shevchenko /* Intel Merrifield has 192 GPIO pins */
38*ccf6fd6dSAndy Shevchenko #define MRFLD_NGPIO	192
39*ccf6fd6dSAndy Shevchenko 
40*ccf6fd6dSAndy Shevchenko struct mrfld_gpio_pinrange {
41*ccf6fd6dSAndy Shevchenko 	unsigned int gpio_base;
42*ccf6fd6dSAndy Shevchenko 	unsigned int pin_base;
43*ccf6fd6dSAndy Shevchenko 	unsigned int npins;
44*ccf6fd6dSAndy Shevchenko };
45*ccf6fd6dSAndy Shevchenko 
46*ccf6fd6dSAndy Shevchenko #define GPIO_PINRANGE(gstart, gend, pstart)		\
47*ccf6fd6dSAndy Shevchenko 	{						\
48*ccf6fd6dSAndy Shevchenko 		.gpio_base = (gstart),			\
49*ccf6fd6dSAndy Shevchenko 		.pin_base = (pstart),			\
50*ccf6fd6dSAndy Shevchenko 		.npins = (gend) - (gstart) + 1,		\
51*ccf6fd6dSAndy Shevchenko 	}
52*ccf6fd6dSAndy Shevchenko 
53*ccf6fd6dSAndy Shevchenko struct mrfld_gpio {
54*ccf6fd6dSAndy Shevchenko 	struct gpio_chip	chip;
55*ccf6fd6dSAndy Shevchenko 	void __iomem		*reg_base;
56*ccf6fd6dSAndy Shevchenko 	raw_spinlock_t		lock;
57*ccf6fd6dSAndy Shevchenko 	struct device		*dev;
58*ccf6fd6dSAndy Shevchenko };
59*ccf6fd6dSAndy Shevchenko 
60*ccf6fd6dSAndy Shevchenko static const struct mrfld_gpio_pinrange mrfld_gpio_ranges[] = {
61*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(0, 11, 146),
62*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(12, 13, 144),
63*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(14, 15, 35),
64*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(16, 16, 164),
65*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(17, 18, 105),
66*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(19, 22, 101),
67*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(23, 30, 107),
68*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(32, 43, 67),
69*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(44, 63, 195),
70*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(64, 67, 140),
71*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(68, 69, 165),
72*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(70, 71, 65),
73*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(72, 76, 228),
74*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(77, 86, 37),
75*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(87, 87, 48),
76*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(88, 88, 47),
77*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(89, 96, 49),
78*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(97, 97, 34),
79*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(102, 119, 83),
80*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(120, 123, 79),
81*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(124, 135, 115),
82*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(137, 142, 158),
83*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(154, 163, 24),
84*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(164, 176, 215),
85*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(177, 189, 127),
86*ccf6fd6dSAndy Shevchenko 	GPIO_PINRANGE(190, 191, 178),
87*ccf6fd6dSAndy Shevchenko };
88*ccf6fd6dSAndy Shevchenko 
89*ccf6fd6dSAndy Shevchenko static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset,
90*ccf6fd6dSAndy Shevchenko 			      unsigned int reg_type_offset)
91*ccf6fd6dSAndy Shevchenko {
92*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(chip);
93*ccf6fd6dSAndy Shevchenko 	u8 reg = offset / 32;
94*ccf6fd6dSAndy Shevchenko 
95*ccf6fd6dSAndy Shevchenko 	return priv->reg_base + reg_type_offset + reg * 4;
96*ccf6fd6dSAndy Shevchenko }
97*ccf6fd6dSAndy Shevchenko 
98*ccf6fd6dSAndy Shevchenko static int mrfld_gpio_get(struct gpio_chip *chip, unsigned int offset)
99*ccf6fd6dSAndy Shevchenko {
100*ccf6fd6dSAndy Shevchenko 	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
101*ccf6fd6dSAndy Shevchenko 
102*ccf6fd6dSAndy Shevchenko 	return !!(readl(gplr) & BIT(offset % 32));
103*ccf6fd6dSAndy Shevchenko }
104*ccf6fd6dSAndy Shevchenko 
105*ccf6fd6dSAndy Shevchenko static void mrfld_gpio_set(struct gpio_chip *chip, unsigned int offset,
106*ccf6fd6dSAndy Shevchenko 			   int value)
107*ccf6fd6dSAndy Shevchenko {
108*ccf6fd6dSAndy Shevchenko 	void __iomem *gpsr, *gpcr;
109*ccf6fd6dSAndy Shevchenko 
110*ccf6fd6dSAndy Shevchenko 	if (value) {
111*ccf6fd6dSAndy Shevchenko 		gpsr = gpio_reg(chip, offset, GPSR);
112*ccf6fd6dSAndy Shevchenko 		writel(BIT(offset % 32), gpsr);
113*ccf6fd6dSAndy Shevchenko 	} else {
114*ccf6fd6dSAndy Shevchenko 		gpcr = gpio_reg(chip, offset, GPCR);
115*ccf6fd6dSAndy Shevchenko 		writel(BIT(offset % 32), gpcr);
116*ccf6fd6dSAndy Shevchenko 	}
117*ccf6fd6dSAndy Shevchenko }
118*ccf6fd6dSAndy Shevchenko 
119*ccf6fd6dSAndy Shevchenko static int mrfld_gpio_direction_input(struct gpio_chip *chip,
120*ccf6fd6dSAndy Shevchenko 				      unsigned int offset)
121*ccf6fd6dSAndy Shevchenko {
122*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(chip);
123*ccf6fd6dSAndy Shevchenko 	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
124*ccf6fd6dSAndy Shevchenko 	unsigned long flags;
125*ccf6fd6dSAndy Shevchenko 	u32 value;
126*ccf6fd6dSAndy Shevchenko 
127*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_irqsave(&priv->lock, flags);
128*ccf6fd6dSAndy Shevchenko 
129*ccf6fd6dSAndy Shevchenko 	value = readl(gpdr);
130*ccf6fd6dSAndy Shevchenko 	value &= ~BIT(offset % 32);
131*ccf6fd6dSAndy Shevchenko 	writel(value, gpdr);
132*ccf6fd6dSAndy Shevchenko 
133*ccf6fd6dSAndy Shevchenko 	raw_spin_unlock_irqrestore(&priv->lock, flags);
134*ccf6fd6dSAndy Shevchenko 
135*ccf6fd6dSAndy Shevchenko 	return 0;
136*ccf6fd6dSAndy Shevchenko }
137*ccf6fd6dSAndy Shevchenko 
138*ccf6fd6dSAndy Shevchenko static int mrfld_gpio_direction_output(struct gpio_chip *chip,
139*ccf6fd6dSAndy Shevchenko 				       unsigned int offset, int value)
140*ccf6fd6dSAndy Shevchenko {
141*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(chip);
142*ccf6fd6dSAndy Shevchenko 	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
143*ccf6fd6dSAndy Shevchenko 	unsigned long flags;
144*ccf6fd6dSAndy Shevchenko 
145*ccf6fd6dSAndy Shevchenko 	mrfld_gpio_set(chip, offset, value);
146*ccf6fd6dSAndy Shevchenko 
147*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_irqsave(&priv->lock, flags);
148*ccf6fd6dSAndy Shevchenko 
149*ccf6fd6dSAndy Shevchenko 	value = readl(gpdr);
150*ccf6fd6dSAndy Shevchenko 	value |= BIT(offset % 32);
151*ccf6fd6dSAndy Shevchenko 	writel(value, gpdr);
152*ccf6fd6dSAndy Shevchenko 
153*ccf6fd6dSAndy Shevchenko 	raw_spin_unlock_irqrestore(&priv->lock, flags);
154*ccf6fd6dSAndy Shevchenko 
155*ccf6fd6dSAndy Shevchenko 	return 0;
156*ccf6fd6dSAndy Shevchenko }
157*ccf6fd6dSAndy Shevchenko 
158*ccf6fd6dSAndy Shevchenko static void mrfld_irq_ack(struct irq_data *d)
159*ccf6fd6dSAndy Shevchenko {
160*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
161*ccf6fd6dSAndy Shevchenko 	u32 gpio = irqd_to_hwirq(d);
162*ccf6fd6dSAndy Shevchenko 	void __iomem *gisr = gpio_reg(&priv->chip, gpio, GISR);
163*ccf6fd6dSAndy Shevchenko 
164*ccf6fd6dSAndy Shevchenko 	writel(BIT(gpio % 32), gisr);
165*ccf6fd6dSAndy Shevchenko }
166*ccf6fd6dSAndy Shevchenko 
167*ccf6fd6dSAndy Shevchenko static void mrfld_irq_unmask_mask(struct irq_data *d, bool unmask)
168*ccf6fd6dSAndy Shevchenko {
169*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
170*ccf6fd6dSAndy Shevchenko 	u32 gpio = irqd_to_hwirq(d);
171*ccf6fd6dSAndy Shevchenko 	void __iomem *gimr = gpio_reg(&priv->chip, gpio, GIMR);
172*ccf6fd6dSAndy Shevchenko 	unsigned long flags;
173*ccf6fd6dSAndy Shevchenko 	u32 value;
174*ccf6fd6dSAndy Shevchenko 
175*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_irqsave(&priv->lock, flags);
176*ccf6fd6dSAndy Shevchenko 
177*ccf6fd6dSAndy Shevchenko 	if (unmask)
178*ccf6fd6dSAndy Shevchenko 		value = readl(gimr) | BIT(gpio % 32);
179*ccf6fd6dSAndy Shevchenko 	else
180*ccf6fd6dSAndy Shevchenko 		value = readl(gimr) & ~BIT(gpio % 32);
181*ccf6fd6dSAndy Shevchenko 	writel(value, gimr);
182*ccf6fd6dSAndy Shevchenko 
183*ccf6fd6dSAndy Shevchenko 	raw_spin_unlock_irqrestore(&priv->lock, flags);
184*ccf6fd6dSAndy Shevchenko }
185*ccf6fd6dSAndy Shevchenko 
186*ccf6fd6dSAndy Shevchenko static void mrfld_irq_mask(struct irq_data *d)
187*ccf6fd6dSAndy Shevchenko {
188*ccf6fd6dSAndy Shevchenko 	mrfld_irq_unmask_mask(d, false);
189*ccf6fd6dSAndy Shevchenko }
190*ccf6fd6dSAndy Shevchenko 
191*ccf6fd6dSAndy Shevchenko static void mrfld_irq_unmask(struct irq_data *d)
192*ccf6fd6dSAndy Shevchenko {
193*ccf6fd6dSAndy Shevchenko 	mrfld_irq_unmask_mask(d, true);
194*ccf6fd6dSAndy Shevchenko }
195*ccf6fd6dSAndy Shevchenko 
196*ccf6fd6dSAndy Shevchenko static int mrfld_irq_set_type(struct irq_data *d, unsigned int type)
197*ccf6fd6dSAndy Shevchenko {
198*ccf6fd6dSAndy Shevchenko 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
199*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(gc);
200*ccf6fd6dSAndy Shevchenko 	u32 gpio = irqd_to_hwirq(d);
201*ccf6fd6dSAndy Shevchenko 	void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
202*ccf6fd6dSAndy Shevchenko 	void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
203*ccf6fd6dSAndy Shevchenko 	void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR);
204*ccf6fd6dSAndy Shevchenko 	void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR);
205*ccf6fd6dSAndy Shevchenko 	unsigned long flags;
206*ccf6fd6dSAndy Shevchenko 	u32 value;
207*ccf6fd6dSAndy Shevchenko 
208*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_irqsave(&priv->lock, flags);
209*ccf6fd6dSAndy Shevchenko 
210*ccf6fd6dSAndy Shevchenko 	if (type & IRQ_TYPE_EDGE_RISING)
211*ccf6fd6dSAndy Shevchenko 		value = readl(grer) | BIT(gpio % 32);
212*ccf6fd6dSAndy Shevchenko 	else
213*ccf6fd6dSAndy Shevchenko 		value = readl(grer) & ~BIT(gpio % 32);
214*ccf6fd6dSAndy Shevchenko 	writel(value, grer);
215*ccf6fd6dSAndy Shevchenko 
216*ccf6fd6dSAndy Shevchenko 	if (type & IRQ_TYPE_EDGE_FALLING)
217*ccf6fd6dSAndy Shevchenko 		value = readl(gfer) | BIT(gpio % 32);
218*ccf6fd6dSAndy Shevchenko 	else
219*ccf6fd6dSAndy Shevchenko 		value = readl(gfer) & ~BIT(gpio % 32);
220*ccf6fd6dSAndy Shevchenko 	writel(value, gfer);
221*ccf6fd6dSAndy Shevchenko 
222*ccf6fd6dSAndy Shevchenko 	/*
223*ccf6fd6dSAndy Shevchenko 	 * To prevent glitches from triggering an unintended level interrupt,
224*ccf6fd6dSAndy Shevchenko 	 * configure GLPR register first and then configure GITR.
225*ccf6fd6dSAndy Shevchenko 	 */
226*ccf6fd6dSAndy Shevchenko 	if (type & IRQ_TYPE_LEVEL_LOW)
227*ccf6fd6dSAndy Shevchenko 		value = readl(glpr) | BIT(gpio % 32);
228*ccf6fd6dSAndy Shevchenko 	else
229*ccf6fd6dSAndy Shevchenko 		value = readl(glpr) & ~BIT(gpio % 32);
230*ccf6fd6dSAndy Shevchenko 	writel(value, glpr);
231*ccf6fd6dSAndy Shevchenko 
232*ccf6fd6dSAndy Shevchenko 	if (type & IRQ_TYPE_LEVEL_MASK) {
233*ccf6fd6dSAndy Shevchenko 		value = readl(gitr) | BIT(gpio % 32);
234*ccf6fd6dSAndy Shevchenko 		writel(value, gitr);
235*ccf6fd6dSAndy Shevchenko 
236*ccf6fd6dSAndy Shevchenko 		irq_set_handler_locked(d, handle_level_irq);
237*ccf6fd6dSAndy Shevchenko 	} else if (type & IRQ_TYPE_EDGE_BOTH) {
238*ccf6fd6dSAndy Shevchenko 		value = readl(gitr) & ~BIT(gpio % 32);
239*ccf6fd6dSAndy Shevchenko 		writel(value, gitr);
240*ccf6fd6dSAndy Shevchenko 
241*ccf6fd6dSAndy Shevchenko 		irq_set_handler_locked(d, handle_edge_irq);
242*ccf6fd6dSAndy Shevchenko 	}
243*ccf6fd6dSAndy Shevchenko 
244*ccf6fd6dSAndy Shevchenko 	raw_spin_unlock_irqrestore(&priv->lock, flags);
245*ccf6fd6dSAndy Shevchenko 
246*ccf6fd6dSAndy Shevchenko 	return 0;
247*ccf6fd6dSAndy Shevchenko }
248*ccf6fd6dSAndy Shevchenko 
249*ccf6fd6dSAndy Shevchenko static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on)
250*ccf6fd6dSAndy Shevchenko {
251*ccf6fd6dSAndy Shevchenko 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
252*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(gc);
253*ccf6fd6dSAndy Shevchenko 	u32 gpio = irqd_to_hwirq(d);
254*ccf6fd6dSAndy Shevchenko 	void __iomem *gwmr = gpio_reg(&priv->chip, gpio, GWMR);
255*ccf6fd6dSAndy Shevchenko 	void __iomem *gwsr = gpio_reg(&priv->chip, gpio, GWSR);
256*ccf6fd6dSAndy Shevchenko 	unsigned long flags;
257*ccf6fd6dSAndy Shevchenko 	u32 value;
258*ccf6fd6dSAndy Shevchenko 
259*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_irqsave(&priv->lock, flags);
260*ccf6fd6dSAndy Shevchenko 
261*ccf6fd6dSAndy Shevchenko 	/* Clear the existing wake status */
262*ccf6fd6dSAndy Shevchenko 	writel(BIT(gpio % 32), gwsr);
263*ccf6fd6dSAndy Shevchenko 
264*ccf6fd6dSAndy Shevchenko 	if (on)
265*ccf6fd6dSAndy Shevchenko 		value = readl(gwmr) | BIT(gpio % 32);
266*ccf6fd6dSAndy Shevchenko 	else
267*ccf6fd6dSAndy Shevchenko 		value = readl(gwmr) & ~BIT(gpio % 32);
268*ccf6fd6dSAndy Shevchenko 	writel(value, gwmr);
269*ccf6fd6dSAndy Shevchenko 
270*ccf6fd6dSAndy Shevchenko 	raw_spin_unlock_irqrestore(&priv->lock, flags);
271*ccf6fd6dSAndy Shevchenko 
272*ccf6fd6dSAndy Shevchenko 	dev_dbg(priv->dev, "%sable wake for gpio %u\n", on ? "en" : "dis", gpio);
273*ccf6fd6dSAndy Shevchenko 	return 0;
274*ccf6fd6dSAndy Shevchenko }
275*ccf6fd6dSAndy Shevchenko 
276*ccf6fd6dSAndy Shevchenko static struct irq_chip mrfld_irqchip = {
277*ccf6fd6dSAndy Shevchenko 	.name		= "gpio-merrifield",
278*ccf6fd6dSAndy Shevchenko 	.irq_ack	= mrfld_irq_ack,
279*ccf6fd6dSAndy Shevchenko 	.irq_mask	= mrfld_irq_mask,
280*ccf6fd6dSAndy Shevchenko 	.irq_unmask	= mrfld_irq_unmask,
281*ccf6fd6dSAndy Shevchenko 	.irq_set_type	= mrfld_irq_set_type,
282*ccf6fd6dSAndy Shevchenko 	.irq_set_wake	= mrfld_irq_set_wake,
283*ccf6fd6dSAndy Shevchenko };
284*ccf6fd6dSAndy Shevchenko 
285*ccf6fd6dSAndy Shevchenko static void mrfld_irq_handler(struct irq_desc *desc)
286*ccf6fd6dSAndy Shevchenko {
287*ccf6fd6dSAndy Shevchenko 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
288*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv = gpiochip_get_data(gc);
289*ccf6fd6dSAndy Shevchenko 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
290*ccf6fd6dSAndy Shevchenko 	unsigned long base, gpio;
291*ccf6fd6dSAndy Shevchenko 
292*ccf6fd6dSAndy Shevchenko 	chained_irq_enter(irqchip, desc);
293*ccf6fd6dSAndy Shevchenko 
294*ccf6fd6dSAndy Shevchenko 	/* Check GPIO controller to check which pin triggered the interrupt */
295*ccf6fd6dSAndy Shevchenko 	for (base = 0; base < priv->chip.ngpio; base += 32) {
296*ccf6fd6dSAndy Shevchenko 		void __iomem *gisr = gpio_reg(&priv->chip, base, GISR);
297*ccf6fd6dSAndy Shevchenko 		void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR);
298*ccf6fd6dSAndy Shevchenko 		unsigned long pending, enabled;
299*ccf6fd6dSAndy Shevchenko 
300*ccf6fd6dSAndy Shevchenko 		pending = readl(gisr);
301*ccf6fd6dSAndy Shevchenko 		enabled = readl(gimr);
302*ccf6fd6dSAndy Shevchenko 
303*ccf6fd6dSAndy Shevchenko 		/* Only interrupts that are enabled */
304*ccf6fd6dSAndy Shevchenko 		pending &= enabled;
305*ccf6fd6dSAndy Shevchenko 
306*ccf6fd6dSAndy Shevchenko 		for_each_set_bit(gpio, &pending, 32) {
307*ccf6fd6dSAndy Shevchenko 			unsigned int irq;
308*ccf6fd6dSAndy Shevchenko 
309*ccf6fd6dSAndy Shevchenko 			irq = irq_find_mapping(gc->irqdomain, base + gpio);
310*ccf6fd6dSAndy Shevchenko 			generic_handle_irq(irq);
311*ccf6fd6dSAndy Shevchenko 		}
312*ccf6fd6dSAndy Shevchenko 	}
313*ccf6fd6dSAndy Shevchenko 
314*ccf6fd6dSAndy Shevchenko 	chained_irq_exit(irqchip, desc);
315*ccf6fd6dSAndy Shevchenko }
316*ccf6fd6dSAndy Shevchenko 
317*ccf6fd6dSAndy Shevchenko static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
318*ccf6fd6dSAndy Shevchenko {
319*ccf6fd6dSAndy Shevchenko 	void __iomem *reg;
320*ccf6fd6dSAndy Shevchenko 	unsigned int base;
321*ccf6fd6dSAndy Shevchenko 
322*ccf6fd6dSAndy Shevchenko 	for (base = 0; base < priv->chip.ngpio; base += 32) {
323*ccf6fd6dSAndy Shevchenko 		/* Clear the rising-edge detect register */
324*ccf6fd6dSAndy Shevchenko 		reg = gpio_reg(&priv->chip, base, GRER);
325*ccf6fd6dSAndy Shevchenko 		writel(0, reg);
326*ccf6fd6dSAndy Shevchenko 		/* Clear the falling-edge detect register */
327*ccf6fd6dSAndy Shevchenko 		reg = gpio_reg(&priv->chip, base, GFER);
328*ccf6fd6dSAndy Shevchenko 		writel(0, reg);
329*ccf6fd6dSAndy Shevchenko 	}
330*ccf6fd6dSAndy Shevchenko }
331*ccf6fd6dSAndy Shevchenko 
332*ccf6fd6dSAndy Shevchenko static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
333*ccf6fd6dSAndy Shevchenko {
334*ccf6fd6dSAndy Shevchenko 	const struct mrfld_gpio_pinrange *range;
335*ccf6fd6dSAndy Shevchenko 	struct mrfld_gpio *priv;
336*ccf6fd6dSAndy Shevchenko 	u32 gpio_base, irq_base;
337*ccf6fd6dSAndy Shevchenko 	void __iomem *base;
338*ccf6fd6dSAndy Shevchenko 	unsigned int i;
339*ccf6fd6dSAndy Shevchenko 	int retval;
340*ccf6fd6dSAndy Shevchenko 
341*ccf6fd6dSAndy Shevchenko 	retval = pcim_enable_device(pdev);
342*ccf6fd6dSAndy Shevchenko 	if (retval)
343*ccf6fd6dSAndy Shevchenko 		return retval;
344*ccf6fd6dSAndy Shevchenko 
345*ccf6fd6dSAndy Shevchenko 	retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev));
346*ccf6fd6dSAndy Shevchenko 	if (retval) {
347*ccf6fd6dSAndy Shevchenko 		dev_err(&pdev->dev, "I/O memory mapping error\n");
348*ccf6fd6dSAndy Shevchenko 		return retval;
349*ccf6fd6dSAndy Shevchenko 	}
350*ccf6fd6dSAndy Shevchenko 
351*ccf6fd6dSAndy Shevchenko 	base = pcim_iomap_table(pdev)[1];
352*ccf6fd6dSAndy Shevchenko 
353*ccf6fd6dSAndy Shevchenko 	irq_base = readl(base);
354*ccf6fd6dSAndy Shevchenko 	gpio_base = readl(sizeof(u32) + base);
355*ccf6fd6dSAndy Shevchenko 
356*ccf6fd6dSAndy Shevchenko 	/* Release the IO mapping, since we already get the info from BAR1 */
357*ccf6fd6dSAndy Shevchenko 	pcim_iounmap_regions(pdev, BIT(1));
358*ccf6fd6dSAndy Shevchenko 
359*ccf6fd6dSAndy Shevchenko 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
360*ccf6fd6dSAndy Shevchenko 	if (!priv) {
361*ccf6fd6dSAndy Shevchenko 		dev_err(&pdev->dev, "can't allocate chip data\n");
362*ccf6fd6dSAndy Shevchenko 		return -ENOMEM;
363*ccf6fd6dSAndy Shevchenko 	}
364*ccf6fd6dSAndy Shevchenko 
365*ccf6fd6dSAndy Shevchenko 	priv->dev = &pdev->dev;
366*ccf6fd6dSAndy Shevchenko 	priv->reg_base = pcim_iomap_table(pdev)[0];
367*ccf6fd6dSAndy Shevchenko 
368*ccf6fd6dSAndy Shevchenko 	priv->chip.label = dev_name(&pdev->dev);
369*ccf6fd6dSAndy Shevchenko 	priv->chip.parent = &pdev->dev;
370*ccf6fd6dSAndy Shevchenko 	priv->chip.request = gpiochip_generic_request;
371*ccf6fd6dSAndy Shevchenko 	priv->chip.free = gpiochip_generic_free;
372*ccf6fd6dSAndy Shevchenko 	priv->chip.direction_input = mrfld_gpio_direction_input;
373*ccf6fd6dSAndy Shevchenko 	priv->chip.direction_output = mrfld_gpio_direction_output;
374*ccf6fd6dSAndy Shevchenko 	priv->chip.get = mrfld_gpio_get;
375*ccf6fd6dSAndy Shevchenko 	priv->chip.set = mrfld_gpio_set;
376*ccf6fd6dSAndy Shevchenko 	priv->chip.base = gpio_base;
377*ccf6fd6dSAndy Shevchenko 	priv->chip.ngpio = MRFLD_NGPIO;
378*ccf6fd6dSAndy Shevchenko 	priv->chip.can_sleep = false;
379*ccf6fd6dSAndy Shevchenko 
380*ccf6fd6dSAndy Shevchenko 	raw_spin_lock_init(&priv->lock);
381*ccf6fd6dSAndy Shevchenko 
382*ccf6fd6dSAndy Shevchenko 	pci_set_drvdata(pdev, priv);
383*ccf6fd6dSAndy Shevchenko 	retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
384*ccf6fd6dSAndy Shevchenko 	if (retval) {
385*ccf6fd6dSAndy Shevchenko 		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
386*ccf6fd6dSAndy Shevchenko 		return retval;
387*ccf6fd6dSAndy Shevchenko 	}
388*ccf6fd6dSAndy Shevchenko 
389*ccf6fd6dSAndy Shevchenko 	for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) {
390*ccf6fd6dSAndy Shevchenko 		range = &mrfld_gpio_ranges[i];
391*ccf6fd6dSAndy Shevchenko 		retval = gpiochip_add_pin_range(&priv->chip,
392*ccf6fd6dSAndy Shevchenko 						"pinctrl-merrifield",
393*ccf6fd6dSAndy Shevchenko 						range->gpio_base,
394*ccf6fd6dSAndy Shevchenko 						range->pin_base,
395*ccf6fd6dSAndy Shevchenko 						range->npins);
396*ccf6fd6dSAndy Shevchenko 		if (retval) {
397*ccf6fd6dSAndy Shevchenko 			dev_err(&pdev->dev, "failed to add GPIO pin range\n");
398*ccf6fd6dSAndy Shevchenko 			return retval;
399*ccf6fd6dSAndy Shevchenko 		}
400*ccf6fd6dSAndy Shevchenko 	}
401*ccf6fd6dSAndy Shevchenko 
402*ccf6fd6dSAndy Shevchenko 	retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
403*ccf6fd6dSAndy Shevchenko 				      handle_simple_irq, IRQ_TYPE_NONE);
404*ccf6fd6dSAndy Shevchenko 	if (retval) {
405*ccf6fd6dSAndy Shevchenko 		dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
406*ccf6fd6dSAndy Shevchenko 		return retval;
407*ccf6fd6dSAndy Shevchenko 	}
408*ccf6fd6dSAndy Shevchenko 
409*ccf6fd6dSAndy Shevchenko 	mrfld_irq_init_hw(priv);
410*ccf6fd6dSAndy Shevchenko 
411*ccf6fd6dSAndy Shevchenko 	gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
412*ccf6fd6dSAndy Shevchenko 				     mrfld_irq_handler);
413*ccf6fd6dSAndy Shevchenko 
414*ccf6fd6dSAndy Shevchenko 	return 0;
415*ccf6fd6dSAndy Shevchenko }
416*ccf6fd6dSAndy Shevchenko 
417*ccf6fd6dSAndy Shevchenko static const struct pci_device_id mrfld_gpio_ids[] = {
418*ccf6fd6dSAndy Shevchenko 	{ PCI_VDEVICE(INTEL, 0x1199) },
419*ccf6fd6dSAndy Shevchenko 	{ }
420*ccf6fd6dSAndy Shevchenko };
421*ccf6fd6dSAndy Shevchenko MODULE_DEVICE_TABLE(pci, mrfld_gpio_ids);
422*ccf6fd6dSAndy Shevchenko 
423*ccf6fd6dSAndy Shevchenko static struct pci_driver mrfld_gpio_driver = {
424*ccf6fd6dSAndy Shevchenko 	.name		= "gpio-merrifield",
425*ccf6fd6dSAndy Shevchenko 	.id_table	= mrfld_gpio_ids,
426*ccf6fd6dSAndy Shevchenko 	.probe		= mrfld_gpio_probe,
427*ccf6fd6dSAndy Shevchenko };
428*ccf6fd6dSAndy Shevchenko 
429*ccf6fd6dSAndy Shevchenko module_pci_driver(mrfld_gpio_driver);
430*ccf6fd6dSAndy Shevchenko 
431*ccf6fd6dSAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
432*ccf6fd6dSAndy Shevchenko MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver");
433*ccf6fd6dSAndy Shevchenko MODULE_LICENSE("GPL v2");
434