xref: /openbmc/linux/drivers/gpio/gpio-max77620.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
202c5ba1eSLaxman Dewangan /*
302c5ba1eSLaxman Dewangan  * MAXIM MAX77620 GPIO driver
402c5ba1eSLaxman Dewangan  *
502c5ba1eSLaxman Dewangan  * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
602c5ba1eSLaxman Dewangan  */
702c5ba1eSLaxman Dewangan 
802c5ba1eSLaxman Dewangan #include <linux/gpio/driver.h>
902c5ba1eSLaxman Dewangan #include <linux/interrupt.h>
1002c5ba1eSLaxman Dewangan #include <linux/mfd/max77620.h>
1102c5ba1eSLaxman Dewangan #include <linux/module.h>
1202c5ba1eSLaxman Dewangan #include <linux/platform_device.h>
1302c5ba1eSLaxman Dewangan #include <linux/regmap.h>
1402c5ba1eSLaxman Dewangan 
1502c5ba1eSLaxman Dewangan #define GPIO_REG_ADDR(offset) (MAX77620_REG_GPIO0 + offset)
1602c5ba1eSLaxman Dewangan 
1702c5ba1eSLaxman Dewangan struct max77620_gpio {
1802c5ba1eSLaxman Dewangan 	struct gpio_chip	gpio_chip;
1902c5ba1eSLaxman Dewangan 	struct regmap		*rmap;
2002c5ba1eSLaxman Dewangan 	struct device		*dev;
21ab3dd9ccSTimo Alho 	struct mutex		buslock; /* irq_bus_lock */
224ee82256SDmitry Osipenko 	unsigned int		irq_type[MAX77620_GPIO_NR];
234ee82256SDmitry Osipenko 	bool			irq_enabled[MAX77620_GPIO_NR];
2402c5ba1eSLaxman Dewangan };
2502c5ba1eSLaxman Dewangan 
max77620_gpio_irqhandler(int irq,void * data)26ab3dd9ccSTimo Alho static irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
27ab3dd9ccSTimo Alho {
28ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = data;
29ab3dd9ccSTimo Alho 	unsigned int value, offset;
30ab3dd9ccSTimo Alho 	unsigned long pending;
31ab3dd9ccSTimo Alho 	int err;
3202c5ba1eSLaxman Dewangan 
33ab3dd9ccSTimo Alho 	err = regmap_read(gpio->rmap, MAX77620_REG_IRQ_LVL2_GPIO, &value);
34ab3dd9ccSTimo Alho 	if (err < 0) {
35ab3dd9ccSTimo Alho 		dev_err(gpio->dev, "REG_IRQ_LVL2_GPIO read failed: %d\n", err);
36ab3dd9ccSTimo Alho 		return IRQ_NONE;
37ab3dd9ccSTimo Alho 	}
38ab3dd9ccSTimo Alho 
39ab3dd9ccSTimo Alho 	pending = value;
40ab3dd9ccSTimo Alho 
414ee82256SDmitry Osipenko 	for_each_set_bit(offset, &pending, MAX77620_GPIO_NR) {
42ab3dd9ccSTimo Alho 		unsigned int virq;
43ab3dd9ccSTimo Alho 
44ab3dd9ccSTimo Alho 		virq = irq_find_mapping(gpio->gpio_chip.irq.domain, offset);
45ab3dd9ccSTimo Alho 		handle_nested_irq(virq);
46ab3dd9ccSTimo Alho 	}
47ab3dd9ccSTimo Alho 
48ab3dd9ccSTimo Alho 	return IRQ_HANDLED;
49ab3dd9ccSTimo Alho }
50ab3dd9ccSTimo Alho 
max77620_gpio_irq_mask(struct irq_data * data)51ab3dd9ccSTimo Alho static void max77620_gpio_irq_mask(struct irq_data *data)
52ab3dd9ccSTimo Alho {
53ab3dd9ccSTimo Alho 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
54ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = gpiochip_get_data(chip);
55ab3dd9ccSTimo Alho 
56ab3dd9ccSTimo Alho 	gpio->irq_enabled[data->hwirq] = false;
57*7f42aa7bSJon Hunter 	gpiochip_disable_irq(chip, data->hwirq);
58ab3dd9ccSTimo Alho }
59ab3dd9ccSTimo Alho 
max77620_gpio_irq_unmask(struct irq_data * data)60ab3dd9ccSTimo Alho static void max77620_gpio_irq_unmask(struct irq_data *data)
61ab3dd9ccSTimo Alho {
62ab3dd9ccSTimo Alho 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
63ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = gpiochip_get_data(chip);
64ab3dd9ccSTimo Alho 
65*7f42aa7bSJon Hunter 	gpiochip_enable_irq(chip, data->hwirq);
66ab3dd9ccSTimo Alho 	gpio->irq_enabled[data->hwirq] = true;
67ab3dd9ccSTimo Alho }
68ab3dd9ccSTimo Alho 
max77620_gpio_set_irq_type(struct irq_data * data,unsigned int type)69ab3dd9ccSTimo Alho static int max77620_gpio_set_irq_type(struct irq_data *data, unsigned int type)
70ab3dd9ccSTimo Alho {
71ab3dd9ccSTimo Alho 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
72ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = gpiochip_get_data(chip);
73ab3dd9ccSTimo Alho 	unsigned int irq_type;
74ab3dd9ccSTimo Alho 
75ab3dd9ccSTimo Alho 	switch (type) {
76ab3dd9ccSTimo Alho 	case IRQ_TYPE_EDGE_RISING:
77ab3dd9ccSTimo Alho 		irq_type = MAX77620_CNFG_GPIO_INT_RISING;
78ab3dd9ccSTimo Alho 		break;
79ab3dd9ccSTimo Alho 
80ab3dd9ccSTimo Alho 	case IRQ_TYPE_EDGE_FALLING:
81ab3dd9ccSTimo Alho 		irq_type = MAX77620_CNFG_GPIO_INT_FALLING;
82ab3dd9ccSTimo Alho 		break;
83ab3dd9ccSTimo Alho 
84ab3dd9ccSTimo Alho 	case IRQ_TYPE_EDGE_BOTH:
85ab3dd9ccSTimo Alho 		irq_type = MAX77620_CNFG_GPIO_INT_RISING |
86ab3dd9ccSTimo Alho 			   MAX77620_CNFG_GPIO_INT_FALLING;
87ab3dd9ccSTimo Alho 		break;
88ab3dd9ccSTimo Alho 
89ab3dd9ccSTimo Alho 	default:
90ab3dd9ccSTimo Alho 		return -EINVAL;
91ab3dd9ccSTimo Alho 	}
92ab3dd9ccSTimo Alho 
93ab3dd9ccSTimo Alho 	gpio->irq_type[data->hwirq] = irq_type;
94ab3dd9ccSTimo Alho 
95ab3dd9ccSTimo Alho 	return 0;
96ab3dd9ccSTimo Alho }
97ab3dd9ccSTimo Alho 
max77620_gpio_bus_lock(struct irq_data * data)98ab3dd9ccSTimo Alho static void max77620_gpio_bus_lock(struct irq_data *data)
99ab3dd9ccSTimo Alho {
100ab3dd9ccSTimo Alho 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
101ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = gpiochip_get_data(chip);
102ab3dd9ccSTimo Alho 
103ab3dd9ccSTimo Alho 	mutex_lock(&gpio->buslock);
104ab3dd9ccSTimo Alho }
105ab3dd9ccSTimo Alho 
max77620_gpio_bus_sync_unlock(struct irq_data * data)106ab3dd9ccSTimo Alho static void max77620_gpio_bus_sync_unlock(struct irq_data *data)
107ab3dd9ccSTimo Alho {
108ab3dd9ccSTimo Alho 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
109ab3dd9ccSTimo Alho 	struct max77620_gpio *gpio = gpiochip_get_data(chip);
110ab3dd9ccSTimo Alho 	unsigned int value, offset = data->hwirq;
111ab3dd9ccSTimo Alho 	int err;
112ab3dd9ccSTimo Alho 
113ab3dd9ccSTimo Alho 	value = gpio->irq_enabled[offset] ? gpio->irq_type[offset] : 0;
114ab3dd9ccSTimo Alho 
115ab3dd9ccSTimo Alho 	err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(offset),
116ab3dd9ccSTimo Alho 				 MAX77620_CNFG_GPIO_INT_MASK, value);
117ab3dd9ccSTimo Alho 	if (err < 0)
118ab3dd9ccSTimo Alho 		dev_err(chip->parent, "failed to update interrupt mask: %d\n",
119ab3dd9ccSTimo Alho 			err);
120ab3dd9ccSTimo Alho 
121ab3dd9ccSTimo Alho 	mutex_unlock(&gpio->buslock);
122ab3dd9ccSTimo Alho }
123ab3dd9ccSTimo Alho 
124*7f42aa7bSJon Hunter static const struct irq_chip max77620_gpio_irqchip = {
12502c5ba1eSLaxman Dewangan 	.name		= "max77620-gpio",
126ab3dd9ccSTimo Alho 	.irq_mask	= max77620_gpio_irq_mask,
127ab3dd9ccSTimo Alho 	.irq_unmask	= max77620_gpio_irq_unmask,
128ab3dd9ccSTimo Alho 	.irq_set_type	= max77620_gpio_set_irq_type,
129ab3dd9ccSTimo Alho 	.irq_bus_lock	= max77620_gpio_bus_lock,
130ab3dd9ccSTimo Alho 	.irq_bus_sync_unlock = max77620_gpio_bus_sync_unlock,
131*7f42aa7bSJon Hunter 	.flags		= IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND,
132*7f42aa7bSJon Hunter 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
13302c5ba1eSLaxman Dewangan };
13402c5ba1eSLaxman Dewangan 
max77620_gpio_dir_input(struct gpio_chip * gc,unsigned int offset)13502c5ba1eSLaxman Dewangan static int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
13602c5ba1eSLaxman Dewangan {
13702c5ba1eSLaxman Dewangan 	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
13802c5ba1eSLaxman Dewangan 	int ret;
13902c5ba1eSLaxman Dewangan 
14002c5ba1eSLaxman Dewangan 	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
14102c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_DIR_MASK,
14202c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_DIR_INPUT);
14302c5ba1eSLaxman Dewangan 	if (ret < 0)
14402c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
14502c5ba1eSLaxman Dewangan 
14602c5ba1eSLaxman Dewangan 	return ret;
14702c5ba1eSLaxman Dewangan }
14802c5ba1eSLaxman Dewangan 
max77620_gpio_get(struct gpio_chip * gc,unsigned int offset)14902c5ba1eSLaxman Dewangan static int max77620_gpio_get(struct gpio_chip *gc, unsigned int offset)
15002c5ba1eSLaxman Dewangan {
15102c5ba1eSLaxman Dewangan 	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
15202c5ba1eSLaxman Dewangan 	unsigned int val;
15302c5ba1eSLaxman Dewangan 	int ret;
15402c5ba1eSLaxman Dewangan 
15502c5ba1eSLaxman Dewangan 	ret = regmap_read(mgpio->rmap, GPIO_REG_ADDR(offset), &val);
15602c5ba1eSLaxman Dewangan 	if (ret < 0) {
15702c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIOx read failed: %d\n", ret);
15802c5ba1eSLaxman Dewangan 		return ret;
15902c5ba1eSLaxman Dewangan 	}
16002c5ba1eSLaxman Dewangan 
1611941b441SVenkat Reddy Talla 	if  (val & MAX77620_CNFG_GPIO_DIR_MASK)
16202c5ba1eSLaxman Dewangan 		return !!(val & MAX77620_CNFG_GPIO_INPUT_VAL_MASK);
1631941b441SVenkat Reddy Talla 	else
1641941b441SVenkat Reddy Talla 		return !!(val & MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK);
16502c5ba1eSLaxman Dewangan }
16602c5ba1eSLaxman Dewangan 
max77620_gpio_dir_output(struct gpio_chip * gc,unsigned int offset,int value)16702c5ba1eSLaxman Dewangan static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
16802c5ba1eSLaxman Dewangan 				    int value)
16902c5ba1eSLaxman Dewangan {
17002c5ba1eSLaxman Dewangan 	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
17102c5ba1eSLaxman Dewangan 	u8 val;
17202c5ba1eSLaxman Dewangan 	int ret;
17302c5ba1eSLaxman Dewangan 
17402c5ba1eSLaxman Dewangan 	val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
17502c5ba1eSLaxman Dewangan 				MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
17602c5ba1eSLaxman Dewangan 
17702c5ba1eSLaxman Dewangan 	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
17802c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
17902c5ba1eSLaxman Dewangan 	if (ret < 0) {
18002c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIOx val update failed: %d\n", ret);
18102c5ba1eSLaxman Dewangan 		return ret;
18202c5ba1eSLaxman Dewangan 	}
18302c5ba1eSLaxman Dewangan 
18402c5ba1eSLaxman Dewangan 	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
18502c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_DIR_MASK,
18602c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_DIR_OUTPUT);
18702c5ba1eSLaxman Dewangan 	if (ret < 0)
18802c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
18902c5ba1eSLaxman Dewangan 
19002c5ba1eSLaxman Dewangan 	return ret;
19102c5ba1eSLaxman Dewangan }
19202c5ba1eSLaxman Dewangan 
max77620_gpio_set_debounce(struct max77620_gpio * mgpio,unsigned int offset,unsigned int debounce)1932956b5d9SMika Westerberg static int max77620_gpio_set_debounce(struct max77620_gpio *mgpio,
19402c5ba1eSLaxman Dewangan 				      unsigned int offset,
19502c5ba1eSLaxman Dewangan 				      unsigned int debounce)
19602c5ba1eSLaxman Dewangan {
19702c5ba1eSLaxman Dewangan 	u8 val;
19802c5ba1eSLaxman Dewangan 	int ret;
19902c5ba1eSLaxman Dewangan 
20002c5ba1eSLaxman Dewangan 	switch (debounce) {
20102c5ba1eSLaxman Dewangan 	case 0:
20202c5ba1eSLaxman Dewangan 		val = MAX77620_CNFG_GPIO_DBNC_None;
20302c5ba1eSLaxman Dewangan 		break;
204b0391479SThierry Reding 	case 1 ... 8000:
20502c5ba1eSLaxman Dewangan 		val = MAX77620_CNFG_GPIO_DBNC_8ms;
20602c5ba1eSLaxman Dewangan 		break;
207b0391479SThierry Reding 	case 8001 ... 16000:
20802c5ba1eSLaxman Dewangan 		val = MAX77620_CNFG_GPIO_DBNC_16ms;
20902c5ba1eSLaxman Dewangan 		break;
210b0391479SThierry Reding 	case 16001 ... 32000:
21102c5ba1eSLaxman Dewangan 		val = MAX77620_CNFG_GPIO_DBNC_32ms;
21202c5ba1eSLaxman Dewangan 		break;
21302c5ba1eSLaxman Dewangan 	default:
21402c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "Illegal value %u\n", debounce);
21502c5ba1eSLaxman Dewangan 		return -EINVAL;
21602c5ba1eSLaxman Dewangan 	}
21702c5ba1eSLaxman Dewangan 
21802c5ba1eSLaxman Dewangan 	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
21902c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_DBNC_MASK, val);
22002c5ba1eSLaxman Dewangan 	if (ret < 0)
22102c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIOx_DBNC update failed: %d\n", ret);
22202c5ba1eSLaxman Dewangan 
22302c5ba1eSLaxman Dewangan 	return ret;
22402c5ba1eSLaxman Dewangan }
22502c5ba1eSLaxman Dewangan 
max77620_gpio_set(struct gpio_chip * gc,unsigned int offset,int value)22602c5ba1eSLaxman Dewangan static void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset,
22702c5ba1eSLaxman Dewangan 			      int value)
22802c5ba1eSLaxman Dewangan {
22902c5ba1eSLaxman Dewangan 	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
23002c5ba1eSLaxman Dewangan 	u8 val;
23102c5ba1eSLaxman Dewangan 	int ret;
23202c5ba1eSLaxman Dewangan 
23302c5ba1eSLaxman Dewangan 	val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
23402c5ba1eSLaxman Dewangan 				MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
23502c5ba1eSLaxman Dewangan 
23602c5ba1eSLaxman Dewangan 	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
23702c5ba1eSLaxman Dewangan 				 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
23802c5ba1eSLaxman Dewangan 	if (ret < 0)
23902c5ba1eSLaxman Dewangan 		dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret);
24002c5ba1eSLaxman Dewangan }
24102c5ba1eSLaxman Dewangan 
max77620_gpio_set_config(struct gpio_chip * gc,unsigned int offset,unsigned long config)2422956b5d9SMika Westerberg static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
2432956b5d9SMika Westerberg 				    unsigned long config)
24423087a05SLaxman Dewangan {
24523087a05SLaxman Dewangan 	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
24623087a05SLaxman Dewangan 
2472956b5d9SMika Westerberg 	switch (pinconf_to_config_param(config)) {
2482956b5d9SMika Westerberg 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
24923087a05SLaxman Dewangan 		return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
25023087a05SLaxman Dewangan 					  MAX77620_CNFG_GPIO_DRV_MASK,
25123087a05SLaxman Dewangan 					  MAX77620_CNFG_GPIO_DRV_OPENDRAIN);
2522956b5d9SMika Westerberg 	case PIN_CONFIG_DRIVE_PUSH_PULL:
25323087a05SLaxman Dewangan 		return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
25423087a05SLaxman Dewangan 					  MAX77620_CNFG_GPIO_DRV_MASK,
25523087a05SLaxman Dewangan 					  MAX77620_CNFG_GPIO_DRV_PUSHPULL);
2562956b5d9SMika Westerberg 	case PIN_CONFIG_INPUT_DEBOUNCE:
2572956b5d9SMika Westerberg 		return max77620_gpio_set_debounce(mgpio, offset,
2582956b5d9SMika Westerberg 			pinconf_to_config_argument(config));
25923087a05SLaxman Dewangan 	default:
26023087a05SLaxman Dewangan 		break;
26123087a05SLaxman Dewangan 	}
26223087a05SLaxman Dewangan 
26323087a05SLaxman Dewangan 	return -ENOTSUPP;
26423087a05SLaxman Dewangan }
26523087a05SLaxman Dewangan 
max77620_gpio_irq_init_hw(struct gpio_chip * gc)266e6827bc3SDmitry Osipenko static int max77620_gpio_irq_init_hw(struct gpio_chip *gc)
267e6827bc3SDmitry Osipenko {
268e6827bc3SDmitry Osipenko 	struct max77620_gpio *gpio = gpiochip_get_data(gc);
269e6827bc3SDmitry Osipenko 	unsigned int i;
270e6827bc3SDmitry Osipenko 	int err;
271e6827bc3SDmitry Osipenko 
272e6827bc3SDmitry Osipenko 	/*
273e6827bc3SDmitry Osipenko 	 * GPIO interrupts may be left ON after bootloader, hence let's
274e6827bc3SDmitry Osipenko 	 * pre-initialize hardware to the expected state by disabling all
275e6827bc3SDmitry Osipenko 	 * the interrupts.
276e6827bc3SDmitry Osipenko 	 */
277e6827bc3SDmitry Osipenko 	for (i = 0; i < MAX77620_GPIO_NR; i++) {
278e6827bc3SDmitry Osipenko 		err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(i),
279e6827bc3SDmitry Osipenko 					 MAX77620_CNFG_GPIO_INT_MASK, 0);
280e6827bc3SDmitry Osipenko 		if (err < 0) {
281e6827bc3SDmitry Osipenko 			dev_err(gpio->dev,
282e6827bc3SDmitry Osipenko 				"failed to disable interrupt: %d\n", err);
283e6827bc3SDmitry Osipenko 			return err;
284e6827bc3SDmitry Osipenko 		}
285e6827bc3SDmitry Osipenko 	}
286e6827bc3SDmitry Osipenko 
287e6827bc3SDmitry Osipenko 	return 0;
288e6827bc3SDmitry Osipenko }
289e6827bc3SDmitry Osipenko 
max77620_gpio_probe(struct platform_device * pdev)29002c5ba1eSLaxman Dewangan static int max77620_gpio_probe(struct platform_device *pdev)
29102c5ba1eSLaxman Dewangan {
29202c5ba1eSLaxman Dewangan 	struct max77620_chip *chip =  dev_get_drvdata(pdev->dev.parent);
29302c5ba1eSLaxman Dewangan 	struct max77620_gpio *mgpio;
29480606cb2SLinus Walleij 	struct gpio_irq_chip *girq;
295c607e5e2SDmitry Osipenko 	unsigned int gpio_irq;
29602c5ba1eSLaxman Dewangan 	int ret;
29702c5ba1eSLaxman Dewangan 
298c607e5e2SDmitry Osipenko 	ret = platform_get_irq(pdev, 0);
299c607e5e2SDmitry Osipenko 	if (ret < 0)
300c607e5e2SDmitry Osipenko 		return ret;
301c607e5e2SDmitry Osipenko 
302c607e5e2SDmitry Osipenko 	gpio_irq = ret;
30302c5ba1eSLaxman Dewangan 
30402c5ba1eSLaxman Dewangan 	mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
30502c5ba1eSLaxman Dewangan 	if (!mgpio)
30602c5ba1eSLaxman Dewangan 		return -ENOMEM;
30702c5ba1eSLaxman Dewangan 
30815d9e7e8SDmitry Osipenko 	mutex_init(&mgpio->buslock);
30902c5ba1eSLaxman Dewangan 	mgpio->rmap = chip->rmap;
31002c5ba1eSLaxman Dewangan 	mgpio->dev = &pdev->dev;
31102c5ba1eSLaxman Dewangan 
31202c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.label = pdev->name;
31378934d88SDmitry Osipenko 	mgpio->gpio_chip.parent = pdev->dev.parent;
31402c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
31502c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.get = max77620_gpio_get;
31602c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
31702c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.set = max77620_gpio_set;
3182956b5d9SMika Westerberg 	mgpio->gpio_chip.set_config = max77620_gpio_set_config;
31902c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
32002c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.can_sleep = 1;
32102c5ba1eSLaxman Dewangan 	mgpio->gpio_chip.base = -1;
32202c5ba1eSLaxman Dewangan 
32380606cb2SLinus Walleij 	girq = &mgpio->gpio_chip.irq;
324*7f42aa7bSJon Hunter 	gpio_irq_chip_set_chip(girq, &max77620_gpio_irqchip);
32580606cb2SLinus Walleij 	/* This will let us handle the parent IRQ in the driver */
32680606cb2SLinus Walleij 	girq->parent_handler = NULL;
32780606cb2SLinus Walleij 	girq->num_parents = 0;
32880606cb2SLinus Walleij 	girq->parents = NULL;
32980606cb2SLinus Walleij 	girq->default_type = IRQ_TYPE_NONE;
33080606cb2SLinus Walleij 	girq->handler = handle_edge_irq;
331de49e83cSZheng Yongjun 	girq->init_hw = max77620_gpio_irq_init_hw;
33280606cb2SLinus Walleij 	girq->threaded = true;
33315d9e7e8SDmitry Osipenko 
33402c5ba1eSLaxman Dewangan 	ret = devm_gpiochip_add_data(&pdev->dev, &mgpio->gpio_chip, mgpio);
33502c5ba1eSLaxman Dewangan 	if (ret < 0) {
33602c5ba1eSLaxman Dewangan 		dev_err(&pdev->dev, "gpio_init: Failed to add max77620_gpio\n");
33702c5ba1eSLaxman Dewangan 		return ret;
33802c5ba1eSLaxman Dewangan 	}
33902c5ba1eSLaxman Dewangan 
3402a5e6f7eSDmitry Osipenko 	ret = devm_request_threaded_irq(&pdev->dev, gpio_irq, NULL,
3412a5e6f7eSDmitry Osipenko 					max77620_gpio_irqhandler, IRQF_ONESHOT,
3422a5e6f7eSDmitry Osipenko 					"max77620-gpio", mgpio);
34302c5ba1eSLaxman Dewangan 	if (ret < 0) {
344ab3dd9ccSTimo Alho 		dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
34502c5ba1eSLaxman Dewangan 		return ret;
34602c5ba1eSLaxman Dewangan 	}
34702c5ba1eSLaxman Dewangan 
34802c5ba1eSLaxman Dewangan 	return 0;
34902c5ba1eSLaxman Dewangan }
35002c5ba1eSLaxman Dewangan 
35102c5ba1eSLaxman Dewangan static const struct platform_device_id max77620_gpio_devtype[] = {
35202c5ba1eSLaxman Dewangan 	{ .name = "max77620-gpio", },
3533107d572SVenkat Reddy Talla 	{ .name = "max20024-gpio", },
35402c5ba1eSLaxman Dewangan 	{},
35502c5ba1eSLaxman Dewangan };
35602c5ba1eSLaxman Dewangan MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
35702c5ba1eSLaxman Dewangan 
35802c5ba1eSLaxman Dewangan static struct platform_driver max77620_gpio_driver = {
35902c5ba1eSLaxman Dewangan 	.driver.name	= "max77620-gpio",
36002c5ba1eSLaxman Dewangan 	.probe		= max77620_gpio_probe,
36102c5ba1eSLaxman Dewangan 	.id_table	= max77620_gpio_devtype,
36202c5ba1eSLaxman Dewangan };
36302c5ba1eSLaxman Dewangan 
36402c5ba1eSLaxman Dewangan module_platform_driver(max77620_gpio_driver);
36502c5ba1eSLaxman Dewangan 
36602c5ba1eSLaxman Dewangan MODULE_DESCRIPTION("GPIO interface for MAX77620 and MAX20024 PMIC");
36702c5ba1eSLaxman Dewangan MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
36802c5ba1eSLaxman Dewangan MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
36902c5ba1eSLaxman Dewangan MODULE_LICENSE("GPL v2");
370