Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/extcon/extcon-max8997.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0+
2
//
3
// extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
4
//
5
// Copyright (C) 2012 Samsung Electronics
6
// Donggeun Kim <[email protected]>
7
8
#include <linux/devm-helpers.h>
9
#include <linux/kernel.h>
10
#include <linux/module.h>
11
#include <linux/i2c.h>
12
#include <linux/slab.h>
13
#include <linux/interrupt.h>
14
#include <linux/err.h>
15
#include <linux/platform_device.h>
16
#include <linux/kobject.h>
17
#include <linux/mfd/max8997.h>
18
#include <linux/mfd/max8997-private.h>
19
#include <linux/extcon-provider.h>
20
#include <linux/irqdomain.h>
21
22
#define DEV_NAME "max8997-muic"
23
#define DELAY_MS_DEFAULT 20000 /* unit: millisecond */
24
25
enum max8997_muic_adc_debounce_time {
26
ADC_DEBOUNCE_TIME_0_5MS = 0, /* 0.5ms */
27
ADC_DEBOUNCE_TIME_10MS, /* 10ms */
28
ADC_DEBOUNCE_TIME_25MS, /* 25ms */
29
ADC_DEBOUNCE_TIME_38_62MS, /* 38.62ms */
30
};
31
32
struct max8997_muic_irq {
33
unsigned int irq;
34
const char *name;
35
unsigned int virq;
36
};
37
38
static struct max8997_muic_irq muic_irqs[] = {
39
{ MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
40
{ MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
41
{ MAX8997_MUICIRQ_ADC, "muic-ADC" },
42
{ MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
43
{ MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
44
{ MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
45
{ MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
46
{ MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
47
{ MAX8997_MUICIRQ_OVP, "muic-OVP" },
48
{ MAX8997_PMICIRQ_CHGINS, "pmic-CHGINS" },
49
{ MAX8997_PMICIRQ_CHGRM, "pmic-CHGRM" },
50
};
51
52
/* Define supported cable type */
53
enum max8997_muic_acc_type {
54
MAX8997_MUIC_ADC_GROUND = 0x0,
55
MAX8997_MUIC_ADC_MHL, /* MHL*/
56
MAX8997_MUIC_ADC_REMOTE_S1_BUTTON,
57
MAX8997_MUIC_ADC_REMOTE_S2_BUTTON,
58
MAX8997_MUIC_ADC_REMOTE_S3_BUTTON,
59
MAX8997_MUIC_ADC_REMOTE_S4_BUTTON,
60
MAX8997_MUIC_ADC_REMOTE_S5_BUTTON,
61
MAX8997_MUIC_ADC_REMOTE_S6_BUTTON,
62
MAX8997_MUIC_ADC_REMOTE_S7_BUTTON,
63
MAX8997_MUIC_ADC_REMOTE_S8_BUTTON,
64
MAX8997_MUIC_ADC_REMOTE_S9_BUTTON,
65
MAX8997_MUIC_ADC_REMOTE_S10_BUTTON,
66
MAX8997_MUIC_ADC_REMOTE_S11_BUTTON,
67
MAX8997_MUIC_ADC_REMOTE_S12_BUTTON,
68
MAX8997_MUIC_ADC_RESERVED_ACC_1,
69
MAX8997_MUIC_ADC_RESERVED_ACC_2,
70
MAX8997_MUIC_ADC_RESERVED_ACC_3,
71
MAX8997_MUIC_ADC_RESERVED_ACC_4,
72
MAX8997_MUIC_ADC_RESERVED_ACC_5,
73
MAX8997_MUIC_ADC_CEA936_AUDIO,
74
MAX8997_MUIC_ADC_PHONE_POWERED_DEV,
75
MAX8997_MUIC_ADC_TTY_CONVERTER,
76
MAX8997_MUIC_ADC_UART_CABLE,
77
MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG,
78
MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF, /* JIG-USB-OFF */
79
MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON, /* JIG-USB-ON */
80
MAX8997_MUIC_ADC_AV_CABLE_NOLOAD, /* DESKDOCK */
81
MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG,
82
MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF, /* JIG-UART */
83
MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON, /* CARDOCK */
84
MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE,
85
MAX8997_MUIC_ADC_OPEN, /* OPEN */
86
};
87
88
enum max8997_muic_cable_group {
89
MAX8997_CABLE_GROUP_ADC = 0,
90
MAX8997_CABLE_GROUP_ADC_GND,
91
MAX8997_CABLE_GROUP_CHG,
92
MAX8997_CABLE_GROUP_VBVOLT,
93
};
94
95
enum max8997_muic_usb_type {
96
MAX8997_USB_HOST,
97
MAX8997_USB_DEVICE,
98
};
99
100
enum max8997_muic_charger_type {
101
MAX8997_CHARGER_TYPE_NONE = 0,
102
MAX8997_CHARGER_TYPE_USB,
103
MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT,
104
MAX8997_CHARGER_TYPE_DEDICATED_CHG,
105
MAX8997_CHARGER_TYPE_500MA,
106
MAX8997_CHARGER_TYPE_1A,
107
MAX8997_CHARGER_TYPE_DEAD_BATTERY = 7,
108
};
109
110
struct max8997_muic_info {
111
struct device *dev;
112
struct i2c_client *muic;
113
struct extcon_dev *edev;
114
int prev_cable_type;
115
int prev_chg_type;
116
u8 status[2];
117
118
int irq;
119
struct work_struct irq_work;
120
struct mutex mutex;
121
122
struct max8997_muic_platform_data *muic_pdata;
123
enum max8997_muic_charger_type pre_charger_type;
124
125
/*
126
* Use delayed workqueue to detect cable state and then
127
* notify cable state to notifiee/platform through uevent.
128
* After completing the booting of platform, the extcon provider
129
* driver should notify cable state to upper layer.
130
*/
131
struct delayed_work wq_detcable;
132
133
/*
134
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
135
* h/w path of COMP2/COMN1 on CONTROL1 register.
136
*/
137
int path_usb;
138
int path_uart;
139
};
140
141
static const unsigned int max8997_extcon_cable[] = {
142
EXTCON_USB,
143
EXTCON_USB_HOST,
144
EXTCON_CHG_USB_SDP,
145
EXTCON_CHG_USB_DCP,
146
EXTCON_CHG_USB_FAST,
147
EXTCON_CHG_USB_SLOW,
148
EXTCON_CHG_USB_CDP,
149
EXTCON_DISP_MHL,
150
EXTCON_DOCK,
151
EXTCON_JIG,
152
EXTCON_NONE,
153
};
154
155
/*
156
* max8997_muic_set_debounce_time - Set the debounce time of ADC
157
* @info: the instance including private data of max8997 MUIC
158
* @time: the debounce time of ADC
159
*/
160
static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
161
enum max8997_muic_adc_debounce_time time)
162
{
163
int ret;
164
165
switch (time) {
166
case ADC_DEBOUNCE_TIME_0_5MS:
167
case ADC_DEBOUNCE_TIME_10MS:
168
case ADC_DEBOUNCE_TIME_25MS:
169
case ADC_DEBOUNCE_TIME_38_62MS:
170
ret = max8997_update_reg(info->muic,
171
MAX8997_MUIC_REG_CONTROL3,
172
time << CONTROL3_ADCDBSET_SHIFT,
173
CONTROL3_ADCDBSET_MASK);
174
if (ret) {
175
dev_err(info->dev, "failed to set ADC debounce time\n");
176
return ret;
177
}
178
break;
179
default:
180
dev_err(info->dev, "invalid ADC debounce time\n");
181
return -EINVAL;
182
}
183
184
return 0;
185
};
186
187
/*
188
* max8997_muic_set_path - Set hardware line according to attached cable
189
* @info: the instance including private data of max8997 MUIC
190
* @value: the path according to attached cable
191
* @attached: the state of cable (true:attached, false:detached)
192
*
193
* The max8997 MUIC device share outside H/W line among a varity of cables,
194
* so this function set internal path of H/W line according to the type of
195
* attached cable.
196
*/
197
static int max8997_muic_set_path(struct max8997_muic_info *info,
198
u8 val, bool attached)
199
{
200
int ret;
201
u8 ctrl1, ctrl2 = 0;
202
203
if (attached)
204
ctrl1 = val;
205
else
206
ctrl1 = CONTROL1_SW_OPEN;
207
208
ret = max8997_update_reg(info->muic,
209
MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
210
if (ret < 0) {
211
dev_err(info->dev, "failed to update MUIC register\n");
212
return ret;
213
}
214
215
if (attached)
216
ctrl2 |= CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */
217
else
218
ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
219
220
ret = max8997_update_reg(info->muic,
221
MAX8997_MUIC_REG_CONTROL2, ctrl2,
222
CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
223
if (ret < 0) {
224
dev_err(info->dev, "failed to update MUIC register\n");
225
return ret;
226
}
227
228
dev_info(info->dev,
229
"CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
230
ctrl1, ctrl2, attached ? "attached" : "detached");
231
232
return 0;
233
}
234
235
/*
236
* max8997_muic_get_cable_type - Return cable type and check cable state
237
* @info: the instance including private data of max8997 MUIC
238
* @group: the path according to attached cable
239
* @attached: store cable state and return
240
*
241
* This function check the cable state either attached or detached,
242
* and then divide precise type of cable according to cable group.
243
* - MAX8997_CABLE_GROUP_ADC
244
* - MAX8997_CABLE_GROUP_CHG
245
*/
246
static int max8997_muic_get_cable_type(struct max8997_muic_info *info,
247
enum max8997_muic_cable_group group, bool *attached)
248
{
249
int cable_type = 0;
250
int adc;
251
int chg_type;
252
253
switch (group) {
254
case MAX8997_CABLE_GROUP_ADC:
255
/*
256
* Read ADC value to check cable type and decide cable state
257
* according to cable type
258
*/
259
adc = info->status[0] & STATUS1_ADC_MASK;
260
adc >>= STATUS1_ADC_SHIFT;
261
262
/*
263
* Check current cable state/cable type and store cable type
264
* (info->prev_cable_type) for handling cable when cable is
265
* detached.
266
*/
267
if (adc == MAX8997_MUIC_ADC_OPEN) {
268
*attached = false;
269
270
cable_type = info->prev_cable_type;
271
info->prev_cable_type = MAX8997_MUIC_ADC_OPEN;
272
} else {
273
*attached = true;
274
275
cable_type = info->prev_cable_type = adc;
276
}
277
break;
278
case MAX8997_CABLE_GROUP_CHG:
279
/*
280
* Read charger type to check cable type and decide cable state
281
* according to type of charger cable.
282
*/
283
chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
284
chg_type >>= STATUS2_CHGTYP_SHIFT;
285
286
if (chg_type == MAX8997_CHARGER_TYPE_NONE) {
287
*attached = false;
288
289
cable_type = info->prev_chg_type;
290
info->prev_chg_type = MAX8997_CHARGER_TYPE_NONE;
291
} else {
292
*attached = true;
293
294
/*
295
* Check current cable state/cable type and store cable
296
* type(info->prev_chg_type) for handling cable when
297
* charger cable is detached.
298
*/
299
cable_type = info->prev_chg_type = chg_type;
300
}
301
302
break;
303
default:
304
dev_err(info->dev, "Unknown cable group (%d)\n", group);
305
cable_type = -EINVAL;
306
break;
307
}
308
309
return cable_type;
310
}
311
312
static int max8997_muic_handle_usb(struct max8997_muic_info *info,
313
enum max8997_muic_usb_type usb_type, bool attached)
314
{
315
int ret = 0;
316
317
ret = max8997_muic_set_path(info, info->path_usb, attached);
318
if (ret < 0) {
319
dev_err(info->dev, "failed to update muic register\n");
320
return ret;
321
}
322
323
switch (usb_type) {
324
case MAX8997_USB_HOST:
325
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
326
break;
327
case MAX8997_USB_DEVICE:
328
extcon_set_state_sync(info->edev, EXTCON_USB, attached);
329
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
330
attached);
331
break;
332
default:
333
dev_err(info->dev, "failed to detect %s usb cable\n",
334
attached ? "attached" : "detached");
335
return -EINVAL;
336
}
337
338
return 0;
339
}
340
341
static int max8997_muic_handle_dock(struct max8997_muic_info *info,
342
int cable_type, bool attached)
343
{
344
int ret = 0;
345
346
ret = max8997_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
347
if (ret) {
348
dev_err(info->dev, "failed to update muic register\n");
349
return ret;
350
}
351
352
switch (cable_type) {
353
case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
354
case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
355
extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
356
break;
357
default:
358
dev_err(info->dev, "failed to detect %s dock device\n",
359
attached ? "attached" : "detached");
360
return -EINVAL;
361
}
362
363
return 0;
364
}
365
366
static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
367
bool attached)
368
{
369
int ret = 0;
370
371
/* switch to UART */
372
ret = max8997_muic_set_path(info, info->path_uart, attached);
373
if (ret) {
374
dev_err(info->dev, "failed to update muic register\n");
375
return ret;
376
}
377
378
extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
379
380
return 0;
381
}
382
383
static int max8997_muic_adc_handler(struct max8997_muic_info *info)
384
{
385
int cable_type;
386
bool attached;
387
int ret = 0;
388
389
/* Check cable state which is either detached or attached */
390
cable_type = max8997_muic_get_cable_type(info,
391
MAX8997_CABLE_GROUP_ADC, &attached);
392
393
switch (cable_type) {
394
case MAX8997_MUIC_ADC_GROUND:
395
ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, attached);
396
if (ret < 0)
397
return ret;
398
break;
399
case MAX8997_MUIC_ADC_MHL:
400
extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
401
break;
402
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
403
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
404
ret = max8997_muic_handle_usb(info,
405
MAX8997_USB_DEVICE, attached);
406
if (ret < 0)
407
return ret;
408
break;
409
case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
410
case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
411
ret = max8997_muic_handle_dock(info, cable_type, attached);
412
if (ret < 0)
413
return ret;
414
break;
415
case MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF:
416
ret = max8997_muic_handle_jig_uart(info, attached);
417
break;
418
case MAX8997_MUIC_ADC_REMOTE_S1_BUTTON:
419
case MAX8997_MUIC_ADC_REMOTE_S2_BUTTON:
420
case MAX8997_MUIC_ADC_REMOTE_S3_BUTTON:
421
case MAX8997_MUIC_ADC_REMOTE_S4_BUTTON:
422
case MAX8997_MUIC_ADC_REMOTE_S5_BUTTON:
423
case MAX8997_MUIC_ADC_REMOTE_S6_BUTTON:
424
case MAX8997_MUIC_ADC_REMOTE_S7_BUTTON:
425
case MAX8997_MUIC_ADC_REMOTE_S8_BUTTON:
426
case MAX8997_MUIC_ADC_REMOTE_S9_BUTTON:
427
case MAX8997_MUIC_ADC_REMOTE_S10_BUTTON:
428
case MAX8997_MUIC_ADC_REMOTE_S11_BUTTON:
429
case MAX8997_MUIC_ADC_REMOTE_S12_BUTTON:
430
case MAX8997_MUIC_ADC_RESERVED_ACC_1:
431
case MAX8997_MUIC_ADC_RESERVED_ACC_2:
432
case MAX8997_MUIC_ADC_RESERVED_ACC_3:
433
case MAX8997_MUIC_ADC_RESERVED_ACC_4:
434
case MAX8997_MUIC_ADC_RESERVED_ACC_5:
435
case MAX8997_MUIC_ADC_CEA936_AUDIO:
436
case MAX8997_MUIC_ADC_PHONE_POWERED_DEV:
437
case MAX8997_MUIC_ADC_TTY_CONVERTER:
438
case MAX8997_MUIC_ADC_UART_CABLE:
439
case MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG:
440
case MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG:
441
case MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE:
442
/*
443
* This cable isn't used in general case if it is specially
444
* needed to detect additional cable, should implement
445
* proper operation when this cable is attached/detached.
446
*/
447
dev_info(info->dev,
448
"cable is %s but it isn't used (type:0x%x)\n",
449
attached ? "attached" : "detached", cable_type);
450
return -EAGAIN;
451
default:
452
dev_err(info->dev,
453
"failed to detect %s unknown cable (type:0x%x)\n",
454
attached ? "attached" : "detached", cable_type);
455
return -EINVAL;
456
}
457
458
return 0;
459
}
460
461
static int max8997_muic_chg_handler(struct max8997_muic_info *info)
462
{
463
int chg_type;
464
bool attached;
465
int adc;
466
467
chg_type = max8997_muic_get_cable_type(info,
468
MAX8997_CABLE_GROUP_CHG, &attached);
469
470
switch (chg_type) {
471
case MAX8997_CHARGER_TYPE_NONE:
472
break;
473
case MAX8997_CHARGER_TYPE_USB:
474
adc = info->status[0] & STATUS1_ADC_MASK;
475
adc >>= STATUS1_ADC_SHIFT;
476
477
if ((adc & STATUS1_ADC_MASK) == MAX8997_MUIC_ADC_OPEN) {
478
max8997_muic_handle_usb(info,
479
MAX8997_USB_DEVICE, attached);
480
}
481
break;
482
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
483
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
484
attached);
485
break;
486
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
487
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
488
attached);
489
break;
490
case MAX8997_CHARGER_TYPE_500MA:
491
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
492
attached);
493
break;
494
case MAX8997_CHARGER_TYPE_1A:
495
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
496
attached);
497
break;
498
default:
499
dev_err(info->dev,
500
"failed to detect %s unknown chg cable (type:0x%x)\n",
501
attached ? "attached" : "detached", chg_type);
502
return -EINVAL;
503
}
504
505
return 0;
506
}
507
508
static void max8997_muic_irq_work(struct work_struct *work)
509
{
510
struct max8997_muic_info *info = container_of(work,
511
struct max8997_muic_info, irq_work);
512
int irq_type = 0;
513
int i, ret;
514
515
if (!info->edev)
516
return;
517
518
mutex_lock(&info->mutex);
519
520
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
521
if (info->irq == muic_irqs[i].virq)
522
irq_type = muic_irqs[i].irq;
523
524
ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
525
2, info->status);
526
if (ret) {
527
dev_err(info->dev, "failed to read muic register\n");
528
mutex_unlock(&info->mutex);
529
return;
530
}
531
532
switch (irq_type) {
533
case MAX8997_MUICIRQ_ADCError:
534
case MAX8997_MUICIRQ_ADCLow:
535
case MAX8997_MUICIRQ_ADC:
536
/* Handle all of cable except for charger cable */
537
ret = max8997_muic_adc_handler(info);
538
break;
539
case MAX8997_MUICIRQ_VBVolt:
540
case MAX8997_MUICIRQ_DBChg:
541
case MAX8997_MUICIRQ_DCDTmr:
542
case MAX8997_MUICIRQ_ChgDetRun:
543
case MAX8997_MUICIRQ_ChgTyp:
544
case MAX8997_PMICIRQ_CHGINS:
545
case MAX8997_PMICIRQ_CHGRM:
546
/* Handle charger cable */
547
ret = max8997_muic_chg_handler(info);
548
break;
549
case MAX8997_MUICIRQ_OVP:
550
break;
551
default:
552
dev_info(info->dev, "misc interrupt: irq %d occurred\n",
553
irq_type);
554
mutex_unlock(&info->mutex);
555
return;
556
}
557
558
if (ret < 0)
559
dev_err(info->dev, "failed to handle MUIC interrupt\n");
560
561
mutex_unlock(&info->mutex);
562
}
563
564
static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
565
{
566
struct max8997_muic_info *info = data;
567
568
dev_dbg(info->dev, "irq:%d\n", irq);
569
info->irq = irq;
570
571
schedule_work(&info->irq_work);
572
573
return IRQ_HANDLED;
574
}
575
576
static int max8997_muic_detect_dev(struct max8997_muic_info *info)
577
{
578
int ret = 0;
579
int adc;
580
int chg_type;
581
bool attached;
582
583
mutex_lock(&info->mutex);
584
585
/* Read STATUSx register to detect accessory */
586
ret = max8997_bulk_read(info->muic,
587
MAX8997_MUIC_REG_STATUS1, 2, info->status);
588
if (ret) {
589
dev_err(info->dev, "failed to read MUIC register\n");
590
mutex_unlock(&info->mutex);
591
return ret;
592
}
593
594
adc = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC,
595
&attached);
596
if (attached && adc != MAX8997_MUIC_ADC_OPEN) {
597
ret = max8997_muic_adc_handler(info);
598
if (ret < 0) {
599
dev_err(info->dev, "Cannot detect ADC cable\n");
600
mutex_unlock(&info->mutex);
601
return ret;
602
}
603
}
604
605
chg_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_CHG,
606
&attached);
607
if (attached && chg_type != MAX8997_CHARGER_TYPE_NONE) {
608
ret = max8997_muic_chg_handler(info);
609
if (ret < 0) {
610
dev_err(info->dev, "Cannot detect charger cable\n");
611
mutex_unlock(&info->mutex);
612
return ret;
613
}
614
}
615
616
mutex_unlock(&info->mutex);
617
618
return 0;
619
}
620
621
static void max8997_muic_detect_cable_wq(struct work_struct *work)
622
{
623
struct max8997_muic_info *info = container_of(to_delayed_work(work),
624
struct max8997_muic_info, wq_detcable);
625
int ret;
626
627
ret = max8997_muic_detect_dev(info);
628
if (ret < 0)
629
dev_err(info->dev, "failed to detect cable type\n");
630
}
631
632
static int max8997_muic_probe(struct platform_device *pdev)
633
{
634
struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
635
struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
636
struct max8997_muic_info *info;
637
int delay_jiffies;
638
int cable_type;
639
bool attached;
640
int ret, i;
641
642
info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
643
GFP_KERNEL);
644
if (!info)
645
return -ENOMEM;
646
647
info->dev = &pdev->dev;
648
info->muic = max8997->muic;
649
650
platform_set_drvdata(pdev, info);
651
mutex_init(&info->mutex);
652
653
INIT_WORK(&info->irq_work, max8997_muic_irq_work);
654
ret = devm_work_autocancel(&pdev->dev, &info->irq_work,
655
max8997_muic_irq_work);
656
if (ret)
657
return ret;
658
659
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
660
struct max8997_muic_irq *muic_irq = &muic_irqs[i];
661
unsigned int virq = 0;
662
663
virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
664
if (!virq)
665
return -EINVAL;
666
667
muic_irq->virq = virq;
668
669
ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
670
max8997_muic_irq_handler,
671
IRQF_NO_SUSPEND,
672
muic_irq->name, info);
673
if (ret) {
674
dev_err(&pdev->dev,
675
"failed: irq request (IRQ: %d, error :%d)\n",
676
muic_irq->irq, ret);
677
return ret;
678
}
679
}
680
681
/* External connector */
682
info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
683
if (IS_ERR(info->edev)) {
684
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
685
return PTR_ERR(info->edev);
686
}
687
688
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
689
if (ret) {
690
dev_err(&pdev->dev, "failed to register extcon device\n");
691
return ret;
692
}
693
694
if (pdata && pdata->muic_pdata) {
695
struct max8997_muic_platform_data *muic_pdata
696
= pdata->muic_pdata;
697
698
/* Initialize registers according to platform data */
699
for (i = 0; i < muic_pdata->num_init_data; i++) {
700
max8997_write_reg(info->muic,
701
muic_pdata->init_data[i].addr,
702
muic_pdata->init_data[i].data);
703
}
704
705
/*
706
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
707
* h/w path of COMP2/COMN1 on CONTROL1 register.
708
*/
709
if (muic_pdata->path_uart)
710
info->path_uart = muic_pdata->path_uart;
711
else
712
info->path_uart = CONTROL1_SW_UART;
713
714
if (muic_pdata->path_usb)
715
info->path_usb = muic_pdata->path_usb;
716
else
717
info->path_usb = CONTROL1_SW_USB;
718
719
/*
720
* Default delay time for detecting cable state
721
* after certain time.
722
*/
723
if (muic_pdata->detcable_delay_ms)
724
delay_jiffies =
725
msecs_to_jiffies(muic_pdata->detcable_delay_ms);
726
else
727
delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
728
} else {
729
info->path_uart = CONTROL1_SW_UART;
730
info->path_usb = CONTROL1_SW_USB;
731
delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
732
}
733
734
/* Set initial path for UART when JIG is connected to get serial logs */
735
ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
736
2, info->status);
737
if (ret) {
738
dev_err(info->dev, "failed to read MUIC register\n");
739
return ret;
740
}
741
cable_type = max8997_muic_get_cable_type(info,
742
MAX8997_CABLE_GROUP_ADC, &attached);
743
if (attached && cable_type == MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF)
744
max8997_muic_set_path(info, info->path_uart, true);
745
746
/* Set ADC debounce time */
747
max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
748
749
/*
750
* Detect accessory after completing the initialization of platform
751
*
752
* - Use delayed workqueue to detect cable state and then
753
* notify cable state to notifiee/platform through uevent.
754
* After completing the booting of platform, the extcon provider
755
* driver should notify cable state to upper layer.
756
*/
757
INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
758
queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
759
delay_jiffies);
760
761
return 0;
762
}
763
764
static struct platform_driver max8997_muic_driver = {
765
.driver = {
766
.name = DEV_NAME,
767
},
768
.probe = max8997_muic_probe,
769
};
770
771
module_platform_driver(max8997_muic_driver);
772
773
MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
774
MODULE_AUTHOR("Donggeun Kim <[email protected]>");
775
MODULE_LICENSE("GPL");
776
MODULE_ALIAS("platform:max8997-muic");
777
778