xref: /OK3568_Linux_fs/kernel/drivers/gpio/gpio-wcove.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Intel Whiskey Cove PMIC GPIO Driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This driver is written based on gpio-crystalcove.c
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2016 Intel Corporation. All rights reserved.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/bitops.h>
11*4882a593Smuzhiyun #include <linux/gpio/driver.h>
12*4882a593Smuzhiyun #include <linux/interrupt.h>
13*4882a593Smuzhiyun #include <linux/mfd/intel_soc_pmic.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/seq_file.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks:
21*4882a593Smuzhiyun  * Bank 0: Pin  0 - 6
22*4882a593Smuzhiyun  * Bank 1: Pin  7 - 10
23*4882a593Smuzhiyun  * Bank 2: Pin 11 - 12
24*4882a593Smuzhiyun  * Each pin has one output control register and one input control register.
25*4882a593Smuzhiyun  */
26*4882a593Smuzhiyun #define BANK0_NR_PINS		7
27*4882a593Smuzhiyun #define BANK1_NR_PINS		4
28*4882a593Smuzhiyun #define BANK2_NR_PINS		2
29*4882a593Smuzhiyun #define WCOVE_GPIO_NUM		(BANK0_NR_PINS + BANK1_NR_PINS + BANK2_NR_PINS)
30*4882a593Smuzhiyun #define WCOVE_VGPIO_NUM		94
31*4882a593Smuzhiyun /* GPIO output control registers (one per pin): 0x4e44 - 0x4e50 */
32*4882a593Smuzhiyun #define GPIO_OUT_CTRL_BASE	0x4e44
33*4882a593Smuzhiyun /* GPIO input control registers (one per pin): 0x4e51 - 0x4e5d */
34*4882a593Smuzhiyun #define GPIO_IN_CTRL_BASE	0x4e51
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun  * GPIO interrupts are organized in two groups:
38*4882a593Smuzhiyun  * Group 0: Bank 0 pins (Pin 0 - 6)
39*4882a593Smuzhiyun  * Group 1: Bank 1 and Bank 2 pins (Pin 7 - 12)
40*4882a593Smuzhiyun  * Each group has two registers (one bit per pin): status and mask.
41*4882a593Smuzhiyun  */
42*4882a593Smuzhiyun #define GROUP0_NR_IRQS		7
43*4882a593Smuzhiyun #define GROUP1_NR_IRQS		6
44*4882a593Smuzhiyun #define IRQ_MASK_BASE		0x4e19
45*4882a593Smuzhiyun #define IRQ_STATUS_BASE		0x4e0b
46*4882a593Smuzhiyun #define GPIO_IRQ0_MASK		GENMASK(6, 0)
47*4882a593Smuzhiyun #define GPIO_IRQ1_MASK		GENMASK(5, 0)
48*4882a593Smuzhiyun #define UPDATE_IRQ_TYPE		BIT(0)
49*4882a593Smuzhiyun #define UPDATE_IRQ_MASK		BIT(1)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define CTLI_INTCNT_DIS		(0 << 1)
52*4882a593Smuzhiyun #define CTLI_INTCNT_NE		(1 << 1)
53*4882a593Smuzhiyun #define CTLI_INTCNT_PE		(2 << 1)
54*4882a593Smuzhiyun #define CTLI_INTCNT_BE		(3 << 1)
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define CTLO_DIR_IN		(0 << 5)
57*4882a593Smuzhiyun #define CTLO_DIR_OUT		(1 << 5)
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define CTLO_DRV_MASK		(1 << 4)
60*4882a593Smuzhiyun #define CTLO_DRV_OD		(0 << 4)
61*4882a593Smuzhiyun #define CTLO_DRV_CMOS		(1 << 4)
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define CTLO_DRV_REN		(1 << 3)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define CTLO_RVAL_2KDOWN	(0 << 1)
66*4882a593Smuzhiyun #define CTLO_RVAL_2KUP		(1 << 1)
67*4882a593Smuzhiyun #define CTLO_RVAL_50KDOWN	(2 << 1)
68*4882a593Smuzhiyun #define CTLO_RVAL_50KUP		(3 << 1)
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #define CTLO_INPUT_SET		(CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP)
71*4882a593Smuzhiyun #define CTLO_OUTPUT_SET		(CTLO_DIR_OUT | CTLO_INPUT_SET)
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun enum ctrl_register {
74*4882a593Smuzhiyun 	CTRL_IN,
75*4882a593Smuzhiyun 	CTRL_OUT,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  * struct wcove_gpio - Whiskey Cove GPIO controller
80*4882a593Smuzhiyun  * @buslock: for bus lock/sync and unlock.
81*4882a593Smuzhiyun  * @chip: the abstract gpio_chip structure.
82*4882a593Smuzhiyun  * @dev: the gpio device
83*4882a593Smuzhiyun  * @regmap: the regmap from the parent device.
84*4882a593Smuzhiyun  * @regmap_irq_chip: the regmap of the gpio irq chip.
85*4882a593Smuzhiyun  * @update: pending IRQ setting update, to be written to the chip upon unlock.
86*4882a593Smuzhiyun  * @intcnt: the Interrupt Detect value to be written.
87*4882a593Smuzhiyun  * @set_irq_mask: true if the IRQ mask needs to be set, false to clear.
88*4882a593Smuzhiyun  */
89*4882a593Smuzhiyun struct wcove_gpio {
90*4882a593Smuzhiyun 	struct mutex buslock;
91*4882a593Smuzhiyun 	struct gpio_chip chip;
92*4882a593Smuzhiyun 	struct device *dev;
93*4882a593Smuzhiyun 	struct regmap *regmap;
94*4882a593Smuzhiyun 	struct regmap_irq_chip_data *regmap_irq_chip;
95*4882a593Smuzhiyun 	int update;
96*4882a593Smuzhiyun 	int intcnt;
97*4882a593Smuzhiyun 	bool set_irq_mask;
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun 
to_reg(int gpio,enum ctrl_register reg_type)100*4882a593Smuzhiyun static inline int to_reg(int gpio, enum ctrl_register reg_type)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	unsigned int reg;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (gpio >= WCOVE_GPIO_NUM)
105*4882a593Smuzhiyun 		return -EOPNOTSUPP;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (reg_type == CTRL_IN)
108*4882a593Smuzhiyun 		reg = GPIO_IN_CTRL_BASE + gpio;
109*4882a593Smuzhiyun 	else
110*4882a593Smuzhiyun 		reg = GPIO_OUT_CTRL_BASE + gpio;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return reg;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
wcove_update_irq_mask(struct wcove_gpio * wg,int gpio)115*4882a593Smuzhiyun static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	unsigned int reg, mask;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	if (gpio < GROUP0_NR_IRQS) {
120*4882a593Smuzhiyun 		reg = IRQ_MASK_BASE;
121*4882a593Smuzhiyun 		mask = BIT(gpio % GROUP0_NR_IRQS);
122*4882a593Smuzhiyun 	} else {
123*4882a593Smuzhiyun 		reg = IRQ_MASK_BASE + 1;
124*4882a593Smuzhiyun 		mask = BIT((gpio - GROUP0_NR_IRQS) % GROUP1_NR_IRQS);
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	if (wg->set_irq_mask)
128*4882a593Smuzhiyun 		regmap_update_bits(wg->regmap, reg, mask, mask);
129*4882a593Smuzhiyun 	else
130*4882a593Smuzhiyun 		regmap_update_bits(wg->regmap, reg, mask, 0);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
wcove_update_irq_ctrl(struct wcove_gpio * wg,int gpio)133*4882a593Smuzhiyun static void wcove_update_irq_ctrl(struct wcove_gpio *wg, int gpio)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	int reg = to_reg(gpio, CTRL_IN);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	if (reg < 0)
138*4882a593Smuzhiyun 		return;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	regmap_update_bits(wg->regmap, reg, CTLI_INTCNT_BE, wg->intcnt);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
wcove_gpio_dir_in(struct gpio_chip * chip,unsigned int gpio)143*4882a593Smuzhiyun static int wcove_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
146*4882a593Smuzhiyun 	int reg = to_reg(gpio, CTRL_OUT);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (reg < 0)
149*4882a593Smuzhiyun 		return 0;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return regmap_write(wg->regmap, reg, CTLO_INPUT_SET);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
wcove_gpio_dir_out(struct gpio_chip * chip,unsigned int gpio,int value)154*4882a593Smuzhiyun static int wcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio,
155*4882a593Smuzhiyun 				    int value)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
158*4882a593Smuzhiyun 	int reg = to_reg(gpio, CTRL_OUT);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	if (reg < 0)
161*4882a593Smuzhiyun 		return 0;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	return regmap_write(wg->regmap, reg, CTLO_OUTPUT_SET | value);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
wcove_gpio_get_direction(struct gpio_chip * chip,unsigned int gpio)166*4882a593Smuzhiyun static int wcove_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
169*4882a593Smuzhiyun 	unsigned int val;
170*4882a593Smuzhiyun 	int ret, reg = to_reg(gpio, CTRL_OUT);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (reg < 0)
173*4882a593Smuzhiyun 		return GPIO_LINE_DIRECTION_OUT;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	ret = regmap_read(wg->regmap, reg, &val);
176*4882a593Smuzhiyun 	if (ret)
177*4882a593Smuzhiyun 		return ret;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (val & CTLO_DIR_OUT)
180*4882a593Smuzhiyun 		return GPIO_LINE_DIRECTION_OUT;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	return GPIO_LINE_DIRECTION_IN;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
wcove_gpio_get(struct gpio_chip * chip,unsigned int gpio)185*4882a593Smuzhiyun static int wcove_gpio_get(struct gpio_chip *chip, unsigned int gpio)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
188*4882a593Smuzhiyun 	unsigned int val;
189*4882a593Smuzhiyun 	int ret, reg = to_reg(gpio, CTRL_IN);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	if (reg < 0)
192*4882a593Smuzhiyun 		return 0;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	ret = regmap_read(wg->regmap, reg, &val);
195*4882a593Smuzhiyun 	if (ret)
196*4882a593Smuzhiyun 		return ret;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	return val & 0x1;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
wcove_gpio_set(struct gpio_chip * chip,unsigned int gpio,int value)201*4882a593Smuzhiyun static void wcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
204*4882a593Smuzhiyun 	int reg = to_reg(gpio, CTRL_OUT);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (reg < 0)
207*4882a593Smuzhiyun 		return;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (value)
210*4882a593Smuzhiyun 		regmap_update_bits(wg->regmap, reg, 1, 1);
211*4882a593Smuzhiyun 	else
212*4882a593Smuzhiyun 		regmap_update_bits(wg->regmap, reg, 1, 0);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
wcove_gpio_set_config(struct gpio_chip * chip,unsigned int gpio,unsigned long config)215*4882a593Smuzhiyun static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio,
216*4882a593Smuzhiyun 				 unsigned long config)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
219*4882a593Smuzhiyun 	int reg = to_reg(gpio, CTRL_OUT);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (reg < 0)
222*4882a593Smuzhiyun 		return 0;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	switch (pinconf_to_config_param(config)) {
225*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
226*4882a593Smuzhiyun 		return regmap_update_bits(wg->regmap, reg, CTLO_DRV_MASK,
227*4882a593Smuzhiyun 					  CTLO_DRV_OD);
228*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_PUSH_PULL:
229*4882a593Smuzhiyun 		return regmap_update_bits(wg->regmap, reg, CTLO_DRV_MASK,
230*4882a593Smuzhiyun 					  CTLO_DRV_CMOS);
231*4882a593Smuzhiyun 	default:
232*4882a593Smuzhiyun 		break;
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	return -ENOTSUPP;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
wcove_irq_type(struct irq_data * data,unsigned int type)238*4882a593Smuzhiyun static int wcove_irq_type(struct irq_data *data, unsigned int type)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
241*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (data->hwirq >= WCOVE_GPIO_NUM)
244*4882a593Smuzhiyun 		return 0;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	switch (type) {
247*4882a593Smuzhiyun 	case IRQ_TYPE_NONE:
248*4882a593Smuzhiyun 		wg->intcnt = CTLI_INTCNT_DIS;
249*4882a593Smuzhiyun 		break;
250*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_BOTH:
251*4882a593Smuzhiyun 		wg->intcnt = CTLI_INTCNT_BE;
252*4882a593Smuzhiyun 		break;
253*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_RISING:
254*4882a593Smuzhiyun 		wg->intcnt = CTLI_INTCNT_PE;
255*4882a593Smuzhiyun 		break;
256*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_FALLING:
257*4882a593Smuzhiyun 		wg->intcnt = CTLI_INTCNT_NE;
258*4882a593Smuzhiyun 		break;
259*4882a593Smuzhiyun 	default:
260*4882a593Smuzhiyun 		return -EINVAL;
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	wg->update |= UPDATE_IRQ_TYPE;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
wcove_bus_lock(struct irq_data * data)268*4882a593Smuzhiyun static void wcove_bus_lock(struct irq_data *data)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
271*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	mutex_lock(&wg->buslock);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
wcove_bus_sync_unlock(struct irq_data * data)276*4882a593Smuzhiyun static void wcove_bus_sync_unlock(struct irq_data *data)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
279*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
280*4882a593Smuzhiyun 	int gpio = data->hwirq;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	if (wg->update & UPDATE_IRQ_TYPE)
283*4882a593Smuzhiyun 		wcove_update_irq_ctrl(wg, gpio);
284*4882a593Smuzhiyun 	if (wg->update & UPDATE_IRQ_MASK)
285*4882a593Smuzhiyun 		wcove_update_irq_mask(wg, gpio);
286*4882a593Smuzhiyun 	wg->update = 0;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	mutex_unlock(&wg->buslock);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
wcove_irq_unmask(struct irq_data * data)291*4882a593Smuzhiyun static void wcove_irq_unmask(struct irq_data *data)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
294*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (data->hwirq >= WCOVE_GPIO_NUM)
297*4882a593Smuzhiyun 		return;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	wg->set_irq_mask = false;
300*4882a593Smuzhiyun 	wg->update |= UPDATE_IRQ_MASK;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
wcove_irq_mask(struct irq_data * data)303*4882a593Smuzhiyun static void wcove_irq_mask(struct irq_data *data)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
306*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	if (data->hwirq >= WCOVE_GPIO_NUM)
309*4882a593Smuzhiyun 		return;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	wg->set_irq_mask = true;
312*4882a593Smuzhiyun 	wg->update |= UPDATE_IRQ_MASK;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun static struct irq_chip wcove_irqchip = {
316*4882a593Smuzhiyun 	.name			= "Whiskey Cove",
317*4882a593Smuzhiyun 	.irq_mask		= wcove_irq_mask,
318*4882a593Smuzhiyun 	.irq_unmask		= wcove_irq_unmask,
319*4882a593Smuzhiyun 	.irq_set_type		= wcove_irq_type,
320*4882a593Smuzhiyun 	.irq_bus_lock		= wcove_bus_lock,
321*4882a593Smuzhiyun 	.irq_bus_sync_unlock	= wcove_bus_sync_unlock,
322*4882a593Smuzhiyun };
323*4882a593Smuzhiyun 
wcove_gpio_irq_handler(int irq,void * data)324*4882a593Smuzhiyun static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	struct wcove_gpio *wg = (struct wcove_gpio *)data;
327*4882a593Smuzhiyun 	unsigned int pending, virq, gpio, mask, offset;
328*4882a593Smuzhiyun 	u8 p[2];
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (regmap_bulk_read(wg->regmap, IRQ_STATUS_BASE, p, 2)) {
331*4882a593Smuzhiyun 		dev_err(wg->dev, "Failed to read irq status register\n");
332*4882a593Smuzhiyun 		return IRQ_NONE;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
336*4882a593Smuzhiyun 	if (!pending)
337*4882a593Smuzhiyun 		return IRQ_NONE;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/* Iterate until no interrupt is pending */
340*4882a593Smuzhiyun 	while (pending) {
341*4882a593Smuzhiyun 		/* One iteration is for all pending bits */
342*4882a593Smuzhiyun 		for_each_set_bit(gpio, (const unsigned long *)&pending,
343*4882a593Smuzhiyun 						 WCOVE_GPIO_NUM) {
344*4882a593Smuzhiyun 			offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
345*4882a593Smuzhiyun 			mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
346*4882a593Smuzhiyun 								BIT(gpio);
347*4882a593Smuzhiyun 			virq = irq_find_mapping(wg->chip.irq.domain, gpio);
348*4882a593Smuzhiyun 			handle_nested_irq(virq);
349*4882a593Smuzhiyun 			regmap_update_bits(wg->regmap, IRQ_STATUS_BASE + offset,
350*4882a593Smuzhiyun 								mask, mask);
351*4882a593Smuzhiyun 		}
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 		/* Next iteration */
354*4882a593Smuzhiyun 		if (regmap_bulk_read(wg->regmap, IRQ_STATUS_BASE, p, 2)) {
355*4882a593Smuzhiyun 			dev_err(wg->dev, "Failed to read irq status\n");
356*4882a593Smuzhiyun 			break;
357*4882a593Smuzhiyun 		}
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 		pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
360*4882a593Smuzhiyun 	}
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	return IRQ_HANDLED;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
wcove_gpio_dbg_show(struct seq_file * s,struct gpio_chip * chip)365*4882a593Smuzhiyun static void wcove_gpio_dbg_show(struct seq_file *s,
366*4882a593Smuzhiyun 				      struct gpio_chip *chip)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	unsigned int ctlo, ctli, irq_mask, irq_status;
369*4882a593Smuzhiyun 	struct wcove_gpio *wg = gpiochip_get_data(chip);
370*4882a593Smuzhiyun 	int gpio, offset, group, ret = 0;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) {
373*4882a593Smuzhiyun 		group = gpio < GROUP0_NR_IRQS ? 0 : 1;
374*4882a593Smuzhiyun 		ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
375*4882a593Smuzhiyun 		ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_IN), &ctli);
376*4882a593Smuzhiyun 		ret += regmap_read(wg->regmap, IRQ_MASK_BASE + group,
377*4882a593Smuzhiyun 							&irq_mask);
378*4882a593Smuzhiyun 		ret += regmap_read(wg->regmap, IRQ_STATUS_BASE + group,
379*4882a593Smuzhiyun 							&irq_status);
380*4882a593Smuzhiyun 		if (ret) {
381*4882a593Smuzhiyun 			pr_err("Failed to read registers: ctrl out/in or irq status/mask\n");
382*4882a593Smuzhiyun 			break;
383*4882a593Smuzhiyun 		}
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 		offset = gpio % 8;
386*4882a593Smuzhiyun 		seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s\n",
387*4882a593Smuzhiyun 			   gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ",
388*4882a593Smuzhiyun 			   ctli & 0x1 ? "hi" : "lo",
389*4882a593Smuzhiyun 			   ctli & CTLI_INTCNT_NE ? "fall" : "    ",
390*4882a593Smuzhiyun 			   ctli & CTLI_INTCNT_PE ? "rise" : "    ",
391*4882a593Smuzhiyun 			   ctlo,
392*4882a593Smuzhiyun 			   irq_mask & BIT(offset) ? "mask  " : "unmask",
393*4882a593Smuzhiyun 			   irq_status & BIT(offset) ? "pending" : "       ");
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
wcove_gpio_probe(struct platform_device * pdev)397*4882a593Smuzhiyun static int wcove_gpio_probe(struct platform_device *pdev)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	struct intel_soc_pmic *pmic;
400*4882a593Smuzhiyun 	struct wcove_gpio *wg;
401*4882a593Smuzhiyun 	int virq, ret, irq;
402*4882a593Smuzhiyun 	struct device *dev;
403*4882a593Smuzhiyun 	struct gpio_irq_chip *girq;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	/*
406*4882a593Smuzhiyun 	 * This gpio platform device is created by a mfd device (see
407*4882a593Smuzhiyun 	 * drivers/mfd/intel_soc_pmic_bxtwc.c for details). Information
408*4882a593Smuzhiyun 	 * shared by all sub-devices created by the mfd device, the regmap
409*4882a593Smuzhiyun 	 * pointer for instance, is stored as driver data of the mfd device
410*4882a593Smuzhiyun 	 * driver.
411*4882a593Smuzhiyun 	 */
412*4882a593Smuzhiyun 	pmic = dev_get_drvdata(pdev->dev.parent);
413*4882a593Smuzhiyun 	if (!pmic)
414*4882a593Smuzhiyun 		return -ENODEV;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	irq = platform_get_irq(pdev, 0);
417*4882a593Smuzhiyun 	if (irq < 0)
418*4882a593Smuzhiyun 		return irq;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	dev = &pdev->dev;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	wg = devm_kzalloc(dev, sizeof(*wg), GFP_KERNEL);
423*4882a593Smuzhiyun 	if (!wg)
424*4882a593Smuzhiyun 		return -ENOMEM;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	wg->regmap_irq_chip = pmic->irq_chip_data;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	platform_set_drvdata(pdev, wg);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	mutex_init(&wg->buslock);
431*4882a593Smuzhiyun 	wg->chip.label = KBUILD_MODNAME;
432*4882a593Smuzhiyun 	wg->chip.direction_input = wcove_gpio_dir_in;
433*4882a593Smuzhiyun 	wg->chip.direction_output = wcove_gpio_dir_out;
434*4882a593Smuzhiyun 	wg->chip.get_direction = wcove_gpio_get_direction;
435*4882a593Smuzhiyun 	wg->chip.get = wcove_gpio_get;
436*4882a593Smuzhiyun 	wg->chip.set = wcove_gpio_set;
437*4882a593Smuzhiyun 	wg->chip.set_config = wcove_gpio_set_config,
438*4882a593Smuzhiyun 	wg->chip.base = -1;
439*4882a593Smuzhiyun 	wg->chip.ngpio = WCOVE_VGPIO_NUM;
440*4882a593Smuzhiyun 	wg->chip.can_sleep = true;
441*4882a593Smuzhiyun 	wg->chip.parent = pdev->dev.parent;
442*4882a593Smuzhiyun 	wg->chip.dbg_show = wcove_gpio_dbg_show;
443*4882a593Smuzhiyun 	wg->dev = dev;
444*4882a593Smuzhiyun 	wg->regmap = pmic->regmap;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	virq = regmap_irq_get_virq(wg->regmap_irq_chip, irq);
447*4882a593Smuzhiyun 	if (virq < 0) {
448*4882a593Smuzhiyun 		dev_err(dev, "Failed to get virq by irq %d\n", irq);
449*4882a593Smuzhiyun 		return virq;
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	girq = &wg->chip.irq;
453*4882a593Smuzhiyun 	girq->chip = &wcove_irqchip;
454*4882a593Smuzhiyun 	/* This will let us handle the parent IRQ in the driver */
455*4882a593Smuzhiyun 	girq->parent_handler = NULL;
456*4882a593Smuzhiyun 	girq->num_parents = 0;
457*4882a593Smuzhiyun 	girq->parents = NULL;
458*4882a593Smuzhiyun 	girq->default_type = IRQ_TYPE_NONE;
459*4882a593Smuzhiyun 	girq->handler = handle_simple_irq;
460*4882a593Smuzhiyun 	girq->threaded = true;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	ret = devm_request_threaded_irq(dev, virq, NULL, wcove_gpio_irq_handler,
463*4882a593Smuzhiyun 					IRQF_ONESHOT, pdev->name, wg);
464*4882a593Smuzhiyun 	if (ret) {
465*4882a593Smuzhiyun 		dev_err(dev, "Failed to request irq %d\n", virq);
466*4882a593Smuzhiyun 		return ret;
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	ret = devm_gpiochip_add_data(dev, &wg->chip, wg);
470*4882a593Smuzhiyun 	if (ret) {
471*4882a593Smuzhiyun 		dev_err(dev, "Failed to add gpiochip: %d\n", ret);
472*4882a593Smuzhiyun 		return ret;
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/* Enable GPIO0 interrupts */
476*4882a593Smuzhiyun 	ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK,
477*4882a593Smuzhiyun 				 0x00);
478*4882a593Smuzhiyun 	if (ret)
479*4882a593Smuzhiyun 		return ret;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	/* Enable GPIO1 interrupts */
482*4882a593Smuzhiyun 	ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK,
483*4882a593Smuzhiyun 				 0x00);
484*4882a593Smuzhiyun 	if (ret)
485*4882a593Smuzhiyun 		return ret;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun /*
491*4882a593Smuzhiyun  * Whiskey Cove PMIC itself is a analog device(but with digital control
492*4882a593Smuzhiyun  * interface) providing power management support for other devices in
493*4882a593Smuzhiyun  * the accompanied SoC, so we have no .pm for Whiskey Cove GPIO driver.
494*4882a593Smuzhiyun  */
495*4882a593Smuzhiyun static struct platform_driver wcove_gpio_driver = {
496*4882a593Smuzhiyun 	.driver = {
497*4882a593Smuzhiyun 		.name = "bxt_wcove_gpio",
498*4882a593Smuzhiyun 	},
499*4882a593Smuzhiyun 	.probe = wcove_gpio_probe,
500*4882a593Smuzhiyun };
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun module_platform_driver(wcove_gpio_driver);
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun MODULE_AUTHOR("Ajay Thomas <ajay.thomas.david.rajamanickam@intel.com>");
505*4882a593Smuzhiyun MODULE_AUTHOR("Bin Gao <bin.gao@intel.com>");
506*4882a593Smuzhiyun MODULE_DESCRIPTION("Intel Whiskey Cove GPIO Driver");
507*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
508*4882a593Smuzhiyun MODULE_ALIAS("platform:bxt_wcove_gpio");
509