extcon: max77693: Remove duplicate code by making function
[deliverable/linux.git] / drivers / extcon / extcon-max77693.c
CommitLineData
db1b9037
CC
1/*
2 * extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC
3 *
4 * Copyright (C) 2012 Samsung Electrnoics
5 * Chanwoo Choi <cw00.choi@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/mfd/max77693.h>
26#include <linux/mfd/max77693-private.h>
27#include <linux/extcon.h>
28#include <linux/regmap.h>
29#include <linux/irqdomain.h>
30
31#define DEV_NAME "max77693-muic"
32
db1b9037
CC
33enum max77693_muic_adc_debounce_time {
34 ADC_DEBOUNCE_TIME_5MS = 0,
35 ADC_DEBOUNCE_TIME_10MS,
36 ADC_DEBOUNCE_TIME_25MS,
37 ADC_DEBOUNCE_TIME_38_62MS,
38};
39
40struct max77693_muic_info {
41 struct device *dev;
42 struct max77693_dev *max77693;
43 struct extcon_dev *edev;
154f757f
CC
44 int prev_cable_type;
45 int prev_cable_type_gnd;
db1b9037
CC
46 int prev_chg_type;
47 u8 status[2];
48
49 int irq;
50 struct work_struct irq_work;
51 struct mutex mutex;
52};
53
154f757f
CC
54enum max77693_muic_cable_group {
55 MAX77693_CABLE_GROUP_ADC = 0,
56 MAX77693_CABLE_GROUP_ADC_GND,
57 MAX77693_CABLE_GROUP_CHG,
58 MAX77693_CABLE_GROUP_VBVOLT,
59};
60
db1b9037
CC
61enum max77693_muic_charger_type {
62 MAX77693_CHARGER_TYPE_NONE = 0,
63 MAX77693_CHARGER_TYPE_USB,
64 MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT,
65 MAX77693_CHARGER_TYPE_DEDICATED_CHG,
66 MAX77693_CHARGER_TYPE_APPLE_500MA,
67 MAX77693_CHARGER_TYPE_APPLE_1A_2A,
68 MAX77693_CHARGER_TYPE_DEAD_BATTERY = 7,
69};
70
71/**
72 * struct max77693_muic_irq
73 * @irq: the index of irq list of MUIC device.
74 * @name: the name of irq.
75 * @virq: the virtual irq to use irq domain
76 */
77struct max77693_muic_irq {
78 unsigned int irq;
79 const char *name;
80 unsigned int virq;
81};
82
83static struct max77693_muic_irq muic_irqs[] = {
84 { MAX77693_MUIC_IRQ_INT1_ADC, "muic-ADC" },
85 { MAX77693_MUIC_IRQ_INT1_ADC_LOW, "muic-ADCLOW" },
86 { MAX77693_MUIC_IRQ_INT1_ADC_ERR, "muic-ADCError" },
87 { MAX77693_MUIC_IRQ_INT1_ADC1K, "muic-ADC1K" },
88 { MAX77693_MUIC_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
89 { MAX77693_MUIC_IRQ_INT2_CHGDETREUN, "muic-CHGDETREUN" },
90 { MAX77693_MUIC_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
91 { MAX77693_MUIC_IRQ_INT2_DXOVP, "muic-DXOVP" },
92 { MAX77693_MUIC_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
93 { MAX77693_MUIC_IRQ_INT2_VIDRM, "muic-VIDRM" },
94 { MAX77693_MUIC_IRQ_INT3_EOC, "muic-EOC" },
95 { MAX77693_MUIC_IRQ_INT3_CGMBC, "muic-CGMBC" },
96 { MAX77693_MUIC_IRQ_INT3_OVP, "muic-OVP" },
97 { MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, "muic-MBCCHG_ERR" },
98 { MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, "muic-CHG_ENABLED" },
99 { MAX77693_MUIC_IRQ_INT3_BAT_DET, "muic-BAT_DET" },
100};
101
102/* Define supported accessory type */
103enum max77693_muic_acc_type {
104 MAX77693_MUIC_ADC_GROUND = 0x0,
105 MAX77693_MUIC_ADC_SEND_END_BUTTON,
106 MAX77693_MUIC_ADC_REMOTE_S1_BUTTON,
107 MAX77693_MUIC_ADC_REMOTE_S2_BUTTON,
108 MAX77693_MUIC_ADC_REMOTE_S3_BUTTON,
109 MAX77693_MUIC_ADC_REMOTE_S4_BUTTON,
110 MAX77693_MUIC_ADC_REMOTE_S5_BUTTON,
111 MAX77693_MUIC_ADC_REMOTE_S6_BUTTON,
112 MAX77693_MUIC_ADC_REMOTE_S7_BUTTON,
113 MAX77693_MUIC_ADC_REMOTE_S8_BUTTON,
114 MAX77693_MUIC_ADC_REMOTE_S9_BUTTON,
115 MAX77693_MUIC_ADC_REMOTE_S10_BUTTON,
116 MAX77693_MUIC_ADC_REMOTE_S11_BUTTON,
117 MAX77693_MUIC_ADC_REMOTE_S12_BUTTON,
118 MAX77693_MUIC_ADC_RESERVED_ACC_1,
119 MAX77693_MUIC_ADC_RESERVED_ACC_2,
120 MAX77693_MUIC_ADC_RESERVED_ACC_3,
121 MAX77693_MUIC_ADC_RESERVED_ACC_4,
122 MAX77693_MUIC_ADC_RESERVED_ACC_5,
123 MAX77693_MUIC_ADC_CEA936_AUDIO,
124 MAX77693_MUIC_ADC_PHONE_POWERED_DEV,
125 MAX77693_MUIC_ADC_TTY_CONVERTER,
126 MAX77693_MUIC_ADC_UART_CABLE,
127 MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG,
128 MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF,
129 MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON,
130 MAX77693_MUIC_ADC_AV_CABLE_NOLOAD,
131 MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG,
132 MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF,
133 MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON,
134 MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE,
135 MAX77693_MUIC_ADC_OPEN,
136
137 /* The below accessories have same ADC value so ADCLow and
138 ADC1K bit is used to separate specific accessory */
139 MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, ADCLow:0, ADC1K:0 */
140 MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, ADCLow:1, ADC1K:0 */
141 MAX77693_MUIC_GND_MHL_CABLE = 0x103, /* ADC:0x0, ADCLow:1, ADC1K:1 */
142};
143
144/* MAX77693 MUIC device support below list of accessories(external connector) */
154f757f
CC
145enum {
146 EXTCON_CABLE_USB = 0,
147 EXTCON_CABLE_USB_HOST,
148 EXTCON_CABLE_TA,
149 EXTCON_CABLE_FAST_CHARGER,
150 EXTCON_CABLE_SLOW_CHARGER,
151 EXTCON_CABLE_CHARGE_DOWNSTREAM,
152 EXTCON_CABLE_MHL,
153 EXTCON_CABLE_AUDIO_VIDEO_LOAD,
154 EXTCON_CABLE_AUDIO_VIDEO_NOLOAD,
155 EXTCON_CABLE_JIG,
156
157 _EXTCON_CABLE_NUM,
158};
db1b9037 159
154f757f
CC
160const char *max77693_extcon_cable[] = {
161 [EXTCON_CABLE_USB] = "USB",
162 [EXTCON_CABLE_USB_HOST] = "USB-Host",
163 [EXTCON_CABLE_TA] = "TA",
164 [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger",
165 [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
166 [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
167 [EXTCON_CABLE_MHL] = "MHL",
168 [EXTCON_CABLE_AUDIO_VIDEO_LOAD] = "Audio-video-load",
169 [EXTCON_CABLE_AUDIO_VIDEO_NOLOAD] = "Audio-video-noload",
170 [EXTCON_CABLE_JIG] = "JIG",
db1b9037
CC
171 NULL,
172};
173
154f757f
CC
174/*
175 * max77693_muic_set_debounce_time - Set the debounce time of ADC
176 * @info: the instance including private data of max77693 MUIC
177 * @time: the debounce time of ADC
178 */
db1b9037
CC
179static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
180 enum max77693_muic_adc_debounce_time time)
181{
bf2627d6 182 int ret;
db1b9037
CC
183
184 switch (time) {
185 case ADC_DEBOUNCE_TIME_5MS:
186 case ADC_DEBOUNCE_TIME_10MS:
187 case ADC_DEBOUNCE_TIME_25MS:
188 case ADC_DEBOUNCE_TIME_38_62MS:
bf2627d6
AL
189 ret = max77693_update_reg(info->max77693->regmap_muic,
190 MAX77693_MUIC_REG_CTRL3,
191 time << CONTROL3_ADCDBSET_SHIFT,
192 CONTROL3_ADCDBSET_MASK);
193 if (ret)
db1b9037 194 dev_err(info->dev, "failed to set ADC debounce time\n");
db1b9037
CC
195 break;
196 default:
197 dev_err(info->dev, "invalid ADC debounce time\n");
198 ret = -EINVAL;
199 break;
200 }
201
202 return ret;
203};
204
154f757f
CC
205/*
206 * max77693_muic_set_path - Set hardware line according to attached cable
207 * @info: the instance including private data of max77693 MUIC
208 * @value: the path according to attached cable
209 * @attached: the state of cable (true:attached, false:detached)
210 *
211 * The max77693 MUIC device share outside H/W line among a varity of cables
212 * so, this function set internal path of H/W line according to the type of
213 * attached cable.
214 */
db1b9037
CC
215static int max77693_muic_set_path(struct max77693_muic_info *info,
216 u8 val, bool attached)
217{
218 int ret = 0;
219 u8 ctrl1, ctrl2 = 0;
220
221 if (attached)
222 ctrl1 = val;
223 else
224 ctrl1 = CONTROL1_SW_OPEN;
225
226 ret = max77693_update_reg(info->max77693->regmap_muic,
227 MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK);
228 if (ret < 0) {
229 dev_err(info->dev, "failed to update MUIC register\n");
230 goto out;
231 }
232
233 if (attached)
234 ctrl2 |= CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */
235 else
236 ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
237
238 ret = max77693_update_reg(info->max77693->regmap_muic,
239 MAX77693_MUIC_REG_CTRL2, ctrl2,
240 CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
241 if (ret < 0) {
242 dev_err(info->dev, "failed to update MUIC register\n");
243 goto out;
244 }
245
246 dev_info(info->dev,
247 "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
248 ctrl1, ctrl2, attached ? "attached" : "detached");
249out:
250 return ret;
251}
252
154f757f
CC
253/*
254 * max77693_muic_get_cable_type - Return cable type and check cable state
255 * @info: the instance including private data of max77693 MUIC
256 * @group: the path according to attached cable
257 * @attached: store cable state and return
258 *
259 * This function check the cable state either attached or detached,
260 * and then divide precise type of cable according to cable group.
261 * - MAX77693_CABLE_GROUP_ADC
262 * - MAX77693_CABLE_GROUP_ADC_GND
263 * - MAX77693_CABLE_GROUP_CHG
264 * - MAX77693_CABLE_GROUP_VBVOLT
265 */
266static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
267 enum max77693_muic_cable_group group, bool *attached)
db1b9037 268{
154f757f
CC
269 int cable_type = 0;
270 int adc;
271 int adc1k;
272 int adclow;
273 int vbvolt;
274 int chg_type;
275
276 switch (group) {
277 case MAX77693_CABLE_GROUP_ADC:
278 /*
279 * Read ADC value to check cable type and decide cable state
280 * according to cable type
281 */
282 adc = info->status[0] & STATUS1_ADC_MASK;
283 adc >>= STATUS1_ADC_SHIFT;
284
285 /*
286 * Check current cable state/cable type and store cable type
287 * (info->prev_cable_type) for handling cable when cable is
288 * detached.
289 */
290 if (adc == MAX77693_MUIC_ADC_OPEN) {
291 *attached = false;
292
293 cable_type = info->prev_cable_type;
294 info->prev_cable_type = MAX77693_MUIC_ADC_OPEN;
295 } else {
296 *attached = true;
297
298 cable_type = info->prev_cable_type = adc;
299 }
300 break;
301 case MAX77693_CABLE_GROUP_ADC_GND:
302 /*
303 * Read ADC value to check cable type and decide cable state
304 * according to cable type
305 */
306 adc = info->status[0] & STATUS1_ADC_MASK;
307 adc >>= STATUS1_ADC_SHIFT;
db1b9037 308
154f757f
CC
309 /*
310 * Check current cable state/cable type and store cable type
311 * (info->prev_cable_type/_gnd) for handling cable when cable
312 * is detached.
313 */
314 if (adc == MAX77693_MUIC_ADC_OPEN) {
315 *attached = false;
316
317 cable_type = info->prev_cable_type_gnd;
318 info->prev_cable_type_gnd = MAX77693_MUIC_ADC_OPEN;
319 } else {
320 *attached = true;
321
322 adclow = info->status[0] & STATUS1_ADCLOW_MASK;
323 adclow >>= STATUS1_ADCLOW_SHIFT;
324 adc1k = info->status[0] & STATUS1_ADC1K_MASK;
325 adc1k >>= STATUS1_ADC1K_SHIFT;
326
327 vbvolt = info->status[1] & STATUS2_VBVOLT_MASK;
328 vbvolt >>= STATUS2_VBVOLT_SHIFT;
329
330 /**
331 * [0x1][VBVolt][ADCLow][ADC1K]
332 * [0x1 0 0 0 ] : USB_OTG
333 * [0x1 0 1 0 ] : Audio Video Cable with load
334 * [0x1 0 1 1 ] : MHL without charging connector
335 * [0x1 1 1 1 ] : MHL with charging connector
336 */
337 cable_type = ((0x1 << 8)
338 | (vbvolt << 2)
339 | (adclow << 1)
340 | adc1k);
341
342 info->prev_cable_type = adc;
343 info->prev_cable_type_gnd = cable_type;
344 }
345
346 break;
347 case MAX77693_CABLE_GROUP_CHG:
348 /*
349 * Read charger type to check cable type and decide cable state
350 * according to type of charger cable.
351 */
352 chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
353 chg_type >>= STATUS2_CHGTYP_SHIFT;
354
355 if (chg_type == MAX77693_CHARGER_TYPE_NONE) {
356 *attached = false;
357
358 cable_type = info->prev_chg_type;
359 info->prev_chg_type = MAX77693_CHARGER_TYPE_NONE;
360 } else {
361 *attached = true;
362
363 /*
364 * Check current cable state/cable type and store cable
365 * type(info->prev_chg_type) for handling cable when
366 * charger cable is detached.
367 */
368 cable_type = info->prev_chg_type = chg_type;
369 }
370
371 break;
372 case MAX77693_CABLE_GROUP_VBVOLT:
373 /*
374 * Read ADC value to check cable type and decide cable state
375 * according to cable type
376 */
db1b9037 377 adc = info->status[0] & STATUS1_ADC_MASK;
154f757f
CC
378 adc >>= STATUS1_ADC_SHIFT;
379 chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
380 chg_type >>= STATUS2_CHGTYP_SHIFT;
381
382 if (adc == MAX77693_MUIC_ADC_OPEN
383 && chg_type == MAX77693_CHARGER_TYPE_NONE)
384 *attached = false;
385 else
386 *attached = true;
387
388 /*
389 * Read vbvolt field, if vbvolt is 1,
390 * this cable is used for charging.
db1b9037 391 */
154f757f
CC
392 vbvolt = info->status[1] & STATUS2_VBVOLT_MASK;
393 vbvolt >>= STATUS2_VBVOLT_SHIFT;
394
395 cable_type = vbvolt;
396 break;
397 default:
398 dev_err(info->dev, "Unknown cable group (%d)\n", group);
399 cable_type = -EINVAL;
400 break;
401 }
402
403 return cable_type;
404}
405
406static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
407{
408 int cable_type_gnd;
409 int ret = 0;
410 bool attached;
db1b9037 411
154f757f
CC
412 cable_type_gnd = max77693_muic_get_cable_type(info,
413 MAX77693_CABLE_GROUP_ADC_GND, &attached);
db1b9037 414
154f757f 415 switch (cable_type_gnd) {
db1b9037
CC
416 case MAX77693_MUIC_GND_USB_OTG:
417 /* USB_OTG */
418 ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
419 if (ret < 0)
420 goto out;
421 extcon_set_cable_state(info->edev, "USB-Host", attached);
422 break;
423 case MAX77693_MUIC_GND_AV_CABLE_LOAD:
424 /* Audio Video Cable with load */
425 ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
426 if (ret < 0)
427 goto out;
428 extcon_set_cable_state(info->edev,
429 "Audio-video-load", attached);
430 break;
431 case MAX77693_MUIC_GND_MHL_CABLE:
432 /* MHL */
433 extcon_set_cable_state(info->edev, "MHL", attached);
434 break;
435 default:
afcfaa87 436 dev_err(info->dev, "failed to detect %s accessory\n",
db1b9037 437 attached ? "attached" : "detached");
db1b9037
CC
438 ret = -EINVAL;
439 break;
440 }
441
442out:
443 return ret;
444}
445
154f757f 446static int max77693_muic_adc_handler(struct max77693_muic_info *info)
db1b9037 447{
154f757f
CC
448 int cable_type;
449 bool attached;
db1b9037 450 int ret = 0;
db1b9037 451
154f757f
CC
452 /* Check accessory state which is either detached or attached */
453 cable_type = max77693_muic_get_cable_type(info,
454 MAX77693_CABLE_GROUP_ADC, &attached);
db1b9037
CC
455
456 dev_info(info->dev,
457 "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
154f757f
CC
458 attached ? "attached" : "detached", cable_type,
459 info->prev_cable_type);
db1b9037 460
154f757f 461 switch (cable_type) {
db1b9037
CC
462 case MAX77693_MUIC_ADC_GROUND:
463 /* USB_OTG/MHL/Audio */
154f757f 464 max77693_muic_adc_ground_handler(info);
db1b9037
CC
465 break;
466 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
467 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:
db1b9037 468 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:
db1b9037
CC
469 /* JIG */
470 ret = max77693_muic_set_path(info, CONTROL1_SW_UART, attached);
471 if (ret < 0)
472 goto out;
473 extcon_set_cable_state(info->edev, "JIG", attached);
474 break;
154f757f 475 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:
db1b9037
CC
476 case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE:
477 /* Audio Video cable with no-load */
478 ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
479 if (ret < 0)
480 goto out;
481 extcon_set_cable_state(info->edev,
482 "Audio-video-noload", attached);
483 break;
484 case MAX77693_MUIC_ADC_SEND_END_BUTTON:
485 case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON:
486 case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON:
487 case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON:
488 case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON:
489 case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON:
490 case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON:
491 case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON:
492 case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON:
493 case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:
494 case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:
495 case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON:
496 case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON:
497 case MAX77693_MUIC_ADC_RESERVED_ACC_1:
498 case MAX77693_MUIC_ADC_RESERVED_ACC_2:
499 case MAX77693_MUIC_ADC_RESERVED_ACC_3:
500 case MAX77693_MUIC_ADC_RESERVED_ACC_4:
501 case MAX77693_MUIC_ADC_RESERVED_ACC_5:
502 case MAX77693_MUIC_ADC_CEA936_AUDIO:
503 case MAX77693_MUIC_ADC_PHONE_POWERED_DEV:
504 case MAX77693_MUIC_ADC_TTY_CONVERTER:
505 case MAX77693_MUIC_ADC_UART_CABLE:
506 case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG:
507 case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD:
508 case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG:
509 /* This accessory isn't used in general case if it is specially
510 needed to detect additional accessory, should implement
511 proper operation when this accessory is attached/detached. */
512 dev_info(info->dev,
513 "accessory is %s but it isn't used (adc:0x%x)\n",
154f757f 514 attached ? "attached" : "detached", cable_type);
db1b9037
CC
515 goto out;
516 default:
517 dev_err(info->dev,
518 "failed to detect %s accessory (adc:0x%x)\n",
154f757f 519 attached ? "attached" : "detached", cable_type);
db1b9037
CC
520 ret = -EINVAL;
521 goto out;
522 }
523
524out:
525 return ret;
526}
527
154f757f 528static int max77693_muic_chg_handler(struct max77693_muic_info *info)
db1b9037 529{
db1b9037 530 int chg_type;
154f757f
CC
531 bool attached;
532 int ret = 0;
db1b9037 533
154f757f
CC
534 chg_type = max77693_muic_get_cable_type(info,
535 MAX77693_CABLE_GROUP_CHG, &attached);
db1b9037
CC
536
537 dev_info(info->dev,
538 "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
539 attached ? "attached" : "detached",
154f757f 540 chg_type, info->prev_chg_type);
db1b9037
CC
541
542 switch (chg_type) {
543 case MAX77693_CHARGER_TYPE_USB:
544 ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
545 if (ret < 0)
546 goto out;
547 extcon_set_cable_state(info->edev, "USB", attached);
548 break;
549 case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT:
550 extcon_set_cable_state(info->edev,
551 "Charge-downstream", attached);
552 break;
553 case MAX77693_CHARGER_TYPE_DEDICATED_CHG:
554 extcon_set_cable_state(info->edev, "TA", attached);
555 break;
556 case MAX77693_CHARGER_TYPE_APPLE_500MA:
557 extcon_set_cable_state(info->edev, "Slow-charger", attached);
558 break;
559 case MAX77693_CHARGER_TYPE_APPLE_1A_2A:
560 extcon_set_cable_state(info->edev, "Fast-charger", attached);
561 break;
562 case MAX77693_CHARGER_TYPE_DEAD_BATTERY:
563 break;
564 default:
565 dev_err(info->dev,
566 "failed to detect %s accessory (chg_type:0x%x)\n",
567 attached ? "attached" : "detached", chg_type);
568 ret = -EINVAL;
569 goto out;
570 }
571
572out:
573 return ret;
574}
575
576static void max77693_muic_irq_work(struct work_struct *work)
577{
578 struct max77693_muic_info *info = container_of(work,
579 struct max77693_muic_info, irq_work);
db1b9037
CC
580 int irq_type = -1;
581 int i, ret = 0;
db1b9037
CC
582
583 if (!info->edev)
584 return;
585
586 mutex_lock(&info->mutex);
587
588 for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
589 if (info->irq == muic_irqs[i].virq)
590 irq_type = muic_irqs[i].irq;
591
592 ret = max77693_bulk_read(info->max77693->regmap_muic,
593 MAX77693_MUIC_REG_STATUS1, 2, info->status);
594 if (ret) {
595 dev_err(info->dev, "failed to read MUIC register\n");
596 mutex_unlock(&info->mutex);
597 return;
598 }
599
600 switch (irq_type) {
601 case MAX77693_MUIC_IRQ_INT1_ADC:
602 case MAX77693_MUIC_IRQ_INT1_ADC_LOW:
603 case MAX77693_MUIC_IRQ_INT1_ADC_ERR:
604 case MAX77693_MUIC_IRQ_INT1_ADC1K:
605 /* Handle all of accessory except for
606 type of charger accessory */
154f757f 607 ret = max77693_muic_adc_handler(info);
db1b9037
CC
608 break;
609 case MAX77693_MUIC_IRQ_INT2_CHGTYP:
610 case MAX77693_MUIC_IRQ_INT2_CHGDETREUN:
611 case MAX77693_MUIC_IRQ_INT2_DCDTMR:
612 case MAX77693_MUIC_IRQ_INT2_DXOVP:
613 case MAX77693_MUIC_IRQ_INT2_VBVOLT:
614 case MAX77693_MUIC_IRQ_INT2_VIDRM:
615 /* Handle charger accessory */
154f757f 616 ret = max77693_muic_chg_handler(info);
db1b9037
CC
617 break;
618 case MAX77693_MUIC_IRQ_INT3_EOC:
619 case MAX77693_MUIC_IRQ_INT3_CGMBC:
620 case MAX77693_MUIC_IRQ_INT3_OVP:
621 case MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR:
622 case MAX77693_MUIC_IRQ_INT3_CHG_ENABLED:
623 case MAX77693_MUIC_IRQ_INT3_BAT_DET:
624 break;
625 default:
626 dev_err(info->dev, "muic interrupt: irq %d occurred\n",
627 irq_type);
628 break;
629 }
630
631 if (ret < 0)
632 dev_err(info->dev, "failed to handle MUIC interrupt\n");
633
634 mutex_unlock(&info->mutex);
635
636 return;
637}
638
639static irqreturn_t max77693_muic_irq_handler(int irq, void *data)
640{
641 struct max77693_muic_info *info = data;
642
643 info->irq = irq;
644 schedule_work(&info->irq_work);
645
646 return IRQ_HANDLED;
647}
648
649static struct regmap_config max77693_muic_regmap_config = {
650 .reg_bits = 8,
651 .val_bits = 8,
652};
653
654static int max77693_muic_detect_accessory(struct max77693_muic_info *info)
655{
656 int ret = 0;
154f757f
CC
657 int adc;
658 int chg_type;
659 bool attached;
db1b9037
CC
660
661 mutex_lock(&info->mutex);
662
663 /* Read STATUSx register to detect accessory */
664 ret = max77693_bulk_read(info->max77693->regmap_muic,
665 MAX77693_MUIC_REG_STATUS1, 2, info->status);
666 if (ret) {
667 dev_err(info->dev, "failed to read MUIC register\n");
668 mutex_unlock(&info->mutex);
669 return -EINVAL;
670 }
671
154f757f
CC
672 adc = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_ADC,
673 &attached);
674 if (attached && adc != MAX77693_MUIC_ADC_OPEN) {
675 ret = max77693_muic_adc_handler(info);
db1b9037 676 if (ret < 0)
154f757f 677 dev_err(info->dev, "Cannot detect accessory\n");
db1b9037
CC
678 }
679
154f757f
CC
680 chg_type = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_CHG,
681 &attached);
682 if (attached && chg_type != MAX77693_CHARGER_TYPE_NONE) {
683 ret = max77693_muic_chg_handler(info);
db1b9037 684 if (ret < 0)
154f757f 685 dev_err(info->dev, "Cannot detect charger accessory\n");
db1b9037
CC
686 }
687
db1b9037 688 mutex_unlock(&info->mutex);
154f757f 689
db1b9037
CC
690 return ret;
691}
692
44f34fd4 693static int max77693_muic_probe(struct platform_device *pdev)
db1b9037
CC
694{
695 struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
f8457d57
CC
696 struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
697 struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
db1b9037
CC
698 struct max77693_muic_info *info;
699 int ret, i;
700 u8 id;
701
f4bb5cb5
SK
702 info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
703 GFP_KERNEL);
db1b9037
CC
704 if (!info) {
705 dev_err(&pdev->dev, "failed to allocate memory\n");
f4bb5cb5 706 return -ENOMEM;
db1b9037
CC
707 }
708 info->dev = &pdev->dev;
709 info->max77693 = max77693;
1967fa08 710 if (info->max77693->regmap_muic) {
b186b124 711 dev_dbg(&pdev->dev, "allocate register map\n");
1967fa08 712 } else {
b186b124
CC
713 info->max77693->regmap_muic = devm_regmap_init_i2c(
714 info->max77693->muic,
715 &max77693_muic_regmap_config);
716 if (IS_ERR(info->max77693->regmap_muic)) {
717 ret = PTR_ERR(info->max77693->regmap_muic);
718 dev_err(max77693->dev,
719 "failed to allocate register map: %d\n", ret);
3bf742ff 720 return ret;
b186b124 721 }
db1b9037
CC
722 }
723 platform_set_drvdata(pdev, info);
724 mutex_init(&info->mutex);
725
726 INIT_WORK(&info->irq_work, max77693_muic_irq_work);
727
728 /* Support irq domain for MAX77693 MUIC device */
729 for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
730 struct max77693_muic_irq *muic_irq = &muic_irqs[i];
00af4b16 731 unsigned int virq = 0;
db1b9037
CC
732
733 virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
00af4b16
SK
734 if (!virq) {
735 ret = -EINVAL;
db1b9037 736 goto err_irq;
00af4b16 737 }
db1b9037
CC
738 muic_irq->virq = virq;
739
740 ret = request_threaded_irq(virq, NULL,
741 max77693_muic_irq_handler,
aa49312f 742 IRQF_ONESHOT, muic_irq->name, info);
db1b9037
CC
743 if (ret) {
744 dev_err(&pdev->dev,
745 "failed: irq request (IRQ: %d,"
746 " error :%d)\n",
747 muic_irq->irq, ret);
748
db1b9037
CC
749 goto err_irq;
750 }
751 }
752
753 /* Initialize extcon device */
f4bb5cb5
SK
754 info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
755 GFP_KERNEL);
db1b9037
CC
756 if (!info->edev) {
757 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
758 ret = -ENOMEM;
759 goto err_irq;
760 }
761 info->edev->name = DEV_NAME;
762 info->edev->supported_cable = max77693_extcon_cable;
763 ret = extcon_dev_register(info->edev, NULL);
764 if (ret) {
765 dev_err(&pdev->dev, "failed to register extcon device\n");
f4bb5cb5 766 goto err_irq;
db1b9037
CC
767 }
768
f8457d57
CC
769 /* Initialize MUIC register by using platform data */
770 for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
771 enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
772
773 max77693_write_reg(info->max77693->regmap_muic,
774 muic_pdata->init_data[i].addr,
775 muic_pdata->init_data[i].data);
776
777 switch (muic_pdata->init_data[i].addr) {
778 case MAX77693_MUIC_REG_INTMASK1:
779 irq_src = MUIC_INT1;
780 break;
781 case MAX77693_MUIC_REG_INTMASK2:
782 irq_src = MUIC_INT2;
783 break;
784 case MAX77693_MUIC_REG_INTMASK3:
785 irq_src = MUIC_INT3;
786 break;
787 }
788
789 if (irq_src < MAX77693_IRQ_GROUP_NR)
790 info->max77693->irq_masks_cur[irq_src]
791 = muic_pdata->init_data[i].data;
792 }
793
db1b9037
CC
794 /* Check revision number of MUIC device*/
795 ret = max77693_read_reg(info->max77693->regmap_muic,
796 MAX77693_MUIC_REG_ID, &id);
797 if (ret < 0) {
798 dev_err(&pdev->dev, "failed to read revision number\n");
f4bb5cb5 799 goto err_irq;
db1b9037
CC
800 }
801 dev_info(info->dev, "device ID : 0x%x\n", id);
802
803 /* Set ADC debounce time */
804 max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
805
806 /* Detect accessory on boot */
807 max77693_muic_detect_accessory(info);
808
809 return ret;
810
db1b9037 811err_irq:
00af4b16
SK
812 while (--i >= 0)
813 free_irq(muic_irqs[i].virq, info);
db1b9037
CC
814 return ret;
815}
816
93ed0327 817static int max77693_muic_remove(struct platform_device *pdev)
db1b9037
CC
818{
819 struct max77693_muic_info *info = platform_get_drvdata(pdev);
820 int i;
821
822 for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
823 free_irq(muic_irqs[i].virq, info);
824 cancel_work_sync(&info->irq_work);
825 extcon_dev_unregister(info->edev);
db1b9037
CC
826
827 return 0;
828}
829
830static struct platform_driver max77693_muic_driver = {
831 .driver = {
832 .name = DEV_NAME,
833 .owner = THIS_MODULE,
834 },
835 .probe = max77693_muic_probe,
5f7e2228 836 .remove = max77693_muic_remove,
db1b9037
CC
837};
838
839module_platform_driver(max77693_muic_driver);
840
841MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver");
842MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
843MODULE_LICENSE("GPL");
844MODULE_ALIAS("platform:extcon-max77693");
This page took 0.084775 seconds and 5 git commands to generate.