brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · abbdbf0 Raw
288 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * DA9052 interrupt support4 *5 * Author: Fabio Estevam <fabio.estevam@freescale.com>6 * Based on arizona-irq.c, which is:7 *8 * Copyright 2012 Wolfson Microelectronics plc9 *10 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>11 */12 13#include <linux/device.h>14#include <linux/delay.h>15#include <linux/input.h>16#include <linux/interrupt.h>17#include <linux/irq.h>18#include <linux/irqdomain.h>19#include <linux/slab.h>20#include <linux/module.h>21 22#include <linux/mfd/da9052/da9052.h>23#include <linux/mfd/da9052/reg.h>24 25#define DA9052_NUM_IRQ_REGS		426#define DA9052_IRQ_MASK_POS_1		0x0127#define DA9052_IRQ_MASK_POS_2		0x0228#define DA9052_IRQ_MASK_POS_3		0x0429#define DA9052_IRQ_MASK_POS_4		0x0830#define DA9052_IRQ_MASK_POS_5		0x1031#define DA9052_IRQ_MASK_POS_6		0x2032#define DA9052_IRQ_MASK_POS_7		0x4033#define DA9052_IRQ_MASK_POS_8		0x8034 35static const struct regmap_irq da9052_irqs[] = {36	[DA9052_IRQ_DCIN] = {37		.reg_offset = 0,38		.mask = DA9052_IRQ_MASK_POS_1,39	},40	[DA9052_IRQ_VBUS] = {41		.reg_offset = 0,42		.mask = DA9052_IRQ_MASK_POS_2,43	},44	[DA9052_IRQ_DCINREM] = {45		.reg_offset = 0,46		.mask = DA9052_IRQ_MASK_POS_3,47	},48	[DA9052_IRQ_VBUSREM] = {49		.reg_offset = 0,50		.mask = DA9052_IRQ_MASK_POS_4,51	},52	[DA9052_IRQ_VDDLOW] = {53		.reg_offset = 0,54		.mask = DA9052_IRQ_MASK_POS_5,55	},56	[DA9052_IRQ_ALARM] = {57		.reg_offset = 0,58		.mask = DA9052_IRQ_MASK_POS_6,59	},60	[DA9052_IRQ_SEQRDY] = {61		.reg_offset = 0,62		.mask = DA9052_IRQ_MASK_POS_7,63	},64	[DA9052_IRQ_COMP1V2] = {65		.reg_offset = 0,66		.mask = DA9052_IRQ_MASK_POS_8,67	},68	[DA9052_IRQ_NONKEY] = {69		.reg_offset = 1,70		.mask = DA9052_IRQ_MASK_POS_1,71	},72	[DA9052_IRQ_IDFLOAT] = {73		.reg_offset = 1,74		.mask = DA9052_IRQ_MASK_POS_2,75	},76	[DA9052_IRQ_IDGND] = {77		.reg_offset = 1,78		.mask = DA9052_IRQ_MASK_POS_3,79	},80	[DA9052_IRQ_CHGEND] = {81		.reg_offset = 1,82		.mask = DA9052_IRQ_MASK_POS_4,83	},84	[DA9052_IRQ_TBAT] = {85		.reg_offset = 1,86		.mask = DA9052_IRQ_MASK_POS_5,87	},88	[DA9052_IRQ_ADC_EOM] = {89		.reg_offset = 1,90		.mask = DA9052_IRQ_MASK_POS_6,91	},92	[DA9052_IRQ_PENDOWN] = {93		.reg_offset = 1,94		.mask = DA9052_IRQ_MASK_POS_7,95	},96	[DA9052_IRQ_TSIREADY] = {97		.reg_offset = 1,98		.mask = DA9052_IRQ_MASK_POS_8,99	},100	[DA9052_IRQ_GPI0] = {101		.reg_offset = 2,102		.mask = DA9052_IRQ_MASK_POS_1,103	},104	[DA9052_IRQ_GPI1] = {105		.reg_offset = 2,106		.mask = DA9052_IRQ_MASK_POS_2,107	},108	[DA9052_IRQ_GPI2] = {109		.reg_offset = 2,110		.mask = DA9052_IRQ_MASK_POS_3,111	},112	[DA9052_IRQ_GPI3] = {113		.reg_offset = 2,114		.mask = DA9052_IRQ_MASK_POS_4,115	},116	[DA9052_IRQ_GPI4] = {117		.reg_offset = 2,118		.mask = DA9052_IRQ_MASK_POS_5,119	},120	[DA9052_IRQ_GPI5] = {121		.reg_offset = 2,122		.mask = DA9052_IRQ_MASK_POS_6,123	},124	[DA9052_IRQ_GPI6] = {125		.reg_offset = 2,126		.mask = DA9052_IRQ_MASK_POS_7,127	},128	[DA9052_IRQ_GPI7] = {129		.reg_offset = 2,130		.mask = DA9052_IRQ_MASK_POS_8,131	},132	[DA9052_IRQ_GPI8] = {133		.reg_offset = 3,134		.mask = DA9052_IRQ_MASK_POS_1,135	},136	[DA9052_IRQ_GPI9] = {137		.reg_offset = 3,138		.mask = DA9052_IRQ_MASK_POS_2,139	},140	[DA9052_IRQ_GPI10] = {141		.reg_offset = 3,142		.mask = DA9052_IRQ_MASK_POS_3,143	},144	[DA9052_IRQ_GPI11] = {145		.reg_offset = 3,146		.mask = DA9052_IRQ_MASK_POS_4,147	},148	[DA9052_IRQ_GPI12] = {149		.reg_offset = 3,150		.mask = DA9052_IRQ_MASK_POS_5,151	},152	[DA9052_IRQ_GPI13] = {153		.reg_offset = 3,154		.mask = DA9052_IRQ_MASK_POS_6,155	},156	[DA9052_IRQ_GPI14] = {157		.reg_offset = 3,158		.mask = DA9052_IRQ_MASK_POS_7,159	},160	[DA9052_IRQ_GPI15] = {161		.reg_offset = 3,162		.mask = DA9052_IRQ_MASK_POS_8,163	},164};165 166static const struct regmap_irq_chip da9052_regmap_irq_chip = {167	.name = "da9052_irq",168	.status_base = DA9052_EVENT_A_REG,169	.mask_base = DA9052_IRQ_MASK_A_REG,170	.ack_base = DA9052_EVENT_A_REG,171	.num_regs = DA9052_NUM_IRQ_REGS,172	.irqs = da9052_irqs,173	.num_irqs = ARRAY_SIZE(da9052_irqs),174};175 176static int da9052_map_irq(struct da9052 *da9052, int irq)177{178	return regmap_irq_get_virq(da9052->irq_data, irq);179}180 181int da9052_enable_irq(struct da9052 *da9052, int irq)182{183	irq = da9052_map_irq(da9052, irq);184	if (irq < 0)185		return irq;186 187	enable_irq(irq);188 189	return 0;190}191EXPORT_SYMBOL_GPL(da9052_enable_irq);192 193int da9052_disable_irq(struct da9052 *da9052, int irq)194{195	irq = da9052_map_irq(da9052, irq);196	if (irq < 0)197		return irq;198 199	disable_irq(irq);200 201	return 0;202}203EXPORT_SYMBOL_GPL(da9052_disable_irq);204 205int da9052_disable_irq_nosync(struct da9052 *da9052, int irq)206{207	irq = da9052_map_irq(da9052, irq);208	if (irq < 0)209		return irq;210 211	disable_irq_nosync(irq);212 213	return 0;214}215EXPORT_SYMBOL_GPL(da9052_disable_irq_nosync);216 217int da9052_request_irq(struct da9052 *da9052, int irq, char *name,218			   irq_handler_t handler, void *data)219{220	irq = da9052_map_irq(da9052, irq);221	if (irq < 0)222		return irq;223 224	return request_threaded_irq(irq, NULL, handler,225				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,226				     name, data);227}228EXPORT_SYMBOL_GPL(da9052_request_irq);229 230void da9052_free_irq(struct da9052 *da9052, int irq, void *data)231{232	irq = da9052_map_irq(da9052, irq);233	if (irq < 0)234		return;235 236	free_irq(irq, data);237}238EXPORT_SYMBOL_GPL(da9052_free_irq);239 240static irqreturn_t da9052_auxadc_irq(int irq, void *irq_data)241{242	struct da9052 *da9052 = irq_data;243 244	complete(&da9052->done);245 246	return IRQ_HANDLED;247}248 249int da9052_irq_init(struct da9052 *da9052)250{251	int ret;252 253	ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,254				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,255				  -1, &da9052_regmap_irq_chip,256				  &da9052->irq_data);257	if (ret < 0) {258		dev_err(da9052->dev, "regmap_add_irq_chip failed: %d\n", ret);259		goto regmap_err;260	}261 262	enable_irq_wake(da9052->chip_irq);263 264	ret = da9052_request_irq(da9052, DA9052_IRQ_ADC_EOM, "adc-irq",265			    da9052_auxadc_irq, da9052);266 267	if (ret != 0) {268		dev_err(da9052->dev, "DA9052_IRQ_ADC_EOM failed: %d\n", ret);269		goto request_irq_err;270	}271 272	return 0;273 274request_irq_err:275	regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);276regmap_err:277	return ret;278 279}280 281int da9052_irq_exit(struct da9052 *da9052)282{283	da9052_free_irq(da9052, DA9052_IRQ_ADC_EOM, da9052);284	regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);285 286	return 0;287}288