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