aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@marvell.com>2010-02-05 10:07:54 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2010-03-07 16:17:16 -0500
commit1f1cf8f98cf6588365efeaab8e7e7758aaa77f6e (patch)
treef2e17f85409bb6e2f75e152983e62fd2c4372859
parentb13c0df517bedbc40cff4ab5f797b08b1111918b (diff)
mfd: Update irq handler in max8925
Update thread irq handler. Simply the interface of using thread irq. Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig4
-rw-r--r--drivers/mfd/max8925-core.c678
-rw-r--r--include/linux/mfd/max8925.h139
3 files changed, 564 insertions, 257 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 64fbe3334eb3..84a68d260772 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -204,8 +204,8 @@ config PMIC_ADP5520
204 under the corresponding menus. 204 under the corresponding menus.
205 205
206config MFD_MAX8925 206config MFD_MAX8925
207 tristate "Maxim Semiconductor MAX8925 PMIC Support" 207 bool "Maxim Semiconductor MAX8925 PMIC Support"
208 depends on I2C 208 depends on I2C=y
209 select MFD_CORE 209 select MFD_CORE
210 help 210 help
211 Say yes here to support for Maxim Semiconductor MAX8925. This is 211 Say yes here to support for Maxim Semiconductor MAX8925. This is
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index f36c494b80f1..85d63c04749b 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Base driver for Maxim MAX8925 2 * Base driver for Maxim MAX8925
3 * 3 *
4 * Copyright (C) 2009 Marvell International Ltd. 4 * Copyright (C) 2009-2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com> 5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -12,14 +12,12 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/irq.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
16#include <linux/platform_device.h> 17#include <linux/platform_device.h>
17#include <linux/mfd/core.h> 18#include <linux/mfd/core.h>
18#include <linux/mfd/max8925.h> 19#include <linux/mfd/max8925.h>
19 20
20#define IRQ_MODE_STATUS 0
21#define IRQ_MODE_MASK 1
22
23static struct resource backlight_resources[] = { 21static struct resource backlight_resources[] = {
24 { 22 {
25 .name = "max8925-backlight", 23 .name = "max8925-backlight",
@@ -56,6 +54,42 @@ static struct mfd_cell touch_devs[] = {
56 }, 54 },
57}; 55};
58 56
57static struct resource power_supply_resources[] = {
58 {
59 .name = "max8925-power",
60 .start = MAX8925_CHG_IRQ1,
61 .end = MAX8925_CHG_IRQ1_MASK,
62 .flags = IORESOURCE_IO,
63 },
64};
65
66static struct mfd_cell power_devs[] = {
67 {
68 .name = "max8925-power",
69 .num_resources = 1,
70 .resources = &power_supply_resources[0],
71 .id = -1,
72 },
73};
74
75static struct resource rtc_resources[] = {
76 {
77 .name = "max8925-rtc",
78 .start = MAX8925_RTC_IRQ,
79 .end = MAX8925_RTC_IRQ_MASK,
80 .flags = IORESOURCE_IO,
81 },
82};
83
84static struct mfd_cell rtc_devs[] = {
85 {
86 .name = "max8925-rtc",
87 .num_resources = 1,
88 .resources = &rtc_resources[0],
89 .id = -1,
90 },
91};
92
59#define MAX8925_REG_RESOURCE(_start, _end) \ 93#define MAX8925_REG_RESOURCE(_start, _end) \
60{ \ 94{ \
61 .start = MAX8925_##_start, \ 95 .start = MAX8925_##_start, \
@@ -123,203 +157,450 @@ static struct mfd_cell regulator_devs[] = {
123 MAX8925_REG_DEVS(LDO20), 157 MAX8925_REG_DEVS(LDO20),
124}; 158};
125 159
126static int __get_irq_offset(struct max8925_chip *chip, int irq, int mode, 160enum {
127 int *offset, int *bit) 161 FLAGS_ADC = 1, /* register in ADC component */
162 FLAGS_RTC, /* register in RTC component */
163};
164
165struct max8925_irq_data {
166 int reg;
167 int mask_reg;
168 int enable; /* enable or not */
169 int offs; /* bit offset in mask register */
170 int flags;
171 int tsc_irq;
172};
173
174static struct max8925_irq_data max8925_irqs[] = {
175 [MAX8925_IRQ_VCHG_DC_OVP] = {
176 .reg = MAX8925_CHG_IRQ1,
177 .mask_reg = MAX8925_CHG_IRQ1_MASK,
178 .offs = 1 << 0,
179 },
180 [MAX8925_IRQ_VCHG_DC_F] = {
181 .reg = MAX8925_CHG_IRQ1,
182 .mask_reg = MAX8925_CHG_IRQ1_MASK,
183 .offs = 1 << 1,
184 },
185 [MAX8925_IRQ_VCHG_DC_R] = {
186 .reg = MAX8925_CHG_IRQ1,
187 .mask_reg = MAX8925_CHG_IRQ1_MASK,
188 .offs = 1 << 2,
189 },
190 [MAX8925_IRQ_VCHG_USB_OVP] = {
191 .reg = MAX8925_CHG_IRQ1,
192 .mask_reg = MAX8925_CHG_IRQ1_MASK,
193 .offs = 1 << 3,
194 },
195 [MAX8925_IRQ_VCHG_USB_F] = {
196 .reg = MAX8925_CHG_IRQ1,
197 .mask_reg = MAX8925_CHG_IRQ1_MASK,
198 .offs = 1 << 4,
199 },
200 [MAX8925_IRQ_VCHG_USB_R] = {
201 .reg = MAX8925_CHG_IRQ1,
202 .mask_reg = MAX8925_CHG_IRQ1_MASK,
203 .offs = 1 << 5,
204 },
205 [MAX8925_IRQ_VCHG_THM_OK_R] = {
206 .reg = MAX8925_CHG_IRQ2,
207 .mask_reg = MAX8925_CHG_IRQ2_MASK,
208 .offs = 1 << 0,
209 },
210 [MAX8925_IRQ_VCHG_THM_OK_F] = {
211 .reg = MAX8925_CHG_IRQ2,
212 .mask_reg = MAX8925_CHG_IRQ2_MASK,
213 .offs = 1 << 1,
214 },
215 [MAX8925_IRQ_VCHG_SYSLOW_F] = {
216 .reg = MAX8925_CHG_IRQ2,
217 .mask_reg = MAX8925_CHG_IRQ2_MASK,
218 .offs = 1 << 2,
219 },
220 [MAX8925_IRQ_VCHG_SYSLOW_R] = {
221 .reg = MAX8925_CHG_IRQ2,
222 .mask_reg = MAX8925_CHG_IRQ2_MASK,
223 .offs = 1 << 3,
224 },
225 [MAX8925_IRQ_VCHG_RST] = {
226 .reg = MAX8925_CHG_IRQ2,
227 .mask_reg = MAX8925_CHG_IRQ2_MASK,
228 .offs = 1 << 4,
229 },
230 [MAX8925_IRQ_VCHG_DONE] = {
231 .reg = MAX8925_CHG_IRQ2,
232 .mask_reg = MAX8925_CHG_IRQ2_MASK,
233 .offs = 1 << 5,
234 },
235 [MAX8925_IRQ_VCHG_TOPOFF] = {
236 .reg = MAX8925_CHG_IRQ2,
237 .mask_reg = MAX8925_CHG_IRQ2_MASK,
238 .offs = 1 << 6,
239 },
240 [MAX8925_IRQ_VCHG_TMR_FAULT] = {
241 .reg = MAX8925_CHG_IRQ2,
242 .mask_reg = MAX8925_CHG_IRQ2_MASK,
243 .offs = 1 << 7,
244 },
245 [MAX8925_IRQ_GPM_RSTIN] = {
246 .reg = MAX8925_ON_OFF_IRQ1,
247 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
248 .offs = 1 << 0,
249 },
250 [MAX8925_IRQ_GPM_MPL] = {
251 .reg = MAX8925_ON_OFF_IRQ1,
252 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
253 .offs = 1 << 1,
254 },
255 [MAX8925_IRQ_GPM_SW_3SEC] = {
256 .reg = MAX8925_ON_OFF_IRQ1,
257 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
258 .offs = 1 << 2,
259 },
260 [MAX8925_IRQ_GPM_EXTON_F] = {
261 .reg = MAX8925_ON_OFF_IRQ1,
262 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
263 .offs = 1 << 3,
264 },
265 [MAX8925_IRQ_GPM_EXTON_R] = {
266 .reg = MAX8925_ON_OFF_IRQ1,
267 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
268 .offs = 1 << 4,
269 },
270 [MAX8925_IRQ_GPM_SW_1SEC] = {
271 .reg = MAX8925_ON_OFF_IRQ1,
272 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
273 .offs = 1 << 5,
274 },
275 [MAX8925_IRQ_GPM_SW_F] = {
276 .reg = MAX8925_ON_OFF_IRQ1,
277 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
278 .offs = 1 << 6,
279 },
280 [MAX8925_IRQ_GPM_SW_R] = {
281 .reg = MAX8925_ON_OFF_IRQ1,
282 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
283 .offs = 1 << 7,
284 },
285 [MAX8925_IRQ_GPM_SYSCKEN_F] = {
286 .reg = MAX8925_ON_OFF_IRQ2,
287 .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
288 .offs = 1 << 0,
289 },
290 [MAX8925_IRQ_GPM_SYSCKEN_R] = {
291 .reg = MAX8925_ON_OFF_IRQ2,
292 .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
293 .offs = 1 << 1,
294 },
295 [MAX8925_IRQ_RTC_ALARM1] = {
296 .reg = MAX8925_RTC_IRQ,
297 .mask_reg = MAX8925_RTC_IRQ_MASK,
298 .offs = 1 << 2,
299 .flags = FLAGS_RTC,
300 },
301 [MAX8925_IRQ_RTC_ALARM0] = {
302 .reg = MAX8925_RTC_IRQ,
303 .mask_reg = MAX8925_RTC_IRQ_MASK,
304 .offs = 1 << 3,
305 .flags = FLAGS_RTC,
306 },
307 [MAX8925_IRQ_TSC_STICK] = {
308 .reg = MAX8925_TSC_IRQ,
309 .mask_reg = MAX8925_TSC_IRQ_MASK,
310 .offs = 1 << 0,
311 .flags = FLAGS_ADC,
312 .tsc_irq = 1,
313 },
314 [MAX8925_IRQ_TSC_NSTICK] = {
315 .reg = MAX8925_TSC_IRQ,
316 .mask_reg = MAX8925_TSC_IRQ_MASK,
317 .offs = 1 << 1,
318 .flags = FLAGS_ADC,
319 .tsc_irq = 1,
320 },
321};
322
323static inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip,
324 int irq)
128{ 325{
129 if (!offset || !bit) 326 return &max8925_irqs[irq - chip->irq_base];
130 return -EINVAL; 327}
131 328
132 switch (chip->chip_id) { 329static irqreturn_t max8925_irq(int irq, void *data)
133 case MAX8925_GPM: 330{
134 *bit = irq % BITS_PER_BYTE; 331 struct max8925_chip *chip = data;
135 if (irq < (BITS_PER_BYTE << 1)) { /* irq = [0,15] */ 332 struct max8925_irq_data *irq_data;
136 *offset = (mode) ? MAX8925_CHG_IRQ1_MASK 333 struct i2c_client *i2c;
137 : MAX8925_CHG_IRQ1; 334 int read_reg = -1, value = 0;
138 if (irq >= BITS_PER_BYTE) 335 int i;
139 (*offset)++; 336
140 } else { /* irq = [16,31] */ 337 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
141 *offset = (mode) ? MAX8925_ON_OFF_IRQ1_MASK 338 irq_data = &max8925_irqs[i];
142 : MAX8925_ON_OFF_IRQ1; 339 /* TSC IRQ should be serviced in max8925_tsc_irq() */
143 if (irq >= (BITS_PER_BYTE * 3)) 340 if (irq_data->tsc_irq)
144 (*offset)++; 341 continue;
342 if (irq_data->flags == FLAGS_RTC)
343 i2c = chip->rtc;
344 else if (irq_data->flags == FLAGS_ADC)
345 i2c = chip->adc;
346 else
347 i2c = chip->i2c;
348 if (read_reg != irq_data->reg) {
349 read_reg = irq_data->reg;
350 value = max8925_reg_read(i2c, irq_data->reg);
145 } 351 }
146 break; 352 if (value & irq_data->enable)
147 case MAX8925_ADC: 353 handle_nested_irq(chip->irq_base + i);
148 *bit = irq % BITS_PER_BYTE;
149 *offset = (mode) ? MAX8925_TSC_IRQ_MASK : MAX8925_TSC_IRQ;
150 break;
151 default:
152 goto out;
153 } 354 }
154 return 0; 355 return IRQ_HANDLED;
155out:
156 dev_err(chip->dev, "Wrong irq #%d is assigned\n", irq);
157 return -EINVAL;
158} 356}
159 357
160static int __check_irq(int irq) 358static irqreturn_t max8925_tsc_irq(int irq, void *data)
161{ 359{
162 if ((irq < 0) || (irq >= MAX8925_NUM_IRQ)) 360 struct max8925_chip *chip = data;
163 return -EINVAL; 361 struct max8925_irq_data *irq_data;
164 return 0; 362 struct i2c_client *i2c;
363 int read_reg = -1, value = 0;
364 int i;
365
366 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
367 irq_data = &max8925_irqs[i];
368 /* non TSC IRQ should be serviced in max8925_irq() */
369 if (!irq_data->tsc_irq)
370 continue;
371 if (irq_data->flags == FLAGS_RTC)
372 i2c = chip->rtc;
373 else if (irq_data->flags == FLAGS_ADC)
374 i2c = chip->adc;
375 else
376 i2c = chip->i2c;
377 if (read_reg != irq_data->reg) {
378 read_reg = irq_data->reg;
379 value = max8925_reg_read(i2c, irq_data->reg);
380 }
381 if (value & irq_data->enable)
382 handle_nested_irq(chip->irq_base + i);
383 }
384 return IRQ_HANDLED;
165} 385}
166 386
167int max8925_mask_irq(struct max8925_chip *chip, int irq) 387static void max8925_irq_lock(unsigned int irq)
168{ 388{
169 int offset, bit, ret; 389 struct max8925_chip *chip = get_irq_chip_data(irq);
170 390
171 ret = __get_irq_offset(chip, irq, IRQ_MODE_MASK, &offset, &bit); 391 mutex_lock(&chip->irq_lock);
172 if (ret < 0)
173 return ret;
174 ret = max8925_set_bits(chip->i2c, offset, 1 << bit, 1 << bit);
175 return ret;
176} 392}
177 393
178int max8925_unmask_irq(struct max8925_chip *chip, int irq) 394static void max8925_irq_sync_unlock(unsigned int irq)
179{ 395{
180 int offset, bit, ret; 396 struct max8925_chip *chip = get_irq_chip_data(irq);
397 struct max8925_irq_data *irq_data;
398 static unsigned char cache_chg[2] = {0xff, 0xff};
399 static unsigned char cache_on[2] = {0xff, 0xff};
400 static unsigned char cache_rtc = 0xff, cache_tsc = 0xff;
401 unsigned char irq_chg[2], irq_on[2];
402 unsigned char irq_rtc, irq_tsc;
403 int i;
404
405 /* Load cached value. In initial, all IRQs are masked */
406 irq_chg[0] = cache_chg[0];
407 irq_chg[1] = cache_chg[1];
408 irq_on[0] = cache_on[0];
409 irq_on[1] = cache_on[1];
410 irq_rtc = cache_rtc;
411 irq_tsc = cache_tsc;
412 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
413 irq_data = &max8925_irqs[i];
414 switch (irq_data->mask_reg) {
415 case MAX8925_CHG_IRQ1_MASK:
416 irq_chg[0] &= irq_data->enable;
417 break;
418 case MAX8925_CHG_IRQ2_MASK:
419 irq_chg[1] &= irq_data->enable;
420 break;
421 case MAX8925_ON_OFF_IRQ1_MASK:
422 irq_on[0] &= irq_data->enable;
423 break;
424 case MAX8925_ON_OFF_IRQ2_MASK:
425 irq_on[1] &= irq_data->enable;
426 break;
427 case MAX8925_RTC_IRQ_MASK:
428 irq_rtc &= irq_data->enable;
429 break;
430 case MAX8925_TSC_IRQ_MASK:
431 irq_tsc &= irq_data->enable;
432 break;
433 default:
434 dev_err(chip->dev, "wrong IRQ\n");
435 break;
436 }
437 }
438 /* update mask into registers */
439 if (cache_chg[0] != irq_chg[0]) {
440 cache_chg[0] = irq_chg[0];
441 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK,
442 irq_chg[0]);
443 }
444 if (cache_chg[1] != irq_chg[1]) {
445 cache_chg[1] = irq_chg[1];
446 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK,
447 irq_chg[1]);
448 }
449 if (cache_on[0] != irq_on[0]) {
450 cache_on[0] = irq_on[0];
451 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK,
452 irq_on[0]);
453 }
454 if (cache_on[1] != irq_on[1]) {
455 cache_on[1] = irq_on[1];
456 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK,
457 irq_on[1]);
458 }
459 if (cache_rtc != irq_rtc) {
460 cache_rtc = irq_rtc;
461 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc);
462 }
463 if (cache_tsc != irq_tsc) {
464 cache_tsc = irq_tsc;
465 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc);
466 }
181 467
182 ret = __get_irq_offset(chip, irq, IRQ_MODE_MASK, &offset, &bit); 468 mutex_unlock(&chip->irq_lock);
183 if (ret < 0)
184 return ret;
185 ret = max8925_set_bits(chip->i2c, offset, 1 << bit, 0);
186 return ret;
187} 469}
188 470
189#define INT_STATUS_NUM (MAX8925_NUM_IRQ / BITS_PER_BYTE) 471static void max8925_irq_enable(unsigned int irq)
190
191static irqreturn_t max8925_irq_thread(int irq, void *data)
192{ 472{
193 struct max8925_chip *chip = data; 473 struct max8925_chip *chip = get_irq_chip_data(irq);
194 unsigned long irq_status[INT_STATUS_NUM]; 474 max8925_irqs[irq - chip->irq_base].enable
195 unsigned char status_buf[INT_STATUS_NUM << 1]; 475 = max8925_irqs[irq - chip->irq_base].offs;
196 int i, ret;
197
198 memset(irq_status, 0, sizeof(unsigned long) * INT_STATUS_NUM);
199
200 /* all these interrupt status registers are read-only */
201 switch (chip->chip_id) {
202 case MAX8925_GPM:
203 ret = max8925_bulk_read(chip->i2c, MAX8925_CHG_IRQ1,
204 4, status_buf);
205 if (ret < 0)
206 goto out;
207 ret = max8925_bulk_read(chip->i2c, MAX8925_ON_OFF_IRQ1,
208 2, &status_buf[4]);
209 if (ret < 0)
210 goto out;
211 ret = max8925_bulk_read(chip->i2c, MAX8925_ON_OFF_IRQ2,
212 2, &status_buf[6]);
213 if (ret < 0)
214 goto out;
215 /* clear masked interrupt status */
216 status_buf[0] &= (~status_buf[2] & CHG_IRQ1_MASK);
217 irq_status[0] |= status_buf[0];
218 status_buf[1] &= (~status_buf[3] & CHG_IRQ2_MASK);
219 irq_status[0] |= (status_buf[1] << BITS_PER_BYTE);
220 status_buf[4] &= (~status_buf[5] & ON_OFF_IRQ1_MASK);
221 irq_status[0] |= (status_buf[4] << (BITS_PER_BYTE * 2));
222 status_buf[6] &= (~status_buf[7] & ON_OFF_IRQ2_MASK);
223 irq_status[0] |= (status_buf[6] << (BITS_PER_BYTE * 3));
224 break;
225 case MAX8925_ADC:
226 ret = max8925_bulk_read(chip->i2c, MAX8925_TSC_IRQ,
227 2, status_buf);
228 if (ret < 0)
229 goto out;
230 /* clear masked interrupt status */
231 status_buf[0] &= (~status_buf[1] & TSC_IRQ_MASK);
232 irq_status[0] |= status_buf[0];
233 break;
234 default:
235 goto out;
236 }
237
238 for_each_bit(i, &irq_status[0], MAX8925_NUM_IRQ) {
239 clear_bit(i, irq_status);
240 dev_dbg(chip->dev, "Servicing IRQ #%d in %s\n", i, chip->name);
241
242 mutex_lock(&chip->irq_lock);
243 if (chip->irq[i].handler)
244 chip->irq[i].handler(i, chip->irq[i].data);
245 else {
246 max8925_mask_irq(chip, i);
247 dev_err(chip->dev, "Noboday cares IRQ #%d in %s. "
248 "Now mask it.\n", i, chip->name);
249 }
250 mutex_unlock(&chip->irq_lock);
251 }
252out:
253 return IRQ_HANDLED;
254} 476}
255 477
256int max8925_request_irq(struct max8925_chip *chip, int irq, 478static void max8925_irq_disable(unsigned int irq)
257 irq_handler_t handler, void *data)
258{ 479{
259 if ((__check_irq(irq) < 0) || !handler) 480 struct max8925_chip *chip = get_irq_chip_data(irq);
260 return -EINVAL; 481 max8925_irqs[irq - chip->irq_base].enable = 0;
261
262 mutex_lock(&chip->irq_lock);
263 chip->irq[irq].handler = handler;
264 chip->irq[irq].data = data;
265 mutex_unlock(&chip->irq_lock);
266 return 0;
267} 482}
268EXPORT_SYMBOL(max8925_request_irq);
269 483
270int max8925_free_irq(struct max8925_chip *chip, int irq) 484static struct irq_chip max8925_irq_chip = {
485 .name = "max8925",
486 .bus_lock = max8925_irq_lock,
487 .bus_sync_unlock = max8925_irq_sync_unlock,
488 .enable = max8925_irq_enable,
489 .disable = max8925_irq_disable,
490};
491
492static int max8925_irq_init(struct max8925_chip *chip, int irq,
493 struct max8925_platform_data *pdata)
271{ 494{
272 if (__check_irq(irq) < 0) 495 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
496 struct irq_desc *desc;
497 int i, ret;
498 int __irq;
499
500 if (!pdata || !pdata->irq_base) {
501 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
273 return -EINVAL; 502 return -EINVAL;
503 }
504 /* clear all interrupts */
505 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
506 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
507 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1);
508 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2);
509 max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ);
510 max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
511 /* mask all interrupts */
512 max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0);
513 max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0);
514 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff);
515 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff);
516 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff);
517 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff);
518 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
519 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff);
520
521 mutex_init(&chip->irq_lock);
522 chip->core_irq = irq;
523 chip->irq_base = pdata->irq_base;
524 desc = irq_to_desc(chip->core_irq);
525
526 /* register with genirq */
527 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
528 __irq = i + chip->irq_base;
529 set_irq_chip_data(__irq, chip);
530 set_irq_chip_and_handler(__irq, &max8925_irq_chip,
531 handle_edge_irq);
532 set_irq_nested_thread(__irq, 1);
533#ifdef CONFIG_ARM
534 set_irq_flags(__irq, IRQF_VALID);
535#else
536 set_irq_noprobe(__irq);
537#endif
538 }
539 if (!irq) {
540 dev_warn(chip->dev, "No interrupt support on core IRQ\n");
541 goto tsc_irq;
542 }
274 543
275 mutex_lock(&chip->irq_lock); 544 ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
276 chip->irq[irq].handler = NULL; 545 "max8925", chip);
277 chip->irq[irq].data = NULL; 546 if (ret) {
278 mutex_unlock(&chip->irq_lock); 547 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
548 chip->core_irq = 0;
549 }
550tsc_irq:
551 if (!pdata->tsc_irq) {
552 dev_warn(chip->dev, "No interrupt support on TSC IRQ\n");
553 return 0;
554 }
555 chip->tsc_irq = pdata->tsc_irq;
556
557 ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
558 flags, "max8925-tsc", chip);
559 if (ret) {
560 dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
561 chip->tsc_irq = 0;
562 }
279 return 0; 563 return 0;
280} 564}
281EXPORT_SYMBOL(max8925_free_irq);
282 565
283static int __devinit device_gpm_init(struct max8925_chip *chip, 566int __devinit max8925_device_init(struct max8925_chip *chip,
284 struct i2c_client *i2c, 567 struct max8925_platform_data *pdata)
285 struct max8925_platform_data *pdata)
286{ 568{
287 int ret; 569 int ret;
288 570
289 /* mask all IRQs */ 571 max8925_irq_init(chip, chip->i2c->irq, pdata);
290 ret = max8925_set_bits(i2c, MAX8925_CHG_IRQ1_MASK, 0x7, 0x7); 572
291 if (ret < 0) 573 if (pdata && (pdata->power || pdata->touch)) {
292 goto out; 574 /* enable ADC to control internal reference */
293 ret = max8925_set_bits(i2c, MAX8925_CHG_IRQ2_MASK, 0xff, 0xff); 575 max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1);
294 if (ret < 0) 576 /* enable internal reference for ADC */
295 goto out; 577 max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2);
296 ret = max8925_set_bits(i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff, 0xff); 578 /* check for internal reference IRQ */
297 if (ret < 0) 579 do {
298 goto out; 580 ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
299 ret = max8925_set_bits(i2c, MAX8925_ON_OFF_IRQ2_MASK, 0x3, 0x3); 581 } while (ret & MAX8925_NREF_OK);
300 if (ret < 0) 582 /* enaable ADC scheduler, interval is 1 second */
301 goto out; 583 max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
302
303 chip->name = "GPM";
304 memset(chip->irq, 0, sizeof(struct max8925_irq) * MAX8925_NUM_IRQ);
305 ret = request_threaded_irq(i2c->irq, NULL, max8925_irq_thread,
306 IRQF_ONESHOT | IRQF_TRIGGER_LOW,
307 "max8925-gpm", chip);
308 if (ret < 0) {
309 dev_err(chip->dev, "Failed to request IRQ #%d.\n", i2c->irq);
310 goto out;
311 } 584 }
312 chip->chip_irq = i2c->irq;
313 585
314 /* enable hard-reset for ONKEY power-off */ 586 /* enable Momentary Power Loss */
315 max8925_set_bits(i2c, MAX8925_SYSENSEL, 0x80, 0x80); 587 max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
316 588
317 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0], 589 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
318 ARRAY_SIZE(regulator_devs), 590 ARRAY_SIZE(rtc_devs),
319 &regulator_resources[0], 0); 591 &rtc_resources[0], 0);
320 if (ret < 0) { 592 if (ret < 0) {
321 dev_err(chip->dev, "Failed to add regulator subdev\n"); 593 dev_err(chip->dev, "Failed to add rtc subdev\n");
322 goto out_irq; 594 goto out;
595 }
596 if (pdata && pdata->regulator[0]) {
597 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
598 ARRAY_SIZE(regulator_devs),
599 &regulator_resources[0], 0);
600 if (ret < 0) {
601 dev_err(chip->dev, "Failed to add regulator subdev\n");
602 goto out_dev;
603 }
323 } 604 }
324 605
325 if (pdata && pdata->backlight) { 606 if (pdata && pdata->backlight) {
@@ -331,35 +612,17 @@ static int __devinit device_gpm_init(struct max8925_chip *chip,
331 goto out_dev; 612 goto out_dev;
332 } 613 }
333 } 614 }
334 return 0;
335out_dev:
336 mfd_remove_devices(chip->dev);
337out_irq:
338 if (chip->chip_irq)
339 free_irq(chip->chip_irq, chip);
340out:
341 return ret;
342}
343
344static int __devinit device_adc_init(struct max8925_chip *chip,
345 struct i2c_client *i2c,
346 struct max8925_platform_data *pdata)
347{
348 int ret;
349
350 /* mask all IRQs */
351 ret = max8925_set_bits(i2c, MAX8925_TSC_IRQ_MASK, 3, 3);
352 615
353 chip->name = "ADC"; 616 if (pdata && pdata->power) {
354 memset(chip->irq, 0, sizeof(struct max8925_irq) * MAX8925_NUM_IRQ); 617 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
355 ret = request_threaded_irq(i2c->irq, NULL, max8925_irq_thread, 618 ARRAY_SIZE(power_devs),
356 IRQF_ONESHOT | IRQF_TRIGGER_LOW, 619 &power_supply_resources[0], 0);
357 "max8925-adc", chip); 620 if (ret < 0) {
358 if (ret < 0) { 621 dev_err(chip->dev, "Failed to add power supply "
359 dev_err(chip->dev, "Failed to request IRQ #%d.\n", i2c->irq); 622 "subdev\n");
360 goto out; 623 goto out_dev;
624 }
361 } 625 }
362 chip->chip_irq = i2c->irq;
363 626
364 if (pdata && pdata->touch) { 627 if (pdata && pdata->touch) {
365 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 628 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
@@ -367,38 +630,27 @@ static int __devinit device_adc_init(struct max8925_chip *chip,
367 &touch_resources[0], 0); 630 &touch_resources[0], 0);
368 if (ret < 0) { 631 if (ret < 0) {
369 dev_err(chip->dev, "Failed to add touch subdev\n"); 632 dev_err(chip->dev, "Failed to add touch subdev\n");
370 goto out_irq; 633 goto out_dev;
371 } 634 }
372 } 635 }
636
373 return 0; 637 return 0;
374out_irq: 638out_dev:
375 if (chip->chip_irq) 639 mfd_remove_devices(chip->dev);
376 free_irq(chip->chip_irq, chip);
377out: 640out:
378 return ret; 641 return ret;
379} 642}
380 643
381int __devinit max8925_device_init(struct max8925_chip *chip, 644void __devexit max8925_device_exit(struct max8925_chip *chip)
382 struct max8925_platform_data *pdata)
383{ 645{
384 switch (chip->chip_id) { 646 if (chip->core_irq)
385 case MAX8925_GPM: 647 free_irq(chip->core_irq, chip);
386 device_gpm_init(chip, chip->i2c, pdata); 648 if (chip->tsc_irq)
387 break; 649 free_irq(chip->tsc_irq, chip);
388 case MAX8925_ADC:
389 device_adc_init(chip, chip->i2c, pdata);
390 break;
391 }
392 return 0;
393}
394
395void max8925_device_exit(struct max8925_chip *chip)
396{
397 if (chip->chip_irq >= 0)
398 free_irq(chip->chip_irq, chip);
399 mfd_remove_devices(chip->dev); 650 mfd_remove_devices(chip->dev);
400} 651}
401 652
653
402MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925"); 654MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
403MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com"); 655MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
404MODULE_LICENSE("GPL"); 656MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max8925.h b/include/linux/mfd/max8925.h
index b72dbe174d51..18c1844ed472 100644
--- a/include/linux/mfd/max8925.h
+++ b/include/linux/mfd/max8925.h
@@ -12,6 +12,7 @@
12#ifndef __LINUX_MFD_MAX8925_H 12#ifndef __LINUX_MFD_MAX8925_H
13#define __LINUX_MFD_MAX8925_H 13#define __LINUX_MFD_MAX8925_H
14 14
15#include <linux/mutex.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
16 17
17/* Unified sub device IDs for MAX8925 */ 18/* Unified sub device IDs for MAX8925 */
@@ -39,6 +40,30 @@ enum {
39 MAX8925_ID_LDO18, 40 MAX8925_ID_LDO18,
40 MAX8925_ID_LDO19, 41 MAX8925_ID_LDO19,
41 MAX8925_ID_LDO20, 42 MAX8925_ID_LDO20,
43 MAX8925_ID_MAX,
44};
45
46enum {
47 /*
48 * Charging current threshold trigger going from fast charge
49 * to TOPOFF charge. From 5% to 20% of fasting charging current.
50 */
51 MAX8925_TOPOFF_THR_5PER,
52 MAX8925_TOPOFF_THR_10PER,
53 MAX8925_TOPOFF_THR_15PER,
54 MAX8925_TOPOFF_THR_20PER,
55};
56
57enum {
58 /* Fast charging current */
59 MAX8925_FCHG_85MA,
60 MAX8925_FCHG_300MA,
61 MAX8925_FCHG_460MA,
62 MAX8925_FCHG_600MA,
63 MAX8925_FCHG_700MA,
64 MAX8925_FCHG_800MA,
65 MAX8925_FCHG_900MA,
66 MAX8925_FCHG_1000MA,
42}; 67};
43 68
44/* Charger registers */ 69/* Charger registers */
@@ -46,12 +71,13 @@ enum {
46#define MAX8925_CHG_IRQ2 (0x7f) 71#define MAX8925_CHG_IRQ2 (0x7f)
47#define MAX8925_CHG_IRQ1_MASK (0x80) 72#define MAX8925_CHG_IRQ1_MASK (0x80)
48#define MAX8925_CHG_IRQ2_MASK (0x81) 73#define MAX8925_CHG_IRQ2_MASK (0x81)
74#define MAX8925_CHG_STATUS (0x82)
49 75
50/* GPM registers */ 76/* GPM registers */
51#define MAX8925_SYSENSEL (0x00) 77#define MAX8925_SYSENSEL (0x00)
52#define MAX8925_ON_OFF_IRQ1 (0x01) 78#define MAX8925_ON_OFF_IRQ1 (0x01)
53#define MAX8925_ON_OFF_IRQ1_MASK (0x02) 79#define MAX8925_ON_OFF_IRQ1_MASK (0x02)
54#define MAX8925_ON_OFF_STAT (0x03) 80#define MAX8925_ON_OFF_STATUS (0x03)
55#define MAX8925_ON_OFF_IRQ2 (0x0d) 81#define MAX8925_ON_OFF_IRQ2 (0x0d)
56#define MAX8925_ON_OFF_IRQ2_MASK (0x0e) 82#define MAX8925_ON_OFF_IRQ2_MASK (0x0e)
57#define MAX8925_RESET_CNFG (0x0f) 83#define MAX8925_RESET_CNFG (0x0f)
@@ -59,12 +85,18 @@ enum {
59/* Touch registers */ 85/* Touch registers */
60#define MAX8925_TSC_IRQ (0x00) 86#define MAX8925_TSC_IRQ (0x00)
61#define MAX8925_TSC_IRQ_MASK (0x01) 87#define MAX8925_TSC_IRQ_MASK (0x01)
88#define MAX8925_TSC_CNFG1 (0x02)
89#define MAX8925_ADC_SCHED (0x10)
62#define MAX8925_ADC_RES_END (0x6f) 90#define MAX8925_ADC_RES_END (0x6f)
63 91
92#define MAX8925_NREF_OK (1 << 4)
93
64/* RTC registers */ 94/* RTC registers */
65#define MAX8925_RTC_STATUS (0x1a) 95#define MAX8925_ALARM0_CNTL (0x18)
96#define MAX8925_ALARM1_CNTL (0x19)
66#define MAX8925_RTC_IRQ (0x1c) 97#define MAX8925_RTC_IRQ (0x1c)
67#define MAX8925_RTC_IRQ_MASK (0x1d) 98#define MAX8925_RTC_IRQ_MASK (0x1d)
99#define MAX8925_MPL_CNTL (0x1e)
68 100
69/* WLED registers */ 101/* WLED registers */
70#define MAX8925_WLED_MODE_CNTL (0x84) 102#define MAX8925_WLED_MODE_CNTL (0x84)
@@ -126,45 +158,48 @@ enum {
126#define TSC_IRQ_MASK (0x03) 158#define TSC_IRQ_MASK (0x03)
127#define RTC_IRQ_MASK (0x0c) 159#define RTC_IRQ_MASK (0x0c)
128 160
129#define MAX8925_NUM_IRQ (32) 161#define MAX8925_GPM_NUM_IRQ (40)
162#define MAX8925_ADC_NUM_IRQ (8)
163#define MAX8925_NUM_IRQ (MAX8925_GPM_NUM_IRQ \
164 + MAX8925_ADC_NUM_IRQ)
165
166#define MAX8925_MAX_REGULATOR (23)
130 167
131#define MAX8925_NAME_SIZE (32) 168#define MAX8925_NAME_SIZE (32)
132 169
170/* IRQ definitions */
133enum { 171enum {
134 MAX8925_INVALID = 0, 172 MAX8925_IRQ_VCHG_DC_OVP,
135 MAX8925_RTC, 173 MAX8925_IRQ_VCHG_DC_F,
136 MAX8925_ADC, 174 MAX8925_IRQ_VCHG_DC_R,
137 MAX8925_GPM, /* general power management */ 175 MAX8925_IRQ_VCHG_USB_OVP,
138 MAX8925_MAX, 176 MAX8925_IRQ_VCHG_USB_F,
177 MAX8925_IRQ_VCHG_USB_R,
178 MAX8925_IRQ_VCHG_THM_OK_R,
179 MAX8925_IRQ_VCHG_THM_OK_F,
180 MAX8925_IRQ_VCHG_SYSLOW_F,
181 MAX8925_IRQ_VCHG_SYSLOW_R,
182 MAX8925_IRQ_VCHG_RST,
183 MAX8925_IRQ_VCHG_DONE,
184 MAX8925_IRQ_VCHG_TOPOFF,
185 MAX8925_IRQ_VCHG_TMR_FAULT,
186 MAX8925_IRQ_GPM_RSTIN,
187 MAX8925_IRQ_GPM_MPL,
188 MAX8925_IRQ_GPM_SW_3SEC,
189 MAX8925_IRQ_GPM_EXTON_F,
190 MAX8925_IRQ_GPM_EXTON_R,
191 MAX8925_IRQ_GPM_SW_1SEC,
192 MAX8925_IRQ_GPM_SW_F,
193 MAX8925_IRQ_GPM_SW_R,
194 MAX8925_IRQ_GPM_SYSCKEN_F,
195 MAX8925_IRQ_GPM_SYSCKEN_R,
196 MAX8925_IRQ_RTC_ALARM1,
197 MAX8925_IRQ_RTC_ALARM0,
198 MAX8925_IRQ_TSC_STICK,
199 MAX8925_IRQ_TSC_NSTICK,
200 MAX8925_NR_IRQS,
139}; 201};
140 202
141#define MAX8925_IRQ_VCHG_OVP (0)
142#define MAX8925_IRQ_VCHG_F (1)
143#define MAX8925_IRQ_VCHG_R (2)
144#define MAX8925_IRQ_VCHG_THM_OK_R (8)
145#define MAX8925_IRQ_VCHG_THM_OK_F (9)
146#define MAX8925_IRQ_VCHG_BATTLOW_F (10)
147#define MAX8925_IRQ_VCHG_BATTLOW_R (11)
148#define MAX8925_IRQ_VCHG_RST (12)
149#define MAX8925_IRQ_VCHG_DONE (13)
150#define MAX8925_IRQ_VCHG_TOPOFF (14)
151#define MAX8925_IRQ_VCHG_TMR_FAULT (15)
152#define MAX8925_IRQ_GPM_RSTIN (16)
153#define MAX8925_IRQ_GPM_MPL (17)
154#define MAX8925_IRQ_GPM_SW_3SEC (18)
155#define MAX8925_IRQ_GPM_EXTON_F (19)
156#define MAX8925_IRQ_GPM_EXTON_R (20)
157#define MAX8925_IRQ_GPM_SW_1SEC (21)
158#define MAX8925_IRQ_GPM_SW_F (22)
159#define MAX8925_IRQ_GPM_SW_R (23)
160#define MAX8925_IRQ_GPM_SYSCKEN_F (24)
161#define MAX8925_IRQ_GPM_SYSCKEN_R (25)
162
163#define MAX8925_IRQ_TSC_STICK (0)
164#define MAX8925_IRQ_TSC_NSTICK (1)
165
166#define MAX8925_MAX_REGULATOR (23)
167
168struct max8925_irq { 203struct max8925_irq {
169 irq_handler_t handler; 204 irq_handler_t handler;
170 void *data; 205 void *data;
@@ -172,14 +207,16 @@ struct max8925_irq {
172 207
173struct max8925_chip { 208struct max8925_chip {
174 struct device *dev; 209 struct device *dev;
210 struct i2c_client *i2c;
211 struct i2c_client *adc;
212 struct i2c_client *rtc;
213 struct max8925_irq irqs[MAX8925_NUM_IRQ];
175 struct mutex io_lock; 214 struct mutex io_lock;
176 struct mutex irq_lock; 215 struct mutex irq_lock;
177 struct i2c_client *i2c;
178 struct max8925_irq irq[MAX8925_NUM_IRQ];
179 216
180 const char *name; 217 int irq_base;
181 int chip_id; 218 int core_irq;
182 int chip_irq; 219 int tsc_irq;
183}; 220};
184 221
185struct max8925_backlight_pdata { 222struct max8925_backlight_pdata {
@@ -192,13 +229,25 @@ struct max8925_touch_pdata {
192 unsigned int flags; 229 unsigned int flags;
193}; 230};
194 231
232struct max8925_power_pdata {
233 int (*set_charger)(int);
234 unsigned batt_detect:1;
235 unsigned topoff_threshold:2;
236 unsigned fast_charge:3; /* charge current */
237};
238
239/*
240 * irq_base: stores IRQ base number of MAX8925 in platform
241 * tsc_irq: stores IRQ number of MAX8925 TSC
242 */
195struct max8925_platform_data { 243struct max8925_platform_data {
196 struct max8925_backlight_pdata *backlight; 244 struct max8925_backlight_pdata *backlight;
197 struct max8925_touch_pdata *touch; 245 struct max8925_touch_pdata *touch;
246 struct max8925_power_pdata *power;
198 struct regulator_init_data *regulator[MAX8925_MAX_REGULATOR]; 247 struct regulator_init_data *regulator[MAX8925_MAX_REGULATOR];
199 248
200 int chip_id; 249 int irq_base;
201 int chip_irq; 250 int tsc_irq;
202}; 251};
203 252
204extern int max8925_reg_read(struct i2c_client *, int); 253extern int max8925_reg_read(struct i2c_client *, int);
@@ -208,6 +257,12 @@ extern int max8925_bulk_write(struct i2c_client *, int, int, unsigned char *);
208extern int max8925_set_bits(struct i2c_client *, int, unsigned char, 257extern int max8925_set_bits(struct i2c_client *, int, unsigned char,
209 unsigned char); 258 unsigned char);
210 259
260extern int max8925_request_irq(struct max8925_chip *, int,
261 irq_handler_t, void *);
262extern int max8925_free_irq(struct max8925_chip *, int);
263extern int max8925_mask_irq(struct max8925_chip *, int);
264extern int max8925_unmask_irq(struct max8925_chip *, int);
265
211extern int max8925_device_init(struct max8925_chip *, 266extern int max8925_device_init(struct max8925_chip *,
212 struct max8925_platform_data *); 267 struct max8925_platform_data *);
213extern void max8925_device_exit(struct max8925_chip *); 268extern void max8925_device_exit(struct max8925_chip *);