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