2 * extcon-max77843.c - Maxim MAX77843 extcon driver to support
3 * MUIC(Micro USB Interface Controller)
5 * Copyright (C) 2015 Samsung Electronics
6 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/extcon.h>
15 #include <linux/i2c.h>
16 #include <linux/interrupt.h>
17 #include <linux/kernel.h>
18 #include <linux/mfd/max77843-private.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/workqueue.h>
23 #define DELAY_MS_DEFAULT 15000 /* unit: millisecond */
25 enum max77843_muic_status
{
26 MAX77843_MUIC_STATUS1
= 0,
27 MAX77843_MUIC_STATUS2
,
28 MAX77843_MUIC_STATUS3
,
30 MAX77843_MUIC_STATUS_NUM
,
33 struct max77843_muic_info
{
35 struct max77843
*max77843
;
36 struct extcon_dev
*edev
;
39 struct work_struct irq_work
;
40 struct delayed_work wq_detcable
;
42 u8 status
[MAX77843_MUIC_STATUS_NUM
];
51 enum max77843_muic_cable_group
{
52 MAX77843_CABLE_GROUP_ADC
= 0,
53 MAX77843_CABLE_GROUP_ADC_GND
,
54 MAX77843_CABLE_GROUP_CHG
,
57 enum max77843_muic_adc_debounce_time
{
58 MAX77843_DEBOUNCE_TIME_5MS
= 0,
59 MAX77843_DEBOUNCE_TIME_10MS
,
60 MAX77843_DEBOUNCE_TIME_25MS
,
61 MAX77843_DEBOUNCE_TIME_38_62MS
,
64 /* Define accessory cable type */
65 enum max77843_muic_accessory_type
{
66 MAX77843_MUIC_ADC_GROUND
= 0,
67 MAX77843_MUIC_ADC_SEND_END_BUTTON
,
68 MAX77843_MUIC_ADC_REMOTE_S1_BUTTON
,
69 MAX77843_MUIC_ADC_REMOTE_S2_BUTTON
,
70 MAX77843_MUIC_ADC_REMOTE_S3_BUTTON
,
71 MAX77843_MUIC_ADC_REMOTE_S4_BUTTON
,
72 MAX77843_MUIC_ADC_REMOTE_S5_BUTTON
,
73 MAX77843_MUIC_ADC_REMOTE_S6_BUTTON
,
74 MAX77843_MUIC_ADC_REMOTE_S7_BUTTON
,
75 MAX77843_MUIC_ADC_REMOTE_S8_BUTTON
,
76 MAX77843_MUIC_ADC_REMOTE_S9_BUTTON
,
77 MAX77843_MUIC_ADC_REMOTE_S10_BUTTON
,
78 MAX77843_MUIC_ADC_REMOTE_S11_BUTTON
,
79 MAX77843_MUIC_ADC_REMOTE_S12_BUTTON
,
80 MAX77843_MUIC_ADC_RESERVED_ACC_1
,
81 MAX77843_MUIC_ADC_RESERVED_ACC_2
,
82 MAX77843_MUIC_ADC_RESERVED_ACC_3
,
83 MAX77843_MUIC_ADC_RESERVED_ACC_4
,
84 MAX77843_MUIC_ADC_RESERVED_ACC_5
,
85 MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2
,
86 MAX77843_MUIC_ADC_PHONE_POWERED_DEV
,
87 MAX77843_MUIC_ADC_TTY_CONVERTER
,
88 MAX77843_MUIC_ADC_UART_CABLE
,
89 MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG
,
90 MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF
,
91 MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON
,
92 MAX77843_MUIC_ADC_AV_CABLE_NOLOAD
,
93 MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG
,
94 MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF
,
95 MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON
,
96 MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1
,
97 MAX77843_MUIC_ADC_OPEN
,
99 /* The blow accessories should check
100 not only ADC value but also ADC1K and VBVolt value. */
101 /* Offset|ADC1K|VBVolt| */
102 MAX77843_MUIC_GND_USB_HOST
= 0x100, /* 0x1| 0| 0| */
103 MAX77843_MUIC_GND_USB_HOST_VB
= 0x101, /* 0x1| 0| 1| */
104 MAX77843_MUIC_GND_MHL
= 0x102, /* 0x1| 1| 0| */
105 MAX77843_MUIC_GND_MHL_VB
= 0x103, /* 0x1| 1| 1| */
108 /* Define charger cable type */
109 enum max77843_muic_charger_type
{
110 MAX77843_MUIC_CHG_NONE
= 0,
111 MAX77843_MUIC_CHG_USB
,
112 MAX77843_MUIC_CHG_DOWNSTREAM
,
113 MAX77843_MUIC_CHG_DEDICATED
,
114 MAX77843_MUIC_CHG_SPECIAL_500MA
,
115 MAX77843_MUIC_CHG_SPECIAL_1A
,
116 MAX77843_MUIC_CHG_SPECIAL_BIAS
,
117 MAX77843_MUIC_CHG_RESERVED
,
118 MAX77843_MUIC_CHG_GND
,
122 MAX77843_CABLE_USB
= 0,
123 MAX77843_CABLE_USB_HOST
,
125 MAX77843_CABLE_CHARGE_DOWNSTREAM
,
126 MAX77843_CABLE_FAST_CHARGER
,
127 MAX77843_CABLE_SLOW_CHARGER
,
129 MAX77843_CABLE_MHL_TA
,
130 MAX77843_CABLE_JIG_USB_ON
,
131 MAX77843_CABLE_JIG_USB_OFF
,
132 MAX77843_CABLE_JIG_UART_ON
,
133 MAX77843_CABLE_JIG_UART_OFF
,
138 static const char *max77843_extcon_cable
[] = {
139 [MAX77843_CABLE_USB
] = "USB",
140 [MAX77843_CABLE_USB_HOST
] = "USB-HOST",
141 [MAX77843_CABLE_TA
] = "TA",
142 [MAX77843_CABLE_CHARGE_DOWNSTREAM
] = "CHARGER-DOWNSTREAM",
143 [MAX77843_CABLE_FAST_CHARGER
] = "FAST-CHARGER",
144 [MAX77843_CABLE_SLOW_CHARGER
] = "SLOW-CHARGER",
145 [MAX77843_CABLE_MHL
] = "MHL",
146 [MAX77843_CABLE_MHL_TA
] = "MHL-TA",
147 [MAX77843_CABLE_JIG_USB_ON
] = "JIG-USB-ON",
148 [MAX77843_CABLE_JIG_USB_OFF
] = "JIG-USB-OFF",
149 [MAX77843_CABLE_JIG_UART_ON
] = "JIG-UART-ON",
150 [MAX77843_CABLE_JIG_UART_OFF
] = "JIG-UART-OFF",
153 struct max77843_muic_irq
{
159 static struct max77843_muic_irq max77843_muic_irqs
[] = {
160 { MAX77843_MUIC_IRQ_INT1_ADC
, "MUIC-ADC" },
161 { MAX77843_MUIC_IRQ_INT1_ADCERROR
, "MUIC-ADC_ERROR" },
162 { MAX77843_MUIC_IRQ_INT1_ADC1K
, "MUIC-ADC1K" },
163 { MAX77843_MUIC_IRQ_INT2_CHGTYP
, "MUIC-CHGTYP" },
164 { MAX77843_MUIC_IRQ_INT2_CHGDETRUN
, "MUIC-CHGDETRUN" },
165 { MAX77843_MUIC_IRQ_INT2_DCDTMR
, "MUIC-DCDTMR" },
166 { MAX77843_MUIC_IRQ_INT2_DXOVP
, "MUIC-DXOVP" },
167 { MAX77843_MUIC_IRQ_INT2_VBVOLT
, "MUIC-VBVOLT" },
168 { MAX77843_MUIC_IRQ_INT3_VBADC
, "MUIC-VBADC" },
169 { MAX77843_MUIC_IRQ_INT3_VDNMON
, "MUIC-VDNMON" },
170 { MAX77843_MUIC_IRQ_INT3_DNRES
, "MUIC-DNRES" },
171 { MAX77843_MUIC_IRQ_INT3_MPNACK
, "MUIC-MPNACK"},
172 { MAX77843_MUIC_IRQ_INT3_MRXBUFOW
, "MUIC-MRXBUFOW"},
173 { MAX77843_MUIC_IRQ_INT3_MRXTRF
, "MUIC-MRXTRF"},
174 { MAX77843_MUIC_IRQ_INT3_MRXPERR
, "MUIC-MRXPERR"},
175 { MAX77843_MUIC_IRQ_INT3_MRXRDY
, "MUIC-MRXRDY"},
178 static const struct regmap_config max77843_muic_regmap_config
= {
181 .max_register
= MAX77843_MUIC_REG_END
,
184 static const struct regmap_irq max77843_muic_irq
[] = {
186 { .reg_offset
= 0, .mask
= MAX77843_MUIC_ADC
, },
187 { .reg_offset
= 0, .mask
= MAX77843_MUIC_ADCERROR
, },
188 { .reg_offset
= 0, .mask
= MAX77843_MUIC_ADC1K
, },
191 { .reg_offset
= 1, .mask
= MAX77843_MUIC_CHGTYP
, },
192 { .reg_offset
= 1, .mask
= MAX77843_MUIC_CHGDETRUN
, },
193 { .reg_offset
= 1, .mask
= MAX77843_MUIC_DCDTMR
, },
194 { .reg_offset
= 1, .mask
= MAX77843_MUIC_DXOVP
, },
195 { .reg_offset
= 1, .mask
= MAX77843_MUIC_VBVOLT
, },
198 { .reg_offset
= 2, .mask
= MAX77843_MUIC_VBADC
, },
199 { .reg_offset
= 2, .mask
= MAX77843_MUIC_VDNMON
, },
200 { .reg_offset
= 2, .mask
= MAX77843_MUIC_DNRES
, },
201 { .reg_offset
= 2, .mask
= MAX77843_MUIC_MPNACK
, },
202 { .reg_offset
= 2, .mask
= MAX77843_MUIC_MRXBUFOW
, },
203 { .reg_offset
= 2, .mask
= MAX77843_MUIC_MRXTRF
, },
204 { .reg_offset
= 2, .mask
= MAX77843_MUIC_MRXPERR
, },
205 { .reg_offset
= 2, .mask
= MAX77843_MUIC_MRXRDY
, },
208 static const struct regmap_irq_chip max77843_muic_irq_chip
= {
209 .name
= "max77843-muic",
210 .status_base
= MAX77843_MUIC_REG_INT1
,
211 .mask_base
= MAX77843_MUIC_REG_INTMASK1
,
214 .irqs
= max77843_muic_irq
,
215 .num_irqs
= ARRAY_SIZE(max77843_muic_irq
),
218 static int max77843_muic_set_path(struct max77843_muic_info
*info
,
219 u8 val
, bool attached
)
221 struct max77843
*max77843
= info
->max77843
;
223 unsigned int ctrl1
, ctrl2
;
228 ctrl1
= CONTROL1_SW_OPEN
;
230 ret
= regmap_update_bits(max77843
->regmap_muic
,
231 MAX77843_MUIC_REG_CONTROL1
,
232 CONTROL1_COM_SW
, ctrl1
);
234 dev_err(info
->dev
, "Cannot switch MUIC port\n");
239 ctrl2
= MAX77843_MUIC_CONTROL2_CPEN_MASK
;
241 ctrl2
= MAX77843_MUIC_CONTROL2_LOWPWR_MASK
;
243 ret
= regmap_update_bits(max77843
->regmap_muic
,
244 MAX77843_MUIC_REG_CONTROL2
,
245 MAX77843_MUIC_CONTROL2_LOWPWR_MASK
|
246 MAX77843_MUIC_CONTROL2_CPEN_MASK
, ctrl2
);
248 dev_err(info
->dev
, "Cannot update lowpower mode\n");
253 "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
254 ctrl1
, ctrl2
, attached
? "attached" : "detached");
259 static int max77843_muic_get_cable_type(struct max77843_muic_info
*info
,
260 enum max77843_muic_cable_group group
, bool *attached
)
262 int adc
, chg_type
, cable_type
, gnd_type
;
264 adc
= info
->status
[MAX77843_MUIC_STATUS1
] &
265 MAX77843_MUIC_STATUS1_ADC_MASK
;
266 adc
>>= STATUS1_ADC_SHIFT
;
269 case MAX77843_CABLE_GROUP_ADC
:
270 if (adc
== MAX77843_MUIC_ADC_OPEN
) {
272 cable_type
= info
->prev_cable_type
;
273 info
->prev_cable_type
= MAX77843_MUIC_ADC_OPEN
;
276 cable_type
= info
->prev_cable_type
= adc
;
279 case MAX77843_CABLE_GROUP_CHG
:
280 chg_type
= info
->status
[MAX77843_MUIC_STATUS2
] &
281 MAX77843_MUIC_STATUS2_CHGTYP_MASK
;
283 /* Check GROUND accessory with charger cable */
284 if (adc
== MAX77843_MUIC_ADC_GROUND
) {
285 if (chg_type
== MAX77843_MUIC_CHG_NONE
) {
286 /* The following state when charger cable is
287 * disconnected but the GROUND accessory still
290 cable_type
= info
->prev_chg_type
;
291 info
->prev_chg_type
= MAX77843_MUIC_CHG_NONE
;
294 /* The following state when charger cable is
295 * connected on the GROUND accessory */
297 cable_type
= MAX77843_MUIC_CHG_GND
;
298 info
->prev_chg_type
= MAX77843_MUIC_CHG_GND
;
303 if (chg_type
== MAX77843_MUIC_CHG_NONE
) {
305 cable_type
= info
->prev_chg_type
;
306 info
->prev_chg_type
= MAX77843_MUIC_CHG_NONE
;
309 cable_type
= info
->prev_chg_type
= chg_type
;
312 case MAX77843_CABLE_GROUP_ADC_GND
:
313 if (adc
== MAX77843_MUIC_ADC_OPEN
) {
315 cable_type
= info
->prev_gnd_type
;
316 info
->prev_gnd_type
= MAX77843_MUIC_ADC_OPEN
;
320 /* Offset|ADC1K|VBVolt|
321 * 0x1| 0| 0| USB-HOST
322 * 0x1| 0| 1| USB-HOST with VB
324 * 0x1| 1| 1| MHL with VB */
325 /* Get ADC1K register bit */
326 gnd_type
= (info
->status
[MAX77843_MUIC_STATUS1
] &
327 MAX77843_MUIC_STATUS1_ADC1K_MASK
);
329 /* Get VBVolt register bit */
330 gnd_type
|= (info
->status
[MAX77843_MUIC_STATUS2
] &
331 MAX77843_MUIC_STATUS2_VBVOLT_MASK
);
332 gnd_type
>>= STATUS2_VBVOLT_SHIFT
;
334 /* Offset of GND cable */
335 gnd_type
|= MAX77843_MUIC_GND_USB_HOST
;
336 cable_type
= info
->prev_gnd_type
= gnd_type
;
340 dev_err(info
->dev
, "Unknown cable group (%d)\n", group
);
341 cable_type
= -EINVAL
;
348 static int max77843_muic_adc_gnd_handler(struct max77843_muic_info
*info
)
350 int ret
, gnd_cable_type
;
353 gnd_cable_type
= max77843_muic_get_cable_type(info
,
354 MAX77843_CABLE_GROUP_ADC_GND
, &attached
);
355 dev_dbg(info
->dev
, "external connector is %s (gnd:0x%02x)\n",
356 attached
? "attached" : "detached", gnd_cable_type
);
358 switch (gnd_cable_type
) {
359 case MAX77843_MUIC_GND_USB_HOST
:
360 case MAX77843_MUIC_GND_USB_HOST_VB
:
361 ret
= max77843_muic_set_path(info
, CONTROL1_SW_USB
, attached
);
365 extcon_set_cable_state(info
->edev
, "USB-HOST", attached
);
367 case MAX77843_MUIC_GND_MHL_VB
:
368 case MAX77843_MUIC_GND_MHL
:
369 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
373 extcon_set_cable_state(info
->edev
, "MHL", attached
);
376 dev_err(info
->dev
, "failed to detect %s accessory(gnd:0x%x)\n",
377 attached
? "attached" : "detached", gnd_cable_type
);
384 static int max77843_muic_jig_handler(struct max77843_muic_info
*info
,
385 int cable_type
, bool attached
)
389 dev_dbg(info
->dev
, "external connector is %s (adc:0x%02x)\n",
390 attached
? "attached" : "detached", cable_type
);
392 switch (cable_type
) {
393 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF
:
394 ret
= max77843_muic_set_path(info
, CONTROL1_SW_USB
, attached
);
397 extcon_set_cable_state(info
->edev
, "JIG-USB-OFF", attached
);
399 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON
:
400 ret
= max77843_muic_set_path(info
, CONTROL1_SW_USB
, attached
);
403 extcon_set_cable_state(info
->edev
, "JIG-USB-ON", attached
);
405 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF
:
406 ret
= max77843_muic_set_path(info
, CONTROL1_SW_UART
, attached
);
409 extcon_set_cable_state(info
->edev
, "JIG-UART-OFF", attached
);
412 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
421 static int max77843_muic_adc_handler(struct max77843_muic_info
*info
)
426 cable_type
= max77843_muic_get_cable_type(info
,
427 MAX77843_CABLE_GROUP_ADC
, &attached
);
430 "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
431 attached
? "attached" : "detached", cable_type
,
432 info
->prev_cable_type
);
434 switch (cable_type
) {
435 case MAX77843_MUIC_ADC_GROUND
:
436 ret
= max77843_muic_adc_gnd_handler(info
);
440 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF
:
441 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON
:
442 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF
:
443 ret
= max77843_muic_jig_handler(info
, cable_type
, attached
);
447 case MAX77843_MUIC_ADC_SEND_END_BUTTON
:
448 case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON
:
449 case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON
:
450 case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON
:
451 case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON
:
452 case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON
:
453 case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON
:
454 case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON
:
455 case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON
:
456 case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON
:
457 case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON
:
458 case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON
:
459 case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON
:
460 case MAX77843_MUIC_ADC_RESERVED_ACC_1
:
461 case MAX77843_MUIC_ADC_RESERVED_ACC_2
:
462 case MAX77843_MUIC_ADC_RESERVED_ACC_3
:
463 case MAX77843_MUIC_ADC_RESERVED_ACC_4
:
464 case MAX77843_MUIC_ADC_RESERVED_ACC_5
:
465 case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2
:
466 case MAX77843_MUIC_ADC_PHONE_POWERED_DEV
:
467 case MAX77843_MUIC_ADC_TTY_CONVERTER
:
468 case MAX77843_MUIC_ADC_UART_CABLE
:
469 case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG
:
470 case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD
:
471 case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG
:
472 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON
:
473 case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1
:
474 case MAX77843_MUIC_ADC_OPEN
:
476 "accessory is %s but it isn't used (adc:0x%x)\n",
477 attached
? "attached" : "detached", cable_type
);
481 "failed to detect %s accessory (adc:0x%x)\n",
482 attached
? "attached" : "detached", cable_type
);
489 static int max77843_muic_chg_handler(struct max77843_muic_info
*info
)
491 int ret
, chg_type
, gnd_type
;
494 chg_type
= max77843_muic_get_cable_type(info
,
495 MAX77843_CABLE_GROUP_CHG
, &attached
);
498 "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
499 attached
? "attached" : "detached",
500 chg_type
, info
->prev_chg_type
);
503 case MAX77843_MUIC_CHG_USB
:
504 ret
= max77843_muic_set_path(info
, CONTROL1_SW_USB
, attached
);
508 extcon_set_cable_state(info
->edev
, "USB", attached
);
510 case MAX77843_MUIC_CHG_DOWNSTREAM
:
511 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
515 extcon_set_cable_state(info
->edev
,
516 "CHARGER-DOWNSTREAM", attached
);
518 case MAX77843_MUIC_CHG_DEDICATED
:
519 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
523 extcon_set_cable_state(info
->edev
, "TA", attached
);
525 case MAX77843_MUIC_CHG_SPECIAL_500MA
:
526 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
530 extcon_set_cable_state(info
->edev
, "SLOW-CHAREGER", attached
);
532 case MAX77843_MUIC_CHG_SPECIAL_1A
:
533 ret
= max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
537 extcon_set_cable_state(info
->edev
, "FAST-CHARGER", attached
);
539 case MAX77843_MUIC_CHG_GND
:
540 gnd_type
= max77843_muic_get_cable_type(info
,
541 MAX77843_CABLE_GROUP_ADC_GND
, &attached
);
543 /* Charger cable on MHL accessory is attach or detach */
544 if (gnd_type
== MAX77843_MUIC_GND_MHL_VB
)
545 extcon_set_cable_state(info
->edev
, "MHL-TA", true);
546 else if (gnd_type
== MAX77843_MUIC_GND_MHL
)
547 extcon_set_cable_state(info
->edev
, "MHL-TA", false);
549 case MAX77843_MUIC_CHG_NONE
:
553 "failed to detect %s accessory (chg_type:0x%x)\n",
554 attached
? "attached" : "detached", chg_type
);
556 max77843_muic_set_path(info
, CONTROL1_SW_OPEN
, attached
);
563 static void max77843_muic_irq_work(struct work_struct
*work
)
565 struct max77843_muic_info
*info
= container_of(work
,
566 struct max77843_muic_info
, irq_work
);
567 struct max77843
*max77843
= info
->max77843
;
570 mutex_lock(&info
->mutex
);
572 ret
= regmap_bulk_read(max77843
->regmap_muic
,
573 MAX77843_MUIC_REG_STATUS1
, info
->status
,
574 MAX77843_MUIC_STATUS_NUM
);
576 dev_err(info
->dev
, "Cannot read STATUS registers\n");
577 mutex_unlock(&info
->mutex
);
582 ret
= max77843_muic_adc_handler(info
);
584 dev_err(info
->dev
, "Unknown cable type\n");
585 info
->irq_adc
= false;
589 ret
= max77843_muic_chg_handler(info
);
591 dev_err(info
->dev
, "Unknown charger type\n");
592 info
->irq_chg
= false;
595 mutex_unlock(&info
->mutex
);
598 static irqreturn_t
max77843_muic_irq_handler(int irq
, void *data
)
600 struct max77843_muic_info
*info
= data
;
601 int i
, irq_type
= -1;
603 for (i
= 0; i
< ARRAY_SIZE(max77843_muic_irqs
); i
++)
604 if (irq
== max77843_muic_irqs
[i
].virq
)
605 irq_type
= max77843_muic_irqs
[i
].irq
;
608 case MAX77843_MUIC_IRQ_INT1_ADC
:
609 case MAX77843_MUIC_IRQ_INT1_ADCERROR
:
610 case MAX77843_MUIC_IRQ_INT1_ADC1K
:
611 info
->irq_adc
= true;
613 case MAX77843_MUIC_IRQ_INT2_CHGTYP
:
614 case MAX77843_MUIC_IRQ_INT2_CHGDETRUN
:
615 case MAX77843_MUIC_IRQ_INT2_DCDTMR
:
616 case MAX77843_MUIC_IRQ_INT2_DXOVP
:
617 case MAX77843_MUIC_IRQ_INT2_VBVOLT
:
618 info
->irq_chg
= true;
620 case MAX77843_MUIC_IRQ_INT3_VBADC
:
621 case MAX77843_MUIC_IRQ_INT3_VDNMON
:
622 case MAX77843_MUIC_IRQ_INT3_DNRES
:
623 case MAX77843_MUIC_IRQ_INT3_MPNACK
:
624 case MAX77843_MUIC_IRQ_INT3_MRXBUFOW
:
625 case MAX77843_MUIC_IRQ_INT3_MRXTRF
:
626 case MAX77843_MUIC_IRQ_INT3_MRXPERR
:
627 case MAX77843_MUIC_IRQ_INT3_MRXRDY
:
630 dev_err(info
->dev
, "Cannot recognize IRQ(%d)\n", irq_type
);
634 schedule_work(&info
->irq_work
);
639 static void max77843_muic_detect_cable_wq(struct work_struct
*work
)
641 struct max77843_muic_info
*info
= container_of(to_delayed_work(work
),
642 struct max77843_muic_info
, wq_detcable
);
643 struct max77843
*max77843
= info
->max77843
;
644 int chg_type
, adc
, ret
;
647 mutex_lock(&info
->mutex
);
649 ret
= regmap_bulk_read(max77843
->regmap_muic
,
650 MAX77843_MUIC_REG_STATUS1
, info
->status
,
651 MAX77843_MUIC_STATUS_NUM
);
653 dev_err(info
->dev
, "Cannot read STATUS registers\n");
657 adc
= max77843_muic_get_cable_type(info
,
658 MAX77843_CABLE_GROUP_ADC
, &attached
);
659 if (attached
&& adc
!= MAX77843_MUIC_ADC_OPEN
) {
660 ret
= max77843_muic_adc_handler(info
);
662 dev_err(info
->dev
, "Cannot detect accessory\n");
667 chg_type
= max77843_muic_get_cable_type(info
,
668 MAX77843_CABLE_GROUP_CHG
, &attached
);
669 if (attached
&& chg_type
!= MAX77843_MUIC_CHG_NONE
) {
670 ret
= max77843_muic_chg_handler(info
);
672 dev_err(info
->dev
, "Cannot detect charger accessory\n");
678 mutex_unlock(&info
->mutex
);
681 static int max77843_muic_set_debounce_time(struct max77843_muic_info
*info
,
682 enum max77843_muic_adc_debounce_time time
)
684 struct max77843
*max77843
= info
->max77843
;
688 case MAX77843_DEBOUNCE_TIME_5MS
:
689 case MAX77843_DEBOUNCE_TIME_10MS
:
690 case MAX77843_DEBOUNCE_TIME_25MS
:
691 case MAX77843_DEBOUNCE_TIME_38_62MS
:
692 ret
= regmap_update_bits(max77843
->regmap_muic
,
693 MAX77843_MUIC_REG_CONTROL4
,
694 MAX77843_MUIC_CONTROL4_ADCDBSET_MASK
,
695 time
<< CONTROL4_ADCDBSET_SHIFT
);
697 dev_err(info
->dev
, "Cannot write MUIC regmap\n");
702 dev_err(info
->dev
, "Invalid ADC debounce time\n");
709 static int max77843_init_muic_regmap(struct max77843
*max77843
)
713 max77843
->i2c_muic
= i2c_new_dummy(max77843
->i2c
->adapter
,
715 if (!max77843
->i2c_muic
) {
716 dev_err(&max77843
->i2c
->dev
,
717 "Cannot allocate I2C device for MUIC\n");
721 i2c_set_clientdata(max77843
->i2c_muic
, max77843
);
723 max77843
->regmap_muic
= devm_regmap_init_i2c(max77843
->i2c_muic
,
724 &max77843_muic_regmap_config
);
725 if (IS_ERR(max77843
->regmap_muic
)) {
726 ret
= PTR_ERR(max77843
->regmap_muic
);
730 ret
= regmap_add_irq_chip(max77843
->regmap_muic
, max77843
->irq
,
731 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
| IRQF_SHARED
,
732 0, &max77843_muic_irq_chip
, &max77843
->irq_data_muic
);
734 dev_err(&max77843
->i2c
->dev
, "Cannot add MUIC IRQ chip\n");
741 i2c_unregister_device(max77843
->i2c_muic
);
746 static int max77843_muic_probe(struct platform_device
*pdev
)
748 struct max77843
*max77843
= dev_get_drvdata(pdev
->dev
.parent
);
749 struct max77843_muic_info
*info
;
753 info
= devm_kzalloc(&pdev
->dev
, sizeof(*info
), GFP_KERNEL
);
757 info
->dev
= &pdev
->dev
;
758 info
->max77843
= max77843
;
760 platform_set_drvdata(pdev
, info
);
761 mutex_init(&info
->mutex
);
763 /* Initialize i2c and regmap */
764 ret
= max77843_init_muic_regmap(max77843
);
766 dev_err(&pdev
->dev
, "Failed to init MUIC regmap\n");
770 /* Turn off auto detection configuration */
771 ret
= regmap_update_bits(max77843
->regmap_muic
,
772 MAX77843_MUIC_REG_CONTROL4
,
773 MAX77843_MUIC_CONTROL4_USBAUTO_MASK
|
774 MAX77843_MUIC_CONTROL4_FCTAUTO_MASK
,
775 CONTROL4_AUTO_DISABLE
);
777 /* Initialize extcon device */
778 info
->edev
= devm_extcon_dev_allocate(&pdev
->dev
,
779 max77843_extcon_cable
);
780 if (IS_ERR(info
->edev
)) {
781 dev_err(&pdev
->dev
, "Failed to allocate memory for extcon\n");
786 ret
= devm_extcon_dev_register(&pdev
->dev
, info
->edev
);
788 dev_err(&pdev
->dev
, "Failed to register extcon device\n");
792 /* Set ADC debounce time */
793 max77843_muic_set_debounce_time(info
, MAX77843_DEBOUNCE_TIME_25MS
);
795 /* Set initial path for UART */
796 max77843_muic_set_path(info
, CONTROL1_SW_UART
, true);
798 /* Check revision number of MUIC device */
799 ret
= regmap_read(max77843
->regmap_muic
, MAX77843_MUIC_REG_ID
, &id
);
801 dev_err(&pdev
->dev
, "Failed to read revision number\n");
804 dev_info(info
->dev
, "MUIC device ID : 0x%x\n", id
);
806 /* Support virtual irq domain for max77843 MUIC device */
807 INIT_WORK(&info
->irq_work
, max77843_muic_irq_work
);
809 for (i
= 0; i
< ARRAY_SIZE(max77843_muic_irqs
); i
++) {
810 struct max77843_muic_irq
*muic_irq
= &max77843_muic_irqs
[i
];
811 unsigned int virq
= 0;
813 virq
= regmap_irq_get_virq(max77843
->irq_data_muic
,
819 muic_irq
->virq
= virq
;
821 ret
= devm_request_threaded_irq(&pdev
->dev
, virq
, NULL
,
822 max77843_muic_irq_handler
, IRQF_NO_SUSPEND
,
823 muic_irq
->name
, info
);
826 "Failed to request irq (IRQ: %d, error: %d)\n",
832 /* Detect accessory after completing the initialization of platform */
833 INIT_DELAYED_WORK(&info
->wq_detcable
, max77843_muic_detect_cable_wq
);
834 queue_delayed_work(system_power_efficient_wq
,
835 &info
->wq_detcable
, msecs_to_jiffies(DELAY_MS_DEFAULT
));
840 regmap_del_irq_chip(max77843
->irq
, max77843
->irq_data_muic
);
841 i2c_unregister_device(max77843
->i2c_muic
);
846 static int max77843_muic_remove(struct platform_device
*pdev
)
848 struct max77843_muic_info
*info
= platform_get_drvdata(pdev
);
849 struct max77843
*max77843
= info
->max77843
;
851 cancel_work_sync(&info
->irq_work
);
852 regmap_del_irq_chip(max77843
->irq
, max77843
->irq_data_muic
);
853 i2c_unregister_device(max77843
->i2c_muic
);
858 static const struct platform_device_id max77843_muic_id
[] = {
859 { "max77843-muic", },
862 MODULE_DEVICE_TABLE(platform
, max77843_muic_id
);
864 static struct platform_driver max77843_muic_driver
= {
866 .name
= "max77843-muic",
868 .probe
= max77843_muic_probe
,
869 .remove
= max77843_muic_remove
,
870 .id_table
= max77843_muic_id
,
873 static int __init
max77843_muic_init(void)
875 return platform_driver_register(&max77843_muic_driver
);
877 subsys_initcall(max77843_muic_init
);
879 MODULE_DESCRIPTION("Maxim MAX77843 Extcon driver");
880 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
881 MODULE_LICENSE("GPL");