18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2018 Spreadtrum Communications Inc.
48c2ecf20Sopenharmony_ci * Copyright (C) 2018 Linaro Ltd.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
88c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/of_device.h>
128c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
138c2ecf20Sopenharmony_ci#include <linux/regmap.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* EIC registers definition */
168c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_DATA		0x0
178c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_DMSK		0x4
188c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_IEV		0x14
198c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_IE		0x18
208c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_RIS		0x1c
218c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_MIS		0x20
228c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_IC		0x24
238c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_TRIG		0x28
248c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_CTRL0		0x40
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * The PMIC EIC controller only has one bank, and each bank now can contain
288c2ecf20Sopenharmony_ci * 16 EICs.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_PER_BANK_NR	16
318c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_NR		SPRD_PMIC_EIC_PER_BANK_NR
328c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_DATA_MASK		GENMASK(15, 0)
338c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_BIT(x)		((x) & (SPRD_PMIC_EIC_PER_BANK_NR - 1))
348c2ecf20Sopenharmony_ci#define SPRD_PMIC_EIC_DBNC_MASK		GENMASK(11, 0)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * These registers are modified under the irq bus lock and cached to avoid
388c2ecf20Sopenharmony_ci * unnecessary writes in bus_sync_unlock.
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_cienum {
418c2ecf20Sopenharmony_ci	REG_IEV,
428c2ecf20Sopenharmony_ci	REG_IE,
438c2ecf20Sopenharmony_ci	REG_TRIG,
448c2ecf20Sopenharmony_ci	CACHE_NR_REGS
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/**
488c2ecf20Sopenharmony_ci * struct sprd_pmic_eic - PMIC EIC controller
498c2ecf20Sopenharmony_ci * @chip: the gpio_chip structure.
508c2ecf20Sopenharmony_ci * @intc: the irq_chip structure.
518c2ecf20Sopenharmony_ci * @map:  the regmap from the parent device.
528c2ecf20Sopenharmony_ci * @offset: the EIC controller's offset address of the PMIC.
538c2ecf20Sopenharmony_ci * @reg: the array to cache the EIC registers.
548c2ecf20Sopenharmony_ci * @buslock: for bus lock/sync and unlock.
558c2ecf20Sopenharmony_ci * @irq: the interrupt number of the PMIC EIC conteroller.
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_cistruct sprd_pmic_eic {
588c2ecf20Sopenharmony_ci	struct gpio_chip chip;
598c2ecf20Sopenharmony_ci	struct irq_chip intc;
608c2ecf20Sopenharmony_ci	struct regmap *map;
618c2ecf20Sopenharmony_ci	u32 offset;
628c2ecf20Sopenharmony_ci	u8 reg[CACHE_NR_REGS];
638c2ecf20Sopenharmony_ci	struct mutex buslock;
648c2ecf20Sopenharmony_ci	int irq;
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_update(struct gpio_chip *chip, unsigned int offset,
688c2ecf20Sopenharmony_ci				 u16 reg, unsigned int val)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
718c2ecf20Sopenharmony_ci	u32 shift = SPRD_PMIC_EIC_BIT(offset);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	regmap_update_bits(pmic_eic->map, pmic_eic->offset + reg,
748c2ecf20Sopenharmony_ci			   BIT(shift), val << shift);
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_read(struct gpio_chip *chip, unsigned int offset,
788c2ecf20Sopenharmony_ci			      u16 reg)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
818c2ecf20Sopenharmony_ci	u32 value;
828c2ecf20Sopenharmony_ci	int ret;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value);
858c2ecf20Sopenharmony_ci	if (ret)
868c2ecf20Sopenharmony_ci		return ret;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	return !!(value & BIT(SPRD_PMIC_EIC_BIT(offset)));
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_request(struct gpio_chip *chip, unsigned int offset)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 1);
948c2ecf20Sopenharmony_ci	return 0;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_free(struct gpio_chip *chip, unsigned int offset)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 0);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_get(struct gpio_chip *chip, unsigned int offset)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	return sprd_pmic_eic_read(chip, offset, SPRD_PMIC_EIC_DATA);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_direction_input(struct gpio_chip *chip,
1088c2ecf20Sopenharmony_ci					 unsigned int offset)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	/* EICs are always input, nothing need to do here. */
1118c2ecf20Sopenharmony_ci	return 0;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_set(struct gpio_chip *chip, unsigned int offset,
1158c2ecf20Sopenharmony_ci			      int value)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	/* EICs are always input, nothing need to do here. */
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_set_debounce(struct gpio_chip *chip,
1218c2ecf20Sopenharmony_ci				      unsigned int offset,
1228c2ecf20Sopenharmony_ci				      unsigned int debounce)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
1258c2ecf20Sopenharmony_ci	u32 reg, value;
1268c2ecf20Sopenharmony_ci	int ret;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	reg = SPRD_PMIC_EIC_CTRL0 + SPRD_PMIC_EIC_BIT(offset) * 0x4;
1298c2ecf20Sopenharmony_ci	ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value);
1308c2ecf20Sopenharmony_ci	if (ret)
1318c2ecf20Sopenharmony_ci		return ret;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	value &= ~SPRD_PMIC_EIC_DBNC_MASK;
1348c2ecf20Sopenharmony_ci	value |= (debounce / 1000) & SPRD_PMIC_EIC_DBNC_MASK;
1358c2ecf20Sopenharmony_ci	return regmap_write(pmic_eic->map, pmic_eic->offset + reg, value);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_set_config(struct gpio_chip *chip, unsigned int offset,
1398c2ecf20Sopenharmony_ci				    unsigned long config)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	unsigned long param = pinconf_to_config_param(config);
1428c2ecf20Sopenharmony_ci	u32 arg = pinconf_to_config_argument(config);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (param == PIN_CONFIG_INPUT_DEBOUNCE)
1458c2ecf20Sopenharmony_ci		return sprd_pmic_eic_set_debounce(chip, offset, arg);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	return -ENOTSUPP;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_irq_mask(struct irq_data *data)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
1538c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	pmic_eic->reg[REG_IE] = 0;
1568c2ecf20Sopenharmony_ci	pmic_eic->reg[REG_TRIG] = 0;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_irq_unmask(struct irq_data *data)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
1628c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	pmic_eic->reg[REG_IE] = 1;
1658c2ecf20Sopenharmony_ci	pmic_eic->reg[REG_TRIG] = 1;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_irq_set_type(struct irq_data *data,
1698c2ecf20Sopenharmony_ci				      unsigned int flow_type)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
1728c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	switch (flow_type) {
1758c2ecf20Sopenharmony_ci	case IRQ_TYPE_LEVEL_HIGH:
1768c2ecf20Sopenharmony_ci		pmic_eic->reg[REG_IEV] = 1;
1778c2ecf20Sopenharmony_ci		break;
1788c2ecf20Sopenharmony_ci	case IRQ_TYPE_LEVEL_LOW:
1798c2ecf20Sopenharmony_ci		pmic_eic->reg[REG_IEV] = 0;
1808c2ecf20Sopenharmony_ci		break;
1818c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_RISING:
1828c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_FALLING:
1838c2ecf20Sopenharmony_ci	case IRQ_TYPE_EDGE_BOTH:
1848c2ecf20Sopenharmony_ci		/*
1858c2ecf20Sopenharmony_ci		 * Will set the trigger level according to current EIC level
1868c2ecf20Sopenharmony_ci		 * in irq_bus_sync_unlock() interface, so here nothing to do.
1878c2ecf20Sopenharmony_ci		 */
1888c2ecf20Sopenharmony_ci		break;
1898c2ecf20Sopenharmony_ci	default:
1908c2ecf20Sopenharmony_ci		return -ENOTSUPP;
1918c2ecf20Sopenharmony_ci	}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	return 0;
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_bus_lock(struct irq_data *data)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
1998c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	mutex_lock(&pmic_eic->buslock);
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
2078c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
2088c2ecf20Sopenharmony_ci	u32 trigger = irqd_get_trigger_type(data);
2098c2ecf20Sopenharmony_ci	u32 offset = irqd_to_hwirq(data);
2108c2ecf20Sopenharmony_ci	int state;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	/* Set irq type */
2138c2ecf20Sopenharmony_ci	if (trigger & IRQ_TYPE_EDGE_BOTH) {
2148c2ecf20Sopenharmony_ci		state = sprd_pmic_eic_get(chip, offset);
2158c2ecf20Sopenharmony_ci		if (state)
2168c2ecf20Sopenharmony_ci			sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0);
2178c2ecf20Sopenharmony_ci		else
2188c2ecf20Sopenharmony_ci			sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1);
2198c2ecf20Sopenharmony_ci	} else {
2208c2ecf20Sopenharmony_ci		sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV,
2218c2ecf20Sopenharmony_ci				     pmic_eic->reg[REG_IEV]);
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Set irq unmask */
2258c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE,
2268c2ecf20Sopenharmony_ci			     pmic_eic->reg[REG_IE]);
2278c2ecf20Sopenharmony_ci	/* Generate trigger start pulse for debounce EIC */
2288c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG,
2298c2ecf20Sopenharmony_ci			     pmic_eic->reg[REG_TRIG]);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	mutex_unlock(&pmic_eic->buslock);
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic void sprd_pmic_eic_toggle_trigger(struct gpio_chip *chip,
2358c2ecf20Sopenharmony_ci					 unsigned int irq, unsigned int offset)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	u32 trigger = irq_get_trigger_type(irq);
2388c2ecf20Sopenharmony_ci	int state, post_state;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (!(trigger & IRQ_TYPE_EDGE_BOTH))
2418c2ecf20Sopenharmony_ci		return;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	state = sprd_pmic_eic_get(chip, offset);
2448c2ecf20Sopenharmony_ciretry:
2458c2ecf20Sopenharmony_ci	if (state)
2468c2ecf20Sopenharmony_ci		sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0);
2478c2ecf20Sopenharmony_ci	else
2488c2ecf20Sopenharmony_ci		sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	post_state = sprd_pmic_eic_get(chip, offset);
2518c2ecf20Sopenharmony_ci	if (state != post_state) {
2528c2ecf20Sopenharmony_ci		dev_warn(chip->parent, "PMIC EIC level was changed.\n");
2538c2ecf20Sopenharmony_ci		state = post_state;
2548c2ecf20Sopenharmony_ci		goto retry;
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* Set irq unmask */
2588c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE, 1);
2598c2ecf20Sopenharmony_ci	/* Generate trigger start pulse for debounce EIC */
2608c2ecf20Sopenharmony_ci	sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG, 1);
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic = data;
2668c2ecf20Sopenharmony_ci	struct gpio_chip *chip = &pmic_eic->chip;
2678c2ecf20Sopenharmony_ci	unsigned long status;
2688c2ecf20Sopenharmony_ci	u32 n, girq, val;
2698c2ecf20Sopenharmony_ci	int ret;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	ret = regmap_read(pmic_eic->map, pmic_eic->offset + SPRD_PMIC_EIC_MIS,
2728c2ecf20Sopenharmony_ci			  &val);
2738c2ecf20Sopenharmony_ci	if (ret)
2748c2ecf20Sopenharmony_ci		return IRQ_RETVAL(ret);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	status = val & SPRD_PMIC_EIC_DATA_MASK;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	for_each_set_bit(n, &status, chip->ngpio) {
2798c2ecf20Sopenharmony_ci		/* Clear the interrupt */
2808c2ecf20Sopenharmony_ci		sprd_pmic_eic_update(chip, n, SPRD_PMIC_EIC_IC, 1);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci		girq = irq_find_mapping(chip->irq.domain, n);
2838c2ecf20Sopenharmony_ci		handle_nested_irq(girq);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci		/*
2868c2ecf20Sopenharmony_ci		 * The PMIC EIC can only support level trigger, so we can
2878c2ecf20Sopenharmony_ci		 * toggle the level trigger to emulate the edge trigger.
2888c2ecf20Sopenharmony_ci		 */
2898c2ecf20Sopenharmony_ci		sprd_pmic_eic_toggle_trigger(chip, girq, n);
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic int sprd_pmic_eic_probe(struct platform_device *pdev)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct gpio_irq_chip *irq;
2988c2ecf20Sopenharmony_ci	struct sprd_pmic_eic *pmic_eic;
2998c2ecf20Sopenharmony_ci	int ret;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	pmic_eic = devm_kzalloc(&pdev->dev, sizeof(*pmic_eic), GFP_KERNEL);
3028c2ecf20Sopenharmony_ci	if (!pmic_eic)
3038c2ecf20Sopenharmony_ci		return -ENOMEM;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	mutex_init(&pmic_eic->buslock);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	pmic_eic->irq = platform_get_irq(pdev, 0);
3088c2ecf20Sopenharmony_ci	if (pmic_eic->irq < 0)
3098c2ecf20Sopenharmony_ci		return pmic_eic->irq;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL);
3128c2ecf20Sopenharmony_ci	if (!pmic_eic->map)
3138c2ecf20Sopenharmony_ci		return -ENODEV;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	ret = of_property_read_u32(pdev->dev.of_node, "reg", &pmic_eic->offset);
3168c2ecf20Sopenharmony_ci	if (ret) {
3178c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to get PMIC EIC base address.\n");
3188c2ecf20Sopenharmony_ci		return ret;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(&pdev->dev, pmic_eic->irq, NULL,
3228c2ecf20Sopenharmony_ci					sprd_pmic_eic_irq_handler,
3238c2ecf20Sopenharmony_ci					IRQF_ONESHOT | IRQF_NO_SUSPEND,
3248c2ecf20Sopenharmony_ci					dev_name(&pdev->dev), pmic_eic);
3258c2ecf20Sopenharmony_ci	if (ret) {
3268c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to request PMIC EIC IRQ.\n");
3278c2ecf20Sopenharmony_ci		return ret;
3288c2ecf20Sopenharmony_ci	}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	pmic_eic->chip.label = dev_name(&pdev->dev);
3318c2ecf20Sopenharmony_ci	pmic_eic->chip.ngpio = SPRD_PMIC_EIC_NR;
3328c2ecf20Sopenharmony_ci	pmic_eic->chip.base = -1;
3338c2ecf20Sopenharmony_ci	pmic_eic->chip.parent = &pdev->dev;
3348c2ecf20Sopenharmony_ci	pmic_eic->chip.of_node = pdev->dev.of_node;
3358c2ecf20Sopenharmony_ci	pmic_eic->chip.direction_input = sprd_pmic_eic_direction_input;
3368c2ecf20Sopenharmony_ci	pmic_eic->chip.request = sprd_pmic_eic_request;
3378c2ecf20Sopenharmony_ci	pmic_eic->chip.free = sprd_pmic_eic_free;
3388c2ecf20Sopenharmony_ci	pmic_eic->chip.set_config = sprd_pmic_eic_set_config;
3398c2ecf20Sopenharmony_ci	pmic_eic->chip.set = sprd_pmic_eic_set;
3408c2ecf20Sopenharmony_ci	pmic_eic->chip.get = sprd_pmic_eic_get;
3418c2ecf20Sopenharmony_ci	pmic_eic->chip.can_sleep = true;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	pmic_eic->intc.name = dev_name(&pdev->dev);
3448c2ecf20Sopenharmony_ci	pmic_eic->intc.irq_mask = sprd_pmic_eic_irq_mask;
3458c2ecf20Sopenharmony_ci	pmic_eic->intc.irq_unmask = sprd_pmic_eic_irq_unmask;
3468c2ecf20Sopenharmony_ci	pmic_eic->intc.irq_set_type = sprd_pmic_eic_irq_set_type;
3478c2ecf20Sopenharmony_ci	pmic_eic->intc.irq_bus_lock = sprd_pmic_eic_bus_lock;
3488c2ecf20Sopenharmony_ci	pmic_eic->intc.irq_bus_sync_unlock = sprd_pmic_eic_bus_sync_unlock;
3498c2ecf20Sopenharmony_ci	pmic_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	irq = &pmic_eic->chip.irq;
3528c2ecf20Sopenharmony_ci	irq->chip = &pmic_eic->intc;
3538c2ecf20Sopenharmony_ci	irq->threaded = true;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	ret = devm_gpiochip_add_data(&pdev->dev, &pmic_eic->chip, pmic_eic);
3568c2ecf20Sopenharmony_ci	if (ret < 0) {
3578c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret);
3588c2ecf20Sopenharmony_ci		return ret;
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, pmic_eic);
3628c2ecf20Sopenharmony_ci	return 0;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic const struct of_device_id sprd_pmic_eic_of_match[] = {
3668c2ecf20Sopenharmony_ci	{ .compatible = "sprd,sc2731-eic", },
3678c2ecf20Sopenharmony_ci	{ /* end of list */ }
3688c2ecf20Sopenharmony_ci};
3698c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sprd_pmic_eic_of_match);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic struct platform_driver sprd_pmic_eic_driver = {
3728c2ecf20Sopenharmony_ci	.probe = sprd_pmic_eic_probe,
3738c2ecf20Sopenharmony_ci	.driver = {
3748c2ecf20Sopenharmony_ci		.name = "sprd-pmic-eic",
3758c2ecf20Sopenharmony_ci		.of_match_table	= sprd_pmic_eic_of_match,
3768c2ecf20Sopenharmony_ci	},
3778c2ecf20Sopenharmony_ci};
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cimodule_platform_driver(sprd_pmic_eic_driver);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Spreadtrum PMIC EIC driver");
3828c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
383