aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-max8997.c
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2013-02-12 22:05:42 -0500
committerChanwoo Choi <cw00.choi@samsung.com>2013-02-13 17:54:22 -0500
commitf73f6232af9131f7b6fc6e377267e4a441727eb3 (patch)
tree67282c916730b43330c345f1e16ee29bb0b474b7 /drivers/extcon/extcon-max8997.c
parent027fcd50500fd87847891d5c2f341c1f002de3e8 (diff)
extcon: max8997: Consolidate duplicate code for checking ADC/CHG cable type
This patch make max8997_muic_get_cable_type() function to remove duplicate code for checking ADC/Charger cable type because almost internal function need to read adc/chg_type value of MUIC register. Also, remove *_detach() function, extcon-max8997 driver treat attach/detach operation of cable in max8997_*_handler() function. Lastly, this patch move defined constant in header file(include/ linux/mfd/max8997.h, max8997-private.h) because defined constant is only used in the 'extcon-max8997.c'. Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/extcon/extcon-max8997.c')
-rw-r--r--drivers/extcon/extcon-max8997.c492
1 files changed, 323 insertions, 169 deletions
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 3206daaf8e08..35338a090c06 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -44,31 +44,89 @@ struct max8997_muic_irq {
44}; 44};
45 45
46static struct max8997_muic_irq muic_irqs[] = { 46static struct max8997_muic_irq muic_irqs[] = {
47 { MAX8997_MUICIRQ_ADCError, "muic-ADC_error" }, 47 { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
48 { MAX8997_MUICIRQ_ADCLow, "muic-ADC_low" }, 48 { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
49 { MAX8997_MUICIRQ_ADC, "muic-ADC" }, 49 { MAX8997_MUICIRQ_ADC, "muic-ADC" },
50 { MAX8997_MUICIRQ_VBVolt, "muic-VB_voltage" }, 50 { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
51 { MAX8997_MUICIRQ_DBChg, "muic-DB_charger" }, 51 { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
52 { MAX8997_MUICIRQ_DCDTmr, "muic-DCD_timer" }, 52 { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
53 { MAX8997_MUICIRQ_ChgDetRun, "muic-CDR_status" }, 53 { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
54 { MAX8997_MUICIRQ_ChgTyp, "muic-charger_type" }, 54 { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
55 { MAX8997_MUICIRQ_OVP, "muic-over_voltage" }, 55 { MAX8997_MUICIRQ_OVP, "muic-OVP" },
56};
57
58/* Define supported cable type */
59enum max8997_muic_acc_type {
60 MAX8997_MUIC_ADC_GROUND = 0x0,
61 MAX8997_MUIC_ADC_MHL, /* MHL*/
62 MAX8997_MUIC_ADC_REMOTE_S1_BUTTON,
63 MAX8997_MUIC_ADC_REMOTE_S2_BUTTON,
64 MAX8997_MUIC_ADC_REMOTE_S3_BUTTON,
65 MAX8997_MUIC_ADC_REMOTE_S4_BUTTON,
66 MAX8997_MUIC_ADC_REMOTE_S5_BUTTON,
67 MAX8997_MUIC_ADC_REMOTE_S6_BUTTON,
68 MAX8997_MUIC_ADC_REMOTE_S7_BUTTON,
69 MAX8997_MUIC_ADC_REMOTE_S8_BUTTON,
70 MAX8997_MUIC_ADC_REMOTE_S9_BUTTON,
71 MAX8997_MUIC_ADC_REMOTE_S10_BUTTON,
72 MAX8997_MUIC_ADC_REMOTE_S11_BUTTON,
73 MAX8997_MUIC_ADC_REMOTE_S12_BUTTON,
74 MAX8997_MUIC_ADC_RESERVED_ACC_1,
75 MAX8997_MUIC_ADC_RESERVED_ACC_2,
76 MAX8997_MUIC_ADC_RESERVED_ACC_3,
77 MAX8997_MUIC_ADC_RESERVED_ACC_4,
78 MAX8997_MUIC_ADC_RESERVED_ACC_5,
79 MAX8997_MUIC_ADC_CEA936_AUDIO,
80 MAX8997_MUIC_ADC_PHONE_POWERED_DEV,
81 MAX8997_MUIC_ADC_TTY_CONVERTER,
82 MAX8997_MUIC_ADC_UART_CABLE,
83 MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG,
84 MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF, /* JIG-USB-OFF */
85 MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON, /* JIG-USB-ON */
86 MAX8997_MUIC_ADC_AV_CABLE_NOLOAD, /* DESKDOCK */
87 MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG,
88 MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF, /* JIG-UART */
89 MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON, /* CARDOCK */
90 MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE,
91 MAX8997_MUIC_ADC_OPEN, /* OPEN */
92};
93
94enum max8997_muic_cable_group {
95 MAX8997_CABLE_GROUP_ADC = 0,
96 MAX8997_CABLE_GROUP_ADC_GND,
97 MAX8997_CABLE_GROUP_CHG,
98 MAX8997_CABLE_GROUP_VBVOLT,
99};
100
101enum max8997_muic_usb_type {
102 MAX8997_USB_HOST,
103 MAX8997_USB_DEVICE,
104};
105
106enum max8997_muic_charger_type {
107 MAX8997_CHARGER_TYPE_NONE = 0,
108 MAX8997_CHARGER_TYPE_USB,
109 MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT,
110 MAX8997_CHARGER_TYPE_DEDICATED_CHG,
111 MAX8997_CHARGER_TYPE_500MA,
112 MAX8997_CHARGER_TYPE_1A,
113 MAX8997_CHARGER_TYPE_DEAD_BATTERY = 7,
56}; 114};
57 115
58struct max8997_muic_info { 116struct max8997_muic_info {
59 struct device *dev; 117 struct device *dev;
60 struct i2c_client *muic; 118 struct i2c_client *muic;
61 struct max8997_muic_platform_data *muic_pdata; 119 struct extcon_dev *edev;
120 int prev_cable_type;
121 int prev_chg_type;
122 u8 status[2];
62 123
63 int irq; 124 int irq;
64 struct work_struct irq_work; 125 struct work_struct irq_work;
65
66 enum max8997_muic_charger_type pre_charger_type;
67 int pre_adc;
68
69 struct mutex mutex; 126 struct mutex mutex;
70 127
71 struct extcon_dev *edev; 128 struct max8997_muic_platform_data *muic_pdata;
129 enum max8997_muic_charger_type pre_charger_type;
72}; 130};
73 131
74enum { 132enum {
@@ -181,6 +239,83 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
181 return 0; 239 return 0;
182} 240}
183 241
242/*
243 * max8997_muic_get_cable_type - Return cable type and check cable state
244 * @info: the instance including private data of max8997 MUIC
245 * @group: the path according to attached cable
246 * @attached: store cable state and return
247 *
248 * This function check the cable state either attached or detached,
249 * and then divide precise type of cable according to cable group.
250 * - MAX8997_CABLE_GROUP_ADC
251 * - MAX8997_CABLE_GROUP_CHG
252 */
253static int max8997_muic_get_cable_type(struct max8997_muic_info *info,
254 enum max8997_muic_cable_group group, bool *attached)
255{
256 int cable_type = 0;
257 int adc;
258 int chg_type;
259
260 switch (group) {
261 case MAX8997_CABLE_GROUP_ADC:
262 /*
263 * Read ADC value to check cable type and decide cable state
264 * according to cable type
265 */
266 adc = info->status[0] & STATUS1_ADC_MASK;
267 adc >>= STATUS1_ADC_SHIFT;
268
269 /*
270 * Check current cable state/cable type and store cable type
271 * (info->prev_cable_type) for handling cable when cable is
272 * detached.
273 */
274 if (adc == MAX8997_MUIC_ADC_OPEN) {
275 *attached = false;
276
277 cable_type = info->prev_cable_type;
278 info->prev_cable_type = MAX8997_MUIC_ADC_OPEN;
279 } else {
280 *attached = true;
281
282 cable_type = info->prev_cable_type = adc;
283 }
284 break;
285 case MAX8997_CABLE_GROUP_CHG:
286 /*
287 * Read charger type to check cable type and decide cable state
288 * according to type of charger cable.
289 */
290 chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
291 chg_type >>= STATUS2_CHGTYP_SHIFT;
292
293 if (chg_type == MAX8997_CHARGER_TYPE_NONE) {
294 *attached = false;
295
296 cable_type = info->prev_chg_type;
297 info->prev_chg_type = MAX8997_CHARGER_TYPE_NONE;
298 } else {
299 *attached = true;
300
301 /*
302 * Check current cable state/cable type and store cable
303 * type(info->prev_chg_type) for handling cable when
304 * charger cable is detached.
305 */
306 cable_type = info->prev_chg_type = chg_type;
307 }
308
309 break;
310 default:
311 dev_err(info->dev, "Unknown cable group (%d)\n", group);
312 cable_type = -EINVAL;
313 break;
314 }
315
316 return cable_type;
317}
318
184static int max8997_muic_handle_usb(struct max8997_muic_info *info, 319static int max8997_muic_handle_usb(struct max8997_muic_info *info,
185 enum max8997_muic_usb_type usb_type, bool attached) 320 enum max8997_muic_usb_type usb_type, bool attached)
186{ 321{
@@ -188,9 +323,9 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info,
188 323
189 if (usb_type == MAX8997_USB_HOST) { 324 if (usb_type == MAX8997_USB_HOST) {
190 ret = max8997_muic_set_path(info, CONTROL1_SW_USB, attached); 325 ret = max8997_muic_set_path(info, CONTROL1_SW_USB, attached);
191 if (ret) { 326 if (ret < 0) {
192 dev_err(info->dev, "failed to update muic register\n"); 327 dev_err(info->dev, "failed to update muic register\n");
193 goto out; 328 return ret;
194 } 329 }
195 } 330 }
196 331
@@ -202,38 +337,39 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info,
202 extcon_set_cable_state(info->edev, "USB", attached); 337 extcon_set_cable_state(info->edev, "USB", attached);
203 break; 338 break;
204 default: 339 default:
205 ret = -EINVAL; 340 dev_err(info->dev, "failed to detect %s usb cable\n",
206 break; 341 attached ? "attached" : "detached");
342 return -EINVAL;
207 } 343 }
208 344
209out: 345 return 0;
210 return ret;
211} 346}
212 347
213static int max8997_muic_handle_dock(struct max8997_muic_info *info, 348static int max8997_muic_handle_dock(struct max8997_muic_info *info,
214 int adc, bool attached) 349 int cable_type, bool attached)
215{ 350{
216 int ret = 0; 351 int ret = 0;
217 352
218 ret = max8997_muic_set_path(info, CONTROL1_SW_AUDIO, attached); 353 ret = max8997_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
219 if (ret) { 354 if (ret) {
220 dev_err(info->dev, "failed to update muic register\n"); 355 dev_err(info->dev, "failed to update muic register\n");
221 goto out; 356 return ret;
222 } 357 }
223 358
224 switch (adc) { 359 switch (cable_type) {
225 case MAX8997_ADC_DESKDOCK: 360 case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
226 extcon_set_cable_state(info->edev, "Dock-desk", attached); 361 extcon_set_cable_state(info->edev, "Dock-desk", attached);
227 break; 362 break;
228 case MAX8997_ADC_CARDOCK: 363 case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
229 extcon_set_cable_state(info->edev, "Dock-card", attached); 364 extcon_set_cable_state(info->edev, "Dock-card", attached);
230 break; 365 break;
231 default: 366 default:
232 ret = -EINVAL; 367 dev_err(info->dev, "failed to detect %s dock device\n",
233 break; 368 attached ? "attached" : "detached");
369 return -EINVAL;
234 } 370 }
235out: 371
236 return ret; 372 return 0;
237} 373}
238 374
239static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, 375static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
@@ -245,193 +381,185 @@ static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
245 ret = max8997_muic_set_path(info, CONTROL1_SW_UART, attached); 381 ret = max8997_muic_set_path(info, CONTROL1_SW_UART, attached);
246 if (ret) { 382 if (ret) {
247 dev_err(info->dev, "failed to update muic register\n"); 383 dev_err(info->dev, "failed to update muic register\n");
248 goto out; 384 return -EINVAL;
249 } 385 }
250 386
251 extcon_set_cable_state(info->edev, "JIG", attached); 387 extcon_set_cable_state(info->edev, "JIG", attached);
252out:
253 return ret;
254}
255 388
256static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info) 389 return 0;
257{
258 int ret = 0;
259
260 switch (info->pre_adc) {
261 case MAX8997_ADC_GROUND:
262 ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false);
263 break;
264 case MAX8997_ADC_MHL:
265 extcon_set_cable_state(info->edev, "MHL", false);
266 break;
267 case MAX8997_ADC_JIG_USB_1:
268 case MAX8997_ADC_JIG_USB_2:
269 ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, false);
270 break;
271 case MAX8997_ADC_DESKDOCK:
272 case MAX8997_ADC_CARDOCK:
273 ret = max8997_muic_handle_dock(info, info->pre_adc, false);
274 break;
275 case MAX8997_ADC_JIG_UART:
276 ret = max8997_muic_handle_jig_uart(info, false);
277 break;
278 default:
279 break;
280 }
281
282 return ret;
283} 390}
284 391
285static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) 392static int max8997_muic_adc_handler(struct max8997_muic_info *info)
286{ 393{
394 int cable_type;
395 bool attached;
287 int ret = 0; 396 int ret = 0;
288 397
289 switch (adc) { 398 /* Check cable state which is either detached or attached */
290 case MAX8997_ADC_GROUND: 399 cable_type = max8997_muic_get_cable_type(info,
291 ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true); 400 MAX8997_CABLE_GROUP_ADC, &attached);
292 break; 401
293 case MAX8997_ADC_MHL: 402 switch (cable_type) {
294 extcon_set_cable_state(info->edev, "MHL", true); 403 case MAX8997_MUIC_ADC_GROUND:
295 break; 404 ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, attached);
296 case MAX8997_ADC_JIG_USB_1: 405 if (ret < 0)
297 case MAX8997_ADC_JIG_USB_2: 406 return ret;
298 ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, true); 407 break;
299 break; 408 case MAX8997_MUIC_ADC_MHL:
300 case MAX8997_ADC_DESKDOCK: 409 extcon_set_cable_state(info->edev, "MHL", attached);
301 case MAX8997_ADC_CARDOCK: 410 break;
302 ret = max8997_muic_handle_dock(info, adc, true); 411 case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
303 break; 412 case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
304 case MAX8997_ADC_JIG_UART: 413 ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, attached);
305 ret = max8997_muic_handle_jig_uart(info, true); 414 if (ret < 0)
306 break; 415 return ret;
307 case MAX8997_ADC_OPEN: 416 break;
308 ret = max8997_muic_handle_adc_detach(info); 417 case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
309 break; 418 case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
310 default: 419 ret = max8997_muic_handle_dock(info, cable_type, attached);
311 ret = -EINVAL; 420 if (ret < 0)
312 goto out; 421 return ret;
313 } 422 break;
314 423 case MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF:
315 info->pre_adc = adc; 424 ret = max8997_muic_handle_jig_uart(info, attached);
316out: 425 break;
317 return ret; 426 case MAX8997_MUIC_ADC_REMOTE_S1_BUTTON:
318} 427 case MAX8997_MUIC_ADC_REMOTE_S2_BUTTON:
319 428 case MAX8997_MUIC_ADC_REMOTE_S3_BUTTON:
320static int max8997_muic_handle_charger_type_detach( 429 case MAX8997_MUIC_ADC_REMOTE_S4_BUTTON:
321 struct max8997_muic_info *info) 430 case MAX8997_MUIC_ADC_REMOTE_S5_BUTTON:
322{ 431 case MAX8997_MUIC_ADC_REMOTE_S6_BUTTON:
323 switch (info->pre_charger_type) { 432 case MAX8997_MUIC_ADC_REMOTE_S7_BUTTON:
324 case MAX8997_CHARGER_TYPE_USB: 433 case MAX8997_MUIC_ADC_REMOTE_S8_BUTTON:
325 extcon_set_cable_state(info->edev, "USB", false); 434 case MAX8997_MUIC_ADC_REMOTE_S9_BUTTON:
326 break; 435 case MAX8997_MUIC_ADC_REMOTE_S10_BUTTON:
327 case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: 436 case MAX8997_MUIC_ADC_REMOTE_S11_BUTTON:
328 extcon_set_cable_state(info->edev, "Charge-downstream", false); 437 case MAX8997_MUIC_ADC_REMOTE_S12_BUTTON:
329 break; 438 case MAX8997_MUIC_ADC_RESERVED_ACC_1:
330 case MAX8997_CHARGER_TYPE_DEDICATED_CHG: 439 case MAX8997_MUIC_ADC_RESERVED_ACC_2:
331 extcon_set_cable_state(info->edev, "TA", false); 440 case MAX8997_MUIC_ADC_RESERVED_ACC_3:
332 break; 441 case MAX8997_MUIC_ADC_RESERVED_ACC_4:
333 case MAX8997_CHARGER_TYPE_500MA: 442 case MAX8997_MUIC_ADC_RESERVED_ACC_5:
334 extcon_set_cable_state(info->edev, "Slow-charger", false); 443 case MAX8997_MUIC_ADC_CEA936_AUDIO:
335 break; 444 case MAX8997_MUIC_ADC_PHONE_POWERED_DEV:
336 case MAX8997_CHARGER_TYPE_1A: 445 case MAX8997_MUIC_ADC_TTY_CONVERTER:
337 extcon_set_cable_state(info->edev, "Fast-charger", false); 446 case MAX8997_MUIC_ADC_UART_CABLE:
338 break; 447 case MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG:
448 case MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG:
449 case MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE:
450 /*
451 * This cable isn't used in general case if it is specially
452 * needed to detect additional cable, should implement
453 * proper operation when this cable is attached/detached.
454 */
455 dev_info(info->dev,
456 "cable is %s but it isn't used (type:0x%x)\n",
457 attached ? "attached" : "detached", cable_type);
458 return -EAGAIN;
339 default: 459 default:
460 dev_err(info->dev,
461 "failed to detect %s unknown cable (type:0x%x)\n",
462 attached ? "attached" : "detached", cable_type);
340 return -EINVAL; 463 return -EINVAL;
341 } 464 }
342 465
343 return 0; 466 return 0;
344} 467}
345 468
346static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, 469static int max8997_muic_chg_handler(struct max8997_muic_info *info)
347 enum max8997_muic_charger_type charger_type)
348{ 470{
349 u8 adc; 471 int chg_type;
350 int ret; 472 bool attached;
473 int adc;
351 474
352 ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_STATUS1, &adc); 475 chg_type = max8997_muic_get_cable_type(info,
353 if (ret) { 476 MAX8997_CABLE_GROUP_CHG, &attached);
354 dev_err(info->dev, "failed to read muic register\n");
355 goto out;
356 }
357 477
358 switch (charger_type) { 478 switch (chg_type) {
359 case MAX8997_CHARGER_TYPE_NONE: 479 case MAX8997_CHARGER_TYPE_NONE:
360 ret = max8997_muic_handle_charger_type_detach(info);
361 break; 480 break;
362 case MAX8997_CHARGER_TYPE_USB: 481 case MAX8997_CHARGER_TYPE_USB:
363 if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) { 482 adc = info->status[0] & STATUS1_ADC_MASK;
483 adc >>= STATUS1_ADC_SHIFT;
484
485 if ((adc & STATUS1_ADC_MASK) == MAX8997_MUIC_ADC_OPEN) {
364 max8997_muic_handle_usb(info, 486 max8997_muic_handle_usb(info,
365 MAX8997_USB_DEVICE, true); 487 MAX8997_USB_DEVICE, attached);
366 } 488 }
367 break; 489 break;
368 case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: 490 case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
369 extcon_set_cable_state(info->edev, "Charge-downstream", true); 491 extcon_set_cable_state(info->edev, "Charge-downstream", attached);
370 break; 492 break;
371 case MAX8997_CHARGER_TYPE_DEDICATED_CHG: 493 case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
372 extcon_set_cable_state(info->edev, "TA", true); 494 extcon_set_cable_state(info->edev, "TA", attached);
373 break; 495 break;
374 case MAX8997_CHARGER_TYPE_500MA: 496 case MAX8997_CHARGER_TYPE_500MA:
375 extcon_set_cable_state(info->edev, "Slow-charger", true); 497 extcon_set_cable_state(info->edev, "Slow-charger", attached);
376 break; 498 break;
377 case MAX8997_CHARGER_TYPE_1A: 499 case MAX8997_CHARGER_TYPE_1A:
378 extcon_set_cable_state(info->edev, "Fast-charger", true); 500 extcon_set_cable_state(info->edev, "Fast-charger", attached);
379 break; 501 break;
380 default: 502 default:
381 ret = -EINVAL; 503 dev_err(info->dev,
382 goto out; 504 "failed to detect %s unknown chg cable (type:0x%x)\n",
505 attached ? "attached" : "detached", chg_type);
506 return -EINVAL;
383 } 507 }
384 508
385 info->pre_charger_type = charger_type; 509 return 0;
386out:
387 return ret;
388} 510}
389 511
390static void max8997_muic_irq_work(struct work_struct *work) 512static void max8997_muic_irq_work(struct work_struct *work)
391{ 513{
392 struct max8997_muic_info *info = container_of(work, 514 struct max8997_muic_info *info = container_of(work,
393 struct max8997_muic_info, irq_work); 515 struct max8997_muic_info, irq_work);
394 u8 status[2];
395 u8 adc, chg_type;
396 int irq_type = 0; 516 int irq_type = 0;
397 int i, ret; 517 int i, ret;
398 518
519 if (!info->edev)
520 return;
521
399 mutex_lock(&info->mutex); 522 mutex_lock(&info->mutex);
400 523
524 for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
525 if (info->irq == muic_irqs[i].virq)
526 irq_type = muic_irqs[i].irq;
527
401 ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 528 ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
402 2, status); 529 2, info->status);
403 if (ret) { 530 if (ret) {
404 dev_err(info->dev, "failed to read muic register\n"); 531 dev_err(info->dev, "failed to read muic register\n");
405 mutex_unlock(&info->mutex); 532 mutex_unlock(&info->mutex);
406 return; 533 return;
407 } 534 }
408 535
409 dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__,
410 status[0], status[1]);
411
412 for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
413 if (info->irq == muic_irqs[i].virq)
414 irq_type = muic_irqs[i].irq;
415
416 switch (irq_type) { 536 switch (irq_type) {
537 case MAX8997_MUICIRQ_ADCError:
538 case MAX8997_MUICIRQ_ADCLow:
417 case MAX8997_MUICIRQ_ADC: 539 case MAX8997_MUICIRQ_ADC:
418 adc = status[0] & STATUS1_ADC_MASK; 540 /* Handle all of cable except for charger cable */
419 adc >>= STATUS1_ADC_SHIFT; 541 ret = max8997_muic_adc_handler(info);
420
421 max8997_muic_handle_adc(info, adc);
422 break; 542 break;
543 case MAX8997_MUICIRQ_VBVolt:
544 case MAX8997_MUICIRQ_DBChg:
545 case MAX8997_MUICIRQ_DCDTmr:
546 case MAX8997_MUICIRQ_ChgDetRun:
423 case MAX8997_MUICIRQ_ChgTyp: 547 case MAX8997_MUICIRQ_ChgTyp:
424 chg_type = status[1] & STATUS2_CHGTYP_MASK; 548 /* Handle charger cable */
425 chg_type >>= STATUS2_CHGTYP_SHIFT; 549 ret = max8997_muic_chg_handler(info);
426 550 break;
427 max8997_muic_handle_charger_type(info, chg_type); 551 case MAX8997_MUICIRQ_OVP:
428 break; 552 break;
429 default: 553 default:
430 dev_info(info->dev, "misc interrupt: irq %d occurred\n", 554 dev_info(info->dev, "misc interrupt: irq %d occurred\n",
431 irq_type); 555 irq_type);
432 break; 556 mutex_unlock(&info->mutex);
557 return;
433 } 558 }
434 559
560 if (ret < 0)
561 dev_err(info->dev, "failed to handle MUIC interrupt\n");
562
435 mutex_unlock(&info->mutex); 563 mutex_unlock(&info->mutex);
436 564
437 return; 565 return;
@@ -449,29 +577,49 @@ static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
449 return IRQ_HANDLED; 577 return IRQ_HANDLED;
450} 578}
451 579
452static void max8997_muic_detect_dev(struct max8997_muic_info *info) 580static int max8997_muic_detect_dev(struct max8997_muic_info *info)
453{ 581{
454 int ret; 582 int ret = 0;
455 u8 status[2], adc, chg_type; 583 int adc;
584 int chg_type;
585 bool attached;
456 586
457 ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 587 mutex_lock(&info->mutex);
458 2, status); 588
589 /* Read STATUSx register to detect accessory */
590 ret = max8997_bulk_read(info->muic,
591 MAX8997_MUIC_REG_STATUS1, 2, info->status);
459 if (ret) { 592 if (ret) {
460 dev_err(info->dev, "failed to read muic register\n"); 593 dev_err(info->dev, "failed to read MUIC register\n");
461 return; 594 mutex_unlock(&info->mutex);
595 return -EINVAL;
462 } 596 }
463 597
464 dev_info(info->dev, "STATUS1:0x%x, STATUS2:0x%x\n", 598 adc = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC,
465 status[0], status[1]); 599 &attached);
600 if (attached && adc != MAX8997_MUIC_ADC_OPEN) {
601 ret = max8997_muic_adc_handler(info);
602 if (ret < 0) {
603 dev_err(info->dev, "Cannot detect ADC cable\n");
604 mutex_unlock(&info->mutex);
605 return ret;
606 }
607 }
466 608
467 adc = status[0] & STATUS1_ADC_MASK; 609 chg_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_CHG,
468 adc >>= STATUS1_ADC_SHIFT; 610 &attached);
611 if (attached && chg_type != MAX8997_CHARGER_TYPE_NONE) {
612 ret = max8997_muic_chg_handler(info);
613 if (ret < 0) {
614 dev_err(info->dev, "Cannot detect charger cable\n");
615 mutex_unlock(&info->mutex);
616 return ret;
617 }
618 }
469 619
470 chg_type = status[1] & STATUS2_CHGTYP_MASK; 620 mutex_unlock(&info->mutex);
471 chg_type >>= STATUS2_CHGTYP_SHIFT;
472 621
473 max8997_muic_handle_adc(info, adc); 622 return 0;
474 max8997_muic_handle_charger_type(info, chg_type);
475} 623}
476 624
477static int max8997_muic_probe(struct platform_device *pdev) 625static int max8997_muic_probe(struct platform_device *pdev)
@@ -550,10 +698,16 @@ static int max8997_muic_probe(struct platform_device *pdev)
550 max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); 698 max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
551 699
552 /* Initial device detection */ 700 /* Initial device detection */
553 max8997_muic_detect_dev(info); 701 ret = max8997_muic_detect_dev(info);
702 if (ret < 0) {
703 dev_err(&pdev->dev, "failed to detect cable type\n");
704 goto err_extcon;
705 }
554 706
555 return ret; 707 return ret;
556 708
709err_extcon:
710 extcon_dev_unregister(info->edev);
557err_irq: 711err_irq:
558 while (--i >= 0) 712 while (--i >= 0)
559 free_irq(muic_irqs[i].virq, info); 713 free_irq(muic_irqs[i].virq, info);