xref: /openbmc/linux/drivers/mfd/tps6586x.c (revision d5bb1221)
1c6c19332SMike Rapoport /*
2c6c19332SMike Rapoport  * Core driver for TI TPS6586x PMIC family
3c6c19332SMike Rapoport  *
4c6c19332SMike Rapoport  * Copyright (c) 2010 CompuLab Ltd.
5c6c19332SMike Rapoport  * Mike Rapoport <mike@compulab.co.il>
6c6c19332SMike Rapoport  *
7c6c19332SMike Rapoport  * Based on da903x.c.
8c6c19332SMike Rapoport  * Copyright (C) 2008 Compulab, Ltd.
9c6c19332SMike Rapoport  * Mike Rapoport <mike@compulab.co.il>
10c6c19332SMike Rapoport  * Copyright (C) 2006-2008 Marvell International Ltd.
11c6c19332SMike Rapoport  * Eric Miao <eric.miao@marvell.com>
12c6c19332SMike Rapoport  *
13c6c19332SMike Rapoport  * This program is free software; you can redistribute it and/or modify
14c6c19332SMike Rapoport  * it under the terms of the GNU General Public License version 2 as
15c6c19332SMike Rapoport  * published by the Free Software Foundation.
16c6c19332SMike Rapoport  */
17c6c19332SMike Rapoport 
18c26448c4SGary King #include <linux/interrupt.h>
19c26448c4SGary King #include <linux/irq.h>
20c6c19332SMike Rapoport #include <linux/kernel.h>
21c6c19332SMike Rapoport #include <linux/module.h>
22c6c19332SMike Rapoport #include <linux/mutex.h>
23c6c19332SMike Rapoport #include <linux/slab.h>
24c6c19332SMike Rapoport #include <linux/gpio.h>
25c6c19332SMike Rapoport #include <linux/i2c.h>
26c6c19332SMike Rapoport 
27c6c19332SMike Rapoport #include <linux/mfd/core.h>
28c6c19332SMike Rapoport #include <linux/mfd/tps6586x.h>
29c6c19332SMike Rapoport 
30c6c19332SMike Rapoport /* GPIO control registers */
31c6c19332SMike Rapoport #define TPS6586X_GPIOSET1	0x5d
32c6c19332SMike Rapoport #define TPS6586X_GPIOSET2	0x5e
33c6c19332SMike Rapoport 
34c26448c4SGary King /* interrupt control registers */
35c26448c4SGary King #define TPS6586X_INT_ACK1	0xb5
36c26448c4SGary King #define TPS6586X_INT_ACK2	0xb6
37c26448c4SGary King #define TPS6586X_INT_ACK3	0xb7
38c26448c4SGary King #define TPS6586X_INT_ACK4	0xb8
39c26448c4SGary King 
40c26448c4SGary King /* interrupt mask registers */
41c26448c4SGary King #define TPS6586X_INT_MASK1	0xb0
42c26448c4SGary King #define TPS6586X_INT_MASK2	0xb1
43c26448c4SGary King #define TPS6586X_INT_MASK3	0xb2
44c26448c4SGary King #define TPS6586X_INT_MASK4	0xb3
45c26448c4SGary King #define TPS6586X_INT_MASK5	0xb4
46c26448c4SGary King 
47c6c19332SMike Rapoport /* device id */
48c6c19332SMike Rapoport #define TPS6586X_VERSIONCRC	0xcd
49c6c19332SMike Rapoport 
50c26448c4SGary King struct tps6586x_irq_data {
51c26448c4SGary King 	u8	mask_reg;
52c26448c4SGary King 	u8	mask_mask;
53c26448c4SGary King };
54c26448c4SGary King 
55c26448c4SGary King #define TPS6586X_IRQ(_reg, _mask)				\
56c26448c4SGary King 	{							\
57c26448c4SGary King 		.mask_reg = (_reg) - TPS6586X_INT_MASK1,	\
58c26448c4SGary King 		.mask_mask = (_mask),				\
59c26448c4SGary King 	}
60c26448c4SGary King 
61c26448c4SGary King static const struct tps6586x_irq_data tps6586x_irqs[] = {
62c26448c4SGary King 	[TPS6586X_INT_PLDO_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0),
63c26448c4SGary King 	[TPS6586X_INT_PLDO_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1),
64c26448c4SGary King 	[TPS6586X_INT_PLDO_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2),
65c26448c4SGary King 	[TPS6586X_INT_PLDO_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3),
66c26448c4SGary King 	[TPS6586X_INT_PLDO_4]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4),
67c26448c4SGary King 	[TPS6586X_INT_PLDO_5]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5),
68c26448c4SGary King 	[TPS6586X_INT_PLDO_6]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6),
69c26448c4SGary King 	[TPS6586X_INT_PLDO_7]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7),
70c26448c4SGary King 	[TPS6586X_INT_COMP_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0),
71c26448c4SGary King 	[TPS6586X_INT_ADC]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1),
72c26448c4SGary King 	[TPS6586X_INT_PLDO_8]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2),
73c26448c4SGary King 	[TPS6586X_INT_PLDO_9]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3),
74c26448c4SGary King 	[TPS6586X_INT_PSM_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4),
75c26448c4SGary King 	[TPS6586X_INT_PSM_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5),
76c26448c4SGary King 	[TPS6586X_INT_PSM_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6),
77c26448c4SGary King 	[TPS6586X_INT_PSM_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7),
78c26448c4SGary King 	[TPS6586X_INT_RTC_ALM1]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4),
79c26448c4SGary King 	[TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03),
80c26448c4SGary King 	[TPS6586X_INT_USB_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2),
81c26448c4SGary King 	[TPS6586X_INT_AC_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3),
82c26448c4SGary King 	[TPS6586X_INT_BAT_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0),
83c26448c4SGary King 	[TPS6586X_INT_CHG_STAT]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc),
84c26448c4SGary King 	[TPS6586X_INT_CHG_TEMP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06),
85c26448c4SGary King 	[TPS6586X_INT_PP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0),
86c26448c4SGary King 	[TPS6586X_INT_RESUME]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5),
87c26448c4SGary King 	[TPS6586X_INT_LOW_SYS]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6),
88c26448c4SGary King 	[TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
89c26448c4SGary King };
90c26448c4SGary King 
91c6c19332SMike Rapoport struct tps6586x {
92c6c19332SMike Rapoport 	struct mutex		lock;
93c6c19332SMike Rapoport 	struct device		*dev;
94c6c19332SMike Rapoport 	struct i2c_client	*client;
95c6c19332SMike Rapoport 
96c6c19332SMike Rapoport 	struct gpio_chip	gpio;
97c26448c4SGary King 	struct irq_chip		irq_chip;
98c26448c4SGary King 	struct mutex		irq_lock;
99c26448c4SGary King 	int			irq_base;
100c26448c4SGary King 	u32			irq_en;
101c26448c4SGary King 	u8			mask_cache[5];
102c26448c4SGary King 	u8			mask_reg[5];
103c6c19332SMike Rapoport };
104c6c19332SMike Rapoport 
105c6c19332SMike Rapoport static inline int __tps6586x_read(struct i2c_client *client,
106c6c19332SMike Rapoport 				  int reg, uint8_t *val)
107c6c19332SMike Rapoport {
108c6c19332SMike Rapoport 	int ret;
109c6c19332SMike Rapoport 
110c6c19332SMike Rapoport 	ret = i2c_smbus_read_byte_data(client, reg);
111c6c19332SMike Rapoport 	if (ret < 0) {
112c6c19332SMike Rapoport 		dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
113c6c19332SMike Rapoport 		return ret;
114c6c19332SMike Rapoport 	}
115c6c19332SMike Rapoport 
116c6c19332SMike Rapoport 	*val = (uint8_t)ret;
117c6c19332SMike Rapoport 
118c6c19332SMike Rapoport 	return 0;
119c6c19332SMike Rapoport }
120c6c19332SMike Rapoport 
121c6c19332SMike Rapoport static inline int __tps6586x_reads(struct i2c_client *client, int reg,
122c6c19332SMike Rapoport 				   int len, uint8_t *val)
123c6c19332SMike Rapoport {
124c6c19332SMike Rapoport 	int ret;
125c6c19332SMike Rapoport 
126c6c19332SMike Rapoport 	ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
127c6c19332SMike Rapoport 	if (ret < 0) {
128c6c19332SMike Rapoport 		dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
129c6c19332SMike Rapoport 		return ret;
130c6c19332SMike Rapoport 	}
131c6c19332SMike Rapoport 
132c6c19332SMike Rapoport 	return 0;
133c6c19332SMike Rapoport }
134c6c19332SMike Rapoport 
135c6c19332SMike Rapoport static inline int __tps6586x_write(struct i2c_client *client,
136c6c19332SMike Rapoport 				 int reg, uint8_t val)
137c6c19332SMike Rapoport {
138c6c19332SMike Rapoport 	int ret;
139c6c19332SMike Rapoport 
140c6c19332SMike Rapoport 	ret = i2c_smbus_write_byte_data(client, reg, val);
141c6c19332SMike Rapoport 	if (ret < 0) {
142c6c19332SMike Rapoport 		dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
143c6c19332SMike Rapoport 				val, reg);
144c6c19332SMike Rapoport 		return ret;
145c6c19332SMike Rapoport 	}
146c6c19332SMike Rapoport 
147c6c19332SMike Rapoport 	return 0;
148c6c19332SMike Rapoport }
149c6c19332SMike Rapoport 
150c6c19332SMike Rapoport static inline int __tps6586x_writes(struct i2c_client *client, int reg,
151c6c19332SMike Rapoport 				  int len, uint8_t *val)
152c6c19332SMike Rapoport {
1534b57018dSvwadekar@nvidia.com 	int ret, i;
154c6c19332SMike Rapoport 
1554b57018dSvwadekar@nvidia.com 	for (i = 0; i < len; i++) {
1564b57018dSvwadekar@nvidia.com 		ret = __tps6586x_write(client, reg + i, *(val + i));
1574b57018dSvwadekar@nvidia.com 		if (ret < 0)
158c6c19332SMike Rapoport 			return ret;
159c6c19332SMike Rapoport 	}
160c6c19332SMike Rapoport 
161c6c19332SMike Rapoport 	return 0;
162c6c19332SMike Rapoport }
163c6c19332SMike Rapoport 
164c6c19332SMike Rapoport int tps6586x_write(struct device *dev, int reg, uint8_t val)
165c6c19332SMike Rapoport {
166c6c19332SMike Rapoport 	return __tps6586x_write(to_i2c_client(dev), reg, val);
167c6c19332SMike Rapoport }
168c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_write);
169c6c19332SMike Rapoport 
170c6c19332SMike Rapoport int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
171c6c19332SMike Rapoport {
172c6c19332SMike Rapoport 	return __tps6586x_writes(to_i2c_client(dev), reg, len, val);
173c6c19332SMike Rapoport }
174c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_writes);
175c6c19332SMike Rapoport 
176c6c19332SMike Rapoport int tps6586x_read(struct device *dev, int reg, uint8_t *val)
177c6c19332SMike Rapoport {
178c6c19332SMike Rapoport 	return __tps6586x_read(to_i2c_client(dev), reg, val);
179c6c19332SMike Rapoport }
180c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_read);
181c6c19332SMike Rapoport 
182c6c19332SMike Rapoport int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
183c6c19332SMike Rapoport {
184c6c19332SMike Rapoport 	return __tps6586x_reads(to_i2c_client(dev), reg, len, val);
185c6c19332SMike Rapoport }
186c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_reads);
187c6c19332SMike Rapoport 
188c6c19332SMike Rapoport int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
189c6c19332SMike Rapoport {
190c6c19332SMike Rapoport 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
191c6c19332SMike Rapoport 	uint8_t reg_val;
192c6c19332SMike Rapoport 	int ret = 0;
193c6c19332SMike Rapoport 
194c6c19332SMike Rapoport 	mutex_lock(&tps6586x->lock);
195c6c19332SMike Rapoport 
196c6c19332SMike Rapoport 	ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
197c6c19332SMike Rapoport 	if (ret)
198c6c19332SMike Rapoport 		goto out;
199c6c19332SMike Rapoport 
200c6c19332SMike Rapoport 	if ((reg_val & bit_mask) == 0) {
201c6c19332SMike Rapoport 		reg_val |= bit_mask;
202c6c19332SMike Rapoport 		ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
203c6c19332SMike Rapoport 	}
204c6c19332SMike Rapoport out:
205c6c19332SMike Rapoport 	mutex_unlock(&tps6586x->lock);
206c6c19332SMike Rapoport 	return ret;
207c6c19332SMike Rapoport }
208c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_set_bits);
209c6c19332SMike Rapoport 
210c6c19332SMike Rapoport int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
211c6c19332SMike Rapoport {
212c6c19332SMike Rapoport 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
213c6c19332SMike Rapoport 	uint8_t reg_val;
214c6c19332SMike Rapoport 	int ret = 0;
215c6c19332SMike Rapoport 
216c6c19332SMike Rapoport 	mutex_lock(&tps6586x->lock);
217c6c19332SMike Rapoport 
218c6c19332SMike Rapoport 	ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
219c6c19332SMike Rapoport 	if (ret)
220c6c19332SMike Rapoport 		goto out;
221c6c19332SMike Rapoport 
222c6c19332SMike Rapoport 	if (reg_val & bit_mask) {
223c6c19332SMike Rapoport 		reg_val &= ~bit_mask;
224c6c19332SMike Rapoport 		ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
225c6c19332SMike Rapoport 	}
226c6c19332SMike Rapoport out:
227c6c19332SMike Rapoport 	mutex_unlock(&tps6586x->lock);
228c6c19332SMike Rapoport 	return ret;
229c6c19332SMike Rapoport }
230c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_clr_bits);
231c6c19332SMike Rapoport 
232c6c19332SMike Rapoport int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
233c6c19332SMike Rapoport {
234c6c19332SMike Rapoport 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
235c6c19332SMike Rapoport 	uint8_t reg_val;
236c6c19332SMike Rapoport 	int ret = 0;
237c6c19332SMike Rapoport 
238c6c19332SMike Rapoport 	mutex_lock(&tps6586x->lock);
239c6c19332SMike Rapoport 
240c6c19332SMike Rapoport 	ret = __tps6586x_read(tps6586x->client, reg, &reg_val);
241c6c19332SMike Rapoport 	if (ret)
242c6c19332SMike Rapoport 		goto out;
243c6c19332SMike Rapoport 
244c6c19332SMike Rapoport 	if ((reg_val & mask) != val) {
245c6c19332SMike Rapoport 		reg_val = (reg_val & ~mask) | val;
246c6c19332SMike Rapoport 		ret = __tps6586x_write(tps6586x->client, reg, reg_val);
247c6c19332SMike Rapoport 	}
248c6c19332SMike Rapoport out:
249c6c19332SMike Rapoport 	mutex_unlock(&tps6586x->lock);
250c6c19332SMike Rapoport 	return ret;
251c6c19332SMike Rapoport }
252c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_update);
253c6c19332SMike Rapoport 
254c6c19332SMike Rapoport static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
255c6c19332SMike Rapoport {
256c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
257c6c19332SMike Rapoport 	uint8_t val;
258c6c19332SMike Rapoport 	int ret;
259c6c19332SMike Rapoport 
260c6c19332SMike Rapoport 	ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val);
261c6c19332SMike Rapoport 	if (ret)
262c6c19332SMike Rapoport 		return ret;
263c6c19332SMike Rapoport 
264c6c19332SMike Rapoport 	return !!(val & (1 << offset));
265c6c19332SMike Rapoport }
266c6c19332SMike Rapoport 
267c6c19332SMike Rapoport 
268c6c19332SMike Rapoport static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
269c6c19332SMike Rapoport 			      int value)
270c6c19332SMike Rapoport {
271c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
272c6c19332SMike Rapoport 
273c6c19332SMike Rapoport 	__tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2,
274c6c19332SMike Rapoport 			 value << offset);
275c6c19332SMike Rapoport }
276c6c19332SMike Rapoport 
277c6c19332SMike Rapoport static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
278c6c19332SMike Rapoport 				int value)
279c6c19332SMike Rapoport {
280c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
281c6c19332SMike Rapoport 	uint8_t val, mask;
282c6c19332SMike Rapoport 
283c6c19332SMike Rapoport 	tps6586x_gpio_set(gc, offset, value);
284c6c19332SMike Rapoport 
285c6c19332SMike Rapoport 	val = 0x1 << (offset * 2);
286c6c19332SMike Rapoport 	mask = 0x3 << (offset * 2);
287c6c19332SMike Rapoport 
288c6c19332SMike Rapoport 	return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
289c6c19332SMike Rapoport }
290c6c19332SMike Rapoport 
2916f9f13bfSVincent Palatin static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
292c6c19332SMike Rapoport {
293c6c19332SMike Rapoport 	if (!gpio_base)
2946f9f13bfSVincent Palatin 		return 0;
295c6c19332SMike Rapoport 
296c6c19332SMike Rapoport 	tps6586x->gpio.owner		= THIS_MODULE;
297c6c19332SMike Rapoport 	tps6586x->gpio.label		= tps6586x->client->name;
298c6c19332SMike Rapoport 	tps6586x->gpio.dev		= tps6586x->dev;
299c6c19332SMike Rapoport 	tps6586x->gpio.base		= gpio_base;
300c6c19332SMike Rapoport 	tps6586x->gpio.ngpio		= 4;
301c6c19332SMike Rapoport 	tps6586x->gpio.can_sleep	= 1;
302c6c19332SMike Rapoport 
303c6c19332SMike Rapoport 	/* FIXME: add handling of GPIOs as dedicated inputs */
304c6c19332SMike Rapoport 	tps6586x->gpio.direction_output	= tps6586x_gpio_output;
305c6c19332SMike Rapoport 	tps6586x->gpio.set		= tps6586x_gpio_set;
306c6c19332SMike Rapoport 	tps6586x->gpio.get		= tps6586x_gpio_get;
307c6c19332SMike Rapoport 
3086f9f13bfSVincent Palatin 	return gpiochip_add(&tps6586x->gpio);
309c6c19332SMike Rapoport }
310c6c19332SMike Rapoport 
311c6c19332SMike Rapoport static int __remove_subdev(struct device *dev, void *unused)
312c6c19332SMike Rapoport {
313c6c19332SMike Rapoport 	platform_device_unregister(to_platform_device(dev));
314c6c19332SMike Rapoport 	return 0;
315c6c19332SMike Rapoport }
316c6c19332SMike Rapoport 
317c6c19332SMike Rapoport static int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
318c6c19332SMike Rapoport {
319c6c19332SMike Rapoport 	return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
320c6c19332SMike Rapoport }
321c6c19332SMike Rapoport 
32296e824bdSMark Brown static void tps6586x_irq_lock(struct irq_data *data)
323c26448c4SGary King {
32496e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
325c26448c4SGary King 
326c26448c4SGary King 	mutex_lock(&tps6586x->irq_lock);
327c26448c4SGary King }
328c26448c4SGary King 
32996e824bdSMark Brown static void tps6586x_irq_enable(struct irq_data *irq_data)
330c26448c4SGary King {
33196e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
33296e824bdSMark Brown 	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
333c26448c4SGary King 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
334c26448c4SGary King 
335c26448c4SGary King 	tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
336c26448c4SGary King 	tps6586x->irq_en |= (1 << __irq);
337c26448c4SGary King }
338c26448c4SGary King 
33996e824bdSMark Brown static void tps6586x_irq_disable(struct irq_data *irq_data)
340c26448c4SGary King {
34196e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
342c26448c4SGary King 
34396e824bdSMark Brown 	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
344c26448c4SGary King 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
345c26448c4SGary King 
346c26448c4SGary King 	tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
347c26448c4SGary King 	tps6586x->irq_en &= ~(1 << __irq);
348c26448c4SGary King }
349c26448c4SGary King 
35096e824bdSMark Brown static void tps6586x_irq_sync_unlock(struct irq_data *data)
351c26448c4SGary King {
35296e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
353c26448c4SGary King 	int i;
354c26448c4SGary King 
355c26448c4SGary King 	for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
356c26448c4SGary King 		if (tps6586x->mask_reg[i] != tps6586x->mask_cache[i]) {
357c26448c4SGary King 			if (!WARN_ON(tps6586x_write(tps6586x->dev,
358c26448c4SGary King 						    TPS6586X_INT_MASK1 + i,
359c26448c4SGary King 						    tps6586x->mask_reg[i])))
360c26448c4SGary King 				tps6586x->mask_cache[i] = tps6586x->mask_reg[i];
361c26448c4SGary King 		}
362c26448c4SGary King 	}
363c26448c4SGary King 
364c26448c4SGary King 	mutex_unlock(&tps6586x->irq_lock);
365c26448c4SGary King }
366c26448c4SGary King 
367c26448c4SGary King static irqreturn_t tps6586x_irq(int irq, void *data)
368c26448c4SGary King {
369c26448c4SGary King 	struct tps6586x *tps6586x = data;
370c26448c4SGary King 	u32 acks;
371c26448c4SGary King 	int ret = 0;
372c26448c4SGary King 
373c26448c4SGary King 	ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
374c26448c4SGary King 			     sizeof(acks), (uint8_t *)&acks);
375c26448c4SGary King 
376c26448c4SGary King 	if (ret < 0) {
377c26448c4SGary King 		dev_err(tps6586x->dev, "failed to read interrupt status\n");
378c26448c4SGary King 		return IRQ_NONE;
379c26448c4SGary King 	}
380c26448c4SGary King 
381c26448c4SGary King 	acks = le32_to_cpu(acks);
382c26448c4SGary King 
383c26448c4SGary King 	while (acks) {
384c26448c4SGary King 		int i = __ffs(acks);
385c26448c4SGary King 
386c26448c4SGary King 		if (tps6586x->irq_en & (1 << i))
387c26448c4SGary King 			handle_nested_irq(tps6586x->irq_base + i);
388c26448c4SGary King 
389c26448c4SGary King 		acks &= ~(1 << i);
390c26448c4SGary King 	}
391c26448c4SGary King 
392c26448c4SGary King 	return IRQ_HANDLED;
393c26448c4SGary King }
394c26448c4SGary King 
395c26448c4SGary King static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
396c26448c4SGary King 				       int irq_base)
397c26448c4SGary King {
398c26448c4SGary King 	int i, ret;
399c26448c4SGary King 	u8 tmp[4];
400c26448c4SGary King 
401c26448c4SGary King 	if (!irq_base) {
402c26448c4SGary King 		dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n");
403c26448c4SGary King 		return -EINVAL;
404c26448c4SGary King 	}
405c26448c4SGary King 
406c26448c4SGary King 	mutex_init(&tps6586x->irq_lock);
407c26448c4SGary King 	for (i = 0; i < 5; i++) {
408c26448c4SGary King 		tps6586x->mask_cache[i] = 0xff;
409c26448c4SGary King 		tps6586x->mask_reg[i] = 0xff;
410c26448c4SGary King 		tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff);
411c26448c4SGary King 	}
412c26448c4SGary King 
413c26448c4SGary King 	tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp);
414c26448c4SGary King 
415c26448c4SGary King 	tps6586x->irq_base = irq_base;
416c26448c4SGary King 
417c26448c4SGary King 	tps6586x->irq_chip.name = "tps6586x";
41896e824bdSMark Brown 	tps6586x->irq_chip.irq_enable = tps6586x_irq_enable;
41996e824bdSMark Brown 	tps6586x->irq_chip.irq_disable = tps6586x_irq_disable;
42096e824bdSMark Brown 	tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock;
42196e824bdSMark Brown 	tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock;
422c26448c4SGary King 
423c26448c4SGary King 	for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
424c26448c4SGary King 		int __irq = i + tps6586x->irq_base;
425d5bb1221SThomas Gleixner 		irq_set_chip_data(__irq, tps6586x);
426d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
427c26448c4SGary King 					 handle_simple_irq);
428d5bb1221SThomas Gleixner 		irq_set_nested_thread(__irq, 1);
429c26448c4SGary King #ifdef CONFIG_ARM
430c26448c4SGary King 		set_irq_flags(__irq, IRQF_VALID);
431c26448c4SGary King #endif
432c26448c4SGary King 	}
433c26448c4SGary King 
434c26448c4SGary King 	ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT,
435c26448c4SGary King 				   "tps6586x", tps6586x);
436c26448c4SGary King 
437c26448c4SGary King 	if (!ret) {
438c26448c4SGary King 		device_init_wakeup(tps6586x->dev, 1);
439c26448c4SGary King 		enable_irq_wake(irq);
440c26448c4SGary King 	}
441c26448c4SGary King 
442c26448c4SGary King 	return ret;
443c26448c4SGary King }
444c26448c4SGary King 
445c6c19332SMike Rapoport static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
446c6c19332SMike Rapoport 					  struct tps6586x_platform_data *pdata)
447c6c19332SMike Rapoport {
448c6c19332SMike Rapoport 	struct tps6586x_subdev_info *subdev;
449c6c19332SMike Rapoport 	struct platform_device *pdev;
450c6c19332SMike Rapoport 	int i, ret = 0;
451c6c19332SMike Rapoport 
452c6c19332SMike Rapoport 	for (i = 0; i < pdata->num_subdevs; i++) {
453c6c19332SMike Rapoport 		subdev = &pdata->subdevs[i];
454c6c19332SMike Rapoport 
455c6c19332SMike Rapoport 		pdev = platform_device_alloc(subdev->name, subdev->id);
456929980abSAxel Lin 		if (!pdev) {
457929980abSAxel Lin 			ret = -ENOMEM;
458929980abSAxel Lin 			goto failed;
459929980abSAxel Lin 		}
460c6c19332SMike Rapoport 
461c6c19332SMike Rapoport 		pdev->dev.parent = tps6586x->dev;
462c6c19332SMike Rapoport 		pdev->dev.platform_data = subdev->platform_data;
463c6c19332SMike Rapoport 
464c6c19332SMike Rapoport 		ret = platform_device_add(pdev);
465929980abSAxel Lin 		if (ret) {
466929980abSAxel Lin 			platform_device_put(pdev);
467c6c19332SMike Rapoport 			goto failed;
468c6c19332SMike Rapoport 		}
469929980abSAxel Lin 	}
470c6c19332SMike Rapoport 	return 0;
471c6c19332SMike Rapoport 
472c6c19332SMike Rapoport failed:
473c6c19332SMike Rapoport 	tps6586x_remove_subdevs(tps6586x);
474c6c19332SMike Rapoport 	return ret;
475c6c19332SMike Rapoport }
476c6c19332SMike Rapoport 
477c6c19332SMike Rapoport static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
478c6c19332SMike Rapoport 					const struct i2c_device_id *id)
479c6c19332SMike Rapoport {
480c6c19332SMike Rapoport 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
481c6c19332SMike Rapoport 	struct tps6586x *tps6586x;
482c6c19332SMike Rapoport 	int ret;
483c6c19332SMike Rapoport 
484c6c19332SMike Rapoport 	if (!pdata) {
485c6c19332SMike Rapoport 		dev_err(&client->dev, "tps6586x requires platform data\n");
486c6c19332SMike Rapoport 		return -ENOTSUPP;
487c6c19332SMike Rapoport 	}
488c6c19332SMike Rapoport 
489c6c19332SMike Rapoport 	ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
490c6c19332SMike Rapoport 	if (ret < 0) {
491c6c19332SMike Rapoport 		dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
492c6c19332SMike Rapoport 		return -EIO;
493c6c19332SMike Rapoport 	}
494c6c19332SMike Rapoport 
4954d1cdbf6SStephen Warren 	dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
496c6c19332SMike Rapoport 
497c6c19332SMike Rapoport 	tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
498c6c19332SMike Rapoport 	if (tps6586x == NULL)
499c6c19332SMike Rapoport 		return -ENOMEM;
500c6c19332SMike Rapoport 
501c6c19332SMike Rapoport 	tps6586x->client = client;
502c6c19332SMike Rapoport 	tps6586x->dev = &client->dev;
503c6c19332SMike Rapoport 	i2c_set_clientdata(client, tps6586x);
504c6c19332SMike Rapoport 
505c6c19332SMike Rapoport 	mutex_init(&tps6586x->lock);
506c6c19332SMike Rapoport 
507c26448c4SGary King 	if (client->irq) {
508c26448c4SGary King 		ret = tps6586x_irq_init(tps6586x, client->irq,
509c26448c4SGary King 					pdata->irq_base);
510c26448c4SGary King 		if (ret) {
511c26448c4SGary King 			dev_err(&client->dev, "IRQ init failed: %d\n", ret);
512c26448c4SGary King 			goto err_irq_init;
513c26448c4SGary King 		}
514c26448c4SGary King 	}
515c26448c4SGary King 
5166f9f13bfSVincent Palatin 	ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base);
5176f9f13bfSVincent Palatin 	if (ret) {
5186f9f13bfSVincent Palatin 		dev_err(&client->dev, "GPIO registration failed: %d\n", ret);
5196f9f13bfSVincent Palatin 		goto err_gpio_init;
5206f9f13bfSVincent Palatin 	}
5216f9f13bfSVincent Palatin 
522c6c19332SMike Rapoport 	ret = tps6586x_add_subdevs(tps6586x, pdata);
523c6c19332SMike Rapoport 	if (ret) {
524c6c19332SMike Rapoport 		dev_err(&client->dev, "add devices failed: %d\n", ret);
525c6c19332SMike Rapoport 		goto err_add_devs;
526c6c19332SMike Rapoport 	}
527c6c19332SMike Rapoport 
528c6c19332SMike Rapoport 	return 0;
529c6c19332SMike Rapoport 
530c6c19332SMike Rapoport err_add_devs:
5316f9f13bfSVincent Palatin 	if (pdata->gpio_base) {
5326f9f13bfSVincent Palatin 		ret = gpiochip_remove(&tps6586x->gpio);
5336f9f13bfSVincent Palatin 		if (ret)
5346f9f13bfSVincent Palatin 			dev_err(&client->dev, "Can't remove gpio chip: %d\n",
5356f9f13bfSVincent Palatin 				ret);
5366f9f13bfSVincent Palatin 	}
5376f9f13bfSVincent Palatin err_gpio_init:
538c26448c4SGary King 	if (client->irq)
539c26448c4SGary King 		free_irq(client->irq, tps6586x);
540c26448c4SGary King err_irq_init:
541c6c19332SMike Rapoport 	kfree(tps6586x);
542c6c19332SMike Rapoport 	return ret;
543c6c19332SMike Rapoport }
544c6c19332SMike Rapoport 
545c6c19332SMike Rapoport static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
546c6c19332SMike Rapoport {
5474b751cf5SAxel Lin 	struct tps6586x *tps6586x = i2c_get_clientdata(client);
5484b751cf5SAxel Lin 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
5494b751cf5SAxel Lin 	int ret;
5504b751cf5SAxel Lin 
551c26448c4SGary King 	if (client->irq)
552c26448c4SGary King 		free_irq(client->irq, tps6586x);
553c26448c4SGary King 
5544b751cf5SAxel Lin 	if (pdata->gpio_base) {
5554b751cf5SAxel Lin 		ret = gpiochip_remove(&tps6586x->gpio);
5564b751cf5SAxel Lin 		if (ret)
5574b751cf5SAxel Lin 			dev_err(&client->dev, "Can't remove gpio chip: %d\n",
5584b751cf5SAxel Lin 				ret);
5594b751cf5SAxel Lin 	}
5604b751cf5SAxel Lin 
5614b751cf5SAxel Lin 	tps6586x_remove_subdevs(tps6586x);
5624b751cf5SAxel Lin 	kfree(tps6586x);
563c6c19332SMike Rapoport 	return 0;
564c6c19332SMike Rapoport }
565c6c19332SMike Rapoport 
566c6c19332SMike Rapoport static const struct i2c_device_id tps6586x_id_table[] = {
567c6c19332SMike Rapoport 	{ "tps6586x", 0 },
568c6c19332SMike Rapoport 	{ },
569c6c19332SMike Rapoport };
570c6c19332SMike Rapoport MODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
571c6c19332SMike Rapoport 
572c6c19332SMike Rapoport static struct i2c_driver tps6586x_driver = {
573c6c19332SMike Rapoport 	.driver	= {
574c6c19332SMike Rapoport 		.name	= "tps6586x",
575c6c19332SMike Rapoport 		.owner	= THIS_MODULE,
576c6c19332SMike Rapoport 	},
577c6c19332SMike Rapoport 	.probe		= tps6586x_i2c_probe,
578c6c19332SMike Rapoport 	.remove		= __devexit_p(tps6586x_i2c_remove),
579c6c19332SMike Rapoport 	.id_table	= tps6586x_id_table,
580c6c19332SMike Rapoport };
581c6c19332SMike Rapoport 
582c6c19332SMike Rapoport static int __init tps6586x_init(void)
583c6c19332SMike Rapoport {
584c6c19332SMike Rapoport 	return i2c_add_driver(&tps6586x_driver);
585c6c19332SMike Rapoport }
586c6c19332SMike Rapoport subsys_initcall(tps6586x_init);
587c6c19332SMike Rapoport 
588c6c19332SMike Rapoport static void __exit tps6586x_exit(void)
589c6c19332SMike Rapoport {
590c6c19332SMike Rapoport 	i2c_del_driver(&tps6586x_driver);
591c6c19332SMike Rapoport }
592c6c19332SMike Rapoport module_exit(tps6586x_exit);
593c6c19332SMike Rapoport 
594c6c19332SMike Rapoport MODULE_DESCRIPTION("TPS6586X core driver");
595c6c19332SMike Rapoport MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
596c6c19332SMike Rapoport MODULE_LICENSE("GPL");
597