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