18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// max8997-irq.c - Interrupt controller support for MAX8997
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright (C) 2011 Samsung Electronics Co.Ltd
68c2ecf20Sopenharmony_ci// MyungJoo Ham <myungjoo.ham@samsung.com>
78c2ecf20Sopenharmony_ci//
88c2ecf20Sopenharmony_ci// This driver is based on max8998-irq.c
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/err.h>
118c2ecf20Sopenharmony_ci#include <linux/irq.h>
128c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
138c2ecf20Sopenharmony_ci#include <linux/mfd/max8997.h>
148c2ecf20Sopenharmony_ci#include <linux/mfd/max8997-private.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic const u8 max8997_mask_reg[] = {
178c2ecf20Sopenharmony_ci	[PMIC_INT1] = MAX8997_REG_INT1MSK,
188c2ecf20Sopenharmony_ci	[PMIC_INT2] = MAX8997_REG_INT2MSK,
198c2ecf20Sopenharmony_ci	[PMIC_INT3] = MAX8997_REG_INT3MSK,
208c2ecf20Sopenharmony_ci	[PMIC_INT4] = MAX8997_REG_INT4MSK,
218c2ecf20Sopenharmony_ci	[FUEL_GAUGE] = MAX8997_REG_INVALID,
228c2ecf20Sopenharmony_ci	[MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
238c2ecf20Sopenharmony_ci	[MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
248c2ecf20Sopenharmony_ci	[MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
258c2ecf20Sopenharmony_ci	[GPIO_LOW] = MAX8997_REG_INVALID,
268c2ecf20Sopenharmony_ci	[GPIO_HI] = MAX8997_REG_INVALID,
278c2ecf20Sopenharmony_ci	[FLASH_STATUS] = MAX8997_REG_INVALID,
288c2ecf20Sopenharmony_ci};
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic struct i2c_client *get_i2c(struct max8997_dev *max8997,
318c2ecf20Sopenharmony_ci				enum max8997_irq_source src)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	switch (src) {
348c2ecf20Sopenharmony_ci	case PMIC_INT1 ... PMIC_INT4:
358c2ecf20Sopenharmony_ci		return max8997->i2c;
368c2ecf20Sopenharmony_ci	case FUEL_GAUGE:
378c2ecf20Sopenharmony_ci		return NULL;
388c2ecf20Sopenharmony_ci	case MUIC_INT1 ... MUIC_INT3:
398c2ecf20Sopenharmony_ci		return max8997->muic;
408c2ecf20Sopenharmony_ci	case GPIO_LOW ... GPIO_HI:
418c2ecf20Sopenharmony_ci		return max8997->i2c;
428c2ecf20Sopenharmony_ci	case FLASH_STATUS:
438c2ecf20Sopenharmony_ci		return max8997->i2c;
448c2ecf20Sopenharmony_ci	default:
458c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct max8997_irq_data {
508c2ecf20Sopenharmony_ci	int mask;
518c2ecf20Sopenharmony_ci	enum max8997_irq_source group;
528c2ecf20Sopenharmony_ci};
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define DECLARE_IRQ(idx, _group, _mask)		\
558c2ecf20Sopenharmony_ci	[(idx)] = { .group = (_group), .mask = (_mask) }
568c2ecf20Sopenharmony_cistatic const struct max8997_irq_data max8997_irqs[] = {
578c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR,	PMIC_INT1, 1 << 0),
588c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF,	PMIC_INT1, 1 << 1),
598c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC,	PMIC_INT1, 1 << 3),
608c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR,	PMIC_INT1, 1 << 4),
618c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF,	PMIC_INT1, 1 << 5),
628c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2,	PMIC_INT1, 1 << 6),
638c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1,	PMIC_INT1, 1 << 7),
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_JIGR,	PMIC_INT2, 1 << 0),
668c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_JIGF,	PMIC_INT2, 1 << 1),
678c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_MR,		PMIC_INT2, 1 << 2),
688c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK,	PMIC_INT2, 1 << 3),
698c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK,	PMIC_INT2, 1 << 4),
708c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK,	PMIC_INT2, 1 << 5),
718c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK,	PMIC_INT2, 1 << 6),
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS,	PMIC_INT3, 1 << 0),
748c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM,	PMIC_INT3, 1 << 1),
758c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP,	PMIC_INT3, 1 << 2),
768c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR,	PMIC_INT3, 1 << 3),
778c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF,	PMIC_INT3, 1 << 5),
788c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD,	PMIC_INT3, 1 << 7),
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S,	PMIC_INT4, 1 << 0),
818c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1,	PMIC_INT4, 1 << 1),
828c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2,	PMIC_INT4, 1 << 2),
838c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT,	PMIC_INT4, 1 << 3),
848c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S,	PMIC_INT4, 1 << 4),
858c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_PMICIRQ_WTSR,	PMIC_INT4, 1 << 5),
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_ADCError,	MUIC_INT1, 1 << 2),
888c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow,	MUIC_INT1, 1 << 1),
898c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_ADC,	MUIC_INT1, 1 << 0),
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt,	MUIC_INT2, 1 << 4),
928c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_DBChg,	MUIC_INT2, 1 << 3),
938c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr,	MUIC_INT2, 1 << 2),
948c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun,	MUIC_INT2, 1 << 1),
958c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp,	MUIC_INT2, 1 << 0),
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	DECLARE_IRQ(MAX8997_MUICIRQ_OVP,	MUIC_INT3, 1 << 2),
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic void max8997_irq_lock(struct irq_data *data)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	mutex_lock(&max8997->irqlock);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void max8997_irq_sync_unlock(struct irq_data *data)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
1108c2ecf20Sopenharmony_ci	int i;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
1138c2ecf20Sopenharmony_ci		u8 mask_reg = max8997_mask_reg[i];
1148c2ecf20Sopenharmony_ci		struct i2c_client *i2c = get_i2c(max8997, i);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci		if (mask_reg == MAX8997_REG_INVALID ||
1178c2ecf20Sopenharmony_ci				IS_ERR_OR_NULL(i2c))
1188c2ecf20Sopenharmony_ci			continue;
1198c2ecf20Sopenharmony_ci		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci		max8997_write_reg(i2c, max8997_mask_reg[i],
1228c2ecf20Sopenharmony_ci				max8997->irq_masks_cur[i]);
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	mutex_unlock(&max8997->irqlock);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciinline static const struct max8997_irq_data *
1298c2ecf20Sopenharmony_ciirq_to_max8997_irq(struct max8997_dev *max8997, struct irq_data *data)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	return &max8997_irqs[data->hwirq];
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic void max8997_irq_mask(struct irq_data *data)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
1378c2ecf20Sopenharmony_ci	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
1388c2ecf20Sopenharmony_ci								     data);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic void max8997_irq_unmask(struct irq_data *data)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
1468c2ecf20Sopenharmony_ci	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
1478c2ecf20Sopenharmony_ci								     data);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic struct irq_chip max8997_irq_chip = {
1538c2ecf20Sopenharmony_ci	.name			= "max8997",
1548c2ecf20Sopenharmony_ci	.irq_bus_lock		= max8997_irq_lock,
1558c2ecf20Sopenharmony_ci	.irq_bus_sync_unlock	= max8997_irq_sync_unlock,
1568c2ecf20Sopenharmony_ci	.irq_mask		= max8997_irq_mask,
1578c2ecf20Sopenharmony_ci	.irq_unmask		= max8997_irq_unmask,
1588c2ecf20Sopenharmony_ci};
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci#define MAX8997_IRQSRC_PMIC		(1 << 1)
1618c2ecf20Sopenharmony_ci#define MAX8997_IRQSRC_FUELGAUGE	(1 << 2)
1628c2ecf20Sopenharmony_ci#define MAX8997_IRQSRC_MUIC		(1 << 3)
1638c2ecf20Sopenharmony_ci#define MAX8997_IRQSRC_GPIO		(1 << 4)
1648c2ecf20Sopenharmony_ci#define MAX8997_IRQSRC_FLASH		(1 << 5)
1658c2ecf20Sopenharmony_cistatic irqreturn_t max8997_irq_thread(int irq, void *data)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = data;
1688c2ecf20Sopenharmony_ci	u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
1698c2ecf20Sopenharmony_ci	u8 irq_src;
1708c2ecf20Sopenharmony_ci	int ret;
1718c2ecf20Sopenharmony_ci	int i, cur_irq;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
1748c2ecf20Sopenharmony_ci	if (ret < 0) {
1758c2ecf20Sopenharmony_ci		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
1768c2ecf20Sopenharmony_ci				ret);
1778c2ecf20Sopenharmony_ci		return IRQ_NONE;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	if (irq_src & MAX8997_IRQSRC_PMIC) {
1818c2ecf20Sopenharmony_ci		/* PMIC INT1 ~ INT4 */
1828c2ecf20Sopenharmony_ci		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
1838c2ecf20Sopenharmony_ci				&irq_reg[PMIC_INT1]);
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
1868c2ecf20Sopenharmony_ci		/*
1878c2ecf20Sopenharmony_ci		 * TODO: FUEL GAUGE
1888c2ecf20Sopenharmony_ci		 *
1898c2ecf20Sopenharmony_ci		 * This is to be supported by Max17042 driver. When
1908c2ecf20Sopenharmony_ci		 * an interrupt incurs here, it should be relayed to a
1918c2ecf20Sopenharmony_ci		 * Max17042 device that is connected (probably by
1928c2ecf20Sopenharmony_ci		 * platform-data). However, we do not have interrupt
1938c2ecf20Sopenharmony_ci		 * handling in Max17042 driver currently. The Max17042 IRQ
1948c2ecf20Sopenharmony_ci		 * driver should be ready to be used as a stand-alone device and
1958c2ecf20Sopenharmony_ci		 * a Max8997-dependent device. Because it is not ready in
1968c2ecf20Sopenharmony_ci		 * Max17042-side and it is not too critical in operating
1978c2ecf20Sopenharmony_ci		 * Max8997, we do not implement this in initial releases.
1988c2ecf20Sopenharmony_ci		 */
1998c2ecf20Sopenharmony_ci		irq_reg[FUEL_GAUGE] = 0;
2008c2ecf20Sopenharmony_ci	}
2018c2ecf20Sopenharmony_ci	if (irq_src & MAX8997_IRQSRC_MUIC) {
2028c2ecf20Sopenharmony_ci		/* MUIC INT1 ~ INT3 */
2038c2ecf20Sopenharmony_ci		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
2048c2ecf20Sopenharmony_ci				&irq_reg[MUIC_INT1]);
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci	if (irq_src & MAX8997_IRQSRC_GPIO) {
2078c2ecf20Sopenharmony_ci		/* GPIO Interrupt */
2088c2ecf20Sopenharmony_ci		u8 gpio_info[MAX8997_NUM_GPIO];
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		irq_reg[GPIO_LOW] = 0;
2118c2ecf20Sopenharmony_ci		irq_reg[GPIO_HI] = 0;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
2148c2ecf20Sopenharmony_ci				MAX8997_NUM_GPIO, gpio_info);
2158c2ecf20Sopenharmony_ci		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
2168c2ecf20Sopenharmony_ci			bool interrupt = false;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci			switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
2198c2ecf20Sopenharmony_ci			case MAX8997_GPIO_INT_BOTH:
2208c2ecf20Sopenharmony_ci				if (max8997->gpio_status[i] != gpio_info[i])
2218c2ecf20Sopenharmony_ci					interrupt = true;
2228c2ecf20Sopenharmony_ci				break;
2238c2ecf20Sopenharmony_ci			case MAX8997_GPIO_INT_RISE:
2248c2ecf20Sopenharmony_ci				if ((max8997->gpio_status[i] != gpio_info[i]) &&
2258c2ecf20Sopenharmony_ci				    (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
2268c2ecf20Sopenharmony_ci					interrupt = true;
2278c2ecf20Sopenharmony_ci				break;
2288c2ecf20Sopenharmony_ci			case MAX8997_GPIO_INT_FALL:
2298c2ecf20Sopenharmony_ci				if ((max8997->gpio_status[i] != gpio_info[i]) &&
2308c2ecf20Sopenharmony_ci				    !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
2318c2ecf20Sopenharmony_ci					interrupt = true;
2328c2ecf20Sopenharmony_ci				break;
2338c2ecf20Sopenharmony_ci			default:
2348c2ecf20Sopenharmony_ci				break;
2358c2ecf20Sopenharmony_ci			}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci			if (interrupt) {
2388c2ecf20Sopenharmony_ci				if (i < 8)
2398c2ecf20Sopenharmony_ci					irq_reg[GPIO_LOW] |= (1 << i);
2408c2ecf20Sopenharmony_ci				else
2418c2ecf20Sopenharmony_ci					irq_reg[GPIO_HI] |= (1 << (i - 8));
2428c2ecf20Sopenharmony_ci			}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci		}
2458c2ecf20Sopenharmony_ci	}
2468c2ecf20Sopenharmony_ci	if (irq_src & MAX8997_IRQSRC_FLASH) {
2478c2ecf20Sopenharmony_ci		/* Flash Status Interrupt */
2488c2ecf20Sopenharmony_ci		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
2498c2ecf20Sopenharmony_ci				&irq_reg[FLASH_STATUS]);
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	/* Apply masking */
2538c2ecf20Sopenharmony_ci	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
2548c2ecf20Sopenharmony_ci		irq_reg[i] &= ~max8997->irq_masks_cur[i];
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/* Report */
2578c2ecf20Sopenharmony_ci	for (i = 0; i < MAX8997_IRQ_NR; i++) {
2588c2ecf20Sopenharmony_ci		if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
2598c2ecf20Sopenharmony_ci			cur_irq = irq_find_mapping(max8997->irq_domain, i);
2608c2ecf20Sopenharmony_ci			if (cur_irq)
2618c2ecf20Sopenharmony_ci				handle_nested_irq(cur_irq);
2628c2ecf20Sopenharmony_ci		}
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ciint max8997_irq_resume(struct max8997_dev *max8997)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	if (max8997->irq && max8997->irq_domain)
2718c2ecf20Sopenharmony_ci		max8997_irq_thread(0, max8997);
2728c2ecf20Sopenharmony_ci	return 0;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
2768c2ecf20Sopenharmony_ci					irq_hw_number_t hw)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct max8997_dev *max8997 = d->host_data;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	irq_set_chip_data(irq, max8997);
2818c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
2828c2ecf20Sopenharmony_ci	irq_set_nested_thread(irq, 1);
2838c2ecf20Sopenharmony_ci	irq_set_noprobe(irq);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	return 0;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic const struct irq_domain_ops max8997_irq_domain_ops = {
2898c2ecf20Sopenharmony_ci	.map = max8997_irq_domain_map,
2908c2ecf20Sopenharmony_ci};
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ciint max8997_irq_init(struct max8997_dev *max8997)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	struct irq_domain *domain;
2958c2ecf20Sopenharmony_ci	int i;
2968c2ecf20Sopenharmony_ci	int ret;
2978c2ecf20Sopenharmony_ci	u8 val;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (!max8997->irq) {
3008c2ecf20Sopenharmony_ci		dev_warn(max8997->dev, "No interrupt specified.\n");
3018c2ecf20Sopenharmony_ci		return 0;
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	mutex_init(&max8997->irqlock);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* Mask individual interrupt sources */
3078c2ecf20Sopenharmony_ci	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
3088c2ecf20Sopenharmony_ci		struct i2c_client *i2c;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		max8997->irq_masks_cur[i] = 0xff;
3118c2ecf20Sopenharmony_ci		max8997->irq_masks_cache[i] = 0xff;
3128c2ecf20Sopenharmony_ci		i2c = get_i2c(max8997, i);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci		if (IS_ERR_OR_NULL(i2c))
3158c2ecf20Sopenharmony_ci			continue;
3168c2ecf20Sopenharmony_ci		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
3178c2ecf20Sopenharmony_ci			continue;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
3238c2ecf20Sopenharmony_ci		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
3248c2ecf20Sopenharmony_ci						MAX8997_REG_GPIOCNTL1 + i,
3258c2ecf20Sopenharmony_ci						&val)
3268c2ecf20Sopenharmony_ci					& MAX8997_GPIO_DATA_MASK) ?
3278c2ecf20Sopenharmony_ci					true : false;
3288c2ecf20Sopenharmony_ci	}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
3318c2ecf20Sopenharmony_ci					&max8997_irq_domain_ops, max8997);
3328c2ecf20Sopenharmony_ci	if (!domain) {
3338c2ecf20Sopenharmony_ci		dev_err(max8997->dev, "could not create irq domain\n");
3348c2ecf20Sopenharmony_ci		return -ENODEV;
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci	max8997->irq_domain = domain;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
3398c2ecf20Sopenharmony_ci			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
3408c2ecf20Sopenharmony_ci			"max8997-irq", max8997);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (ret) {
3438c2ecf20Sopenharmony_ci		dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
3448c2ecf20Sopenharmony_ci				max8997->irq, ret);
3458c2ecf20Sopenharmony_ci		return ret;
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	if (!max8997->ono)
3498c2ecf20Sopenharmony_ci		return 0;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
3528c2ecf20Sopenharmony_ci			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
3538c2ecf20Sopenharmony_ci			IRQF_ONESHOT, "max8997-ono", max8997);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	if (ret)
3568c2ecf20Sopenharmony_ci		dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
3578c2ecf20Sopenharmony_ci				max8997->ono, ret);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	return 0;
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_civoid max8997_irq_exit(struct max8997_dev *max8997)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	if (max8997->ono)
3658c2ecf20Sopenharmony_ci		free_irq(max8997->ono, max8997);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	if (max8997->irq)
3688c2ecf20Sopenharmony_ci		free_irq(max8997->irq, max8997);
3698c2ecf20Sopenharmony_ci}
370