aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig12
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/tps65090.c387
-rw-r--r--include/linux/mfd/tps65090.h46
4 files changed, 446 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ef22292aa0cd..f67d20e8bc0f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -827,6 +827,18 @@ config MFD_PM8XXX_IRQ
827config TPS65911_COMPARATOR 827config TPS65911_COMPARATOR
828 tristate 828 tristate
829 829
830config MFD_TPS65090
831 bool "TPS65090 Power Management chips"
832 depends on I2C=y && GENERIC_HARDIRQS
833 select MFD_CORE
834 select REGMAP_I2C
835 help
836 If you say yes here you get support for the TPS65090 series of
837 Power Management chips.
838 This driver provides common support for accessing the device,
839 additional drivers must be enabled in order to use the
840 functionality of the device.
841
830config MFD_AAT2870_CORE 842config MFD_AAT2870_CORE
831 bool "Support for the AnalogicTech AAT2870" 843 bool "Support for the AnalogicTech AAT2870"
832 select MFD_CORE 844 select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 67f7b0e34d37..05fa538c5efe 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
110obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o 110obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
111obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o 111obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
112obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o 112obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
113obj-$(CONFIG_MFD_TPS65090) += tps65090.o
113obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o 114obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
114obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o 115obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
115obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o 116obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
new file mode 100644
index 000000000000..a66d4df51293
--- /dev/null
+++ b/drivers/mfd/tps65090.c
@@ -0,0 +1,387 @@
1/*
2 * Core driver for TI TPS65090 PMIC family
3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
5
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/interrupt.h>
20#include <linux/irq.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/mutex.h>
24#include <linux/slab.h>
25#include <linux/i2c.h>
26#include <linux/mfd/core.h>
27#include <linux/mfd/tps65090.h>
28#include <linux/regmap.h>
29#include <linux/err.h>
30
31#define NUM_INT_REG 2
32#define TOTAL_NUM_REG 0x18
33
34/* interrupt status registers */
35#define TPS65090_INT_STS 0x0
36#define TPS65090_INT_STS2 0x1
37
38/* interrupt mask registers */
39#define TPS65090_INT_MSK 0x2
40#define TPS65090_INT_MSK2 0x3
41
42struct tps65090_irq_data {
43 u8 mask_reg;
44 u8 mask_pos;
45};
46
47#define TPS65090_IRQ(_reg, _mask_pos) \
48 { \
49 .mask_reg = (_reg), \
50 .mask_pos = (_mask_pos), \
51 }
52
53static const struct tps65090_irq_data tps65090_irqs[] = {
54 [0] = TPS65090_IRQ(0, 0),
55 [1] = TPS65090_IRQ(0, 1),
56 [2] = TPS65090_IRQ(0, 2),
57 [3] = TPS65090_IRQ(0, 3),
58 [4] = TPS65090_IRQ(0, 4),
59 [5] = TPS65090_IRQ(0, 5),
60 [6] = TPS65090_IRQ(0, 6),
61 [7] = TPS65090_IRQ(0, 7),
62 [8] = TPS65090_IRQ(1, 0),
63 [9] = TPS65090_IRQ(1, 1),
64 [10] = TPS65090_IRQ(1, 2),
65 [11] = TPS65090_IRQ(1, 3),
66 [12] = TPS65090_IRQ(1, 4),
67 [13] = TPS65090_IRQ(1, 5),
68 [14] = TPS65090_IRQ(1, 6),
69 [15] = TPS65090_IRQ(1, 7),
70};
71
72static struct mfd_cell tps65090s[] = {
73 {
74 .name = "tps65910-pmic",
75 },
76 {
77 .name = "tps65910-regulator",
78 },
79};
80
81struct tps65090 {
82 struct mutex lock;
83 struct device *dev;
84 struct i2c_client *client;
85 struct regmap *rmap;
86 struct irq_chip irq_chip;
87 struct mutex irq_lock;
88 int irq_base;
89 unsigned int id;
90};
91
92int tps65090_write(struct device *dev, int reg, uint8_t val)
93{
94 struct tps65090 *tps = dev_get_drvdata(dev);
95 return regmap_write(tps->rmap, reg, val);
96}
97EXPORT_SYMBOL_GPL(tps65090_write);
98
99int tps65090_read(struct device *dev, int reg, uint8_t *val)
100{
101 struct tps65090 *tps = dev_get_drvdata(dev);
102 unsigned int temp_val;
103 int ret;
104 ret = regmap_read(tps->rmap, reg, &temp_val);
105 if (!ret)
106 *val = temp_val;
107 return ret;
108}
109EXPORT_SYMBOL_GPL(tps65090_read);
110
111int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
112{
113 struct tps65090 *tps = dev_get_drvdata(dev);
114 return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u);
115}
116EXPORT_SYMBOL_GPL(tps65090_set_bits);
117
118int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
119{
120 struct tps65090 *tps = dev_get_drvdata(dev);
121 return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u);
122}
123EXPORT_SYMBOL_GPL(tps65090_clr_bits);
124
125static void tps65090_irq_lock(struct irq_data *data)
126{
127 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
128
129 mutex_lock(&tps65090->irq_lock);
130}
131
132static void tps65090_irq_mask(struct irq_data *irq_data)
133{
134 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
135 unsigned int __irq = irq_data->hwirq;
136 const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
137
138 tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
139 data->mask_pos);
140}
141
142static void tps65090_irq_unmask(struct irq_data *irq_data)
143{
144 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
145 unsigned int __irq = irq_data->irq - tps65090->irq_base;
146 const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
147
148 tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
149 data->mask_pos);
150}
151
152static void tps65090_irq_sync_unlock(struct irq_data *data)
153{
154 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
155
156 mutex_unlock(&tps65090->irq_lock);
157}
158
159static irqreturn_t tps65090_irq(int irq, void *data)
160{
161 struct tps65090 *tps65090 = data;
162 int ret = 0;
163 u8 status, mask;
164 unsigned long int acks = 0;
165 int i;
166