aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tps65090.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/tps65090.c')
-rw-r--r--drivers/mfd/tps65090.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
new file mode 100644
index 00000000000..080f97aa264
--- /dev/null
+++ b/drivers/mfd/tps65090.c
@@ -0,0 +1,498 @@
1/*
2 * driver/mfd/tps65090.c
3 *
4 * Core driver for TI TPS65090 PMIC family
5 *
6 * Copyright (C) 2012 NVIDIA Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include <linux/interrupt.h>
25#include <linux/irq.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/mutex.h>
29#include <linux/slab.h>
30#include <linux/i2c.h>
31
32#include <linux/mfd/core.h>
33#include <linux/mfd/tps65090.h>
34#include <linux/regmap.h>
35
36/* interrupt status registers */
37#define TPS65090_INT_STS 0x0
38#define TPS65090_INT_STS2 0x1
39
40/* interrupt mask registers */
41#define TPS65090_INT_MSK 0x2
42#define TPS65090_INT_MSK2 0x3
43
44
45enum irq_type {
46 EVENT,
47};
48
49struct tps65090_irq_data {
50 u8 mask_reg;
51 u8 mask_pos;
52 enum irq_type type;
53};
54
55#define TPS65090_IRQ(_reg, _mask_pos, _type) \
56 { \
57 .mask_reg = (_reg), \
58 .mask_pos = (_mask_pos), \
59 .type = (_type), \
60 }
61
62static const struct tps65090_irq_data tps65090_irqs[] = {
63 [0] = TPS65090_IRQ(0, 0, EVENT),
64 [1] = TPS65090_IRQ(0, 1, EVENT),
65 [2] = TPS65090_IRQ(0, 2, EVENT),
66 [3] = TPS65090_IRQ(0, 3, EVENT),
67 [4] = TPS65090_IRQ(0, 4, EVENT),
68 [5] = TPS65090_IRQ(0, 5, EVENT),
69 [6] = TPS65090_IRQ(0, 6, EVENT),
70 [7] = TPS65090_IRQ(0, 7, EVENT),
71 [8] = TPS65090_IRQ(1, 0, EVENT),
72 [9] = TPS65090_IRQ(1, 1, EVENT),
73 [10] = TPS65090_IRQ(1, 2, EVENT),
74 [11] = TPS65090_IRQ(1, 3, EVENT),
75 [12] = TPS65090_IRQ(1, 4, EVENT),
76 [13] = TPS65090_IRQ(1, 5, EVENT),
77 [14] = TPS65090_IRQ(1, 6, EVENT),
78 [15] = TPS65090_IRQ(1, 7, EVENT),
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 u32 irq_en;
90 u8 mask_cache[2];
91 u8 mask_reg[2];
92};
93int tps65090_write(struct device *dev, int reg, uint8_t val)
94{
95 struct tps65090 *tps = dev_get_drvdata(dev);
96 return regmap_write(tps->rmap, reg, val);
97}
98int tps65090_read(struct device *dev, int reg, uint8_t *val)
99{
100 int rval, ret = 0;
101 struct tps65090 *tps = dev_get_drvdata(dev);
102 ret = regmap_read(tps->rmap, reg, &rval);
103 *val = rval;
104 return 0;
105}
106EXPORT_SYMBOL_GPL(tps65090_read);
107
108int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
109{
110 struct tps65090 *tps = dev_get_drvdata(dev);
111 return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), ~0u);
112
113}
114EXPORT_SYMBOL_GPL(tps65090_set_bits);
115
116int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
117{
118 struct tps65090 *tps = dev_get_drvdata(dev);
119 return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), 0u);
120}
121EXPORT_SYMBOL_GPL(tps65090_clr_bits);
122
123static int __remove_subdev(struct device *dev, void *unused)
124{
125 platform_device_unregister(to_platform_device(dev));
126 return 0;
127}
128
129static int tps65090_remove_subdevs(struct tps65090 *tps65090)
130{
131 return device_for_each_child(tps65090->dev, NULL, __remove_subdev);
132}
133
134static void tps65090_irq_lock(struct irq_data *data)
135{
136 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
137
138 mutex_lock(&tps65090->irq_lock);
139}
140
141static void tps65090_irq_mask(struct irq_data *irq_data)
142{
143 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
144 unsigned int __irq = irq_data->irq - tps65090->irq_base;
145 const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
146
147 if (data->type == EVENT)
148 tps65090->mask_reg[data->mask_reg] |= (1 << data->mask_pos);
149 else
150 tps65090->mask_reg[data->mask_reg] |= (3 << data->mask_pos);
151
152 tps65090->irq_en &= ~(1 << __irq);
153}
154
155static void tps65090_irq_unmask(struct irq_data *irq_data)
156{
157 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
158
159 unsigned int __irq = irq_data->irq - tps65090->irq_base;
160 const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
161
162 if (data->type == EVENT) {
163 tps65090->mask_reg[data->mask_reg] &= ~(1 << data->mask_pos);
164 tps65090->irq_en |= (1 << __irq);
165 }
166}
167
168static void tps65090_irq_sync_unlock(struct irq_data *data)
169{
170 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
171 int i;
172
173 for (i = 0; i < ARRAY_SIZE(tps65090->mask_reg); i++) {
174 if (tps65090->mask_reg[i] != tps65090->mask_cache[i]) {
175 if (!WARN_ON(tps65090_write(tps65090->dev,
176 TPS65090_INT_MSK + 2*i,
177 tps65090->mask_reg[i])))
178 tps65090->mask_cache[i] = tps65090->mask_reg[i];
179 }
180 }
181
182 mutex_unlock(&tps65090->irq_lock);
183}
184
185static int tps65090_irq_set_type(struct irq_data *irq_data, unsigned int type)
186{
187 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
188
189 unsigned int __irq = irq_data->irq - tps65090->irq_base;
190 const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
191
192 if (data->type != EVENT) /* add support for GPIO, if needed */
193 return -EINVAL;
194
195 return 0;
196}
197
198static irqreturn_t tps65090_irq(int irq, void *data)
199{
200 struct tps65090 *tps65090 = data;
201 int ret = 0;
202 u8 tmp[3];
203 u8 int_ack;
204 u32 acks, mask = 0;
205 int i;
206
207 for (i = 0; i < 3; i++) {
208 ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + 2*i,
209 &tmp[i]);
210 if (ret < 0) {
211 dev_err(tps65090->dev,
212 "failed to read interrupt status\n");
213 return IRQ_NONE;
214 }
215 if (tmp[i]) {
216 /* Ack only those interrupts which are enabled */
217 int_ack = tmp[i] & (~(tps65090->mask_cache[i]));
218 ret = tps65090_write(tps65090->dev,
219 TPS65090_INT_STS + 2*i, int_ack);
220 if (ret < 0) {
221 dev_err(tps65090->dev,
222 "failed to write interrupt status\n");
223 return IRQ_NONE;
224 }
225 }
226 }
227
228 acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
229
230 for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
231 if (tps65090_irqs[i].type == EVENT)
232 mask = (1 << (tps65090_irqs[i].mask_pos
233 + tps65090_irqs[i].mask_reg*8));
234 else
235 return -EINVAL;
236 if ((acks & mask) && (tps65090->irq_en & (1 << i)))
237 handle_nested_irq(tps65090->irq_base + i);
238 }
239 return IRQ_HANDLED;
240}
241
242static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
243 int irq_base)
244{
245 int i, ret;
246
247 if (!irq_base) {
248 dev_warn(tps65090->dev, "No interrupt support on IRQ base\n");
249 return -EINVAL;
250 }
251
252 mutex_init(&tps65090->irq_lock);
253
254 tps65090->mask_reg[0] = 0xFF;
255 tps65090->mask_reg[1] = 0xFF;
256 for (i = 0; i < 2; i++) {
257 tps65090->mask_cache[i] = tps65090->mask_reg[i];
258 tps65090_write(tps65090->dev, TPS65090_INT_MSK + i,
259 tps65090->mask_cache[i]);
260 }
261
262 for (i = 0; i < 2; i++)
263 tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
264
265 tps65090->irq_base = irq_base;
266
267 tps65090->irq_chip.name = "tps65090";
268 tps65090->irq_chip.irq_mask = tps65090_irq_mask;
269 tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
270 tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
271 tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
272 tps65090->irq_chip.irq_set_type = tps65090_irq_set_type;
273
274 for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
275 int __irq = i + tps65090->irq_base;
276 irq_set_chip_data(__irq, tps65090);
277 irq_set_chip_and_handler(__irq, &tps65090->irq_chip,
278 handle_simple_irq);
279 irq_set_nested_thread(__irq, 1);
280#ifdef CONFIG_ARM
281 set_irq_flags(__irq, IRQF_VALID);
282#endif
283 }
284
285 ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT,
286 "tps65090", tps65090);
287 if (!ret) {
288 device_init_wakeup(tps65090->dev, 1);
289 enable_irq_wake(irq);
290 }
291
292 return ret;
293}
294
295static int __devinit tps65090_add_subdevs(struct tps65090 *tps65090,
296 struct tps65090_platform_data *pdata)
297{
298 struct tps65090_subdev_info *subdev;
299 struct platform_device *pdev;
300 int i, ret = 0;
301
302 for (i = 0; i < pdata->num_subdevs; i++) {
303 subdev = &pdata->subdevs[i];
304
305 pdev = platform_device_alloc(subdev->name, subdev->id);
306
307 pdev->dev.parent = tps65090->dev;
308 pdev->dev.platform_data = subdev->platform_data;
309
310 ret = platform_device_add(pdev);
311 if (ret)
312 goto failed;
313 }
314 return 0;
315
316failed:
317 tps65090_remove_subdevs(tps65090);
318 return ret;
319}
320#ifdef CONFIG_DEBUG_FS
321#include <linux/debugfs.h>
322#include <linux/seq_file.h>
323static void print_regs(const char *header, struct seq_file *s,
324 struct i2c_client *client, int start_offset,
325 int end_offset)
326{
327 int reg_val;
328 int i;
329 int ret;
330 struct tps65090 *tps = s->private;
331 seq_printf(s, "%s\n", header);
332 for (i = start_offset; i <= end_offset; ++i) {
333 ret = regmap_read(tps->rmap, i, &reg_val);
334 if (ret >= 0)
335 seq_printf(s, "Reg 0x%02x Value 0x%02x\n", i, reg_val);
336 }
337 seq_printf(s, "------------------\n");
338}
339
340static int dbg_tps_show(struct seq_file *s, void *unused)
341{
342 struct tps65090 *tps = s->private;
343 struct i2c_client *client = tps->client;
344
345 seq_printf(s, "TPS65090 Registers\n");
346 seq_printf(s, "------------------\n");
347
348 print_regs("All Regs", s, client, 0x0, 24);
349 return 0;
350}
351
352static int dbg_tps_open(struct inode *inode, struct file *file)
353{
354 return single_open(file, dbg_tps_show, inode->i_private);
355}
356
357static const struct file_operations debug_fops = {
358 .open = dbg_tps_open,
359 .read = seq_read,
360 .llseek = seq_lseek,
361 .release = single_release,
362};
363
364static void __init tps65090_debuginit(struct tps65090 *tps)
365{
366 (void)debugfs_create_file("tps65090", S_IRUGO, NULL,
367 tps, &debug_fops);
368}
369#else
370static void __init tps65090_debuginit(struct tps65090 *tpsi)
371{
372 return;
373}
374#endif
375
376static const struct regmap_config tps65090_regmap_config = {
377 .reg_bits = 8,
378 .val_bits = 8,
379};
380
381static int __devinit tps65090_i2c_probe(struct i2c_client *client,
382 const struct i2c_device_id *id)
383{
384 struct tps65090_platform_data *pdata = client->dev.platform_data;
385 struct tps65090 *tps65090;
386 int ret;
387
388 if (!pdata) {
389 dev_err(&client->dev, "tps65090 requires platform data\n");
390 return -ENOTSUPP;
391 }
392
393 tps65090 = kzalloc(sizeof(struct tps65090), GFP_KERNEL);
394 if (tps65090 == NULL)
395 return -ENOMEM;
396
397 tps65090->client = client;
398 tps65090->dev = &client->dev;
399 i2c_set_clientdata(client, tps65090);
400
401 mutex_init(&tps65090->lock);
402
403 if (client->irq) {
404 ret = tps65090_irq_init(tps65090, client->irq,
405 pdata->irq_base);
406 if (ret) {
407 dev_err(&client->dev, "IRQ init failed: %d\n", ret);
408 goto err_irq_init;
409 }
410 }
411
412 ret = tps65090_add_subdevs(tps65090, pdata);
413 if (ret) {
414 dev_err(&client->dev, "add devices failed: %d\n", ret);
415 goto err_add_devs;
416 }
417
418 tps65090->rmap = regmap_init_i2c(tps65090->client,
419 &tps65090_regmap_config);
420 if (IS_ERR(tps65090->rmap)) {
421 dev_err(&client->dev, "regmap_init failed: %ld\n",
422 PTR_ERR(tps65090->rmap));
423 goto err_add_devs;
424 };
425 tps65090_debuginit(tps65090);
426
427 return 0;
428
429err_add_devs:
430 if (client->irq)
431 free_irq(client->irq, tps65090);
432err_irq_init:
433 kfree(tps65090);
434 return ret;
435}
436
437static int __devexit tps65090_i2c_remove(struct i2c_client *client)
438{
439 struct tps65090 *tps65090 = i2c_get_clientdata(client);
440
441 if (client->irq)
442 free_irq(client->irq, tps65090);
443
444 regmap_exit(tps65090->rmap);
445 kfree(tps65090);
446 return 0;
447}
448#ifdef CONFIG_PM
449static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state)
450{
451 if (client->irq)
452 disable_irq(client->irq);
453 return 0;
454}
455
456static int tps65090_i2c_resume(struct i2c_client *client)
457{
458 if (client->irq)
459 enable_irq(client->irq);
460 return 0;
461}
462#endif
463
464
465static const struct i2c_device_id tps65090_id_table[] = {
466 { "tps65090", 0 },
467 { },
468};
469MODULE_DEVICE_TABLE(i2c, tps65090_id_table);
470
471static struct i2c_driver tps65090_driver = {
472 .driver = {
473 .name = "tps65090",
474 .owner = THIS_MODULE,
475 },
476 .probe = tps65090_i2c_probe,
477 .remove = __devexit_p(tps65090_i2c_remove),
478#ifdef CONFIG_PM
479 .suspend = tps65090_i2c_suspend,
480 .resume = tps65090_i2c_resume,
481#endif
482 .id_table = tps65090_id_table,
483};
484
485static int __init tps65090_init(void)
486{
487 return i2c_add_driver(&tps65090_driver);
488}
489subsys_initcall(tps65090_init);
490
491static void __exit tps65090_exit(void)
492{
493 i2c_del_driver(&tps65090_driver);
494}
495module_exit(tps65090_exit);
496
497MODULE_DESCRIPTION("TPS65090 core driver");
498MODULE_LICENSE("GPL");