xref: /openbmc/linux/drivers/mfd/pcf50633-irq.c (revision 245cb473)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2380c09f6SLars-Peter Clausen /* NXP PCF50633 Power Management Unit (PMU) driver
3380c09f6SLars-Peter Clausen  *
4380c09f6SLars-Peter Clausen  * (C) 2006-2008 by Openmoko, Inc.
5380c09f6SLars-Peter Clausen  * Author: Harald Welte <laforge@openmoko.org>
6380c09f6SLars-Peter Clausen  * 	   Balaji Rao <balajirrao@openmoko.org>
7380c09f6SLars-Peter Clausen  * All rights reserved.
8380c09f6SLars-Peter Clausen  */
9380c09f6SLars-Peter Clausen 
10*245cb473SPaul Cercueil #include <linux/i2c.h>
11380c09f6SLars-Peter Clausen #include <linux/interrupt.h>
12380c09f6SLars-Peter Clausen #include <linux/kernel.h>
13380c09f6SLars-Peter Clausen #include <linux/mutex.h>
145d4a357dSPaul Gortmaker #include <linux/export.h>
15380c09f6SLars-Peter Clausen #include <linux/slab.h>
16380c09f6SLars-Peter Clausen 
17380c09f6SLars-Peter Clausen #include <linux/mfd/pcf50633/core.h>
18624e26e0SAxel Lin #include <linux/mfd/pcf50633/mbc.h>
19380c09f6SLars-Peter Clausen 
pcf50633_register_irq(struct pcf50633 * pcf,int irq,void (* handler)(int,void *),void * data)20380c09f6SLars-Peter Clausen int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
21380c09f6SLars-Peter Clausen 			void (*handler) (int, void *), void *data)
22380c09f6SLars-Peter Clausen {
23380c09f6SLars-Peter Clausen 	if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
24380c09f6SLars-Peter Clausen 		return -EINVAL;
25380c09f6SLars-Peter Clausen 
26380c09f6SLars-Peter Clausen 	if (WARN_ON(pcf->irq_handler[irq].handler))
27380c09f6SLars-Peter Clausen 		return -EBUSY;
28380c09f6SLars-Peter Clausen 
29380c09f6SLars-Peter Clausen 	mutex_lock(&pcf->lock);
30380c09f6SLars-Peter Clausen 	pcf->irq_handler[irq].handler = handler;
31380c09f6SLars-Peter Clausen 	pcf->irq_handler[irq].data = data;
32380c09f6SLars-Peter Clausen 	mutex_unlock(&pcf->lock);
33380c09f6SLars-Peter Clausen 
34380c09f6SLars-Peter Clausen 	return 0;
35380c09f6SLars-Peter Clausen }
36380c09f6SLars-Peter Clausen EXPORT_SYMBOL_GPL(pcf50633_register_irq);
37380c09f6SLars-Peter Clausen 
pcf50633_free_irq(struct pcf50633 * pcf,int irq)38380c09f6SLars-Peter Clausen int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
39380c09f6SLars-Peter Clausen {
40380c09f6SLars-Peter Clausen 	if (irq < 0 || irq >= PCF50633_NUM_IRQ)
41380c09f6SLars-Peter Clausen 		return -EINVAL;
42380c09f6SLars-Peter Clausen 
43380c09f6SLars-Peter Clausen 	mutex_lock(&pcf->lock);
44380c09f6SLars-Peter Clausen 	pcf->irq_handler[irq].handler = NULL;
45380c09f6SLars-Peter Clausen 	mutex_unlock(&pcf->lock);
46380c09f6SLars-Peter Clausen 
47380c09f6SLars-Peter Clausen 	return 0;
48380c09f6SLars-Peter Clausen }
49380c09f6SLars-Peter Clausen EXPORT_SYMBOL_GPL(pcf50633_free_irq);
50380c09f6SLars-Peter Clausen 
__pcf50633_irq_mask_set(struct pcf50633 * pcf,int irq,u8 mask)51380c09f6SLars-Peter Clausen static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
52380c09f6SLars-Peter Clausen {
53380c09f6SLars-Peter Clausen 	u8 reg, bit;
54e7238fd2SJavier Martinez Canillas 	int idx;
55380c09f6SLars-Peter Clausen 
56380c09f6SLars-Peter Clausen 	idx = irq >> 3;
57380c09f6SLars-Peter Clausen 	reg = PCF50633_REG_INT1M + idx;
58380c09f6SLars-Peter Clausen 	bit = 1 << (irq & 0x07);
59380c09f6SLars-Peter Clausen 
60380c09f6SLars-Peter Clausen 	pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
61380c09f6SLars-Peter Clausen 
62380c09f6SLars-Peter Clausen 	mutex_lock(&pcf->lock);
63380c09f6SLars-Peter Clausen 
64380c09f6SLars-Peter Clausen 	if (mask)
65380c09f6SLars-Peter Clausen 		pcf->mask_regs[idx] |= bit;
66380c09f6SLars-Peter Clausen 	else
67380c09f6SLars-Peter Clausen 		pcf->mask_regs[idx] &= ~bit;
68380c09f6SLars-Peter Clausen 
69380c09f6SLars-Peter Clausen 	mutex_unlock(&pcf->lock);
70380c09f6SLars-Peter Clausen 
71e7238fd2SJavier Martinez Canillas 	return 0;
72380c09f6SLars-Peter Clausen }
73380c09f6SLars-Peter Clausen 
pcf50633_irq_mask(struct pcf50633 * pcf,int irq)74380c09f6SLars-Peter Clausen int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
75380c09f6SLars-Peter Clausen {
76380c09f6SLars-Peter Clausen 	dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
77380c09f6SLars-Peter Clausen 
78380c09f6SLars-Peter Clausen 	return __pcf50633_irq_mask_set(pcf, irq, 1);
79380c09f6SLars-Peter Clausen }
80380c09f6SLars-Peter Clausen EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
81380c09f6SLars-Peter Clausen 
pcf50633_irq_unmask(struct pcf50633 * pcf,int irq)82380c09f6SLars-Peter Clausen int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
83380c09f6SLars-Peter Clausen {
84380c09f6SLars-Peter Clausen 	dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
85380c09f6SLars-Peter Clausen 
86380c09f6SLars-Peter Clausen 	return __pcf50633_irq_mask_set(pcf, irq, 0);
87380c09f6SLars-Peter Clausen }
88380c09f6SLars-Peter Clausen EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
89380c09f6SLars-Peter Clausen 
pcf50633_irq_mask_get(struct pcf50633 * pcf,int irq)90380c09f6SLars-Peter Clausen int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
91380c09f6SLars-Peter Clausen {
92380c09f6SLars-Peter Clausen 	u8 reg, bits;
93380c09f6SLars-Peter Clausen 
94380c09f6SLars-Peter Clausen 	reg =  irq >> 3;
95380c09f6SLars-Peter Clausen 	bits = 1 << (irq & 0x07);
96380c09f6SLars-Peter Clausen 
97380c09f6SLars-Peter Clausen 	return pcf->mask_regs[reg] & bits;
98380c09f6SLars-Peter Clausen }
99380c09f6SLars-Peter Clausen EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
100380c09f6SLars-Peter Clausen 
pcf50633_irq_call_handler(struct pcf50633 * pcf,int irq)101380c09f6SLars-Peter Clausen static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
102380c09f6SLars-Peter Clausen {
103380c09f6SLars-Peter Clausen 	if (pcf->irq_handler[irq].handler)
104380c09f6SLars-Peter Clausen 		pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
105380c09f6SLars-Peter Clausen }
106380c09f6SLars-Peter Clausen 
107380c09f6SLars-Peter Clausen /* Maximum amount of time ONKEY is held before emergency action is taken */
108380c09f6SLars-Peter Clausen #define PCF50633_ONKEY1S_TIMEOUT 8
109380c09f6SLars-Peter Clausen 
pcf50633_irq(int irq,void * data)110380c09f6SLars-Peter Clausen static irqreturn_t pcf50633_irq(int irq, void *data)
111380c09f6SLars-Peter Clausen {
112380c09f6SLars-Peter Clausen 	struct pcf50633 *pcf = data;
113380c09f6SLars-Peter Clausen 	int ret, i, j;
114380c09f6SLars-Peter Clausen 	u8 pcf_int[5], chgstat;
115380c09f6SLars-Peter Clausen 
116380c09f6SLars-Peter Clausen 	/* Read the 5 INT regs in one transaction */
117380c09f6SLars-Peter Clausen 	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
118380c09f6SLars-Peter Clausen 						ARRAY_SIZE(pcf_int), pcf_int);
119380c09f6SLars-Peter Clausen 	if (ret != ARRAY_SIZE(pcf_int)) {
120380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "Error reading INT registers\n");
121380c09f6SLars-Peter Clausen 
122380c09f6SLars-Peter Clausen 		/*
123380c09f6SLars-Peter Clausen 		 * If this doesn't ACK the interrupt to the chip, we'll be
124380c09f6SLars-Peter Clausen 		 * called once again as we're level triggered.
125380c09f6SLars-Peter Clausen 		 */
126380c09f6SLars-Peter Clausen 		goto out;
127380c09f6SLars-Peter Clausen 	}
128380c09f6SLars-Peter Clausen 
129380c09f6SLars-Peter Clausen 	/* defeat 8s death from lowsys on A5 */
130380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN,  0x04);
131380c09f6SLars-Peter Clausen 
132380c09f6SLars-Peter Clausen 	/* We immediately read the usb and adapter status. We thus make sure
133380c09f6SLars-Peter Clausen 	 * only of USBINS/USBREM IRQ handlers are called */
134380c09f6SLars-Peter Clausen 	if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
135380c09f6SLars-Peter Clausen 		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
136380c09f6SLars-Peter Clausen 		if (chgstat & (0x3 << 4))
137380c09f6SLars-Peter Clausen 			pcf_int[0] &= ~PCF50633_INT1_USBREM;
138380c09f6SLars-Peter Clausen 		else
139380c09f6SLars-Peter Clausen 			pcf_int[0] &= ~PCF50633_INT1_USBINS;
140380c09f6SLars-Peter Clausen 	}
141380c09f6SLars-Peter Clausen 
142380c09f6SLars-Peter Clausen 	/* Make sure only one of ADPINS or ADPREM is set */
143380c09f6SLars-Peter Clausen 	if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
144380c09f6SLars-Peter Clausen 		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
145380c09f6SLars-Peter Clausen 		if (chgstat & (0x3 << 4))
146380c09f6SLars-Peter Clausen 			pcf_int[0] &= ~PCF50633_INT1_ADPREM;
147380c09f6SLars-Peter Clausen 		else
148380c09f6SLars-Peter Clausen 			pcf_int[0] &= ~PCF50633_INT1_ADPINS;
149380c09f6SLars-Peter Clausen 	}
150380c09f6SLars-Peter Clausen 
151380c09f6SLars-Peter Clausen 	dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
152380c09f6SLars-Peter Clausen 			"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
153380c09f6SLars-Peter Clausen 			pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
154380c09f6SLars-Peter Clausen 
155380c09f6SLars-Peter Clausen 	/* Some revisions of the chip don't have a 8s standby mode on
156380c09f6SLars-Peter Clausen 	 * ONKEY1S press. We try to manually do it in such cases. */
157380c09f6SLars-Peter Clausen 	if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
158380c09f6SLars-Peter Clausen 		dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
159380c09f6SLars-Peter Clausen 							pcf->onkey1s_held);
160380c09f6SLars-Peter Clausen 		if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
161380c09f6SLars-Peter Clausen 			if (pcf->pdata->force_shutdown)
162380c09f6SLars-Peter Clausen 				pcf->pdata->force_shutdown(pcf);
163380c09f6SLars-Peter Clausen 	}
164380c09f6SLars-Peter Clausen 
165380c09f6SLars-Peter Clausen 	if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
166380c09f6SLars-Peter Clausen 		dev_info(pcf->dev, "ONKEY1S held\n");
167380c09f6SLars-Peter Clausen 		pcf->onkey1s_held = 1 ;
168380c09f6SLars-Peter Clausen 
169380c09f6SLars-Peter Clausen 		/* Unmask IRQ_SECOND */
170380c09f6SLars-Peter Clausen 		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
171380c09f6SLars-Peter Clausen 						PCF50633_INT1_SECOND);
172380c09f6SLars-Peter Clausen 
173380c09f6SLars-Peter Clausen 		/* Unmask IRQ_ONKEYR */
174380c09f6SLars-Peter Clausen 		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
175380c09f6SLars-Peter Clausen 						PCF50633_INT2_ONKEYR);
176380c09f6SLars-Peter Clausen 	}
177380c09f6SLars-Peter Clausen 
178380c09f6SLars-Peter Clausen 	if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
179380c09f6SLars-Peter Clausen 		pcf->onkey1s_held = 0;
180380c09f6SLars-Peter Clausen 
181380c09f6SLars-Peter Clausen 		/* Mask SECOND and ONKEYR interrupts */
182380c09f6SLars-Peter Clausen 		if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
183380c09f6SLars-Peter Clausen 			pcf50633_reg_set_bit_mask(pcf,
184380c09f6SLars-Peter Clausen 					PCF50633_REG_INT1M,
185380c09f6SLars-Peter Clausen 					PCF50633_INT1_SECOND,
186380c09f6SLars-Peter Clausen 					PCF50633_INT1_SECOND);
187380c09f6SLars-Peter Clausen 
188380c09f6SLars-Peter Clausen 		if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
189380c09f6SLars-Peter Clausen 			pcf50633_reg_set_bit_mask(pcf,
190380c09f6SLars-Peter Clausen 					PCF50633_REG_INT2M,
191380c09f6SLars-Peter Clausen 					PCF50633_INT2_ONKEYR,
192380c09f6SLars-Peter Clausen 					PCF50633_INT2_ONKEYR);
193380c09f6SLars-Peter Clausen 	}
194380c09f6SLars-Peter Clausen 
195380c09f6SLars-Peter Clausen 	/* Have we just resumed ? */
196380c09f6SLars-Peter Clausen 	if (pcf->is_suspended) {
197380c09f6SLars-Peter Clausen 		pcf->is_suspended = 0;
198380c09f6SLars-Peter Clausen 
199380c09f6SLars-Peter Clausen 		/* Set the resume reason filtering out non resumers */
200380c09f6SLars-Peter Clausen 		for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
201380c09f6SLars-Peter Clausen 			pcf->resume_reason[i] = pcf_int[i] &
202380c09f6SLars-Peter Clausen 						pcf->pdata->resumers[i];
203380c09f6SLars-Peter Clausen 
204380c09f6SLars-Peter Clausen 		/* Make sure we don't pass on any ONKEY events to
205380c09f6SLars-Peter Clausen 		 * userspace now */
206380c09f6SLars-Peter Clausen 		pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
207380c09f6SLars-Peter Clausen 	}
208380c09f6SLars-Peter Clausen 
209380c09f6SLars-Peter Clausen 	for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
210380c09f6SLars-Peter Clausen 		/* Unset masked interrupts */
211380c09f6SLars-Peter Clausen 		pcf_int[i] &= ~pcf->mask_regs[i];
212380c09f6SLars-Peter Clausen 
213380c09f6SLars-Peter Clausen 		for (j = 0; j < 8 ; j++)
214380c09f6SLars-Peter Clausen 			if (pcf_int[i] & (1 << j))
215380c09f6SLars-Peter Clausen 				pcf50633_irq_call_handler(pcf, (i * 8) + j);
216380c09f6SLars-Peter Clausen 	}
217380c09f6SLars-Peter Clausen 
218380c09f6SLars-Peter Clausen out:
219380c09f6SLars-Peter Clausen 	return IRQ_HANDLED;
220380c09f6SLars-Peter Clausen }
221380c09f6SLars-Peter Clausen 
pcf50633_suspend(struct device * dev)222*245cb473SPaul Cercueil static int pcf50633_suspend(struct device *dev)
223380c09f6SLars-Peter Clausen {
224*245cb473SPaul Cercueil 	struct i2c_client *client = to_i2c_client(dev);
225*245cb473SPaul Cercueil 	struct pcf50633 *pcf = i2c_get_clientdata(client);
226380c09f6SLars-Peter Clausen 	int ret;
227380c09f6SLars-Peter Clausen 	int i;
228380c09f6SLars-Peter Clausen 	u8 res[5];
229380c09f6SLars-Peter Clausen 
230380c09f6SLars-Peter Clausen 
231380c09f6SLars-Peter Clausen 	/* Make sure our interrupt handlers are not called
232380c09f6SLars-Peter Clausen 	 * henceforth */
233380c09f6SLars-Peter Clausen 	disable_irq(pcf->irq);
234380c09f6SLars-Peter Clausen 
235380c09f6SLars-Peter Clausen 	/* Save the masks */
236380c09f6SLars-Peter Clausen 	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
237380c09f6SLars-Peter Clausen 				ARRAY_SIZE(pcf->suspend_irq_masks),
238380c09f6SLars-Peter Clausen 					pcf->suspend_irq_masks);
239380c09f6SLars-Peter Clausen 	if (ret < 0) {
240380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "error saving irq masks\n");
241380c09f6SLars-Peter Clausen 		goto out;
242380c09f6SLars-Peter Clausen 	}
243380c09f6SLars-Peter Clausen 
244380c09f6SLars-Peter Clausen 	/* Write wakeup irq masks */
245380c09f6SLars-Peter Clausen 	for (i = 0; i < ARRAY_SIZE(res); i++)
246380c09f6SLars-Peter Clausen 		res[i] = ~pcf->pdata->resumers[i];
247380c09f6SLars-Peter Clausen 
248380c09f6SLars-Peter Clausen 	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
249380c09f6SLars-Peter Clausen 					ARRAY_SIZE(res), &res[0]);
250380c09f6SLars-Peter Clausen 	if (ret < 0) {
251380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "error writing wakeup irq masks\n");
252380c09f6SLars-Peter Clausen 		goto out;
253380c09f6SLars-Peter Clausen 	}
254380c09f6SLars-Peter Clausen 
255380c09f6SLars-Peter Clausen 	pcf->is_suspended = 1;
256380c09f6SLars-Peter Clausen 
257380c09f6SLars-Peter Clausen out:
258380c09f6SLars-Peter Clausen 	return ret;
259380c09f6SLars-Peter Clausen }
260380c09f6SLars-Peter Clausen 
pcf50633_resume(struct device * dev)261*245cb473SPaul Cercueil static int pcf50633_resume(struct device *dev)
262380c09f6SLars-Peter Clausen {
263*245cb473SPaul Cercueil 	struct i2c_client *client = to_i2c_client(dev);
264*245cb473SPaul Cercueil 	struct pcf50633 *pcf = i2c_get_clientdata(client);
265380c09f6SLars-Peter Clausen 	int ret;
266380c09f6SLars-Peter Clausen 
267380c09f6SLars-Peter Clausen 	/* Write the saved mask registers */
268380c09f6SLars-Peter Clausen 	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
269380c09f6SLars-Peter Clausen 				ARRAY_SIZE(pcf->suspend_irq_masks),
270380c09f6SLars-Peter Clausen 					pcf->suspend_irq_masks);
271380c09f6SLars-Peter Clausen 	if (ret < 0)
272380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "Error restoring saved suspend masks\n");
273380c09f6SLars-Peter Clausen 
274380c09f6SLars-Peter Clausen 	enable_irq(pcf->irq);
275380c09f6SLars-Peter Clausen 
276380c09f6SLars-Peter Clausen 	return ret;
277380c09f6SLars-Peter Clausen }
278380c09f6SLars-Peter Clausen 
279*245cb473SPaul Cercueil EXPORT_GPL_SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
280380c09f6SLars-Peter Clausen 
pcf50633_irq_init(struct pcf50633 * pcf,int irq)281380c09f6SLars-Peter Clausen int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
282380c09f6SLars-Peter Clausen {
283380c09f6SLars-Peter Clausen 	int ret;
284380c09f6SLars-Peter Clausen 
285380c09f6SLars-Peter Clausen 	pcf->irq = irq;
286380c09f6SLars-Peter Clausen 
287380c09f6SLars-Peter Clausen 	/* Enable all interrupts except RTC SECOND */
288380c09f6SLars-Peter Clausen 	pcf->mask_regs[0] = 0x80;
289380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
290380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
291380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
292380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
293380c09f6SLars-Peter Clausen 	pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
294380c09f6SLars-Peter Clausen 
295380c09f6SLars-Peter Clausen 	ret = request_threaded_irq(irq, NULL, pcf50633_irq,
296380c09f6SLars-Peter Clausen 					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
297380c09f6SLars-Peter Clausen 					"pcf50633", pcf);
298380c09f6SLars-Peter Clausen 
299380c09f6SLars-Peter Clausen 	if (ret)
300380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
301380c09f6SLars-Peter Clausen 
302380c09f6SLars-Peter Clausen 	if (enable_irq_wake(irq) < 0)
303380c09f6SLars-Peter Clausen 		dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
304380c09f6SLars-Peter Clausen 			"in this hardware revision", irq);
305380c09f6SLars-Peter Clausen 
306380c09f6SLars-Peter Clausen 	return ret;
307380c09f6SLars-Peter Clausen }
308380c09f6SLars-Peter Clausen 
pcf50633_irq_free(struct pcf50633 * pcf)309380c09f6SLars-Peter Clausen void pcf50633_irq_free(struct pcf50633 *pcf)
310380c09f6SLars-Peter Clausen {
311380c09f6SLars-Peter Clausen 	free_irq(pcf->irq, pcf);
312380c09f6SLars-Peter Clausen }
313