Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/extcon/extcon-max77843.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0+
2
//
3
// extcon-max77843.c - Maxim MAX77843 extcon driver to support
4
// MUIC(Micro USB Interface Controller)
5
//
6
// Copyright (C) 2015 Samsung Electronics
7
// Author: Jaewon Kim <[email protected]>
8
9
#include <linux/extcon-provider.h>
10
#include <linux/i2c.h>
11
#include <linux/interrupt.h>
12
#include <linux/kernel.h>
13
#include <linux/mfd/max77693-common.h>
14
#include <linux/mfd/max77843-private.h>
15
#include <linux/module.h>
16
#include <linux/platform_device.h>
17
#include <linux/workqueue.h>
18
19
#define DELAY_MS_DEFAULT 15000 /* unit: millisecond */
20
21
enum max77843_muic_status {
22
MAX77843_MUIC_STATUS1 = 0,
23
MAX77843_MUIC_STATUS2,
24
MAX77843_MUIC_STATUS3,
25
26
MAX77843_MUIC_STATUS_NUM,
27
};
28
29
struct max77843_muic_info {
30
struct device *dev;
31
struct max77693_dev *max77843;
32
struct extcon_dev *edev;
33
34
struct mutex mutex;
35
struct work_struct irq_work;
36
struct delayed_work wq_detcable;
37
38
u8 status[MAX77843_MUIC_STATUS_NUM];
39
int prev_cable_type;
40
int prev_chg_type;
41
int prev_gnd_type;
42
43
bool irq_adc;
44
bool irq_chg;
45
};
46
47
enum max77843_muic_cable_group {
48
MAX77843_CABLE_GROUP_ADC = 0,
49
MAX77843_CABLE_GROUP_ADC_GND,
50
MAX77843_CABLE_GROUP_CHG,
51
};
52
53
enum max77843_muic_adc_debounce_time {
54
MAX77843_DEBOUNCE_TIME_5MS = 0,
55
MAX77843_DEBOUNCE_TIME_10MS,
56
MAX77843_DEBOUNCE_TIME_25MS,
57
MAX77843_DEBOUNCE_TIME_38_62MS,
58
};
59
60
/* Define accessory cable type */
61
enum max77843_muic_accessory_type {
62
MAX77843_MUIC_ADC_GROUND = 0,
63
MAX77843_MUIC_ADC_SEND_END_BUTTON,
64
MAX77843_MUIC_ADC_REMOTE_S1_BUTTON,
65
MAX77843_MUIC_ADC_REMOTE_S2_BUTTON,
66
MAX77843_MUIC_ADC_REMOTE_S3_BUTTON,
67
MAX77843_MUIC_ADC_REMOTE_S4_BUTTON,
68
MAX77843_MUIC_ADC_REMOTE_S5_BUTTON,
69
MAX77843_MUIC_ADC_REMOTE_S6_BUTTON,
70
MAX77843_MUIC_ADC_REMOTE_S7_BUTTON,
71
MAX77843_MUIC_ADC_REMOTE_S8_BUTTON,
72
MAX77843_MUIC_ADC_REMOTE_S9_BUTTON,
73
MAX77843_MUIC_ADC_REMOTE_S10_BUTTON,
74
MAX77843_MUIC_ADC_REMOTE_S11_BUTTON,
75
MAX77843_MUIC_ADC_REMOTE_S12_BUTTON,
76
MAX77843_MUIC_ADC_RESERVED_ACC_1,
77
MAX77843_MUIC_ADC_RESERVED_ACC_2,
78
MAX77843_MUIC_ADC_RESERVED_ACC_3, /* SmartDock */
79
MAX77843_MUIC_ADC_RESERVED_ACC_4,
80
MAX77843_MUIC_ADC_RESERVED_ACC_5,
81
MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2,
82
MAX77843_MUIC_ADC_PHONE_POWERED_DEV,
83
MAX77843_MUIC_ADC_TTY_CONVERTER,
84
MAX77843_MUIC_ADC_UART_CABLE,
85
MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG,
86
MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF,
87
MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON,
88
MAX77843_MUIC_ADC_AV_CABLE_NOLOAD,
89
MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG,
90
MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF,
91
MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON,
92
MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1,
93
MAX77843_MUIC_ADC_OPEN,
94
95
/*
96
* The below accessories should check
97
* not only ADC value but also ADC1K and VBVolt value.
98
*/
99
/* Offset|ADC1K|VBVolt| */
100
MAX77843_MUIC_GND_USB_HOST = 0x100, /* 0x1| 0| 0| */
101
MAX77843_MUIC_GND_USB_HOST_VB = 0x101, /* 0x1| 0| 1| */
102
MAX77843_MUIC_GND_MHL = 0x102, /* 0x1| 1| 0| */
103
MAX77843_MUIC_GND_MHL_VB = 0x103, /* 0x1| 1| 1| */
104
};
105
106
/* Define charger cable type */
107
enum max77843_muic_charger_type {
108
MAX77843_MUIC_CHG_NONE = 0,
109
MAX77843_MUIC_CHG_USB,
110
MAX77843_MUIC_CHG_DOWNSTREAM,
111
MAX77843_MUIC_CHG_DEDICATED,
112
MAX77843_MUIC_CHG_SPECIAL_500MA,
113
MAX77843_MUIC_CHG_SPECIAL_1A,
114
MAX77843_MUIC_CHG_SPECIAL_BIAS,
115
MAX77843_MUIC_CHG_RESERVED,
116
MAX77843_MUIC_CHG_GND,
117
MAX77843_MUIC_CHG_DOCK,
118
};
119
120
static const unsigned int max77843_extcon_cable[] = {
121
EXTCON_USB,
122
EXTCON_USB_HOST,
123
EXTCON_CHG_USB_SDP,
124
EXTCON_CHG_USB_DCP,
125
EXTCON_CHG_USB_CDP,
126
EXTCON_CHG_USB_FAST,
127
EXTCON_CHG_USB_SLOW,
128
EXTCON_DISP_MHL,
129
EXTCON_DOCK,
130
EXTCON_JIG,
131
EXTCON_NONE,
132
};
133
134
struct max77843_muic_irq {
135
unsigned int irq;
136
const char *name;
137
unsigned int virq;
138
};
139
140
static struct max77843_muic_irq max77843_muic_irqs[] = {
141
{ MAX77843_MUIC_IRQ_INT1_ADC, "MUIC-ADC" },
142
{ MAX77843_MUIC_IRQ_INT1_ADCERROR, "MUIC-ADC_ERROR" },
143
{ MAX77843_MUIC_IRQ_INT1_ADC1K, "MUIC-ADC1K" },
144
{ MAX77843_MUIC_IRQ_INT2_CHGTYP, "MUIC-CHGTYP" },
145
{ MAX77843_MUIC_IRQ_INT2_CHGDETRUN, "MUIC-CHGDETRUN" },
146
{ MAX77843_MUIC_IRQ_INT2_DCDTMR, "MUIC-DCDTMR" },
147
{ MAX77843_MUIC_IRQ_INT2_DXOVP, "MUIC-DXOVP" },
148
{ MAX77843_MUIC_IRQ_INT2_VBVOLT, "MUIC-VBVOLT" },
149
{ MAX77843_MUIC_IRQ_INT3_VBADC, "MUIC-VBADC" },
150
{ MAX77843_MUIC_IRQ_INT3_VDNMON, "MUIC-VDNMON" },
151
{ MAX77843_MUIC_IRQ_INT3_DNRES, "MUIC-DNRES" },
152
{ MAX77843_MUIC_IRQ_INT3_MPNACK, "MUIC-MPNACK"},
153
{ MAX77843_MUIC_IRQ_INT3_MRXBUFOW, "MUIC-MRXBUFOW"},
154
{ MAX77843_MUIC_IRQ_INT3_MRXTRF, "MUIC-MRXTRF"},
155
{ MAX77843_MUIC_IRQ_INT3_MRXPERR, "MUIC-MRXPERR"},
156
{ MAX77843_MUIC_IRQ_INT3_MRXRDY, "MUIC-MRXRDY"},
157
};
158
159
static const struct regmap_config max77843_muic_regmap_config = {
160
.reg_bits = 8,
161
.val_bits = 8,
162
.max_register = MAX77843_MUIC_REG_END,
163
};
164
165
static const struct regmap_irq max77843_muic_irq[] = {
166
/* INT1 interrupt */
167
{ .reg_offset = 0, .mask = MAX77843_MUIC_ADC, },
168
{ .reg_offset = 0, .mask = MAX77843_MUIC_ADCERROR, },
169
{ .reg_offset = 0, .mask = MAX77843_MUIC_ADC1K, },
170
171
/* INT2 interrupt */
172
{ .reg_offset = 1, .mask = MAX77843_MUIC_CHGTYP, },
173
{ .reg_offset = 1, .mask = MAX77843_MUIC_CHGDETRUN, },
174
{ .reg_offset = 1, .mask = MAX77843_MUIC_DCDTMR, },
175
{ .reg_offset = 1, .mask = MAX77843_MUIC_DXOVP, },
176
{ .reg_offset = 1, .mask = MAX77843_MUIC_VBVOLT, },
177
178
/* INT3 interrupt */
179
{ .reg_offset = 2, .mask = MAX77843_MUIC_VBADC, },
180
{ .reg_offset = 2, .mask = MAX77843_MUIC_VDNMON, },
181
{ .reg_offset = 2, .mask = MAX77843_MUIC_DNRES, },
182
{ .reg_offset = 2, .mask = MAX77843_MUIC_MPNACK, },
183
{ .reg_offset = 2, .mask = MAX77843_MUIC_MRXBUFOW, },
184
{ .reg_offset = 2, .mask = MAX77843_MUIC_MRXTRF, },
185
{ .reg_offset = 2, .mask = MAX77843_MUIC_MRXPERR, },
186
{ .reg_offset = 2, .mask = MAX77843_MUIC_MRXRDY, },
187
};
188
189
static const struct regmap_irq_chip max77843_muic_irq_chip = {
190
.name = "max77843-muic",
191
.status_base = MAX77843_MUIC_REG_INT1,
192
.unmask_base = MAX77843_MUIC_REG_INTMASK1,
193
.num_regs = 3,
194
.irqs = max77843_muic_irq,
195
.num_irqs = ARRAY_SIZE(max77843_muic_irq),
196
};
197
198
static int max77843_muic_set_path(struct max77843_muic_info *info,
199
u8 val, bool attached, bool nobccomp)
200
{
201
struct max77693_dev *max77843 = info->max77843;
202
int ret = 0;
203
unsigned int ctrl1, ctrl2;
204
205
if (attached)
206
ctrl1 = val;
207
else
208
ctrl1 = MAX77843_MUIC_CONTROL1_SW_OPEN;
209
if (nobccomp) {
210
/* Disable BC1.2 protocol and force manual switch control */
211
ctrl1 |= MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK;
212
}
213
214
ret = regmap_update_bits(max77843->regmap_muic,
215
MAX77843_MUIC_REG_CONTROL1,
216
MAX77843_MUIC_CONTROL1_COM_SW |
217
MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK,
218
ctrl1);
219
if (ret < 0) {
220
dev_err(info->dev, "Cannot switch MUIC port\n");
221
return ret;
222
}
223
224
if (attached)
225
ctrl2 = MAX77843_MUIC_CONTROL2_CPEN_MASK;
226
else
227
ctrl2 = MAX77843_MUIC_CONTROL2_LOWPWR_MASK;
228
229
ret = regmap_update_bits(max77843->regmap_muic,
230
MAX77843_MUIC_REG_CONTROL2,
231
MAX77843_MUIC_CONTROL2_LOWPWR_MASK |
232
MAX77843_MUIC_CONTROL2_CPEN_MASK, ctrl2);
233
if (ret < 0) {
234
dev_err(info->dev, "Cannot update lowpower mode\n");
235
return ret;
236
}
237
238
dev_dbg(info->dev,
239
"CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
240
ctrl1, ctrl2, attached ? "attached" : "detached");
241
242
return 0;
243
}
244
245
static void max77843_charger_set_otg_vbus(struct max77843_muic_info *info,
246
bool on)
247
{
248
struct max77693_dev *max77843 = info->max77843;
249
unsigned int cnfg00;
250
251
if (on)
252
cnfg00 = MAX77843_CHG_OTG_MASK | MAX77843_CHG_BOOST_MASK;
253
else
254
cnfg00 = MAX77843_CHG_ENABLE | MAX77843_CHG_BUCK_MASK;
255
256
regmap_update_bits(max77843->regmap_chg, MAX77843_CHG_REG_CHG_CNFG_00,
257
MAX77843_CHG_MODE_MASK, cnfg00);
258
}
259
260
static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
261
enum max77843_muic_cable_group group, bool *attached)
262
{
263
int adc, chg_type, cable_type, gnd_type;
264
265
adc = info->status[MAX77843_MUIC_STATUS1] &
266
MAX77843_MUIC_STATUS1_ADC_MASK;
267
adc >>= MAX77843_MUIC_STATUS1_ADC_SHIFT;
268
269
switch (group) {
270
case MAX77843_CABLE_GROUP_ADC:
271
if (adc == MAX77843_MUIC_ADC_OPEN) {
272
*attached = false;
273
cable_type = info->prev_cable_type;
274
info->prev_cable_type = MAX77843_MUIC_ADC_OPEN;
275
} else {
276
*attached = true;
277
cable_type = info->prev_cable_type = adc;
278
}
279
break;
280
case MAX77843_CABLE_GROUP_CHG:
281
chg_type = info->status[MAX77843_MUIC_STATUS2] &
282
MAX77843_MUIC_STATUS2_CHGTYP_MASK;
283
284
/* Check GROUND accessory with charger cable */
285
if (adc == MAX77843_MUIC_ADC_GROUND) {
286
if (chg_type == MAX77843_MUIC_CHG_NONE) {
287
/*
288
* The following state when charger cable is
289
* disconnected but the GROUND accessory still
290
* connected.
291
*/
292
*attached = false;
293
cable_type = info->prev_chg_type;
294
info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
295
} else {
296
297
/*
298
* The following state when charger cable is
299
* connected on the GROUND accessory.
300
*/
301
*attached = true;
302
cable_type = MAX77843_MUIC_CHG_GND;
303
info->prev_chg_type = MAX77843_MUIC_CHG_GND;
304
}
305
break;
306
}
307
308
if (adc == MAX77843_MUIC_ADC_RESERVED_ACC_3) { /* SmartDock */
309
if (chg_type == MAX77843_MUIC_CHG_NONE) {
310
*attached = false;
311
cable_type = info->prev_chg_type;
312
info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
313
} else {
314
*attached = true;
315
cable_type = MAX77843_MUIC_CHG_DOCK;
316
info->prev_chg_type = MAX77843_MUIC_CHG_DOCK;
317
}
318
break;
319
}
320
321
if (chg_type == MAX77843_MUIC_CHG_NONE) {
322
*attached = false;
323
cable_type = info->prev_chg_type;
324
info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
325
} else {
326
*attached = true;
327
cable_type = info->prev_chg_type = chg_type;
328
}
329
break;
330
case MAX77843_CABLE_GROUP_ADC_GND:
331
if (adc == MAX77843_MUIC_ADC_OPEN) {
332
*attached = false;
333
cable_type = info->prev_gnd_type;
334
info->prev_gnd_type = MAX77843_MUIC_ADC_OPEN;
335
} else {
336
*attached = true;
337
338
/*
339
* Offset|ADC1K|VBVolt|
340
* 0x1| 0| 0| USB-HOST
341
* 0x1| 0| 1| USB-HOST with VB
342
* 0x1| 1| 0| MHL
343
* 0x1| 1| 1| MHL with VB
344
*/
345
/* Get ADC1K register bit */
346
gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
347
MAX77843_MUIC_STATUS1_ADC1K_MASK);
348
349
/* Get VBVolt register bit */
350
gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
351
MAX77843_MUIC_STATUS2_VBVOLT_MASK);
352
gnd_type >>= MAX77843_MUIC_STATUS2_VBVOLT_SHIFT;
353
354
/* Offset of GND cable */
355
gnd_type |= MAX77843_MUIC_GND_USB_HOST;
356
cable_type = info->prev_gnd_type = gnd_type;
357
}
358
break;
359
default:
360
dev_err(info->dev, "Unknown cable group (%d)\n", group);
361
cable_type = -EINVAL;
362
break;
363
}
364
365
return cable_type;
366
}
367
368
static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
369
{
370
int ret, gnd_cable_type;
371
bool attached;
372
373
gnd_cable_type = max77843_muic_get_cable_type(info,
374
MAX77843_CABLE_GROUP_ADC_GND, &attached);
375
dev_dbg(info->dev, "external connector is %s (gnd:0x%02x)\n",
376
attached ? "attached" : "detached", gnd_cable_type);
377
378
switch (gnd_cable_type) {
379
case MAX77843_MUIC_GND_USB_HOST:
380
case MAX77843_MUIC_GND_USB_HOST_VB:
381
ret = max77843_muic_set_path(info,
382
MAX77843_MUIC_CONTROL1_SW_USB,
383
attached, false);
384
if (ret < 0)
385
return ret;
386
387
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
388
max77843_charger_set_otg_vbus(info, attached);
389
break;
390
case MAX77843_MUIC_GND_MHL_VB:
391
case MAX77843_MUIC_GND_MHL:
392
ret = max77843_muic_set_path(info,
393
MAX77843_MUIC_CONTROL1_SW_OPEN,
394
attached, false);
395
if (ret < 0)
396
return ret;
397
398
extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
399
break;
400
default:
401
dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
402
attached ? "attached" : "detached", gnd_cable_type);
403
return -EINVAL;
404
}
405
406
return 0;
407
}
408
409
static int max77843_muic_jig_handler(struct max77843_muic_info *info,
410
int cable_type, bool attached)
411
{
412
int ret;
413
u8 path = MAX77843_MUIC_CONTROL1_SW_OPEN;
414
415
dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
416
attached ? "attached" : "detached", cable_type);
417
418
switch (cable_type) {
419
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
420
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
421
path = MAX77843_MUIC_CONTROL1_SW_USB;
422
break;
423
case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
424
path = MAX77843_MUIC_CONTROL1_SW_UART;
425
break;
426
default:
427
return -EINVAL;
428
}
429
430
ret = max77843_muic_set_path(info, path, attached, false);
431
if (ret < 0)
432
return ret;
433
434
extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
435
436
return 0;
437
}
438
439
static int max77843_muic_dock_handler(struct max77843_muic_info *info,
440
bool attached)
441
{
442
int ret;
443
444
dev_dbg(info->dev, "external connector is %s (adc: 0x10)\n",
445
attached ? "attached" : "detached");
446
447
ret = max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_USB,
448
attached, attached);
449
if (ret < 0)
450
return ret;
451
452
extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
453
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
454
extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
455
456
return 0;
457
}
458
459
static int max77843_muic_adc_handler(struct max77843_muic_info *info)
460
{
461
int ret, cable_type;
462
bool attached;
463
464
cable_type = max77843_muic_get_cable_type(info,
465
MAX77843_CABLE_GROUP_ADC, &attached);
466
467
dev_dbg(info->dev,
468
"external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
469
attached ? "attached" : "detached", cable_type,
470
info->prev_cable_type);
471
472
switch (cable_type) {
473
case MAX77843_MUIC_ADC_RESERVED_ACC_3: /* SmartDock */
474
ret = max77843_muic_dock_handler(info, attached);
475
if (ret < 0)
476
return ret;
477
break;
478
case MAX77843_MUIC_ADC_GROUND:
479
ret = max77843_muic_adc_gnd_handler(info);
480
if (ret < 0)
481
return ret;
482
break;
483
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
484
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
485
case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
486
ret = max77843_muic_jig_handler(info, cable_type, attached);
487
if (ret < 0)
488
return ret;
489
break;
490
case MAX77843_MUIC_ADC_SEND_END_BUTTON:
491
case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON:
492
case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON:
493
case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON:
494
case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON:
495
case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON:
496
case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON:
497
case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON:
498
case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON:
499
case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON:
500
case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON:
501
case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON:
502
case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON:
503
case MAX77843_MUIC_ADC_RESERVED_ACC_1:
504
case MAX77843_MUIC_ADC_RESERVED_ACC_2:
505
case MAX77843_MUIC_ADC_RESERVED_ACC_4:
506
case MAX77843_MUIC_ADC_RESERVED_ACC_5:
507
case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2:
508
case MAX77843_MUIC_ADC_PHONE_POWERED_DEV:
509
case MAX77843_MUIC_ADC_TTY_CONVERTER:
510
case MAX77843_MUIC_ADC_UART_CABLE:
511
case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG:
512
case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD:
513
case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG:
514
case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON:
515
case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1:
516
case MAX77843_MUIC_ADC_OPEN:
517
dev_err(info->dev,
518
"accessory is %s but it isn't used (adc:0x%x)\n",
519
attached ? "attached" : "detached", cable_type);
520
return -EAGAIN;
521
default:
522
dev_err(info->dev,
523
"failed to detect %s accessory (adc:0x%x)\n",
524
attached ? "attached" : "detached", cable_type);
525
return -EINVAL;
526
}
527
528
return 0;
529
}
530
531
static int max77843_muic_chg_handler(struct max77843_muic_info *info)
532
{
533
int ret, chg_type, gnd_type;
534
bool attached;
535
536
chg_type = max77843_muic_get_cable_type(info,
537
MAX77843_CABLE_GROUP_CHG, &attached);
538
539
dev_dbg(info->dev,
540
"external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
541
attached ? "attached" : "detached",
542
chg_type, info->prev_chg_type);
543
544
switch (chg_type) {
545
case MAX77843_MUIC_CHG_USB:
546
ret = max77843_muic_set_path(info,
547
MAX77843_MUIC_CONTROL1_SW_USB,
548
attached, false);
549
if (ret < 0)
550
return ret;
551
552
extcon_set_state_sync(info->edev, EXTCON_USB, attached);
553
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
554
attached);
555
break;
556
case MAX77843_MUIC_CHG_DOWNSTREAM:
557
ret = max77843_muic_set_path(info,
558
MAX77843_MUIC_CONTROL1_SW_OPEN,
559
attached, false);
560
if (ret < 0)
561
return ret;
562
563
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
564
attached);
565
break;
566
case MAX77843_MUIC_CHG_DEDICATED:
567
ret = max77843_muic_set_path(info,
568
MAX77843_MUIC_CONTROL1_SW_OPEN,
569
attached, false);
570
if (ret < 0)
571
return ret;
572
573
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
574
attached);
575
break;
576
case MAX77843_MUIC_CHG_SPECIAL_500MA:
577
ret = max77843_muic_set_path(info,
578
MAX77843_MUIC_CONTROL1_SW_OPEN,
579
attached, false);
580
if (ret < 0)
581
return ret;
582
583
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
584
attached);
585
break;
586
case MAX77843_MUIC_CHG_SPECIAL_1A:
587
ret = max77843_muic_set_path(info,
588
MAX77843_MUIC_CONTROL1_SW_OPEN,
589
attached, false);
590
if (ret < 0)
591
return ret;
592
593
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
594
attached);
595
break;
596
case MAX77843_MUIC_CHG_GND:
597
gnd_type = max77843_muic_get_cable_type(info,
598
MAX77843_CABLE_GROUP_ADC_GND, &attached);
599
600
/* Charger cable on MHL accessory is attach or detach */
601
if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
602
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
603
true);
604
else if (gnd_type == MAX77843_MUIC_GND_MHL)
605
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
606
false);
607
break;
608
case MAX77843_MUIC_CHG_DOCK:
609
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, attached);
610
break;
611
case MAX77843_MUIC_CHG_NONE:
612
break;
613
default:
614
dev_err(info->dev,
615
"failed to detect %s accessory (chg_type:0x%x)\n",
616
attached ? "attached" : "detached", chg_type);
617
618
max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_OPEN,
619
attached, false);
620
return -EINVAL;
621
}
622
623
return 0;
624
}
625
626
static void max77843_muic_irq_work(struct work_struct *work)
627
{
628
struct max77843_muic_info *info = container_of(work,
629
struct max77843_muic_info, irq_work);
630
struct max77693_dev *max77843 = info->max77843;
631
int ret = 0;
632
633
mutex_lock(&info->mutex);
634
635
ret = regmap_bulk_read(max77843->regmap_muic,
636
MAX77843_MUIC_REG_STATUS1, info->status,
637
MAX77843_MUIC_STATUS_NUM);
638
if (ret) {
639
dev_err(info->dev, "Cannot read STATUS registers\n");
640
mutex_unlock(&info->mutex);
641
return;
642
}
643
644
if (info->irq_adc) {
645
ret = max77843_muic_adc_handler(info);
646
if (ret)
647
dev_err(info->dev, "Unknown cable type\n");
648
info->irq_adc = false;
649
}
650
651
if (info->irq_chg) {
652
ret = max77843_muic_chg_handler(info);
653
if (ret)
654
dev_err(info->dev, "Unknown charger type\n");
655
info->irq_chg = false;
656
}
657
658
mutex_unlock(&info->mutex);
659
}
660
661
static irqreturn_t max77843_muic_irq_handler(int irq, void *data)
662
{
663
struct max77843_muic_info *info = data;
664
int i, irq_type = -1;
665
666
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++)
667
if (irq == max77843_muic_irqs[i].virq)
668
irq_type = max77843_muic_irqs[i].irq;
669
670
switch (irq_type) {
671
case MAX77843_MUIC_IRQ_INT1_ADC:
672
case MAX77843_MUIC_IRQ_INT1_ADCERROR:
673
case MAX77843_MUIC_IRQ_INT1_ADC1K:
674
info->irq_adc = true;
675
break;
676
case MAX77843_MUIC_IRQ_INT2_CHGTYP:
677
case MAX77843_MUIC_IRQ_INT2_CHGDETRUN:
678
case MAX77843_MUIC_IRQ_INT2_DCDTMR:
679
case MAX77843_MUIC_IRQ_INT2_DXOVP:
680
case MAX77843_MUIC_IRQ_INT2_VBVOLT:
681
info->irq_chg = true;
682
break;
683
case MAX77843_MUIC_IRQ_INT3_VBADC:
684
case MAX77843_MUIC_IRQ_INT3_VDNMON:
685
case MAX77843_MUIC_IRQ_INT3_DNRES:
686
case MAX77843_MUIC_IRQ_INT3_MPNACK:
687
case MAX77843_MUIC_IRQ_INT3_MRXBUFOW:
688
case MAX77843_MUIC_IRQ_INT3_MRXTRF:
689
case MAX77843_MUIC_IRQ_INT3_MRXPERR:
690
case MAX77843_MUIC_IRQ_INT3_MRXRDY:
691
break;
692
default:
693
dev_err(info->dev, "Cannot recognize IRQ(%d)\n", irq_type);
694
break;
695
}
696
697
schedule_work(&info->irq_work);
698
699
return IRQ_HANDLED;
700
}
701
702
static void max77843_muic_detect_cable_wq(struct work_struct *work)
703
{
704
struct max77843_muic_info *info = container_of(to_delayed_work(work),
705
struct max77843_muic_info, wq_detcable);
706
struct max77693_dev *max77843 = info->max77843;
707
int chg_type, adc, ret;
708
bool attached;
709
710
mutex_lock(&info->mutex);
711
712
ret = regmap_bulk_read(max77843->regmap_muic,
713
MAX77843_MUIC_REG_STATUS1, info->status,
714
MAX77843_MUIC_STATUS_NUM);
715
if (ret) {
716
dev_err(info->dev, "Cannot read STATUS registers\n");
717
goto err_cable_wq;
718
}
719
720
adc = max77843_muic_get_cable_type(info,
721
MAX77843_CABLE_GROUP_ADC, &attached);
722
if (attached && adc != MAX77843_MUIC_ADC_OPEN) {
723
ret = max77843_muic_adc_handler(info);
724
if (ret < 0) {
725
dev_err(info->dev, "Cannot detect accessory\n");
726
goto err_cable_wq;
727
}
728
}
729
730
chg_type = max77843_muic_get_cable_type(info,
731
MAX77843_CABLE_GROUP_CHG, &attached);
732
if (attached && chg_type != MAX77843_MUIC_CHG_NONE) {
733
ret = max77843_muic_chg_handler(info);
734
if (ret < 0) {
735
dev_err(info->dev, "Cannot detect charger accessory\n");
736
goto err_cable_wq;
737
}
738
}
739
740
err_cable_wq:
741
mutex_unlock(&info->mutex);
742
}
743
744
static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
745
enum max77843_muic_adc_debounce_time time)
746
{
747
struct max77693_dev *max77843 = info->max77843;
748
int ret;
749
750
switch (time) {
751
case MAX77843_DEBOUNCE_TIME_5MS:
752
case MAX77843_DEBOUNCE_TIME_10MS:
753
case MAX77843_DEBOUNCE_TIME_25MS:
754
case MAX77843_DEBOUNCE_TIME_38_62MS:
755
ret = regmap_update_bits(max77843->regmap_muic,
756
MAX77843_MUIC_REG_CONTROL4,
757
MAX77843_MUIC_CONTROL4_ADCDBSET_MASK,
758
time << MAX77843_MUIC_CONTROL4_ADCDBSET_SHIFT);
759
if (ret < 0) {
760
dev_err(info->dev, "Cannot write MUIC regmap\n");
761
return ret;
762
}
763
break;
764
default:
765
dev_err(info->dev, "Invalid ADC debounce time\n");
766
return -EINVAL;
767
}
768
769
return 0;
770
}
771
772
static int max77843_init_muic_regmap(struct max77693_dev *max77843)
773
{
774
int ret;
775
776
max77843->i2c_muic = i2c_new_dummy_device(max77843->i2c->adapter,
777
I2C_ADDR_MUIC);
778
if (IS_ERR(max77843->i2c_muic)) {
779
dev_err(&max77843->i2c->dev,
780
"Cannot allocate I2C device for MUIC\n");
781
return PTR_ERR(max77843->i2c_muic);
782
}
783
784
i2c_set_clientdata(max77843->i2c_muic, max77843);
785
786
max77843->regmap_muic = devm_regmap_init_i2c(max77843->i2c_muic,
787
&max77843_muic_regmap_config);
788
if (IS_ERR(max77843->regmap_muic)) {
789
ret = PTR_ERR(max77843->regmap_muic);
790
goto err_muic_i2c;
791
}
792
793
ret = regmap_add_irq_chip(max77843->regmap_muic, max77843->irq,
794
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
795
0, &max77843_muic_irq_chip, &max77843->irq_data_muic);
796
if (ret < 0) {
797
dev_err(&max77843->i2c->dev, "Cannot add MUIC IRQ chip\n");
798
goto err_muic_i2c;
799
}
800
801
return 0;
802
803
err_muic_i2c:
804
i2c_unregister_device(max77843->i2c_muic);
805
806
return ret;
807
}
808
809
static int max77843_muic_probe(struct platform_device *pdev)
810
{
811
struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent);
812
struct max77843_muic_info *info;
813
unsigned int id;
814
int cable_type;
815
bool attached;
816
int i, ret;
817
818
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
819
if (!info)
820
return -ENOMEM;
821
822
info->dev = &pdev->dev;
823
info->max77843 = max77843;
824
825
platform_set_drvdata(pdev, info);
826
mutex_init(&info->mutex);
827
828
/* Initialize i2c and regmap */
829
ret = max77843_init_muic_regmap(max77843);
830
if (ret) {
831
dev_err(&pdev->dev, "Failed to init MUIC regmap\n");
832
return ret;
833
}
834
835
/* Turn off auto detection configuration */
836
ret = regmap_update_bits(max77843->regmap_muic,
837
MAX77843_MUIC_REG_CONTROL4,
838
MAX77843_MUIC_CONTROL4_USBAUTO_MASK |
839
MAX77843_MUIC_CONTROL4_FCTAUTO_MASK,
840
CONTROL4_AUTO_DISABLE);
841
842
/* Initialize extcon device */
843
info->edev = devm_extcon_dev_allocate(&pdev->dev,
844
max77843_extcon_cable);
845
if (IS_ERR(info->edev)) {
846
dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
847
ret = PTR_ERR(info->edev);
848
goto err_muic_irq;
849
}
850
851
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
852
if (ret) {
853
dev_err(&pdev->dev, "Failed to register extcon device\n");
854
goto err_muic_irq;
855
}
856
857
/* Set ADC debounce time */
858
max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
859
860
/* Set initial path for UART when JIG is connected to get serial logs */
861
ret = regmap_bulk_read(max77843->regmap_muic,
862
MAX77843_MUIC_REG_STATUS1, info->status,
863
MAX77843_MUIC_STATUS_NUM);
864
if (ret) {
865
dev_err(info->dev, "Cannot read STATUS registers\n");
866
goto err_muic_irq;
867
}
868
cable_type = max77843_muic_get_cable_type(info, MAX77843_CABLE_GROUP_ADC,
869
&attached);
870
if (attached && cable_type == MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF)
871
max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART,
872
true, false);
873
874
/* Check revision number of MUIC device */
875
ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);
876
if (ret < 0) {
877
dev_err(&pdev->dev, "Failed to read revision number\n");
878
goto err_muic_irq;
879
}
880
dev_info(info->dev, "MUIC device ID : 0x%x\n", id);
881
882
/* Support virtual irq domain for max77843 MUIC device */
883
INIT_WORK(&info->irq_work, max77843_muic_irq_work);
884
885
/* Clear IRQ bits before request IRQs */
886
ret = regmap_bulk_read(max77843->regmap_muic,
887
MAX77843_MUIC_REG_INT1, info->status,
888
MAX77843_MUIC_STATUS_NUM);
889
if (ret) {
890
dev_err(&pdev->dev, "Failed to Clear IRQ bits\n");
891
goto err_muic_irq;
892
}
893
894
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
895
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
896
int virq = 0;
897
898
virq = regmap_irq_get_virq(max77843->irq_data_muic,
899
muic_irq->irq);
900
if (virq <= 0) {
901
ret = -EINVAL;
902
goto err_muic_irq;
903
}
904
muic_irq->virq = virq;
905
906
ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
907
max77843_muic_irq_handler, IRQF_NO_SUSPEND,
908
muic_irq->name, info);
909
if (ret) {
910
dev_err(&pdev->dev,
911
"Failed to request irq (IRQ: %d, error: %d)\n",
912
muic_irq->irq, ret);
913
goto err_muic_irq;
914
}
915
}
916
917
/* Detect accessory after completing the initialization of platform */
918
INIT_DELAYED_WORK(&info->wq_detcable, max77843_muic_detect_cable_wq);
919
queue_delayed_work(system_power_efficient_wq,
920
&info->wq_detcable, msecs_to_jiffies(DELAY_MS_DEFAULT));
921
922
return 0;
923
924
err_muic_irq:
925
regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
926
i2c_unregister_device(max77843->i2c_muic);
927
928
return ret;
929
}
930
931
static void max77843_muic_remove(struct platform_device *pdev)
932
{
933
struct max77843_muic_info *info = platform_get_drvdata(pdev);
934
struct max77693_dev *max77843 = info->max77843;
935
936
cancel_work_sync(&info->irq_work);
937
regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
938
i2c_unregister_device(max77843->i2c_muic);
939
}
940
941
static const struct platform_device_id max77843_muic_id[] = {
942
{ "max77843-muic", },
943
{ /* sentinel */ },
944
};
945
MODULE_DEVICE_TABLE(platform, max77843_muic_id);
946
947
static const struct of_device_id of_max77843_muic_dt_match[] = {
948
{ .compatible = "maxim,max77843-muic", },
949
{ /* sentinel */ },
950
};
951
MODULE_DEVICE_TABLE(of, of_max77843_muic_dt_match);
952
953
static struct platform_driver max77843_muic_driver = {
954
.driver = {
955
.name = "max77843-muic",
956
.of_match_table = of_max77843_muic_dt_match,
957
},
958
.probe = max77843_muic_probe,
959
.remove = max77843_muic_remove,
960
.id_table = max77843_muic_id,
961
};
962
963
static int __init max77843_muic_init(void)
964
{
965
return platform_driver_register(&max77843_muic_driver);
966
}
967
subsys_initcall(max77843_muic_init);
968
969
MODULE_DESCRIPTION("Maxim MAX77843 Extcon driver");
970
MODULE_AUTHOR("Jaewon Kim <[email protected]>");
971
MODULE_LICENSE("GPL");
972
973