aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMarc Reilly <marc@cpdesign.com.au>2012-04-01 02:41:39 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-01 06:35:41 -0400
commitdf3df6469fd1e59284d6b5d4dd9dbe1bd7861040 (patch)
tree1864a53128e4ec8488118d49171ae6818442b963 /drivers/mfd
parenta0c7c1d48ea9f53c67c79eda498bb8eda1422748 (diff)
mfd: Add mc13xxx i2c driver
Adds support for mc13xxx family ICs connected via i2c. Signed-off-by: Marc Reilly <marc@cpdesign.com.au> Acked-by: Oskar Schirmer <oskar@scara.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/mc13xxx-i2c.c128
3 files changed, 137 insertions, 1 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 9c8294c26efb..ef86a741b7e2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -597,7 +597,7 @@ config MFD_MC13783
597 597
598config MFD_MC13XXX 598config MFD_MC13XXX
599 tristate "Support Freescale MC13783 and MC13892" 599 tristate "Support Freescale MC13783 and MC13892"
600 depends on SPI_MASTER 600 depends on SPI_MASTER || I2C
601 select MFD_CORE 601 select MFD_CORE
602 select MFD_MC13783 602 select MFD_MC13783
603 help 603 help
@@ -615,6 +615,13 @@ config MFD_MC13XXX_SPI
615 help 615 help
616 Select this if your MC13xxx is connected via an SPI bus. 616 Select this if your MC13xxx is connected via an SPI bus.
617 617
618config MFD_MC13XXX_I2C
619 tristate "MC13xxx I2C interface" if I2C
620 default I2C
621 select REGMAP_I2C
622 help
623 Select this if your MC13xxx is connected via an I2C bus.
624
618endif 625endif
619 626
620config ABX500_CORE 627config ABX500_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 7ce5b5c15dee..5dd6be7aa350 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
55 55
56obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o 56obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
57obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o 57obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
58obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
58 59
59obj-$(CONFIG_MFD_CORE) += mfd-core.o 60obj-$(CONFIG_MFD_CORE) += mfd-core.o
60 61
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
new file mode 100644
index 000000000000..d22501dad6a6
--- /dev/null
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -0,0 +1,128 @@
1/*
2 * Copyright 2009-2010 Creative Product Design
3 * Marc Reilly marc@cpdesign.com.au
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 */
9
10#include <linux/slab.h>
11#include <linux/module.h>
12#include <linux/platform_device.h>
13#include <linux/mutex.h>
14#include <linux/mfd/core.h>
15#include <linux/mfd/mc13xxx.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/of_gpio.h>
19#include <linux/i2c.h>
20#include <linux/err.h>
21
22#include "mc13xxx.h"
23
24static const struct i2c_device_id mc13xxx_i2c_device_id[] = {
25 {
26 .name = "mc13892",
27 .driver_data = MC13XXX_ID_MC13892,
28 }, {
29 /* sentinel */
30 }
31};
32MODULE_DEVICE_TABLE(i2c, mc13xxx_i2c_device_id);
33
34static const struct of_device_id mc13xxx_dt_ids[] = {
35 {
36 .compatible = "fsl,mc13892",
37 .data = (void *) &mc13xxx_i2c_device_id[0],
38 }, {
39 /* sentinel */
40 }
41};
42MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
43
44static struct regmap_config mc13xxx_regmap_i2c_config = {
45 .reg_bits = 8,
46 .val_bits = 24,
47
48 .max_register = MC13XXX_NUMREGS,
49
50 .cache_type = REGCACHE_NONE,
51};
52
53static int mc13xxx_i2c_probe(struct i2c_client *client,
54 const struct i2c_device_id *id)
55{
56 const struct of_device_id *of_id;
57 struct i2c_driver *idrv = to_i2c_driver(client->dev.driver);
58 struct mc13xxx *mc13xxx;
59 struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev);
60 int ret;
61
62 of_id = of_match_device(mc13xxx_dt_ids, &client->dev);
63 if (of_id)
64 idrv->id_table = (const struct i2c_device_id*) of_id->data;
65
66 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
67 if (!mc13xxx)
68 return -ENOMEM;
69
70 dev_set_drvdata(&client->dev, mc13xxx);
71
72 mc13xxx->dev = &client->dev;
73 mutex_init(&mc13xxx->lock);
74
75 mc13xxx->regmap = regmap_init_i2c(client, &mc13xxx_regmap_i2c_config);
76 if (IS_ERR(mc13xxx->regmap)) {
77 ret = PTR_ERR(mc13xxx->regmap);
78 dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
79 ret);
80 dev_set_drvdata(&client->dev, NULL);
81 kfree(mc13xxx);
82 return ret;
83 }
84
85 ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
86
87 if (ret == 0 && (id->driver_data != mc13xxx->ictype))
88 dev_warn(mc13xxx->dev,
89 "device id doesn't match auto detection!\n");
90
91 return ret;
92}
93
94static int __devexit mc13xxx_i2c_remove(struct i2c_client *client)
95{
96 struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
97
98 mc13xxx_common_cleanup(mc13xxx);
99
100 return 0;
101}
102
103static struct i2c_driver mc13xxx_i2c_driver = {
104 .id_table = mc13xxx_i2c_device_id,
105 .driver = {
106 .owner = THIS_MODULE,
107 .name = "mc13xxx",
108 .of_match_table = mc13xxx_dt_ids,
109 },
110 .probe = mc13xxx_i2c_probe,
111 .remove = __devexit_p(mc13xxx_i2c_remove),
112};
113
114static int __init mc13xxx_i2c_init(void)
115{
116 return i2c_add_driver(&mc13xxx_i2c_driver);
117}
118subsys_initcall(mc13xxx_i2c_init);
119
120static void __exit mc13xxx_i2c_exit(void)
121{
122 i2c_del_driver(&mc13xxx_i2c_driver);
123}
124module_exit(mc13xxx_i2c_exit);
125
126MODULE_DESCRIPTION("i2c driver for Freescale MC13XXX PMIC");
127MODULE_AUTHOR("Marc Reilly <marc@cpdesign.com.au");
128MODULE_LICENSE("GPL v2");