18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * MAXIM MAX77620 GPIO driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
98c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
108c2ecf20Sopenharmony_ci#include <linux/mfd/max77620.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
138c2ecf20Sopenharmony_ci#include <linux/regmap.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define GPIO_REG_ADDR(offset) (MAX77620_REG_GPIO0 + offset)
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct max77620_gpio {
188c2ecf20Sopenharmony_ci	struct gpio_chip	gpio_chip;
198c2ecf20Sopenharmony_ci	struct regmap		*rmap;
208c2ecf20Sopenharmony_ci	struct device		*dev;
218c2ecf20Sopenharmony_ci	struct mutex		buslock; /* irq_bus_lock */
228c2ecf20Sopenharmony_ci	unsigned int		irq_type[MAX77620_GPIO_NR];
238c2ecf20Sopenharmony_ci	bool			irq_enabled[MAX77620_GPIO_NR];
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = data;
298c2ecf20Sopenharmony_ci	unsigned int value, offset;
308c2ecf20Sopenharmony_ci	unsigned long pending;
318c2ecf20Sopenharmony_ci	int err;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	err = regmap_read(gpio->rmap, MAX77620_REG_IRQ_LVL2_GPIO, &value);
348c2ecf20Sopenharmony_ci	if (err < 0) {
358c2ecf20Sopenharmony_ci		dev_err(gpio->dev, "REG_IRQ_LVL2_GPIO read failed: %d\n", err);
368c2ecf20Sopenharmony_ci		return IRQ_NONE;
378c2ecf20Sopenharmony_ci	}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	pending = value;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	for_each_set_bit(offset, &pending, MAX77620_GPIO_NR) {
428c2ecf20Sopenharmony_ci		unsigned int virq;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci		virq = irq_find_mapping(gpio->gpio_chip.irq.domain, offset);
458c2ecf20Sopenharmony_ci		handle_nested_irq(virq);
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic void max77620_gpio_irq_mask(struct irq_data *data)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
548c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(chip);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	gpio->irq_enabled[data->hwirq] = false;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void max77620_gpio_irq_unmask(struct irq_data *data)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
628c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(chip);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	gpio->irq_enabled[data->hwirq] = true;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic int max77620_gpio_set_irq_type(struct irq_data *data, unsigned int type)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
708c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(chip);
718c2ecf20Sopenharmony_ci	unsigned int irq_type;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	switch (type) {
748c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_RISING:
758c2ecf20Sopenharmony_ci		irq_type = MAX77620_CNFG_GPIO_INT_RISING;
768c2ecf20Sopenharmony_ci		break;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_FALLING:
798c2ecf20Sopenharmony_ci		irq_type = MAX77620_CNFG_GPIO_INT_FALLING;
808c2ecf20Sopenharmony_ci		break;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_BOTH:
838c2ecf20Sopenharmony_ci		irq_type = MAX77620_CNFG_GPIO_INT_RISING |
848c2ecf20Sopenharmony_ci			   MAX77620_CNFG_GPIO_INT_FALLING;
858c2ecf20Sopenharmony_ci		break;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	default:
888c2ecf20Sopenharmony_ci		return -EINVAL;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	gpio->irq_type[data->hwirq] = irq_type;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	return 0;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic void max77620_gpio_bus_lock(struct irq_data *data)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
998c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(chip);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	mutex_lock(&gpio->buslock);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic void max77620_gpio_bus_sync_unlock(struct irq_data *data)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
1078c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(chip);
1088c2ecf20Sopenharmony_ci	unsigned int value, offset = data->hwirq;
1098c2ecf20Sopenharmony_ci	int err;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	value = gpio->irq_enabled[offset] ? gpio->irq_type[offset] : 0;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(offset),
1148c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_INT_MASK, value);
1158c2ecf20Sopenharmony_ci	if (err < 0)
1168c2ecf20Sopenharmony_ci		dev_err(chip->parent, "failed to update interrupt mask: %d\n",
1178c2ecf20Sopenharmony_ci			err);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	mutex_unlock(&gpio->buslock);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic struct irq_chip max77620_gpio_irqchip = {
1238c2ecf20Sopenharmony_ci	.name		= "max77620-gpio",
1248c2ecf20Sopenharmony_ci	.irq_mask	= max77620_gpio_irq_mask,
1258c2ecf20Sopenharmony_ci	.irq_unmask	= max77620_gpio_irq_unmask,
1268c2ecf20Sopenharmony_ci	.irq_set_type	= max77620_gpio_set_irq_type,
1278c2ecf20Sopenharmony_ci	.irq_bus_lock	= max77620_gpio_bus_lock,
1288c2ecf20Sopenharmony_ci	.irq_bus_sync_unlock = max77620_gpio_bus_sync_unlock,
1298c2ecf20Sopenharmony_ci	.flags		= IRQCHIP_MASK_ON_SUSPEND,
1308c2ecf20Sopenharmony_ci};
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
1358c2ecf20Sopenharmony_ci	int ret;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
1388c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_DIR_MASK,
1398c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_DIR_INPUT);
1408c2ecf20Sopenharmony_ci	if (ret < 0)
1418c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return ret;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic int max77620_gpio_get(struct gpio_chip *gc, unsigned int offset)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
1498c2ecf20Sopenharmony_ci	unsigned int val;
1508c2ecf20Sopenharmony_ci	int ret;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	ret = regmap_read(mgpio->rmap, GPIO_REG_ADDR(offset), &val);
1538c2ecf20Sopenharmony_ci	if (ret < 0) {
1548c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIOx read failed: %d\n", ret);
1558c2ecf20Sopenharmony_ci		return ret;
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	if  (val & MAX77620_CNFG_GPIO_DIR_MASK)
1598c2ecf20Sopenharmony_ci		return !!(val & MAX77620_CNFG_GPIO_INPUT_VAL_MASK);
1608c2ecf20Sopenharmony_ci	else
1618c2ecf20Sopenharmony_ci		return !!(val & MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK);
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
1658c2ecf20Sopenharmony_ci				    int value)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
1688c2ecf20Sopenharmony_ci	u8 val;
1698c2ecf20Sopenharmony_ci	int ret;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
1728c2ecf20Sopenharmony_ci				MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
1758c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
1768c2ecf20Sopenharmony_ci	if (ret < 0) {
1778c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIOx val update failed: %d\n", ret);
1788c2ecf20Sopenharmony_ci		return ret;
1798c2ecf20Sopenharmony_ci	}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
1828c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_DIR_MASK,
1838c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_DIR_OUTPUT);
1848c2ecf20Sopenharmony_ci	if (ret < 0)
1858c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	return ret;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int max77620_gpio_set_debounce(struct max77620_gpio *mgpio,
1918c2ecf20Sopenharmony_ci				      unsigned int offset,
1928c2ecf20Sopenharmony_ci				      unsigned int debounce)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	u8 val;
1958c2ecf20Sopenharmony_ci	int ret;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	switch (debounce) {
1988c2ecf20Sopenharmony_ci	case 0:
1998c2ecf20Sopenharmony_ci		val = MAX77620_CNFG_GPIO_DBNC_None;
2008c2ecf20Sopenharmony_ci		break;
2018c2ecf20Sopenharmony_ci	case 1 ... 8000:
2028c2ecf20Sopenharmony_ci		val = MAX77620_CNFG_GPIO_DBNC_8ms;
2038c2ecf20Sopenharmony_ci		break;
2048c2ecf20Sopenharmony_ci	case 8001 ... 16000:
2058c2ecf20Sopenharmony_ci		val = MAX77620_CNFG_GPIO_DBNC_16ms;
2068c2ecf20Sopenharmony_ci		break;
2078c2ecf20Sopenharmony_ci	case 16001 ... 32000:
2088c2ecf20Sopenharmony_ci		val = MAX77620_CNFG_GPIO_DBNC_32ms;
2098c2ecf20Sopenharmony_ci		break;
2108c2ecf20Sopenharmony_ci	default:
2118c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "Illegal value %u\n", debounce);
2128c2ecf20Sopenharmony_ci		return -EINVAL;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
2168c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_DBNC_MASK, val);
2178c2ecf20Sopenharmony_ci	if (ret < 0)
2188c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIOx_DBNC update failed: %d\n", ret);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	return ret;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset,
2248c2ecf20Sopenharmony_ci			      int value)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
2278c2ecf20Sopenharmony_ci	u8 val;
2288c2ecf20Sopenharmony_ci	int ret;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
2318c2ecf20Sopenharmony_ci				MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
2348c2ecf20Sopenharmony_ci				 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
2358c2ecf20Sopenharmony_ci	if (ret < 0)
2368c2ecf20Sopenharmony_ci		dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret);
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
2408c2ecf20Sopenharmony_ci				    unsigned long config)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio = gpiochip_get_data(gc);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	switch (pinconf_to_config_param(config)) {
2458c2ecf20Sopenharmony_ci	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
2468c2ecf20Sopenharmony_ci		return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
2478c2ecf20Sopenharmony_ci					  MAX77620_CNFG_GPIO_DRV_MASK,
2488c2ecf20Sopenharmony_ci					  MAX77620_CNFG_GPIO_DRV_OPENDRAIN);
2498c2ecf20Sopenharmony_ci	case PIN_CONFIG_DRIVE_PUSH_PULL:
2508c2ecf20Sopenharmony_ci		return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
2518c2ecf20Sopenharmony_ci					  MAX77620_CNFG_GPIO_DRV_MASK,
2528c2ecf20Sopenharmony_ci					  MAX77620_CNFG_GPIO_DRV_PUSHPULL);
2538c2ecf20Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
2548c2ecf20Sopenharmony_ci		return max77620_gpio_set_debounce(mgpio, offset,
2558c2ecf20Sopenharmony_ci			pinconf_to_config_argument(config));
2568c2ecf20Sopenharmony_ci	default:
2578c2ecf20Sopenharmony_ci		break;
2588c2ecf20Sopenharmony_ci	}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	return -ENOTSUPP;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic int max77620_gpio_irq_init_hw(struct gpio_chip *gc)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct max77620_gpio *gpio = gpiochip_get_data(gc);
2668c2ecf20Sopenharmony_ci	unsigned int i;
2678c2ecf20Sopenharmony_ci	int err;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	/*
2708c2ecf20Sopenharmony_ci	 * GPIO interrupts may be left ON after bootloader, hence let's
2718c2ecf20Sopenharmony_ci	 * pre-initialize hardware to the expected state by disabling all
2728c2ecf20Sopenharmony_ci	 * the interrupts.
2738c2ecf20Sopenharmony_ci	 */
2748c2ecf20Sopenharmony_ci	for (i = 0; i < MAX77620_GPIO_NR; i++) {
2758c2ecf20Sopenharmony_ci		err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(i),
2768c2ecf20Sopenharmony_ci					 MAX77620_CNFG_GPIO_INT_MASK, 0);
2778c2ecf20Sopenharmony_ci		if (err < 0) {
2788c2ecf20Sopenharmony_ci			dev_err(gpio->dev,
2798c2ecf20Sopenharmony_ci				"failed to disable interrupt: %d\n", err);
2808c2ecf20Sopenharmony_ci			return err;
2818c2ecf20Sopenharmony_ci		}
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	return 0;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic int max77620_gpio_probe(struct platform_device *pdev)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	struct max77620_chip *chip =  dev_get_drvdata(pdev->dev.parent);
2908c2ecf20Sopenharmony_ci	struct max77620_gpio *mgpio;
2918c2ecf20Sopenharmony_ci	struct gpio_irq_chip *girq;
2928c2ecf20Sopenharmony_ci	unsigned int gpio_irq;
2938c2ecf20Sopenharmony_ci	int ret;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	ret = platform_get_irq(pdev, 0);
2968c2ecf20Sopenharmony_ci	if (ret < 0)
2978c2ecf20Sopenharmony_ci		return ret;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	gpio_irq = ret;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
3028c2ecf20Sopenharmony_ci	if (!mgpio)
3038c2ecf20Sopenharmony_ci		return -ENOMEM;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	mutex_init(&mgpio->buslock);
3068c2ecf20Sopenharmony_ci	mgpio->rmap = chip->rmap;
3078c2ecf20Sopenharmony_ci	mgpio->dev = &pdev->dev;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	mgpio->gpio_chip.label = pdev->name;
3108c2ecf20Sopenharmony_ci	mgpio->gpio_chip.parent = pdev->dev.parent;
3118c2ecf20Sopenharmony_ci	mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
3128c2ecf20Sopenharmony_ci	mgpio->gpio_chip.get = max77620_gpio_get;
3138c2ecf20Sopenharmony_ci	mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
3148c2ecf20Sopenharmony_ci	mgpio->gpio_chip.set = max77620_gpio_set;
3158c2ecf20Sopenharmony_ci	mgpio->gpio_chip.set_config = max77620_gpio_set_config;
3168c2ecf20Sopenharmony_ci	mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
3178c2ecf20Sopenharmony_ci	mgpio->gpio_chip.can_sleep = 1;
3188c2ecf20Sopenharmony_ci	mgpio->gpio_chip.base = -1;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	girq = &mgpio->gpio_chip.irq;
3218c2ecf20Sopenharmony_ci	girq->chip = &max77620_gpio_irqchip;
3228c2ecf20Sopenharmony_ci	/* This will let us handle the parent IRQ in the driver */
3238c2ecf20Sopenharmony_ci	girq->parent_handler = NULL;
3248c2ecf20Sopenharmony_ci	girq->num_parents = 0;
3258c2ecf20Sopenharmony_ci	girq->parents = NULL;
3268c2ecf20Sopenharmony_ci	girq->default_type = IRQ_TYPE_NONE;
3278c2ecf20Sopenharmony_ci	girq->handler = handle_edge_irq;
3288c2ecf20Sopenharmony_ci	girq->init_hw = max77620_gpio_irq_init_hw,
3298c2ecf20Sopenharmony_ci	girq->threaded = true;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, mgpio);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	ret = devm_gpiochip_add_data(&pdev->dev, &mgpio->gpio_chip, mgpio);
3348c2ecf20Sopenharmony_ci	if (ret < 0) {
3358c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "gpio_init: Failed to add max77620_gpio\n");
3368c2ecf20Sopenharmony_ci		return ret;
3378c2ecf20Sopenharmony_ci	}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(&pdev->dev, gpio_irq, NULL,
3408c2ecf20Sopenharmony_ci					max77620_gpio_irqhandler, IRQF_ONESHOT,
3418c2ecf20Sopenharmony_ci					"max77620-gpio", mgpio);
3428c2ecf20Sopenharmony_ci	if (ret < 0) {
3438c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
3448c2ecf20Sopenharmony_ci		return ret;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return 0;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic const struct platform_device_id max77620_gpio_devtype[] = {
3518c2ecf20Sopenharmony_ci	{ .name = "max77620-gpio", },
3528c2ecf20Sopenharmony_ci	{ .name = "max20024-gpio", },
3538c2ecf20Sopenharmony_ci	{},
3548c2ecf20Sopenharmony_ci};
3558c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic struct platform_driver max77620_gpio_driver = {
3588c2ecf20Sopenharmony_ci	.driver.name	= "max77620-gpio",
3598c2ecf20Sopenharmony_ci	.probe		= max77620_gpio_probe,
3608c2ecf20Sopenharmony_ci	.id_table	= max77620_gpio_devtype,
3618c2ecf20Sopenharmony_ci};
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cimodule_platform_driver(max77620_gpio_driver);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GPIO interface for MAX77620 and MAX20024 PMIC");
3668c2ecf20Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
3678c2ecf20Sopenharmony_ciMODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
3688c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:max77620-gpio");
3698c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
370