aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonghwa Lee <jonghwa3.lee@samsung.com>2012-06-25 04:34:36 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-07-08 18:16:07 -0400
commitdae8a969d512ee15e08fbec7837b9dab1777896d (patch)
tree9158b5af28aa5a5be5c9d52c1dc3ffaff782914e
parentbd0a521e88aa7a06ae7aabaed7ae196ed4ad867a (diff)
mfd: Add Maxim 77686 driver
This patch is device driver for MAX77686 chip. MAX77686 is PMIC and includes regulator and rtc on it. This driver is core of MAX77686 chip, so provides common support for accessing on-chip devices. It uses irq_domain to manage irq and regmap to read/write data to its register with i2c bus. Signed-off-by: Chiwoong Byun <woong.byun@samsung.com> Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com> Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig13
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/max77686-irq.c309
-rw-r--r--drivers/mfd/max77686.c156
-rw-r--r--include/linux/mfd/max77686-private.h247
-rw-r--r--include/linux/mfd/max77686.h117
6 files changed, 843 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index e129c820df7d..a7d0c851afc5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -422,6 +422,19 @@ config PMIC_ADP5520
422 individual components like LCD backlight, LEDs, GPIOs and Kepad 422 individual components like LCD backlight, LEDs, GPIOs and Kepad
423 under the corresponding menus. 423 under the corresponding menus.
424 424
425config MFD_MAX77686
426 bool "Maxim Semiconductor MAX77686 PMIC Support"
427 depends on I2C=y && GENERIC_HARDIRQS
428 select MFD_CORE
429 select REGMAP_I2C
430 select IRQ_DOMAIN
431 help
432 Say yes here to support for Maxim Semiconductor MAX77686.
433 This is a Power Management IC with RTC on chip.
434 This driver provides common support for accessing the device;
435 additional drivers must be enabled in order to use the functionality
436 of the device.
437
425config MFD_MAX77693 438config MFD_MAX77693
426 bool "Maxim Semiconductor MAX77693 PMIC Support" 439 bool "Maxim Semiconductor MAX77693 PMIC Support"
427 depends on I2C=y && GENERIC_HARDIRQS 440 depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 75f6ed68a4b9..8ee7a3bf595b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
78obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o 78obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
79obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o 79obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
80 80
81obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
81obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o 82obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
82max8925-objs := max8925-core.o max8925-i2c.o 83max8925-objs := max8925-core.o max8925-i2c.o
83obj-$(CONFIG_MFD_MAX8925) += max8925.o 84obj-$(CONFIG_MFD_MAX8925) += max8925.o
diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c
new file mode 100644
index 000000000000..fc101220f990
--- /dev/null
+++ b/drivers/mfd/max77686-irq.c
@@ -0,0 +1,309 @@
1/*
2 * max77686-irq.c - Interrupt controller support for MAX77686
3 *
4 * Copyright (C) 2012 Samsung Electronics Co.Ltd
5 * Chiwoong Byun <woong.byun@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * This driver is based on max8997-irq.c
22 */
23
24#include <linux/err.h>
25#include <linux/irq.h>
26#include <linux/interrupt.h>
27#include <linux/gpio.h>
28#include <linux/mfd/max77686.h>
29#include <linux/mfd/max77686-private.h>
30#include <linux/irqdomain.h>
31#include <linux/regmap.h>
32
33enum {
34 MAX77686_DEBUG_IRQ_INFO = 1 << 0,
35 MAX77686_DEBUG_IRQ_MASK = 1 << 1,
36 MAX77686_DEBUG_IRQ_INT = 1 << 2,
37};
38
39static int debug_mask = 0;
40module_param(debug_mask, int, 0);
41MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)");
42
43static const u8 max77686_mask_reg[] = {
44 [PMIC_INT1] = MAX77686_REG_INT1MSK,
45 [PMIC_INT2] = MAX77686_REG_INT2MSK,
46 [RTC_INT] = MAX77686_RTC_INTM,
47};
48
49static struct regmap *max77686_get_regmap(struct max77686_dev *max77686,
50 enum max77686_irq_source src)
51{
52 switch (src) {
53 case PMIC_INT1 ... PMIC_INT2:
54 return max77686->regmap;
55 case RTC_INT:
56 return max77686->rtc_regmap;
57 default:
58 return ERR_PTR(-EINVAL);
59 }
60}
61
62struct max77686_irq_data {
63 int mask;
64 enum max77686_irq_source group;
65};
66
67#define DECLARE_IRQ(idx, _group, _mask) \
68 [(idx)] = { .group = (_group), .mask = (_mask) }
69static const struct max77686_irq_data max77686_irqs[] = {
70 DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0),
71 DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1),
72 DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2),
73 DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3),
74 DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4),
75 DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5),
76 DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6),
77 DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7),
78 DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0),
79 DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1),
80 DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0),
81 DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1),
82 DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2),
83 DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3),
84 DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4),
85 DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5),
86};
87
88static void max77686_irq_lock(struct irq_data *data)
89{
90 struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
91
92 if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
93 pr_info("%s\n", __func__);
94
95 mutex_lock(&max77686->irqlock);
96}
97
98static void max77686_irq_sync_unlock(struct irq_data *data)
99{
100 struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
101 int i;
102
103 for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
104 u8 mask_reg = max77686_mask_reg[i];
105 struct regmap *map = max77686_get_regmap(max77686, i);
106
107 if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
108 pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n",
109 __func__, i, mask_reg, max77686->irq_masks_cur[i]);
110
111 if (mask_reg == MAX77686_REG_INVALID ||
112 IS_ERR_OR_NULL(map))
113 continue;
114
115 max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i];
116
117 regmap_write(map, max77686_mask_reg[i],
118 max77686->irq_masks_cur[i]);
119 }
120
121 mutex_unlock(&max77686->irqlock);
122}
123
124static const inline struct max77686_irq_data *to_max77686_irq(int irq)
125{
126 struct irq_data *data = irq_get_irq_data(irq);
127 return &max77686_irqs[data->hwirq];
128}
129
130static void max77686_irq_mask(struct irq_data *data)
131{
132 struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
133 const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
134
135 max77686->irq_masks_cur[irq_data->group] |= irq_data->mask;
136
137 if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
138 pr_info("%s: group=%d, cur=0x%x\n",
139 __func__, irq_data->group,
140 max77686->irq_masks_cur[irq_data->group]);
141}
142
143static void max77686_irq_unmask(struct irq_data *data)
144{
145 struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
146 const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
147
148 max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
149
150 if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
151 pr_info("%s: group=%d, cur=0x%x\n",
152 __func__, irq_data->group,
153 max77686->irq_masks_cur[irq_data->group]);
154}
155
156static struct irq_chip max77686_irq_chip = {
157 .name = "max77686",
158 .irq_bus_lock = max77686_irq_lock,
159 .irq_bus_sync_unlock = max77686_irq_sync_unlock,
160 .irq_mask = max77686_irq_mask,
161 .irq_unmask = max77686_irq_unmask,
162};
163
164static irqreturn_t max77686_irq_thread(int irq, void *data)
165{
166 struct max77686_dev *max77686 = data;
167 unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {};
168 unsigned int irq_src;
169 int ret;
170 int i, cur_irq;
171
172 ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src);
173 if (ret < 0) {
174 dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
175 ret);
176 return IRQ_NONE;
177 }
178
179 if (debug_mask & MAX77686_DEBUG_IRQ_INT)
180 pr_info("%s: irq_src=0x%x\n", __func__, irq_src);
181
182 if (irq_src == MAX77686_IRQSRC_PMIC) {
183 ret = regmap_bulk_read(max77686->rtc_regmap,
184 MAX77686_REG_INT1, irq_reg, 2);
185 if (ret < 0) {
186 dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
187 ret);
188 return IRQ_NONE;
189 }
190
191 if (debug_mask & MAX77686_DEBUG_IRQ_INT)
192 pr_info("%s: int1=0x%x, int2=0x%x\n", __func__,
193 irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]);
194 }
195
196 if (irq_src & MAX77686_IRQSRC_RTC) {
197 ret = regmap_read(max77686->rtc_regmap,
198 MAX77686_RTC_INT, &irq_reg[RTC_INT]);
199 if (ret < 0) {
200 dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
201 ret);
202 return IRQ_NONE;
203 }
204
205 if (debug_mask & MAX77686_DEBUG_IRQ_INT)
206 pr_info("%s: rtc int=0x%x\n", __func__,
207 irq_reg[RTC_INT]);
208
209 }
210
211 for (i = 0; i < MAX77686_IRQ_NR; i++) {
212 if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) {
213 cur_irq = irq_find_mapping(max77686->irq_domain, i);
214 if (cur_irq)
215 handle_nested_irq(cur_irq);
216 }
217 }
218
219 return IRQ_HANDLED;
220}
221
222static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq,
223 irq_hw_number_t hw)
224{
225 struct max77686_dev *max77686 = d->host_data;
226
227 irq_set_chip_data(irq, max77686);
228 irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq);
229 irq_set_nested_thread(irq, 1);
230#ifdef CONFIG_ARM
231 set_irq_flags(irq, IRQF_VALID);
232#else
233 irq_set_noprobe(irq);
234#endif
235 return 0;
236}
237
238static struct irq_domain_ops max77686_irq_domain_ops = {
239 .map = max77686_irq_domain_map,
240};
241
242int max77686_irq_init(struct max77686_dev *max77686)
243{
244 struct irq_domain *domain;
245 int i;
246 int ret;
247 int val;
248 struct regmap *map;
249
250 mutex_init(&max77686->irqlock);
251
252 max77686->irq = gpio_to_irq(max77686->irq_gpio);
253
254 if (debug_mask & MAX77686_DEBUG_IRQ_INT) {
255 ret = gpio_request(max77686->irq_gpio, "pmic_irq");
256 if (ret < 0) {
257 dev_err(max77686->dev,
258 "Failed to request gpio %d with ret: %d\n",
259 max77686->irq_gpio, ret);
260 return IRQ_NONE;
261 }
262
263 gpio_direction_input(max77686->irq_gpio);
264 val = gpio_get_value(max77686->irq_gpio);
265 gpio_free(max77686->irq_gpio);
266 pr_info("%s: gpio_irq=%x\n", __func__, val);
267 }
268
269 /* Mask individual interrupt sources */
270 for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
271 max77686->irq_masks_cur[i] = 0xff;
272 max77686->irq_masks_cache[i] = 0xff;
273 map = max77686_get_regmap(max77686, i);
274
275 if (IS_ERR_OR_NULL(map))
276 continue;
277 if (max77686_mask_reg[i] == MAX77686_REG_INVALID)
278 continue;
279
280 regmap_write(map, max77686_mask_reg[i], 0xff);
281 }
282 domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR,
283 &max77686_irq_domain_ops, max77686);
284 if (!domain) {
285 dev_err(max77686->dev, "could not create irq domain\n");
286 return -ENODEV;
287 }
288 max77686->irq_domain = domain;
289
290 ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread,
291 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
292 "max77686-irq", max77686);
293
294 if (ret)
295 dev_err(max77686->dev, "Failed to request IRQ %d: %d\n",
296 max77686->irq, ret);
297
298
299 if (debug_mask & MAX77686_DEBUG_IRQ_INFO)
300 pr_info("%s-\n", __func__);
301
302 return 0;
303}
304
305void max77686_irq_exit(struct max77686_dev *max77686)
306{
307 if (max77686->irq)
308 free_irq(max77686->irq, max77686);
309}
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
new file mode 100644
index 000000000000..11e56017e0b0
--- /dev/null
+++ b/drivers/mfd/max77686.c
@@ -0,0 +1,156 @@
1/*
2 * max77686.c - mfd core driver for the Maxim 77686
3 *
4 * Copyright (C) 2012 Samsung Electronics
5 * Chiwoong Byun <woong.byun@smasung.com>
6 * Jonghwa Lee <jonghwa3.lee@samsung.com>
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,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * This driver is based on max8997.c
23 */
24
25#include <linux/export.h>
26#include <linux/slab.h>
27#include <linux/i2c.h>
28#include <linux/pm_runtime.h>
29#include <linux/module.h>
30#include <linux/mutex.h>
31#include <linux/mfd/core.h>
32#include <linux/mfd/max77686.h>
33#include <linux/mfd/max77686-private.h>
34#include <linux/err.h>
35
36#define I2C_ADDR_RTC (0x0C >> 1)
37
38static struct mfd_cell max77686_devs[] = {
39 { .name = "max77686-pmic", },
40 { .name = "max77686-rtc", },
41};
42
43static struct regmap_config max77686_regmap_config = {
44 .reg_bits = 8,
45 .val_bits = 8,
46};
47
48static int max77686_i2c_probe(struct i2c_client *i2c,
49 const struct i2c_device_id *id)
50{
51 struct max77686_dev *max77686;
52 struct max77686_platform_data *pdata = i2c->dev.platform_data;
53 unsigned int data;
54 int ret = 0;
55
56 max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL);
57 if (max77686 == NULL)
58 return -ENOMEM;
59
60 max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
61 if (IS_ERR(max77686->regmap)) {
62 ret = PTR_ERR(max77686->regmap);
63 dev_err(max77686->dev, "Failed to allocate register map: %d\n",
64 ret);
65 kfree(max77686);
66 return ret;
67 }
68
69 i2c_set_clientdata(i2c, max77686);
70 max77686->dev = &i2c->dev;
71 max77686->i2c = i2c;
72 max77686->type = id->driver_data;
73
74 if (!pdata) {
75 ret = -EIO;
76 goto err;
77 }
78
79 max77686->wakeup = pdata->wakeup;
80 max77686->irq_gpio = pdata->irq_gpio;
81
82 mutex_init(&max77686->iolock);
83
84 if (regmap_read(max77686->regmap,
85 MAX77686_REG_DEVICE_ID, &data) < 0) {
86 dev_err(max77686->dev,
87 "device not found on this channel (this is not an error)\n");
88 ret = -ENODEV;
89 goto err;
90 } else
91 dev_info(max77686->dev, "device found\n");
92
93 max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
94 i2c_set_clientdata(max77686->rtc, max77686);
95
96 max77686_irq_init(max77686);
97
98 ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
99 ARRAY_SIZE(max77686_devs), NULL, 0);
100
101 if (ret < 0)
102 goto err_mfd;
103
104 return ret;
105
106err_mfd:
107 mfd_remove_devices(max77686->dev);
108 i2c_unregister_device(max77686->rtc);
109err:
110 kfree(max77686);
111 return ret;
112}
113
114static int max77686_i2c_remove(struct i2c_client *i2c)
115{
116 struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
117
118 mfd_remove_devices(max77686->dev);
119 i2c_unregister_device(max77686->rtc);
120 kfree(max77686);
121
122 return 0;
123}
124
125static const struct i2c_device_id max77686_i2c_id[] = {
126 { "max77686", TYPE_MAX77686 },
127 { }
128};
129MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
130
131static struct i2c_driver max77686_i2c_driver = {
132 .driver = {
133 .name = "max77686",
134 .owner = THIS_MODULE,
135 },
136 .probe = max77686_i2c_probe,
137 .remove = max77686_i2c_remove,
138 .id_table = max77686_i2c_id,
139};
140
141static int __init max77686_i2c_init(void)
142{
143 return i2c_add_driver(&max77686_i2c_driver);
144}
145/* init early so consumer devices can complete system boot */
146subsys_initcall(max77686_i2c_init);
147
148static void __exit max77686_i2c_exit(void)
149{
150 i2c_del_driver(&max77686_i2c_driver);
151}
152module_exit(max77686_i2c_exit);
153
154MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver");
155MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
156MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77686-private.h b/include/linux/mfd/max77686-private.h
new file mode 100644
index 000000000000..962f65e72b71
--- /dev/null
+++ b/include/linux/mfd/max77686-private.h
@@ -0,0 +1,247 @@
1/*
2 * max77686.h - Voltage regulator driver for the Maxim 77686
3 *
4 * Copyright (C) 2012 Samsung Electrnoics
5 * Chiwoong Byun <woong.byun@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifndef __LINUX_MFD_MAX77686_PRIV_H
23#define __LINUX_MFD_MAX77686_PRIV_H
24
25#include <linux/i2c.h>
26#include <linux/regmap.h>
27#include <linux/module.h>
28
29#define MAX77686_REG_INVALID (0xff)
30
31enum max77686_pmic_reg {
32 MAX77686_REG_DEVICE_ID = 0x00,
33 MAX77686_REG_INTSRC = 0x01,
34 MAX77686_REG_INT1 = 0x02,
35 MAX77686_REG_INT2 = 0x03,
36
37 MAX77686_REG_INT1MSK = 0x04,
38 MAX77686_REG_INT2MSK = 0x05,
39
40 MAX77686_REG_STATUS1 = 0x06,
41 MAX77686_REG_STATUS2 = 0x07,
42
43 MAX77686_REG_PWRON = 0x08,
44 MAX77686_REG_ONOFF_DELAY = 0x09,
45 MAX77686_REG_MRSTB = 0x0A,
46 /* Reserved: 0x0B-0x0F */
47
48 MAX77686_REG_BUCK1CTRL = 0x10,
49 MAX77686_REG_BUCK1OUT = 0x11,
50 MAX77686_REG_BUCK2CTRL1 = 0x12,
51 MAX77686_REG_BUCK234FREQ = 0x13,
52 MAX77686_REG_BUCK2DVS1 = 0x14,
53 MAX77686_REG_BUCK2DVS2 = 0x15,
54 MAX77686_REG_BUCK2DVS3 = 0x16,
55 MAX77686_REG_BUCK2DVS4 = 0x17,
56 MAX77686_REG_BUCK2DVS5 = 0x18,
57 MAX77686_REG_BUCK2DVS6 = 0x19,
58 MAX77686_REG_BUCK2DVS7 = 0x1A,
59 MAX77686_REG_BUCK2DVS8 = 0x1B,
60 MAX77686_REG_BUCK3CTRL1 = 0x1C,
61 /* Reserved: 0x1D */
62 MAX77686_REG_BUCK3DVS1 = 0x1E,
63 MAX77686_REG_BUCK3DVS2 = 0x1F,
64 MAX77686_REG_BUCK3DVS3 = 0x20,
65 MAX77686_REG_BUCK3DVS4 = 0x21,
66 MAX77686_REG_BUCK3DVS5 = 0x22,
67 MAX77686_REG_BUCK3DVS6 = 0x23,
68 MAX77686_REG_BUCK3DVS7 = 0x24,
69 MAX77686_REG_BUCK3DVS8 = 0x25,
70 MAX77686_REG_BUCK4CTRL1 = 0x26,
71 /* Reserved: 0x27 */
72 MAX77686_REG_BUCK4DVS1 = 0x28,
73 MAX77686_REG_BUCK4DVS2 = 0x29,
74 MAX77686_REG_BUCK4DVS3 = 0x2A,
75 MAX77686_REG_BUCK4DVS4 = 0x2B,
76 MAX77686_REG_BUCK4DVS5 = 0x2C,
77 MAX77686_REG_BUCK4DVS6 = 0x2D,
78 MAX77686_REG_BUCK4DVS7 = 0x2E,
79 MAX77686_REG_BUCK4DVS8 = 0x2F,
80 MAX77686_REG_BUCK5CTRL = 0x30,
81 MAX77686_REG_BUCK5OUT = 0x31,
82 MAX77686_REG_BUCK6CTRL = 0x32,
83 MAX77686_REG_BUCK6OUT = 0x33,
84 MAX77686_REG_BUCK7CTRL = 0x34,
85 MAX77686_REG_BUCK7OUT = 0x35,
86 MAX77686_REG_BUCK8CTRL = 0x36,
87 MAX77686_REG_BUCK8OUT = 0x37,
88 MAX77686_REG_BUCK9CTRL = 0x38,
89 MAX77686_REG_BUCK9OUT = 0x39,
90 /* Reserved: 0x3A-0x3F */
91
92 MAX77686_REG_LDO1CTRL1 = 0x40,
93 MAX77686_REG_LDO2CTRL1 = 0x41,
94 MAX77686_REG_LDO3CTRL1 = 0x42,
95 MAX77686_REG_LDO4CTRL1 = 0x43,
96 MAX77686_REG_LDO5CTRL1 = 0x44,
97 MAX77686_REG_LDO6CTRL1 = 0x45,
98 MAX77686_REG_LDO7CTRL1 = 0x46,
99 MAX77686_REG_LDO8CTRL1 = 0x47,
100 MAX77686_REG_LDO9CTRL1 = 0x48,
101 MAX77686_REG_LDO10CTRL1 = 0x49,
102 MAX77686_REG_LDO11CTRL1 = 0x4A,
103 MAX77686_REG_LDO12CTRL1 = 0x4B,
104 MAX77686_REG_LDO13CTRL1 = 0x4C,
105 MAX77686_REG_LDO14CTRL1 = 0x4D,
106 MAX77686_REG_LDO15CTRL1 = 0x4E,
107 MAX77686_REG_LDO16CTRL1 = 0x4F,
108 MAX77686_REG_LDO17CTRL1 = 0x50,
109 MAX77686_REG_LDO18CTRL1 = 0x51,
110 MAX77686_REG_LDO19CTRL1 = 0x52,
111 MAX77686_REG_LDO20CTRL1 = 0x53,
112 MAX77686_REG_LDO21CTRL1 = 0x54,
113 MAX77686_REG_LDO22CTRL1 = 0x55,
114 MAX77686_REG_LDO23CTRL1 = 0x56,
115 MAX77686_REG_LDO24CTRL1 = 0x57,
116 MAX77686_REG_LDO25CTRL1 = 0x58,
117 MAX77686_REG_LDO26CTRL1 = 0x59,
118 /* Reserved: 0x5A-0x5F */
119 MAX77686_REG_LDO1CTRL2 = 0x60,
120 MAX77686_REG_LDO2CTRL2 = 0x61,
121 MAX77686_REG_LDO3CTRL2 = 0x62,
122 MAX77686_REG_LDO4CTRL2 = 0x63,
123 MAX77686_REG_LDO5CTRL2 = 0x64,
124 MAX77686_REG_LDO6CTRL2 = 0x65,
125 MAX77686_REG_LDO7CTRL2 = 0x66,
126 MAX77686_REG_LDO8CTRL2 = 0x67,
127 MAX77686_REG_LDO9CTRL2 = 0x68,
128 MAX77686_REG_LDO10CTRL2 = 0x69,
129 MAX77686_REG_LDO11CTRL2 = 0x6A,
130 MAX77686_REG_LDO12CTRL2 = 0x6B,
131 MAX77686_REG_LDO13CTRL2 = 0x6C,
132 MAX77686_REG_LDO14CTRL2 = 0x6D,
133 MAX77686_REG_LDO15CTRL2 = 0x6E,
134 MAX77686_REG_LDO16CTRL2 = 0x6F,
135 MAX77686_REG_LDO17CTRL2 = 0x70,
136 MAX77686_REG_LDO18CTRL2 = 0x71,
137 MAX77686_REG_LDO19CTRL2 = 0x72,
138 MAX77686_REG_LDO20CTRL2 = 0x73,
139 MAX77686_REG_LDO21CTRL2 = 0x74,
140 MAX77686_REG_LDO22CTRL2 = 0x75,
141 MAX77686_REG_LDO23CTRL2 = 0x76,
142 MAX77686_REG_LDO24CTRL2 = 0x77,
143 MAX77686_REG_LDO25CTRL2 = 0x78,
144 MAX77686_REG_LDO26CTRL2 = 0x79,
145 /* Reserved: 0x7A-0x7D */
146
147 MAX77686_REG_BBAT_CHG = 0x7E,
148 MAX77686_REG_32KHZ = 0x7F,
149
150 MAX77686_REG_PMIC_END = 0x80,
151};
152
153enum max77686_rtc_reg {
154 MAX77686_RTC_INT = 0x00,
155 MAX77686_RTC_INTM = 0x01,
156 MAX77686_RTC_CONTROLM = 0x02,
157 MAX77686_RTC_CONTROL = 0x03,
158 MAX77686_RTC_UPDATE0 = 0x04,
159 /* Reserved: 0x5 */
160 MAX77686_WTSR_SMPL_CNTL = 0x06,
161 MAX77686_RTC_SEC = 0x07,
162 MAX77686_RTC_MIN = 0x08,
163 MAX77686_RTC_HOUR = 0x09,
164 MAX77686_RTC_WEEKDAY = 0x0A,
165 MAX77686_RTC_MONTH = 0x0B,
166 MAX77686_RTC_YEAR = 0x0C,
167 MAX77686_RTC_DATE = 0x0D,
168 MAX77686_ALARM1_SEC = 0x0E,
169 MAX77686_ALARM1_MIN = 0x0F,
170 MAX77686_ALARM1_HOUR = 0x10,
171 MAX77686_ALARM1_WEEKDAY = 0x11,
172 MAX77686_ALARM1_MONTH = 0x12,
173 MAX77686_ALARM1_YEAR = 0x13,
174 MAX77686_ALARM1_DATE = 0x14,
175 MAX77686_ALARM2_SEC = 0x15,
176 MAX77686_ALARM2_MIN = 0x16,
177 MAX77686_ALARM2_HOUR = 0x17,
178 MAX77686_ALARM2_WEEKDAY = 0x18,
179 MAX77686_ALARM2_MONTH = 0x19,
180 MAX77686_ALARM2_YEAR = 0x1A,
181 MAX77686_ALARM2_DATE = 0x1B,
182};
183
184#define MAX77686_IRQSRC_PMIC (0)
185#define MAX77686_IRQSRC_RTC (1 << 0)
186
187enum max77686_irq_source {
188 PMIC_INT1 = 0,
189 PMIC_INT2,
190 RTC_INT,
191
192 MAX77686_IRQ_GROUP_NR,
193};
194
195enum max77686_irq {
196 MAX77686_PMICIRQ_PWRONF,
197 MAX77686_PMICIRQ_PWRONR,
198 MAX77686_PMICIRQ_JIGONBF,
199 MAX77686_PMICIRQ_JIGONBR,
200 MAX77686_PMICIRQ_ACOKBF,
201 MAX77686_PMICIRQ_ACOKBR,
202 MAX77686_PMICIRQ_ONKEY1S,
203 MAX77686_PMICIRQ_MRSTB,
204
205 MAX77686_PMICIRQ_140C,
206 MAX77686_PMICIRQ_120C,
207
208 MAX77686_RTCIRQ_RTC60S,
209 MAX77686_RTCIRQ_RTCA1,
210 MAX77686_RTCIRQ_RTCA2,
211 MAX77686_RTCIRQ_SMPL,
212 MAX77686_RTCIRQ_RTC1S,
213 MAX77686_RTCIRQ_WTSR,
214
215 MAX77686_IRQ_NR,
216};
217
218struct max77686_dev {
219 struct device *dev;
220 struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
221 struct i2c_client *rtc; /* slave addr 0x0c */
222 struct mutex iolock;
223
224 int type;
225
226 struct regmap *regmap; /* regmap for mfd */
227 struct regmap *rtc_regmap; /* regmap for rtc */
228
229 struct irq_domain *irq_domain;
230
231 int irq;
232 int irq_gpio;
233 bool wakeup;
234 struct mutex irqlock;
235 int irq_masks_cur[MAX77686_IRQ_GROUP_NR];
236 int irq_masks_cache[MAX77686_IRQ_GROUP_NR];
237};
238
239enum max77686_types {
240 TYPE_MAX77686,
241};
242
243extern int max77686_irq_init(struct max77686_dev *max77686);
244extern void max77686_irq_exit(struct max77686_dev *max77686);
245extern int max77686_irq_resume(struct max77686_dev *max77686);
246
247#endif /* __LINUX_MFD_MAX77686_PRIV_H */
diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h
new file mode 100644
index 000000000000..fcf312678cac
--- /dev/null
+++ b/include/linux/mfd/max77686.h
@@ -0,0 +1,117 @@
1/*
2 * max77686.h - Driver for the Maxim 77686
3 *
4 * Copyright (C) 2012 Samsung Electrnoics
5 * Chiwoong Byun <woong.byun@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * This driver is based on max8997.h
22 *
23 * MAX77686 has PMIC, RTC devices.
24 * The devices share the same I2C bus and included in
25 * this mfd driver.
26 */
27
28#ifndef __LINUX_MFD_MAX77686_H
29#define __LINUX_MFD_MAX77686_H
30
31#include <linux/regulator/consumer.h>
32
33/* MAX77686 regulator IDs */
34enum max77686_regulators {
35 MAX77686_LDO1 = 0,
36 MAX77686_LDO2,
37 MAX77686_LDO3,
38 MAX77686_LDO4,
39 MAX77686_LDO5,
40 MAX77686_LDO6,
41 MAX77686_LDO7,
42 MAX77686_LDO8,
43 MAX77686_LDO9,
44 MAX77686_LDO10,
45 MAX77686_LDO11,
46 MAX77686_LDO12,
47 MAX77686_LDO13,
48 MAX77686_LDO14,
49 MAX77686_LDO15,
50 MAX77686_LDO16,
51 MAX77686_LDO17,
52 MAX77686_LDO18,
53 MAX77686_LDO19,
54 MAX77686_LDO20,
55 MAX77686_LDO21,
56 MAX77686_LDO22,
57 MAX77686_LDO23,
58 MAX77686_LDO24,
59 MAX77686_LDO25,
60 MAX77686_LDO26,
61 MAX77686_BUCK1,
62 MAX77686_BUCK2,
63 MAX77686_BUCK3,
64 MAX77686_BUCK4,
65 MAX77686_BUCK5,
66 MAX77686_BUCK6,
67 MAX77686_BUCK7,
68 MAX77686_BUCK8,
69 MAX77686_BUCK9,
70 MAX77686_EN32KHZ_AP,
71 MAX77686_EN32KHZ_CP,
72 MAX77686_P32KH,
73
74 MAX77686_REG_MAX,
75};
76
77struct max77686_regulator_data {
78 int id;
79 struct regulator_init_data *initdata;
80};
81
82enum max77686_opmode {
83 MAX77686_OPMODE_NORMAL,
84 MAX77686_OPMODE_LP,
85 MAX77686_OPMODE_STANDBY,
86};
87
88struct max77686_opmode_data {
89 int id;
90 int mode;
91};
92
93struct max77686_platform_data {
94 /* IRQ */
95 int irq_gpio;
96 int ono;
97 int wakeup;
98
99 /* ---- PMIC ---- */
100 struct max77686_regulator_data *regulators;
101 int num_regulators;
102
103 struct max77686_opmode_data *opmode_data;
104
105 /*
106 * GPIO-DVS feature is not enabled with the current version of
107 * MAX77686 driver. Buck2/3/4_voltages[0] is used as the default
108 * voltage at probe. DVS/SELB gpios are set as OUTPUT-LOW.
109 */
110 int buck234_gpio_dvs[3]; /* GPIO of [0]DVS1, [1]DVS2, [2]DVS3 */
111 int buck234_gpio_selb[3]; /* [0]SELB2, [1]SELB3, [2]SELB4 */
112 unsigned int buck2_voltage[8]; /* buckx_voltage in uV */
113 unsigned int buck3_voltage[8];
114 unsigned int buck4_voltage[8];
115};
116
117#endif /* __LINUX_MFD_MAX77686_H */