Merge branch 'master' of git://1984.lsi.us.es/nf
[pandora-kernel.git] / drivers / extcon / extcon-max8997.c
1 /*
2  * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
3  *
4  *  Copyright (C) 2012 Samsung Electrnoics
5  *  Donggeun Kim <dg77.kim@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
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/i2c.h>
21 #include <linux/slab.h>
22 #include <linux/interrupt.h>
23 #include <linux/err.h>
24 #include <linux/platform_device.h>
25 #include <linux/kobject.h>
26 #include <linux/mfd/max8997.h>
27 #include <linux/mfd/max8997-private.h>
28 #include <linux/extcon.h>
29 #include <linux/irqdomain.h>
30
31 #define DEV_NAME                        "max8997-muic"
32
33 /* MAX8997-MUIC STATUS1 register */
34 #define STATUS1_ADC_SHIFT               0
35 #define STATUS1_ADCLOW_SHIFT            5
36 #define STATUS1_ADCERR_SHIFT            6
37 #define STATUS1_ADC_MASK                (0x1f << STATUS1_ADC_SHIFT)
38 #define STATUS1_ADCLOW_MASK             (0x1 << STATUS1_ADCLOW_SHIFT)
39 #define STATUS1_ADCERR_MASK             (0x1 << STATUS1_ADCERR_SHIFT)
40
41 /* MAX8997-MUIC STATUS2 register */
42 #define STATUS2_CHGTYP_SHIFT            0
43 #define STATUS2_CHGDETRUN_SHIFT         3
44 #define STATUS2_DCDTMR_SHIFT            4
45 #define STATUS2_DBCHG_SHIFT             5
46 #define STATUS2_VBVOLT_SHIFT            6
47 #define STATUS2_CHGTYP_MASK             (0x7 << STATUS2_CHGTYP_SHIFT)
48 #define STATUS2_CHGDETRUN_MASK          (0x1 << STATUS2_CHGDETRUN_SHIFT)
49 #define STATUS2_DCDTMR_MASK             (0x1 << STATUS2_DCDTMR_SHIFT)
50 #define STATUS2_DBCHG_MASK              (0x1 << STATUS2_DBCHG_SHIFT)
51 #define STATUS2_VBVOLT_MASK             (0x1 << STATUS2_VBVOLT_SHIFT)
52
53 /* MAX8997-MUIC STATUS3 register */
54 #define STATUS3_OVP_SHIFT               2
55 #define STATUS3_OVP_MASK                (0x1 << STATUS3_OVP_SHIFT)
56
57 /* MAX8997-MUIC CONTROL1 register */
58 #define COMN1SW_SHIFT                   0
59 #define COMP2SW_SHIFT                   3
60 #define COMN1SW_MASK                    (0x7 << COMN1SW_SHIFT)
61 #define COMP2SW_MASK                    (0x7 << COMP2SW_SHIFT)
62 #define SW_MASK                         (COMP2SW_MASK | COMN1SW_MASK)
63
64 #define MAX8997_SW_USB          ((1 << COMP2SW_SHIFT) | (1 << COMN1SW_SHIFT))
65 #define MAX8997_SW_AUDIO        ((2 << COMP2SW_SHIFT) | (2 << COMN1SW_SHIFT))
66 #define MAX8997_SW_UART         ((3 << COMP2SW_SHIFT) | (3 << COMN1SW_SHIFT))
67 #define MAX8997_SW_OPEN         ((0 << COMP2SW_SHIFT) | (0 << COMN1SW_SHIFT))
68
69 #define MAX8997_ADC_GROUND              0x00
70 #define MAX8997_ADC_MHL                 0x01
71 #define MAX8997_ADC_JIG_USB_1           0x18
72 #define MAX8997_ADC_JIG_USB_2           0x19
73 #define MAX8997_ADC_DESKDOCK            0x1a
74 #define MAX8997_ADC_JIG_UART            0x1c
75 #define MAX8997_ADC_CARDOCK             0x1d
76 #define MAX8997_ADC_OPEN                0x1f
77
78 struct max8997_muic_irq {
79         unsigned int irq;
80         const char *name;
81         unsigned int virq;
82 };
83
84 static struct max8997_muic_irq muic_irqs[] = {
85         { MAX8997_MUICIRQ_ADCError, "muic-ADC_error" },
86         { MAX8997_MUICIRQ_ADCLow, "muic-ADC_low" },
87         { MAX8997_MUICIRQ_ADC, "muic-ADC" },
88         { MAX8997_MUICIRQ_VBVolt, "muic-VB_voltage" },
89         { MAX8997_MUICIRQ_DBChg, "muic-DB_charger" },
90         { MAX8997_MUICIRQ_DCDTmr, "muic-DCD_timer" },
91         { MAX8997_MUICIRQ_ChgDetRun, "muic-CDR_status" },
92         { MAX8997_MUICIRQ_ChgTyp, "muic-charger_type" },
93         { MAX8997_MUICIRQ_OVP, "muic-over_voltage" },
94 };
95
96 struct max8997_muic_info {
97         struct device *dev;
98         struct i2c_client *muic;
99         struct max8997_muic_platform_data *muic_pdata;
100
101         int irq;
102         struct work_struct irq_work;
103
104         enum max8997_muic_charger_type pre_charger_type;
105         int pre_adc;
106
107         struct mutex mutex;
108
109         struct extcon_dev       *edev;
110 };
111
112 const char *max8997_extcon_cable[] = {
113         [0] = "USB",
114         [1] = "USB-Host",
115         [2] = "TA",
116         [3] = "Fast-charger",
117         [4] = "Slow-charger",
118         [5] = "Charge-downstream",
119         [6] = "MHL",
120         [7] = "Dock-desk",
121         [8] = "Dock-card",
122         [9] = "JIG",
123
124         NULL,
125 };
126
127 static int max8997_muic_handle_usb(struct max8997_muic_info *info,
128                         enum max8997_muic_usb_type usb_type, bool attached)
129 {
130         int ret = 0;
131
132         if (usb_type == MAX8997_USB_HOST) {
133                 /* switch to USB */
134                 ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
135                                 attached ? MAX8997_SW_USB : MAX8997_SW_OPEN,
136                                 SW_MASK);
137                 if (ret) {
138                         dev_err(info->dev, "failed to update muic register\n");
139                         goto out;
140                 }
141         }
142
143         switch (usb_type) {
144         case MAX8997_USB_HOST:
145                 extcon_set_cable_state(info->edev, "USB-Host", attached);
146                 break;
147         case MAX8997_USB_DEVICE:
148                 extcon_set_cable_state(info->edev, "USB", attached);
149                 break;
150         default:
151                 ret = -EINVAL;
152                 break;
153         }
154
155 out:
156         return ret;
157 }
158
159 static int max8997_muic_handle_dock(struct max8997_muic_info *info,
160                         int adc, bool attached)
161 {
162         int ret = 0;
163
164         /* switch to AUDIO */
165         ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
166                                 attached ? MAX8997_SW_AUDIO : MAX8997_SW_OPEN,
167                                 SW_MASK);
168         if (ret) {
169                 dev_err(info->dev, "failed to update muic register\n");
170                 goto out;
171         }
172
173         switch (adc) {
174         case MAX8997_ADC_DESKDOCK:
175                 extcon_set_cable_state(info->edev, "Dock-desk", attached);
176                 break;
177         case MAX8997_ADC_CARDOCK:
178                 extcon_set_cable_state(info->edev, "Dock-card", attached);
179                 break;
180         default:
181                 ret = -EINVAL;
182                 break;
183         }
184 out:
185         return ret;
186 }
187
188 static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
189                         bool attached)
190 {
191         int ret = 0;
192
193         /* switch to UART */
194         ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
195                                 attached ? MAX8997_SW_UART : MAX8997_SW_OPEN,
196                                 SW_MASK);
197         if (ret) {
198                 dev_err(info->dev, "failed to update muic register\n");
199                 goto out;
200         }
201
202         extcon_set_cable_state(info->edev, "JIG", attached);
203 out:
204         return ret;
205 }
206
207 static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info)
208 {
209         int ret = 0;
210
211         switch (info->pre_adc) {
212         case MAX8997_ADC_GROUND:
213                 ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false);
214                 break;
215         case MAX8997_ADC_MHL:
216                 extcon_set_cable_state(info->edev, "MHL", false);
217                 break;
218         case MAX8997_ADC_JIG_USB_1:
219         case MAX8997_ADC_JIG_USB_2:
220                 ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, false);
221                 break;
222         case MAX8997_ADC_DESKDOCK:
223         case MAX8997_ADC_CARDOCK:
224                 ret = max8997_muic_handle_dock(info, info->pre_adc, false);
225                 break;
226         case MAX8997_ADC_JIG_UART:
227                 ret = max8997_muic_handle_jig_uart(info, false);
228                 break;
229         default:
230                 break;
231         }
232
233         return ret;
234 }
235
236 static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
237 {
238         int ret = 0;
239
240         switch (adc) {
241         case MAX8997_ADC_GROUND:
242                 ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true);
243                 break;
244         case MAX8997_ADC_MHL:
245                 extcon_set_cable_state(info->edev, "MHL", true);
246                 break;
247         case MAX8997_ADC_JIG_USB_1:
248         case MAX8997_ADC_JIG_USB_2:
249                 ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, true);
250                 break;
251         case MAX8997_ADC_DESKDOCK:
252         case MAX8997_ADC_CARDOCK:
253                 ret = max8997_muic_handle_dock(info, adc, true);
254                 break;
255         case MAX8997_ADC_JIG_UART:
256                 ret = max8997_muic_handle_jig_uart(info, true);
257                 break;
258         case MAX8997_ADC_OPEN:
259                 ret = max8997_muic_handle_adc_detach(info);
260                 break;
261         default:
262                 ret = -EINVAL;
263                 goto out;
264         }
265
266         info->pre_adc = adc;
267 out:
268         return ret;
269 }
270
271 static int max8997_muic_handle_charger_type_detach(
272                                 struct max8997_muic_info *info)
273 {
274         int ret = 0;
275
276         switch (info->pre_charger_type) {
277         case MAX8997_CHARGER_TYPE_USB:
278                 extcon_set_cable_state(info->edev, "USB", false);
279                 break;
280         case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
281                 extcon_set_cable_state(info->edev, "Charge-downstream", false);
282                 break;
283         case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
284                 extcon_set_cable_state(info->edev, "TA", false);
285                 break;
286         case MAX8997_CHARGER_TYPE_500MA:
287                 extcon_set_cable_state(info->edev, "Slow-charger", false);
288                 break;
289         case MAX8997_CHARGER_TYPE_1A:
290                 extcon_set_cable_state(info->edev, "Fast-charger", false);
291                 break;
292         default:
293                 ret = -EINVAL;
294                 break;
295         }
296
297         return ret;
298 }
299
300 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
301                                 enum max8997_muic_charger_type charger_type)
302 {
303         u8 adc;
304         int ret;
305
306         ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_STATUS1, &adc);
307         if (ret) {
308                 dev_err(info->dev, "failed to read muic register\n");
309                 goto out;
310         }
311
312         switch (charger_type) {
313         case MAX8997_CHARGER_TYPE_NONE:
314                 ret = max8997_muic_handle_charger_type_detach(info);
315                 break;
316         case MAX8997_CHARGER_TYPE_USB:
317                 if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) {
318                         max8997_muic_handle_usb(info,
319                                         MAX8997_USB_DEVICE, true);
320                 }
321                 break;
322         case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
323                 extcon_set_cable_state(info->edev, "Charge-downstream", true);
324                 break;
325         case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
326                 extcon_set_cable_state(info->edev, "TA", true);
327                 break;
328         case MAX8997_CHARGER_TYPE_500MA:
329                 extcon_set_cable_state(info->edev, "Slow-charger", true);
330                 break;
331         case MAX8997_CHARGER_TYPE_1A:
332                 extcon_set_cable_state(info->edev, "Fast-charger", true);
333                 break;
334         default:
335                 ret = -EINVAL;
336                 goto out;
337         }
338
339         info->pre_charger_type = charger_type;
340 out:
341         return ret;
342 }
343
344 static void max8997_muic_irq_work(struct work_struct *work)
345 {
346         struct max8997_muic_info *info = container_of(work,
347                         struct max8997_muic_info, irq_work);
348         u8 status[2];
349         u8 adc, chg_type;
350         int irq_type = 0;
351         int i, ret;
352
353         mutex_lock(&info->mutex);
354
355         ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
356                                 2, status);
357         if (ret) {
358                 dev_err(info->dev, "failed to read muic register\n");
359                 mutex_unlock(&info->mutex);
360                 return;
361         }
362
363         dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__,
364                         status[0], status[1]);
365
366         for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
367                 if (info->irq == muic_irqs[i].virq)
368                         irq_type = muic_irqs[i].irq;
369
370         switch (irq_type) {
371         case MAX8997_MUICIRQ_ADC:
372                 adc = status[0] & STATUS1_ADC_MASK;
373                 adc >>= STATUS1_ADC_SHIFT;
374
375                 max8997_muic_handle_adc(info, adc);
376                 break;
377         case MAX8997_MUICIRQ_ChgTyp:
378                 chg_type = status[1] & STATUS2_CHGTYP_MASK;
379                 chg_type >>= STATUS2_CHGTYP_SHIFT;
380
381                 max8997_muic_handle_charger_type(info, chg_type);
382                 break;
383         default:
384                 dev_info(info->dev, "misc interrupt: irq %d occurred\n",
385                                 irq_type);
386                 break;
387         }
388
389         mutex_unlock(&info->mutex);
390
391         return;
392 }
393
394 static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
395 {
396         struct max8997_muic_info *info = data;
397
398         dev_dbg(info->dev, "irq:%d\n", irq);
399         info->irq = irq;
400
401         schedule_work(&info->irq_work);
402
403         return IRQ_HANDLED;
404 }
405
406 static void max8997_muic_detect_dev(struct max8997_muic_info *info)
407 {
408         int ret;
409         u8 status[2], adc, chg_type;
410
411         ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
412                                 2, status);
413         if (ret) {
414                 dev_err(info->dev, "failed to read muic register\n");
415                 return;
416         }
417
418         dev_info(info->dev, "STATUS1:0x%x, STATUS2:0x%x\n",
419                         status[0], status[1]);
420
421         adc = status[0] & STATUS1_ADC_MASK;
422         adc >>= STATUS1_ADC_SHIFT;
423
424         chg_type = status[1] & STATUS2_CHGTYP_MASK;
425         chg_type >>= STATUS2_CHGTYP_SHIFT;
426
427         max8997_muic_handle_adc(info, adc);
428         max8997_muic_handle_charger_type(info, chg_type);
429 }
430
431 static int __devinit max8997_muic_probe(struct platform_device *pdev)
432 {
433         struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
434         struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
435         struct max8997_muic_info *info;
436         int ret, i;
437
438         info = kzalloc(sizeof(struct max8997_muic_info), GFP_KERNEL);
439         if (!info) {
440                 dev_err(&pdev->dev, "failed to allocate memory\n");
441                 ret = -ENOMEM;
442                 goto err_kfree;
443         }
444
445         info->dev = &pdev->dev;
446         info->muic = max8997->muic;
447
448         platform_set_drvdata(pdev, info);
449         mutex_init(&info->mutex);
450
451         INIT_WORK(&info->irq_work, max8997_muic_irq_work);
452
453         for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
454                 struct max8997_muic_irq *muic_irq = &muic_irqs[i];
455                 int virq = 0;
456
457                 virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
458                 if (!virq)
459                         goto err_irq;
460                 muic_irq->virq = virq;
461
462                 ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler,
463                                 0, muic_irq->name, info);
464                 if (ret) {
465                         dev_err(&pdev->dev,
466                                 "failed: irq request (IRQ: %d,"
467                                 " error :%d)\n",
468                                 muic_irq->irq, ret);
469                         goto err_irq;
470                 }
471         }
472
473         /* External connector */
474         info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL);
475         if (!info->edev) {
476                 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
477                 ret = -ENOMEM;
478                 goto err_irq;
479         }
480         info->edev->name = DEV_NAME;
481         info->edev->supported_cable = max8997_extcon_cable;
482         ret = extcon_dev_register(info->edev, NULL);
483         if (ret) {
484                 dev_err(&pdev->dev, "failed to register extcon device\n");
485                 goto err_extcon;
486         }
487
488         /* Initialize registers according to platform data */
489         if (pdata->muic_pdata) {
490                 struct max8997_muic_platform_data *mdata = info->muic_pdata;
491
492                 for (i = 0; i < mdata->num_init_data; i++) {
493                         max8997_write_reg(info->muic, mdata->init_data[i].addr,
494                                         mdata->init_data[i].data);
495                 }
496         }
497
498         /* Initial device detection */
499         max8997_muic_detect_dev(info);
500
501         return ret;
502
503 err_extcon:
504         kfree(info->edev);
505 err_irq:
506         while (--i >= 0)
507                 free_irq(muic_irqs[i].virq, info);
508         kfree(info);
509 err_kfree:
510         return ret;
511 }
512
513 static int __devexit max8997_muic_remove(struct platform_device *pdev)
514 {
515         struct max8997_muic_info *info = platform_get_drvdata(pdev);
516         int i;
517
518         for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
519                 free_irq(muic_irqs[i].virq, info);
520         cancel_work_sync(&info->irq_work);
521
522         extcon_dev_unregister(info->edev);
523
524         kfree(info->edev);
525         kfree(info);
526
527         return 0;
528 }
529
530 static struct platform_driver max8997_muic_driver = {
531         .driver         = {
532                 .name   = DEV_NAME,
533                 .owner  = THIS_MODULE,
534         },
535         .probe          = max8997_muic_probe,
536         .remove         = __devexit_p(max8997_muic_remove),
537 };
538
539 module_platform_driver(max8997_muic_driver);
540
541 MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
542 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
543 MODULE_LICENSE("GPL");