aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tps65910.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
commit2dfea3803dcf70983d14ce1dcbb3e97a7459a28b (patch)
tree59bffc7389ff554585f79d7cc06021790dc2b317 /drivers/mfd/tps65910.c
parentaed606e3bc1f10753254db308d3fd8c053c41328 (diff)
parent1881b68b8961a86d40c3c5c205e533515a2dc9c6 (diff)
Merge tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFS update from Samuel Ortiz: "This is the MFD patch set for the 3.8 merge window. We have several new drivers, most of the time coming with their sub devices drivers: - Austria Microsystem's AS3711 - Nano River's viperboard - TI's TPS80031, AM335x TS/ADC, - Realtek's MMC/memstick card reader - Nokia's retu We also got some notable cleanups and improvements: - tps6586x got converted to IRQ domains. - tps65910 and tps65090 moved to the regmap IRQ API. - STMPE is now Device Tree aware. - A general twl6040 and twl-core cleanup, with moves to the regmap I/O and IRQ APIs and a conversion to the recently added PWM framework. - sta2x11 gained regmap support. Then the rest is mostly tiny cleanups and fixes, among which we have Mark's wm5xxx and wm8xxx patchset." Far amount of annoying but largely trivial conflicts. Many due to __devinit/exit removal, others due to one or two of the new drivers also having come in through another tree. * tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (119 commits) mfd: tps6507x: Convert to devm_kzalloc mfd: stmpe: Update DT support for stmpe driver mfd: wm5102: Add readback of DSP status 3 register mfd: arizona: Log if we fail to create the primary IRQ domain mfd: tps80031: MFD_TPS80031 needs to select REGMAP_IRQ mfd: tps80031: Add terminating entry for tps80031_id_table mfd: sta2x11: Fix potential NULL pointer dereference in __sta2x11_mfd_mask() mfd: wm5102: Add tuning for revision B mfd: arizona: Defer patch initialistation until after first device boot mfd: tps65910: Fix wrong ack_base register mfd: tps65910: Remove unused data mfd: stmpe: Get rid of irq_invert_polarity mfd: ab8500-core: Fix invalid free of devm_ allocated data mfd: wm5102: Mark DSP memory regions as volatile mfd: wm5102: Correct default for LDO1_CONTROL_2 mfd: arizona: Register haptics devices mfd: wm8994: Make current device behaviour the default mfd: tps65090: MFD_TPS65090 needs to select REGMAP_IRQ mfd: Fix stmpe.c build when OF is not enabled mfd: jz4740-adc: Use devm_kzalloc ...
Diffstat (limited to 'drivers/mfd/tps65910.c')
-rw-r--r--drivers/mfd/tps65910.c234
1 files changed, 225 insertions, 9 deletions
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index ce054654f5bb..d79277204835 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -19,6 +19,9 @@
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/i2c.h> 21#include <linux/i2c.h>
22#include <linux/interrupt.h>
23#include <linux/irq.h>
24#include <linux/irqdomain.h>
22#include <linux/mfd/core.h> 25#include <linux/mfd/core.h>
23#include <linux/regmap.h> 26#include <linux/regmap.h>
24#include <linux/mfd/tps65910.h> 27#include <linux/mfd/tps65910.h>
@@ -50,6 +53,219 @@ static struct mfd_cell tps65910s[] = {
50}; 53};
51 54
52 55
56static const struct regmap_irq tps65911_irqs[] = {
57 /* INT_STS */
58 [TPS65911_IRQ_PWRHOLD_F] = {
59 .mask = INT_MSK_PWRHOLD_F_IT_MSK_MASK,
60 .reg_offset = 0,
61 },
62 [TPS65911_IRQ_VBAT_VMHI] = {
63 .mask = INT_MSK_VMBHI_IT_MSK_MASK,
64 .reg_offset = 0,
65 },
66 [TPS65911_IRQ_PWRON] = {
67 .mask = INT_MSK_PWRON_IT_MSK_MASK,
68 .reg_offset = 0,
69 },
70 [TPS65911_IRQ_PWRON_LP] = {
71 .mask = INT_MSK_PWRON_LP_IT_MSK_MASK,
72 .reg_offset = 0,
73 },
74 [TPS65911_IRQ_PWRHOLD_R] = {
75 .mask = INT_MSK_PWRHOLD_R_IT_MSK_MASK,
76 .reg_offset = 0,
77 },
78 [TPS65911_IRQ_HOTDIE] = {
79 .mask = INT_MSK_HOTDIE_IT_MSK_MASK,
80 .reg_offset = 0,
81 },
82 [TPS65911_IRQ_RTC_ALARM] = {
83 .mask = INT_MSK_RTC_ALARM_IT_MSK_MASK,
84 .reg_offset = 0,
85 },
86 [TPS65911_IRQ_RTC_PERIOD] = {
87 .mask = INT_MSK_RTC_PERIOD_IT_MSK_MASK,
88 .reg_offset = 0,
89 },
90
91 /* INT_STS2 */
92 [TPS65911_IRQ_GPIO0_R] = {
93 .mask = INT_MSK2_GPIO0_R_IT_MSK_MASK,
94 .reg_offset = 1,
95 },
96 [TPS65911_IRQ_GPIO0_F] = {
97 .mask = INT_MSK2_GPIO0_F_IT_MSK_MASK,
98 .reg_offset = 1,
99 },
100 [TPS65911_IRQ_GPIO1_R] = {
101 .mask = INT_MSK2_GPIO1_R_IT_MSK_MASK,
102 .reg_offset = 1,
103 },
104 [TPS65911_IRQ_GPIO1_F] = {
105 .mask = INT_MSK2_GPIO1_F_IT_MSK_MASK,
106 .reg_offset = 1,
107 },
108 [TPS65911_IRQ_GPIO2_R] = {
109 .mask = INT_MSK2_GPIO2_R_IT_MSK_MASK,
110 .reg_offset = 1,
111 },
112 [TPS65911_IRQ_GPIO2_F] = {
113 .mask = INT_MSK2_GPIO2_F_IT_MSK_MASK,
114 .reg_offset = 1,
115 },
116 [TPS65911_IRQ_GPIO3_R] = {
117 .mask = INT_MSK2_GPIO3_R_IT_MSK_MASK,
118 .reg_offset = 1,
119 },
120 [TPS65911_IRQ_GPIO3_F] = {
121 .mask = INT_MSK2_GPIO3_F_IT_MSK_MASK,
122 .reg_offset = 1,
123 },
124
125 /* INT_STS2 */
126 [TPS65911_IRQ_GPIO4_R] = {
127 .mask = INT_MSK3_GPIO4_R_IT_MSK_MASK,
128 .reg_offset = 2,
129 },
130 [TPS65911_IRQ_GPIO4_F] = {
131 .mask = INT_MSK3_GPIO4_F_IT_MSK_MASK,
132 .reg_offset = 2,
133 },
134 [TPS65911_IRQ_GPIO5_R] = {
135 .mask = INT_MSK3_GPIO5_R_IT_MSK_MASK,
136 .reg_offset = 2,
137 },
138 [TPS65911_IRQ_GPIO5_F] = {
139 .mask = INT_MSK3_GPIO5_F_IT_MSK_MASK,
140 .reg_offset = 2,
141 },
142 [TPS65911_IRQ_WTCHDG] = {
143 .mask = INT_MSK3_WTCHDG_IT_MSK_MASK,
144 .reg_offset = 2,
145 },
146 [TPS65911_IRQ_VMBCH2_H] = {
147 .mask = INT_MSK3_VMBCH2_H_IT_MSK_MASK,
148 .reg_offset = 2,
149 },
150 [TPS65911_IRQ_VMBCH2_L] = {
151 .mask = INT_MSK3_VMBCH2_L_IT_MSK_MASK,
152 .reg_offset = 2,
153 },
154 [TPS65911_IRQ_PWRDN] = {
155 .mask = INT_MSK3_PWRDN_IT_MSK_MASK,
156 .reg_offset = 2,
157 },
158};
159
160static const struct regmap_irq tps65910_irqs[] = {
161 /* INT_STS */
162 [TPS65910_IRQ_VBAT_VMBDCH] = {
163 .mask = TPS65910_INT_MSK_VMBDCH_IT_MSK_MASK,
164 .reg_offset = 0,
165 },
166 [TPS65910_IRQ_VBAT_VMHI] = {
167 .mask = TPS65910_INT_MSK_VMBHI_IT_MSK_MASK,
168 .reg_offset = 0,
169 },
170 [TPS65910_IRQ_PWRON] = {
171 .mask = TPS65910_INT_MSK_PWRON_IT_MSK_MASK,
172 .reg_offset = 0,
173 },
174 [TPS65910_IRQ_PWRON_LP] = {
175 .mask = TPS65910_INT_MSK_PWRON_LP_IT_MSK_MASK,
176 .reg_offset = 0,
177 },
178 [TPS65910_IRQ_PWRHOLD] = {
179 .mask = TPS65910_INT_MSK_PWRHOLD_IT_MSK_MASK,
180 .reg_offset = 0,
181 },
182 [TPS65910_IRQ_HOTDIE] = {
183 .mask = TPS65910_INT_MSK_HOTDIE_IT_MSK_MASK,
184 .reg_offset = 0,
185 },
186 [TPS65910_IRQ_RTC_ALARM] = {
187 .mask = TPS65910_INT_MSK_RTC_ALARM_IT_MSK_MASK,
188 .reg_offset = 0,
189 },
190 [TPS65910_IRQ_RTC_PERIOD] = {
191 .mask = TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_MASK,
192 .reg_offset = 0,
193 },
194
195 /* INT_STS2 */
196 [TPS65910_IRQ_GPIO_R] = {
197 .mask = TPS65910_INT_MSK2_GPIO0_F_IT_MSK_MASK,
198 .reg_offset = 1,
199 },
200 [TPS65910_IRQ_GPIO_F] = {
201 .mask = TPS65910_INT_MSK2_GPIO0_R_IT_MSK_MASK,
202 .reg_offset = 1,
203 },
204};
205
206static struct regmap_irq_chip tps65911_irq_chip = {
207 .name = "tps65910",
208 .irqs = tps65911_irqs,
209 .num_irqs = ARRAY_SIZE(tps65911_irqs),
210 .num_regs = 3,
211 .irq_reg_stride = 2,
212 .status_base = TPS65910_INT_STS,
213 .mask_base = TPS65910_INT_MSK,
214 .ack_base = TPS65910_INT_STS,
215};
216
217static struct regmap_irq_chip tps65910_irq_chip = {
218 .name = "tps65910",
219 .irqs = tps65910_irqs,
220 .num_irqs = ARRAY_SIZE(tps65910_irqs),
221 .num_regs = 2,
222 .irq_reg_stride = 2,
223 .status_base = TPS65910_INT_STS,
224 .mask_base = TPS65910_INT_MSK,
225 .ack_base = TPS65910_INT_STS,
226};
227
228static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
229 struct tps65910_platform_data *pdata)
230{
231 int ret = 0;
232 static struct regmap_irq_chip *tps6591x_irqs_chip;
233
234 if (!irq) {
235 dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
236 return -EINVAL;
237 }
238
239 if (!pdata) {
240 dev_warn(tps65910->dev, "No interrupt support, no pdata\n");
241 return -EINVAL;
242 }
243
244 switch (tps65910_chip_id(tps65910)) {
245 case TPS65910:
246 tps6591x_irqs_chip = &tps65910_irq_chip;
247 break;
248 case TPS65911:
249 tps6591x_irqs_chip = &tps65911_irq_chip;
250 break;
251 }
252
253 tps65910->chip_irq = irq;
254 ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq,
255 IRQF_ONESHOT, pdata->irq_base,
256 tps6591x_irqs_chip, &tps65910->irq_data);
257 if (ret < 0)
258 dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);
259 return ret;
260}
261
262static int tps65910_irq_exit(struct tps65910 *tps65910)
263{
264 if (tps65910->chip_irq > 0)
265 regmap_del_irq_chip(tps65910->chip_irq, tps65910->irq_data);
266 return 0;
267}
268
53static bool is_volatile_reg(struct device *dev, unsigned int reg) 269static bool is_volatile_reg(struct device *dev, unsigned int reg)
54{ 270{
55 struct tps65910 *tps65910 = dev_get_drvdata(dev); 271 struct tps65910 *tps65910 = dev_get_drvdata(dev);
@@ -270,7 +486,6 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
270 tps65910->dev = &i2c->dev; 486 tps65910->dev = &i2c->dev;
271 tps65910->i2c_client = i2c; 487 tps65910->i2c_client = i2c;
272 tps65910->id = chip_id; 488 tps65910->id = chip_id;
273 mutex_init(&tps65910->io_mutex);
274 489
275 tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config); 490 tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config);
276 if (IS_ERR(tps65910->regmap)) { 491 if (IS_ERR(tps65910->regmap)) {
@@ -279,14 +494,6 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
279 return ret; 494 return ret;
280 } 495 }
281 496
282 ret = mfd_add_devices(tps65910->dev, -1,
283 tps65910s, ARRAY_SIZE(tps65910s),
284 NULL, 0, NULL);
285 if (ret < 0) {
286 dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
287 return ret;
288 }
289
290 init_data->irq = pmic_plat_data->irq; 497 init_data->irq = pmic_plat_data->irq;
291 init_data->irq_base = pmic_plat_data->irq_base; 498 init_data->irq_base = pmic_plat_data->irq_base;
292 499
@@ -299,6 +506,15 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
299 pm_power_off = tps65910_power_off; 506 pm_power_off = tps65910_power_off;
300 } 507 }
301 508
509 ret = mfd_add_devices(tps65910->dev, -1,
510 tps65910s, ARRAY_SIZE(tps65910s),
511 NULL, 0,
512 regmap_irq_get_domain(tps65910->irq_data));
513 if (ret < 0) {
514 dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
515 return ret;
516 }
517
302 return ret; 518 return ret;
303} 519}
304 520