xref: /openbmc/linux/drivers/mfd/pcf50633-core.c (revision 8915e540)
1f52046b1SBalaji Rao /* NXP PCF50633 Power Management Unit (PMU) driver
2f52046b1SBalaji Rao  *
3f52046b1SBalaji Rao  * (C) 2006-2008 by Openmoko, Inc.
4f52046b1SBalaji Rao  * Author: Harald Welte <laforge@openmoko.org>
5f52046b1SBalaji Rao  * 	   Balaji Rao <balajirrao@openmoko.org>
6f52046b1SBalaji Rao  * All rights reserved.
7f52046b1SBalaji Rao  *
8f52046b1SBalaji Rao  *  This program is free software; you can redistribute  it and/or modify it
9f52046b1SBalaji Rao  *  under  the terms of  the GNU General  Public License as published by the
10f52046b1SBalaji Rao  *  Free Software Foundation;  either version 2 of the  License, or (at your
11f52046b1SBalaji Rao  *  option) any later version.
12f52046b1SBalaji Rao  *
13f52046b1SBalaji Rao  */
14f52046b1SBalaji Rao 
15f52046b1SBalaji Rao #include <linux/kernel.h>
16f52046b1SBalaji Rao #include <linux/device.h>
17f52046b1SBalaji Rao #include <linux/sysfs.h>
18f52046b1SBalaji Rao #include <linux/device.h>
19f52046b1SBalaji Rao #include <linux/module.h>
20f52046b1SBalaji Rao #include <linux/types.h>
21f52046b1SBalaji Rao #include <linux/interrupt.h>
22f52046b1SBalaji Rao #include <linux/workqueue.h>
23f52046b1SBalaji Rao #include <linux/platform_device.h>
24f52046b1SBalaji Rao #include <linux/i2c.h>
25f52046b1SBalaji Rao #include <linux/irq.h>
26f52046b1SBalaji Rao 
27f52046b1SBalaji Rao #include <linux/mfd/pcf50633/core.h>
28f52046b1SBalaji Rao 
29f52046b1SBalaji Rao /* Two MBCS registers used during cold start */
30f52046b1SBalaji Rao #define PCF50633_REG_MBCS1		0x4b
31f52046b1SBalaji Rao #define PCF50633_REG_MBCS2		0x4c
32f52046b1SBalaji Rao #define PCF50633_MBCS1_USBPRES 		0x01
33f52046b1SBalaji Rao #define PCF50633_MBCS1_ADAPTPRES	0x01
34f52046b1SBalaji Rao 
35f52046b1SBalaji Rao static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
36f52046b1SBalaji Rao {
37f52046b1SBalaji Rao 	int ret;
38f52046b1SBalaji Rao 
39f52046b1SBalaji Rao 	ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
40f52046b1SBalaji Rao 				num, data);
41f52046b1SBalaji Rao 	if (ret < 0)
42f52046b1SBalaji Rao 		dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
43f52046b1SBalaji Rao 
44f52046b1SBalaji Rao 	return ret;
45f52046b1SBalaji Rao }
46f52046b1SBalaji Rao 
47f52046b1SBalaji Rao static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
48f52046b1SBalaji Rao {
49f52046b1SBalaji Rao 	int ret;
50f52046b1SBalaji Rao 
51f52046b1SBalaji Rao 	ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
52f52046b1SBalaji Rao 				num, data);
53f52046b1SBalaji Rao 	if (ret < 0)
54f52046b1SBalaji Rao 		dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
55f52046b1SBalaji Rao 
56f52046b1SBalaji Rao 	return ret;
57f52046b1SBalaji Rao 
58f52046b1SBalaji Rao }
59f52046b1SBalaji Rao 
60f52046b1SBalaji Rao /* Read a block of upto 32 regs  */
61f52046b1SBalaji Rao int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
62f52046b1SBalaji Rao 					int nr_regs, u8 *data)
63f52046b1SBalaji Rao {
64f52046b1SBalaji Rao 	int ret;
65f52046b1SBalaji Rao 
66f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
67f52046b1SBalaji Rao 	ret = __pcf50633_read(pcf, reg, nr_regs, data);
68f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
69f52046b1SBalaji Rao 
70f52046b1SBalaji Rao 	return ret;
71f52046b1SBalaji Rao }
72f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_read_block);
73f52046b1SBalaji Rao 
74f52046b1SBalaji Rao /* Write a block of upto 32 regs  */
75f52046b1SBalaji Rao int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
76f52046b1SBalaji Rao 					int nr_regs, u8 *data)
77f52046b1SBalaji Rao {
78f52046b1SBalaji Rao 	int ret;
79f52046b1SBalaji Rao 
80f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
81f52046b1SBalaji Rao 	ret = __pcf50633_write(pcf, reg, nr_regs, data);
82f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
83f52046b1SBalaji Rao 
84f52046b1SBalaji Rao 	return ret;
85f52046b1SBalaji Rao }
86f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_write_block);
87f52046b1SBalaji Rao 
88f52046b1SBalaji Rao u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
89f52046b1SBalaji Rao {
90f52046b1SBalaji Rao 	u8 val;
91f52046b1SBalaji Rao 
92f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
93f52046b1SBalaji Rao 	__pcf50633_read(pcf, reg, 1, &val);
94f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
95f52046b1SBalaji Rao 
96f52046b1SBalaji Rao 	return val;
97f52046b1SBalaji Rao }
98f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_reg_read);
99f52046b1SBalaji Rao 
100f52046b1SBalaji Rao int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
101f52046b1SBalaji Rao {
102f52046b1SBalaji Rao 	int ret;
103f52046b1SBalaji Rao 
104f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
105f52046b1SBalaji Rao 	ret = __pcf50633_write(pcf, reg, 1, &val);
106f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
107f52046b1SBalaji Rao 
108f52046b1SBalaji Rao 	return ret;
109f52046b1SBalaji Rao }
110f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_reg_write);
111f52046b1SBalaji Rao 
112f52046b1SBalaji Rao int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
113f52046b1SBalaji Rao {
114f52046b1SBalaji Rao 	int ret;
115f52046b1SBalaji Rao 	u8 tmp;
116f52046b1SBalaji Rao 
117f52046b1SBalaji Rao 	val &= mask;
118f52046b1SBalaji Rao 
119f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
120f52046b1SBalaji Rao 	ret = __pcf50633_read(pcf, reg, 1, &tmp);
121f52046b1SBalaji Rao 	if (ret < 0)
122f52046b1SBalaji Rao 		goto out;
123f52046b1SBalaji Rao 
124f52046b1SBalaji Rao 	tmp &= ~mask;
125f52046b1SBalaji Rao 	tmp |= val;
126f52046b1SBalaji Rao 	ret = __pcf50633_write(pcf, reg, 1, &tmp);
127f52046b1SBalaji Rao 
128f52046b1SBalaji Rao out:
129f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
130f52046b1SBalaji Rao 
131f52046b1SBalaji Rao 	return ret;
132f52046b1SBalaji Rao }
133f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
134f52046b1SBalaji Rao 
135f52046b1SBalaji Rao int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
136f52046b1SBalaji Rao {
137f52046b1SBalaji Rao 	int ret;
138f52046b1SBalaji Rao 	u8 tmp;
139f52046b1SBalaji Rao 
140f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
141f52046b1SBalaji Rao 	ret = __pcf50633_read(pcf, reg, 1, &tmp);
142f52046b1SBalaji Rao 	if (ret < 0)
143f52046b1SBalaji Rao 		goto out;
144f52046b1SBalaji Rao 
145f52046b1SBalaji Rao 	tmp &= ~val;
146f52046b1SBalaji Rao 	ret = __pcf50633_write(pcf, reg, 1, &tmp);
147f52046b1SBalaji Rao 
148f52046b1SBalaji Rao out:
149f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
150f52046b1SBalaji Rao 
151f52046b1SBalaji Rao 	return ret;
152f52046b1SBalaji Rao }
153f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
154f52046b1SBalaji Rao 
155f52046b1SBalaji Rao /* sysfs attributes */
156f52046b1SBalaji Rao static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
157f52046b1SBalaji Rao 			    char *buf)
158f52046b1SBalaji Rao {
159f52046b1SBalaji Rao 	struct pcf50633 *pcf = dev_get_drvdata(dev);
160f52046b1SBalaji Rao 	u8 dump[16];
161f52046b1SBalaji Rao 	int n, n1, idx = 0;
162f52046b1SBalaji Rao 	char *buf1 = buf;
163f52046b1SBalaji Rao 	static u8 address_no_read[] = { /* must be ascending */
164f52046b1SBalaji Rao 		PCF50633_REG_INT1,
165f52046b1SBalaji Rao 		PCF50633_REG_INT2,
166f52046b1SBalaji Rao 		PCF50633_REG_INT3,
167f52046b1SBalaji Rao 		PCF50633_REG_INT4,
168f52046b1SBalaji Rao 		PCF50633_REG_INT5,
169f52046b1SBalaji Rao 		0 /* terminator */
170f52046b1SBalaji Rao 	};
171f52046b1SBalaji Rao 
172f52046b1SBalaji Rao 	for (n = 0; n < 256; n += sizeof(dump)) {
173f52046b1SBalaji Rao 		for (n1 = 0; n1 < sizeof(dump); n1++)
174f52046b1SBalaji Rao 			if (n == address_no_read[idx]) {
175f52046b1SBalaji Rao 				idx++;
176f52046b1SBalaji Rao 				dump[n1] = 0x00;
177f52046b1SBalaji Rao 			} else
178f52046b1SBalaji Rao 				dump[n1] = pcf50633_reg_read(pcf, n + n1);
179f52046b1SBalaji Rao 
180f52046b1SBalaji Rao 		hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0);
181f52046b1SBalaji Rao 		buf1 += strlen(buf1);
182f52046b1SBalaji Rao 		*buf1++ = '\n';
183f52046b1SBalaji Rao 		*buf1 = '\0';
184f52046b1SBalaji Rao 	}
185f52046b1SBalaji Rao 
186f52046b1SBalaji Rao 	return buf1 - buf;
187f52046b1SBalaji Rao }
188f52046b1SBalaji Rao static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
189f52046b1SBalaji Rao 
190f52046b1SBalaji Rao static ssize_t show_resume_reason(struct device *dev,
191f52046b1SBalaji Rao 				struct device_attribute *attr, char *buf)
192f52046b1SBalaji Rao {
193f52046b1SBalaji Rao 	struct pcf50633 *pcf = dev_get_drvdata(dev);
194f52046b1SBalaji Rao 	int n;
195f52046b1SBalaji Rao 
196f52046b1SBalaji Rao 	n = sprintf(buf, "%02x%02x%02x%02x%02x\n",
197f52046b1SBalaji Rao 				pcf->resume_reason[0],
198f52046b1SBalaji Rao 				pcf->resume_reason[1],
199f52046b1SBalaji Rao 				pcf->resume_reason[2],
200f52046b1SBalaji Rao 				pcf->resume_reason[3],
201f52046b1SBalaji Rao 				pcf->resume_reason[4]);
202f52046b1SBalaji Rao 
203f52046b1SBalaji Rao 	return n;
204f52046b1SBalaji Rao }
205f52046b1SBalaji Rao static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
206f52046b1SBalaji Rao 
207f52046b1SBalaji Rao static struct attribute *pcf_sysfs_entries[] = {
208f52046b1SBalaji Rao 	&dev_attr_dump_regs.attr,
209f52046b1SBalaji Rao 	&dev_attr_resume_reason.attr,
210f52046b1SBalaji Rao 	NULL,
211f52046b1SBalaji Rao };
212f52046b1SBalaji Rao 
213f52046b1SBalaji Rao static struct attribute_group pcf_attr_group = {
214f52046b1SBalaji Rao 	.name	= NULL,			/* put in device directory */
215f52046b1SBalaji Rao 	.attrs	= pcf_sysfs_entries,
216f52046b1SBalaji Rao };
217f52046b1SBalaji Rao 
218f52046b1SBalaji Rao int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
219f52046b1SBalaji Rao 			void (*handler) (int, void *), void *data)
220f52046b1SBalaji Rao {
221f52046b1SBalaji Rao 	if (irq < 0 || irq > PCF50633_NUM_IRQ || !handler)
222f52046b1SBalaji Rao 		return -EINVAL;
223f52046b1SBalaji Rao 
224f52046b1SBalaji Rao 	if (WARN_ON(pcf->irq_handler[irq].handler))
225f52046b1SBalaji Rao 		return -EBUSY;
226f52046b1SBalaji Rao 
227f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
228f52046b1SBalaji Rao 	pcf->irq_handler[irq].handler = handler;
229f52046b1SBalaji Rao 	pcf->irq_handler[irq].data = data;
230f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
231f52046b1SBalaji Rao 
232f52046b1SBalaji Rao 	return 0;
233f52046b1SBalaji Rao }
234f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_register_irq);
235f52046b1SBalaji Rao 
236f52046b1SBalaji Rao int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
237f52046b1SBalaji Rao {
238f52046b1SBalaji Rao 	if (irq < 0 || irq > PCF50633_NUM_IRQ)
239f52046b1SBalaji Rao 		return -EINVAL;
240f52046b1SBalaji Rao 
241f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
242f52046b1SBalaji Rao 	pcf->irq_handler[irq].handler = NULL;
243f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
244f52046b1SBalaji Rao 
245f52046b1SBalaji Rao 	return 0;
246f52046b1SBalaji Rao }
247f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_free_irq);
248f52046b1SBalaji Rao 
249f52046b1SBalaji Rao static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
250f52046b1SBalaji Rao {
251f52046b1SBalaji Rao 	u8 reg, bits, tmp;
252f52046b1SBalaji Rao 	int ret = 0, idx;
253f52046b1SBalaji Rao 
254f52046b1SBalaji Rao 	idx = irq >> 3;
255f52046b1SBalaji Rao 	reg =  PCF50633_REG_INT1M + idx;
256f52046b1SBalaji Rao 	bits = 1 << (irq & 0x07);
257f52046b1SBalaji Rao 
258f52046b1SBalaji Rao 	mutex_lock(&pcf->lock);
259f52046b1SBalaji Rao 
260f52046b1SBalaji Rao 	if (mask) {
261f52046b1SBalaji Rao 		ret = __pcf50633_read(pcf, reg, 1, &tmp);
262f52046b1SBalaji Rao 		if (ret < 0)
263f52046b1SBalaji Rao 			goto out;
264f52046b1SBalaji Rao 
265f52046b1SBalaji Rao 		tmp |= bits;
266f52046b1SBalaji Rao 
267f52046b1SBalaji Rao 		ret = __pcf50633_write(pcf, reg, 1, &tmp);
268f52046b1SBalaji Rao 		if (ret < 0)
269f52046b1SBalaji Rao 			goto out;
270f52046b1SBalaji Rao 
271f52046b1SBalaji Rao 		pcf->mask_regs[idx] &= ~bits;
272f52046b1SBalaji Rao 		pcf->mask_regs[idx] |= bits;
273f52046b1SBalaji Rao 	} else {
274f52046b1SBalaji Rao 		ret = __pcf50633_read(pcf, reg, 1, &tmp);
275f52046b1SBalaji Rao 		if (ret < 0)
276f52046b1SBalaji Rao 			goto out;
277f52046b1SBalaji Rao 
278f52046b1SBalaji Rao 		tmp &= ~bits;
279f52046b1SBalaji Rao 
280f52046b1SBalaji Rao 		ret = __pcf50633_write(pcf, reg, 1, &tmp);
281f52046b1SBalaji Rao 		if (ret < 0)
282f52046b1SBalaji Rao 			goto out;
283f52046b1SBalaji Rao 
284f52046b1SBalaji Rao 		pcf->mask_regs[idx] &= ~bits;
285f52046b1SBalaji Rao 	}
286f52046b1SBalaji Rao out:
287f52046b1SBalaji Rao 	mutex_unlock(&pcf->lock);
288f52046b1SBalaji Rao 
289f52046b1SBalaji Rao 	return ret;
290f52046b1SBalaji Rao }
291f52046b1SBalaji Rao 
292f52046b1SBalaji Rao int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
293f52046b1SBalaji Rao {
294f52046b1SBalaji Rao 	dev_info(pcf->dev, "Masking IRQ %d\n", irq);
295f52046b1SBalaji Rao 
296f52046b1SBalaji Rao 	return __pcf50633_irq_mask_set(pcf, irq, 1);
297f52046b1SBalaji Rao }
298f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
299f52046b1SBalaji Rao 
300f52046b1SBalaji Rao int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
301f52046b1SBalaji Rao {
302f52046b1SBalaji Rao 	dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
303f52046b1SBalaji Rao 
304f52046b1SBalaji Rao 	return __pcf50633_irq_mask_set(pcf, irq, 0);
305f52046b1SBalaji Rao }
306f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
307f52046b1SBalaji Rao 
308f52046b1SBalaji Rao int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
309f52046b1SBalaji Rao {
310f52046b1SBalaji Rao 	u8 reg, bits;
311f52046b1SBalaji Rao 
312f52046b1SBalaji Rao 	reg =  irq >> 3;
313f52046b1SBalaji Rao 	bits = 1 << (irq & 0x07);
314f52046b1SBalaji Rao 
315f52046b1SBalaji Rao 	return pcf->mask_regs[reg] & bits;
316f52046b1SBalaji Rao }
317f52046b1SBalaji Rao EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
318f52046b1SBalaji Rao 
319f52046b1SBalaji Rao static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
320f52046b1SBalaji Rao {
321f52046b1SBalaji Rao 	if (pcf->irq_handler[irq].handler)
322f52046b1SBalaji Rao 		pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
323f52046b1SBalaji Rao }
324f52046b1SBalaji Rao 
325f52046b1SBalaji Rao /* Maximum amount of time ONKEY is held before emergency action is taken */
326f52046b1SBalaji Rao #define PCF50633_ONKEY1S_TIMEOUT 8
327f52046b1SBalaji Rao 
328f52046b1SBalaji Rao static void pcf50633_irq_worker(struct work_struct *work)
329f52046b1SBalaji Rao {
330f52046b1SBalaji Rao 	struct pcf50633 *pcf;
331f52046b1SBalaji Rao 	int ret, i, j;
332f52046b1SBalaji Rao 	u8 pcf_int[5], chgstat;
333f52046b1SBalaji Rao 
334f52046b1SBalaji Rao 	pcf = container_of(work, struct pcf50633, irq_work);
335f52046b1SBalaji Rao 
336f52046b1SBalaji Rao 	/* Read the 5 INT regs in one transaction */
337f52046b1SBalaji Rao 	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
338f52046b1SBalaji Rao 						ARRAY_SIZE(pcf_int), pcf_int);
339f52046b1SBalaji Rao 	if (ret != ARRAY_SIZE(pcf_int)) {
340f52046b1SBalaji Rao 		dev_err(pcf->dev, "Error reading INT registers\n");
341f52046b1SBalaji Rao 
342f52046b1SBalaji Rao 		/*
343f52046b1SBalaji Rao 		 * If this doesn't ACK the interrupt to the chip, we'll be
344f52046b1SBalaji Rao 		 * called once again as we're level triggered.
345f52046b1SBalaji Rao 		 */
346f52046b1SBalaji Rao 		goto out;
347f52046b1SBalaji Rao 	}
348f52046b1SBalaji Rao 
349f52046b1SBalaji Rao 	/* We immediately read the usb and adapter status. We thus make sure
350f52046b1SBalaji Rao 	 * only of USBINS/USBREM IRQ handlers are called */
351f52046b1SBalaji Rao 	if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
352f52046b1SBalaji Rao 		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
353f52046b1SBalaji Rao 		if (chgstat & (0x3 << 4))
354f52046b1SBalaji Rao 			pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM);
355f52046b1SBalaji Rao 		else
356f52046b1SBalaji Rao 			pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS);
357f52046b1SBalaji Rao 	}
358f52046b1SBalaji Rao 
359f52046b1SBalaji Rao 	/* Make sure only one of ADPINS or ADPREM is set */
360f52046b1SBalaji Rao 	if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
361f52046b1SBalaji Rao 		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
362f52046b1SBalaji Rao 		if (chgstat & (0x3 << 4))
363f52046b1SBalaji Rao 			pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM);
364f52046b1SBalaji Rao 		else
365f52046b1SBalaji Rao 			pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS);
366f52046b1SBalaji Rao 	}
367f52046b1SBalaji Rao 
368f52046b1SBalaji Rao 	dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
369f52046b1SBalaji Rao 			"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
370f52046b1SBalaji Rao 			pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
371f52046b1SBalaji Rao 
372f52046b1SBalaji Rao 	/* Some revisions of the chip don't have a 8s standby mode on
373f52046b1SBalaji Rao 	 * ONKEY1S press. We try to manually do it in such cases. */
374f52046b1SBalaji Rao 	if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
375f52046b1SBalaji Rao 		dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
376f52046b1SBalaji Rao 							pcf->onkey1s_held);
377f52046b1SBalaji Rao 		if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
378f52046b1SBalaji Rao 			if (pcf->pdata->force_shutdown)
379f52046b1SBalaji Rao 				pcf->pdata->force_shutdown(pcf);
380f52046b1SBalaji Rao 	}
381f52046b1SBalaji Rao 
382f52046b1SBalaji Rao 	if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
383f52046b1SBalaji Rao 		dev_info(pcf->dev, "ONKEY1S held\n");
384f52046b1SBalaji Rao 		pcf->onkey1s_held = 1 ;
385f52046b1SBalaji Rao 
386f52046b1SBalaji Rao 		/* Unmask IRQ_SECOND */
387f52046b1SBalaji Rao 		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
388f52046b1SBalaji Rao 						PCF50633_INT1_SECOND);
389f52046b1SBalaji Rao 
390f52046b1SBalaji Rao 		/* Unmask IRQ_ONKEYR */
391f52046b1SBalaji Rao 		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
392f52046b1SBalaji Rao 						PCF50633_INT2_ONKEYR);
393f52046b1SBalaji Rao 	}
394f52046b1SBalaji Rao 
395f52046b1SBalaji Rao 	if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
396f52046b1SBalaji Rao 		pcf->onkey1s_held = 0;
397f52046b1SBalaji Rao 
398f52046b1SBalaji Rao 		/* Mask SECOND and ONKEYR interrupts */
399f52046b1SBalaji Rao 		if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
400f52046b1SBalaji Rao 			pcf50633_reg_set_bit_mask(pcf,
401f52046b1SBalaji Rao 					PCF50633_REG_INT1M,
402f52046b1SBalaji Rao 					PCF50633_INT1_SECOND,
403f52046b1SBalaji Rao 					PCF50633_INT1_SECOND);
404f52046b1SBalaji Rao 
405f52046b1SBalaji Rao 		if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
406f52046b1SBalaji Rao 			pcf50633_reg_set_bit_mask(pcf,
407f52046b1SBalaji Rao 					PCF50633_REG_INT2M,
408f52046b1SBalaji Rao 					PCF50633_INT2_ONKEYR,
409f52046b1SBalaji Rao 					PCF50633_INT2_ONKEYR);
410f52046b1SBalaji Rao 	}
411f52046b1SBalaji Rao 
412f52046b1SBalaji Rao 	/* Have we just resumed ? */
413f52046b1SBalaji Rao 	if (pcf->is_suspended) {
414f52046b1SBalaji Rao 		pcf->is_suspended = 0;
415f52046b1SBalaji Rao 
416f52046b1SBalaji Rao 		/* Set the resume reason filtering out non resumers */
417f52046b1SBalaji Rao 		for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
418f52046b1SBalaji Rao 			pcf->resume_reason[i] = pcf_int[i] &
419f52046b1SBalaji Rao 						pcf->pdata->resumers[i];
420f52046b1SBalaji Rao 
421f52046b1SBalaji Rao 		/* Make sure we don't pass on any ONKEY events to
422f52046b1SBalaji Rao 		 * userspace now */
423f52046b1SBalaji Rao 		pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
424f52046b1SBalaji Rao 	}
425f52046b1SBalaji Rao 
426f52046b1SBalaji Rao 	for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
427f52046b1SBalaji Rao 		/* Unset masked interrupts */
428f52046b1SBalaji Rao 		pcf_int[i] &= ~pcf->mask_regs[i];
429f52046b1SBalaji Rao 
430f52046b1SBalaji Rao 		for (j = 0; j < 8 ; j++)
431f52046b1SBalaji Rao 			if (pcf_int[i] & (1 << j))
432f52046b1SBalaji Rao 				pcf50633_irq_call_handler(pcf, (i * 8) + j);
433f52046b1SBalaji Rao 	}
434f52046b1SBalaji Rao 
435f52046b1SBalaji Rao out:
436f52046b1SBalaji Rao 	put_device(pcf->dev);
437f52046b1SBalaji Rao 	enable_irq(pcf->irq);
438f52046b1SBalaji Rao }
439f52046b1SBalaji Rao 
440f52046b1SBalaji Rao static irqreturn_t pcf50633_irq(int irq, void *data)
441f52046b1SBalaji Rao {
442f52046b1SBalaji Rao 	struct pcf50633 *pcf = data;
443f52046b1SBalaji Rao 
444f52046b1SBalaji Rao 	dev_dbg(pcf->dev, "pcf50633_irq\n");
445f52046b1SBalaji Rao 
446f52046b1SBalaji Rao 	get_device(pcf->dev);
447f52046b1SBalaji Rao 	disable_irq(pcf->irq);
448f52046b1SBalaji Rao 	schedule_work(&pcf->irq_work);
449f52046b1SBalaji Rao 
450f52046b1SBalaji Rao 	return IRQ_HANDLED;
451f52046b1SBalaji Rao }
452f52046b1SBalaji Rao 
453f52046b1SBalaji Rao static void
454f52046b1SBalaji Rao pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
455f52046b1SBalaji Rao 						struct platform_device **pdev)
456f52046b1SBalaji Rao {
457f52046b1SBalaji Rao 	struct pcf50633_subdev_pdata *subdev_pdata;
458f52046b1SBalaji Rao 	int ret;
459f52046b1SBalaji Rao 
460f52046b1SBalaji Rao 	*pdev = platform_device_alloc(name, -1);
461f52046b1SBalaji Rao 	if (!*pdev) {
462f52046b1SBalaji Rao 		dev_err(pcf->dev, "Falied to allocate %s\n", name);
463f52046b1SBalaji Rao 		return;
464f52046b1SBalaji Rao 	}
465f52046b1SBalaji Rao 
466f52046b1SBalaji Rao 	subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL);
467f52046b1SBalaji Rao 	if (!subdev_pdata) {
468f52046b1SBalaji Rao 		dev_err(pcf->dev, "Error allocating subdev pdata\n");
469f52046b1SBalaji Rao 		platform_device_put(*pdev);
470f52046b1SBalaji Rao 	}
471f52046b1SBalaji Rao 
472f52046b1SBalaji Rao 	subdev_pdata->pcf = pcf;
473f52046b1SBalaji Rao 	platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata));
474f52046b1SBalaji Rao 
475f52046b1SBalaji Rao 	(*pdev)->dev.parent = pcf->dev;
476f52046b1SBalaji Rao 
477f52046b1SBalaji Rao 	ret = platform_device_add(*pdev);
478f52046b1SBalaji Rao 	if (ret) {
479f52046b1SBalaji Rao 		dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
480f52046b1SBalaji Rao 		platform_device_put(*pdev);
481f52046b1SBalaji Rao 		*pdev = NULL;
482f52046b1SBalaji Rao 	}
483f52046b1SBalaji Rao }
484f52046b1SBalaji Rao 
485f52046b1SBalaji Rao #ifdef CONFIG_PM
486f52046b1SBalaji Rao static int pcf50633_suspend(struct device *dev, pm_message_t state)
487f52046b1SBalaji Rao {
488f52046b1SBalaji Rao 	struct pcf50633 *pcf;
489f52046b1SBalaji Rao 	int ret = 0, i;
490f52046b1SBalaji Rao 	u8 res[5];
491f52046b1SBalaji Rao 
492f52046b1SBalaji Rao 	pcf = dev_get_drvdata(dev);
493f52046b1SBalaji Rao 
494f52046b1SBalaji Rao 	/* Make sure our interrupt handlers are not called
495f52046b1SBalaji Rao 	 * henceforth */
496f52046b1SBalaji Rao 	disable_irq(pcf->irq);
497f52046b1SBalaji Rao 
498f52046b1SBalaji Rao 	/* Make sure that any running IRQ worker has quit */
499f52046b1SBalaji Rao 	cancel_work_sync(&pcf->irq_work);
500f52046b1SBalaji Rao 
501f52046b1SBalaji Rao 	/* Save the masks */
502f52046b1SBalaji Rao 	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
503f52046b1SBalaji Rao 				ARRAY_SIZE(pcf->suspend_irq_masks),
504f52046b1SBalaji Rao 					pcf->suspend_irq_masks);
505f52046b1SBalaji Rao 	if (ret < 0) {
506f52046b1SBalaji Rao 		dev_err(pcf->dev, "error saving irq masks\n");
507f52046b1SBalaji Rao 		goto out;
508f52046b1SBalaji Rao 	}
509f52046b1SBalaji Rao 
510f52046b1SBalaji Rao 	/* Write wakeup irq masks */
511f52046b1SBalaji Rao 	for (i = 0; i < ARRAY_SIZE(res); i++)
512f52046b1SBalaji Rao 		res[i] = ~pcf->pdata->resumers[i];
513f52046b1SBalaji Rao 
514f52046b1SBalaji Rao 	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
515f52046b1SBalaji Rao 					ARRAY_SIZE(res), &res[0]);
516f52046b1SBalaji Rao 	if (ret < 0) {
517f52046b1SBalaji Rao 		dev_err(pcf->dev, "error writing wakeup irq masks\n");
518f52046b1SBalaji Rao 		goto out;
519f52046b1SBalaji Rao 	}
520f52046b1SBalaji Rao 
521f52046b1SBalaji Rao 	pcf->is_suspended = 1;
522f52046b1SBalaji Rao 
523f52046b1SBalaji Rao out:
524f52046b1SBalaji Rao 	return ret;
525f52046b1SBalaji Rao }
526f52046b1SBalaji Rao 
527f52046b1SBalaji Rao static int pcf50633_resume(struct device *dev)
528f52046b1SBalaji Rao {
529f52046b1SBalaji Rao 	struct pcf50633 *pcf;
530f52046b1SBalaji Rao 	int ret;
531f52046b1SBalaji Rao 
532f52046b1SBalaji Rao 	pcf = dev_get_drvdata(dev);
533f52046b1SBalaji Rao 
534f52046b1SBalaji Rao 	/* Write the saved mask registers */
535f52046b1SBalaji Rao 	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
536f52046b1SBalaji Rao 				ARRAY_SIZE(pcf->suspend_irq_masks),
537f52046b1SBalaji Rao 					pcf->suspend_irq_masks);
538f52046b1SBalaji Rao 	if (ret < 0)
539f52046b1SBalaji Rao 		dev_err(pcf->dev, "Error restoring saved suspend masks\n");
540f52046b1SBalaji Rao 
541f52046b1SBalaji Rao 	/* Restore regulators' state */
542f52046b1SBalaji Rao 
543f52046b1SBalaji Rao 
544f52046b1SBalaji Rao 	get_device(pcf->dev);
545f52046b1SBalaji Rao 
546f52046b1SBalaji Rao 	/*
547f52046b1SBalaji Rao 	 * Clear any pending interrupts and set resume reason if any.
548f52046b1SBalaji Rao 	 * This will leave with enable_irq()
549f52046b1SBalaji Rao 	 */
550f52046b1SBalaji Rao 	pcf50633_irq_worker(&pcf->irq_work);
551f52046b1SBalaji Rao 
552f52046b1SBalaji Rao 	return 0;
553f52046b1SBalaji Rao }
554f52046b1SBalaji Rao #else
555f52046b1SBalaji Rao #define pcf50633_suspend NULL
556f52046b1SBalaji Rao #define pcf50633_resume NULL
557f52046b1SBalaji Rao #endif
558f52046b1SBalaji Rao 
559f52046b1SBalaji Rao static int __devinit pcf50633_probe(struct i2c_client *client,
560f52046b1SBalaji Rao 				const struct i2c_device_id *ids)
561f52046b1SBalaji Rao {
562f52046b1SBalaji Rao 	struct pcf50633 *pcf;
563f52046b1SBalaji Rao 	struct pcf50633_platform_data *pdata = client->dev.platform_data;
564f52046b1SBalaji Rao 	int i, ret = 0;
565f52046b1SBalaji Rao 	int version, variant;
566f52046b1SBalaji Rao 
567f52046b1SBalaji Rao 	pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
568f52046b1SBalaji Rao 	if (!pcf)
569f52046b1SBalaji Rao 		return -ENOMEM;
570f52046b1SBalaji Rao 
571f52046b1SBalaji Rao 	pcf->pdata = pdata;
572f52046b1SBalaji Rao 
573f52046b1SBalaji Rao 	mutex_init(&pcf->lock);
574f52046b1SBalaji Rao 
575f52046b1SBalaji Rao 	i2c_set_clientdata(client, pcf);
576f52046b1SBalaji Rao 	pcf->dev = &client->dev;
577f52046b1SBalaji Rao 	pcf->i2c_client = client;
578f52046b1SBalaji Rao 	pcf->irq = client->irq;
579f52046b1SBalaji Rao 
580f52046b1SBalaji Rao 	INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
581f52046b1SBalaji Rao 
582f52046b1SBalaji Rao 	version = pcf50633_reg_read(pcf, 0);
583f52046b1SBalaji Rao 	variant = pcf50633_reg_read(pcf, 1);
584f52046b1SBalaji Rao 	if (version < 0 || variant < 0) {
585f52046b1SBalaji Rao 		dev_err(pcf->dev, "Unable to probe pcf50633\n");
586f52046b1SBalaji Rao 		ret = -ENODEV;
587f52046b1SBalaji Rao 		goto err;
588f52046b1SBalaji Rao 	}
589f52046b1SBalaji Rao 
590f52046b1SBalaji Rao 	dev_info(pcf->dev, "Probed device version %d variant %d\n",
591f52046b1SBalaji Rao 							version, variant);
592f52046b1SBalaji Rao 
593f52046b1SBalaji Rao 	/* Enable all interrupts except RTC SECOND */
594f52046b1SBalaji Rao 	pcf->mask_regs[0] = 0x80;
595f52046b1SBalaji Rao 	pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
596f52046b1SBalaji Rao 	pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
597f52046b1SBalaji Rao 	pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
598f52046b1SBalaji Rao 	pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
599f52046b1SBalaji Rao 	pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
600f52046b1SBalaji Rao 
601f52046b1SBalaji Rao 	/* Create sub devices */
602f52046b1SBalaji Rao 	pcf50633_client_dev_register(pcf, "pcf50633-input",
603f52046b1SBalaji Rao 						&pcf->input_pdev);
604f52046b1SBalaji Rao 	pcf50633_client_dev_register(pcf, "pcf50633-rtc",
605f52046b1SBalaji Rao 						&pcf->rtc_pdev);
606f52046b1SBalaji Rao 	pcf50633_client_dev_register(pcf, "pcf50633-mbc",
607f52046b1SBalaji Rao 						&pcf->mbc_pdev);
608f52046b1SBalaji Rao 	pcf50633_client_dev_register(pcf, "pcf50633-adc",
609f52046b1SBalaji Rao 						&pcf->adc_pdev);
610f52046b1SBalaji Rao 
611f52046b1SBalaji Rao 	for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
612f52046b1SBalaji Rao 		struct platform_device *pdev;
613f52046b1SBalaji Rao 
614f52046b1SBalaji Rao 		pdev = platform_device_alloc("pcf50633-regltr", i);
615f52046b1SBalaji Rao 		if (!pdev) {
616f52046b1SBalaji Rao 			dev_err(pcf->dev, "Cannot create regulator\n");
617f52046b1SBalaji Rao 			continue;
618f52046b1SBalaji Rao 		}
619f52046b1SBalaji Rao 
620f52046b1SBalaji Rao 		pdev->dev.parent = pcf->dev;
621f52046b1SBalaji Rao 		pdev->dev.platform_data = &pdata->reg_init_data[i];
622f52046b1SBalaji Rao 		pdev->dev.driver_data = pcf;
623f52046b1SBalaji Rao 		pcf->regulator_pdev[i] = pdev;
624f52046b1SBalaji Rao 
625f52046b1SBalaji Rao 		platform_device_add(pdev);
626f52046b1SBalaji Rao 	}
627f52046b1SBalaji Rao 
628f52046b1SBalaji Rao 	if (client->irq) {
629f52046b1SBalaji Rao 		ret = request_irq(client->irq, pcf50633_irq,
630f52046b1SBalaji Rao 				IRQF_TRIGGER_LOW, "pcf50633", pcf);
631f52046b1SBalaji Rao 
632f52046b1SBalaji Rao 		if (ret) {
633f52046b1SBalaji Rao 			dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
634f52046b1SBalaji Rao 			goto err;
635f52046b1SBalaji Rao 		}
636f52046b1SBalaji Rao 	} else {
637f52046b1SBalaji Rao 		dev_err(pcf->dev, "No IRQ configured\n");
638f52046b1SBalaji Rao 		goto err;
639f52046b1SBalaji Rao 	}
640f52046b1SBalaji Rao 
641f52046b1SBalaji Rao 	if (enable_irq_wake(client->irq) < 0)
642f52046b1SBalaji Rao 		dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
643f52046b1SBalaji Rao 			"in this hardware revision", client->irq);
644f52046b1SBalaji Rao 
645f52046b1SBalaji Rao 	ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
646f52046b1SBalaji Rao 	if (ret)
647f52046b1SBalaji Rao 		dev_err(pcf->dev, "error creating sysfs entries\n");
648f52046b1SBalaji Rao 
649f52046b1SBalaji Rao 	if (pdata->probe_done)
650f52046b1SBalaji Rao 		pdata->probe_done(pcf);
651f52046b1SBalaji Rao 
652f52046b1SBalaji Rao 	return 0;
653f52046b1SBalaji Rao 
654f52046b1SBalaji Rao err:
655f52046b1SBalaji Rao 	kfree(pcf);
656f52046b1SBalaji Rao 	return ret;
657f52046b1SBalaji Rao }
658f52046b1SBalaji Rao 
659f52046b1SBalaji Rao static int __devexit pcf50633_remove(struct i2c_client *client)
660f52046b1SBalaji Rao {
661f52046b1SBalaji Rao 	struct pcf50633 *pcf = i2c_get_clientdata(client);
662f52046b1SBalaji Rao 	int i;
663f52046b1SBalaji Rao 
664f52046b1SBalaji Rao 	free_irq(pcf->irq, pcf);
665f52046b1SBalaji Rao 
666f52046b1SBalaji Rao 	platform_device_unregister(pcf->input_pdev);
667f52046b1SBalaji Rao 	platform_device_unregister(pcf->rtc_pdev);
668f52046b1SBalaji Rao 	platform_device_unregister(pcf->mbc_pdev);
669f52046b1SBalaji Rao 	platform_device_unregister(pcf->adc_pdev);
670f52046b1SBalaji Rao 
671f52046b1SBalaji Rao 	for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
672f52046b1SBalaji Rao 		platform_device_unregister(pcf->regulator_pdev[i]);
673f52046b1SBalaji Rao 
674f52046b1SBalaji Rao 	kfree(pcf);
675f52046b1SBalaji Rao 
676f52046b1SBalaji Rao 	return 0;
677f52046b1SBalaji Rao }
678f52046b1SBalaji Rao 
679f52046b1SBalaji Rao static struct i2c_device_id pcf50633_id_table[] = {
680f52046b1SBalaji Rao 	{"pcf50633", 0x73},
6818915e540SJean Delvare 	{/* end of list */}
682f52046b1SBalaji Rao };
683f52046b1SBalaji Rao 
684f52046b1SBalaji Rao static struct i2c_driver pcf50633_driver = {
685f52046b1SBalaji Rao 	.driver = {
686f52046b1SBalaji Rao 		.name	= "pcf50633",
687f52046b1SBalaji Rao 		.suspend = pcf50633_suspend,
688f52046b1SBalaji Rao 		.resume	= pcf50633_resume,
689f52046b1SBalaji Rao 	},
690f52046b1SBalaji Rao 	.id_table = pcf50633_id_table,
691f52046b1SBalaji Rao 	.probe = pcf50633_probe,
692f52046b1SBalaji Rao 	.remove = __devexit_p(pcf50633_remove),
693f52046b1SBalaji Rao };
694f52046b1SBalaji Rao 
695f52046b1SBalaji Rao static int __init pcf50633_init(void)
696f52046b1SBalaji Rao {
697f52046b1SBalaji Rao 	return i2c_add_driver(&pcf50633_driver);
698f52046b1SBalaji Rao }
699f52046b1SBalaji Rao 
700f52046b1SBalaji Rao static void __exit pcf50633_exit(void)
701f52046b1SBalaji Rao {
702f52046b1SBalaji Rao 	i2c_del_driver(&pcf50633_driver);
703f52046b1SBalaji Rao }
704f52046b1SBalaji Rao 
705f52046b1SBalaji Rao MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU");
706f52046b1SBalaji Rao MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
707f52046b1SBalaji Rao MODULE_LICENSE("GPL");
708f52046b1SBalaji Rao 
709f52046b1SBalaji Rao module_init(pcf50633_init);
710f52046b1SBalaji Rao module_exit(pcf50633_exit);
711