xref: /openbmc/linux/drivers/mfd/tps6586x.c (revision 75edd5af)
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>
241176b5beSLaxman Dewangan #include <linux/err.h>
25c6c19332SMike Rapoport #include <linux/gpio.h>
26c6c19332SMike Rapoport #include <linux/i2c.h>
271176b5beSLaxman Dewangan #include <linux/regmap.h>
2862f6b087SThierry Reding #include <linux/regulator/of_regulator.h>
29c6c19332SMike Rapoport 
30c6c19332SMike Rapoport #include <linux/mfd/core.h>
31c6c19332SMike Rapoport #include <linux/mfd/tps6586x.h>
32c6c19332SMike Rapoport 
33c6c19332SMike Rapoport /* GPIO control registers */
34c6c19332SMike Rapoport #define TPS6586X_GPIOSET1	0x5d
35c6c19332SMike Rapoport #define TPS6586X_GPIOSET2	0x5e
36c6c19332SMike Rapoport 
37c26448c4SGary King /* interrupt control registers */
38c26448c4SGary King #define TPS6586X_INT_ACK1	0xb5
39c26448c4SGary King #define TPS6586X_INT_ACK2	0xb6
40c26448c4SGary King #define TPS6586X_INT_ACK3	0xb7
41c26448c4SGary King #define TPS6586X_INT_ACK4	0xb8
42c26448c4SGary King 
43c26448c4SGary King /* interrupt mask registers */
44c26448c4SGary King #define TPS6586X_INT_MASK1	0xb0
45c26448c4SGary King #define TPS6586X_INT_MASK2	0xb1
46c26448c4SGary King #define TPS6586X_INT_MASK3	0xb2
47c26448c4SGary King #define TPS6586X_INT_MASK4	0xb3
48c26448c4SGary King #define TPS6586X_INT_MASK5	0xb4
49c26448c4SGary King 
50c6c19332SMike Rapoport /* device id */
51c6c19332SMike Rapoport #define TPS6586X_VERSIONCRC	0xcd
52c6c19332SMike Rapoport 
531176b5beSLaxman Dewangan /* Maximum register */
541176b5beSLaxman Dewangan #define TPS6586X_MAX_REGISTER	(TPS6586X_VERSIONCRC + 1)
551176b5beSLaxman Dewangan 
56c26448c4SGary King struct tps6586x_irq_data {
57c26448c4SGary King 	u8	mask_reg;
58c26448c4SGary King 	u8	mask_mask;
59c26448c4SGary King };
60c26448c4SGary King 
61c26448c4SGary King #define TPS6586X_IRQ(_reg, _mask)				\
62c26448c4SGary King 	{							\
63c26448c4SGary King 		.mask_reg = (_reg) - TPS6586X_INT_MASK1,	\
64c26448c4SGary King 		.mask_mask = (_mask),				\
65c26448c4SGary King 	}
66c26448c4SGary King 
67c26448c4SGary King static const struct tps6586x_irq_data tps6586x_irqs[] = {
68c26448c4SGary King 	[TPS6586X_INT_PLDO_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0),
69c26448c4SGary King 	[TPS6586X_INT_PLDO_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1),
70c26448c4SGary King 	[TPS6586X_INT_PLDO_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2),
71c26448c4SGary King 	[TPS6586X_INT_PLDO_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3),
72c26448c4SGary King 	[TPS6586X_INT_PLDO_4]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4),
73c26448c4SGary King 	[TPS6586X_INT_PLDO_5]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5),
74c26448c4SGary King 	[TPS6586X_INT_PLDO_6]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6),
75c26448c4SGary King 	[TPS6586X_INT_PLDO_7]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7),
76c26448c4SGary King 	[TPS6586X_INT_COMP_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0),
77c26448c4SGary King 	[TPS6586X_INT_ADC]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1),
78c26448c4SGary King 	[TPS6586X_INT_PLDO_8]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2),
79c26448c4SGary King 	[TPS6586X_INT_PLDO_9]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3),
80c26448c4SGary King 	[TPS6586X_INT_PSM_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4),
81c26448c4SGary King 	[TPS6586X_INT_PSM_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5),
82c26448c4SGary King 	[TPS6586X_INT_PSM_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6),
83c26448c4SGary King 	[TPS6586X_INT_PSM_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7),
84c26448c4SGary King 	[TPS6586X_INT_RTC_ALM1]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4),
85c26448c4SGary King 	[TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03),
86c26448c4SGary King 	[TPS6586X_INT_USB_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2),
87c26448c4SGary King 	[TPS6586X_INT_AC_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3),
88c26448c4SGary King 	[TPS6586X_INT_BAT_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0),
89c26448c4SGary King 	[TPS6586X_INT_CHG_STAT]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc),
90c26448c4SGary King 	[TPS6586X_INT_CHG_TEMP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06),
91c26448c4SGary King 	[TPS6586X_INT_PP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0),
92c26448c4SGary King 	[TPS6586X_INT_RESUME]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5),
93c26448c4SGary King 	[TPS6586X_INT_LOW_SYS]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6),
94c26448c4SGary King 	[TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
95c26448c4SGary King };
96c26448c4SGary King 
97c6c19332SMike Rapoport struct tps6586x {
98c6c19332SMike Rapoport 	struct device		*dev;
99c6c19332SMike Rapoport 	struct i2c_client	*client;
1001176b5beSLaxman Dewangan 	struct regmap		*regmap;
101c6c19332SMike Rapoport 
102c6c19332SMike Rapoport 	struct gpio_chip	gpio;
103c26448c4SGary King 	struct irq_chip		irq_chip;
104c26448c4SGary King 	struct mutex		irq_lock;
105c26448c4SGary King 	int			irq_base;
106c26448c4SGary King 	u32			irq_en;
107c26448c4SGary King 	u8			mask_reg[5];
108c6c19332SMike Rapoport };
109c6c19332SMike Rapoport 
1101176b5beSLaxman Dewangan static inline struct tps6586x *dev_to_tps6586x(struct device *dev)
111c6c19332SMike Rapoport {
1121176b5beSLaxman Dewangan 	return i2c_get_clientdata(to_i2c_client(dev));
113c6c19332SMike Rapoport }
114c6c19332SMike Rapoport 
115c6c19332SMike Rapoport int tps6586x_write(struct device *dev, int reg, uint8_t val)
116c6c19332SMike Rapoport {
1171176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1181176b5beSLaxman Dewangan 
1191176b5beSLaxman Dewangan 	return regmap_write(tps6586x->regmap, reg, val);
120c6c19332SMike Rapoport }
121c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_write);
122c6c19332SMike Rapoport 
123c6c19332SMike Rapoport int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
124c6c19332SMike Rapoport {
1251176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1261176b5beSLaxman Dewangan 
1271176b5beSLaxman Dewangan 	return regmap_bulk_write(tps6586x->regmap, reg, val, len);
128c6c19332SMike Rapoport }
129c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_writes);
130c6c19332SMike Rapoport 
131c6c19332SMike Rapoport int tps6586x_read(struct device *dev, int reg, uint8_t *val)
132c6c19332SMike Rapoport {
1331176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1341176b5beSLaxman Dewangan 	unsigned int rval;
1351176b5beSLaxman Dewangan 	int ret;
1361176b5beSLaxman Dewangan 
1371176b5beSLaxman Dewangan 	ret = regmap_read(tps6586x->regmap, reg, &rval);
1381176b5beSLaxman Dewangan 	if (!ret)
1391176b5beSLaxman Dewangan 		*val = rval;
1401176b5beSLaxman Dewangan 	return ret;
141c6c19332SMike Rapoport }
142c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_read);
143c6c19332SMike Rapoport 
144c6c19332SMike Rapoport int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
145c6c19332SMike Rapoport {
1461176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1471176b5beSLaxman Dewangan 
1481176b5beSLaxman Dewangan 	return regmap_bulk_read(tps6586x->regmap, reg, val, len);
149c6c19332SMike Rapoport }
150c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_reads);
151c6c19332SMike Rapoport 
152c6c19332SMike Rapoport int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
153c6c19332SMike Rapoport {
1541176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
155c6c19332SMike Rapoport 
1561176b5beSLaxman Dewangan 	return regmap_update_bits(tps6586x->regmap, reg, bit_mask, bit_mask);
157c6c19332SMike Rapoport }
158c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_set_bits);
159c6c19332SMike Rapoport 
160c6c19332SMike Rapoport int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
161c6c19332SMike Rapoport {
1621176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
163c6c19332SMike Rapoport 
1641176b5beSLaxman Dewangan 	return regmap_update_bits(tps6586x->regmap, reg, bit_mask, 0);
165c6c19332SMike Rapoport }
166c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_clr_bits);
167c6c19332SMike Rapoport 
168c6c19332SMike Rapoport int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
169c6c19332SMike Rapoport {
1701176b5beSLaxman Dewangan 	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
171c6c19332SMike Rapoport 
1721176b5beSLaxman Dewangan 	return regmap_update_bits(tps6586x->regmap, reg, mask, val);
173c6c19332SMike Rapoport }
174c6c19332SMike Rapoport EXPORT_SYMBOL_GPL(tps6586x_update);
175c6c19332SMike Rapoport 
176c6c19332SMike Rapoport static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
177c6c19332SMike Rapoport {
178c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
179c6c19332SMike Rapoport 	uint8_t val;
180c6c19332SMike Rapoport 	int ret;
181c6c19332SMike Rapoport 
1821176b5beSLaxman Dewangan 	ret = tps6586x_read(tps6586x->dev, TPS6586X_GPIOSET2, &val);
183c6c19332SMike Rapoport 	if (ret)
184c6c19332SMike Rapoport 		return ret;
185c6c19332SMike Rapoport 
186c6c19332SMike Rapoport 	return !!(val & (1 << offset));
187c6c19332SMike Rapoport }
188c6c19332SMike Rapoport 
189c6c19332SMike Rapoport 
190c6c19332SMike Rapoport static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
191c6c19332SMike Rapoport 			      int value)
192c6c19332SMike Rapoport {
193c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
194c6c19332SMike Rapoport 
195e6f1945bSVincent Palatin 	tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2,
196e6f1945bSVincent Palatin 			value << offset, 1 << offset);
197c6c19332SMike Rapoport }
198c6c19332SMike Rapoport 
199c6c19332SMike Rapoport static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
200c6c19332SMike Rapoport 				int value)
201c6c19332SMike Rapoport {
202c6c19332SMike Rapoport 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
203c6c19332SMike Rapoport 	uint8_t val, mask;
204c6c19332SMike Rapoport 
205c6c19332SMike Rapoport 	tps6586x_gpio_set(gc, offset, value);
206c6c19332SMike Rapoport 
207c6c19332SMike Rapoport 	val = 0x1 << (offset * 2);
208c6c19332SMike Rapoport 	mask = 0x3 << (offset * 2);
209c6c19332SMike Rapoport 
210c6c19332SMike Rapoport 	return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
211c6c19332SMike Rapoport }
212c6c19332SMike Rapoport 
2136f9f13bfSVincent Palatin static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
214c6c19332SMike Rapoport {
215c6c19332SMike Rapoport 	if (!gpio_base)
2166f9f13bfSVincent Palatin 		return 0;
217c6c19332SMike Rapoport 
218c6c19332SMike Rapoport 	tps6586x->gpio.owner		= THIS_MODULE;
219c6c19332SMike Rapoport 	tps6586x->gpio.label		= tps6586x->client->name;
220c6c19332SMike Rapoport 	tps6586x->gpio.dev		= tps6586x->dev;
221c6c19332SMike Rapoport 	tps6586x->gpio.base		= gpio_base;
222c6c19332SMike Rapoport 	tps6586x->gpio.ngpio		= 4;
223c6c19332SMike Rapoport 	tps6586x->gpio.can_sleep	= 1;
224c6c19332SMike Rapoport 
225c6c19332SMike Rapoport 	/* FIXME: add handling of GPIOs as dedicated inputs */
226c6c19332SMike Rapoport 	tps6586x->gpio.direction_output	= tps6586x_gpio_output;
227c6c19332SMike Rapoport 	tps6586x->gpio.set		= tps6586x_gpio_set;
228c6c19332SMike Rapoport 	tps6586x->gpio.get		= tps6586x_gpio_get;
229c6c19332SMike Rapoport 
2306f9f13bfSVincent Palatin 	return gpiochip_add(&tps6586x->gpio);
231c6c19332SMike Rapoport }
232c6c19332SMike Rapoport 
233c6c19332SMike Rapoport static int __remove_subdev(struct device *dev, void *unused)
234c6c19332SMike Rapoport {
235c6c19332SMike Rapoport 	platform_device_unregister(to_platform_device(dev));
236c6c19332SMike Rapoport 	return 0;
237c6c19332SMike Rapoport }
238c6c19332SMike Rapoport 
239c6c19332SMike Rapoport static int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
240c6c19332SMike Rapoport {
241c6c19332SMike Rapoport 	return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
242c6c19332SMike Rapoport }
243c6c19332SMike Rapoport 
24496e824bdSMark Brown static void tps6586x_irq_lock(struct irq_data *data)
245c26448c4SGary King {
24696e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
247c26448c4SGary King 
248c26448c4SGary King 	mutex_lock(&tps6586x->irq_lock);
249c26448c4SGary King }
250c26448c4SGary King 
25196e824bdSMark Brown static void tps6586x_irq_enable(struct irq_data *irq_data)
252c26448c4SGary King {
25396e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
25496e824bdSMark Brown 	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
255c26448c4SGary King 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
256c26448c4SGary King 
257c26448c4SGary King 	tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
258c26448c4SGary King 	tps6586x->irq_en |= (1 << __irq);
259c26448c4SGary King }
260c26448c4SGary King 
26196e824bdSMark Brown static void tps6586x_irq_disable(struct irq_data *irq_data)
262c26448c4SGary King {
26396e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
264c26448c4SGary King 
26596e824bdSMark Brown 	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
266c26448c4SGary King 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
267c26448c4SGary King 
268c26448c4SGary King 	tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
269c26448c4SGary King 	tps6586x->irq_en &= ~(1 << __irq);
270c26448c4SGary King }
271c26448c4SGary King 
27296e824bdSMark Brown static void tps6586x_irq_sync_unlock(struct irq_data *data)
273c26448c4SGary King {
27496e824bdSMark Brown 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
275c26448c4SGary King 	int i;
276c26448c4SGary King 
277c26448c4SGary King 	for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
27875edd5afSLaxman Dewangan 		int ret;
27975edd5afSLaxman Dewangan 		ret = tps6586x_write(tps6586x->dev,
280c26448c4SGary King 					    TPS6586X_INT_MASK1 + i,
28175edd5afSLaxman Dewangan 					    tps6586x->mask_reg[i]);
28275edd5afSLaxman Dewangan 		WARN_ON(ret);
283c26448c4SGary King 	}
284c26448c4SGary King 
285c26448c4SGary King 	mutex_unlock(&tps6586x->irq_lock);
286c26448c4SGary King }
287c26448c4SGary King 
288c26448c4SGary King static irqreturn_t tps6586x_irq(int irq, void *data)
289c26448c4SGary King {
290c26448c4SGary King 	struct tps6586x *tps6586x = data;
291c26448c4SGary King 	u32 acks;
292c26448c4SGary King 	int ret = 0;
293c26448c4SGary King 
294c26448c4SGary King 	ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
295c26448c4SGary King 			     sizeof(acks), (uint8_t *)&acks);
296c26448c4SGary King 
297c26448c4SGary King 	if (ret < 0) {
298c26448c4SGary King 		dev_err(tps6586x->dev, "failed to read interrupt status\n");
299c26448c4SGary King 		return IRQ_NONE;
300c26448c4SGary King 	}
301c26448c4SGary King 
302c26448c4SGary King 	acks = le32_to_cpu(acks);
303c26448c4SGary King 
304c26448c4SGary King 	while (acks) {
305c26448c4SGary King 		int i = __ffs(acks);
306c26448c4SGary King 
307c26448c4SGary King 		if (tps6586x->irq_en & (1 << i))
308c26448c4SGary King 			handle_nested_irq(tps6586x->irq_base + i);
309c26448c4SGary King 
310c26448c4SGary King 		acks &= ~(1 << i);
311c26448c4SGary King 	}
312c26448c4SGary King 
313c26448c4SGary King 	return IRQ_HANDLED;
314c26448c4SGary King }
315c26448c4SGary King 
316c26448c4SGary King static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
317c26448c4SGary King 				       int irq_base)
318c26448c4SGary King {
319c26448c4SGary King 	int i, ret;
320c26448c4SGary King 	u8 tmp[4];
321c26448c4SGary King 
322c26448c4SGary King 	if (!irq_base) {
323c26448c4SGary King 		dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n");
324c26448c4SGary King 		return -EINVAL;
325c26448c4SGary King 	}
326c26448c4SGary King 
327c26448c4SGary King 	mutex_init(&tps6586x->irq_lock);
328c26448c4SGary King 	for (i = 0; i < 5; i++) {
329c26448c4SGary King 		tps6586x->mask_reg[i] = 0xff;
330c26448c4SGary King 		tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff);
331c26448c4SGary King 	}
332c26448c4SGary King 
333c26448c4SGary King 	tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp);
334c26448c4SGary King 
335c26448c4SGary King 	tps6586x->irq_base = irq_base;
336c26448c4SGary King 
337c26448c4SGary King 	tps6586x->irq_chip.name = "tps6586x";
33896e824bdSMark Brown 	tps6586x->irq_chip.irq_enable = tps6586x_irq_enable;
33996e824bdSMark Brown 	tps6586x->irq_chip.irq_disable = tps6586x_irq_disable;
34096e824bdSMark Brown 	tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock;
34196e824bdSMark Brown 	tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock;
342c26448c4SGary King 
343c26448c4SGary King 	for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
344c26448c4SGary King 		int __irq = i + tps6586x->irq_base;
345d5bb1221SThomas Gleixner 		irq_set_chip_data(__irq, tps6586x);
346d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
347c26448c4SGary King 					 handle_simple_irq);
348d5bb1221SThomas Gleixner 		irq_set_nested_thread(__irq, 1);
349c26448c4SGary King #ifdef CONFIG_ARM
350c26448c4SGary King 		set_irq_flags(__irq, IRQF_VALID);
351c26448c4SGary King #endif
352c26448c4SGary King 	}
353c26448c4SGary King 
354c26448c4SGary King 	ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT,
355c26448c4SGary King 				   "tps6586x", tps6586x);
356c26448c4SGary King 
357c26448c4SGary King 	if (!ret) {
358c26448c4SGary King 		device_init_wakeup(tps6586x->dev, 1);
359c26448c4SGary King 		enable_irq_wake(irq);
360c26448c4SGary King 	}
361c26448c4SGary King 
362c26448c4SGary King 	return ret;
363c26448c4SGary King }
364c26448c4SGary King 
365c6c19332SMike Rapoport static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
366c6c19332SMike Rapoport 					  struct tps6586x_platform_data *pdata)
367c6c19332SMike Rapoport {
368c6c19332SMike Rapoport 	struct tps6586x_subdev_info *subdev;
369c6c19332SMike Rapoport 	struct platform_device *pdev;
370c6c19332SMike Rapoport 	int i, ret = 0;
371c6c19332SMike Rapoport 
372c6c19332SMike Rapoport 	for (i = 0; i < pdata->num_subdevs; i++) {
373c6c19332SMike Rapoport 		subdev = &pdata->subdevs[i];
374c6c19332SMike Rapoport 
375c6c19332SMike Rapoport 		pdev = platform_device_alloc(subdev->name, subdev->id);
376929980abSAxel Lin 		if (!pdev) {
377929980abSAxel Lin 			ret = -ENOMEM;
378929980abSAxel Lin 			goto failed;
379929980abSAxel Lin 		}
380c6c19332SMike Rapoport 
381c6c19332SMike Rapoport 		pdev->dev.parent = tps6586x->dev;
382c6c19332SMike Rapoport 		pdev->dev.platform_data = subdev->platform_data;
38362f6b087SThierry Reding 		pdev->dev.of_node = subdev->of_node;
384c6c19332SMike Rapoport 
385c6c19332SMike Rapoport 		ret = platform_device_add(pdev);
386929980abSAxel Lin 		if (ret) {
387929980abSAxel Lin 			platform_device_put(pdev);
388c6c19332SMike Rapoport 			goto failed;
389c6c19332SMike Rapoport 		}
390929980abSAxel Lin 	}
391c6c19332SMike Rapoport 	return 0;
392c6c19332SMike Rapoport 
393c6c19332SMike Rapoport failed:
394c6c19332SMike Rapoport 	tps6586x_remove_subdevs(tps6586x);
395c6c19332SMike Rapoport 	return ret;
396c6c19332SMike Rapoport }
397c6c19332SMike Rapoport 
39862f6b087SThierry Reding #ifdef CONFIG_OF
39962f6b087SThierry Reding static struct of_regulator_match tps6586x_matches[] = {
40062f6b087SThierry Reding 	{ .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
40162f6b087SThierry Reding 	{ .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
40262f6b087SThierry Reding 	{ .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
40362f6b087SThierry Reding 	{ .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
40462f6b087SThierry Reding 	{ .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
40562f6b087SThierry Reding 	{ .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
40662f6b087SThierry Reding 	{ .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
40762f6b087SThierry Reding 	{ .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
40862f6b087SThierry Reding 	{ .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
40962f6b087SThierry Reding 	{ .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
41062f6b087SThierry Reding 	{ .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
41162f6b087SThierry Reding 	{ .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
41262f6b087SThierry Reding 	{ .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
41362f6b087SThierry Reding 	{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
41462f6b087SThierry Reding };
41562f6b087SThierry Reding 
41662f6b087SThierry Reding static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
41762f6b087SThierry Reding {
41862f6b087SThierry Reding 	const unsigned int num = ARRAY_SIZE(tps6586x_matches);
41962f6b087SThierry Reding 	struct device_node *np = client->dev.of_node;
42062f6b087SThierry Reding 	struct tps6586x_platform_data *pdata;
42162f6b087SThierry Reding 	struct tps6586x_subdev_info *devs;
42262f6b087SThierry Reding 	struct device_node *regs;
42362f6b087SThierry Reding 	unsigned int count;
42462f6b087SThierry Reding 	unsigned int i, j;
42562f6b087SThierry Reding 	int err;
42662f6b087SThierry Reding 
42762f6b087SThierry Reding 	regs = of_find_node_by_name(np, "regulators");
42862f6b087SThierry Reding 	if (!regs)
42962f6b087SThierry Reding 		return NULL;
43062f6b087SThierry Reding 
43162f6b087SThierry Reding 	err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
43262f6b087SThierry Reding 	if (err < 0) {
43362f6b087SThierry Reding 		of_node_put(regs);
43462f6b087SThierry Reding 		return NULL;
43562f6b087SThierry Reding 	}
43662f6b087SThierry Reding 
43762f6b087SThierry Reding 	of_node_put(regs);
43862f6b087SThierry Reding 	count = err;
43962f6b087SThierry Reding 
44062f6b087SThierry Reding 	devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
44162f6b087SThierry Reding 	if (!devs)
44262f6b087SThierry Reding 		return NULL;
44362f6b087SThierry Reding 
44462f6b087SThierry Reding 	for (i = 0, j = 0; i < num && j < count; i++) {
44562f6b087SThierry Reding 		if (!tps6586x_matches[i].init_data)
44662f6b087SThierry Reding 			continue;
44762f6b087SThierry Reding 
44862f6b087SThierry Reding 		devs[j].name = "tps6586x-regulator";
44962f6b087SThierry Reding 		devs[j].platform_data = tps6586x_matches[i].init_data;
45062f6b087SThierry Reding 		devs[j].id = (int)tps6586x_matches[i].driver_data;
45162f6b087SThierry Reding 		devs[j].of_node = tps6586x_matches[i].of_node;
45262f6b087SThierry Reding 		j++;
45362f6b087SThierry Reding 	}
45462f6b087SThierry Reding 
45562f6b087SThierry Reding 	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
45662f6b087SThierry Reding 	if (!pdata)
45762f6b087SThierry Reding 		return NULL;
45862f6b087SThierry Reding 
45962f6b087SThierry Reding 	pdata->num_subdevs = count;
46062f6b087SThierry Reding 	pdata->subdevs = devs;
46162f6b087SThierry Reding 	pdata->gpio_base = -1;
46262f6b087SThierry Reding 	pdata->irq_base = -1;
46362f6b087SThierry Reding 
46462f6b087SThierry Reding 	return pdata;
46562f6b087SThierry Reding }
46662f6b087SThierry Reding 
46762f6b087SThierry Reding static struct of_device_id tps6586x_of_match[] = {
46862f6b087SThierry Reding 	{ .compatible = "ti,tps6586x", },
46962f6b087SThierry Reding 	{ },
47062f6b087SThierry Reding };
47162f6b087SThierry Reding #else
47262f6b087SThierry Reding static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
47362f6b087SThierry Reding {
47462f6b087SThierry Reding 	return NULL;
47562f6b087SThierry Reding }
47662f6b087SThierry Reding #endif
47762f6b087SThierry Reding 
47875edd5afSLaxman Dewangan static bool is_volatile_reg(struct device *dev, unsigned int reg)
47975edd5afSLaxman Dewangan {
48075edd5afSLaxman Dewangan 	/* Cache all interrupt mask register */
48175edd5afSLaxman Dewangan 	if ((reg >= TPS6586X_INT_MASK1) && (reg <= TPS6586X_INT_MASK5))
48275edd5afSLaxman Dewangan 		return false;
48375edd5afSLaxman Dewangan 
48475edd5afSLaxman Dewangan 	return true;
48575edd5afSLaxman Dewangan }
48675edd5afSLaxman Dewangan 
4871176b5beSLaxman Dewangan static const struct regmap_config tps6586x_regmap_config = {
4881176b5beSLaxman Dewangan 	.reg_bits = 8,
4891176b5beSLaxman Dewangan 	.val_bits = 8,
4901176b5beSLaxman Dewangan 	.max_register = TPS6586X_MAX_REGISTER - 1,
49175edd5afSLaxman Dewangan 	.volatile_reg = is_volatile_reg,
49275edd5afSLaxman Dewangan 	.cache_type = REGCACHE_RBTREE,
4931176b5beSLaxman Dewangan };
4941176b5beSLaxman Dewangan 
495c6c19332SMike Rapoport static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
496c6c19332SMike Rapoport 					const struct i2c_device_id *id)
497c6c19332SMike Rapoport {
498c6c19332SMike Rapoport 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
499c6c19332SMike Rapoport 	struct tps6586x *tps6586x;
500c6c19332SMike Rapoport 	int ret;
501c6c19332SMike Rapoport 
50262f6b087SThierry Reding 	if (!pdata && client->dev.of_node)
50362f6b087SThierry Reding 		pdata = tps6586x_parse_dt(client);
50462f6b087SThierry Reding 
505c6c19332SMike Rapoport 	if (!pdata) {
506c6c19332SMike Rapoport 		dev_err(&client->dev, "tps6586x requires platform data\n");
507c6c19332SMike Rapoport 		return -ENOTSUPP;
508c6c19332SMike Rapoport 	}
509c6c19332SMike Rapoport 
510c6c19332SMike Rapoport 	ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
511c6c19332SMike Rapoport 	if (ret < 0) {
512c6c19332SMike Rapoport 		dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
513c6c19332SMike Rapoport 		return -EIO;
514c6c19332SMike Rapoport 	}
515c6c19332SMike Rapoport 
5164d1cdbf6SStephen Warren 	dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
517c6c19332SMike Rapoport 
518b6719412SLaxman Dewangan 	tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
519b6719412SLaxman Dewangan 	if (tps6586x == NULL) {
520b6719412SLaxman Dewangan 		dev_err(&client->dev, "memory for tps6586x alloc failed\n");
521c6c19332SMike Rapoport 		return -ENOMEM;
522b6719412SLaxman Dewangan 	}
523c6c19332SMike Rapoport 
524c6c19332SMike Rapoport 	tps6586x->client = client;
525c6c19332SMike Rapoport 	tps6586x->dev = &client->dev;
526c6c19332SMike Rapoport 	i2c_set_clientdata(client, tps6586x);
527c6c19332SMike Rapoport 
5281176b5beSLaxman Dewangan 	tps6586x->regmap = devm_regmap_init_i2c(client,
5291176b5beSLaxman Dewangan 					&tps6586x_regmap_config);
5301176b5beSLaxman Dewangan 	if (IS_ERR(tps6586x->regmap)) {
5311176b5beSLaxman Dewangan 		ret = PTR_ERR(tps6586x->regmap);
5321176b5beSLaxman Dewangan 		dev_err(&client->dev, "regmap init failed: %d\n", ret);
5331176b5beSLaxman Dewangan 		return ret;
5341176b5beSLaxman Dewangan 	}
5351176b5beSLaxman Dewangan 
536c6c19332SMike Rapoport 
537c26448c4SGary King 	if (client->irq) {
538c26448c4SGary King 		ret = tps6586x_irq_init(tps6586x, client->irq,
539c26448c4SGary King 					pdata->irq_base);
540c26448c4SGary King 		if (ret) {
541c26448c4SGary King 			dev_err(&client->dev, "IRQ init failed: %d\n", ret);
542b6719412SLaxman Dewangan 			return ret;
543c26448c4SGary King 		}
544c26448c4SGary King 	}
545c26448c4SGary King 
5466f9f13bfSVincent Palatin 	ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base);
5476f9f13bfSVincent Palatin 	if (ret) {
5486f9f13bfSVincent Palatin 		dev_err(&client->dev, "GPIO registration failed: %d\n", ret);
5496f9f13bfSVincent Palatin 		goto err_gpio_init;
5506f9f13bfSVincent Palatin 	}
5516f9f13bfSVincent Palatin 
552c6c19332SMike Rapoport 	ret = tps6586x_add_subdevs(tps6586x, pdata);
553c6c19332SMike Rapoport 	if (ret) {
554c6c19332SMike Rapoport 		dev_err(&client->dev, "add devices failed: %d\n", ret);
555c6c19332SMike Rapoport 		goto err_add_devs;
556c6c19332SMike Rapoport 	}
557c6c19332SMike Rapoport 
558c6c19332SMike Rapoport 	return 0;
559c6c19332SMike Rapoport 
560c6c19332SMike Rapoport err_add_devs:
5616f9f13bfSVincent Palatin 	if (pdata->gpio_base) {
5626f9f13bfSVincent Palatin 		ret = gpiochip_remove(&tps6586x->gpio);
5636f9f13bfSVincent Palatin 		if (ret)
5646f9f13bfSVincent Palatin 			dev_err(&client->dev, "Can't remove gpio chip: %d\n",
5656f9f13bfSVincent Palatin 				ret);
5666f9f13bfSVincent Palatin 	}
5676f9f13bfSVincent Palatin err_gpio_init:
568c26448c4SGary King 	if (client->irq)
569c26448c4SGary King 		free_irq(client->irq, tps6586x);
570b6719412SLaxman Dewangan 
571c6c19332SMike Rapoport 	return ret;
572c6c19332SMike Rapoport }
573c6c19332SMike Rapoport 
574c6c19332SMike Rapoport static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
575c6c19332SMike Rapoport {
5764b751cf5SAxel Lin 	struct tps6586x *tps6586x = i2c_get_clientdata(client);
5774b751cf5SAxel Lin 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
5784b751cf5SAxel Lin 	int ret;
5794b751cf5SAxel Lin 
580c26448c4SGary King 	if (client->irq)
581c26448c4SGary King 		free_irq(client->irq, tps6586x);
582c26448c4SGary King 
5834b751cf5SAxel Lin 	if (pdata->gpio_base) {
5844b751cf5SAxel Lin 		ret = gpiochip_remove(&tps6586x->gpio);
5854b751cf5SAxel Lin 		if (ret)
5864b751cf5SAxel Lin 			dev_err(&client->dev, "Can't remove gpio chip: %d\n",
5874b751cf5SAxel Lin 				ret);
5884b751cf5SAxel Lin 	}
5894b751cf5SAxel Lin 
5904b751cf5SAxel Lin 	tps6586x_remove_subdevs(tps6586x);
591c6c19332SMike Rapoport 	return 0;
592c6c19332SMike Rapoport }
593c6c19332SMike Rapoport 
594c6c19332SMike Rapoport static const struct i2c_device_id tps6586x_id_table[] = {
595c6c19332SMike Rapoport 	{ "tps6586x", 0 },
596c6c19332SMike Rapoport 	{ },
597c6c19332SMike Rapoport };
598c6c19332SMike Rapoport MODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
599c6c19332SMike Rapoport 
600c6c19332SMike Rapoport static struct i2c_driver tps6586x_driver = {
601c6c19332SMike Rapoport 	.driver	= {
602c6c19332SMike Rapoport 		.name	= "tps6586x",
603c6c19332SMike Rapoport 		.owner	= THIS_MODULE,
60462f6b087SThierry Reding 		.of_match_table = of_match_ptr(tps6586x_of_match),
605c6c19332SMike Rapoport 	},
606c6c19332SMike Rapoport 	.probe		= tps6586x_i2c_probe,
607c6c19332SMike Rapoport 	.remove		= __devexit_p(tps6586x_i2c_remove),
608c6c19332SMike Rapoport 	.id_table	= tps6586x_id_table,
609c6c19332SMike Rapoport };
610c6c19332SMike Rapoport 
611c6c19332SMike Rapoport static int __init tps6586x_init(void)
612c6c19332SMike Rapoport {
613c6c19332SMike Rapoport 	return i2c_add_driver(&tps6586x_driver);
614c6c19332SMike Rapoport }
615c6c19332SMike Rapoport subsys_initcall(tps6586x_init);
616c6c19332SMike Rapoport 
617c6c19332SMike Rapoport static void __exit tps6586x_exit(void)
618c6c19332SMike Rapoport {
619c6c19332SMike Rapoport 	i2c_del_driver(&tps6586x_driver);
620c6c19332SMike Rapoport }
621c6c19332SMike Rapoport module_exit(tps6586x_exit);
622c6c19332SMike Rapoport 
623c6c19332SMike Rapoport MODULE_DESCRIPTION("TPS6586X core driver");
624c6c19332SMike Rapoport MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
625c6c19332SMike Rapoport MODULE_LICENSE("GPL");
626