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