1281 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC4//5// Copyright (C) 2012 Samsung Electrnoics6// Chanwoo Choi <cw00.choi@samsung.com>7 8#include <linux/devm-helpers.h>9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/i2c.h>12#include <linux/slab.h>13#include <linux/input.h>14#include <linux/interrupt.h>15#include <linux/err.h>16#include <linux/platform_device.h>17#include <linux/mfd/max77693.h>18#include <linux/mfd/max77693-common.h>19#include <linux/mfd/max77693-private.h>20#include <linux/extcon-provider.h>21#include <linux/regmap.h>22#include <linux/irqdomain.h>23 24#define DEV_NAME "max77693-muic"25#define DELAY_MS_DEFAULT 20000 /* unit: millisecond */26 27/*28 * Default value of MAX77693 register to bring up MUIC device.29 * If user don't set some initial value for MUIC device through platform data,30 * extcon-max77693 driver use 'default_init_data' to bring up base operation31 * of MAX77693 MUIC device.32 */33static struct max77693_reg_data default_init_data[] = {34 {35 /* STATUS2 - [3]ChgDetRun */36 .addr = MAX77693_MUIC_REG_STATUS2,37 .data = MAX77693_STATUS2_CHGDETRUN_MASK,38 }, {39 /* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */40 .addr = MAX77693_MUIC_REG_INTMASK1,41 .data = INTMASK1_ADC1K_MASK42 | INTMASK1_ADC_MASK,43 }, {44 /* INTMASK2 - Unmask [0]ChgTypM */45 .addr = MAX77693_MUIC_REG_INTMASK2,46 .data = INTMASK2_CHGTYP_MASK,47 }, {48 /* INTMASK3 - Mask all of interrupts */49 .addr = MAX77693_MUIC_REG_INTMASK3,50 .data = 0x0,51 }, {52 /* CDETCTRL2 */53 .addr = MAX77693_MUIC_REG_CDETCTRL2,54 .data = CDETCTRL2_VIDRMEN_MASK55 | CDETCTRL2_DXOVPEN_MASK,56 },57};58 59enum max77693_muic_adc_debounce_time {60 ADC_DEBOUNCE_TIME_5MS = 0,61 ADC_DEBOUNCE_TIME_10MS,62 ADC_DEBOUNCE_TIME_25MS,63 ADC_DEBOUNCE_TIME_38_62MS,64};65 66struct max77693_muic_info {67 struct device *dev;68 struct max77693_dev *max77693;69 struct extcon_dev *edev;70 int prev_cable_type;71 int prev_cable_type_gnd;72 int prev_chg_type;73 int prev_button_type;74 u8 status[2];75 76 int irq;77 struct work_struct irq_work;78 struct mutex mutex;79 80 /*81 * Use delayed workqueue to detect cable state and then82 * notify cable state to notifiee/platform through uevent.83 * After completing the booting of platform, the extcon provider84 * driver should notify cable state to upper layer.85 */86 struct delayed_work wq_detcable;87 88 /* Button of dock device */89 struct input_dev *dock;90 91 /*92 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB93 * h/w path of COMP2/COMN1 on CONTROL1 register.94 */95 int path_usb;96 int path_uart;97};98 99enum max77693_muic_cable_group {100 MAX77693_CABLE_GROUP_ADC = 0,101 MAX77693_CABLE_GROUP_ADC_GND,102 MAX77693_CABLE_GROUP_CHG,103 MAX77693_CABLE_GROUP_VBVOLT,104};105 106enum max77693_muic_charger_type {107 MAX77693_CHARGER_TYPE_NONE = 0,108 MAX77693_CHARGER_TYPE_USB,109 MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT,110 MAX77693_CHARGER_TYPE_DEDICATED_CHG,111 MAX77693_CHARGER_TYPE_APPLE_500MA,112 MAX77693_CHARGER_TYPE_APPLE_1A_2A,113 MAX77693_CHARGER_TYPE_DEAD_BATTERY = 7,114};115 116/**117 * struct max77693_muic_irq118 * @irq: the index of irq list of MUIC device.119 * @name: the name of irq.120 * @virq: the virtual irq to use irq domain121 */122struct max77693_muic_irq {123 unsigned int irq;124 const char *name;125 unsigned int virq;126};127 128static struct max77693_muic_irq muic_irqs[] = {129 { MAX77693_MUIC_IRQ_INT1_ADC, "muic-ADC" },130 { MAX77693_MUIC_IRQ_INT1_ADC_LOW, "muic-ADCLOW" },131 { MAX77693_MUIC_IRQ_INT1_ADC_ERR, "muic-ADCError" },132 { MAX77693_MUIC_IRQ_INT1_ADC1K, "muic-ADC1K" },133 { MAX77693_MUIC_IRQ_INT2_CHGTYP, "muic-CHGTYP" },134 { MAX77693_MUIC_IRQ_INT2_CHGDETREUN, "muic-CHGDETREUN" },135 { MAX77693_MUIC_IRQ_INT2_DCDTMR, "muic-DCDTMR" },136 { MAX77693_MUIC_IRQ_INT2_DXOVP, "muic-DXOVP" },137 { MAX77693_MUIC_IRQ_INT2_VBVOLT, "muic-VBVOLT" },138 { MAX77693_MUIC_IRQ_INT2_VIDRM, "muic-VIDRM" },139 { MAX77693_MUIC_IRQ_INT3_EOC, "muic-EOC" },140 { MAX77693_MUIC_IRQ_INT3_CGMBC, "muic-CGMBC" },141 { MAX77693_MUIC_IRQ_INT3_OVP, "muic-OVP" },142 { MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, "muic-MBCCHG_ERR" },143 { MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, "muic-CHG_ENABLED" },144 { MAX77693_MUIC_IRQ_INT3_BAT_DET, "muic-BAT_DET" },145};146 147/* Define supported accessory type */148enum max77693_muic_acc_type {149 MAX77693_MUIC_ADC_GROUND = 0x0,150 MAX77693_MUIC_ADC_SEND_END_BUTTON,151 MAX77693_MUIC_ADC_REMOTE_S1_BUTTON,152 MAX77693_MUIC_ADC_REMOTE_S2_BUTTON,153 MAX77693_MUIC_ADC_REMOTE_S3_BUTTON,154 MAX77693_MUIC_ADC_REMOTE_S4_BUTTON,155 MAX77693_MUIC_ADC_REMOTE_S5_BUTTON,156 MAX77693_MUIC_ADC_REMOTE_S6_BUTTON,157 MAX77693_MUIC_ADC_REMOTE_S7_BUTTON,158 MAX77693_MUIC_ADC_REMOTE_S8_BUTTON,159 MAX77693_MUIC_ADC_REMOTE_S9_BUTTON,160 MAX77693_MUIC_ADC_REMOTE_S10_BUTTON,161 MAX77693_MUIC_ADC_REMOTE_S11_BUTTON,162 MAX77693_MUIC_ADC_REMOTE_S12_BUTTON,163 MAX77693_MUIC_ADC_RESERVED_ACC_1,164 MAX77693_MUIC_ADC_RESERVED_ACC_2,165 MAX77693_MUIC_ADC_RESERVED_ACC_3,166 MAX77693_MUIC_ADC_RESERVED_ACC_4,167 MAX77693_MUIC_ADC_RESERVED_ACC_5,168 MAX77693_MUIC_ADC_CEA936_AUDIO,169 MAX77693_MUIC_ADC_PHONE_POWERED_DEV,170 MAX77693_MUIC_ADC_TTY_CONVERTER,171 MAX77693_MUIC_ADC_UART_CABLE,172 MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG,173 MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF,174 MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON,175 MAX77693_MUIC_ADC_AV_CABLE_NOLOAD,176 MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG,177 MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF,178 MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON,179 MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE,180 MAX77693_MUIC_ADC_OPEN,181 182 /*183 * The below accessories have same ADC value so ADCLow and184 * ADC1K bit is used to separate specific accessory.185 */186 /* ADC|VBVolot|ADCLow|ADC1K| */187 MAX77693_MUIC_GND_USB_HOST = 0x100, /* 0x0| 0| 0| 0| */188 MAX77693_MUIC_GND_USB_HOST_VB = 0x104, /* 0x0| 1| 0| 0| */189 MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */190 MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */191 MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */192};193 194/*195 * MAX77693 MUIC device support below list of accessories(external connector)196 */197static const unsigned int max77693_extcon_cable[] = {198 EXTCON_USB,199 EXTCON_USB_HOST,200 EXTCON_CHG_USB_SDP,201 EXTCON_CHG_USB_DCP,202 EXTCON_CHG_USB_FAST,203 EXTCON_CHG_USB_SLOW,204 EXTCON_CHG_USB_CDP,205 EXTCON_DISP_MHL,206 EXTCON_JIG,207 EXTCON_DOCK,208 EXTCON_NONE,209};210 211/*212 * max77693_muic_set_debounce_time - Set the debounce time of ADC213 * @info: the instance including private data of max77693 MUIC214 * @time: the debounce time of ADC215 */216static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,217 enum max77693_muic_adc_debounce_time time)218{219 int ret;220 221 switch (time) {222 case ADC_DEBOUNCE_TIME_5MS:223 case ADC_DEBOUNCE_TIME_10MS:224 case ADC_DEBOUNCE_TIME_25MS:225 case ADC_DEBOUNCE_TIME_38_62MS:226 /*227 * Don't touch BTLDset, JIGset when you want to change adc228 * debounce time. If it writes other than 0 to BTLDset, JIGset229 * muic device will be reset and loose current state.230 */231 ret = regmap_write(info->max77693->regmap_muic,232 MAX77693_MUIC_REG_CTRL3,233 time << MAX77693_CONTROL3_ADCDBSET_SHIFT);234 if (ret) {235 dev_err(info->dev, "failed to set ADC debounce time\n");236 return ret;237 }238 break;239 default:240 dev_err(info->dev, "invalid ADC debounce time\n");241 return -EINVAL;242 }243 244 return 0;245};246 247/*248 * max77693_muic_set_path - Set hardware line according to attached cable249 * @info: the instance including private data of max77693 MUIC250 * @value: the path according to attached cable251 * @attached: the state of cable (true:attached, false:detached)252 *253 * The max77693 MUIC device share outside H/W line among a varity of cables254 * so, this function set internal path of H/W line according to the type of255 * attached cable.256 */257static int max77693_muic_set_path(struct max77693_muic_info *info,258 u8 val, bool attached)259{260 int ret;261 unsigned int ctrl1, ctrl2 = 0;262 263 if (attached)264 ctrl1 = val;265 else266 ctrl1 = MAX77693_CONTROL1_SW_OPEN;267 268 ret = regmap_update_bits(info->max77693->regmap_muic,269 MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);270 if (ret < 0) {271 dev_err(info->dev, "failed to update MUIC register\n");272 return ret;273 }274 275 if (attached)276 ctrl2 |= MAX77693_CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */277 else278 ctrl2 |= MAX77693_CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */279 280 ret = regmap_update_bits(info->max77693->regmap_muic,281 MAX77693_MUIC_REG_CTRL2,282 MAX77693_CONTROL2_LOWPWR_MASK | MAX77693_CONTROL2_CPEN_MASK,283 ctrl2);284 if (ret < 0) {285 dev_err(info->dev, "failed to update MUIC register\n");286 return ret;287 }288 289 dev_info(info->dev,290 "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",291 ctrl1, ctrl2, attached ? "attached" : "detached");292 293 return 0;294}295 296/*297 * max77693_muic_get_cable_type - Return cable type and check cable state298 * @info: the instance including private data of max77693 MUIC299 * @group: the path according to attached cable300 * @attached: store cable state and return301 *302 * This function check the cable state either attached or detached,303 * and then divide precise type of cable according to cable group.304 * - MAX77693_CABLE_GROUP_ADC305 * - MAX77693_CABLE_GROUP_ADC_GND306 * - MAX77693_CABLE_GROUP_CHG307 * - MAX77693_CABLE_GROUP_VBVOLT308 */309static int max77693_muic_get_cable_type(struct max77693_muic_info *info,310 enum max77693_muic_cable_group group, bool *attached)311{312 int cable_type = 0;313 int adc;314 int adc1k;315 int adclow;316 int vbvolt;317 int chg_type;318 319 switch (group) {320 case MAX77693_CABLE_GROUP_ADC:321 /*322 * Read ADC value to check cable type and decide cable state323 * according to cable type324 */325 adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;326 adc >>= MAX77693_STATUS1_ADC_SHIFT;327 328 /*329 * Check current cable state/cable type and store cable type330 * (info->prev_cable_type) for handling cable when cable is331 * detached.332 */333 if (adc == MAX77693_MUIC_ADC_OPEN) {334 *attached = false;335 336 cable_type = info->prev_cable_type;337 info->prev_cable_type = MAX77693_MUIC_ADC_OPEN;338 } else {339 *attached = true;340 341 cable_type = info->prev_cable_type = adc;342 }343 break;344 case MAX77693_CABLE_GROUP_ADC_GND:345 /*346 * Read ADC value to check cable type and decide cable state347 * according to cable type348 */349 adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;350 adc >>= MAX77693_STATUS1_ADC_SHIFT;351 352 /*353 * Check current cable state/cable type and store cable type354 * (info->prev_cable_type/_gnd) for handling cable when cable355 * is detached.356 */357 if (adc == MAX77693_MUIC_ADC_OPEN) {358 *attached = false;359 360 cable_type = info->prev_cable_type_gnd;361 info->prev_cable_type_gnd = MAX77693_MUIC_ADC_OPEN;362 } else {363 *attached = true;364 365 adclow = info->status[0] & MAX77693_STATUS1_ADCLOW_MASK;366 adclow >>= MAX77693_STATUS1_ADCLOW_SHIFT;367 adc1k = info->status[0] & MAX77693_STATUS1_ADC1K_MASK;368 adc1k >>= MAX77693_STATUS1_ADC1K_SHIFT;369 370 vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;371 vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;372 373 /**374 * [0x1|VBVolt|ADCLow|ADC1K]375 * [0x1| 0| 0| 0] USB_HOST376 * [0x1| 1| 0| 0] USB_HSOT_VB377 * [0x1| 0| 1| 0] Audio Video cable with load378 * [0x1| 0| 1| 1] MHL without charging cable379 * [0x1| 1| 1| 1] MHL with charging cable380 */381 cable_type = ((0x1 << 8)382 | (vbvolt << 2)383 | (adclow << 1)384 | adc1k);385 386 info->prev_cable_type = adc;387 info->prev_cable_type_gnd = cable_type;388 }389 390 break;391 case MAX77693_CABLE_GROUP_CHG:392 /*393 * Read charger type to check cable type and decide cable state394 * according to type of charger cable.395 */396 chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;397 chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;398 399 if (chg_type == MAX77693_CHARGER_TYPE_NONE) {400 *attached = false;401 402 cable_type = info->prev_chg_type;403 info->prev_chg_type = MAX77693_CHARGER_TYPE_NONE;404 } else {405 *attached = true;406 407 /*408 * Check current cable state/cable type and store cable409 * type(info->prev_chg_type) for handling cable when410 * charger cable is detached.411 */412 cable_type = info->prev_chg_type = chg_type;413 }414 415 break;416 case MAX77693_CABLE_GROUP_VBVOLT:417 /*418 * Read ADC value to check cable type and decide cable state419 * according to cable type420 */421 adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;422 adc >>= MAX77693_STATUS1_ADC_SHIFT;423 chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;424 chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;425 426 if (adc == MAX77693_MUIC_ADC_OPEN427 && chg_type == MAX77693_CHARGER_TYPE_NONE)428 *attached = false;429 else430 *attached = true;431 432 /*433 * Read vbvolt field, if vbvolt is 1,434 * this cable is used for charging.435 */436 vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;437 vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;438 439 cable_type = vbvolt;440 break;441 default:442 dev_err(info->dev, "Unknown cable group (%d)\n", group);443 cable_type = -EINVAL;444 break;445 }446 447 return cable_type;448}449 450static int max77693_muic_dock_handler(struct max77693_muic_info *info,451 int cable_type, bool attached)452{453 int ret = 0;454 int vbvolt;455 bool cable_attached;456 unsigned int dock_id;457 458 dev_info(info->dev,459 "external connector is %s (adc:0x%02x)\n",460 attached ? "attached" : "detached", cable_type);461 462 switch (cable_type) {463 case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */464 /*465 * Check power cable whether attached or detached state.466 * The Dock-Smart device need surely external power supply.467 * If power cable(USB/TA) isn't connected to Dock device,468 * user can't use Dock-Smart for desktop mode.469 */470 vbvolt = max77693_muic_get_cable_type(info,471 MAX77693_CABLE_GROUP_VBVOLT, &cable_attached);472 if (attached && !vbvolt) {473 dev_warn(info->dev,474 "Cannot detect external power supply\n");475 return 0;476 }477 478 /*479 * Notify Dock/MHL state.480 * - Dock device include three type of cable which481 * are HDMI, USB for mouse/keyboard and micro-usb port482 * for USB/TA cable. Dock device need always exteranl483 * power supply(USB/TA cable through micro-usb cable). Dock484 * device support screen output of target to separate485 * monitor and mouse/keyboard for desktop mode.486 *487 * Features of 'USB/TA cable with Dock device'488 * - Support MHL489 * - Support external output feature of audio490 * - Support charging through micro-usb port without data491 * connection if TA cable is connected to target.492 * - Support charging and data connection through micro-usb port493 * if USB cable is connected between target and host494 * device.495 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)496 */497 ret = max77693_muic_set_path(info, info->path_usb, attached);498 if (ret < 0)499 return ret;500 501 extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);502 extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);503 goto out;504 case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */505 dock_id = EXTCON_DOCK;506 break;507 case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */508 dock_id = EXTCON_DOCK;509 if (!attached) {510 extcon_set_state_sync(info->edev, EXTCON_USB, false);511 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,512 false);513 }514 break;515 default:516 dev_err(info->dev, "failed to detect %s dock device\n",517 attached ? "attached" : "detached");518 return -EINVAL;519 }520 521 /* Dock-Car/Desk/Audio, PATH:AUDIO */522 ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,523 attached);524 if (ret < 0)525 return ret;526 extcon_set_state_sync(info->edev, dock_id, attached);527 528out:529 return 0;530}531 532static int max77693_muic_dock_button_handler(struct max77693_muic_info *info,533 int button_type, bool attached)534{535 struct input_dev *dock = info->dock;536 unsigned int code;537 538 switch (button_type) {539 case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON-1540 ... MAX77693_MUIC_ADC_REMOTE_S3_BUTTON+1:541 /* DOCK_KEY_PREV */542 code = KEY_PREVIOUSSONG;543 break;544 case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON-1545 ... MAX77693_MUIC_ADC_REMOTE_S7_BUTTON+1:546 /* DOCK_KEY_NEXT */547 code = KEY_NEXTSONG;548 break;549 case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:550 /* DOCK_VOL_DOWN */551 code = KEY_VOLUMEDOWN;552 break;553 case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:554 /* DOCK_VOL_UP */555 code = KEY_VOLUMEUP;556 break;557 case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON-1558 ... MAX77693_MUIC_ADC_REMOTE_S12_BUTTON+1:559 /* DOCK_KEY_PLAY_PAUSE */560 code = KEY_PLAYPAUSE;561 break;562 default:563 dev_err(info->dev,564 "failed to detect %s key (adc:0x%x)\n",565 attached ? "pressed" : "released", button_type);566 return -EINVAL;567 }568 569 input_event(dock, EV_KEY, code, attached);570 input_sync(dock);571 572 return 0;573}574 575static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)576{577 int cable_type_gnd;578 int ret = 0;579 bool attached;580 581 cable_type_gnd = max77693_muic_get_cable_type(info,582 MAX77693_CABLE_GROUP_ADC_GND, &attached);583 584 switch (cable_type_gnd) {585 case MAX77693_MUIC_GND_USB_HOST:586 case MAX77693_MUIC_GND_USB_HOST_VB:587 /* USB_HOST, PATH: AP_USB */588 ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_USB,589 attached);590 if (ret < 0)591 return ret;592 extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);593 break;594 case MAX77693_MUIC_GND_AV_CABLE_LOAD:595 /* Audio Video Cable with load, PATH:AUDIO */596 ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,597 attached);598 if (ret < 0)599 return ret;600 extcon_set_state_sync(info->edev, EXTCON_USB, attached);601 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,602 attached);603 break;604 case MAX77693_MUIC_GND_MHL:605 case MAX77693_MUIC_GND_MHL_VB:606 /* MHL or MHL with USB/TA cable */607 extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);608 break;609 default:610 dev_err(info->dev, "failed to detect %s cable of gnd type\n",611 attached ? "attached" : "detached");612 return -EINVAL;613 }614 615 return 0;616}617 618static int max77693_muic_jig_handler(struct max77693_muic_info *info,619 int cable_type, bool attached)620{621 int ret = 0;622 u8 path = MAX77693_CONTROL1_SW_OPEN;623 624 dev_info(info->dev,625 "external connector is %s (adc:0x%02x)\n",626 attached ? "attached" : "detached", cable_type);627 628 switch (cable_type) {629 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */630 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */631 /* PATH:AP_USB */632 path = MAX77693_CONTROL1_SW_USB;633 break;634 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */635 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* ADC_JIG_UART_ON */636 /* PATH:AP_UART */637 path = MAX77693_CONTROL1_SW_UART;638 break;639 default:640 dev_err(info->dev, "failed to detect %s jig cable\n",641 attached ? "attached" : "detached");642 return -EINVAL;643 }644 645 ret = max77693_muic_set_path(info, path, attached);646 if (ret < 0)647 return ret;648 649 extcon_set_state_sync(info->edev, EXTCON_JIG, attached);650 651 return 0;652}653 654static int max77693_muic_adc_handler(struct max77693_muic_info *info)655{656 int cable_type;657 int button_type;658 bool attached;659 int ret = 0;660 661 /* Check accessory state which is either detached or attached */662 cable_type = max77693_muic_get_cable_type(info,663 MAX77693_CABLE_GROUP_ADC, &attached);664 665 dev_info(info->dev,666 "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",667 attached ? "attached" : "detached", cable_type,668 info->prev_cable_type);669 670 switch (cable_type) {671 case MAX77693_MUIC_ADC_GROUND:672 /* USB_HOST/MHL/Audio */673 max77693_muic_adc_ground_handler(info);674 break;675 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:676 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:677 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:678 case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:679 /* JIG */680 ret = max77693_muic_jig_handler(info, cable_type, attached);681 if (ret < 0)682 return ret;683 break;684 case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */685 case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */686 case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */687 /*688 * DOCK device689 *690 * The MAX77693 MUIC device can detect total 34 cable type691 * except of charger cable and MUIC device didn't define692 * specfic role of cable in the range of from 0x01 to 0x12693 * of ADC value. So, can use/define cable with no role according694 * to schema of hardware board.695 */696 ret = max77693_muic_dock_handler(info, cable_type, attached);697 if (ret < 0)698 return ret;699 break;700 case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */701 case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */702 case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */703 case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */704 case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */705 /*706 * Button of DOCK device707 * - the Prev/Next/Volume Up/Volume Down/Play-Pause button708 *709 * The MAX77693 MUIC device can detect total 34 cable type710 * except of charger cable and MUIC device didn't define711 * specfic role of cable in the range of from 0x01 to 0x12712 * of ADC value. So, can use/define cable with no role according713 * to schema of hardware board.714 */715 if (attached)716 button_type = info->prev_button_type = cable_type;717 else718 button_type = info->prev_button_type;719 720 ret = max77693_muic_dock_button_handler(info, button_type,721 attached);722 if (ret < 0)723 return ret;724 break;725 case MAX77693_MUIC_ADC_SEND_END_BUTTON:726 case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON:727 case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON:728 case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON:729 case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON:730 case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON:731 case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON:732 case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON:733 case MAX77693_MUIC_ADC_RESERVED_ACC_1:734 case MAX77693_MUIC_ADC_RESERVED_ACC_2:735 case MAX77693_MUIC_ADC_RESERVED_ACC_4:736 case MAX77693_MUIC_ADC_RESERVED_ACC_5:737 case MAX77693_MUIC_ADC_CEA936_AUDIO:738 case MAX77693_MUIC_ADC_PHONE_POWERED_DEV:739 case MAX77693_MUIC_ADC_TTY_CONVERTER:740 case MAX77693_MUIC_ADC_UART_CABLE:741 case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG:742 case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG:743 /*744 * This accessory isn't used in general case if it is specially745 * needed to detect additional accessory, should implement746 * proper operation when this accessory is attached/detached.747 */748 dev_info(info->dev,749 "accessory is %s but it isn't used (adc:0x%x)\n",750 attached ? "attached" : "detached", cable_type);751 return -EAGAIN;752 default:753 dev_err(info->dev,754 "failed to detect %s accessory (adc:0x%x)\n",755 attached ? "attached" : "detached", cable_type);756 return -EINVAL;757 }758 759 return 0;760}761 762static int max77693_muic_chg_handler(struct max77693_muic_info *info)763{764 int chg_type;765 int cable_type_gnd;766 int cable_type;767 bool attached;768 bool cable_attached;769 int ret = 0;770 771 chg_type = max77693_muic_get_cable_type(info,772 MAX77693_CABLE_GROUP_CHG, &attached);773 774 dev_info(info->dev,775 "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",776 attached ? "attached" : "detached",777 chg_type, info->prev_chg_type);778 779 switch (chg_type) {780 case MAX77693_CHARGER_TYPE_USB:781 case MAX77693_CHARGER_TYPE_DEDICATED_CHG:782 case MAX77693_CHARGER_TYPE_NONE:783 /* Check MAX77693_CABLE_GROUP_ADC_GND type */784 cable_type_gnd = max77693_muic_get_cable_type(info,785 MAX77693_CABLE_GROUP_ADC_GND,786 &cable_attached);787 switch (cable_type_gnd) {788 case MAX77693_MUIC_GND_MHL:789 case MAX77693_MUIC_GND_MHL_VB:790 /*791 * MHL cable with USB/TA cable792 * - MHL cable include two port(HDMI line and separate793 * micro-usb port. When the target connect MHL cable,794 * extcon driver check whether USB/TA cable is795 * connected. If USB/TA cable is connected, extcon796 * driver notify state to notifiee for charging battery.797 *798 * Features of 'USB/TA with MHL cable'799 * - Support MHL800 * - Support charging through micro-usb port without801 * data connection802 */803 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,804 attached);805 extcon_set_state_sync(info->edev, EXTCON_DISP_MHL,806 cable_attached);807 break;808 }809 810 /* Check MAX77693_CABLE_GROUP_ADC type */811 cable_type = max77693_muic_get_cable_type(info,812 MAX77693_CABLE_GROUP_ADC,813 &cable_attached);814 switch (cable_type) {815 case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */816 /*817 * Dock-Audio device with USB/TA cable818 * - Dock device include two port(Dock-Audio and micro-819 * usb port). When the target connect Dock-Audio device,820 * extcon driver check whether USB/TA cable is connected821 * or not. If USB/TA cable is connected, extcon driver822 * notify state to notifiee for charging battery.823 *824 * Features of 'USB/TA cable with Dock-Audio device'825 * - Support external output feature of audio.826 * - Support charging through micro-usb port without827 * data connection.828 */829 extcon_set_state_sync(info->edev, EXTCON_USB,830 attached);831 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,832 attached);833 834 if (!cable_attached)835 extcon_set_state_sync(info->edev, EXTCON_DOCK,836 cable_attached);837 break;838 case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */839 /*840 * Dock-Smart device with USB/TA cable841 * - Dock-Desk device include three type of cable which842 * are HDMI, USB for mouse/keyboard and micro-usb port843 * for USB/TA cable. Dock-Smart device need always844 * exteranl power supply(USB/TA cable through micro-usb845 * cable). Dock-Smart device support screen output of846 * target to separate monitor and mouse/keyboard for847 * desktop mode.848 *849 * Features of 'USB/TA cable with Dock-Smart device'850 * - Support MHL851 * - Support external output feature of audio852 * - Support charging through micro-usb port without853 * data connection if TA cable is connected to target.854 * - Support charging and data connection through micro-855 * usb port if USB cable is connected between target856 * and host device857 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)858 */859 ret = max77693_muic_set_path(info, info->path_usb,860 attached);861 if (ret < 0)862 return ret;863 864 extcon_set_state_sync(info->edev, EXTCON_DOCK,865 attached);866 extcon_set_state_sync(info->edev, EXTCON_DISP_MHL,867 attached);868 break;869 }870 871 /* Check MAX77693_CABLE_GROUP_CHG type */872 switch (chg_type) {873 case MAX77693_CHARGER_TYPE_NONE:874 /*875 * When MHL(with USB/TA cable) or Dock-Audio with USB/TA876 * cable is attached, muic device happen below two irq.877 * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting878 * MHL/Dock-Audio.879 * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting880 * USB/TA cable connected to MHL or Dock-Audio.881 * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC882 * irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq.883 *884 * If user attach MHL (with USB/TA cable and immediately885 * detach MHL with USB/TA cable before MAX77693_MUIC_IRQ886 * _INT2_CHGTYP irq is happened, USB/TA cable remain887 * connected state to target. But USB/TA cable isn't888 * connected to target. The user be face with unusual889 * action. So, driver should check this situation in890 * spite of, that previous charger type is N/A.891 */892 break;893 case MAX77693_CHARGER_TYPE_USB:894 /* Only USB cable, PATH:AP_USB */895 ret = max77693_muic_set_path(info, info->path_usb,896 attached);897 if (ret < 0)898 return ret;899 900 extcon_set_state_sync(info->edev, EXTCON_USB,901 attached);902 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,903 attached);904 break;905 case MAX77693_CHARGER_TYPE_DEDICATED_CHG:906 /* Only TA cable */907 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,908 attached);909 break;910 }911 break;912 case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT:913 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,914 attached);915 break;916 case MAX77693_CHARGER_TYPE_APPLE_500MA:917 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,918 attached);919 break;920 case MAX77693_CHARGER_TYPE_APPLE_1A_2A:921 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,922 attached);923 break;924 case MAX77693_CHARGER_TYPE_DEAD_BATTERY:925 break;926 default:927 dev_err(info->dev,928 "failed to detect %s accessory (chg_type:0x%x)\n",929 attached ? "attached" : "detached", chg_type);930 return -EINVAL;931 }932 933 return 0;934}935 936static void max77693_muic_irq_work(struct work_struct *work)937{938 struct max77693_muic_info *info = container_of(work,939 struct max77693_muic_info, irq_work);940 int irq_type = -1;941 int i, ret = 0;942 943 if (!info->edev)944 return;945 946 mutex_lock(&info->mutex);947 948 for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)949 if (info->irq == muic_irqs[i].virq)950 irq_type = muic_irqs[i].irq;951 952 ret = regmap_bulk_read(info->max77693->regmap_muic,953 MAX77693_MUIC_REG_STATUS1, info->status, 2);954 if (ret) {955 dev_err(info->dev, "failed to read MUIC register\n");956 mutex_unlock(&info->mutex);957 return;958 }959 960 switch (irq_type) {961 case MAX77693_MUIC_IRQ_INT1_ADC:962 case MAX77693_MUIC_IRQ_INT1_ADC_LOW:963 case MAX77693_MUIC_IRQ_INT1_ADC_ERR:964 case MAX77693_MUIC_IRQ_INT1_ADC1K:965 /*966 * Handle all of accessory except for967 * type of charger accessory.968 */969 ret = max77693_muic_adc_handler(info);970 break;971 case MAX77693_MUIC_IRQ_INT2_CHGTYP:972 case MAX77693_MUIC_IRQ_INT2_CHGDETREUN:973 case MAX77693_MUIC_IRQ_INT2_DCDTMR:974 case MAX77693_MUIC_IRQ_INT2_DXOVP:975 case MAX77693_MUIC_IRQ_INT2_VBVOLT:976 case MAX77693_MUIC_IRQ_INT2_VIDRM:977 /* Handle charger accessory */978 ret = max77693_muic_chg_handler(info);979 break;980 case MAX77693_MUIC_IRQ_INT3_EOC:981 case MAX77693_MUIC_IRQ_INT3_CGMBC:982 case MAX77693_MUIC_IRQ_INT3_OVP:983 case MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR:984 case MAX77693_MUIC_IRQ_INT3_CHG_ENABLED:985 case MAX77693_MUIC_IRQ_INT3_BAT_DET:986 break;987 default:988 dev_err(info->dev, "muic interrupt: irq %d occurred\n",989 irq_type);990 mutex_unlock(&info->mutex);991 return;992 }993 994 if (ret < 0)995 dev_err(info->dev, "failed to handle MUIC interrupt\n");996 997 mutex_unlock(&info->mutex);998}999 1000static irqreturn_t max77693_muic_irq_handler(int irq, void *data)1001{1002 struct max77693_muic_info *info = data;1003 1004 info->irq = irq;1005 schedule_work(&info->irq_work);1006 1007 return IRQ_HANDLED;1008}1009 1010static const struct regmap_config max77693_muic_regmap_config = {1011 .reg_bits = 8,1012 .val_bits = 8,1013};1014 1015static int max77693_muic_detect_accessory(struct max77693_muic_info *info)1016{1017 int ret = 0;1018 int adc;1019 int chg_type;1020 bool attached;1021 1022 mutex_lock(&info->mutex);1023 1024 /* Read STATUSx register to detect accessory */1025 ret = regmap_bulk_read(info->max77693->regmap_muic,1026 MAX77693_MUIC_REG_STATUS1, info->status, 2);1027 if (ret) {1028 dev_err(info->dev, "failed to read MUIC register\n");1029 mutex_unlock(&info->mutex);1030 return ret;1031 }1032 1033 adc = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_ADC,1034 &attached);1035 if (attached && adc != MAX77693_MUIC_ADC_OPEN) {1036 ret = max77693_muic_adc_handler(info);1037 if (ret < 0) {1038 dev_err(info->dev, "Cannot detect accessory\n");1039 mutex_unlock(&info->mutex);1040 return ret;1041 }1042 }1043 1044 chg_type = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_CHG,1045 &attached);1046 if (attached && chg_type != MAX77693_CHARGER_TYPE_NONE) {1047 ret = max77693_muic_chg_handler(info);1048 if (ret < 0) {1049 dev_err(info->dev, "Cannot detect charger accessory\n");1050 mutex_unlock(&info->mutex);1051 return ret;1052 }1053 }1054 1055 mutex_unlock(&info->mutex);1056 1057 return 0;1058}1059 1060static void max77693_muic_detect_cable_wq(struct work_struct *work)1061{1062 struct max77693_muic_info *info = container_of(to_delayed_work(work),1063 struct max77693_muic_info, wq_detcable);1064 1065 max77693_muic_detect_accessory(info);1066}1067 1068static int max77693_muic_probe(struct platform_device *pdev)1069{1070 struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);1071 struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);1072 struct max77693_muic_info *info;1073 struct max77693_reg_data *init_data;1074 int num_init_data;1075 int delay_jiffies;1076 int cable_type;1077 bool attached;1078 int ret;1079 int i;1080 unsigned int id;1081 1082 info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),1083 GFP_KERNEL);1084 if (!info)1085 return -ENOMEM;1086 1087 info->dev = &pdev->dev;1088 info->max77693 = max77693;1089 if (info->max77693->regmap_muic) {1090 dev_dbg(&pdev->dev, "allocate register map\n");1091 } else {1092 info->max77693->regmap_muic = devm_regmap_init_i2c(1093 info->max77693->i2c_muic,1094 &max77693_muic_regmap_config);1095 if (IS_ERR(info->max77693->regmap_muic)) {1096 ret = PTR_ERR(info->max77693->regmap_muic);1097 dev_err(max77693->dev,1098 "failed to allocate register map: %d\n", ret);1099 return ret;1100 }1101 }1102 1103 /* Register input device for button of dock device */1104 info->dock = devm_input_allocate_device(&pdev->dev);1105 if (!info->dock) {1106 dev_err(&pdev->dev, "%s: failed to allocate input\n", __func__);1107 return -ENOMEM;1108 }1109 info->dock->name = "max77693-muic/dock";1110 info->dock->phys = "max77693-muic/extcon";1111 info->dock->dev.parent = &pdev->dev;1112 1113 __set_bit(EV_REP, info->dock->evbit);1114 1115 input_set_capability(info->dock, EV_KEY, KEY_VOLUMEUP);1116 input_set_capability(info->dock, EV_KEY, KEY_VOLUMEDOWN);1117 input_set_capability(info->dock, EV_KEY, KEY_PLAYPAUSE);1118 input_set_capability(info->dock, EV_KEY, KEY_PREVIOUSSONG);1119 input_set_capability(info->dock, EV_KEY, KEY_NEXTSONG);1120 1121 ret = input_register_device(info->dock);1122 if (ret < 0) {1123 dev_err(&pdev->dev, "Cannot register input device error(%d)\n",1124 ret);1125 return ret;1126 }1127 1128 platform_set_drvdata(pdev, info);1129 mutex_init(&info->mutex);1130 1131 ret = devm_work_autocancel(&pdev->dev, &info->irq_work,1132 max77693_muic_irq_work);1133 if (ret)1134 return ret;1135 1136 /* Support irq domain for MAX77693 MUIC device */1137 for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {1138 struct max77693_muic_irq *muic_irq = &muic_irqs[i];1139 int virq;1140 1141 virq = regmap_irq_get_virq(max77693->irq_data_muic,1142 muic_irq->irq);1143 if (virq <= 0)1144 return -EINVAL;1145 muic_irq->virq = virq;1146 1147 ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,1148 max77693_muic_irq_handler,1149 IRQF_NO_SUSPEND,1150 muic_irq->name, info);1151 if (ret) {1152 dev_err(&pdev->dev,1153 "failed: irq request (IRQ: %d, error :%d)\n",1154 muic_irq->irq, ret);1155 return ret;1156 }1157 }1158 1159 /* Initialize extcon device */1160 info->edev = devm_extcon_dev_allocate(&pdev->dev,1161 max77693_extcon_cable);1162 if (IS_ERR(info->edev)) {1163 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");1164 return PTR_ERR(info->edev);1165 }1166 1167 ret = devm_extcon_dev_register(&pdev->dev, info->edev);1168 if (ret) {1169 dev_err(&pdev->dev, "failed to register extcon device\n");1170 return ret;1171 }1172 1173 /* Initialize MUIC register by using platform data or default data */1174 if (pdata && pdata->muic_data) {1175 init_data = pdata->muic_data->init_data;1176 num_init_data = pdata->muic_data->num_init_data;1177 } else {1178 init_data = default_init_data;1179 num_init_data = ARRAY_SIZE(default_init_data);1180 }1181 1182 for (i = 0; i < num_init_data; i++) {1183 regmap_write(info->max77693->regmap_muic,1184 init_data[i].addr,1185 init_data[i].data);1186 }1187 1188 if (pdata && pdata->muic_data) {1189 struct max77693_muic_platform_data *muic_pdata1190 = pdata->muic_data;1191 1192 /*1193 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB1194 * h/w path of COMP2/COMN1 on CONTROL1 register.1195 */1196 if (muic_pdata->path_uart)1197 info->path_uart = muic_pdata->path_uart;1198 else1199 info->path_uart = MAX77693_CONTROL1_SW_UART;1200 1201 if (muic_pdata->path_usb)1202 info->path_usb = muic_pdata->path_usb;1203 else1204 info->path_usb = MAX77693_CONTROL1_SW_USB;1205 1206 /*1207 * Default delay time for detecting cable state1208 * after certain time.1209 */1210 if (muic_pdata->detcable_delay_ms)1211 delay_jiffies =1212 msecs_to_jiffies(muic_pdata->detcable_delay_ms);1213 else1214 delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);1215 } else {1216 info->path_usb = MAX77693_CONTROL1_SW_USB;1217 info->path_uart = MAX77693_CONTROL1_SW_UART;1218 delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);1219 }1220 1221 /* Set initial path for UART when JIG is connected to get serial logs */1222 ret = regmap_bulk_read(info->max77693->regmap_muic,1223 MAX77693_MUIC_REG_STATUS1, info->status, 2);1224 if (ret) {1225 dev_err(info->dev, "failed to read MUIC register\n");1226 return ret;1227 }1228 cable_type = max77693_muic_get_cable_type(info,1229 MAX77693_CABLE_GROUP_ADC, &attached);1230 if (attached && (cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON ||1231 cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF))1232 max77693_muic_set_path(info, info->path_uart, true);1233 1234 /* Check revision number of MUIC device*/1235 ret = regmap_read(info->max77693->regmap_muic,1236 MAX77693_MUIC_REG_ID, &id);1237 if (ret < 0) {1238 dev_err(&pdev->dev, "failed to read revision number\n");1239 return ret;1240 }1241 dev_info(info->dev, "device ID : 0x%x\n", id);1242 1243 /* Set ADC debounce time */1244 max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);1245 1246 /*1247 * Detect accessory after completing the initialization of platform1248 *1249 * - Use delayed workqueue to detect cable state and then1250 * notify cable state to notifiee/platform through uevent.1251 * After completing the booting of platform, the extcon provider1252 * driver should notify cable state to upper layer.1253 */1254 INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq);1255 queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,1256 delay_jiffies);1257 1258 return ret;1259}1260 1261static const struct of_device_id of_max77693_muic_dt_match[] = {1262 { .compatible = "maxim,max77693-muic", },1263 { /* sentinel */ },1264};1265MODULE_DEVICE_TABLE(of, of_max77693_muic_dt_match);1266 1267static struct platform_driver max77693_muic_driver = {1268 .driver = {1269 .name = DEV_NAME,1270 .of_match_table = of_max77693_muic_dt_match,1271 },1272 .probe = max77693_muic_probe,1273};1274 1275module_platform_driver(max77693_muic_driver);1276 1277MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver");1278MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");1279MODULE_LICENSE("GPL");1280MODULE_ALIAS("platform:max77693-muic");1281