aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c15
-rw-r--r--drivers/mfd/88pm860x-core.c408
-rw-r--r--include/linux/mfd/88pm860x.h30
3 files changed, 311 insertions, 142 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index 56254d2a1f6e..286bb490a9f2 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -54,7 +54,6 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
54 int z1, z2, rt = 0; 54 int z1, z2, rt = 0;
55 int ret; 55 int ret;
56 56
57 pm860x_mask_irq(chip, irq);
58 ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf); 57 ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
59 if (ret < 0) 58 if (ret < 0)
60 goto out; 59 goto out;
@@ -83,7 +82,6 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
83 dev_dbg(chip->dev, "pen release\n"); 82 dev_dbg(chip->dev, "pen release\n");
84 } 83 }
85 input_sync(touch->idev); 84 input_sync(touch->idev);
86 pm860x_unmask_irq(chip, irq);
87 85
88out: 86out:
89 return IRQ_HANDLED; 87 return IRQ_HANDLED;
@@ -92,7 +90,6 @@ out:
92static int pm860x_touch_open(struct input_dev *dev) 90static int pm860x_touch_open(struct input_dev *dev)
93{ 91{
94 struct pm860x_touch *touch = input_get_drvdata(dev); 92 struct pm860x_touch *touch = input_get_drvdata(dev);
95 struct pm860x_chip *chip = touch->chip;
96 int data, ret; 93 int data, ret;
97 94
98 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN 95 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
@@ -100,7 +97,6 @@ static int pm860x_touch_open(struct input_dev *dev)
100 ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data); 97 ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
101 if (ret < 0) 98 if (ret < 0)
102 goto out; 99 goto out;
103 pm860x_unmask_irq(chip, touch->irq);
104 return 0; 100 return 0;
105out: 101out:
106 return ret; 102 return ret;
@@ -109,13 +105,11 @@ out:
109static void pm860x_touch_close(struct input_dev *dev) 105static void pm860x_touch_close(struct input_dev *dev)
110{ 106{
111 struct pm860x_touch *touch = input_get_drvdata(dev); 107 struct pm860x_touch *touch = input_get_drvdata(dev);
112 struct pm860x_chip *chip = touch->chip;
113 int data; 108 int data;
114 109
115 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN 110 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
116 | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN; 111 | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
117 pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); 112 pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
118 pm860x_mask_irq(chip, touch->irq);
119} 113}
120 114
121static int __devinit pm860x_touch_probe(struct platform_device *pdev) 115static int __devinit pm860x_touch_probe(struct platform_device *pdev)
@@ -164,11 +158,12 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
164 touch->idev->close = pm860x_touch_close; 158 touch->idev->close = pm860x_touch_close;
165 touch->chip = chip; 159 touch->chip = chip;
166 touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 160 touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
167 touch->irq = irq; 161 touch->irq = irq + chip->irq_base;
168 touch->res_x = pdata->res_x; 162 touch->res_x = pdata->res_x;
169 input_set_drvdata(touch->idev, touch); 163 input_set_drvdata(touch->idev, touch);
170 164
171 ret = pm860x_request_irq(chip, irq, pm860x_touch_handler, touch); 165 ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
166 IRQF_ONESHOT, "touch", touch);
172 if (ret < 0) 167 if (ret < 0)
173 goto out_irq; 168 goto out_irq;
174 169
@@ -194,7 +189,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
194 platform_set_drvdata(pdev, touch); 189 platform_set_drvdata(pdev, touch);
195 return 0; 190 return 0;
196out_rg: 191out_rg:
197 pm860x_free_irq(chip, irq); 192 free_irq(touch->irq, touch);
198out_irq: 193out_irq:
199 input_free_device(touch->idev); 194 input_free_device(touch->idev);
200out: 195out:
@@ -207,7 +202,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
207 struct pm860x_touch *touch = platform_get_drvdata(pdev); 202 struct pm860x_touch *touch = platform_get_drvdata(pdev);
208 203
209 input_unregister_device(touch->idev); 204 input_unregister_device(touch->idev);
210 pm860x_free_irq(touch->chip, touch->irq); 205 free_irq(touch->irq, touch);
211 platform_set_drvdata(pdev, NULL); 206 platform_set_drvdata(pdev, NULL);
212 kfree(touch); 207 kfree(touch);
213 return 0; 208 return 0;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 16f0dca707a7..6a14d2b1ccf0 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -12,11 +12,14 @@
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/88pm860x.h> 19#include <linux/mfd/88pm860x.h>
19 20
21#define INT_STATUS_NUM 3
22
20char pm860x_backlight_name[][MFD_NAME_SIZE] = { 23char pm860x_backlight_name[][MFD_NAME_SIZE] = {
21 "backlight-0", 24 "backlight-0",
22 "backlight-1", 25 "backlight-1",
@@ -119,6 +122,42 @@ static struct mfd_cell touch_devs[] = {
119 .flags = IORESOURCE_IO, \ 122 .flags = IORESOURCE_IO, \
120} 123}
121 124
125static struct resource power_supply_resources[] = {
126 {
127 .name = "88pm860x-power",
128 .start = PM8607_IRQ_CHG,
129 .end = PM8607_IRQ_CHG,
130 .flags = IORESOURCE_IRQ,
131 },
132};
133
134static struct mfd_cell power_devs[] = {
135 {
136 .name = "88pm860x-power",
137 .num_resources = 1,
138 .resources = &power_supply_resources[0],
139 .id = -1,
140 },
141};
142
143static struct resource onkey_resources[] = {
144 {
145 .name = "88pm860x-onkey",
146 .start = PM8607_IRQ_ONKEY,
147 .end = PM8607_IRQ_ONKEY,
148 .flags = IORESOURCE_IRQ,
149 },
150};
151
152static struct mfd_cell onkey_devs[] = {
153 {
154 .name = "88pm860x-onkey",
155 .num_resources = 1,
156 .resources = &onkey_resources[0],
157 .id = -1,
158 },
159};
160
122static struct resource regulator_resources[] = { 161static struct resource regulator_resources[] = {
123 PM8607_REG_RESOURCE(BUCK1, BUCK1), 162 PM8607_REG_RESOURCE(BUCK1, BUCK1),
124 PM8607_REG_RESOURCE(BUCK2, BUCK2), 163 PM8607_REG_RESOURCE(BUCK2, BUCK2),
@@ -163,129 +202,224 @@ static struct mfd_cell regulator_devs[] = {
163 PM8607_REG_DEVS(ldo14, LDO14), 202 PM8607_REG_DEVS(ldo14, LDO14),
164}; 203};
165 204
166#define CHECK_IRQ(irq) \ 205struct pm860x_irq_data {
167do { \ 206 int reg;
168 if ((irq < 0) || (irq >= PM860X_NUM_IRQ)) \ 207 int mask_reg;
169 return -EINVAL; \ 208 int enable; /* enable or not */
170} while (0) 209 int offs; /* bit offset in mask register */
171 210};
172/* IRQs only occur on 88PM8607 */
173int pm860x_mask_irq(struct pm860x_chip *chip, int irq)
174{
175 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
176 : chip->companion;
177 int offset, data, ret;
178
179 CHECK_IRQ(irq);
180
181 offset = (irq >> 3) + PM8607_INT_MASK_1;
182 data = 1 << (irq % 8);
183 ret = pm860x_set_bits(i2c, offset, data, 0);
184 211
185 return ret; 212static struct pm860x_irq_data pm860x_irqs[] = {
186} 213 [PM8607_IRQ_ONKEY] = {
187EXPORT_SYMBOL(pm860x_mask_irq); 214 .reg = PM8607_INT_STATUS1,
215 .mask_reg = PM8607_INT_MASK_1,
216 .offs = 1 << 0,
217 },
218 [PM8607_IRQ_EXTON] = {
219 .reg = PM8607_INT_STATUS1,
220 .mask_reg = PM8607_INT_MASK_1,
221 .offs = 1 << 1,
222 },
223 [PM8607_IRQ_CHG] = {
224 .reg = PM8607_INT_STATUS1,
225 .mask_reg = PM8607_INT_MASK_1,
226 .offs = 1 << 2,
227 },
228 [PM8607_IRQ_BAT] = {
229 .reg = PM8607_INT_STATUS1,
230 .mask_reg = PM8607_INT_MASK_1,
231 .offs = 1 << 3,
232 },
233 [PM8607_IRQ_RTC] = {
234 .reg = PM8607_INT_STATUS1,
235 .mask_reg = PM8607_INT_MASK_1,
236 .offs = 1 << 4,
237 },
238 [PM8607_IRQ_CC] = {
239 .reg = PM8607_INT_STATUS1,
240 .mask_reg = PM8607_INT_MASK_1,
241 .offs = 1 << 5,
242 },
243 [PM8607_IRQ_VBAT] = {
244 .reg = PM8607_INT_STATUS2,
245 .mask_reg = PM8607_INT_MASK_2,
246 .offs = 1 << 0,
247 },
248 [PM8607_IRQ_VCHG] = {
249 .reg = PM8607_INT_STATUS2,
250 .mask_reg = PM8607_INT_MASK_2,
251 .offs = 1 << 1,
252 },
253 [PM8607_IRQ_VSYS] = {
254 .reg = PM8607_INT_STATUS2,
255 .mask_reg = PM8607_INT_MASK_2,
256 .offs = 1 << 2,
257 },
258 [PM8607_IRQ_TINT] = {
259 .reg = PM8607_INT_STATUS2,
260 .mask_reg = PM8607_INT_MASK_2,
261 .offs = 1 << 3,
262 },
263 [PM8607_IRQ_GPADC0] = {
264 .reg = PM8607_INT_STATUS2,
265 .mask_reg = PM8607_INT_MASK_2,
266 .offs = 1 << 4,
267 },
268 [PM8607_IRQ_GPADC1] = {
269 .reg = PM8607_INT_STATUS2,
270 .mask_reg = PM8607_INT_MASK_2,
271 .offs = 1 << 5,
272 },
273 [PM8607_IRQ_GPADC2] = {
274 .reg = PM8607_INT_STATUS2,
275 .mask_reg = PM8607_INT_MASK_2,
276 .offs = 1 << 6,
277 },
278 [PM8607_IRQ_GPADC3] = {
279 .reg = PM8607_INT_STATUS2,
280 .mask_reg = PM8607_INT_MASK_2,
281 .offs = 1 << 7,
282 },
283 [PM8607_IRQ_AUDIO_SHORT] = {
284 .reg = PM8607_INT_STATUS3,
285 .mask_reg = PM8607_INT_MASK_3,
286 .offs = 1 << 0,
287 },
288 [PM8607_IRQ_PEN] = {
289 .reg = PM8607_INT_STATUS3,
290 .mask_reg = PM8607_INT_MASK_3,
291 .offs = 1 << 1,
292 },
293 [PM8607_IRQ_HEADSET] = {
294 .reg = PM8607_INT_STATUS3,
295 .mask_reg = PM8607_INT_MASK_3,
296 .offs = 1 << 2,
297 },
298 [PM8607_IRQ_HOOK] = {
299 .reg = PM8607_INT_STATUS3,
300 .mask_reg = PM8607_INT_MASK_3,
301 .offs = 1 << 3,
302 },
303 [PM8607_IRQ_MICIN] = {
304 .reg = PM8607_INT_STATUS3,
305 .mask_reg = PM8607_INT_MASK_3,
306 .offs = 1 << 4,
307 },
308 [PM8607_IRQ_CHG_FAIL] = {
309 .reg = PM8607_INT_STATUS3,
310 .mask_reg = PM8607_INT_MASK_3,
311 .offs = 1 << 5,
312 },
313 [PM8607_IRQ_CHG_DONE] = {
314 .reg = PM8607_INT_STATUS3,
315 .mask_reg = PM8607_INT_MASK_3,
316 .offs = 1 << 6,
317 },
318 [PM8607_IRQ_CHG_FAULT] = {
319 .reg = PM8607_INT_STATUS3,
320 .mask_reg = PM8607_INT_MASK_3,
321 .offs = 1 << 7,
322 },
323};
188 324
189int pm860x_unmask_irq(struct pm860x_chip *chip, int irq) 325static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
326 int irq)
190{ 327{
191 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 328 return &pm860x_irqs[irq - chip->irq_base];
192 : chip->companion;
193 int offset, data, ret;
194
195 CHECK_IRQ(irq);
196
197 offset = (irq >> 3) + PM8607_INT_MASK_1;
198 data = 1 << (irq % 8);
199 ret = pm860x_set_bits(i2c, offset, data, data);
200
201 return ret;
202} 329}
203EXPORT_SYMBOL(pm860x_unmask_irq);
204 330
205#define INT_STATUS_NUM (3) 331static irqreturn_t pm860x_irq(int irq, void *data)
206
207static irqreturn_t pm8607_irq_thread(int irq, void *data)
208{ 332{
209 DECLARE_BITMAP(irq_status, PM860X_NUM_IRQ);
210 struct pm860x_chip *chip = data; 333 struct pm860x_chip *chip = data;
211 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 334 struct pm860x_irq_data *irq_data;
212 : chip->companion; 335 struct i2c_client *i2c;
213 unsigned char status_buf[INT_STATUS_NUM << 1]; 336 int read_reg = -1, value = 0;
214 unsigned long value; 337 int i;
215 int i, ret; 338
216 339 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
217 irq_status[0] = 0; 340 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
218 341 irq_data = &pm860x_irqs[i];
219 /* read out status register */ 342 if (read_reg != irq_data->reg) {
220 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, 343 read_reg = irq_data->reg;
221 INT_STATUS_NUM << 1, status_buf); 344 value = pm860x_reg_read(i2c, irq_data->reg);
222 if (ret < 0)
223 goto out;
224 if (chip->irq_mode) {
225 /* 0, clear by read. 1, clear by write */
226 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
227 INT_STATUS_NUM, status_buf);
228 if (ret < 0)
229 goto out;
230 }
231
232 /* clear masked interrupt status */
233 for (i = 0, value = 0; i < INT_STATUS_NUM; i++) {
234 status_buf[i] &= status_buf[i + INT_STATUS_NUM];
235 irq_status[0] |= status_buf[i] << (i * 8);
236 }
237
238 while (!bitmap_empty(irq_status, PM860X_NUM_IRQ)) {
239 irq = find_first_bit(irq_status, PM860X_NUM_IRQ);
240 clear_bit(irq, irq_status);
241 dev_dbg(chip->dev, "Servicing IRQ #%d\n", irq);
242
243 mutex_lock(&chip->irq_lock);
244 if (chip->irq[irq].handler)
245 chip->irq[irq].handler(irq, chip->irq[irq].data);
246 else {
247 pm860x_mask_irq(chip, irq);
248 dev_err(chip->dev, "Nobody cares IRQ %d. "
249 "Now mask it.\n", irq);
250 for (i = 0; i < (INT_STATUS_NUM << 1); i++) {
251 dev_err(chip->dev, "status[%d]:%x\n", i,
252 status_buf[i]);
253 }
254 } 345 }
255 mutex_unlock(&chip->irq_lock); 346 if (value & irq_data->enable)
347 handle_nested_irq(chip->irq_base + i);
256 } 348 }
257out:
258 return IRQ_HANDLED; 349 return IRQ_HANDLED;
259} 350}
260 351
261int pm860x_request_irq(struct pm860x_chip *chip, int irq, 352static void pm860x_irq_lock(unsigned int irq)
262 irq_handler_t handler, void *data)
263{ 353{
264 CHECK_IRQ(irq); 354 struct pm860x_chip *chip = get_irq_chip_data(irq);
265 if (!handler)
266 return -EINVAL;
267 355
268 mutex_lock(&chip->irq_lock); 356 mutex_lock(&chip->irq_lock);
269 chip->irq[irq].handler = handler;
270 chip->irq[irq].data = data;
271 mutex_unlock(&chip->irq_lock);
272
273 return 0;
274} 357}
275EXPORT_SYMBOL(pm860x_request_irq);
276 358
277int pm860x_free_irq(struct pm860x_chip *chip, int irq) 359static void pm860x_irq_sync_unlock(unsigned int irq)
278{ 360{
279 CHECK_IRQ(irq); 361 struct pm860x_chip *chip = get_irq_chip_data(irq);
362 struct pm860x_irq_data *irq_data;
363 struct i2c_client *i2c;
364 static unsigned char cached[3] = {0x0, 0x0, 0x0};
365 unsigned char mask[3];
366 int i;
367
368 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
369 /* Load cached value. In initial, all IRQs are masked */
370 for (i = 0; i < 3; i++)
371 mask[i] = cached[i];
372 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
373 irq_data = &pm860x_irqs[i];
374 switch (irq_data->mask_reg) {
375 case PM8607_INT_MASK_1:
376 mask[0] &= ~irq_data->offs;
377 mask[0] |= irq_data->enable;
378 break;
379 case PM8607_INT_MASK_2:
380 mask[1] &= ~irq_data->offs;
381 mask[1] |= irq_data->enable;
382 break;
383 case PM8607_INT_MASK_3:
384 mask[2] &= ~irq_data->offs;
385 mask[2] |= irq_data->enable;
386 break;
387 default:
388 dev_err(chip->dev, "wrong IRQ\n");
389 break;
390 }
391 }
392 /* update mask into registers */
393 for (i = 0; i < 3; i++) {
394 if (mask[i] != cached[i]) {
395 cached[i] = mask[i];
396 pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
397 }
398 }
280 399
281 mutex_lock(&chip->irq_lock);
282 chip->irq[irq].handler = NULL;
283 chip->irq[irq].data = NULL;
284 mutex_unlock(&chip->irq_lock); 400 mutex_unlock(&chip->irq_lock);
401}
285 402
286 return 0; 403static void pm860x_irq_enable(unsigned int irq)
404{
405 struct pm860x_chip *chip = get_irq_chip_data(irq);
406 pm860x_irqs[irq - chip->irq_base].enable
407 = pm860x_irqs[irq - chip->irq_base].offs;
287} 408}
288EXPORT_SYMBOL(pm860x_free_irq); 409
410static void pm860x_irq_disable(unsigned int irq)
411{
412 struct pm860x_chip *chip = get_irq_chip_data(irq);
413 pm860x_irqs[irq - chip->irq_base].enable = 0;
414}
415
416static struct irq_chip pm860x_irq_chip = {
417 .name = "88pm860x",
418 .bus_lock = pm860x_irq_lock,
419 .bus_sync_unlock = pm860x_irq_sync_unlock,
420 .enable = pm860x_irq_enable,
421 .disable = pm860x_irq_disable,
422};
289 423
290static int __devinit device_gpadc_init(struct pm860x_chip *chip, 424static int __devinit device_gpadc_init(struct pm860x_chip *chip,
291 struct pm860x_platform_data *pdata) 425 struct pm860x_platform_data *pdata)
@@ -348,9 +482,15 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
348 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 482 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
349 : chip->companion; 483 : chip->companion;
350 unsigned char status_buf[INT_STATUS_NUM]; 484 unsigned char status_buf[INT_STATUS_NUM];
351 int data, mask, ret = -EINVAL; 485 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
486 struct irq_desc *desc;
487 int i, data, mask, ret = -EINVAL;
488 int __irq;
352 489
353 mutex_init(&chip->irq_lock); 490 if (!pdata || !pdata->irq_base) {
491 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
492 return -EINVAL;
493 }
354 494
355 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR 495 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
356 | PM8607_B0_MISC1_INT_MASK; 496 | PM8607_B0_MISC1_INT_MASK;
@@ -389,25 +529,45 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
389 if (ret < 0) 529 if (ret < 0)
390 goto out; 530 goto out;
391 531
392 memset(chip->irq, 0, sizeof(struct pm860x_irq) * PM860X_NUM_IRQ); 532 mutex_init(&chip->irq_lock);
393 533 chip->irq_base = pdata->irq_base;
394 ret = request_threaded_irq(i2c->irq, NULL, pm8607_irq_thread, 534 chip->core_irq = i2c->irq;
395 IRQF_ONESHOT | IRQF_TRIGGER_LOW, 535 if (!chip->core_irq)
396 "88PM8607", chip);
397 if (ret < 0) {
398 dev_err(chip->dev, "Failed to request IRQ #%d.\n", i2c->irq);
399 goto out; 536 goto out;
537
538 desc = irq_to_desc(chip->core_irq);
539
540 /* register IRQ by genirq */
541 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
542 __irq = i + chip->irq_base;
543 set_irq_chip_data(__irq, chip);
544 set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
545 handle_edge_irq);
546 set_irq_nested_thread(__irq, 1);
547#ifdef CONFIG_ARM
548 set_irq_flags(__irq, IRQF_VALID);
549#else
550 set_irq_noprobe(__irq);
551#endif
400 } 552 }
401 chip->chip_irq = i2c->irq; 553
554 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
555 "88pm860x", chip);
556 if (ret) {
557 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
558 chip->core_irq = 0;
559 }
560
402 return 0; 561 return 0;
403out: 562out:
563 chip->core_irq = 0;
404 return ret; 564 return ret;
405} 565}
406 566
407static void __devexit device_irq_exit(struct pm860x_chip *chip) 567static void __devexit device_irq_exit(struct pm860x_chip *chip)
408{ 568{
409 if (chip->chip_irq >= 0) 569 if (chip->core_irq)
410 free_irq(chip->chip_irq, chip); 570 free_irq(chip->core_irq, chip);
411} 571}
412 572
413static void __devinit device_8606_init(struct pm860x_chip *chip, 573static void __devinit device_8606_init(struct pm860x_chip *chip,
@@ -513,6 +673,26 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
513 goto out_dev; 673 goto out_dev;
514 } 674 }
515 } 675 }
676
677 if (pdata && pdata->power) {
678 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
679 ARRAY_SIZE(power_devs),
680 &power_supply_resources[0], 0);
681 if (ret < 0) {
682 dev_err(chip->dev, "Failed to add power supply "
683 "subdev\n");
684 goto out_dev;
685 }
686 }
687
688 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
689 ARRAY_SIZE(onkey_devs),
690 &onkey_resources[0], 0);
691 if (ret < 0) {
692 dev_err(chip->dev, "Failed to add onkey subdev\n");
693 goto out_dev;
694 }
695
516 return; 696 return;
517out_dev: 697out_dev:
518 mfd_remove_devices(chip->dev); 698 mfd_remove_devices(chip->dev);
@@ -524,7 +704,7 @@ out:
524int pm860x_device_init(struct pm860x_chip *chip, 704int pm860x_device_init(struct pm860x_chip *chip,
525 struct pm860x_platform_data *pdata) 705 struct pm860x_platform_data *pdata)
526{ 706{
527 chip->chip_irq = -EINVAL; 707 chip->core_irq = 0;
528 708
529 switch (chip->id) { 709 switch (chip->id) {
530 case CHIP_PM8606: 710 case CHIP_PM8606:
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index 80bc82a7ac96..73f92c5feea2 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -262,12 +262,13 @@ enum {
262 262
263/* Interrupt Number in 88PM8607 */ 263/* Interrupt Number in 88PM8607 */
264enum { 264enum {
265 PM8607_IRQ_ONKEY = 0, 265 PM8607_IRQ_ONKEY,
266 PM8607_IRQ_EXTON, 266 PM8607_IRQ_EXTON,
267 PM8607_IRQ_CHG, 267 PM8607_IRQ_CHG,
268 PM8607_IRQ_BAT, 268 PM8607_IRQ_BAT,
269 PM8607_IRQ_RTC, 269 PM8607_IRQ_RTC,
270 PM8607_IRQ_VBAT = 8, 270 PM8607_IRQ_CC,
271 PM8607_IRQ_VBAT,
271 PM8607_IRQ_VCHG, 272 PM8607_IRQ_VCHG,
272 PM8607_IRQ_VSYS, 273 PM8607_IRQ_VSYS,
273 PM8607_IRQ_TINT, 274 PM8607_IRQ_TINT,
@@ -275,7 +276,7 @@ enum {
275 PM8607_IRQ_GPADC1, 276 PM8607_IRQ_GPADC1,
276 PM8607_IRQ_GPADC2, 277 PM8607_IRQ_GPADC2,
277 PM8607_IRQ_GPADC3, 278 PM8607_IRQ_GPADC3,
278 PM8607_IRQ_AUDIO_SHORT = 16, 279 PM8607_IRQ_AUDIO_SHORT,
279 PM8607_IRQ_PEN, 280 PM8607_IRQ_PEN,
280 PM8607_IRQ_HEADSET, 281 PM8607_IRQ_HEADSET,
281 PM8607_IRQ_HOOK, 282 PM8607_IRQ_HOOK,
@@ -291,26 +292,19 @@ enum {
291 PM8607_CHIP_B0 = 0x48, 292 PM8607_CHIP_B0 = 0x48,
292}; 293};
293 294
294#define PM860X_NUM_IRQ 24
295
296struct pm860x_irq {
297 irq_handler_t handler;
298 void *data;
299};
300
301struct pm860x_chip { 295struct pm860x_chip {
302 struct device *dev; 296 struct device *dev;
303 struct mutex io_lock; 297 struct mutex io_lock;
304 struct mutex irq_lock; 298 struct mutex irq_lock;
305 struct i2c_client *client; 299 struct i2c_client *client;
306 struct i2c_client *companion; /* companion chip client */ 300 struct i2c_client *companion; /* companion chip client */
307 struct pm860x_irq irq[PM860X_NUM_IRQ];
308 301
309 int buck3_double; /* DVC ramp slope double */ 302 int buck3_double; /* DVC ramp slope double */
310 unsigned short companion_addr; 303 unsigned short companion_addr;
311 int id; 304 int id;
312 int irq_mode; 305 int irq_mode;
313 int chip_irq; 306 int irq_base;
307 int core_irq;
314 unsigned char chip_version; 308 unsigned char chip_version;
315 309
316}; 310};
@@ -347,14 +341,20 @@ struct pm860x_touch_pdata {
347 unsigned long flags; 341 unsigned long flags;
348}; 342};
349 343
344struct pm860x_power_pdata {
345 unsigned fast_charge; /* charge current */
346};
347
350struct pm860x_platform_data { 348struct pm860x_platform_data {
351 struct pm860x_backlight_pdata *backlight; 349 struct pm860x_backlight_pdata *backlight;
352 struct pm860x_led_pdata *led; 350 struct pm860x_led_pdata *led;
353 struct pm860x_touch_pdata *touch; 351 struct pm860x_touch_pdata *touch;
352 struct pm860x_power_pdata *power;
354 353
355 unsigned short companion_addr; /* I2C address of companion chip */ 354 unsigned short companion_addr; /* I2C address of companion chip */
356 int i2c_port; /* Controlled by GI2C or PI2C */ 355 int i2c_port; /* Controlled by GI2C or PI2C */
357 int irq_mode; /* Clear interrupt by read/write(0/1) */ 356 int irq_mode; /* Clear interrupt by read/write(0/1) */
357 int irq_base; /* IRQ base number of 88pm860x */
358 struct regulator_init_data *regulator[PM8607_MAX_REGULATOR]; 358 struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
359}; 359};
360 360
@@ -368,12 +368,6 @@ extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *);
368extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, 368extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
369 unsigned char); 369 unsigned char);
370 370
371extern int pm860x_mask_irq(struct pm860x_chip *, int);
372extern int pm860x_unmask_irq(struct pm860x_chip *, int);
373extern int pm860x_request_irq(struct pm860x_chip *, int,
374 irq_handler_t handler, void *);
375extern int pm860x_free_irq(struct pm860x_chip *, int);
376
377extern int pm860x_device_init(struct pm860x_chip *chip, 371extern int pm860x_device_init(struct pm860x_chip *chip,
378 struct pm860x_platform_data *pdata); 372 struct pm860x_platform_data *pdata);
379extern void pm860x_device_exit(struct pm860x_chip *chip); 373extern void pm860x_device_exit(struct pm860x_chip *chip);